add uninstall function

This commit is contained in:
Rikka 2023-01-26 23:23:50 +08:00 committed by Rikka
parent 4d15b6153c
commit 0d7681bccb
No known key found for this signature in database
GPG key ID: CD36B07FA9F7D2AA
12 changed files with 244 additions and 63 deletions

View file

@ -140,17 +140,19 @@ Star this repository if you find this useful, if you encounter problem create a
## Error handling ## Error handling
In case of error, if you retry immediately and it fails with this error - WayDroid no longer boots
``` ```
==> Failed to resize image '/var/lib/waydroid/images/system.img' .. ! e2fsck 1.45.5 (07-Jan-2020) sudo waydroid upgrade -o
/var/lib/waydroid/images/system.img is mounted. sudo systemctl restart waydroid-container.service
e2fsck: Cannot continue, aborting.
``` ```
You need to get the mounting point using `df | grep waydroid`. It will be something like `/dev/loopXXX`. Then, unmount it This will make `/var/lib/waydroid/waydroid_base.prop` return to original state, so libndk/libhoudini will be invalid. You need to modify `waydroid_base.prop` again.
```
sudo umount /dev/loopXXX Or use `sudo python3 main.py uninstall xxxxx` to remove what is causing the issue.
```
And re-run the script. - Magisk installed: N/A
Check [waydroid-magisk](https://github.com/nitanmarcel/waydroid-magisk)
## Credits ## Credits
- [WayDroid](https://github.com/waydroid/waydroid) - [WayDroid](https://github.com/waydroid/waydroid)

20
main.py
View file

@ -41,18 +41,10 @@ def install(*args):
def uninstall(*args): def uninstall(*args):
if "gapps" in args: if "gapps" in args:
Gapps().uninstall() Gapps().uninstall()
if "libndk" in args and "houdini" not in args: if "libndk" in args:
arch = helper.host()[0] Ndk().uninstall()
if arch == "x86_64": if "libhoudini" in args:
Ndk().uninstall() Houdini().uninstall()
else:
Logger.warn("libndk is not supported on your CPU")
if "libhoudini" in args and "ndk" not in args:
arch = helper.host()[0]
if arch == "x86_64":
Houdini().uninstall()
else:
Logger.warn("libhoudini is not supported on your CPU")
if "magisk" in args: if "magisk" in args:
Magisk().uninstall() Magisk().uninstall()
if "widevine" in args: if "widevine" in args:
@ -61,6 +53,8 @@ def uninstall(*args):
Smartdock().uninstall() Smartdock().uninstall()
if "nodataperm" in args: if "nodataperm" in args:
Nodataperm().uninstall() Nodataperm().uninstall()
if "microg" in args:
MicroG().uninstall()
def main(): def main():
about = """ about = """
@ -85,7 +79,7 @@ def main():
"type": str, "type": str,
"nargs": '+', "nargs": '+',
"metavar":"", "metavar":"",
"choices": ["gapps", "microg", "libndk","libhoudini","magisk", "smartdock","widevine", "nodataperm"], "choices": ["gapps", "microg", "libndk", "libhoudini", "magisk", "smartdock", "widevine", "nodataperm"],
} }
install_help = """ install_help = """

View file

@ -27,6 +27,36 @@ class Gapps(General):
"setupwizarddefault-x86_64.tar.lz", "setupwizarddefault-x86_64.tar.lz",
"setupwizardtablet-x86_64.tar.lz" "setupwizardtablet-x86_64.tar.lz"
] ]
files = [
"etc/default-permissions/default-permissions.xml",
"etc/default-permissions/opengapps-permissions-q.xml",
"etc/permissions/com.google.android.maps.xml",
"etc/permissions/com.google.android.media.effects.xml",
"etc/permissions/privapp-permissions-google.xml",
"etc/permissions/split-permissions-google.xml",
"etc/preferred-apps/google.xml",
"etc/sysconfig/google.xml",
"etc/sysconfig/google_build.xml",
"etc/sysconfig/google_exclusives_enable.xml",
"etc/sysconfig/google-hiddenapi-package-whitelist.xml",
"framework/com.google.android.maps.jar",
"framework/com.google.android.media.effects.jar",
"priv-app/AndroidMigratePrebuilt",
"priv-app/GoogleExtServices",
"priv-app/GoogleRestore",
"priv-app/CarrierSetup",
"priv-app/GoogleExtShared",
"priv-app/GoogleServicesFramework",
"priv-app/ConfigUpdater",
"priv-app/GoogleFeedback",
"priv-app/Phonesky",
"priv-app/GoogleBackupTransport",
"priv-app/GoogleOneTimeInitializer",
"priv-app/PrebuiltGmsCore",
"priv-app/GoogleContactsSyncAdapter",
"priv-app/GooglePartnerSetup",
"product/overlay/PlayStoreOverlay.apk"
]
def copy(self): def copy(self):
if not os.path.exists(self.extract_to): if not os.path.exists(self.extract_to):

