X-Git-Url: https://glassweightruler.freedombox.rocks/gitweb/waydroid.git/blobdiff_plain/a6e58f9e24d89d66960375b6776fdbeb63294eaf..c181bf984d4c5c8b189e3ffcf6bb52f5ed6b0d98:/tools/services/user_manager.py diff --git a/tools/services/user_manager.py b/tools/services/user_manager.py index b8d1df5..ac7a87c 100644 --- a/tools/services/user_manager.py +++ b/tools/services/user_manager.py @@ -1,94 +1,166 @@ # Copyright 2021 Erfan Abdi # SPDX-License-Identifier: GPL-3.0-or-later +import glob import logging import os import threading import tools.config +import tools.helpers.net from tools.interfaces import IUserMonitor from tools.interfaces import IPlatform +from gi.repository import GLib stopping = False def start(args, session, unlocked_cb=None): + waydroid_data = session["waydroid_data"] + apps_dir = session["xdg_data_home"] + "/applications/" + + system_apps = [ + "com.android.calculator2", + "com.android.camera2", + "com.android.contacts", + "com.android.deskclock", + "com.android.documentsui", + "com.android.email", + "com.android.gallery3d", + "com.android.inputmethod.latin", + "com.android.settings", + "com.google.android.gms", + "org.lineageos.eleven", + "org.lineageos.etar", + "org.lineageos.jelly", + "org.lineageos.recorder" + ] + + + def prepend_list(old_list, new_list): + for s in reversed(new_list): + if s not in old_list: + old_list.insert(0, s) + + def glib_key_file_get_string_list(key_file, group, key): + try: + return key_file.get_string_list(group, key) + except: + return [] + + def glib_key_file_prepend_string_list(key_file, group, key, new_list): + old_list = glib_key_file_get_string_list(key_file, group, key) + prepend_list(old_list, new_list) + key_file.set_string_list(group, key, new_list) + + def glib_key_file_has_value(key_file, group, key): + try: + key_file.get_value(group, key) + return True + except: + return False + + + # Creates, deletes, or updates desktop file + def updateDesktopFile(appInfo): + if appInfo is None: + return - def makeDesktopFile(appInfo): showApp = False for cat in appInfo["categories"]: if cat.strip() == "android.intent.category.LAUNCHER": showApp = True if not showApp: - return -1 - + try: + os.remove(desktop_file_path) + except: + pass + packageName = appInfo["packageName"] - desktop_file_path = args.apps_dir + "/waydroid." + packageName + ".desktop" - if not os.path.exists(desktop_file_path): - lines = ["[Desktop Entry]", "Type=Application"] - lines.append("Name=" + appInfo["name"]) - lines.append("Exec=waydroid app launch " + packageName) - lines.append("Icon=" + args.waydroid_data + "/icons/" + packageName + ".png") - lines.append("X-Purism-FormFactor=Workstation;Mobile;") - desktop_file = open(desktop_file_path, "w") - for line in lines: - desktop_file.write(line + "\n") - desktop_file.close() - os.chmod(desktop_file_path, 0o755) - return 0 - - def makeWaydroidDesktopFile(hide): - desktop_file_path = args.apps_dir + "/Waydroid.desktop" - if os.path.isfile(desktop_file_path): - os.remove(desktop_file_path) - lines = ["[Desktop Entry]", "Type=Application"] - lines.append("Name=Waydroid") - lines.append("Exec=waydroid show-full-ui") - lines.append("X-Purism-FormFactor=Workstation;Mobile;") - if hide: - lines.append("NoDisplay=true") - lines.append("Icon=" + tools.config.tools_src + "/data/AppIcon.png") - desktop_file = open(desktop_file_path, "w") - for line in lines: - desktop_file.write(line + "\n") - desktop_file.close() - os.chmod(desktop_file_path, 0o755) + desktop_file_path = apps_dir + "/waydroid." + packageName + ".desktop" + desktop_file = GLib.KeyFile() + try: + flags = GLib.KeyFileFlags.KEEP_COMMENTS | GLib.KeyFileFlags.KEEP_TRANSLATIONS + desktop_file.load_from_file(desktop_file_path, flags) + except: + pass + + desktop_file.set_string("Desktop Entry", "Type", "Application") + desktop_file.set_string("Desktop Entry", "Name", appInfo["name"]) + desktop_file.set_string("Desktop Entry", "Exec", f"waydroid app launch {packageName}") + desktop_file.set_string("Desktop Entry", "Icon", f"{waydroid_data}/icons/{packageName}.png") + glib_key_file_prepend_string_list(desktop_file, "Desktop Entry", "Categories", ["X-WayDroid-App"]) + desktop_file.set_string_list("Desktop Entry", "X-Purism-FormFactor", ["Workstation", "Mobile"]) + glib_key_file_prepend_string_list(desktop_file, "Desktop Entry", "Actions", ["app_settings"]) + if packageName in system_apps and not glib_key_file_has_value(desktop_file, "Desktop Entry", "NoDisplay"): + desktop_file.set_boolean("Desktop Entry", "NoDisplay", True) + + desktop_file.set_string("Desktop Action app_settings", "Name", "App Settings") + desktop_file.set_string("Desktop Action app_settings", "Exec", f"waydroid app intent android.settings.APPLICATION_DETAILS_SETTINGS package:{packageName}") + desktop_file.set_string("Desktop Action app_settings", "Icon", f"{waydroid_data}/icons/com.android.settings.png") + + desktop_file.save_to_file(desktop_file_path) + + + def updateWaydroidDesktopFile(hide): + desktop_file_path = apps_dir + "/Waydroid.desktop" + # If the user has set the desktop file as read-only, we won't replace it + if os.path.isfile(desktop_file_path) and not os.access(desktop_file_path, os.W_OK): + logging.info(f"Desktop file '{desktop_file_path}' is not writeable, not updating it") + return + + desktop_file = GLib.KeyFile() + try: + flags = GLib.KeyFileFlags.KEEP_COMMENTS | GLib.KeyFileFlags.KEEP_TRANSLATIONS + desktop_file.load_from_file(desktop_file_path, flags) + except: + pass + + desktop_file.set_string("Desktop Entry", "Type", "Application") + desktop_file.set_string("Desktop Entry", "Name", "Waydroid") + desktop_file.set_string("Desktop Entry", "Exec", "waydroid show-full-ui") + glib_key_file_prepend_string_list(desktop_file, "Desktop Entry", "Categories", ["X-WayDroid-App", "Utility"]) + desktop_file.set_string_list("Desktop Entry", "X-Purism-FormFactor", ["Workstation", "Mobile"]) + desktop_file.set_string("Desktop Entry", "Icon", "waydroid") + desktop_file.set_boolean("Desktop Entry", "NoDisplay", hide) + + desktop_file.save_to_file(desktop_file_path) def userUnlocked(uid): + cfg = tools.config.load(args) logging.info("Android with user {} is ready".format(uid)) - args.waydroid_data = session["waydroid_data"] - args.apps_dir = session["xdg_data_home"] + \ - "/applications/" + + if cfg["waydroid"]["auto_adb"] == "True": + try: + tools.helpers.net.adb_connect(args) + except: + pass platformService = IPlatform.get_service(args) if platformService: - if not os.path.exists(args.apps_dir): - os.mkdir(args.apps_dir) - os.chmod(args.apps_dir, 0o700) + if not os.path.exists(apps_dir): + os.mkdir(apps_dir, 0o700) appsList = platformService.getAppsInfo() for app in appsList: - makeDesktopFile(app) + updateDesktopFile(app) + for existing in glob.iglob(f'{apps_dir}/waydroid.*.desktop'): + if os.path.basename(existing) not in map(lambda appInfo: f"waydroid.{appInfo['packageName']}.desktop", appsList): + os.remove(existing) multiwin = platformService.getprop("persist.waydroid.multi_windows", "false") - if multiwin == "false": - makeWaydroidDesktopFile(False) - else: - makeWaydroidDesktopFile(True) + updateWaydroidDesktopFile(multiwin == "true") if unlocked_cb: unlocked_cb() def packageStateChanged(mode, packageName, uid): platformService = IPlatform.get_service(args) if platformService: - appInfo = platformService.getAppInfo(packageName) - desktop_file_path = args.apps_dir + "/waydroid." + packageName + ".desktop" - if mode == 0: - # Package added - makeDesktopFile(appInfo) - elif mode == 1: - if os.path.isfile(desktop_file_path): + desktop_file_path = apps_dir + "/waydroid." + packageName + ".desktop" + if mode == IUserMonitor.PACKAGE_REMOVED: + try: os.remove(desktop_file_path) + except: + pass else: - if os.path.isfile(desktop_file_path): - if makeDesktopFile(appInfo) == -1: - os.remove(desktop_file_path) + appInfo = platformService.getAppInfo(packageName) + updateDesktopFile(appInfo) def service_thread(): while not stopping: