]> glassweightruler.freedombox.rocks Git - waydroid.git/blob - tools/actions/container_manager.py
session: Also log dbus connection exceptions
[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 import dbus
15 import dbus.service
16 import dbus.exceptions
17 from gi.repository import GLib
18
19 class DbusContainerManager(dbus.service.Object):
20 def __init__(self, looper, bus, object_path, args):
21 self.args = args
22 self.looper = looper
23 dbus.service.Object.__init__(self, bus, object_path)
24
25 @dbus.service.method("id.waydro.ContainerManager", in_signature='a{ss}', out_signature='', sender_keyword="sender", connection_keyword="conn")
26 def Start(self, session, sender, conn):
27 if session["user_id"] != "0":
28 dbus_info = dbus.Interface(conn.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus/Bus", False), "org.freedesktop.DBus")
29 uid = dbus_info.GetConnectionUnixUser(sender)
30 if str(uid) != session["user_id"]:
31 raise RuntimeError("Cannot start a session on behalf of another user")
32 do_start(self.args, session)
33
34 @dbus.service.method("id.waydro.ContainerManager", in_signature='b', out_signature='')
35 def Stop(self, quit_session):
36 stop(self.args, quit_session)
37
38 @dbus.service.method("id.waydro.ContainerManager", in_signature='', out_signature='')
39 def Freeze(self):
40 freeze(self.args)
41
42 @dbus.service.method("id.waydro.ContainerManager", in_signature='', out_signature='')
43 def Unfreeze(self):
44 unfreeze(self.args)
45
46 @dbus.service.method("id.waydro.ContainerManager", in_signature='', out_signature='a{ss}')
47 def GetSession(self):
48 try:
49 session = self.args.session
50 session["state"] = helpers.lxc.status(self.args)
51 return session
52 except AttributeError:
53 return {}
54
55 def service(args, looper):
56 dbus_obj = DbusContainerManager(looper, dbus.SystemBus(), '/ContainerManager', args)
57 looper.run()
58
59 def set_permissions(args, perm_list=None, mode="777"):
60 def chmod(path, mode):
61 if os.path.exists(path):
62 command = ["chmod", mode, "-R", path]
63 tools.helpers.run.user(args, command, check=False)
64
65 # Nodes list
66 if not perm_list:
67 perm_list = [
68 "/dev/ashmem",
69
70 # sw_sync for HWC
71 "/dev/sw_sync",
72 "/sys/kernel/debug/sync/sw_sync",
73
74 # Media
75 "/dev/Vcodec",
76 "/dev/MTK_SMI",
77 "/dev/mdp_sync",
78 "/dev/mtk_cmdq",
79
80 # Graphics
81 "/dev/dri",
82 "/dev/graphics",
83 "/dev/pvr_sync",
84 "/dev/ion",
85 ]
86
87 # Framebuffers
88 perm_list.extend(glob.glob("/dev/fb*"))
89 # Videos
90 perm_list.extend(glob.glob("/dev/video*"))
91
92 for path in perm_list:
93 chmod(path, mode)
94
95 def start(args):
96 try:
97 name = dbus.service.BusName("id.waydro.Container", dbus.SystemBus(), do_not_queue=True)
98 except dbus.exceptions.NameExistsException:
99 logging.error("Container service is already running")
100 return
101
102 status = helpers.lxc.status(args)
103 if status == "STOPPED":
104 # Load binder and ashmem drivers
105 cfg = tools.config.load(args)
106 if cfg["waydroid"]["vendor_type"] == "MAINLINE":
107 if helpers.drivers.probeBinderDriver(args) != 0:
108 logging.error("Failed to load Binder driver")
109 helpers.drivers.probeAshmemDriver(args)
110 helpers.drivers.loadBinderNodes(args)
111 set_permissions(args, [
112 "/dev/" + args.BINDER_DRIVER,
113 "/dev/" + args.VNDBINDER_DRIVER,
114 "/dev/" + args.HWBINDER_DRIVER
115 ], "666")
116
117 mainloop = GLib.MainLoop()
118
119 def sigint_handler(data):
120 stop(args)
121 mainloop.quit()
122
123 GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, sigint_handler, None)
124 GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, sigint_handler, None)
125 service(args, mainloop)
126 else:
127 logging.error("WayDroid container is {}".format(status))
128
129 def do_start(args, session):
130 if "session" in args:
131 raise RuntimeError("Already tracking a session")
132
133 # Networking
134 command = [tools.config.tools_src +
135 "/data/scripts/waydroid-net.sh", "start"]
136 tools.helpers.run.user(args, command)
137
138 # Sensors
139 if which("waydroid-sensord"):
140 tools.helpers.run.user(
141 args, ["waydroid-sensord", "/dev/" + args.HWBINDER_DRIVER], output="background")
142
143 # Mount rootfs
144 cfg = tools.config.load(args)
145 helpers.images.mount_rootfs(args, cfg["waydroid"]["images_path"], session)
146
147 helpers.protocol.set_aidl_version(args)
148
149 # Mount data
150 helpers.mount.bind(args, session["waydroid_data"],
151 tools.config.defaults["data"])
152
153 # Cgroup hacks
154 if which("start"):
155 command = ["start", "cgroup-lite"]
156 tools.helpers.run.user(args, command, check=False)
157 if os.path.ismount("/sys/fs/cgroup/schedtune"):
158 command = ["umount", "-l", "/sys/fs/cgroup/schedtune"]
159 tools.helpers.run.user(args, command, check=False)
160
161 #TODO: remove NFC hacks
162 if which("stop"):
163 command = ["stop", "nfcd"]
164 tools.helpers.run.user(args, command, check=False)
165
166 # Set permissions
167 set_permissions(args)
168
169 helpers.lxc.start(args)
170 services.hardware_manager.start(args)
171
172 args.session = session
173
174 def stop(args, quit_session=True):
175 try:
176 services.hardware_manager.stop(args)
177 status = helpers.lxc.status(args)
178 if status != "STOPPED":
179 helpers.lxc.stop(args)
180 while helpers.lxc.status(args) != "STOPPED":
181 pass
182
183 # Networking
184 command = [tools.config.tools_src +
185 "/data/scripts/waydroid-net.sh", "stop"]
186 tools.helpers.run.user(args, command, check=False)
187
188 #TODO: remove NFC hacks
189 if which("start"):
190 command = ["start", "nfcd"]
191 tools.helpers.run.user(args, command, check=False)
192
193 # Sensors
194 if which("waydroid-sensord"):
195 command = ["pidof", "waydroid-sensord"]
196 pid = tools.helpers.run.user(args, command, check=False, output_return=True).strip()
197 if pid:
198 command = ["kill", "-9", pid]
199 tools.helpers.run.user(args, command, check=False)
200
201 # Umount rootfs
202 helpers.images.umount_rootfs(args)
203
204 # Umount data
205 helpers.mount.umount_all(args, tools.config.defaults["data"])
206
207 if "session" in args:
208 if quit_session:
209 try:
210 os.kill(int(args.session["pid"]), signal.SIGUSR1)
211 except:
212 pass
213 del args.session
214 except:
215 pass
216
217 def restart(args):
218 status = helpers.lxc.status(args)
219 if status == "RUNNING":
220 helpers.lxc.stop(args)
221 helpers.lxc.start(args)
222 else:
223 logging.error("WayDroid container is {}".format(status))
224
225 def freeze(args):
226 status = helpers.lxc.status(args)
227 if status == "RUNNING":
228 helpers.lxc.freeze(args)
229 while helpers.lxc.status(args) == "RUNNING":
230 pass
231 else:
232 logging.error("WayDroid container is {}".format(status))
233
234 def unfreeze(args):
235 status = helpers.lxc.status(args)
236 if status == "FROZEN":
237 helpers.lxc.unfreeze(args)
238 while helpers.lxc.status(args) == "FROZEN":
239 pass