View file

@ -1,6 +1,7 @@
import configparser import glob
import os import os
import re import re
import shutil
import zipfile import zipfile
import hashlib import hashlib
from tools import images from tools import images
@ -37,6 +38,21 @@ class General:
Logger.warning( Logger.warning(
"md5 mismatches, redownloading now ....") "md5 mismatches, redownloading now ....")
loc_md5 = download_file(self.dl_link, self.download_loc) loc_md5 = download_file(self.dl_link, self.download_loc)
def remove(self):
for f in self.files:
file = os.path.join(self.copy_dir, self.partition, f)
if "*" in file:
for wildcard_file in glob.glob(file):
if os.path.isdir(wildcard_file):
shutil.rmtree(wildcard_file)
elif os.path.isfile(wildcard_file):
os.remove(wildcard_file)
else:
if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file):
os.remove(file)
def extract(self): def extract(self):
Logger.info("Extracting archive...") Logger.info("Extracting archive...")
@ -44,14 +60,26 @@ class General:
z.extractall(self.extract_to) z.extractall(self.extract_to)
def add_props(self): def add_props(self):
cfg = configparser.ConfigParser() with open(os.path.join("/var/lib/waydroid/waydroid_base.prop"), "r") as propfile:
cfg.read("/var/lib/waydroid/waydroid.cfg") prop_content = propfile.read()
for key in self.apply_props:
for key in self.apply_props.keys(): if key not in prop_content:
cfg.set('properties', key, self.apply_props[key]) prop_content = prop_content+"\n{key}={value}".format(key=key, value=self.apply_props[key])
else:
with open("/var/lib/waydroid/waydroid.cfg", "w") as f: p = re.compile(r"^{key}=.*$".format(key=key), re.M)
cfg.write(f) prop_content = re.sub(p, "{key}={value}".format(key=key, value=self.apply_props[key]), prop_content)
with open(os.path.join("/var/lib/waydroid/waydroid_base.prop"), "w") as propfile:
propfile.write(prop_content)
def remove_props(self):
with open(os.path.join("/var/lib/waydroid/waydroid_base.prop"), "r") as propfile:
prop_content = propfile.read()
for key in self.apply_props:
if key in prop_content:
p = re.compile(r"^{key}=.*(\n)*".format(key=key), re.M)
prop_content = re.sub(p, "", prop_content)
with open(os.path.join("/var/lib/waydroid/waydroid_base.prop"), "w") as propfile:
propfile.write(prop_content)
def mount(self): def mount(self):
img = os.path.join(images.get_image_dir(), self.partition+".img") img = os.path.join(images.get_image_dir(), self.partition+".img")
@ -103,6 +131,9 @@ class General:
def extra2(self): def extra2(self):
pass pass
def extra3(self):
pass
def install(self): def install(self):
if container.use_overlayfs(): if container.use_overlayfs():
self.download() self.download()
@ -131,4 +162,19 @@ class General:
Logger.info("Installation finished") Logger.info("Installation finished")
def uninstall(self): def uninstall(self):
pass if container.use_overlayfs():
self.remove()
if hasattr(self, "apply_props"):
self.remove_props()
self.extra3()
self.restart()
else:
self.stop()
self.mount()
self.remove()
if hasattr(self, "apply_props"):
self.remove_props()
self.extra3()
self.umount()
self.start()
Logger.info("Uninstallation finished")

View file

