Files
waydroid/tools/actions/session_manager.py
2026-03-10 20:36:41 +01:00

129 lines
4.4 KiB
Python

# Copyright 2021 Erfan Abdi
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import os
import signal
import sys
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(quit_session=False)
def handle_disconnect(args, looper):
do_stop(args, looper)
stop_container(quit_session=False)
def service(args, looper):
bus = dbus.SessionBus()
bus.set_exit_on_disconnect(False)
bus.add_signal_receiver(lambda: handle_disconnect(args, looper),
signal_name='Disconnected',
dbus_interface='org.freedesktop.DBus.Local')
_session_manager = DbusSessionManager(looper, dbus.SessionBus(), '/SessionManager', args)
looper.run()
def start(args, unlocked_cb=None, background=True):
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
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("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")
if dpi is not None:
dpi = str(int(dpi) * 20)
else:
dpi = "0"
session["lcd_density"] = dpi
session["background_start"] = "true" if background else "false"
mainloop = GLib.MainLoop()
def sigint_handler(data):
do_stop(args, mainloop)
stop_container(quit_session=False)
def sigusr_handler(data):
do_stop(args, mainloop)
GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGHUP, sigint_handler, None)
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:
logging.debug(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)
services.notification_manager.start(args, session)
service(args, mainloop)
def do_stop(args, looper):
services.user_manager.stop(args)
services.clipboard_manager.stop(args)
services.notification_manager.stop(args)
looper.quit()
def stop(args):
try:
tools.helpers.ipc.DBusSessionService().Stop()
except dbus.DBusException:
stop_container(quit_session=True)
def stop_container(quit_session):
try:
tools.helpers.ipc.DBusContainerService().Stop(quit_session)
except dbus.DBusException:
pass