Refactor: Split into multiple small scripts

pull/64/head
Rikka 3 years ago
parent 4681bb48fe
commit df46ba8fed
No known key found for this signature in database
GPG Key ID: 27646650E3A52AAF

106
.gitignore vendored

@ -0,0 +1,106 @@
git
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
*.out
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
.idea/
# celery beat schedule file
celerybeat-schedule
workspace.xml
# SageMath parsed files
*.sage.py
.idea/workspace.xml
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/

@ -0,0 +1,58 @@
import argparse
from stuffs.android_id import Android_id
from stuffs.gapps import Gapps
from stuffs.houdini import Houdini
from stuffs.magisk import Magisk
from stuffs.ndk import Ndk
from stuffs.widevine import Widevine
import tools.helper as helper
def main():
about = """
WayDroid Helper script v0.3
Does stuff like installing Gapps, Installing NDK Translation and getting Android ID for device registration.
Use -h flag for help !
"""
helper.check_root()
parser = argparse.ArgumentParser(description=about, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-g', '--install-gapps',
dest='gapps',
help='Install OpenGapps to waydroid',
action='store_true')
parser.add_argument('-n', '--install-ndk-translation',
dest='ndk',
help='Install libndk translation for arm translation',
action='store_true')
parser.add_argument('-i', '--get-android-id', dest='getid',
help='Displays your android id for manual registration',
action='store_true')
parser.add_argument('-m', '--install-magisk', dest='magisk',
help='Attempts to install Magisk ( Bootless )',
action='store_true')
parser.add_argument('-l', '--install-libhoudini', dest='houdini',
help='Install libhoudini for arm translation',
action='store_true')
parser.add_argument('-w', '--install-windevine', dest='widevine',
help='Integrate Widevine DRM (L3)',
action='store_true')
args = parser.parse_args()
if args.getid:
Android_id().get_id()
if args.gapps:
Gapps().install()
if args.ndk and not args.houdini:
arch = helper.host()[0]
if arch == "x86" or arch == "x86_64":
Ndk().install()
if args.houdini and not args.ndk:
arch = helper.host()[0]
if arch == "x86" or arch == "x86_64":
Houdini().install()
if args.magisk:
Magisk().install()
if args.widevine:
Widevine().install()
if __name__ == "__main__":
main()

@ -0,0 +1,18 @@
import os
import sys
from tools.helper import run
from tools.logger import Logger
class Android_id:
def get_id(self):
if not os.path.isfile("/var/lib/waydroid/data/data/com.google.android.gsf/databases/gservices.db"):
Logger.error("Cannot access gservices.db, make sure gapps is installed and waydroid was started at least once after installation and make sure waydroid is running !")
sys.exit(1)
sqs = """
SELECT * FROM main WHERE name='android_id'
"""
queryout = run(["sqlite3", "/var/lib/waydroid/data/data/com.google.android.gsf/databases/gservices.db", sqs.strip()])
print(queryout.stdout.decode().replace("android_id|", "").strip())
print(" ^----- Open https://google.com/android/uncertified/?pli=1")
print(" Login with your google id then submit the form with id shown above")

@ -0,0 +1,59 @@
import os
import shutil
from stuffs.general import General
from tools.helper import host, run
from tools.logger import Logger
class Gapps(General):
partition = "system"
dl_links = {
"x86_64": ["https://master.dl.sourceforge.net/project/opengapps/x86_64/20220121/open_gapps-x86_64-10.0-pico-20220121.zip?viasf=1", "e8c9a7412f5712eea7948957a62a7d66"],
"x86": ["https://udomain.dl.sourceforge.net/project/opengapps/x86/20220122/open_gapps-x86-10.0-pico-20220122.zip", "9e39e45584b7ade4529e6be654af7b81"],
"arm64-v8a": ["https://liquidtelecom.dl.sourceforge.net/project/opengapps/arm64/20220122/open_gapps-arm64-10.0-pico-20220122.zip", "8dfa6e76aeb2d1d5aed40b058e8a852c"],
"armeabi-v7a": ["https://nav.dl.sourceforge.net/project/opengapps/arm/20220122/open_gapps-arm-10.0-pico-20220122.zip", "a48ccbd25eb0a3c5e30f5db5435f5536"]
}
arch = host()
dl_link = dl_links[arch[0]][0]
dl_file_name = "open_gapps.zip"
act_md5 = dl_links[arch[0]][1]
extract_to = "/tmp/ogapps/extract"
non_apks = [
"defaultetc-common.tar.lz",
"defaultframework-common.tar.lz",
"googlepixelconfig-common.tar.lz"
]
skip = [
"setupwizarddefault-x86_64.tar.lz",
"setupwizardtablet-x86_64.tar.lz"
]
def download(self):
Logger.info("Downloading OpenGapps now to {} .....".format(self.download_loc))
super().download()
def copy(self):
if not os.path.exists(self.extract_to):
os.makedirs(self.extract_to)
if not os.path.exists(os.path.join(self.extract_to, "appunpack")):
os.makedirs(os.path.join(self.extract_to, "appunpack"))
for lz_file in os.listdir(os.path.join(self.extract_to, "Core")):
for d in os.listdir(os.path.join(self.extract_to, "appunpack")):
shutil.rmtree(os.path.join(self.extract_to, "appunpack", d))
if lz_file not in self.skip:
if lz_file not in self.non_apks:
print(" Processing app package : "+os.path.join(self.extract_to, "Core", lz_file))
run(["tar", "--lzip", "-xvf", os.path.join(self.extract_to, "Core", lz_file), "-C", os.path.join(self.extract_to, "appunpack")])
app_name = os.listdir(os.path.join(self.extract_to, "appunpack"))[0]
xx_dpi = os.listdir(os.path.join(self.extract_to, "appunpack", app_name))[0]
app_priv = os.listdir(os.path.join(self.extract_to, "appunpack", app_name, "nodpi"))[0]
app_src_dir = os.path.join(self.extract_to, "appunpack", app_name, xx_dpi, app_priv)
for app in os.listdir(app_src_dir):
shutil.copytree(os.path.join(app_src_dir, app), os.path.join(self.copy_dir, self.partition, "priv-app", app), dirs_exist_ok=True)
else:
print(" Processing extra package : "+os.path.join(self.extract_to, "Core", lz_file))
run(["tar", "--lzip", "-xvf", os.path.join(self.extract_to, "Core", lz_file), "-C", os.path.join(self.extract_to, "appunpack")])
app_name = os.listdir(os.path.join(self.extract_to, "appunpack"))[0]
common_content_dirs = os.listdir(os.path.join(self.extract_to, "appunpack", app_name, "common"))
for ccdir in common_content_dirs:
shutil.copytree(os.path.join(self.extract_to, "appunpack", app_name, "common", ccdir), os.path.join(self.copy_dir, self.partition, ccdir), dirs_exist_ok=True)