@ -31,6 +31,18 @@ on property:ro.enable.native.bridge.exec=1
"ro.dalvik.vm.isa.arm": "x86", "ro.dalvik.vm.isa.arm": "x86",
"ro.dalvik.vm.isa.arm64": "x86_64" "ro.dalvik.vm.isa.arm64": "x86_64"
} }
files = [
"bin/arm",
"bin/arm64",
"bin/houdini",
"bin/houdini64",
"etc/binfmt_misc",
"etc/init/houdini.rc",
"lib/arm",
"lib/libhoudini.so",
"lib64/arm64",
"lib64/libhoudini.so"
]
def copy(self): def copy(self):
run(["chmod", "+x", self.extract_to, "-R"]) run(["chmod", "+x", self.extract_to, "-R"])

View file

@ -3,7 +3,7 @@ import os
import shutil import shutil
import re import re
from stuffs.general import General from stuffs.general import General
from tools.helper import download_file, host, run from tools.helper import download_file, get_data_dir, host, run
from tools.logger import Logger from tools.logger import Logger
from tools import container from tools import container
@ -14,6 +14,7 @@ class Magisk(General):
extract_to = "/tmp/magisk_unpack" extract_to = "/tmp/magisk_unpack"
magisk_dir = os.path.join(partition, "etc", "init", "magisk") magisk_dir = os.path.join(partition, "etc", "init", "magisk")
machine = host() machine = host()
files = ["etc/init/magisk"]
oringinal_bootanim = """ oringinal_bootanim = """
service bootanim /system/bin/bootanimation service bootanim /system/bin/bootanimation
class core animation class core animation
@ -60,6 +61,13 @@ on property:init.svc.zygote=stopped
Logger.info("Downloading latest Magisk-Delta to {} now ...".format(self.download_loc)) Logger.info("Downloading latest Magisk-Delta to {} now ...".format(self.download_loc))
download_file(self.dl_link, self.download_loc) download_file(self.dl_link, self.download_loc)
# require additional setup
def setup(self):
Logger.info("Additional setup")
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
data_dir = get_data_dir()
shutil.copytree(magisk_absolute_dir, os.path.join(data_dir, "adb", "magisk"), dirs_exist_ok=True)
def copy(self): def copy(self):
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir) magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
if not os.path.exists(magisk_absolute_dir): if not os.path.exists(magisk_absolute_dir):
@ -79,6 +87,16 @@ on property:init.svc.zygote=stopped
shutil.copyfile(o_path, n_path) shutil.copyfile(o_path, n_path)
run(["chmod", "+x", n_path]) run(["chmod", "+x", n_path])
shutil.copyfile(self.download_loc, os.path.join(magisk_absolute_dir,"magisk.apk") ) shutil.copyfile(self.download_loc, os.path.join(magisk_absolute_dir,"magisk.apk") )
shutil.copytree(os.path.join(self.extract_to, "assets", "chromeos"), os.path.join(magisk_absolute_dir, "chromeos"), dirs_exist_ok=True)
assets_files = [
"addon.d.sh",
"boot_patch.sh",
"stub.apk",
"util_functions.sh"
]
for f in assets_files:
shutil.copyfile(os.path.join(self.extract_to, "assets", f), os.path.join(magisk_absolute_dir, f))
self.setup()
# Updating Magisk from Magisk manager will modify bootanim.rc, # Updating Magisk from Magisk manager will modify bootanim.rc,
# So it is necessary to backup the original bootanim.rc. # So it is necessary to backup the original bootanim.rc.
@ -94,16 +112,36 @@ on property:init.svc.zygote=stopped
def extra1(self): def extra1(self):
if container.use_overlayfs(): if container.use_overlayfs():
sys_overlay_rw = "/var/lib/waydroid/overlay_rw" sys_overlay_rw = "/var/lib/waydroid/overlay_rw"
old_bootanim_rc = os.path.join(sys_overlay_rw, "system","system", "etc", "init", "bootanim.rc") files = [
old_bootanim_rc_gz = os.path.join(sys_overlay_rw, "system","system", "etc", "init", "bootanim.rc.gz") "system/system/etc/init/bootanim.rc",
old_magisk = os.path.join(sys_overlay_rw, "system","system", "etc", "init", "magisk") "system/system/etc/init/bootanim.rc.gz",
"system/system/etc/init/magisk",
"system/system/addon.d/99-magisk.sh",
"vendor/etc/selinux/precompiled_sepolicy"
]
if os.path.exists(old_bootanim_rc): for f in files:
os.remove(old_bootanim_rc) file = os.path.join(sys_overlay_rw, f)
if os.path.exists(old_bootanim_rc_gz): if os.path.isdir(file):
os.remove(old_bootanim_rc_gz) shutil.rmtree(file)
if os.path.exists(old_magisk): elif os.path.isfile(file) or os.path.exists(file):
if os.path.isdir(old_magisk): os.remove(file)
shutil.rmtree(old_magisk)
else: def extra3(self):
os.remove(old_magisk) self.extra1()
data_dir = get_data_dir()
files = [
os.path.join(data_dir, "adb/magisk.db"),
os.path.join(data_dir, "adb/magisk")
]
for file in files:
if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file):
os.remove(file)
bootanim_path = os.path.join(self.copy_dir, self.partition, "etc", "init", "bootanim.rc")
if container.use_overlayfs():
os.remove(bootanim_path)
else:
with open(bootanim_path, "w") as initfile:
initfile.write(self.oringinal_bootanim)

