import sys
import shutil
import tools.config
+import tools.helpers.ipc
from tools import services
+import dbus
+import dbus.service
+import dbus.exceptions
+from gi.repository import GLib
+import copy
+class DbusSessionManager(dbus.service.Object):
+ def __init__(self, looper, bus, object_path, args):
+ self.args = args
+ self.looper = looper
+ dbus.service.Object.__init__(self, bus, object_path)
+
+ @dbus.service.method("id.waydro.SessionManager", in_signature='', out_signature='')
+ def Stop(self):
+ do_stop(self.args, self.looper)
+ stop_container()
+
+def service(args, looper):
+ dbus_obj = DbusSessionManager(looper, dbus.SessionBus(), '/SessionManager', args)
+ looper.run()
def start(args, unlocked_cb=None):
- def signal_handler(sig, frame):
- stop(args)
- sys.exit(0)
+ try:
+ name = dbus.service.BusName("id.waydro.Session", dbus.SessionBus(), do_not_queue=True)
+ except dbus.exceptions.NameExistsException:
+ logging.error("Session is already running")
+ if unlocked_cb:
+ unlocked_cb()
+ return
- xdg_session = os.getenv("XDG_SESSION_TYPE")
- if xdg_session != "wayland":
- logging.warning('XDG Session is not "wayland"')
-
- cfg = tools.config.load_session()
- waydroid_data = cfg["session"]["waydroid_data"]
- #TODO: Drop me
- old_user_waydroid = cfg["session"]["host_user"] + "/waydroid"
- if os.path.isdir(old_user_waydroid):
- if not os.path.isdir(waydroid_data):
- shutil.move(old_user_waydroid, cfg["session"]["xdg_data_home"])
- else:
- os.removedirs(old_user_waydroid)
+ session = copy.copy(tools.config.session_defaults)
+
+ # TODO: also support WAYLAND_SOCKET?
+ wayland_display = session["wayland_display"]
+ if wayland_display == "None" or not wayland_display:
+ logging.warning('WAYLAND_DISPLAY is not set, defaulting to "wayland-0"')
+ wayland_display = session["wayland_display"] = "wayland-0"
+
+ if os.path.isabs(wayland_display):
+ wayland_socket_path = wayland_display
+ else:
+ xdg_runtime_dir = session["xdg_runtime_dir"]
+ if xdg_runtime_dir == "None" or not xdg_runtime_dir:
+ logging.error(f"XDG_RUNTIME_DIR is not set; please don't start a Waydroid session with 'sudo'!")
+ sys.exit(1)
+ wayland_socket_path = os.path.join(xdg_runtime_dir, wayland_display)
+ if not os.path.exists(wayland_socket_path):
+ logging.error(f"Wayland socket '{wayland_socket_path}' doesn't exist; are you running a Wayland compositor?")
+ sys.exit(1)
+
+ waydroid_data = session["waydroid_data"]
if not os.path.isdir(waydroid_data):
os.makedirs(waydroid_data)
+
dpi = tools.helpers.props.host_get(args, "ro.sf.lcd_density")
if dpi == "":
dpi = os.getenv("GRID_UNIT_PX")
dpi = str(int(dpi) * 20)
else:
dpi = "0"
- cfg["session"]["lcd_density"] = dpi
- tools.config.save_session(cfg)
-
- container_state = "IDLE"
- signal.signal(signal.SIGINT, signal_handler)
- while os.path.exists(tools.config.session_defaults["config_path"]):
- session_cfg = tools.config.load_session()
- if container_state != session_cfg["session"]["state"]:
- if session_cfg["session"]["state"] == "RUNNING":
- services.user_manager.start(args, unlocked_cb)
- services.clipboard_manager.start(args)
- if unlocked_cb:
- unlocked_cb = None
- elif session_cfg["session"]["state"] == "STOPPED":
- services.user_manager.stop(args)
- services.clipboard_manager.stop(args)
- container_state = session_cfg["session"]["state"]
- time.sleep(1)
+ session["lcd_density"] = dpi
+
+ mainloop = GLib.MainLoop()
+
+ def sigint_handler(data):
+ do_stop(args, mainloop)
+ stop_container()
+
+ def sigusr_handler(data):
+ do_stop(args, mainloop)
+
+ GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, sigint_handler, None)
+ GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, sigint_handler, None)
+ GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGUSR1, sigusr_handler, None)
+ try:
+ tools.helpers.ipc.DBusContainerService().Start(session)
+ except dbus.DBusException as e:
+ if e.get_dbus_name().startswith("org.freedesktop.DBus.Python"):
+ logging.error(e.get_dbus_message().splitlines()[-1])
+ else:
+ logging.error("WayDroid container is not listening")
+ sys.exit(0)
+
+ services.user_manager.start(args, session, unlocked_cb)
+ services.clipboard_manager.start(args)
+ service(args, mainloop)
+
+def do_stop(args, looper):
services.user_manager.stop(args)
services.clipboard_manager.stop(args)
+ looper.quit()
def stop(args):
- config_path = tools.config.session_defaults["config_path"]
- if os.path.isfile(config_path):
- services.user_manager.stop(args)
- services.clipboard_manager.stop(args)
- os.remove(config_path)
- else:
- logging.error("WayDroid session is not started")
+ try:
+ tools.helpers.ipc.DBusSessionService().Stop()
+ except dbus.DBusException:
+ stop_container()
+
+def stop_container():
+ try:
+ tools.helpers.ipc.DBusContainerService().Stop()
+ except dbus.DBusException:
+ pass