@ -0,0 +1,132 @@
import os
import re
import zipfile
import hashlib
from tools import images
from tools.helper import download_file, get_download_dir, run
from tools.container import DBusContainerService
from tools.logger import Logger
class General:
@property
def download_loc(self):
return os.path.join(get_download_dir(), self.dl_file_name)
@property
def copy_dir(self):
if self.use_overlayfs:
return "/var/lib/waydroid/overlay"
else:
return "/tmp/waydroid"
@property
def use_dbus(self):
try:
DBusContainerService()
except:
return False
return
@property
def use_overlayfs(self):
return os.path.isdir("/var/lib/waydroid/overlay")
# return False
def download(self):
loc_md5 = ""
if os.path.isfile(self.download_loc):
with open(self.download_loc, "rb") as f:
bytes = f.read()
loc_md5 = hashlib.md5(bytes).hexdigest()
while not os.path.isfile(self.download_loc) or loc_md5 != self.act_md5:
if os.path.isfile(self.download_loc):
os.remove(self.download_loc)
Logger.warning(
"md5 mismatches, redownloading now ....")
loc_md5 = download_file(self.dl_link, self.download_loc)
def extract(self):
Logger.info("Extracting archive...")
with zipfile.ZipFile(self.download_loc) as z:
z.extractall(self.extract_to)
def add_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 not in prop_content:
prop_content = prop_content+"\n{key}={value}".format(key=key, value=self.apply_props[key])
else:
p = re.compile(r"^{key}=.*$".format(key=key), re.M)
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 mount(self):
img = os.path.join(images.get_image_dir(), self.partition+".img")
mount_point = ""
if self.partition == "system":
mount_point = os.path.join(self.copy_dir)
else:
mount_point = os.path.join(self.copy_dir, self.partition)
Logger.info("Mounting {} to {}".format(img, mount_point))
images.mount(img, mount_point)
def resize(self):
img = os.path.join(images.get_image_dir(), self.partition+".img")
img_size = int(os.path.getsize(img)/(1024*1024))
new_size = "{}M".format(img_size+500)
Logger.info("Resizing {} to {}".format(img, new_size))
images.resize(img, new_size)
def umount(self):
mount_point = ""
if self.partition == "system":
mount_point = os.path.join(self.copy_dir)
else:
mount_point = os.path.join(self.copy_dir, self.partition)
Logger.info("Umounting {}".format(mount_point))
images.umount(mount_point)
def stop(self):
if self.use_dbus:
self.session = DBusContainerService().GetSession()
if self.session:
DBusContainerService().Stop(False)
else:
run(["waydroid", "container", "stop"])
def start(self):
if self.use_dbus:
DBusContainerService().Start(self.session)
else:
run(["systemctl", "restart", "waydroid-container.service"])
def restart(self):
if DBusContainerService().GetSession():
self.stop()
self.start()
def copy(self):
pass
def install(self):
if self.use_overlayfs:
self.download()
self.extract()
self.copy()
if hasattr(self, "apply_props"):
self.add_props()
self.restart()
else:
self.stop()
self.download()
self.extract()
self.resize()
self.mount()
self.copy()
if hasattr(self, "apply_props"):
self.add_props()
self.umount()
self.start()
Logger.info("Installation finished")

