]> glassweightruler.freedombox.rocks Git - waydroid.git/blob - tools/actions/session_manager.py
debian: Unify waydroid.postinst indentation
[waydroid.git] / tools / actions / session_manager.py
1 # Copyright 2021 Erfan Abdi
2 # SPDX-License-Identifier: GPL-3.0-or-later
3 import logging
4 import os
5 import time
6 import signal
7 import sys
8 import shutil
9 import tools.config
10 import tools.helpers.ipc
11 from tools import services
12 import dbus
13 import dbus.service
14 import dbus.exceptions
15 from gi.repository import GLib
16 import copy
17
18 class DbusSessionManager(dbus.service.Object):
19 def __init__(self, looper, bus, object_path, args):
20 self.args = args
21 self.looper = looper
22 dbus.service.Object.__init__(self, bus, object_path)
23
24 @dbus.service.method("id.waydro.SessionManager", in_signature='', out_signature='')
25 def Stop(self):
26 do_stop(self.args, self.looper)
27 stop_container()
28
29 def service(args, looper):
30 dbus_obj = DbusSessionManager(looper, dbus.SessionBus(), '/SessionManager', args)
31 looper.run()
32
33 def start(args, unlocked_cb=None):
34 try:
35 name = dbus.service.BusName("id.waydro.Session", dbus.SessionBus(), do_not_queue=True)
36 except dbus.exceptions.NameExistsException:
37 logging.error("Session is already running")
38 if unlocked_cb:
39 unlocked_cb()
40 return
41
42 session = copy.copy(tools.config.session_defaults)
43
44 # TODO: also support WAYLAND_SOCKET?
45 wayland_display = session["wayland_display"]
46 if wayland_display == "None" or not wayland_display:
47 logging.warning('WAYLAND_DISPLAY is not set, defaulting to "wayland-0"')
48 wayland_display = session["wayland_display"] = "wayland-0"
49
50 if os.path.isabs(wayland_display):
51 wayland_socket_path = wayland_display
52 else:
53 xdg_runtime_dir = session["xdg_runtime_dir"]
54 if xdg_runtime_dir == "None" or not xdg_runtime_dir:
55 logging.error(f"XDG_RUNTIME_DIR is not set; please don't start a Waydroid session with 'sudo'!")
56 sys.exit(1)
57 wayland_socket_path = os.path.join(xdg_runtime_dir, wayland_display)
58 if not os.path.exists(wayland_socket_path):
59 logging.error(f"Wayland socket '{wayland_socket_path}' doesn't exist; are you running a Wayland compositor?")
60 sys.exit(1)
61
62 waydroid_data = session["waydroid_data"]
63 if not os.path.isdir(waydroid_data):
64 os.makedirs(waydroid_data)
65
66 dpi = tools.helpers.props.host_get(args, "ro.sf.lcd_density")
67 if dpi == "":
68 dpi = os.getenv("GRID_UNIT_PX")
69 if dpi is not None:
70 dpi = str(int(dpi) * 20)
71 else:
72 dpi = "0"
73 session["lcd_density"] = dpi
74
75 mainloop = GLib.MainLoop()
76
77 def sigint_handler(data):
78 do_stop(args, mainloop)
79 stop_container()
80
81 def sigusr_handler(data):
82 do_stop(args, mainloop)
83
84 GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, sigint_handler, None)
85 GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, sigint_handler, None)
86 GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGUSR1, sigusr_handler, None)
87 try:
88 tools.helpers.ipc.DBusContainerService().Start(session)
89 except dbus.DBusException as e:
90 if e.get_dbus_name().startswith("org.freedesktop.DBus.Python"):
91 logging.error(e.get_dbus_message().splitlines()[-1])
92 else:
93 logging.error("WayDroid container is not listening")
94 sys.exit(0)
95
96 services.user_manager.start(args, session, unlocked_cb)
97 services.clipboard_manager.start(args)
98 service(args, mainloop)
99
100 def do_stop(args, looper):
101 services.user_manager.stop(args)
102 services.clipboard_manager.stop(args)
103 looper.quit()
104
105 def stop(args):
106 try:
107 tools.helpers.ipc.DBusSessionService().Stop()
108 except dbus.DBusException:
109 stop_container()
110
111 def stop_container():
112 try:
113 tools.helpers.ipc.DBusContainerService().Stop()
114 except dbus.DBusException:
115 pass