The target app crashed on launch after the root/manager-app and Settings
hooks landed. The actual bug: the pass-through branch of both
hookSettingsClass and hookPackageManager used XC_MethodReplacement and
manually called XposedBridge.invokeOriginalMethod() when a call wasn't one
we wanted to intercept. That routes through Method.invoke(), which wraps
*any* exception the real method throws in InvocationTargetException — including
completely normal ones like NameNotFoundException for a not-installed
package, or SettingNotFoundException for an unrecognized key, unrelated to
anything we hide. The target app's own root-detection code checks a list of
known manager packages and expects to catch NameNotFoundException directly;
the wrapped exception type broke that on the very first miss.
Fixed by switching both to XC_MethodHook.beforeHookedMethod, setting
param.result/param.throwable only for the keys/packages we actually want to
affect and leaving param untouched otherwise. That lets the real method run
through its normal, non-reflective path for everything else, so its
exceptions propagate correctly.
Confirmed on-device: the target app launches and stays in the foreground
with all six features enabled.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>