mirror of
https://github.com/waydroid/waydroid.git
synced 2025-12-23 22:29:18 -05:00
init: Allow re-initializing while container daemon is running
* Make the container service always expose the initializer object on DBus * Add `waydroid init --client` to always bring up the GTK initializer client
This commit is contained in:
@@ -4,10 +4,14 @@ Name=Waydroid
|
||||
Exec=waydroid
|
||||
Icon=waydroid
|
||||
Categories=X-WayDroid-App;Utility;
|
||||
Actions=stop;
|
||||
Actions=stop;initialize;
|
||||
X-Purism-FormFactor=Workstation;Mobile;
|
||||
|
||||
[Desktop Action stop]
|
||||
Name=Stop Waydroid
|
||||
Exec=waydroid session stop
|
||||
Icon=waydroid
|
||||
|
||||
[Desktop Action initialize]
|
||||
Name=Initialize Waydroid
|
||||
Exec=waydroid init --client
|
||||
|
||||
@@ -4,7 +4,7 @@ Description=Waydroid Container
|
||||
[Service]
|
||||
UMask=0022
|
||||
BusName=id.waydro.Container
|
||||
ExecStart=/usr/bin/waydroid -w container start
|
||||
ExecStart=/usr/bin/waydroid container start
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -43,27 +43,16 @@ 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:
|
||||
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
|
||||
|
||||
if args.action is None:
|
||||
args.action = "first-launch"
|
||||
|
||||
if args.action == "init":
|
||||
actionNeedRoot(args.action)
|
||||
actions.init(args)
|
||||
if args.client:
|
||||
actions.remote_init_client(args)
|
||||
else:
|
||||
actionNeedRoot(args.action)
|
||||
actions.init(args)
|
||||
elif args.action == "upgrade":
|
||||
actionNeedRoot(args.action)
|
||||
actions.upgrade(args)
|
||||
@@ -78,12 +67,6 @@ 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)
|
||||
@@ -127,7 +110,8 @@ def main():
|
||||
elif args.action == "show-full-ui":
|
||||
actions.app_manager.showFullUI(args)
|
||||
elif args.action == "first-launch":
|
||||
actions.remote_init_client(args)
|
||||
if not actions.initializer.is_initialized(args):
|
||||
actions.remote_init_client(args)
|
||||
if actions.initializer.is_initialized(args):
|
||||
actions.app_manager.showFullUI(args)
|
||||
elif args.action == "status":
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Copyright 2021 Erfan Abdi
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from tools.actions.initializer import init, wait_for_init, remote_init_client
|
||||
from tools.actions.initializer import init, remote_init_client
|
||||
from tools.actions.upgrader import upgrade
|
||||
from tools.actions.session_manager import start, stop
|
||||
from tools.actions.container_manager import start, stop, freeze, unfreeze
|
||||
|
||||
@@ -8,6 +8,7 @@ import signal
|
||||
import tools.config
|
||||
from tools import helpers
|
||||
from tools import services
|
||||
from tools import actions
|
||||
import dbus
|
||||
import dbus.service
|
||||
import dbus.exceptions
|
||||
@@ -36,14 +37,20 @@ class DbusContainerManager(dbus.service.Object):
|
||||
|
||||
@dbus.service.method("id.waydro.ContainerManager", in_signature='', out_signature='')
|
||||
def Freeze(self):
|
||||
if not actions.initializer.is_initialized(self.args):
|
||||
raise RuntimeError("Waydroid is not initialized")
|
||||
freeze(self.args)
|
||||
|
||||
@dbus.service.method("id.waydro.ContainerManager", in_signature='', out_signature='')
|
||||
def Unfreeze(self):
|
||||
if not actions.initializer.is_initialized(self.args):
|
||||
raise RuntimeError("Waydroid is not initialized")
|
||||
unfreeze(self.args)
|
||||
|
||||
@dbus.service.method("id.waydro.ContainerManager", in_signature='', out_signature='a{ss}')
|
||||
def GetSession(self):
|
||||
if not actions.initializer.is_initialized(self.args):
|
||||
raise RuntimeError("Waydroid is not initialized")
|
||||
try:
|
||||
session = self.args.session
|
||||
session["state"] = helpers.lxc.status(self.args)
|
||||
@@ -52,7 +59,8 @@ class DbusContainerManager(dbus.service.Object):
|
||||
return {}
|
||||
|
||||
def service(args, looper):
|
||||
dbus_obj = DbusContainerManager(looper, dbus.SystemBus(), '/ContainerManager', args)
|
||||
initializer = actions.initializer.DbusInitializer(looper, dbus.SystemBus(), '/Initializer', args)
|
||||
runner = DbusContainerManager(looper, dbus.SystemBus(), '/ContainerManager', args)
|
||||
looper.run()
|
||||
|
||||
def set_permissions(args, perm_list=None, mode="777"):
|
||||
@@ -101,37 +109,48 @@ def start(args):
|
||||
logging.error("Container service is already running")
|
||||
return
|
||||
|
||||
status = helpers.lxc.status(args)
|
||||
if status == "STOPPED":
|
||||
# Load binder and ashmem drivers
|
||||
cfg = tools.config.load(args)
|
||||
if cfg["waydroid"]["vendor_type"] == "MAINLINE":
|
||||
if helpers.drivers.probeBinderDriver(args) != 0:
|
||||
logging.error("Failed to load Binder driver")
|
||||
helpers.drivers.probeAshmemDriver(args)
|
||||
helpers.drivers.loadBinderNodes(args)
|
||||
set_permissions(args, [
|
||||
"/dev/" + args.BINDER_DRIVER,
|
||||
"/dev/" + args.VNDBINDER_DRIVER,
|
||||
"/dev/" + args.HWBINDER_DRIVER
|
||||
], "666")
|
||||
mainloop = GLib.MainLoop()
|
||||
|
||||
mainloop = GLib.MainLoop()
|
||||
|
||||
def sigint_handler(data):
|
||||
def sigint_handler(data):
|
||||
try:
|
||||
stop(args)
|
||||
mainloop.quit()
|
||||
except:
|
||||
pass
|
||||
mainloop.quit()
|
||||
|
||||
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))
|
||||
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)
|
||||
|
||||
prepared_drivers = False
|
||||
def prepare_drivers_once(args):
|
||||
global prepared_drivers
|
||||
if prepared_drivers:
|
||||
return
|
||||
|
||||
# Load binder and ashmem drivers
|
||||
cfg = tools.config.load(args)
|
||||
if cfg["waydroid"]["vendor_type"] == "MAINLINE":
|
||||
if helpers.drivers.probeBinderDriver(args) != 0:
|
||||
logging.error("Failed to load Binder driver")
|
||||
helpers.drivers.probeAshmemDriver(args)
|
||||
helpers.drivers.loadBinderNodes(args)
|
||||
set_permissions(args, [
|
||||
"/dev/" + args.BINDER_DRIVER,
|
||||
"/dev/" + args.VNDBINDER_DRIVER,
|
||||
"/dev/" + args.HWBINDER_DRIVER
|
||||
], "666")
|
||||
prepared_drivers = True
|
||||
|
||||
def do_start(args, session):
|
||||
if not actions.initializer.is_initialized(args):
|
||||
raise RuntimeError("Waydroid is not initialized")
|
||||
|
||||
if "session" in args:
|
||||
raise RuntimeError("Already tracking a session")
|
||||
|
||||
prepare_drivers_once(args)
|
||||
|
||||
logging.info("Starting up container for a new session")
|
||||
|
||||
# Networking
|
||||
@@ -194,6 +213,9 @@ def do_start(args, session):
|
||||
args.session = session
|
||||
|
||||
def stop(args, quit_session=True):
|
||||
if not actions.initializer.is_initialized(args):
|
||||
raise RuntimeError("Waydroid is not initialized")
|
||||
|
||||
logging.info("Stopping container")
|
||||
|
||||
try:
|
||||
|
||||
@@ -117,69 +117,56 @@ def setup_config(args):
|
||||
return True
|
||||
|
||||
def init(args):
|
||||
if not is_initialized(args) or args.force:
|
||||
initializer_service = None
|
||||
try:
|
||||
initializer_service = tools.helpers.ipc.DBusContainerService("/Initializer", "id.waydro.Initializer")
|
||||
except dbus.DBusException:
|
||||
pass
|
||||
if not setup_config(args):
|
||||
return
|
||||
status = "STOPPED"
|
||||
if os.path.exists(tools.config.defaults["lxc"] + "/waydroid"):
|
||||
status = helpers.lxc.status(args)
|
||||
if status != "STOPPED":
|
||||
if is_initialized(args) and not args.force:
|
||||
logging.info("Already initialized")
|
||||
|
||||
if not setup_config(args):
|
||||
return
|
||||
|
||||
status = "STOPPED"
|
||||
session = None
|
||||
if os.path.exists(tools.config.defaults["lxc"] + "/waydroid"):
|
||||
status = helpers.lxc.status(args)
|
||||
if status != "STOPPED":
|
||||
if "running_init_in_service" in args:
|
||||
session = args.session
|
||||
tools.actions.container_manager.stop(args, False)
|
||||
else:
|
||||
logging.info("Stopping container")
|
||||
try:
|
||||
container = tools.helpers.ipc.DBusContainerService()
|
||||
args.session = container.GetSession()
|
||||
session = container.GetSession()
|
||||
container.Stop(False)
|
||||
except Exception as e:
|
||||
logging.debug(e)
|
||||
tools.actions.container_manager.stop(args)
|
||||
if args.images_path not in tools.config.defaults["preinstalled_images_paths"]:
|
||||
helpers.images.get(args)
|
||||
else:
|
||||
helpers.images.remove_overlay(args)
|
||||
if not os.path.isdir(tools.config.defaults["rootfs"]):
|
||||
os.mkdir(tools.config.defaults["rootfs"])
|
||||
if not os.path.isdir(tools.config.defaults["overlay"]):
|
||||
os.mkdir(tools.config.defaults["overlay"])
|
||||
os.mkdir(tools.config.defaults["overlay"]+"/vendor")
|
||||
if not os.path.isdir(tools.config.defaults["overlay_rw"]):
|
||||
os.mkdir(tools.config.defaults["overlay_rw"])
|
||||
os.mkdir(tools.config.defaults["overlay_rw"]+"/system")
|
||||
os.mkdir(tools.config.defaults["overlay_rw"]+"/vendor")
|
||||
helpers.drivers.probeAshmemDriver(args)
|
||||
helpers.lxc.setup_host_perms(args)
|
||||
helpers.lxc.set_lxc_config(args)
|
||||
helpers.lxc.make_base_props(args)
|
||||
if status != "STOPPED":
|
||||
logging.info("Starting container")
|
||||
try:
|
||||
container.Start(args.session)
|
||||
except Exception as e:
|
||||
logging.debug(e)
|
||||
logging.error("Failed to restart container. Please do so manually.")
|
||||
|
||||
if "running_init_in_service" not in args or not args.running_init_in_service:
|
||||
try:
|
||||
if initializer_service:
|
||||
initializer_service.Done()
|
||||
except dbus.DBusException:
|
||||
pass
|
||||
tools.actions.container_manager.stop(args, False)
|
||||
if args.images_path not in tools.config.defaults["preinstalled_images_paths"]:
|
||||
helpers.images.get(args)
|
||||
else:
|
||||
logging.info("Already initialized")
|
||||
|
||||
def wait_for_init(args):
|
||||
helpers.ipc.create_channel("remote_init_output")
|
||||
|
||||
mainloop = GLib.MainLoop()
|
||||
dbus_obj = DbusInitializer(mainloop, dbus.SystemBus(), '/Initializer', args)
|
||||
mainloop.run()
|
||||
|
||||
# After init
|
||||
dbus_obj.remove_from_connection()
|
||||
helpers.images.remove_overlay(args)
|
||||
if not os.path.isdir(tools.config.defaults["rootfs"]):
|
||||
os.mkdir(tools.config.defaults["rootfs"])
|
||||
if not os.path.isdir(tools.config.defaults["overlay"]):
|
||||
os.mkdir(tools.config.defaults["overlay"])
|
||||
os.mkdir(tools.config.defaults["overlay"]+"/vendor")
|
||||
if not os.path.isdir(tools.config.defaults["overlay_rw"]):
|
||||
os.mkdir(tools.config.defaults["overlay_rw"])
|
||||
os.mkdir(tools.config.defaults["overlay_rw"]+"/system")
|
||||
os.mkdir(tools.config.defaults["overlay_rw"]+"/vendor")
|
||||
helpers.drivers.probeAshmemDriver(args)
|
||||
helpers.lxc.setup_host_perms(args)
|
||||
helpers.lxc.set_lxc_config(args)
|
||||
helpers.lxc.make_base_props(args)
|
||||
if status != "STOPPED":
|
||||
try:
|
||||
if "running_init_in_service" in args:
|
||||
tools.actions.container_manager.do_start(args, session)
|
||||
else:
|
||||
logging.info("Starting container")
|
||||
container.Start(session)
|
||||
except Exception as e:
|
||||
logging.debug(e)
|
||||
logging.error("Failed to restart container. Please do so manually.")
|
||||
|
||||
class DbusInitializer(dbus.service.Object):
|
||||
def __init__(self, looper, bus, object_path, args):
|
||||
@@ -197,11 +184,6 @@ class DbusInitializer(dbus.service.Object):
|
||||
else:
|
||||
raise PermissionError("Polkit: Authentication failed")
|
||||
|
||||
@dbus.service.method("id.waydro.Initializer", in_signature='', out_signature='')
|
||||
def Done(self):
|
||||
if is_initialized(self.args):
|
||||
self.looper.quit()
|
||||
|
||||
def ensure_polkit_auth(sender, conn, privilege):
|
||||
dbus_info = dbus.Interface(conn.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus/Bus", False), "org.freedesktop.DBus")
|
||||
pid = dbus_info.GetConnectionUnixProcessID(sender)
|
||||
@@ -289,21 +271,6 @@ def remote_init_client(args):
|
||||
|
||||
bus = dbus.SystemBus()
|
||||
|
||||
if is_initialized(args):
|
||||
try:
|
||||
tools.helpers.ipc.DBusContainerService("/Initializer", "id.waydro.Initializer").Done()
|
||||
except dbus.DBusException:
|
||||
pass
|
||||
return
|
||||
|
||||
def notify_and_quit(caller):
|
||||
if is_initialized(args):
|
||||
try:
|
||||
tools.helpers.ipc.DBusContainerService("/Initializer", "id.waydro.Initializer").Done()
|
||||
except dbus.DBusException:
|
||||
pass
|
||||
GLib.idle_add(Gtk.main_quit)
|
||||
|
||||
class WaydroidInitWindow(Gtk.Window):
|
||||
def __init__(self):
|
||||
super().__init__(title="Initialize Waydroid")
|
||||
@@ -440,7 +407,7 @@ def remote_init_client(args):
|
||||
|
||||
GLib.set_prgname("Waydroid")
|
||||
win = WaydroidInitWindow()
|
||||
win.connect("destroy", notify_and_quit)
|
||||
win.connect("destroy", Gtk.main_quit)
|
||||
|
||||
win.show_all()
|
||||
win.outTextView.hide()
|
||||
|
||||
@@ -33,6 +33,7 @@ def arguments_init(subparser):
|
||||
help="rom type (options: \"lineage\", \"bliss\" or OTA channel URL; default is LineageOS)")
|
||||
ret.add_argument("-s", "--system_type",
|
||||
help="system type (options: VANILLA, FOSS or GAPPS; default is VANILLA)")
|
||||
ret.add_argument("--client", help="run as user mode, connecting to the remote initializer service", action="store_true")
|
||||
return ret
|
||||
|
||||
def arguments_status(subparser):
|
||||
@@ -152,8 +153,6 @@ def arguments():
|
||||
" logfiles (this may reduce performance)")
|
||||
parser.add_argument("-q", "--quiet", dest="quiet", action="store_true",
|
||||
help="do not output any log messages")
|
||||
parser.add_argument("-w", "--wait", dest="wait_for_init", action="store_true",
|
||||
help="wait for init before running")
|
||||
|
||||
# Actions
|
||||
sub = parser.add_subparsers(title="action", dest="action")
|
||||
|
||||
Reference in New Issue
Block a user