--- /dev/null
+import java.lang.reflect.Method;\r
+\r
+import de.robv.android.xposed.IXposedHookCmdInit;\r
+import de.robv.android.xposed.XC_MethodHook;\r
+import de.robv.android.xposed.XposedBridge;\r
+import de.robv.android.xposed.XposedHelpers;\r
+import de.robv.android.xposed.callbacks.XC_LoadPackage;\r
+\r
+public class Mypackage implements IXposedHookCmdInit\r
+{\r
+ @Override\r
+ public void initCmdApp(StartupParam startupParam) throws Throwable {\r
+ if (!startupParam.startClassName.equals("com.android.commands.pm.Pm")) {\r
+ return;\r
+ }\r
+ //XposedBridge.log("startup:" + startupParam.startClassName);\r
+\r
+ /*\r
+ Final Fantasy 3 has a native library lib__57d5__.so that tries to clear the data\r
+ for all apk files in /data/app/. We do not know why.\r
+\r
+ It fails to do this for root-owned packages like this xposed module.\r
+ See\r
+ https://forum.xda-developers.com/xposed/framework-xposed-rom-modding-modifying-t1574401/page170#1700\r
+\r
+ We simply prevent it from doing that.\r
+\r
+ https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-4.1.2_r1/core/java/android/app/ActivityManagerNative.java#2880\r
+\r
+ public boolean clearApplicationUserData(\r
+ String packageName, IPackageDataObserver observer, final int userId\r
+ )\r
+ */\r
+ XposedHelpers.findAndHookMethod(\r
+ "android.app.ActivityManagerProxy",\r
+ null,\r
+ "clearApplicationUserData",\r
+ String.class,\r
+ "android.content.pm.IPackageDataObserver",\r
+ int.class,\r
+ new XC_MethodHook() {\r
+ @Override\r
+ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {\r
+ String packageName = (String) param.args[0];\r
+ XposedBridge.log("clearApplicationUserData: " + packageName);\r
+ if (!packageName.equals("mypackage")) {\r
+ return;\r
+ }\r
+\r
+ param.setResult(true);\r
+\r
+ //we do not have direct access to IPackageDataObserver, so we have to dance\r
+ Object observer = param.args[1];\r
+ if(observer != null) {\r
+ Class<?> iPackageDataObserverClass = Class.forName("android.content.pm.IPackageDataObserver");\r
+ Class<?>[] paramTypes = {String.class, boolean.class};\r
+ Method onRemoveCompletedMethod = iPackageDataObserverClass.getMethod("onRemoveCompleted", paramTypes);\r
+ Object[] params = {packageName, true};\r
+ try {\r
+ onRemoveCompletedMethod.invoke(observer, params);\r
+ //observer.onRemoveCompleted(packageName, true);\r
+ } catch (Exception e) {\r
+ XposedBridge.log("Observer no longer exists.");\r
+ }\r
+ }\r
+ //end dance\r
+ }\r
+ }\r
+ );\r
+\r
+ }\r
+}\r