View file

@ -28,6 +28,7 @@ class MicroG(General):
"com.android.vending-22.apk": "6815d191433ffcd8fa65923d5b0b0573", "com.android.vending-22.apk": "6815d191433ffcd8fa65923d5b0b0573",
"org.microg.gms.droidguard-14.apk": "4734b41c1a6bc34a541053ddde7a0f8e" "org.microg.gms.droidguard-14.apk": "4734b41c1a6bc34a541053ddde7a0f8e"
} }
priv_apps = ["com.google.android.gms", "com.android.vending"]
def skip_extract(self): def skip_extract(self):
return True return True
@ -59,12 +60,11 @@ class MicroG(General):
def copy(self): def copy(self):
Logger.info("Copying MicroG and other files") Logger.info("Copying MicroG and other files")
priv_apps = ["com.google.android.gms", "com.android.vending"]
for apk in {**self.fdroid_repo_apks, **self.microg_apks}.keys(): for apk in {**self.fdroid_repo_apks, **self.microg_apks}.keys():
splitor = "_" if apk in self.fdroid_repo_apks.keys() else "-" splitor = "_" if apk in self.fdroid_repo_apks.keys() else "-"
package = apk.split(splitor)[0] package = apk.split(splitor)[0]
download_dir = get_download_dir() download_dir = get_download_dir()
apk_dir = "app" if package not in priv_apps else "priv-app" apk_dir = "app" if package not in self.priv_apps else "priv-app"
if not os.path.exists(os.path.join(self.copy_dir, self.partition, apk_dir, package)): if not os.path.exists(os.path.join(self.copy_dir, self.partition, apk_dir, package)):
os.makedirs(os.path.join(self.copy_dir, self.partition, apk_dir, package)) os.makedirs(os.path.join(self.copy_dir, self.partition, apk_dir, package))
shutil.copyfile(os.path.join(download_dir, apk), shutil.copyfile(os.path.join(download_dir, apk),
@ -89,3 +89,17 @@ class MicroG(General):
Logger.info("Signature spoofing") Logger.info("Signature spoofing")
run("waydroid shell pm grant com.google.android.gms android.permission.FAKE_PACKAGE_SIGNATURE".split()) run("waydroid shell pm grant com.google.android.gms android.permission.FAKE_PACKAGE_SIGNATURE".split())
run("waydroid shell pm grant com.android.vending android.permission.FAKE_PACKAGE_SIGNATURE".split()) run("waydroid shell pm grant com.android.vending android.permission.FAKE_PACKAGE_SIGNATURE".split())
def remove(self):
system_dir = os.path.join(self.copy_dir, self.partition)
files = [key.split("_")[0] for key in self.fdroid_repo_apks.keys()]
files += [key.split("-")[0] for key in self.microg_apks.keys()]
for f in files:
if f in self.priv_apps:
file = os.path.join(system_dir, "priv-app", f)
else:
file = os.path.join(system_dir, "app", f)
if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file):
os.remove(file)

View file

@ -1,4 +1,5 @@
from os import path, makedirs import glob
import os
import shutil import shutil
from stuffs.general import General from stuffs.general import General
from tools.helper import run from tools.helper import run
@ -6,10 +7,10 @@ from tools.logger import Logger
class Ndk(General): class Ndk(General):
partition = "system" partition = "system"
dl_link = "https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/181d9290a69309511185c4417ba3d890b3caaaa8.zip" dl_link = "https://www.dropbox.com/s/eaf4dj3novwiccp/libndk_translation_Module-c6077f3398172c64f55aad7aab0e55fad9110cf3.zip?dl=1"
dl_file_name = "libndktranslation.zip" dl_file_name = "libndktranslation.zip"
extract_to = "/tmp/libndkunpack" extract_to = "/tmp/libndkunpack"
act_md5 = "0beff55f312492f24d539569d84f5bfb" act_md5 = "4456fc1002dc78e544e8d9721bb24398"
apply_props = { apply_props = {
"ro.product.cpu.abilist": "x86_64,x86,armeabi-v7a,armeabi,arm64-v8a", "ro.product.cpu.abilist": "x86_64,x86,armeabi-v7a,armeabi,arm64-v8a",
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi", "ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
@ -31,23 +32,29 @@ on property:ro.enable.native.bridge.exec=1
copy /system/etc/binfmt_misc/arm64_exe /proc/sys/fs/binfmt_misc/register copy /system/etc/binfmt_misc/arm64_exe /proc/sys/fs/binfmt_misc/register
copy /system/etc/binfmt_misc/arm64_dyn /proc/sys/fs/binfmt_misc/register copy /system/etc/binfmt_misc/arm64_dyn /proc/sys/fs/binfmt_misc/register
""" """
files = [
"bin/arm",
"bin/arm64",
"bin/ndk_translation_program_runner_binfmt_misc",
"bin/ndk_translation_program_runner_binfmt_misc_arm64",
"etc/binfmt_misc",
"etc/ld.config.arm.txt",
"etc/ld.config.arm64.txt",
"etc/init/libndk.rc",
"lib/arm",
"lib64/arm64",
"lib/libndk*",
"lib64/libndk*"
]
def copy(self): def copy(self):
run(["chmod", "+x", self.extract_to, "-R"]) run(["chmod", "+x", self.extract_to, "-R"])
Logger.info("Copying libndk library files ...") Logger.info("Copying libndk library files ...")
archive_url, commit_sha = path.split(path.splitext(self.dl_link)[0]) shutil.copytree(os.path.join(self.extract_to, "libndk_translation_Module-c6077f3398172c64f55aad7aab0e55fad9110cf3", "system"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
zipped_basepath, _ = path.split(archive_url)
prebuilts_sourcedir = path.join(
self.extract_to,
f"{path.basename(zipped_basepath)}-{commit_sha}",
"prebuilts")
shutil.copytree(
prebuilts_sourcedir,
path.join(self.copy_dir, self.partition),
dirs_exist_ok=True)
init_path = path.join(self.copy_dir, self.partition, "etc", "init", "libndk.rc") init_path = os.path.join(self.copy_dir, self.partition, "etc", "init", "libndk.rc")
if not path.isfile(init_path): if not os.path.isfile(init_path):
makedirs(path.dirname(init_path), exist_ok=True) os.makedirs(os.path.dirname(init_path), exist_ok=True)
with open(init_path, "w") as initfile: with open(init_path, "w") as initfile:
initfile.write(self.init_rc_component) initfile.write(self.init_rc_component)

View file

@ -1,8 +1,10 @@
import gzip
import os import os
import shutil import shutil
from stuffs.general import General from stuffs.general import General
from tools.helper import run from tools.helper import run
from tools.logger import Logger from tools.logger import Logger
from tools import container
class Nodataperm(General): class Nodataperm(General):
dl_link = "https://github.com/ayasa520/hack_full_data_permission/archive/refs/heads/main.zip" dl_link = "https://github.com/ayasa520/hack_full_data_permission/archive/refs/heads/main.zip"
@ -10,11 +12,30 @@ class Nodataperm(General):
extract_to = "/tmp/nodataperm" extract_to = "/tmp/nodataperm"
act_md5 = "eafd7b0986f3edaebaf1dd89f19d49bf" act_md5 = "eafd7b0986f3edaebaf1dd89f19d49bf"
partition = "system" partition = "system"
files = [
"etc/nodataperm.sh",
"etc/init/nodataperm.rc",
"framework/services.jar"
]
def copy(self): def copy(self):
extract_path = os.path.join(self.extract_to, "hack_full_data_permission-main") extract_path = os.path.join(self.extract_to, "hack_full_data_permission-main")
if not container.use_overlayfs():
services_jar = os.path.join(self.copy_dir, self.partition, "framework", "services.jar")
gz_filename = services_jar+".gz"
with gzip.open(gz_filename,'wb') as f_gz:
with open(services_jar, "rb") as f:
f_gz.write(f.read())
os.chmod(os.path.join(extract_path, "framework", "services.jar"), 0o644) os.chmod(os.path.join(extract_path, "framework", "services.jar"), 0o644)
os.chmod(os.path.join(extract_path, "etc", "nodataperm.sh"), 0o755) os.chmod(os.path.join(extract_path, "etc", "nodataperm.sh"), 0o755)
os.chmod(os.path.join(extract_path, "etc", "init", "nodataperm.rc"), 0o755) os.chmod(os.path.join(extract_path, "etc", "init", "nodataperm.rc"), 0o755)
Logger.info("Copying widevine library files ...") Logger.info("Copying widevine library files ...")
shutil.copytree(extract_path, os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True) shutil.copytree(extract_path, os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
def extra3(self):
if not container.use_overlayfs():
services_jar = os.path.join(self.copy_dir, self.partition, "framework", "services.jar")
gz_filename = services_jar+".gz"
with gzip.GzipFile(gz_filename) as f_gz:
with open(services_jar, "wb") as f:
f.writelines(f_gz)

View file

@ -12,6 +12,10 @@ class Smartdock(General):
dl_file_name = "smartdock.zip" dl_file_name = "smartdock.zip"
act_md5 = "ad0cc5e023ac6ee97e7b013b9b0defee" act_md5 = "ad0cc5e023ac6ee97e7b013b9b0defee"
apply_props = { "qemu.hw.mainkeys" : "1" } apply_props = { "qemu.hw.mainkeys" : "1" }
files = [
"etc/permissions/permissions_cu.axel.smartdock.xml",
"priv-app/SmartDock"
]
def copy(self): def copy(self):
if not os.path.exists(os.path.join(self.copy_dir, self.partition, "priv-app", "SmartDock")): if not os.path.exists(os.path.join(self.copy_dir, self.partition, "priv-app", "SmartDock")):

View file

@ -11,6 +11,15 @@ class Widevine(General):
dl_file_name = "widevine.zip" dl_file_name = "widevine.zip"
extract_to = "/tmp/widevineunpack" extract_to = "/tmp/widevineunpack"
act_md5 = "a31f325453c5d239c21ecab8cfdbd878" act_md5 = "a31f325453c5d239c21ecab8cfdbd878"
files = [
"bin/hw/android.hardware.drm@1.3-service-lazy.widevine",
"bin/move_widevine_data.sh",
"etc/init/android.hardware.drm@1.3-service-lazy.widevine.rc",
"etc/vintf/manifest/manifest_android.hardware.drm@1.3-service.widevine.xml",
"lib/libwvhidl.so",
"lib/mediadrm",
"lib64/mediadrm"
]
def copy(self): def copy(self):
run(["chmod", "+x", self.extract_to, "-R"]) run(["chmod", "+x", self.extract_to, "-R"])

View file

@ -19,6 +19,10 @@ def get_download_dir():
os.makedirs(download_loc) os.makedirs(download_loc)
return download_loc return download_loc
# not good
def get_data_dir():
return os.path.join('/', "home", os.environ.get("SUDO_USER", os.environ["USER"]), ".local", "share", "waydroid", "data")
def run(args, ignore=""): def run(args, ignore=""):
result = subprocess.run(args=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) result = subprocess.run(args=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# print(result.stdout.decode()) # print(result.stdout.decode())