--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<policyconfig>
+ <action id="org.waydro.id.policy">
+ <description>Waydroid</description>
+ <message>Authentication is required to initialize Waydroid</message>
+ <icon_name>system-software-install</icon_name>
+ <defaults>
+ <allow_any>auth_admin</allow_any>
+ <allow_inactive>auth_admin</allow_inactive>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/waydroid</annotate>
+ <annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
+ </action>
+</policyconfig>
import logging
import os
import traceback
+import subprocess
from . import actions
from . import config
args.timeout = 1800
if not actions.initializer.is_initialized(args):
- if args.action and (args.action != "init" and args.action != "log"):
+ if args.action and (args.action not in ("init", "first-launch", "log")):
if not args.wait_for_init:
print('ERROR: WayDroid is not initialized, run "waydroid init"')
return 0
helpers.lxc.logcat(args)
elif args.action == "show-full-ui":
actions.app_manager.showFullUI(args)
+ elif args.action == "first-launch":
+ subprocess.run(["pkexec", sys.argv[0], "init", "--gui"])
+ if actions.initializer.is_initialized(args):
+ actions.app_manager.showFullUI(args)
elif args.action == "status":
actions.status.print_status(args)
elif args.action == "log":
from tools import helpers
import tools.config
+from tkinter import *
+from tkinter import ttk
+
+import sys
+import threading
+class Daemon(threading.Thread):
+ def __init__(self):
+ super().__init__()
+ self.daemon = True
+
def is_initialized(args):
return os.path.isfile(args.config) and os.path.isdir(tools.config.defaults["rootfs"])
cfg["waydroid"]["hwbinder"] = args.HWBINDER_DRIVER
tools.config.save(args, cfg)
-def init(args):
+def do_init(args):
if not is_initialized(args) or args.force:
setup_config(args)
status = "STOPPED"
helpers.ipc.notify(channel="init", msg="done")
else:
logging.info("Already initialized")
+
+def init(args):
+ if args.gui:
+ gui_init(args)
+ else:
+ do_init(args)
+
+def gui_init(args):
+ if is_initialized(args) and not args.force:
+ return
+
+ root = Tk()
+ root.title("Initialize Waydroid")
+ root.iconphoto(True, PhotoImage(file="/usr/lib/waydroid/data/AppIcon.png"))
+ frm = ttk.Frame(root, padding=10)
+ frm.grid()
+
+ systemChannel = StringVar(frm, args.system_channel or tools.config.channels_defaults["system_channel"])
+ ttk.Label(frm, text="System OTA").grid(row=0, column=0)
+ ttk.Entry(frm, textvariable=systemChannel).grid(row=0, column=1, ipadx=20)
+
+ vendorChannel = StringVar(frm, args.vendor_channel or tools.config.channels_defaults["vendor_channel"])
+ ttk.Label(frm, text="Vendor OTA").grid(row=1, column=0)
+ ttk.Entry(frm, textvariable=vendorChannel).grid(row=1, column=1, ipadx=20)
+
+ systemType = StringVar(frm)
+ systemTypes = ["VANILLA", "GAPPS"]
+ ttk.Label(frm, text="Android Type").grid(row=2, column=0)
+ ttk.OptionMenu(frm, systemType, args.system_type or systemTypes[0], *systemTypes).grid(row=2, column=1)
+
+ done = ttk.Button(frm, text="Done", command=root.destroy)
+
+ logBox = Text(frm, borderwidth=3, relief="sunken", height=5)
+ logBox.bind("<Key>", lambda e: "break")
+
+ class StdoutRedirect(logging.StreamHandler):
+ def write(self, s):
+ if s.startswith('\r'):
+ logBox.delete("end-1l", "end")
+ logBox.insert(END, '\n')
+ s = s[1:]
+
+ logBox.insert(END, s)
+ logBox.see(END)
+ def flush(self):
+ pass
+ def emit(self, record):
+ if record.levelno >= logging.INFO:
+ self.write(self.format(record) + self.terminator)
+
+ out = StdoutRedirect()
+ sys.stdout = sys.stderr = out
+ logging.getLogger().addHandler(out)
+
+ def runInit():
+ download["state"] = DISABLED
+ logBox.grid(row=4, columnspan=2)
+
+ args.system_channel = systemChannel.get()
+ args.vendor_channel = vendorChannel.get()
+ args.system_type = systemType.get()
+
+ class Runner(Daemon):
+ def run(self):
+ try:
+ do_init(args)
+ if is_initialized(args):
+ done.grid(row=5, columnspan=2)
+ print("Done")
+ else:
+ download["state"] = NORMAL
+ except Exception as e:
+ print("ERROR: " + str(e))
+ download["state"] = NORMAL
+
+ Runner().start()
+
+ download = ttk.Button(frm, text="Download", command=runInit)
+ download.grid(row=3, columnspan=2)
+ root.mainloop()
+
+ sys.stdout = sys.__stdout__
+ sys.stderr = sys.__stderr__
+ logging.getLogger().removeHandler(out)
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("-g", "--gui", action="store_true",
+ help="run as a graphical interface")
return ret
def arguments_status(subparser):
ret = subparser.add_parser("show-full-ui", help="show android full screen in window")
return ret
+def arguments_firstLaunch(subparser):
+ ret = subparser.add_parser("first-launch", help="initialize waydroid and start it")
+ return ret
+
def arguments_shell(subparser):
ret = subparser.add_parser("shell", help="run remote shell command")
ret.add_argument('COMMAND', nargs='?', help="command to run")
arguments_app(sub)
arguments_prop(sub)
arguments_fullUI(sub)
+ arguments_firstLaunch(sub)
arguments_shell(sub)
arguments_logcat(sub)