From ff4cf1c83f09e639504209dec68855cdf3c69bce Mon Sep 17 00:00:00 2001 From: Alessandro Astone Date: Wed, 28 Dec 2022 16:52:25 +0100 Subject: [PATCH] Move session IPC to dbus --- tools/__init__.py | 16 +- tools/actions/app_manager.py | 116 +++++------- tools/actions/container_manager.py | 292 ++++++++++++++++------------- tools/actions/initializer.py | 14 +- tools/actions/session_manager.py | 98 +++++++--- tools/actions/status.py | 26 ++- tools/actions/upgrader.py | 11 +- tools/config/__init__.py | 17 +- tools/config/load.py | 20 -- tools/config/save.py | 7 - tools/helpers/images.py | 12 +- tools/helpers/ipc.py | 7 + tools/helpers/props.py | 32 +--- tools/services/hardware_manager.py | 2 +- tools/services/user_manager.py | 9 +- 15 files changed, 351 insertions(+), 328 deletions(-) diff --git a/tools/__init__.py b/tools/__init__.py index 992049e..9a4701b 100644 --- a/tools/__init__.py +++ b/tools/__init__.py @@ -6,6 +6,8 @@ import logging import os import traceback import dbus.mainloop.glib +import dbus +import dbus.exceptions from . import actions from . import config @@ -42,11 +44,17 @@ def main(): dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) dbus.mainloop.glib.threads_init() + dbus_name_scope = None if not actions.initializer.is_initialized(args) and \ args.action and args.action not in ("init", "first-launch", "log"): if args.wait_for_init: - actions.wait_for_init(args) + try: + dbus_name_scope = dbus.service.BusName("id.waydro.Container", dbus.SystemBus(), do_not_queue=True) + actions.wait_for_init(args) + except dbus.exceptions.NameExistsException: + print('ERROR: WayDroid service is already awaiting initialization') + return 1 else: print('ERROR: WayDroid is not initialized, run "waydroid init"') return 0 @@ -69,6 +77,12 @@ def main(): elif args.action == "container": actionNeedRoot(args.action) if args.subaction == "start": + if dbus_name_scope is None: + try: + dbus_name_scope = dbus.service.BusName("id.waydro.Container", dbus.SystemBus(), do_not_queue=True) + except dbus.exceptions.NameExistsException: + print('ERROR: WayDroid container service is already running') + return 1 actions.container_manager.start(args) elif args.subaction == "stop": actions.container_manager.stop(args) diff --git a/tools/actions/app_manager.py b/tools/actions/app_manager.py index f4a4b6a..47b2787 100644 --- a/tools/actions/app_manager.py +++ b/tools/actions/app_manager.py @@ -6,63 +6,50 @@ import shutil import time import tools.config import tools.helpers.props +import tools.helpers.ipc from tools.interfaces import IPlatform from tools.interfaces import IStatusBarService +import dbus def install(args): - if os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() - if session_cfg["session"]["state"] == "RUNNING": - tmp_dir = session_cfg["session"]["waydroid_data"] + "/waydroid_tmp" - if not os.path.exists(tmp_dir): - os.makedirs(tmp_dir) + try: + tools.helpers.ipc.DBusSessionService() - shutil.copyfile(args.PACKAGE, tmp_dir + "/base.apk") - platformService = IPlatform.get_service(args) - if platformService: - platformService.installApp("/data/waydroid_tmp/base.apk") - os.remove(tmp_dir + "/base.apk") - else: - logging.error("WayDroid container is {}".format( - session_cfg["session"]["state"])) - else: + tmp_dir = tools.config.session_defaults["waydroid_data"] + "/waydroid_tmp" + if not os.path.exists(tmp_dir): + os.makedirs(tmp_dir) + + shutil.copyfile(args.PACKAGE, tmp_dir + "/base.apk") + platformService = IPlatform.get_service(args) + if platformService: + platformService.installApp("/data/waydroid_tmp/base.apk") + os.remove(tmp_dir + "/base.apk") + except (dbus.DBusException, KeyError): logging.error("WayDroid session is stopped") def remove(args): - if os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() - if session_cfg["session"]["state"] == "RUNNING": - platformService = IPlatform.get_service(args) - if platformService: - ret = platformService.removeApp(args.PACKAGE) - if ret != 0: - logging.error("Failed to uninstall package: {}".format(args.PACKAGE)) - else: - logging.error("Failed to access IPlatform service") - else: - logging.error("WayDroid container is {}".format( - session_cfg["session"]["state"])) - else: - logging.error("WayDroid session is stopped") + try: + tools.helpers.ipc.DBusSessionService() -def maybeLaunchLater(args, retry, launchNow): - if os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() + platformService = IPlatform.get_service(args) + if platformService: + ret = platformService.removeApp(args.PACKAGE) + if ret != 0: + logging.error("Failed to uninstall package: {}".format(args.PACKAGE)) + except dbus.DBusException: + logging.error("WayDroid session is stopped") - if session_cfg["session"]["state"] == "RUNNING": - launchNow() - elif session_cfg["session"]["state"] == "FROZEN" or session_cfg["session"]["state"] == "UNFREEZE": - session_cfg["session"]["state"] = "UNFREEZE" - tools.config.save_session(session_cfg) - while session_cfg["session"]["state"] != "RUNNING": - session_cfg = tools.config.load_session() - launchNow() - else: - logging.error("WayDroid container is {}".format( - session_cfg["session"]["state"])) - else: +def maybeLaunchLater(args, launchNow): + try: + tools.helpers.ipc.DBusSessionService() + try: + tools.helpers.ipc.DBusContainerService().Unfreeze() + except: + logging.error("Failed to unfreeze container. Trying to launch anyways...") + launchNow() + except dbus.DBusException: logging.error("Starting waydroid session") - tools.actions.session_manager.start(args, retry) + tools.actions.session_manager.start(args, launchNow) def launch(args): def justLaunch(): @@ -80,27 +67,24 @@ def launch(args): 2, "policy_control", "immersive.full=*") else: logging.error("Failed to access IPlatform service") - maybeLaunchLater(args, launch, justLaunch) + maybeLaunchLater(args, justLaunch) def list(args): - if os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() - if session_cfg["session"]["state"] == "RUNNING": - platformService = IPlatform.get_service(args) - if platformService: - appsList = platformService.getAppsInfo() - for app in appsList: - print("Name: " + app["name"]) - print("packageName: " + app["packageName"]) - print("categories:") - for cat in app["categories"]: - print("\t" + cat) - else: - logging.error("Failed to access IPlatform service") + try: + tools.helpers.ipc.DBusSessionService() + + platformService = IPlatform.get_service(args) + if platformService: + appsList = platformService.getAppsInfo() + for app in appsList: + print("Name: " + app["name"]) + print("packageName: " + app["packageName"]) + print("categories:") + for cat in app["categories"]: + print("\t" + cat) else: - logging.error("WayDroid container is {}".format( - session_cfg["session"]["state"])) - else: + logging.error("Failed to access IPlatform service") + except dbus.DBusException: logging.error("WayDroid session is stopped") def showFullUI(args): @@ -115,7 +99,7 @@ def showFullUI(args): statusBarService.expand() time.sleep(0.5) statusBarService.collapse() - maybeLaunchLater(args, showFullUI, justShow) + maybeLaunchLater(args, justShow) def intent(args): def justLaunch(): @@ -136,4 +120,4 @@ def intent(args): 2, "policy_control", "immersive.full=*") else: logging.error("Failed to access IPlatform service") - maybeLaunchLater(args, intent, justLaunch) + maybeLaunchLater(args, justLaunch) diff --git a/tools/actions/container_manager.py b/tools/actions/container_manager.py index dd316c7..e36cfbf 100644 --- a/tools/actions/container_manager.py +++ b/tools/actions/container_manager.py @@ -11,49 +11,88 @@ import uuid import tools.config from tools import helpers from tools import services +import dbus +import dbus.service +import dbus.exceptions +from gi.repository import GLib + +class DbusContainerManager(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.ContainerManager", in_signature='a{ss}', out_signature='') + def Start(self, session): + do_start(self.args, session) + + @dbus.service.method("id.waydro.ContainerManager", in_signature='', out_signature='') + def Stop(self): + stop(self.args) + + @dbus.service.method("id.waydro.ContainerManager", in_signature='', out_signature='') + def Freeze(self): + freeze(self.args) + + @dbus.service.method("id.waydro.ContainerManager", in_signature='', out_signature='') + def Unfreeze(self): + unfreeze(self.args) + + @dbus.service.method("id.waydro.ContainerManager", in_signature='', out_signature='a{ss}') + def GetSession(self): + try: + session = self.args.session + session["state"] = helpers.lxc.status(self.args) + return session + except AttributeError: + return {} + +def service(args, looper): + dbus_obj = DbusContainerManager(looper, dbus.SystemBus(), '/ContainerManager', args) + looper.run() + +def set_permissions(args, perm_list=None, mode="777"): + def chmod(path, mode): + if os.path.exists(path): + command = ["chmod", mode, "-R", path] + tools.helpers.run.user(args, command, check=False) + # Nodes list + if not perm_list: + perm_list = [ + "/dev/ashmem", -def start(args): - def set_permissions(perm_list=None, mode="777"): - def chmod(path, mode): - if os.path.exists(path): - command = ["chmod", mode, "-R", path] - tools.helpers.run.user(args, command, check=False) + # sw_sync for HWC + "/dev/sw_sync", + "/sys/kernel/debug/sync/sw_sync", - # Nodes list - if not perm_list: - perm_list = [ - "/dev/ashmem", - - # sw_sync for HWC - "/dev/sw_sync", - "/sys/kernel/debug/sync/sw_sync", - - # Media - "/dev/Vcodec", - "/dev/MTK_SMI", - "/dev/mdp_sync", - "/dev/mtk_cmdq", - - # Graphics - "/dev/dri", - "/dev/graphics", - "/dev/pvr_sync", - "/dev/ion", - ] - - # Framebuffers - perm_list.extend(glob.glob("/dev/fb*")) - # Videos - perm_list.extend(glob.glob("/dev/video*")) - - for path in perm_list: - chmod(path, mode) - - def signal_handler(sig, frame): - services.hardware_manager.stop(args) - stop(args) - sys.exit(0) + # Media + "/dev/Vcodec", + "/dev/MTK_SMI", + "/dev/mdp_sync", + "/dev/mtk_cmdq", + + # Graphics + "/dev/dri", + "/dev/graphics", + "/dev/pvr_sync", + "/dev/ion", + ] + + # Framebuffers + perm_list.extend(glob.glob("/dev/fb*")) + # Videos + perm_list.extend(glob.glob("/dev/video*")) + + for path in perm_list: + chmod(path, mode) + +def start(args): + try: + name = dbus.service.BusName("id.waydro.Container", dbus.SystemBus(), do_not_queue=True) + except dbus.exceptions.NameExistsException: + logging.error("Container service is already running") + return status = helpers.lxc.status(args) if status == "STOPPED": @@ -64,102 +103,89 @@ def start(args): logging.error("Failed to load Binder driver") helpers.drivers.probeAshmemDriver(args) helpers.drivers.loadBinderNodes(args) - set_permissions([ + set_permissions(args, [ "/dev/" + args.BINDER_DRIVER, "/dev/" + args.VNDBINDER_DRIVER, "/dev/" + args.HWBINDER_DRIVER ], "666") - if os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() - if session_cfg["session"]["state"] != "STOPPED": - logging.warning("Found session config on state: {}, restart session".format( - session_cfg["session"]["state"])) - os.remove(tools.config.session_defaults["config_path"]) - logging.debug("Container manager is waiting for session to load") - while not os.path.exists(tools.config.session_defaults["config_path"]): - time.sleep(1) - - # Load session configs - session_cfg = tools.config.load_session() + mainloop = GLib.MainLoop() - # Networking - command = [tools.config.tools_src + - "/data/scripts/waydroid-net.sh", "start"] - tools.helpers.run.user(args, command, check=False) + def sigint_handler(data): + stop(args) + mainloop.quit() - # Sensors - if which("waydroid-sensord"): - tools.helpers.run.user( - args, ["waydroid-sensord", "/dev/" + args.HWBINDER_DRIVER], output="background") + GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, sigint_handler, None) + GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, sigint_handler, None) + service(args, mainloop) + else: + logging.error("WayDroid container is {}".format(status)) - # Mount rootfs - helpers.images.mount_rootfs(args, cfg["waydroid"]["images_path"]) +def do_start(args, session): + if "session" in args: + logging.info("Already tracking a session") + return - helpers.protocol.set_aidl_version(args) + args.session = session - # Mount data - helpers.mount.bind(args, session_cfg["session"]["waydroid_data"], - tools.config.defaults["data"]) + # Networking + command = [tools.config.tools_src + + "/data/scripts/waydroid-net.sh", "start"] + tools.helpers.run.user(args, command, check=False) - # Cgroup hacks - if which("start"): - command = ["start", "cgroup-lite"] - tools.helpers.run.user(args, command, check=False) - if os.path.ismount("/sys/fs/cgroup/schedtune"): - command = ["umount", "-l", "/sys/fs/cgroup/schedtune"] - tools.helpers.run.user(args, command, check=False) + # Sensors + if which("waydroid-sensord"): + tools.helpers.run.user( + args, ["waydroid-sensord", "/dev/" + args.HWBINDER_DRIVER], output="background") - #TODO: remove NFC hacks - if which("stop"): - command = ["stop", "nfcd"] - tools.helpers.run.user(args, command, check=False) + # Mount rootfs + cfg = tools.config.load(args) + helpers.images.mount_rootfs(args, cfg["waydroid"]["images_path"], args.session) - # Set permissions - set_permissions() - - helpers.lxc.start(args) - session_cfg["session"]["state"] = helpers.lxc.status(args) - timeout = 10 - while session_cfg["session"]["state"] != "RUNNING" and timeout > 0: - session_cfg["session"]["state"] = helpers.lxc.status(args) - logging.info( - "waiting {} seconds for container to start...".format(timeout)) - timeout = timeout - 1 - time.sleep(1) - if session_cfg["session"]["state"] != "RUNNING": - raise OSError("container failed to start") - tools.config.save_session(session_cfg) - - services.hardware_manager.start(args) - - signal.signal(signal.SIGINT, signal_handler) - while os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() - if session_cfg["session"]["state"] == "STOPPED": - services.hardware_manager.stop(args) - sys.exit(0) - elif session_cfg["session"]["state"] == "UNFREEZE": - session_cfg["session"]["state"] = helpers.lxc.status(args) - tools.config.save_session(session_cfg) - unfreeze(args) - time.sleep(1) - - logging.warning("session manager stopped, stopping container and waiting...") - stop(args) - services.hardware_manager.stop(args) - start(args) - else: - logging.error("WayDroid container is {}".format(status)) + helpers.protocol.set_aidl_version(args) + + # Mount data + helpers.mount.bind(args, args.session["waydroid_data"], + tools.config.defaults["data"]) + + # Cgroup hacks + if which("start"): + command = ["start", "cgroup-lite"] + tools.helpers.run.user(args, command, check=False) + if os.path.ismount("/sys/fs/cgroup/schedtune"): + command = ["umount", "-l", "/sys/fs/cgroup/schedtune"] + tools.helpers.run.user(args, command, check=False) + + #TODO: remove NFC hacks + if which("stop"): + command = ["stop", "nfcd"] + tools.helpers.run.user(args, command, check=False) + + # Set permissions + set_permissions(args) + + helpers.lxc.start(args) + lxc_status = helpers.lxc.status(args) + timeout = 10 + while lxc_status != "RUNNING" and timeout > 0: + lxc_status = helpers.lxc.status(args) + logging.info( + "waiting {} seconds for container to start...".format(timeout)) + timeout = timeout - 1 + time.sleep(1) + if lxc_status != "RUNNING": + raise OSError("container failed to start") + + services.hardware_manager.start(args) def stop(args): - status = helpers.lxc.status(args) - if status != "STOPPED": - helpers.lxc.stop(args) - if os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() - session_cfg["session"]["state"] = helpers.lxc.status(args) - tools.config.save_session(session_cfg) + try: + services.hardware_manager.stop(args) + status = helpers.lxc.status(args) + if status != "STOPPED": + helpers.lxc.stop(args) + while helpers.lxc.status(args) != "STOPPED": + pass # Networking command = [tools.config.tools_src + @@ -185,8 +211,14 @@ def stop(args): # Umount data helpers.mount.umount_all(args, tools.config.defaults["data"]) - else: - logging.error("WayDroid container is {}".format(status)) + if "session" in args: + try: + os.kill(int(args.session["pid"]), signal.SIGUSR1) + except: + pass + del args.session + except: + pass def restart(args): status = helpers.lxc.status(args) @@ -200,10 +232,8 @@ def freeze(args): status = helpers.lxc.status(args) if status == "RUNNING": helpers.lxc.freeze(args) - if os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() - session_cfg["session"]["state"] = helpers.lxc.status(args) - tools.config.save_session(session_cfg) + while helpers.lxc.status(args) == "RUNNING": + pass else: logging.error("WayDroid container is {}".format(status)) @@ -211,9 +241,5 @@ def unfreeze(args): status = helpers.lxc.status(args) if status == "FROZEN": helpers.lxc.unfreeze(args) - if os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() - session_cfg["session"]["state"] = helpers.lxc.status(args) - tools.config.save_session(session_cfg) - else: - logging.error("WayDroid container is {}".format(status)) + while helpers.lxc.status(args) == "FROZEN": + pass diff --git a/tools/actions/initializer.py b/tools/actions/initializer.py index 0d7755b..5238b3c 100644 --- a/tools/actions/initializer.py +++ b/tools/actions/initializer.py @@ -104,7 +104,7 @@ def init(args): if not is_initialized(args) or args.force: initializer_service = None try: - initializer_service = dbus.SystemBus().get_object("id.waydro.ContainerService", "/Initializer") + initializer_service = tools.helpers.ipc.DBusContainerService("/Initializer", "id.waydro.Initializer") except dbus.DBusException: pass setup_config(args) @@ -130,7 +130,7 @@ def init(args): if "running_init_in_service" not in args or not args.running_init_in_service: try: if initializer_service: - initializer_service.Done(dbus_interface="id.waydro.Initializer") + initializer_service.Done() except dbus.DBusException: pass else: @@ -139,11 +139,13 @@ def init(args): def wait_for_init(args): helpers.ipc.create_channel("remote_init_output") - name = dbus.service.BusName("id.waydro.ContainerService", dbus.SystemBus()) mainloop = GLib.MainLoop() dbus_obj = DbusInitializer(mainloop, dbus.SystemBus(), '/Initializer', args) mainloop.run() + # After init + dbus_obj.remove_from_connection() + class DbusInitializer(dbus.service.Object): def __init__(self, looper, bus, object_path, args): self.args = args @@ -231,7 +233,7 @@ def remote_init_client(args): if is_initialized(args): try: - bus.get_object("id.waydro.ContainerService", "/Initializer").Done(dbus_interface="id.waydro.Initializer") + tools.helpers.ipc.DBusContainerService("/Initializer", "id.waydro.Initializer").Done() except dbus.DBusException: pass return @@ -239,7 +241,7 @@ def remote_init_client(args): def notify_and_quit(caller): if is_initialized(args): try: - bus.get_object("id.waydro.ContainerService", "/Initializer").Done(dbus_interface="id.waydro.Initializer") + tools.helpers.ipc.DBusContainerService("/Initializer", "id.waydro.Initializer").Done() except dbus.DBusException: pass GLib.idle_add(Gtk.main_quit) @@ -340,7 +342,7 @@ def remote_init_client(args): "vendor_channel": self.vndOta.get_text(), "system_type": self.sysType.get_active_text() } - bus.get_object("id.waydro.ContainerService", "/Initializer").Init(params, dbus_interface="id.waydro.Initializer") + tools.helpers.ipc.DBusContainerService("/Initializer", "id.waydro.Initializer").Init(params) except: draw("The waydroid container service is not listening\n") GLib.idle_add(self.downloadBtn.set_sensitive, True) diff --git a/tools/actions/session_manager.py b/tools/actions/session_manager.py index cc6a946..cfcd267 100644 --- a/tools/actions/session_manager.py +++ b/tools/actions/session_manager.py @@ -7,19 +7,43 @@ import signal 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 - cfg = tools.config.load_session() - wayland_display = cfg["session"]["wayland_display"] + session = copy.copy(tools.config.session_defaults); + wayland_display = session["wayland_display"] if wayland_display == "None" or not wayland_display: logging.warning('WAYLAND_DISPLAY is not set, defaulting to "wayland-0"') - waydroid_data = cfg["session"]["waydroid_data"] + 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") @@ -29,32 +53,44 @@ def start(args, unlocked_cb=None): 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: + 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 diff --git a/tools/actions/status.py b/tools/actions/status.py index 00261ce..32ad899 100644 --- a/tools/actions/status.py +++ b/tools/actions/status.py @@ -2,18 +2,24 @@ # SPDX-License-Identifier: GPL-3.0-or-later import os import tools.config +import tools.helpers.ipc +import dbus def print_status(args): cfg = tools.config.load(args) - if os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() - print("Session:\tRUNNING") - print("Container:\t" + session_cfg["session"]["state"]) - print("Vendor type:\t" + cfg["waydroid"]["vendor_type"]) - print("Session user:\t{}({})".format( - session_cfg["session"]["user_name"], session_cfg["session"]["user_id"])) - print("Wayland display:\t" + - session_cfg["session"]["wayland_display"]) - else: + def print_stopped(): print("Session:\tSTOPPED") print("Vendor type:\t" + cfg["waydroid"]["vendor_type"]) + + try: + session = tools.helpers.ipc.DBusContainerService().GetSession() + if session: + print("Session:\tRUNNING") + print("Container:\t" + session["state"]) + print("Vendor type:\t" + cfg["waydroid"]["vendor_type"]) + print("Session user:\t{}({})".format(session["user_name"], session["user_id"])) + print("Wayland display:\t" + session["wayland_display"]) + else: + print_stopped() + except dbus.DBusException: + print_stopped() diff --git a/tools/actions/upgrader.py b/tools/actions/upgrader.py index b788f50..2181971 100644 --- a/tools/actions/upgrader.py +++ b/tools/actions/upgrader.py @@ -4,7 +4,7 @@ import logging import os from tools import helpers import tools.config - +import dbus def get_config(args): cfg = tools.config.load(args) @@ -13,6 +13,7 @@ def get_config(args): args.vendor_type = cfg["waydroid"]["vendor_type"] args.system_ota = cfg["waydroid"]["system_ota"] args.vendor_ota = cfg["waydroid"]["vendor_ota"] + args.session = None def upgrade(args): get_config(args) @@ -22,6 +23,10 @@ def upgrade(args): if status != "STOPPED": logging.info("Stopping container") helpers.lxc.stop(args) + try: + args.session = tools.helpers.ipc.DBusContainerService().GetSession() + except dbus.DBusException: + pass helpers.images.umount_rootfs(args) helpers.drivers.loadBinderNodes(args) if not args.offline: @@ -32,8 +37,8 @@ def upgrade(args): helpers.lxc.setup_host_perms(args) helpers.lxc.set_lxc_config(args) helpers.lxc.make_base_props(args) - if status != "STOPPED": + if status != "STOPPED" and args.session: logging.info("Starting container") - helpers.images.mount_rootfs(args, args.images_path) + helpers.images.mount_rootfs(args, args.images_path, args.session) helpers.protocol.set_aidl_version(args) helpers.lxc.start(args) diff --git a/tools/config/__init__.py b/tools/config/__init__.py index 2ec77dc..0ed3d46 100644 --- a/tools/config/__init__.py +++ b/tools/config/__init__.py @@ -6,8 +6,8 @@ import pwd # # Exported functions # -from tools.config.load import load, load_session, load_channels -from tools.config.save import save, save_session +from tools.config.load import load, load_channels +from tools.config.save import save # # Exported variables (internal configuration) @@ -23,18 +23,6 @@ config_keys = ["arch", "vendor_datetime", "suspend_action"] -session_config_keys = ["user_name", - "user_id", - "group_id", - "host_user", - "xdg_data_home", - "waydroid_data", - "xdg_runtime_dir", - "wayland_display", - "pulse_runtime_path", - "state", - "lcd_density"] - # Config file/commandline default values # $WORK gets replaced with the actual value for args.work (which may be # overridden on the commandline) @@ -61,6 +49,7 @@ session_defaults = { "user_id": str(os.getuid()), "group_id": str(os.getgid()), "host_user": os.path.expanduser("~"), + "pid": str(os.getpid()), "xdg_data_home": str(os.environ.get('XDG_DATA_HOME', os.path.expanduser("~") + "/.local/share")), "xdg_runtime_dir": str(os.environ.get('XDG_RUNTIME_DIR')), "wayland_display": str(os.environ.get('WAYLAND_DISPLAY')), diff --git a/tools/config/load.py b/tools/config/load.py index 87a1757..12978d3 100644 --- a/tools/config/load.py +++ b/tools/config/load.py @@ -32,26 +32,6 @@ def load(args): return cfg -def load_session(): - config_path = tools.config.session_defaults["config_path"] - cfg = configparser.ConfigParser() - if os.path.isfile(config_path): - cfg.read(config_path) - - if "session" not in cfg: - cfg["session"] = {} - - for key in tools.config.session_defaults: - if key in tools.config.session_config_keys and key not in cfg["session"]: - cfg["session"][key] = str(tools.config.session_defaults[key]) - - if key not in tools.config.session_config_keys and key in cfg["session"]: - logging.debug("Ignored unconfigurable and possibly outdated" - " default value from config: {}".format(cfg['session'][key])) - del cfg["session"][key] - - return cfg - def load_channels(): config_path = tools.config.channels_defaults["config_path"] cfg = configparser.ConfigParser() diff --git a/tools/config/save.py b/tools/config/save.py index 67e25ea..43c7822 100644 --- a/tools/config/save.py +++ b/tools/config/save.py @@ -10,10 +10,3 @@ def save(args, cfg): os.makedirs(os.path.dirname(args.config), 0o700, True) with open(args.config, "w") as handle: cfg.write(handle) - -def save_session(cfg): - config_path = tools.config.session_defaults["config_path"] - logging.debug("Save session config: " + config_path) - os.makedirs(os.path.dirname(config_path), 0o700, True) - with open(config_path, "w") as handle: - cfg.write(handle) diff --git a/tools/helpers/images.py b/tools/helpers/images.py index ac85f4f..cf65a11 100644 --- a/tools/helpers/images.py +++ b/tools/helpers/images.py @@ -93,7 +93,7 @@ def replace(args, system_zip, system_time, vendor_zip, vendor_time): cfg["waydroid"]["vendor_datetime"] = str(vendor_time) tools.config.save(args, cfg) -def make_prop(args, full_props_path): +def make_prop(args, cfg, full_props_path): if not os.path.isfile(args.work + "/waydroid_base.prop"): raise RuntimeError("waydroid_base.prop Not found") with open(args.work + "/waydroid_base.prop") as f: @@ -101,10 +101,8 @@ def make_prop(args, full_props_path): if not props: raise RuntimeError("waydroid_base.prop is broken!!?") - session_cfg = tools.config.load_session() - def add_prop(key, cfg_key): - value = session_cfg["session"][cfg_key] + value = cfg[cfg_key] if value != "None": value = value.replace("/mnt/", "/mnt_extra/") props.append(key + "=" + value) @@ -117,7 +115,7 @@ def make_prop(args, full_props_path): add_prop("waydroid.wayland_display", "wayland_display") if which("waydroid-sensord") is None: props.append("waydroid.stub_sensors_hal=1") - dpi = session_cfg["session"]["lcd_density"] + dpi = cfg["lcd_density"] if dpi != "0": props.append("ro.sf.lcd_density=" + dpi) @@ -127,7 +125,7 @@ def make_prop(args, full_props_path): final_props.close() os.chmod(full_props_path, 0o644) -def mount_rootfs(args, images_dir): +def mount_rootfs(args, images_dir, session): helpers.mount.mount(args, images_dir + "/system.img", tools.config.defaults["rootfs"], umount=True) helpers.mount.mount(args, images_dir + "/vendor.img", @@ -144,7 +142,7 @@ def mount_rootfs(args, images_dir): helpers.mount.bind( args, "/vendor/odm", tools.config.defaults["rootfs"] + "/odm_extra") - make_prop(args, args.work + "/waydroid.prop") + make_prop(args, session, args.work + "/waydroid.prop") helpers.mount.bind_file(args, args.work + "/waydroid.prop", tools.config.defaults["rootfs"] + "/vendor/waydroid.prop") diff --git a/tools/helpers/ipc.py b/tools/helpers/ipc.py index 2ea28e1..aa62061 100644 --- a/tools/helpers/ipc.py +++ b/tools/helpers/ipc.py @@ -3,6 +3,7 @@ # Currently implemented as FIFO import os +import dbus BASE_DIR = "/var/run/" @@ -35,3 +36,9 @@ def notify(channel, msg): def notify_blocking(channel, msg): with open_channel(channel, "w", 1) as channel: channel.write(msg) + +def DBusContainerService(object_path="/ContainerManager", intf="id.waydro.ContainerManager"): + return dbus.Interface(dbus.SystemBus().get_object("id.waydro.Container", object_path), intf) + +def DBusSessionService(object_path="/SessionManager", intf="id.waydro.SessionManager"): + return dbus.Interface(dbus.SessionBus().get_object("id.waydro.Session", object_path), intf) diff --git a/tools/helpers/props.py b/tools/helpers/props.py index de3c3a8..0d7f4bc 100644 --- a/tools/helpers/props.py +++ b/tools/helpers/props.py @@ -21,34 +21,18 @@ def host_set(args, prop, value): tools.helpers.run.user(args, command) def get(args, prop): - if os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() - if session_cfg["session"]["state"] == "RUNNING": - platformService = IPlatform.get_service(args) - if platformService: - return platformService.getprop(prop, "") - else: - logging.error("Failed to access IPlatform service") - else: - logging.error("WayDroid container is {}".format( - session_cfg["session"]["state"])) + platformService = IPlatform.get_service(args) + if platformService: + return platformService.getprop(prop, "") else: - logging.error("WayDroid session is stopped") + logging.error("Failed to access IPlatform service") def set(args, prop, value): - if os.path.exists(tools.config.session_defaults["config_path"]): - session_cfg = tools.config.load_session() - if session_cfg["session"]["state"] == "RUNNING": - platformService = IPlatform.get_service(args) - if platformService: - platformService.setprop(prop, value) - else: - logging.error("Failed to access IPlatform service") - else: - logging.error("WayDroid container is {}".format( - session_cfg["session"]["state"])) + platformService = IPlatform.get_service(args) + if platformService: + platformService.setprop(prop, value) else: - logging.error("WayDroid session is stopped") + logging.error("Failed to access IPlatform service") def file_get(args, file, prop): with open(file) as build_prop: diff --git a/tools/services/hardware_manager.py b/tools/services/hardware_manager.py index 8d21dd0..efc3236 100644 --- a/tools/services/hardware_manager.py +++ b/tools/services/hardware_manager.py @@ -33,7 +33,7 @@ def start(args): helpers.images.umount_rootfs(args) helpers.images.replace(args, system_zip, system_time, vendor_zip, vendor_time) - helpers.images.mount_rootfs(args, args.images_path) + helpers.images.mount_rootfs(args, args.images_path, args.session) helpers.protocol.set_aidl_version(args) helpers.lxc.start(args) diff --git a/tools/services/user_manager.py b/tools/services/user_manager.py index c33f189..f64ebcb 100644 --- a/tools/services/user_manager.py +++ b/tools/services/user_manager.py @@ -9,7 +9,7 @@ from tools.interfaces import IPlatform stopping = False -def start(args, unlocked_cb=None): +def start(args, session, unlocked_cb=None): def makeDesktopFile(appInfo): showApp = False @@ -54,9 +54,8 @@ def start(args, unlocked_cb=None): def userUnlocked(uid): logging.info("Android with user {} is ready".format(uid)) - session_cfg = tools.config.load_session() - args.waydroid_data = session_cfg["session"]["waydroid_data"] - args.apps_dir = session_cfg["session"]["xdg_data_home"] + \ + args.waydroid_data = session["waydroid_data"] + args.apps_dir = session["xdg_data_home"] + \ "/applications/" platformService = IPlatform.get_service(args) @@ -73,7 +72,7 @@ def start(args, unlocked_cb=None): else: makeWaydroidDesktopFile(True) if unlocked_cb: - unlocked_cb(args) + unlocked_cb() def packageStateChanged(mode, packageName, uid): platformService = IPlatform.get_service(args) -- 2.47.3