@ -0,0 +1,49 @@
import os
import re
import shutil
from stuffs.general import General
from tools.helper import run
from tools.logger import Logger
class Houdini(General):
partition = "system"
dl_link = "https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/81f2a51ef539a35aead396ab7fce2adf89f46e88.zip"
act_md5 = "fbff756612b4144797fbc99eadcb6653"
dl_file_name = "libhoudini.zip"
extract_to = "/tmp/houdiniunpack"
init_rc_component = """
on early-init
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1
exec -- /system/bin/sh -c "echo ':arm_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x28::/system/bin/houdini:P' > /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm_dyn:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x03\\\\x00\\\\x28::/system/bin/houdini:P' >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm64_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x02\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\xb7::/system/bin/houdini64:P' >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm64_dyn:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x02\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x03\\\\x00\\\\xb7::/system/bin/houdini64:P' >> /proc/sys/fs/binfmt_misc/register"
"""
apply_props = {
"ro.product.cpu.abilist": "x86_64,x86,arm64-v8a,armeabi-v7a,armeabi",
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
"ro.product.cpu.abilist64": "x86_64,arm64-v8a",
"ro.dalvik.vm.native.bridge": "libhoudini.so",
"ro.enable.native.bridge.exec": "1",
"ro.dalvik.vm.isa.arm": "x86",
"ro.dalvik.vm.isa.arm64": "x86_64"
}
def download(self):
Logger.info("Downloading libhoudini to {}now .....".format(self.download_loc))
super().download()
def copy(self):
run(["chmod", "+x", self.extract_to, "-R"])
Logger.info("Copying libhoudini library files ...")
name = re.findall("([a-zA-Z0-9]+)\.zip", self.dl_link)[0]
shutil.copytree(os.path.join(self.extract_to, "vendor_intel_proprietary_houdini-" + name,
"prebuilts"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
init_path = os.path.join(self.copy_dir, self.partition, "etc", "init", "houdini.rc")
if not os.path.isfile(init_path):
os.makedirs(os.path.dirname(init_path), exist_ok=True)
with open(init_path, "w") as initfile:
initfile.write(self.init_rc_component)

@ -0,0 +1,89 @@
import gzip
import os
import shutil
import re
from stuffs.general import General
from tools.helper import download_file, host, run
from tools.logger import Logger
class Magisk(General):
partition = "system"
dl_link = "https://huskydg.github.io/magisk-files/app-release.apk"
dl_file_name = "magisk.apk"
extract_to = "/tmp/magisk_unpack"
magisk_dir = os.path.join(partition, "etc", "init", "magisk")
machine = host()
oringinal_bootanim = """
service bootanim /system/bin/bootanimation
class core animation
user graphics
group graphics audio
disabled
oneshot
ioprio rt 0
task_profiles MaxPerformance
"""
bootanim_component = """
on post-fs-data
start logd
exec u:r:su:s0 root root -- /system/etc/init/magisk/magisk{arch} --auto-selinux --setup-sbin /system/etc/init/magisk
exec u:r:su:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk "allow * magisk_file lnk_file *"
mkdir /sbin/.magisk 700
mkdir /sbin/.magisk/mirror 700
mkdir /sbin/.magisk/block 700
copy /system/etc/init/magisk/config /sbin/.magisk/config
rm /dev/.magisk_unblock
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --post-fs-data
wait /dev/.magisk_unblock 40
rm /dev/.magisk_unblock
on zygote-start
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --service
on property:sys.boot_completed=1
mkdir /data/adb/magisk 755
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --boot-complete
exec -- /system/bin/sh -c "if [ ! -e /data/data/io.github.huskydg.magisk ] ; then pm install /system/etc/init/magisk/magisk.apk ; fi"
on property:init.svc.zygote=restarting
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --zygote-restart
on property:init.svc.zygote=stopped
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --zygote-restart
""".format(arch=machine[1])
def download(self):
if os.path.isfile(self.download_loc):
os.remove(self.download_loc)
Logger.info("Downloading latest Magisk-Delta to {} now ...".format(self.download_loc))
download_file(self.dl_link, self.download_loc)
def copy(self):
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
if not os.path.exists(magisk_absolute_dir):
os.makedirs(magisk_absolute_dir, exist_ok=True)
if not os.path.exists(os.path.join(self.copy_dir, "sbin")):
os.makedirs(os.path.join(self.copy_dir, "sbin"), exist_ok=True)
Logger.info("Copying magisk libs now ...")
lib_dir = os.path.join(self.extract_to, "lib", self.machine[0])
for parent, dirnames, filenames in os.walk(lib_dir):
for filename in filenames:
o_path = os.path.join(lib_dir, filename)
filename = re.search('lib(.*)\.so', filename)
n_path = os.path.join(magisk_absolute_dir, filename.group(1))
shutil.copyfile(o_path, n_path)
run(["chmod", "+x", n_path])
shutil.copyfile(self.download_loc, os.path.join(magisk_absolute_dir,"magisk.apk") )
# Updating Magisk from Magisk manager will modify bootanim.rc,
# So it is necessary to backup the original bootanim.rc.
bootanim_path = os.path.join(self.copy_dir, self.partition, "etc", "init", "bootanim.rc")
gz_filename = os.path.join(bootanim_path)+".gz"
with gzip.open(gz_filename,'wb') as f_gz:
f_gz.write(self.oringinal_bootanim.encode('utf-8'))
with open(bootanim_path, "w") as initfile:
initfile.write(self.oringinal_bootanim+self.bootanim_component)

@ -0,0 +1,48 @@
import os
import shutil
from stuffs.general import General
from tools.helper import run
from tools.logger import Logger
class Ndk(General):
partition = "system"
dl_link = "https://www.dropbox.com/s/eaf4dj3novwiccp/libndk_translation_Module-c6077f3398172c64f55aad7aab0e55fad9110cf3.zip?dl=1"
dl_file_name = "libndktranslation.zip"
extract_to = "/tmp/libndkunpack"
act_md5 = "4456fc1002dc78e544e8d9721bb24398"
apply_props = {
"ro.product.cpu.abilist": "x86_64,x86,armeabi-v7a,armeabi,arm64-v8a",
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
"ro.product.cpu.abilist64": "x86_64,arm64-v8a",
"ro.dalvik.vm.native.bridge": "libndk_translation.so",
"ro.enable.native.bridge.exec": "1",
# "ro.ndk_translation.version": "0.2.2",
"ro.dalvik.vm.isa.arm": "x86",
"ro.dalvik.vm.isa.arm64": "x86_64"
}
init_rc_component = """
# Enable native bridge for target executables
on early-init
mount binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1
copy /system/etc/binfmt_misc/arm_exe /proc/sys/fs/binfmt_misc/register
copy /system/etc/binfmt_misc/arm_dyn /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
"""
def download(self):
Logger.info("Downloading libndk to {} now .....".format(self.download_loc))
super().download()
def copy(self):
run(["chmod", "+x", self.extract_to, "-R"])
Logger.info("Copying libndk library files ...")
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)
init_path = os.path.join(self.copy_dir, self.partition, "etc", "init", "libndk.rc")
if not os.path.isfile(init_path):
os.makedirs(os.path.dirname(init_path), exist_ok=True)
with open(init_path, "w") as initfile:
initfile.write(self.init_rc_component)

@ -0,0 +1,23 @@
import os
import shutil
from stuffs.general import General
from tools.helper import run
from tools.logger import Logger
class Widevine(General):
partition = "vendor"
dl_link = "https://codeload.github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/zip/94c9ee172e3d78fecc81863f50a59e3646f7a2bd"
dl_file_name = "widevine.zip"
extract_to = "/tmp/widevineunpack"
act_md5 = "a31f325453c5d239c21ecab8cfdbd878"
def download(self):
Logger.info("Downloading widevine to {} now .....".format(self.download_loc))
super().download()
def copy(self):
run(["chmod", "+x", self.extract_to, "-R"])
Logger.info("Copying widevine library files ...")
shutil.copytree(os.path.join(self.extract_to, "vendor_google_proprietary_widevine-prebuilt-94c9ee172e3d78fecc81863f50a59e3646f7a2bd",
"prebuilts"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)

@ -0,0 +1,7 @@
import dbus
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)

@ -0,0 +1,74 @@
import os
import platform
import subprocess
import sys
import requests
from tools.logger import Logger
from tqdm import tqdm
import hashlib
def get_download_dir():
download_loc = ""
if os.environ.get("XDG_CACHE_HOME", None) is None:
download_loc = os.path.join('/', "home", os.environ.get("SUDO_USER", os.environ["USER"]), ".cache", "waydroid-script", "downloads")
else:
download_loc = os.path.join(os.environ["XDG_CACHE_HOME"], "waydroid-script", "downloads")
if not os.path.exists(download_loc):
os.makedirs(download_loc)
return download_loc
def run(args):
result = subprocess.run(args=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# print(result.stdout.decode())
if result.stderr:
Logger.error(result.stderr.decode("utf-8"))
raise subprocess.CalledProcessError(
returncode = result.returncode,
cmd = result.args,
stderr = result.stderr
)
return result
def download_file(url, f_name):
md5 = ""
response = requests.get(url, stream=True)
total_size_in_bytes = int(response.headers.get('content-length', 0))
block_size = 1024 # 1 Kibibyte
progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)
with open(f_name, 'wb') as file:
for data in response.iter_content(block_size):
progress_bar.update(len(data))
file.write(data)
progress_bar.close()
with open(f_name, "rb") as f:
bytes = f.read()
md5 = hashlib.md5(bytes).hexdigest()
if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes:
raise ValueError("Something went wrong while downloading")
return md5
def host():
machine = platform.machine()
mapping = {
"i686": ("x86", 32),
"x86_64": ("x86_64", 64),
"aarch64": ("arm64-v8a", 64),
"armv7l": ("armeabi-v7a", 32),
"armv8l": ("armeabi-v7a", 32)
}
if machine in mapping:
if mapping[machine] == "x86_64":
with open("/proc/cpuinfo") as f:
if "sse4_2" not in f.read():
Logger.warning("x86_64 CPU does not support SSE4.2, falling back to x86...")
return ("x86", 32)
return mapping[machine]
raise ValueError("platform.machine '" + machine + "'"
" architecture is not supported")
def check_root():
if os.geteuid() != 0:
Logger.error("This script must be run as root. Aborting.")
sys.exit(1)

@ -0,0 +1,47 @@
import configparser
import os
import subprocess
import sys
from tools.helper import run
from tools.logger import Logger
def mount(image, mount_point):
umount(mount_point, False)
if not os.path.exists(mount_point):
os.makedirs(mount_point)
run(["mount", "-o", "rw", image, mount_point])
def umount(mount_point, exists=True):
if not os.path.exists(mount_point):
if not exists:
return
Logger.error("{} does not exist!".format(mount_point))
raise FileNotFoundError()
if not run(["mountpoint", mount_point]).returncode:
run(["umount", mount_point])
else:
Logger.warning("{} is not a mount point".format(
mount_point))
def resize(img_file, size):
try:
run(["e2fsck", "-y", "-f", img_file])
except subprocess.CalledProcessError:
pass
try:
run(["resize2fs", img_file, size])
except subprocess.CalledProcessError:
pass
def get_image_dir():
# Read waydroid config to get image location
cfg = configparser.ConfigParser()
cfg_file = os.environ.get("WAYDROID_CONFIG", "/var/lib/waydroid/waydroid.cfg")
if not os.path.isfile(cfg_file):
Logger.error("Cannot locate waydroid config file, reinit wayland and try again!")
sys.exit(1)
cfg.read(cfg_file)
if "waydroid" not in cfg:
Logger.error("ERROR: Required entry in config was not found, Cannot continue!") #magisk
sys.exit(1)
return cfg["waydroid"]["images_path"]

@ -0,0 +1,13 @@
class Logger:
@staticmethod
def error(str):
print("\033[31m"+"ERROR: "+str+"\033[0m")
@staticmethod
def info(str):
print("\033[32m"+"INFO: "+"\033[0m"+str)
@staticmethod
def warning(str):
print("\033[33m"+"WARN: "+str+"\033[0m")

@ -1,556 +0,0 @@
import sys
import os
import hashlib
import shutil
import zipfile
import subprocess
import argparse
import platform
from tqdm import tqdm
import requests
import re
import gzip
import dbus
import subprocess
download_loc = ""
if os.environ.get("XDG_CACHE_HOME", None) is None:
download_loc = os.path.join('/', "home", os.environ.get("SUDO_USER", os.environ["USER"]), ".cache", "waydroid_script", "downloads")
else:
download_loc = os.path.join(os.environ["XDG_CACHE_HOME"], "waydroid_script", "downloads")
print(download_loc)
if not os.path.exists(download_loc):
os.makedirs(download_loc)
def host():
machine = platform.machine()
mapping = {
"i686": ("x86", 32),
"x86_64": ("x86_64", 64),
"aarch64": ("arm64-v8a", 64),
"armv7l": ("armeabi-v7a", 32),
"armv8l": ("armeabi-v7a", 32)
}
if machine in mapping:
if mapping[machine] == "x86_64":
with open("/proc/cpuinfo") as f:
if "sse4_2" not in f.read():
print("x86_64 CPU does not support SSE4.2, falling back to x86...")
return ("x86", 32)
return mapping[machine]
raise ValueError("platform.machine '" + machine + "'"
" architecture is not supported")
def download_file(url, f_name):
md5 = ""
response = requests.get(url, stream=True)
total_size_in_bytes = int(response.headers.get('content-length', 0))
block_size = 1024 # 1 Kibibyte
progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)
with open(f_name, 'wb') as file:
for data in response.iter_content(block_size):
progress_bar.update(len(data))
file.write(data)
progress_bar.close()
with open(f_name, "rb") as f:
bytes = f.read()
md5 = hashlib.md5(bytes).hexdigest()
if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes:
print("==> Something went wrong while downloading")
sys.exit(1)
return md5
def check_root():
if os.geteuid() != 0:
print("This script must be run as root. Aborting.")
sys.exit(1)
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)
def restart():
waydroid_session = DBusContainerService().GetSession()
if DBusContainerService().GetSession():
DBusContainerService().Stop()
DBusContainerService().Start(waydroid_session)
def run(args):
result = subprocess.run(args=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.stderr:
print(result.stderr.decode("utf-8"))
raise subprocess.CalledProcessError(
returncode = result.returncode,
cmd = result.args,
stderr = result.stderr
)
return result
def install_gapps():
dl_links = {
"x86_64": ["https://master.dl.sourceforge.net/project/opengapps/x86_64/20220121/open_gapps-x86_64-10.0-pico-20220121.zip?viasf=1", "e8c9a7412f5712eea7948957a62a7d66"],
"x86": ["https://udomain.dl.sourceforge.net/project/opengapps/x86/20220122/open_gapps-x86-10.0-pico-20220122.zip", "9e39e45584b7ade4529e6be654af7b81"],
"aarch64": ["https://liquidtelecom.dl.sourceforge.net/project/opengapps/arm64/20220122/open_gapps-arm64-10.0-pico-20220122.zip", "8dfa6e76aeb2d1d5aed40b058e8a852c"],
"arm": ["https://nav.dl.sourceforge.net/project/opengapps/arm/20220122/open_gapps-arm-10.0-pico-20220122.zip", "a48ccbd25eb0a3c5e30f5db5435f5536"]
}
if platform.machine() not in dl_links.keys():
print("==> Unsupported architecture '{}' .. ".format(platform.machine()))
sys.exit(1)
google_apps_dl_link = dl_links[platform.machine()][0]
dl_file_name = os.path.join(download_loc, "open_gapps.zip")
act_md5 = dl_links[platform.machine()][1]
loc_md5 = ""
sys_image_mount = "/var/lib/waydroid/overlay"
extract_to = "/tmp/ogapps/extract"
non_apks = [
"defaultetc-common.tar.lz",
"defaultframework-common.tar.lz",
"googlepixelconfig-common.tar.lz"
]
skip = [
"setupwizarddefault-x86_64.tar.lz",
"setupwizardtablet-x86_64.tar.lz"
]
if not os.path.exists(extract_to):
os.makedirs(extract_to)
if not os.path.exists(os.path.join(extract_to, "appunpack")):
os.makedirs(os.path.join(extract_to, "appunpack"))
if os.path.isfile(dl_file_name):
with open(dl_file_name,"rb") as f:
bytes = f.read()
loc_md5 = hashlib.md5(bytes).hexdigest()
print("==> Excepted hash: {} | File hash: {}".format(act_md5, loc_md5))
# Download the file if hash mismatches or if file does not exist
while not os.path.isfile(dl_file_name) or loc_md5 != act_md5:
if os.path.isfile(dl_file_name):
os.remove(dl_file_name)
print("==> OpenGapps zip not downloaded or hash mismatches, downloading now .....")
loc_md5 = download_file(google_apps_dl_link, dl_file_name)
# Extract opengapps
print("==> Extracting opengapps...")
with zipfile.ZipFile(dl_file_name) as z:
z.extractall(extract_to)
# Now copy the files
for lz_file in os.listdir(os.path.join(extract_to, "Core")):
for d in os.listdir(os.path.join(extract_to, "appunpack")):
shutil.rmtree(os.path.join(extract_to, "appunpack", d))
if lz_file not in skip:
if lz_file not in non_apks:
print("==> Processing app package : "+os.path.join(extract_to, "Core", lz_file))
run(["tar", "--lzip", "-xvf", os.path.join(extract_to, "Core", lz_file), "-C", os.path.join(extract_to, "appunpack")])
app_name = os.listdir(os.path.join(extract_to, "appunpack"))[0]
xx_dpi = os.listdir(os.path.join(extract_to, "appunpack", app_name))[0]
app_priv = os.listdir(os.path.join(extract_to, "appunpack", app_name, "nodpi"))[0]
app_src_dir = os.path.join(extract_to, "appunpack", app_name, xx_dpi, app_priv)
for app in os.listdir(app_src_dir):
shutil.copytree(os.path.join(app_src_dir, app), os.path.join(sys_image_mount, "system", "priv-app", app), dirs_exist_ok=True)
else:
print("==> Processing extra package : "+os.path.join(extract_to, "Core", lz_file))
run(["tar", "--lzip", "-xvf", os.path.join(extract_to, "Core", lz_file), "-C", os.path.join(extract_to, "appunpack")])
app_name = os.listdir(os.path.join(extract_to, "appunpack"))[0]
common_content_dirs = os.listdir(os.path.join(extract_to, "appunpack", app_name, "common"))
for ccdir in common_content_dirs:
shutil.copytree(os.path.join(extract_to, "appunpack", app_name, "common", ccdir), os.path.join(sys_image_mount, "system", ccdir), dirs_exist_ok=True)
print("==> OpenGapps installation complete try re init /restarting waydroid")
print("==> Please note, google apps wont be usable without device registration !, Use --get-android-id for registration instructions")
restart()
def get_android_id():
try:
if not os.path.isfile("/var/lib/waydroid/data/data/com.google.android.gsf/databases/gservices.db"):
print("Cannot access gservices.db, make sure gapps is installed and waydroid was started at least once after installation and make sure waydroid is running !")
sys.exit(1)
sqs = """
SELECT * FROM main WHERE name='android_id'
"""
queryout = run(["sqlite3", "/var/lib/waydroid/data/data/com.google.android.gsf/databases/gservices.db", sqs.strip()])
print(queryout.stdout.decode().replace("android_id|", "").strip())
print(" ^----- Open https://google.com/android/uncertified/?pli=1")
print(" Login with your google id then submit the form with id shown above")
except subprocess.CalledProcessError as e:
print("==> Error getting id... '{}' ".format(str(e.output.decode())))
def install_ndk():
# sys_image_mount = "/tmp/waydroidimage"
sys_image_mount = "/var/lib/waydroid/overlay"
prop_file = "/var/lib/waydroid/waydroid_base.prop"
ndk_zip_url = "https://www.dropbox.com/s/eaf4dj3novwiccp/libndk_translation_Module-c6077f3398172c64f55aad7aab0e55fad9110cf3.zip?dl=1"
dl_file_name = os.path.join(download_loc, "libndktranslation.zip")
extract_to = "/tmp/libndkunpack" #All catalog files will be marked as executable!
act_md5 = "4456fc1002dc78e544e8d9721bb24398"
loc_md5 = ""
apply_props = {
"ro.product.cpu.abilist": "x86_64,x86,armeabi-v7a,armeabi,arm64-v8a",
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
"ro.product.cpu.abilist64": "x86_64,arm64-v8a",
"ro.dalvik.vm.native.bridge": "libndk_translation.so",
"ro.enable.native.bridge.exec": "1",
# "ro.ndk_translation.version": "0.2.2",
"ro.dalvik.vm.isa.arm": "x86",
"ro.dalvik.vm.isa.arm64": "x86_64"
}
init_rc_component = """
on early-init
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1
exec -- /system/bin/sh -c "cat /system/etc/binfmt_misc/arm_exe > /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "cat /system/etc/binfmt_misc/arm_dyn >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "cat /system/etc/binfmt_misc/arm64_exe >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "cat /system/etc/binfmt_misc/arm64_dyn >> /proc/sys/fs/binfmt_misc/register"
"""
if os.path.isfile(dl_file_name):
with open(dl_file_name,"rb") as f:
bytes = f.read()
loc_md5 = hashlib.md5(bytes).hexdigest()
# Download the file if hash mismatches or if file does not exist
while not os.path.isfile(dl_file_name) or loc_md5 != act_md5:
if os.path.isfile(dl_file_name):
os.remove(dl_file_name)
print("==> NDK Translation zip not downloaded or hash mismatches, downloading now .....")
loc_md5 = download_file(ndk_zip_url, dl_file_name)
# Extract ndk files
print("==> Extracting archive...")
with zipfile.ZipFile(dl_file_name) as z:
z.extractall(extract_to)
#Mark ndk files as executable
print("==> Chmodding...")
run(["chmod", "+x", extract_to, "-R"])
# Copy library file
print("==> Copying library files ...")
shutil.copytree(os.path.join(extract_to, "libndk_translation_Module-c6077f3398172c64f55aad7aab0e55fad9110cf3", "system"), os.path.join(sys_image_mount, "system"), dirs_exist_ok=True)
# Add entries to build.prop
print("==> Adding arch in", prop_file)
with open(os.path.join(prop_file), "r") as propfile:
prop_content = propfile.read()
for key in apply_props:
if key not in prop_content:
prop_content = prop_content+"\n{key}={value}".format(key=key, value=apply_props[key])
else:
p = re.compile(r"^{key}=.*$".format(key=key), re.M)
prop_content = re.sub(p, "{key}={value}".format(key=key, value=apply_props[key]), prop_content)
with open(os.path.join(prop_file), "w") as propfile:
propfile.write(prop_content)
# Add entry to init.rc
print("==> Adding entry to init.rc")
# Check if init.rc is located in Android 11's path
init_path = os.path.join(sys_image_mount, "system", "etc", "init", "houdini.rc")
if not os.path.isfile(init_path):
os.makedirs(os.path.dirname(init_path), exist_ok=True)
f = open(init_path, "x")
with open(init_path, "r") as initfile:
initcontent = initfile.read()
if init_rc_component not in initcontent:
initcontent=initcontent+init_rc_component
with open(init_path, "w") as initfile:
initfile.write(initcontent)
print("==> libndk translation installed ! Restarting waydroid service to apply changes !")
restart()
def install_houdini():
sys_image_mount = "/var/lib/waydroid/overlay"
prop_file = "/var/lib/waydroid/waydroid_base.prop"
houdini_zip_url = "https://www.dropbox.com/s/v7g0fluc7e8tod8/libhoudini.zip?dl=1"
dl_file_name = os.path.join(download_loc, "libhoudini.zip")
extract_to = "/tmp/houdiniunpack" #All catalog files will be marked as executable!
act_md5 = "838097117cec7762e958d7cbc209415e"
loc_md5 = ""
apply_props = {
"ro.product.cpu.abilist": "x86_64,x86,arm64-v8a,armeabi-v7a,armeabi",
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
"ro.product.cpu.abilist64": "x86_64,arm64-v8a",
"ro.dalvik.vm.native.bridge": "libhoudini.so",
"ro.enable.native.bridge.exec": "1",
"ro.dalvik.vm.isa.arm": "x86",
"ro.dalvik.vm.isa.arm64": "x86_64"
}
init_rc_component = """
on early-init
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1
exec -- /system/bin/sh -c "echo ':arm_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x28::/system/bin/houdini:P' > /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm_dyn:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x03\\\\x00\\\\x28::/system/bin/houdini:P' >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm64_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x02\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\xb7::/system/bin/houdini64:P' >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm64_dyn:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x02\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x03\\\\x00\\\\xb7::/system/bin/houdini64:P' >> /proc/sys/fs/binfmt_misc/register"
"""
if os.path.isfile(dl_file_name):
with open(dl_file_name,"rb") as f:
bytes = f.read()
loc_md5 = hashlib.md5(bytes).hexdigest()
# Download the file if hash mismatches or if file does not exist
while not os.path.isfile(dl_file_name) or loc_md5 != act_md5:
if os.path.isfile(dl_file_name):
os.remove(dl_file_name)
print("==> libhoudini zip not downloaded or hash mismatches, downloading now .....")
loc_md5 = download_file(houdini_zip_url, dl_file_name)
# Extract ndk files
print("==> Extracting archive...")
with zipfile.ZipFile(dl_file_name) as z:
z.extractall(extract_to)
# Mark libhoudini files as executable
print("==> Chmodding...")
run(["chmod", "+x", extract_to, "-R"])
# Copy library file
print("==> Copying library files ...")
shutil.copytree(os.path.join(extract_to, "system"), os.path.join(sys_image_mount, "system"), dirs_exist_ok=True)
# Add entries to build.prop
print("==> Adding arch in", prop_file)
with open(os.path.join(prop_file), "r") as propfile:
prop_content = propfile.read()
for key in apply_props:
if key not in prop_content:
prop_content = prop_content+"\n{key}={value}".format(key=key, value=apply_props[key])
else:
p = re.compile(r"^{key}=.*$".format(key=key), re.M)
prop_content = re.sub(p, "{key}={value}".format(key=key, value=apply_props[key]), prop_content)
with open(os.path.join(prop_file), "w") as propfile:
propfile.write(prop_content)
# Add entry to init.rc
print("==> Adding entry to init.rc")
# Check if init.rc is located in Android 11's path
init_path = os.path.join(sys_image_mount, "system", "etc", "init", "houdini.rc")
if not os.path.isfile(init_path):
os.makedirs(os.path.dirname(init_path), exist_ok=True)
f = open(init_path, "x")
with open(init_path, "r") as initfile:
initcontent = initfile.read()
if init_rc_component not in initcontent:
initcontent=initcontent+init_rc_component
with open(init_path, "w") as initfile:
initfile.write(initcontent)
print("==> libhoudini translation installed ! Restarting waydroid container to apply changes !")
restart()
def install_magisk():
dl_link = "https://huskydg.github.io/magisk-files/app-release.apk"
dl_file_name = os.path.join(download_loc, "magisk.apk")
extract_to = "/tmp/magisk_unpack"
# sys_overlay_dir = "/var/lib/waydroid/overlay_rw/system"
sys_overlay_dir = "/var/lib/waydroid/overlay"
merge_dir = "/var/lib/waydroid/rootfs"
magisk_dir = os.path.join(sys_overlay_dir, "system", "etc", "init", "magisk")
sys_overlay_rw = "/var/lib/waydroid/overlay_rw"
machine = host()
init_rc_component = """
on post-fs-data
start logd
exec u:r:su:s0 root root -- /system/etc/init/magisk/magisk{arch} --auto-selinux --setup-sbin /system/etc/init/magisk
exec u:r:su:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk "allow * magisk_file lnk_file *"
mkdir /sbin/.magisk 700
mkdir /sbin/.magisk/mirror 700
mkdir /sbin/.magisk/block 700
copy /system/etc/init/magisk/config /sbin/.magisk/config
rm /dev/.magisk_unblock
start 7zKkuZ1ZhD
wait /dev/.magisk_unblock 40
rm /dev/.magisk_unblock
service 7zKkuZ1ZhD /sbin/magisk --auto-selinux --post-fs-data
user root
seclabel u:r:su:s0
oneshot
service wHgGlkRCtMoIQw /sbin/magisk --auto-selinux --service
class late_start
user root
seclabel u:r:su:s0
oneshot
on property:sys.boot_completed=1
mkdir /data/adb/magisk 755
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --boot-complete
exec -- /system/bin/sh -c "if [ ! -e /data/data/io.github.huskydg.magisk ] ; then pm install /system/etc/init/magisk/magisk.apk ; fi"
on property:init.svc.zygote=restarting
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --zygote-restart
on property:init.svc.zygote=stopped
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --zygote-restart
""".format(arch=machine[1])
if not DBusContainerService().GetSession():
print("Please make sure waydroid container is running!")
sys.exit(1)
# Clear overlay_rw
print("==> Deleting residual files...")
old_bootanim_rc = os.path.join(sys_overlay_rw, "system","system", "etc", "init", "bootanim.rc")
old_bootanim_rc_gz = os.path.join(sys_overlay_rw, "system","system", "etc", "init", "bootanim.rc.gz")
old_magisk = os.path.join(sys_overlay_rw, "system","system", "etc", "init", "magisk")
if os.path.exists(old_bootanim_rc):
os.remove(old_bootanim_rc)
if os.path.exists(old_bootanim_rc_gz):
os.remove(old_bootanim_rc_gz)
if os.path.exists(old_magisk):
if os.path.isdir(old_magisk):
shutil.rmtree(old_magisk)
else:
os.remove(old_magisk)
# Download magisk
if os.path.isfile(dl_file_name):
os.remove(dl_file_name)
print("==> Downloading latest Magisk-Delta now .....")
download_file(dl_link, dl_file_name)
# Extract magisk files
print("==> Extracting archive...")
with zipfile.ZipFile(dl_file_name) as z:
z.extractall(extract_to)
if not os.path.exists(magisk_dir):
os.makedirs(magisk_dir, exist_ok=True)
if not os.path.exists(os.path.join(sys_overlay_dir, "sbin")):
os.makedirs(os.path.join(sys_overlay_dir, "sbin"), exist_ok=True)
# Now setup and install magisk binary and app
print("==> Installing magisk now ...")
lib_dir = os.path.join(extract_to, "lib", machine[0])
for parent, dirnames, filenames in os.walk(lib_dir):
for filename in filenames:
o_path = os.path.join(lib_dir, filename)
filename = re.search('lib(.*)\.so', filename)
n_path = os.path.join(magisk_dir, filename.group(1))
shutil.copyfile(o_path, n_path)
run(["chmod", "+x", n_path])
shutil.copyfile(dl_file_name, os.path.join(magisk_dir,"magisk.apk") )
# Updating Magisk from Magisk manager will modify bootanim.rc,
# So it is necessary to backup the original bootanim.rc.
print("==> Adding entry to bootanim.rc")
bootanim = os.path.join(sys_overlay_dir, "system", "etc", "init", "bootanim.rc")
original_bootanim = os.path.join(merge_dir, "system", "etc", "init", "bootanim.rc")
if not os.path.isfile(bootanim):
os.makedirs(os.path.dirname(bootanim), exist_ok=True)
gz_filename = bootanim+".gz"
with open(original_bootanim,'rb') as f_ungz:
with gzip.open(gz_filename,'wb') as f_gz:
f_gz.writelines(f_ungz)
with open(original_bootanim, "r") as initfile:
initcontent = initfile.read()
if init_rc_component not in initcontent:
initcontent=initcontent+init_rc_component
with open(bootanim, "w") as initfile:
initfile.write(initcontent)
print("==> Magisk was installed ! Restarting waydroid container to apply changes !")
restart()
def install_widevine():
vendor_image_mount = "/var/lib/waydroid/overlay/vendor"
widevine_zip_url = "https://codeload.github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/zip/94c9ee172e3d78fecc81863f50a59e3646f7a2bd"
dl_file_name = os.path.join(download_loc, "widevine.zip")
extract_to = "/tmp/widevineunpack" #All catalog files will be marked as executable!
act_md5 = "a31f325453c5d239c21ecab8cfdbd878"
loc_md5 = ""
if os.path.isfile(dl_file_name):
with open(dl_file_name,"rb") as f:
bytes = f.read()
loc_md5 = hashlib.md5(bytes).hexdigest()
# Download the file if hash mismatches or if file does not exist
while not os.path.isfile(dl_file_name) or loc_md5 != act_md5:
if os.path.isfile(dl_file_name):
os.remove(dl_file_name)
print("==> windevine zip not downloaded or hash mismatches, downloading now .....")
loc_md5 = download_file(widevine_zip_url, dl_file_name)
# Extract widevine files
print("==> Extracting archive...")
with zipfile.ZipFile(dl_file_name) as z:
z.extractall(extract_to)
#Mark widevine files as executable
print("==> Chmodding...")
run(["chmod", "+x", extract_to, "-R"])
# Copy library file
print("==> Copying library files ...")
shutil.copytree(os.path.join(extract_to, "vendor_google_proprietary_widevine-prebuilt-94c9ee172e3d78fecc81863f50a59e3646f7a2bd",
"prebuilts"), vendor_image_mount, dirs_exist_ok=True)
print("==> Widevine installed ! Restarting waydroid container to apply changes !")
restart()
def main():
about = """
WayDroid Helper script v0.3
Does stuff like installing Gapps, Installing NDK Translation and getting Android ID for device registration.
Use -h flag for help !
"""
check_root()
parser = argparse.ArgumentParser(description=about, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-g', '--install-gapps',
dest='install',
help='Install OpenGapps to waydroid',
action='store_true')
parser.add_argument('-n', '--install-ndk-translation',
dest='installndk',
help='Install experimental libndk translation files',
action='store_true')
parser.add_argument('-i', '--get-android-id', dest='getid',
help='Displays your android id for manual registration',
action='store_true')
parser.add_argument('-m', '--install-magisk', dest='magisk',
help='Attempts to install Magisk ( Bootless )',
action='store_true')
parser.add_argument('-l', '--install-libhoudini', dest='houdini',
help='Install libhoudini for arm translation',
action='store_true')
parser.add_argument('-w', '--install-windevine', dest='widevine',
help='Integrate Widevine DRM (L3)',
action='store_true')
args = parser.parse_args()
if args.install:
install_gapps()
elif args.installndk:
install_ndk()
elif args.getid:
get_android_id()
elif args.magisk:
install_magisk()
elif args.houdini:
install_houdini()
elif args.widevine:
install_widevine()
if __name__ == "__main__":
main()
Loading…
Cancel
Save