diff --git a/README.md b/README.md index 7324545..a70b4c8 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,16 @@ Open terminal and switch to directory where "waydroid_extras.py" is located then Then restart waydroid service with command below : sudo systemctl start waydroid-container.service + +## Install libhoudini arm translation + +This may or may not work properly and is only for testing: ( Much stable than libndk ) and works on android 11 images +Open terminal and switch to directory where "waydroid_extras.py" is located then run: + + sudo python3 waydroid_extras.py -l +Then restart waydroid service with command below : + + sudo systemctl start waydroid-container.service ## Get Android ID for device registration diff --git a/waydroid_extras.py b/waydroid_extras.py index 4e97b4a..c52336e 100644 --- a/waydroid_extras.py +++ b/waydroid_extras.py @@ -246,7 +246,7 @@ on property:ro.enable.native.bridge.exec=1 #Mark ndk files as executable print("==> Chmodding...") try: os.system("chmod +x "+extract_to+" -R") - except: print("Couldn't mark files as executable!") + except: print("==> Couldn't mark files as executable!") # Copy library file print("==> Copying library files ...") @@ -268,11 +268,12 @@ on property:ro.enable.native.bridge.exec=1 # Add entry to init.rc print("==> Adding entry to init.rc") - with open(os.path.join(sys_image_mount, "init.rc"), "r") as initfile: + init_path = os.path.join(sys_image_mount, "system", "etc", "init", "hw", "init.rc") if os.environ.get("ANDROID_VERSION", "10") == "11" else os.path.join(sys_image_mount, "init.rc") + with open(init_path, "r") as initfile: initcontent = initfile.read() if init_rc_component not in initcontent: initcontent=initcontent+init_rc_component - with open(os.path.join(sys_image_mount, "init.rc"), "w") as initfile: + with open(init_path, "w") as initfile: initfile.write(initcontent) # Unmount and exit @@ -284,6 +285,106 @@ on property:ro.enable.native.bridge.exec=1 print("==> libndk translation installed ! Restart waydroid service to apply changes !") + +def install_houdini(): + sys_image_mount = "/tmp/waydroidimage" + houdini_zip_url = "https://raw.githubusercontent.com/casualsnek/miscpackages/main/libhoudini_a11.zip" + dl_file_name = "libhoudini.zip" + extract_to = "/tmp/houdiniunpack" #All catalog files will be marked as executable! + act_md5 = "c9a80831641de8fd44ccf93a0ad8b585" + 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 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("/tmp/"+dl_file_name): + with open("/tmp/"+dl_file_name,"rb") as f: + bytes = f.read() + loc_md5 = hashlib.md5(bytes).hexdigest() + + system_img = os.path.join(get_image_dir(), "system.img") + if not os.path.isfile(system_img): + print("The system image path '{}' from waydroid config is not valid !".format(system_img)) + sys.exit(1) + print("==> Found system image: "+system_img) + + # Resize rootfs + resize_img(system_img, "6G") + + # Mount the system image + mount_image(system_img, sys_image_mount) + + # Download the file if hash mismatches or if file does not exist + while not os.path.isfile("/tmp/"+dl_file_name) or loc_md5 != act_md5: + if os.path.isfile("/tmp/"+dl_file_name): + os.remove("/tmp/"+dl_file_name) + print("==> libhoudini zip not downloaded or hash mismatches, downloading now .....") + loc_md5 = download_file(houdini_zip_url, '/tmp/'+dl_file_name) + + # Extract ndk files + print("==> Extracting archive...") + with zipfile.ZipFile("/tmp/"+dl_file_name) as z: + z.extractall(extract_to) + + # Mark libhoudini files as executable + print("==> Chmodding...") + try: os.system("chmod +x "+extract_to+" -R") + except: print("==> Couldn't mark files as executable!") + + # 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 build.prop") + with open(os.path.join(sys_image_mount, "system", "build.prop"), "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(sys_image_mount, "system", "build.prop"), "w") as propfile: + propfile.write(prop_content) + + # Add entry to init.rc + print("==> Adding entry to init.rc") + init_path = os.path.join(sys_image_mount, "system", "etc", "init", "hw", "init.rc") if os.environ.get("ANDROID_VERSION", "10") == "11" else os.path.join(sys_image_mount, "init.rc") + 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) + + # Unmount and exit + print("==> Unmounting .. ") + try: + subprocess.check_output(["umount", sys_image_mount], stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + print("==> Warning: umount failed.. {} ".format(str(e.output.decode()))) + + print("==> libhoudini translation installed ! Restart waydroid service to apply changes !") + + def install_magisk(): dl_link = "https://github.com/topjohnwu/Magisk/releases/download/v20.4/Magisk-v20.4.zip" busybox_dl_link = "https://github.com/Gnurou/busybox-android/raw/master/busybox-android" @@ -442,6 +543,9 @@ def main(): 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') args = parser.parse_args() if args.install: @@ -454,6 +558,8 @@ def main(): get_android_id() elif args.magisk: install_magisk() + elif args.houdini: + install_houdini() if __name__ == "__main__": main()