diff --git a/main.py b/main.py index 35bc1fc..2e14cf6 100755 --- a/main.py +++ b/main.py @@ -18,6 +18,7 @@ from stuff.nodataperm import Nodataperm from stuff.smartdock import Smartdock from stuff.widevine import Widevine from stuff.fdroidpriv import FDroidPriv +from stuff.tflitefix import TfliteFix import tools.helper as helper from tools import container from tools import images @@ -144,6 +145,8 @@ def remove_app(args): remove_list.append(Nodataperm(args.android_version)) if "hidestatusbar" in app: remove_list.append(HideStatusBar()) + if "tflitefix" in app: + remove_list.append(TfliteFix()) if not container.use_overlayfs(): copy_dir = "/tmp/waydroid" @@ -169,6 +172,8 @@ def hack_option(args): hack_list.append(Nodataperm()) if "hidestatusbar" in options: hack_list.append(HideStatusBar()) + if "tflitefix" in options: + hack_list.append(TfliteFix()) if not container.use_overlayfs(): copy_dir = "/tmp/waydroid" @@ -204,7 +209,7 @@ def interact(): args = argparse.Namespace() android_version = inquirer.select( message="Select Android version", - instruction="(\u2191\u2193 Select Item)", + instruction="(↑↓ Select Item)", choices=[ Choice(name="Android 11", value="11"), Choice(name="Android 13", value="13"), @@ -230,7 +235,7 @@ def interact(): exit() install_choices = ["gapps", "microg", "libndk", "libhoudini", "magisk", "smartdock", "fdroidpriv", "widevine",] - hack_choices = [] + hack_choices = ["tflitefix"] if android_version=="11": hack_choices.extend(["nodataperm", "hidestatusbar"]) @@ -297,7 +302,7 @@ def main(): install_choices = ["gapps", "microg", "libndk", "libhoudini", "magisk", "mitm", "smartdock", "widevine"] - hack_choices = ["nodataperm", "hidestatusbar"] + hack_choices = ["nodataperm", "hidestatusbar", "tflitefix"] micrg_variants = ["Standard", "NoGoolag", "UNLP", "Minimal", "MinimalIAP"] remove_choices = install_choices diff --git a/stuff/tflitefix.py b/stuff/tflitefix.py new file mode 100644 index 0000000..e6ad5c8 --- /dev/null +++ b/stuff/tflitefix.py @@ -0,0 +1,78 @@ +import glob +import os +import shutil +from stuff.general import General +from tools.logger import Logger + + +class TfliteFix(General): + id = "tflitefix" + partition = "system" + TARGET_OFFSET = 0x2E9204 + PATCH_BYTES = b"\xc0\x03\x5f\xd6" # ret in AArch64 little-endian + + def __init__(self, android_version="13") -> None: + super().__init__() + + def download(self): + pass + + @property + def skip_extract(self): + return True + + def copy(self): + pass + + def extra1(self): + """Applies binary patch to libtensorflowlite.so in installed apps""" + search_paths = [ + os.path.expanduser("~/.local/share/waydroid/data/app/~~*==/*/lib/arm64/libtensorflowlite.so"), + "/var/lib/waydroid/data/app/~~*==/*/lib/arm64/libtensorflowlite.so", + ] + found = [] + for p in search_paths: + found.extend(glob.glob(p)) + + if not found: + Logger.warning("No installed apps with libtensorflowlite.so found in Waydroid data.") + return + + for lib_path in found: + try: + with open(lib_path, "rb") as f: + data = bytearray(f.read()) + + if len(data) > self.TARGET_OFFSET + 4: + if bytes(data[self.TARGET_OFFSET:self.TARGET_OFFSET+4]) == self.PATCH_BYTES: + Logger.info(f"Patch already applied to {lib_path}") + continue + + backup = lib_path + ".orig" + if not os.path.exists(backup): + shutil.copy2(lib_path, backup) + + data[self.TARGET_OFFSET:self.TARGET_OFFSET+4] = self.PATCH_BYTES + with open(lib_path, "wb") as f: + f.write(data) + os.chmod(lib_path, 0o755) + Logger.info(f"Successfully patched {lib_path}") + except Exception as e: + Logger.error(f"Failed to patch {lib_path}: {e}") + + def extra2(self): + """Restores original libtensorflowlite.so from backup""" + search_paths = [ + os.path.expanduser("~/.local/share/waydroid/data/app/~~*==/*/lib/arm64/libtensorflowlite.so.orig"), + "/var/lib/waydroid/data/app/~~*==/*/lib/arm64/libtensorflowlite.so.orig", + ] + for p in search_paths: + for orig in glob.glob(p): + target = orig[:-5] + try: + shutil.copy2(orig, target) + os.remove(orig) + os.chmod(target, 0o755) + Logger.info(f"Restored {target}") + except Exception as e: + Logger.error(f"Failed to restore {target}: {e}")