]> glassweightruler.freedombox.rocks Git - waydroid.git/blob - tools/actions/container_manager.py
Makefile: Add distro-agnostic buildsystem
[waydroid.git] / tools / actions / container_manager.py
1 # Copyright 2021 Erfan Abdi
2 # SPDX-License-Identifier: GPL-3.0-or-later
3 from shutil import which
4 import logging
5 import os
6 import time
7 import glob
8 import signal
9 import sys
10 import uuid
11 import tools.config
12 from tools import helpers
13 from tools import services
14
15
16 def start(args):
17 def make_prop(full_props_path):
18 def add_prop(key, cfg_key):
19 value = session_cfg["session"][cfg_key]
20 if value != "None":
21 value = value.replace("/mnt/", "/mnt_extra/")
22 props.append(key + "=" + value)
23
24 if not os.path.isfile(args.work + "/waydroid_base.prop"):
25 raise RuntimeError("waydroid_base.prop Not found")
26 with open(args.work + "/waydroid_base.prop") as f:
27 props = f.read().splitlines()
28 if not props:
29 raise RuntimeError("waydroid_base.prop is broken!!?")
30
31 add_prop("waydroid.host.user", "user_name")
32 add_prop("waydroid.host.uid", "user_id")
33 add_prop("waydroid.host.gid", "group_id")
34 add_prop("waydroid.xdg_runtime_dir", "xdg_runtime_dir")
35 add_prop("waydroid.pulse_runtime_path", "pulse_runtime_path")
36 add_prop("waydroid.wayland_display", "wayland_display")
37 if which("waydroid-sensord") is None:
38 props.append("waydroid.stub_sensors_hal=1")
39 dpi = session_cfg["session"]["lcd_density"]
40 if dpi != "0":
41 props.append("ro.sf.lcd_density=" + dpi)
42
43 final_props = open(full_props_path, "w")
44 for prop in props:
45 final_props.write(prop + "\n")
46 final_props.close()
47 os.chmod(full_props_path, 0o644)
48
49 def set_permissions(perm_list=None, mode="777"):
50 def chmod(path, mode):
51 if os.path.exists(path):
52 command = ["chmod", mode, "-R", path]
53 tools.helpers.run.user(args, command, check=False)
54
55 # Nodes list
56 if not perm_list:
57 perm_list = [
58 "/dev/ashmem",
59
60 # sw_sync for HWC
61 "/dev/sw_sync",
62 "/sys/kernel/debug/sync/sw_sync",
63
64 # Media
65 "/dev/Vcodec",
66 "/dev/MTK_SMI",
67 "/dev/mdp_sync",
68 "/dev/mtk_cmdq",
69
70 # Graphics
71 "/dev/dri",
72 "/dev/graphics",
73 "/dev/pvr_sync",
74 "/dev/ion",
75 ]
76
77 # Framebuffers
78 perm_list.extend(glob.glob("/dev/fb*"))
79 # Videos
80 perm_list.extend(glob.glob("/dev/video*"))
81
82 for path in perm_list:
83 chmod(path, mode)
84
85 def set_aidl_version():
86 cfg = tools.config.load(args)
87 android_api = 0
88 try:
89 android_api = int(helpers.props.file_get(args,
90 tools.config.defaults["rootfs"] + "/system/build.prop",
91 "ro.build.version.sdk"))
92 except:
93 logging.error("Failed to parse android version from system.img")
94
95 if android_api < 28:
96 binder_protocol = "aidl"
97 sm_protocol = "aidl"
98 elif android_api < 30:
99 binder_protocol = "aidl2"
100 sm_protocol = "aidl2"
101 elif android_api < 31:
102 binder_protocol = "aidl3"
103 sm_protocol = "aidl3"
104 else:
105 binder_protocol = "aidl3"
106 sm_protocol = "aidl4"
107
108 cfg["waydroid"]["binder_protocol"] = binder_protocol
109 cfg["waydroid"]["service_manager_protocol"] = sm_protocol
110 tools.config.save(args, cfg)
111
112 def signal_handler(sig, frame):
113 services.hardware_manager.stop(args)
114 stop(args)
115 sys.exit(0)
116
117 status = helpers.lxc.status(args)
118 if status == "STOPPED":
119 # Load binder and ashmem drivers
120 cfg = tools.config.load(args)
121 if cfg["waydroid"]["vendor_type"] == "MAINLINE":
122 if helpers.drivers.probeBinderDriver(args) != 0:
123 logging.error("Failed to load Binder driver")
124 if helpers.drivers.probeAshmemDriver(args) != 0:
125 logging.error("Failed to load Ashmem driver")
126 helpers.drivers.loadBinderNodes(args)
127 set_permissions([
128 "/dev/" + args.BINDER_DRIVER,
129 "/dev/" + args.VNDBINDER_DRIVER,
130 "/dev/" + args.HWBINDER_DRIVER
131 ], "666")
132
133 if os.path.exists(tools.config.session_defaults["config_path"]):
134 session_cfg = tools.config.load_session()
135 if session_cfg["session"]["state"] != "STOPPED":
136 logging.warning("Found session config on state: {}, restart session".format(
137 session_cfg["session"]["state"]))
138 os.remove(tools.config.session_defaults["config_path"])
139 logging.debug("Container manager is waiting for session to load")
140 while not os.path.exists(tools.config.session_defaults["config_path"]):
141 time.sleep(1)
142
143 # Load session configs
144 session_cfg = tools.config.load_session()
145
146 # Generate props
147 make_prop(args.work + "/waydroid.prop")
148
149 # Networking
150 command = [tools.config.tools_src +
151 "/data/scripts/waydroid-net.sh", "start"]
152 tools.helpers.run.user(args, command, check=False)
153
154 # Sensors
155 if which("waydroid-sensord"):
156 tools.helpers.run.user(
157 args, ["waydroid-sensord", "/dev/" + args.HWBINDER_DRIVER], output="background")
158
159 # Mount rootfs
160 helpers.images.mount_rootfs(args, cfg["waydroid"]["images_path"])
161
162 set_aidl_version()
163
164 # Mount data
165 helpers.mount.bind(args, session_cfg["session"]["waydroid_data"],
166 tools.config.defaults["data"])
167
168 # Cgroup hacks
169 if which("start"):
170 command = ["start", "cgroup-lite"]
171 tools.helpers.run.user(args, command, check=False)
172 if os.path.ismount("/sys/fs/cgroup/schedtune"):
173 command = ["umount", "-l", "/sys/fs/cgroup/schedtune"]
174 tools.helpers.run.user(args, command, check=False)
175
176 #TODO: remove NFC hacks
177 if which("stop"):
178 command = ["stop", "nfcd"]
179 tools.helpers.run.user(args, command, check=False)
180
181 # Set permissions
182 set_permissions()
183
184 helpers.lxc.start(args)
185 session_cfg["session"]["state"] = helpers.lxc.status(args)
186 timeout = 10
187 while session_cfg["session"]["state"] != "RUNNING" and timeout > 0:
188 session_cfg["session"]["state"] = helpers.lxc.status(args)
189 logging.info(
190 "waiting {} seconds for container to start...".format(timeout))
191 timeout = timeout - 1
192 time.sleep(1)
193 if session_cfg["session"]["state"] != "RUNNING":
194 raise OSError("container failed to start")
195 tools.config.save_session(session_cfg)
196
197 services.hardware_manager.start(args)
198
199 signal.signal(signal.SIGINT, signal_handler)
200 while os.path.exists(tools.config.session_defaults["config_path"]):
201 session_cfg = tools.config.load_session()
202 if session_cfg["session"]["state"] == "STOPPED":
203 services.hardware_manager.stop(args)
204 sys.exit(0)
205 elif session_cfg["session"]["state"] == "UNFREEZE":
206 session_cfg["session"]["state"] = helpers.lxc.status(args)
207 tools.config.save_session(session_cfg)
208 unfreeze(args)
209 time.sleep(1)
210
211 logging.warning("session manager stopped, stopping container and waiting...")
212 stop(args)
213 services.hardware_manager.stop(args)
214 start(args)
215 else:
216 logging.error("WayDroid container is {}".format(status))
217
218 def stop(args):
219 status = helpers.lxc.status(args)
220 if status != "STOPPED":
221 helpers.lxc.stop(args)
222 if os.path.exists(tools.config.session_defaults["config_path"]):
223 session_cfg = tools.config.load_session()
224 session_cfg["session"]["state"] = helpers.lxc.status(args)
225 tools.config.save_session(session_cfg)
226
227 # Networking
228 command = [tools.config.tools_src +
229 "/data/scripts/waydroid-net.sh", "stop"]
230 tools.helpers.run.user(args, command, check=False)
231
232 #TODO: remove NFC hacks
233 if which("start"):
234 command = ["start", "nfcd"]
235 tools.helpers.run.user(args, command, check=False)
236
237 # Sensors
238 if which("waydroid-sensord"):
239 command = ["pidof", "waydroid-sensord"]
240 pid = tools.helpers.run.user(args, command, check=False, output_return=True).strip()
241 if pid:
242 command = ["kill", "-9", pid]
243 tools.helpers.run.user(args, command, check=False)
244
245 # Umount rootfs
246 helpers.images.umount_rootfs(args)
247
248 # Umount data
249 helpers.mount.umount_all(args, tools.config.defaults["data"])
250
251 else:
252 logging.error("WayDroid container is {}".format(status))
253
254 def restart(args):
255 status = helpers.lxc.status(args)
256 if status == "RUNNING":
257 helpers.lxc.stop(args)
258 helpers.lxc.start(args)
259 else:
260 logging.error("WayDroid container is {}".format(status))
261
262 def freeze(args):
263 status = helpers.lxc.status(args)
264 if status == "RUNNING":
265 helpers.lxc.freeze(args)
266 if os.path.exists(tools.config.session_defaults["config_path"]):
267 session_cfg = tools.config.load_session()
268 session_cfg["session"]["state"] = helpers.lxc.status(args)
269 tools.config.save_session(session_cfg)
270 else:
271 logging.error("WayDroid container is {}".format(status))
272
273 def unfreeze(args):
274 status = helpers.lxc.status(args)
275 if status == "FROZEN":
276 helpers.lxc.unfreeze(args)
277 if os.path.exists(tools.config.session_defaults["config_path"]):
278 session_cfg = tools.config.load_session()
279 session_cfg["session"]["state"] = helpers.lxc.status(args)
280 tools.config.save_session(session_cfg)
281 else:
282 logging.error("WayDroid container is {}".format(status))