]> glassweightruler.freedombox.rocks Git - waydroid.git/blob - tools/helpers/drivers.py
container: don't panic if binder device already exists
[waydroid.git] / tools / helpers / drivers.py
1 # Copyright 2021 Erfan Abdi
2 # SPDX-License-Identifier: GPL-3.0-or-later
3 import logging
4 import os
5 import glob
6 import fcntl
7 import struct
8 import tools.config
9 import tools.helpers.run
10
11
12 BINDER_DRIVERS = [
13 "anbox-binder",
14 "puddlejumper",
15 "binder"
16 ]
17 VNDBINDER_DRIVERS = [
18 "anbox-vndbinder",
19 "vndpuddlejumper",
20 "vndbinder"
21 ]
22 HWBINDER_DRIVERS = [
23 "anbox-hwbinder",
24 "hwpuddlejumper",
25 "hwbinder"
26 ]
27
28
29 def isBinderfsLoaded(args):
30 with open("/proc/filesystems", "r") as handle:
31 for line in handle:
32 words = line.split()
33 if len(words) >= 2 and words[1] == "binder":
34 return True
35
36 return False
37
38 def allocBinderNodes(args, binder_dev_nodes):
39 NRBITS = 8
40 TYPEBITS = 8
41 SIZEBITS = 14
42 NRSHIFT = 0
43 TYPESHIFT = NRSHIFT + NRBITS
44 SIZESHIFT = TYPESHIFT + TYPEBITS
45 DIRSHIFT = SIZESHIFT + SIZEBITS
46 WRITE = 0x1
47 READ = 0x2
48
49 def IOC(direction, _type, nr, size):
50 return (direction << DIRSHIFT) | (_type << TYPESHIFT) | (nr << NRSHIFT) | (size << SIZESHIFT)
51
52 def IOWR(_type, nr, size):
53 return IOC(READ|WRITE, _type, nr, size)
54
55 BINDER_CTL_ADD = IOWR(98, 1, 264)
56 binderctrlfd = open('/dev/binderfs/binder-control','rb')
57
58 for node in binder_dev_nodes:
59 node_struct = struct.pack(
60 '256sII', bytes(node, 'utf-8'), 0, 0)
61 try:
62 fcntl.ioctl(binderctrlfd.fileno(), BINDER_CTL_ADD, node_struct)
63 except FileExistsError:
64 pass
65
66 def probeBinderDriver(args):
67 binder_dev_nodes = []
68 has_binder = False
69 has_vndbinder = False
70 has_hwbinder = False
71 for node in BINDER_DRIVERS:
72 if os.path.exists("/dev/" + node):
73 has_binder = True
74 if not has_binder:
75 binder_dev_nodes.append(BINDER_DRIVERS[0])
76 for node in VNDBINDER_DRIVERS:
77 if os.path.exists("/dev/" + node):
78 has_vndbinder = True
79 if not has_vndbinder:
80 binder_dev_nodes.append(VNDBINDER_DRIVERS[0])
81 for node in HWBINDER_DRIVERS:
82 if os.path.exists("/dev/" + node):
83 has_hwbinder = True
84 if not has_hwbinder:
85 binder_dev_nodes.append(HWBINDER_DRIVERS[0])
86
87 if len(binder_dev_nodes) > 0:
88 if not isBinderfsLoaded(args):
89 command = ["modprobe", "binder_linux"]
90 output = tools.helpers.run.user(args, command, check=False, output_return=True)
91 if output:
92 logging.error("Failed to load binder driver")
93 logging.error(output.strip())
94
95 if isBinderfsLoaded(args):
96 command = ["mkdir", "-p", "/dev/binderfs"]
97 tools.helpers.run.user(args, command, check=False)
98 command = ["mount", "-t", "binder", "binder", "/dev/binderfs"]
99 tools.helpers.run.user(args, command, check=False)
100 allocBinderNodes(args, binder_dev_nodes)
101 command = ["ln", "-s"]
102 command.extend(glob.glob("/dev/binderfs/*"))
103 command.append("/dev/")
104 tools.helpers.run.user(args, command, check=False)
105
106 return 0
107
108 def probeAshmemDriver(args):
109 if not os.path.exists("/dev/ashmem"):
110 command = ["modprobe", "ashmem_linux"]
111 output = tools.helpers.run.user(args, command, check=False, output_return=True)
112 if output:
113 logging.error("Failed to load ashmem driver")
114 logging.error(output.strip())
115
116 if not os.path.exists("/dev/ashmem"):
117 return -1
118
119 return 0
120
121 def setupBinderNodes(args):
122 has_binder = False
123 has_vndbinder = False
124 has_hwbinder = False
125 if args.vendor_type == "MAINLINE":
126 probeBinderDriver(args)
127 for node in BINDER_DRIVERS:
128 if os.path.exists("/dev/" + node):
129 has_binder = True
130 args.BINDER_DRIVER = node
131 if not has_binder:
132 raise OSError('Binder node "binder" for waydroid not found')
133
134 for node in VNDBINDER_DRIVERS:
135 if os.path.exists("/dev/" + node):
136 has_vndbinder = True
137 args.VNDBINDER_DRIVER = node
138 if not has_vndbinder:
139 raise OSError('Binder node "vndbinder" for waydroid not found')
140
141 for node in HWBINDER_DRIVERS:
142 if os.path.exists("/dev/" + node):
143 has_hwbinder = True
144 args.HWBINDER_DRIVER = node
145 if not has_hwbinder:
146 raise OSError('Binder node "hwbinder" for waydroid not found')
147 else:
148 for node in BINDER_DRIVERS[:-1]:
149 if os.path.exists("/dev/" + node):
150 has_binder = True
151 args.BINDER_DRIVER = node
152 if not has_binder:
153 raise OSError('Binder node "binder" for waydroid not found')
154
155 for node in VNDBINDER_DRIVERS[:-1]:
156 if os.path.exists("/dev/" + node):
157 has_vndbinder = True
158 args.VNDBINDER_DRIVER = node
159 if not has_vndbinder:
160 raise OSError('Binder node "vndbinder" for waydroid not found')
161
162 for node in HWBINDER_DRIVERS[:-1]:
163 if os.path.exists("/dev/" + node):
164 has_hwbinder = True
165 args.HWBINDER_DRIVER = node
166 if not has_hwbinder:
167 raise OSError('Binder node "hwbinder" for waydroid not found')
168
169 def loadBinderNodes(args):
170 cfg = tools.config.load(args)
171 args.BINDER_DRIVER = cfg["waydroid"]["binder"]
172 args.VNDBINDER_DRIVER = cfg["waydroid"]["vndbinder"]
173 args.HWBINDER_DRIVER = cfg["waydroid"]["hwbinder"]