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 348dbf4e..e71ddf07 100644
--- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java
+++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java
@@ -25,6 +25,7 @@ public class Main implements KeepAll {
// private static String sForkSystemServerPramsStr = "";
public static String sAppDataDir = "";
public static String sAppProcessName = "";
+ private static boolean sIsGlobalMode = false;
static {
init(Build.VERSION.SDK_INT);
@@ -39,13 +40,16 @@ public class Main implements KeepAll {
public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo,
String niceName, int[] fdsToClose, int[] fdsToIgnore,
- boolean startChildZygote, String instructionSet, String appDataDir) {
+ boolean startChildZygote, String instructionSet,
+ String appDataDir, boolean isGlobalMode) {
// sForkAndSpecializePramsStr = 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);
- if (!DYNAMIC_LOAD_MODULES) {
+ sAppDataDir = appDataDir;
+ sIsGlobalMode = isGlobalMode;
+ if (!DYNAMIC_LOAD_MODULES && isGlobalMode) {
Router.onProcessForked(false);
}
}
@@ -54,8 +58,7 @@ public class Main implements KeepAll {
// Utils.logD(sForkAndSpecializePramsStr + " = " + pid);
if (pid == 0) {
// in app process
- sAppDataDir = appDataDir;
- if (DYNAMIC_LOAD_MODULES) {
+ if (DYNAMIC_LOAD_MODULES || !sIsGlobalMode) {
Router.onProcessForked(false);
}
} else {
@@ -69,13 +72,13 @@ public class Main implements KeepAll {
// sForkSystemServerPramsStr = 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/";
}
public static void forkSystemServerPost(int pid) {
// Utils.logD(sForkSystemServerPramsStr + " = " + pid);
if (pid == 0) {
// in system_server process
- sAppDataDir = getDataPathPrefix() + "android/";
Router.onProcessForked(true);
} else {
// in zygote process, res is child zygote pid
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 6fae2d82..04c0036a 100644
--- a/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java
+++ b/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java
@@ -7,6 +7,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.internal.os.ZygoteInit;
+import com.elderdrivers.riru.xposed.BuildConfig;
import com.elderdrivers.riru.xposed.entry.Router;
import com.elderdrivers.riru.xposed.util.Utils;
@@ -50,6 +51,7 @@ public final class XposedInit {
}
private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false);
+
/**
* Hook some methods which we want to create an easier interface for developers.
*/
@@ -122,10 +124,12 @@ public final class XposedInit {
* in assets/xposed_init.
*/
private static void loadModule(String apk, ClassLoader topClassLoader) {
- Log.i(TAG, "Loading modules from " + apk);
+ if (BuildConfig.DEBUG)
+ Log.i(TAG, "Loading modules from " + apk);
if (!TextUtils.isEmpty(apk) && apk.contains(BLACK_LIST_PACKAGE_NAME)) {
- Log.i(TAG, "We are going to take over black list's job...");
+ if (BuildConfig.DEBUG)
+ Log.i(TAG, "We are going to take over black list's job...");
return;
}
@@ -186,7 +190,8 @@ public final class XposedInit {
continue;
try {
- Log.i(TAG, " Loading class " + moduleClassName);
+ if (BuildConfig.DEBUG)
+ Log.i(TAG, " Loading class " + moduleClassName);
Class> moduleClass = mcl.loadClass(moduleClassName);
if (!IXposedMod.class.isAssignableFrom(moduleClass)) {
diff --git a/Core/jni/main/Android.mk b/Core/jni/main/Android.mk
index b8bff4fe..0abc2c81 100644
--- a/Core/jni/main/Android.mk
+++ b/Core/jni/main/Android.mk
@@ -18,6 +18,7 @@ LOCAL_SRC_FILES:= \
yahfa/HookMain.c \
yahfa/trampoline.c \
java_hook/java_hook.cpp \
- inject/framework_hook.cpp
+ inject/framework_hook.cpp \
+ inject/config_manager.cpp
include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/Core/jni/main/inject/config_manager.cpp b/Core/jni/main/inject/config_manager.cpp
new file mode 100644
index 00000000..24683687
--- /dev/null
+++ b/Core/jni/main/inject/config_manager.cpp
@@ -0,0 +1,65 @@
+//
+// Created by Solo on 2019/1/27.
+//
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "config_manager.h"
+
+#define BLACK_LIST_PATH "/data/misc/riru/modules/edxposed/blacklist/"
+#define WHITE_LIST_PATH "/data/misc/riru/modules/edxposed/whitelist/"
+#define USE_WHITE_LIST "/data/misc/riru/modules/edxposed/usewhitelist"
+#define GLOBAL_MODE "/data/misc/riru/modules/edxposed/forceglobal"
+
+static char package_name[256];
+
+// default is true
+int is_app_need_hook(JNIEnv *env, jstring appDataDir) {
+ if (is_global_mode()) {
+ return 1;
+ }
+ if (!appDataDir) {
+ LOGW("appDataDir is null");
+ return 1;
+ }
+ const char *app_data_dir = env->GetStringUTFChars(appDataDir, nullptr);
+ int user = 0;
+ if (sscanf(app_data_dir, "/data/%*[^/]/%d/%s", &user, package_name) != 2) {
+ if (sscanf(app_data_dir, "/data/%*[^/]/%s", package_name) != 1) {
+ package_name[0] = '\0';
+ LOGW("can't parse %s", app_data_dir);
+ return 1;
+ }
+ }
+ env->ReleaseStringUTFChars(appDataDir, app_data_dir);
+ bool use_white_list = access(USE_WHITE_LIST, F_OK) == 0;
+ bool white_list_exists = access(WHITE_LIST_PATH, F_OK) == 0;
+ bool black_list_exists = access(BLACK_LIST_PATH, F_OK) == 0;
+ if (use_white_list && white_list_exists) {
+ char path[PATH_MAX];
+ snprintf(path, PATH_MAX, WHITE_LIST_PATH "%s", package_name);
+ int res = access(path, F_OK) == 0;
+ LOGD("use whitelist, res=%d", res);
+ return res;
+ } else if (!use_white_list && black_list_exists) {
+ char path[PATH_MAX];
+ snprintf(path, PATH_MAX, BLACK_LIST_PATH "%s", package_name);
+ int res = access(path, F_OK) != 0;
+ LOGD("use blacklist, res=%d", res);
+ return res;
+ } else {
+ LOGD("use nonlist, res=%d", 1);
+ return 1;
+ }
+}
+
+int is_global_mode() {
+ return access(GLOBAL_MODE, F_OK) == 0;
+}
diff --git a/Core/jni/main/inject/config_manager.h b/Core/jni/main/inject/config_manager.h
new file mode 100644
index 00000000..8cc0d4b8
--- /dev/null
+++ b/Core/jni/main/inject/config_manager.h
@@ -0,0 +1,12 @@
+//
+// Created by Solo on 2019/1/27.
+//
+
+#ifndef EDXPOSED_CONFIG_MANAGER_H
+#define EDXPOSED_CONFIG_MANAGER_H
+
+int is_app_need_hook(JNIEnv *env, jstring appDataDir);
+
+int is_global_mode();
+
+#endif //EDXPOSED_CONFIG_MANAGER_H
diff --git a/Core/jni/main/inject/framework_hook.cpp b/Core/jni/main/inject/framework_hook.cpp
index 69730328..2a61235c 100644
--- a/Core/jni/main/inject/framework_hook.cpp
+++ b/Core/jni/main/inject/framework_hook.cpp
@@ -5,6 +5,9 @@
#include
#include "framework_hook.h"
#include "include/misc.h"
+#include "config_manager.h"
+
+#define SYSTEM_SERVER_DATA_DIR "/data/user/0/android/"
static jclass sEntryClass;
static jstring sAppDataDir;
@@ -38,6 +41,9 @@ void findAndCall(JNIEnv *env, const char *methodName, const char *methodSig, ...
void onNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid, jintArray gids,
jint runtime_flags, jobjectArray rlimits,
jlong permittedCapabilities, jlong effectiveCapabilities) {
+ if (!is_app_need_hook(env, env->NewStringUTF(SYSTEM_SERVER_DATA_DIR))) {
+ return;
+ }
prepareJavaEnv(env);
// jump to java code
findAndCall(env, "forkSystemServerPre", "(II[II[[IJJ)V", uid, gid, gids, runtime_flags, rlimits,
@@ -47,6 +53,9 @@ void onNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid
int onNativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) {
if (res == 0) {
+ if (!is_app_need_hook(env, env->NewStringUTF(SYSTEM_SERVER_DATA_DIR))) {
+ return 0;
+ }
prepareJavaEnv(env);
// only do work in child since findAndCall would print log
findAndCall(env, "forkSystemServerPost", "(I)V", res);
@@ -70,17 +79,23 @@ void onNativeForkAndSpecializePre(JNIEnv *env, jclass clazz,
jboolean is_child_zygote,
jstring instructionSet,
jstring appDataDir) {
+ sAppDataDir = appDataDir;
+ if (!is_app_need_hook(env, appDataDir)) {
+ return;
+ }
prepareJavaEnv(env);
findAndCall(env, "forkAndSpecializePre",
- "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)V",
+ "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z)V",
uid, gid, gids, runtime_flags, rlimits,
_mount_external, se_info, se_name, fdsToClose, fdsToIgnore,
- is_child_zygote, instructionSet, appDataDir);
- sAppDataDir = appDataDir;
+ is_child_zygote, instructionSet, appDataDir, is_global_mode());
}
int onNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
if (res == 0) {
+ if (!is_app_need_hook(env, sAppDataDir)) {
+ return 0;
+ }
prepareJavaEnv(env);
findAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;)V", res, sAppDataDir);
} else {