diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java index 2c596211..650599b2 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java @@ -18,17 +18,17 @@ import static com.elderdrivers.riru.xposed.util.FileUtils.getDataPathPrefix; @SuppressLint("DefaultLocale") public class Main implements KeepAll { - public static String sAppDataDir = ""; - public static String sAppProcessName = ""; - private static String sForkAndSpecializePramsStr = ""; - private static String sForkSystemServerPramsStr = ""; + public static String appDataDir = ""; + public static String appProcessName = ""; /** * When set to true, install bootstrap hooks and loadModules * for each process when it starts. * This means you can deactivate or activate every module * for the process you restart without rebooting. */ - private static boolean sIsDynamicModules = false; + public static boolean isDynamicModules = false; + private static String forkAndSpecializePramsStr = ""; + private static String forkSystemServerPramsStr = ""; static { init(Build.VERSION.SDK_INT); @@ -45,29 +45,27 @@ public class Main implements KeepAll { boolean startChildZygote, String instructionSet, String appDataDir, boolean isDynamicModules) { if (BuildConfig.DEBUG) { - sForkAndSpecializePramsStr = String.format( + forkAndSpecializePramsStr = String.format( "Zygote#forkAndSpecialize(%d, %d, %s, %d, %s, %d, %s, %s, %s, %s, %s, %s, %s)", uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits), mountExternal, seInfo, niceName, Arrays.toString(fdsToClose), Arrays.toString(fdsToIgnore), startChildZygote, instructionSet, appDataDir); } - sAppDataDir = appDataDir; - sIsDynamicModules = isDynamicModules; + Main.appDataDir = appDataDir; + Main.isDynamicModules = isDynamicModules; Router.prepare(false); // install bootstrap hooks for secondary zygote Router.installBootstrapHooks(false); - if (!isDynamicModules) { - // load modules only once in zygote process - Router.loadModulesSafely(); - } + // load modules for secondary zygote + Router.loadModulesSafely(); } public static void forkAndSpecializePost(int pid, String appDataDir) { if (pid == 0) { - Utils.logD(sForkAndSpecializePramsStr + " = " + Process.myPid()); + Utils.logD(forkAndSpecializePramsStr + " = " + Process.myPid()); Router.onEnterChildProcess(); DynamicBridge.onForkPost(); - if (sIsDynamicModules) { + if (isDynamicModules) { // load modules for each app process on its forked Router.loadModulesSafely(); } @@ -78,26 +76,31 @@ public class Main implements KeepAll { } public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, - long permittedCapabilities, long effectiveCapabilities) { + long permittedCapabilities, long effectiveCapabilities, + boolean isDynamicModules) { if (BuildConfig.DEBUG) { - sForkSystemServerPramsStr = String.format("Zygote#forkSystemServer(%d, %d, %s, %d, %s, %d, %d)", + forkSystemServerPramsStr = String.format("Zygote#forkSystemServer(%d, %d, %s, %d, %s, %d, %d)", uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits), permittedCapabilities, effectiveCapabilities); } - sAppDataDir = getDataPathPrefix() + "android"; - sIsDynamicModules = false; + Main.appDataDir = getDataPathPrefix() + "android"; + Main.isDynamicModules = isDynamicModules; + Router.prepare(true); // install bootstrap hooks for main zygote as early as possible - // in case we miss some processes + // in case we miss some processes not forked via forkAndSpecialize + // for instance com.android.phone Router.installBootstrapHooks(true); + // loadModules have to be executed in zygote even isDynamicModules is false + // because if not global hooks installed in initZygote might not be + // propagated to processes not forked via forkAndSpecialize + Router.loadModulesSafely(); } public static void forkSystemServerPost(int pid) { if (pid == 0) { - Utils.logD(sForkSystemServerPramsStr + " = " + Process.myPid()); + Utils.logD(forkSystemServerPramsStr + " = " + Process.myPid()); // in system_server process Router.onEnterChildProcess(); - Router.prepare(true); - Router.loadModulesSafely(); } else { // in zygote process, res is child zygote pid // don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66 diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java index 472c8347..8a5dd8bc 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java @@ -25,8 +25,8 @@ public class DexMakerUtils { } String packageName = AndroidAppHelper.currentPackageName(); if (TextUtils.isEmpty(packageName)) { //default to true - DexLog.w("packageName is empty, processName=" + Main.sAppProcessName - + ", appDataDir=" + Main.sAppDataDir); + DexLog.w("packageName is empty, processName=" + Main.appProcessName + + ", appDataDir=" + Main.appDataDir); return true; } return !SELinuxHelper.getAppDataFileService().checkFileExists(COMPAT_LIST_PATH + packageName); diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DynamicBridge.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DynamicBridge.java index d9839a41..07bbdee3 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DynamicBridge.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DynamicBridge.java @@ -53,12 +53,12 @@ public final class DynamicBridge { try { // we always choose to use device encrypted storage data on android N and later // in case some app is installing hooks before phone is unlocked - String fixedAppDataDir = getDataPathPrefix() + getPackageName(Main.sAppDataDir) + "/"; + String fixedAppDataDir = getDataPathPrefix() + getPackageName(Main.appDataDir) + "/"; dexDir = new File(fixedAppDataDir, "/cache/edhookers/" + getCurrentProcessName().replace(":", "_") + "/"); dexOptDir = new File(dexDir, "oat"); dexDir.mkdirs(); - DexLog.d(Main.sAppProcessName + " deleting dir: " + dexOptDir.getAbsolutePath()); + DexLog.d(Main.appProcessName + " deleting dir: " + dexOptDir.getAbsolutePath()); try { FileUtils.delete(dexOptDir); } catch (Throwable throwable) { diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/HandleBindAppHooker.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/HandleBindAppHooker.java index 6e9a1709..17154010 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/HandleBindAppHooker.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/HandleBindAppHooker.java @@ -39,10 +39,10 @@ public class HandleBindAppHooker implements KeepMembers { ActivityThread activityThread = (ActivityThread) thiz; ApplicationInfo appInfo = (ApplicationInfo) getObjectField(bindData, "appInfo"); // save app process name here for later use - Main.sAppProcessName = (String) getObjectField(bindData, "processName"); + Main.appProcessName = (String) getObjectField(bindData, "processName"); String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName; - Utils.logD("processName=" + Main.sAppProcessName + - ", packageName=" + reportedPackageName + ", appDataDir=" + Main.sAppDataDir); + Utils.logD("processName=" + Main.appProcessName + + ", packageName=" + reportedPackageName + ", appDataDir=" + Main.appDataDir); if (XposedBlackListHooker.shouldDisableHooks(reportedPackageName)) { return; diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/util/ProcessUtils.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/util/ProcessUtils.java index 2b0c44c7..f5442ec8 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/util/ProcessUtils.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/util/ProcessUtils.java @@ -13,7 +13,7 @@ import java.io.InputStreamReader; public class ProcessUtils { public static String getCurrentProcessName() { - String prettyName = Main.sAppProcessName; + String prettyName = Main.appProcessName; if (!TextUtils.isEmpty(prettyName)) { return prettyName; } @@ -23,7 +23,7 @@ public class ProcessUtils { /** * a common solution from https://stackoverflow.com/a/21389402 *

- * use {@link com.elderdrivers.riru.xposed.Main#sAppProcessName} to get current process name + * use {@link com.elderdrivers.riru.xposed.Main#appProcessName} to get current process name */ public static String getProcessName(int pid) { BufferedReader cmdlineReader = null; diff --git a/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java b/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java index a73213ae..eccbcaa8 100644 --- a/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java +++ b/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -372,6 +372,12 @@ public final class XposedBridge { } } + public static void clearLoadedPackages() { + synchronized (sLoadedPackageCallbacks) { + sLoadedPackageCallbacks.clear(); + } + } + /** * Adds a callback to be executed when the resources for an app are initialized. * @@ -526,6 +532,10 @@ public final class XposedBridge { public Object[] getSnapshot() { return elements; } + + public synchronized void clear() { + elements = EMPTY_ARRAY; + } } public static class AdditionalHookInfo { diff --git a/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java b/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java index dcd59f3d..6d4720da 100644 --- a/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java +++ b/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java @@ -8,6 +8,7 @@ import android.util.Log; import com.android.internal.os.ZygoteInit; import com.elderdrivers.riru.xposed.BuildConfig; +import com.elderdrivers.riru.xposed.Main; import com.elderdrivers.riru.xposed.entry.Router; import com.elderdrivers.riru.xposed.util.Utils; @@ -93,9 +94,10 @@ public final class XposedInit { private static volatile AtomicBoolean modulesLoaded = new AtomicBoolean(false); public static void loadModules() throws IOException { - if (!modulesLoaded.compareAndSet(false, true)) { + if (!modulesLoaded.compareAndSet(false, true) && !Main.isDynamicModules) { return; } + XposedBridge.clearLoadedPackages(); final String filename = INSTALLER_DATA_BASE_DIR + "conf/modules.list"; BaseService service = SELinuxHelper.getAppDataFileService(); if (!service.checkFileExists(filename)) { diff --git a/Core/jni/main/inject/framework_hook.cpp b/Core/jni/main/inject/framework_hook.cpp index 68717012..e4beefa4 100644 --- a/Core/jni/main/inject/framework_hook.cpp +++ b/Core/jni/main/inject/framework_hook.cpp @@ -47,8 +47,8 @@ void onNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid } prepareJavaEnv(env); // jump to java code - findAndCall(env, "forkSystemServerPre", "(II[II[[IJJ)V", uid, gid, gids, runtime_flags, rlimits, - permittedCapabilities, effectiveCapabilities); + findAndCall(env, "forkSystemServerPre", "(II[II[[IJJZ)V", uid, gid, gids, runtime_flags, rlimits, + permittedCapabilities, effectiveCapabilities, is_dynamic_modules()); }