]>
glassweightruler.freedombox.rocks Git - waydroid.git/blob - tools/actions/container_manager.py
1 # Copyright 2021 Erfan Abdi
2 # SPDX-License-Identifier: GPL-3.0-or-later
3 from shutil
import which
9 from tools
import helpers
10 from tools
import services
13 import dbus
.exceptions
14 from gi
.repository
import GLib
16 class DbusContainerManager(dbus
.service
.Object
):
17 def __init__(self
, looper
, bus
, object_path
, args
):
20 dbus
.service
.Object
.__init
__(self
, bus
, object_path
)
22 @dbus.service.method("id.waydro.ContainerManager", in_signature
='a{ss}', out_signature
='', sender_keyword
="sender", connection_keyword
="conn")
23 def Start(self
, session
, sender
, conn
):
24 dbus_info
= dbus
.Interface(conn
.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus/Bus", False), "org.freedesktop.DBus")
25 uid
= dbus_info
.GetConnectionUnixUser(sender
)
26 if str(uid
) not in ["0", session
["user_id"]]:
27 raise RuntimeError("Cannot start a session on behalf of another user")
28 pid
= dbus_info
.GetConnectionUnixProcessID(sender
)
29 if str(uid
) != "0" and str(pid
) != session
["pid"]:
30 raise RuntimeError("Invalid session pid")
31 do_start(self
.args
, session
)
33 @dbus.service.method("id.waydro.ContainerManager", in_signature
='b', out_signature
='')
34 def Stop(self
, quit_session
):
35 stop(self
.args
, quit_session
)
37 @dbus.service.method("id.waydro.ContainerManager", in_signature
='', out_signature
='')
41 @dbus.service.method("id.waydro.ContainerManager", in_signature
='', out_signature
='')
45 @dbus.service.method("id.waydro.ContainerManager", in_signature
='', out_signature
='a{ss}')
48 session
= self
.args
.session
49 session
["state"] = helpers
.lxc
.status(self
.args
)
51 except AttributeError:
54 def service(args
, looper
):
55 dbus_obj
= DbusContainerManager(looper
, dbus
.SystemBus(), '/ContainerManager', args
)
58 def set_permissions(args
, perm_list
=None, mode
="777"):
59 def chmod(path
, mode
):
60 if os
.path
.exists(path
):
61 command
= ["chmod", mode
, "-R", path
]
62 tools
.helpers
.run
.user(args
, command
, check
=False)
71 "/sys/kernel/debug/sync/sw_sync",
86 perm_list
.extend(glob
.glob("/dev/dri/renderD*"))
88 perm_list
.extend(glob
.glob("/dev/fb*"))
90 perm_list
.extend(glob
.glob("/dev/video*"))
92 perm_list
.extend(glob
.glob("/dev/dma_heap/*"))
94 for path
in perm_list
:
99 name
= dbus
.service
.BusName("id.waydro.Container", dbus
.SystemBus(), do_not_queue
=True)
100 except dbus
.exceptions
.NameExistsException
:
101 logging
.error("Container service is already running")
104 status
= helpers
.lxc
.status(args
)
105 if status
== "STOPPED":
106 # Load binder and ashmem drivers
107 cfg
= tools
.config
.load(args
)
108 if cfg
["waydroid"]["vendor_type"] == "MAINLINE":
109 if helpers
.drivers
.probeBinderDriver(args
) != 0:
110 logging
.error("Failed to load Binder driver")
111 helpers
.drivers
.probeAshmemDriver(args
)
112 helpers
.drivers
.loadBinderNodes(args
)
113 set_permissions(args
, [
114 "/dev/" + args
.BINDER_DRIVER
,
115 "/dev/" + args
.VNDBINDER_DRIVER
,
116 "/dev/" + args
.HWBINDER_DRIVER
119 mainloop
= GLib
.MainLoop()
121 def sigint_handler(data
):
125 GLib
.unix_signal_add(GLib
.PRIORITY_HIGH
, signal
.SIGINT
, sigint_handler
, None)
126 GLib
.unix_signal_add(GLib
.PRIORITY_HIGH
, signal
.SIGTERM
, sigint_handler
, None)
127 service(args
, mainloop
)
129 logging
.error("WayDroid container is {}".format(status
))
131 def do_start(args
, session
):
132 if "session" in args
:
133 raise RuntimeError("Already tracking a session")
135 logging
.info("Starting up container for a new session")
138 command
= [tools
.config
.tools_src
+
139 "/data/scripts/waydroid-net.sh", "start"]
140 tools
.helpers
.run
.user(args
, command
)
143 if which("waydroid-sensord"):
144 tools
.helpers
.run
.user(
145 args
, ["waydroid-sensord", "/dev/" + args
.HWBINDER_DRIVER
], output
="background")
149 command
= ["start", "cgroup-lite"]
150 tools
.helpers
.run
.user(args
, command
, check
=False)
152 # Keep schedtune around in case nesting is supported
153 if os
.path
.ismount("/sys/fs/cgroup/schedtune"):
155 os
.mkdir("/sys/fs/cgroup/schedtune/probe0")
156 os
.mkdir("/sys/fs/cgroup/schedtune/probe0/probe1")
158 command
= ["umount", "-l", "/sys/fs/cgroup/schedtune"]
159 tools
.helpers
.run
.user(args
, command
, check
=False)
161 if os
.path
.exists("/sys/fs/cgroup/schedtune/probe0/probe1"):
162 os
.rmdir("/sys/fs/cgroup/schedtune/probe0/probe1")
163 if os
.path
.exists("/sys/fs/cgroup/schedtune/probe0"):
164 os
.rmdir("/sys/fs/cgroup/schedtune/probe0")
166 #TODO: remove NFC hacks
168 command
= ["stop", "nfcd"]
169 tools
.helpers
.run
.user(args
, command
, check
=False)
170 elif which("systemctl") and (tools
.helpers
.run
.user(args
, ["systemctl", "is-active", "-q", "nfcd"], check
=False) == 0):
171 command
= ["systemctl", "stop", "nfcd"]
172 tools
.helpers
.run
.user(args
, command
, check
=False)
175 set_permissions(args
)
177 # Create session-specific LXC config file
178 helpers
.lxc
.generate_session_lxc_config(args
, session
)
179 # Backwards compatibility
180 with open(tools
.config
.defaults
["lxc"] + "/waydroid/config") as f
:
181 if "config_session" not in f
.read():
182 helpers
.mount
.bind(args
, session
["waydroid_data"],
183 tools
.config
.defaults
["data"])
186 cfg
= tools
.config
.load(args
)
187 helpers
.images
.mount_rootfs(args
, cfg
["waydroid"]["images_path"], session
)
189 helpers
.protocol
.set_aidl_version(args
)
191 helpers
.lxc
.start(args
)
192 services
.hardware_manager
.start(args
)
194 args
.session
= session
196 def stop(args
, quit_session
=True):
197 logging
.info("Stopping container")
200 services
.hardware_manager
.stop(args
)
201 status
= helpers
.lxc
.status(args
)
202 if status
!= "STOPPED":
203 helpers
.lxc
.stop(args
)
204 while helpers
.lxc
.status(args
) != "STOPPED":
208 command
= [tools
.config
.tools_src
+
209 "/data/scripts/waydroid-net.sh", "stop"]
210 tools
.helpers
.run
.user(args
, command
, check
=False)
212 #TODO: remove NFC hacks
214 command
= ["start", "nfcd"]
215 tools
.helpers
.run
.user(args
, command
, check
=False)
216 elif which("systemctl") and (tools
.helpers
.run
.user(args
, ["systemctl", "is-enabled", "-q", "nfcd"], check
=False) == 0):
217 command
= ["systemctl", "start", "nfcd"]
218 tools
.helpers
.run
.user(args
, command
, check
=False)
221 if which("waydroid-sensord"):
222 command
= ["pidof", "waydroid-sensord"]
223 pid
= tools
.helpers
.run
.user(args
, command
, check
=False, output_return
=True).strip()
225 command
= ["kill", "-9", pid
]
226 tools
.helpers
.run
.user(args
, command
, check
=False)
229 helpers
.images
.umount_rootfs(args
)
231 # Backwards compatibility
233 helpers
.mount
.umount_all(args
, tools
.config
.defaults
["data"])
237 if "session" in args
:
239 logging
.info("Terminating session because the container was stopped")
241 os
.kill(int(args
.session
["pid"]), signal
.SIGUSR1
)
249 status
= helpers
.lxc
.status(args
)
250 if status
== "RUNNING":
251 helpers
.lxc
.stop(args
)
252 helpers
.lxc
.start(args
)
254 logging
.error("WayDroid container is {}".format(status
))
257 status
= helpers
.lxc
.status(args
)
258 if status
== "RUNNING":
259 helpers
.lxc
.freeze(args
)
260 while helpers
.lxc
.status(args
) == "RUNNING":
263 logging
.error("WayDroid container is {}".format(status
))
266 status
= helpers
.lxc
.status(args
)
267 if status
== "FROZEN":
268 helpers
.lxc
.unfreeze(args
)
269 while helpers
.lxc
.status(args
) == "FROZEN":