"""Small helpers around the SDK's Xposed hooking and Java threading.""" from hook_utils import find_class def hook_all(plugin, class_name, method_name, hook): """Hooks every overload of `class_name.method_name`; returns the unhook handles.""" clazz = find_class(class_name) if clazz is None: plugin.log(f"class not found: {class_name}") return [] try: unhooks = plugin.hook_all_methods(clazz, method_name, hook) except Exception as exc: plugin.log(f"failed to hook {class_name}.{method_name}: {exc}") return [] unhooks = list(unhooks or []) if not unhooks: plugin.log(f"no overloads hooked for {class_name}.{method_name}") return unhooks def unhook_all(plugin, handles): for handle in handles: try: plugin.unhook_method(handle) except Exception: pass del handles[:] def field(obj, name, default=None): """A (possibly private) field of a Java object.""" value = getattr(obj, name, None) if value is not None: return value try: from hook_utils import get_private_field value = get_private_field(obj, name) except Exception: value = None return default if value is None else value def on_ui(plugin, fn, delay_ms=0): """Runs `fn` on the UI thread; exceptions are logged, not lost.""" from android_utils import run_on_ui_thread def run(): try: fn() except Exception as exc: plugin.log(f"ui task failed: {exc}") run_on_ui_thread(run, delay_ms)