diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseHookProvider.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseHookProvider.java index 019c13c91..9b747f7d1 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseHookProvider.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseHookProvider.java @@ -1,8 +1,5 @@ package com.elderdrivers.riru.edxp.config; -import android.content.res.Resources; -import android.content.res.XResources; - import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; import com.elderdrivers.riru.edxp.hook.HookProvider; @@ -40,9 +37,4 @@ public void deoptMethodNative(Object method) { public boolean initXResourcesNative() { return false; } - - @Override - public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) { - - } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/InlinedMethodCallers.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/InlinedMethodCallers.java index 1f0862ddb..f2a476713 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/InlinedMethodCallers.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/InlinedMethodCallers.java @@ -26,7 +26,22 @@ public class InlinedMethodCallers { */ private static final String[][] BOOT_IMAGE = { // callers of Application#attach(Context) - {"android.app.Instrumentation", "newApplication", "(Ljava/lang/ClassLoader;Ljava/lang/String;Landroid/content/Context;)Landroid/app/Application;"} + {"android.app.Instrumentation", "newApplication", "(Ljava/lang/ClassLoader;Ljava/lang/String;Landroid/content/Context;)Landroid/app/Application;"}, + + // for MIUI resources hooking + {"android.content.res.MiuiResources", "init", "(Ljava/lang/String;)V"}, + {"android.content.res.MiuiResources", "updateMiuiImpl", "()V"}, + {"android.content.res.MiuiResources", "setImpl", "(Landroid/content/res/ResourcesImpl;)V"}, + {"android.content.res.MiuiResources", "loadOverlayValue", "(Landroid/util/TypedValue;I)V"}, + {"android.content.res.MiuiResources", "getThemeString", "(I)Ljava/lang/CharSequence;"}, + {"android.content.res.MiuiResources", "", "(Ljava/lang/ClassLoader;)V"}, + {"android.content.res.MiuiResources", "", "()V"}, + {"android.content.res.MiuiResources", "", "(Landroid/content/res/AssetManager;Landroid/util/DisplayMetrics;Landroid/content/res/Configuration;)V"}, + {"android.miui.ResourcesManager", "initMiuiResource", "(Landroid/content/res/Resources;Ljava/lang/String;)V"}, + {"android.app.LoadedApk", "getResources", "()Landroid/content/res/Resources;"}, + {"android.content.res.Resources", "getSystem", "()Landroid/content/res/Resources;"}, + {"android.app.ApplicationPackageManager", "getResourcesForApplication", "(Landroid/content/pm/ApplicationInfo;)Landroid/content/res/Resources;"}, + {"android.app.ContextImpl", "setResources", "(Landroid/content/res/Resources;)V"}, }; private static final String[][] SYSTEM_SERVER = {}; diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/PrebuiltMethodsDeopter.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/PrebuiltMethodsDeopter.java index a90b19080..4fe9a165b 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/PrebuiltMethodsDeopter.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/PrebuiltMethodsDeopter.java @@ -19,8 +19,12 @@ public static void deoptMethods(String where, ClassLoader cl) { } for (String[] caller : callers) { try { + Class clazz = XposedHelpers.findClassIfExists(caller[0], cl); + if (clazz == null) { + continue; + } Object method = EdXpConfigGlobal.getHookProvider().findMethodNative( - XposedHelpers.findClass(caller[0], cl), caller[1], caller[2]); + clazz, caller[1], caller[2]); if (method != null) { EdXpConfigGlobal.getHookProvider().deoptMethodNative(method); } diff --git a/edxp-core/.gitignore b/edxp-core/.gitignore index bb940433f..64538351a 100644 --- a/edxp-core/.gitignore +++ b/edxp-core/.gitignore @@ -3,6 +3,8 @@ /libs /obj /release +/template_override/module.prop +/template_override/riru_module.prop /template_override/system /template_override/system_x86 *.iml \ No newline at end of file diff --git a/edxp-core/build.gradle b/edxp-core/build.gradle index cf7594923..f6bb092a0 100644 --- a/edxp-core/build.gradle +++ b/edxp-core/build.gradle @@ -2,13 +2,17 @@ import org.gradle.internal.os.OperatingSystem apply plugin: 'com.android.library' -version "v0.4.0.1_beta-SNAPSHOT" +version "v0.4.1.2_beta" ext { + versionCode = "4120" module_name = "EdXposed" jar_dest_dir = "${projectDir}/template_override/system/framework/" is_windows = OperatingSystem.current().isWindows() - backends = ["Yahfa", "Sandhook", "Whale"] + backends = ["YAHFA", "SandHook", "Whale"] + yahfa_authors = "solohsu, rk700 & MlgmXyysd" + sandhook_authors = "solohsu, ganyao114 & MlgmXyysd" + whale_authors = "solohsu, asLody & MlgmXyysd" } android { @@ -72,21 +76,34 @@ afterEvaluate { backends.each { backend -> - def backendCapped = backend.capitalize() def backendLowered = backend.toLowerCase() + def backendCapped = backendLowered.capitalize() + def authorList = property("${backendLowered}" + "_authors") def zipTask = task("zip${backendCapped}${variantCapped}", type: Exec) { dependsOn cleanTemplate, copyDalvikdxJar, copyDexmakerJar dependsOn tasks.getByPath(":edxp-${backendLowered}:makeAndCopy${variantCapped}") workingDir '..' commandLine 'sh', 'build.sh', project.name, - "${backendLowered}-${project.version}-${variantLowered}", "${module_name}" + "${backend}-${project.version}-${variantLowered}", "${module_name}" doFirst { copy { - from "${projectDir}/edconfig.tpl" + from "${projectDir}/tpl/edconfig.tpl" into templateFrameworkPath rename "edconfig.tpl", "edconfig.jar" - expand(backend: "$backendCapped") + expand(version: "$version", backend: "$backend") + } + copy { + from "${projectDir}/tpl/module.prop.tpl" + into templateRootPath + rename "module.prop.tpl", "module.prop" + expand(backend: "$backendCapped", versionName: "$version" + "($backend)", + versionCode: "$versionCode", authorList: "$authorList") + } + copy { + from "${templateRootPath}/module.prop" + into templateRootPath + rename "module.prop", "riru_module.prop" } } } @@ -95,7 +112,7 @@ afterEvaluate { dependsOn zipTask workingDir "${projectDir}/release" def commands = ["adb", "push", - "magisk-${module_name}-${backendLowered}-${project.version}-${variantLowered}.zip", + "magisk-${module_name}-${backend}-${project.version}-${variantLowered}.zip", "/sdcard/"] if (is_windows) { commandLine 'cmd', '/c', commands.join(" ") diff --git a/edxp-core/edconfig.tpl b/edxp-core/edconfig.tpl deleted file mode 100644 index 95f840e17..000000000 --- a/edxp-core/edconfig.tpl +++ /dev/null @@ -1,5 +0,0 @@ -version=90.0-0.4.0.1-beta-SNAPSHOT ($backend) -arch=arm64 -minsdk=23 -maxsdk=28 -requires:fbe_aware=1 diff --git a/edxp-core/jni/main/java_hook/java_hook.cpp b/edxp-core/jni/main/java_hook/java_hook.cpp index 198526601..26de4b9a1 100644 --- a/edxp-core/jni/main/java_hook/java_hook.cpp +++ b/edxp-core/jni/main/java_hook/java_hook.cpp @@ -73,6 +73,19 @@ void setMethodNonCompilable(JNIEnv *env, jclass, jobject member) { setNonCompilable(artMethod); } +static constexpr uint32_t kAccFinal = 0x0010; + +jboolean removeFinalFlag(JNIEnv *env, jclass, jclass clazz) { + if (clazz) { + jfieldID java_lang_Class_accessFlags = env->GetFieldID( + env->FindClass("java/lang/Class"), "accessFlags", "I"); + jint access_flags = env->GetIntField(clazz, java_lang_Class_accessFlags); + env->SetIntField(clazz, java_lang_Class_accessFlags, access_flags & ~kAccFinal); + return true; + } + return false; +} + static JNINativeMethod hookMethods[] = { { "init", @@ -131,7 +144,7 @@ static JNINativeMethod hookMethods[] = { "initXResourcesNative", "()Z", (void *) XposedBridge_initXResourcesNative }, { - "rewriteXmlReferencesNative", "(JLandroid/content/res/XResources;Landroid/content/res/Resources;)V", (void *) XResources_rewriteXmlReferencesNative + "removeFinalFlagNative", "(Ljava/lang/Class;)Z", (void *) removeFinalFlag } }; diff --git a/edxp-core/jni/main/native_hook/native_hook.cpp b/edxp-core/jni/main/native_hook/native_hook.cpp index 1cfc3e6b4..5e3021388 100644 --- a/edxp-core/jni/main/native_hook/native_hook.cpp +++ b/edxp-core/jni/main/native_hook/native_hook.cpp @@ -59,6 +59,13 @@ static bool onIsInSamePackageCalled(void *thiz, void *that) { || strstr(thatDesc, "com/elderdrivers/riru/") != nullptr) { return true; } + // for MIUI resources hooking + if (strstr(thisDesc, "android/content/res/MiuiTypedArray") != nullptr + || strstr(thatDesc, "android/content/res/MiuiTypedArray") != nullptr + || strstr(thisDesc, "android/content/res/XResources$XTypedArray") != nullptr + || strstr(thatDesc, "android/content/res/XResources$XTypedArray") != nullptr) { + return true; + } return (*isInSamePackageBackup)(thiz, that); } diff --git a/edxp-core/jni/main/native_hook/resource_hook.cpp b/edxp-core/jni/main/native_hook/resource_hook.cpp index 09282f92c..56e378654 100644 --- a/edxp-core/jni/main/native_hook/resource_hook.cpp +++ b/edxp-core/jni/main/native_hook/resource_hook.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "resource_hook.h" #define CLASS_XRESOURCES "android/content/res/XResources" @@ -44,7 +45,7 @@ bool prepareSymbols() { #if defined(__LP64__) "_ZNK7android12ResXMLParser18getAttributeNameIDEm" #else - "_ZNK7android12ResXMLParser18getAttributeNameIDEj" + "_ZNK7android12ResXMLParser18getAttributeNameIDEj" #endif )); if (!ResXMLParser_getAttributeNameID) { @@ -66,6 +67,15 @@ bool prepareSymbols() { return true; } +int register_natives_XResources(JNIEnv *env, jclass clazz) { + const JNINativeMethod methods[] = { + {"rewriteXmlReferencesNative", + "(JLandroid/content/res/XResources;Landroid/content/res/Resources;)V", + (void *) XResources_rewriteXmlReferencesNative}, + }; + return env->RegisterNatives(clazz, methods, NELEM(methods)); +} + jboolean XposedBridge_initXResourcesNative(JNIEnv *env, jclass) { classXResources = env->FindClass(CLASS_XRESOURCES); if (classXResources == NULL) { @@ -75,6 +85,12 @@ jboolean XposedBridge_initXResourcesNative(JNIEnv *env, jclass) { } classXResources = reinterpret_cast(env->NewGlobalRef(classXResources)); + if (register_natives_XResources(env, classXResources) != JNI_OK) { + LOGE("Could not register natives for '%s'", CLASS_XRESOURCES); + env->ExceptionClear(); + return false; + } + methodXResourcesTranslateResId = env->GetStaticMethodID(classXResources, "translateResId", "(ILandroid/content/res/XResources;Landroid/content/res/Resources;)I"); if (methodXResourcesTranslateResId == NULL) { diff --git a/edxp-core/template_override/common/util_functions.sh b/edxp-core/template_override/common/util_functions.sh index 068bd15eb..56eeb124b 100644 --- a/edxp-core/template_override/common/util_functions.sh +++ b/edxp-core/template_override/common/util_functions.sh @@ -1,6 +1,6 @@ #!/system/bin/sh -EDXP_VERSION="0.4.0.1_beta-SNAPSHOT (4010)" +EDXP_VERSION="0.4.1.2_beta (4120)" ANDROID_SDK=`getprop ro.build.version.sdk` BUILD_DESC=`getprop ro.build.description` PRODUCT=`getprop ro.build.product` diff --git a/edxp-core/template_override/config.sh b/edxp-core/template_override/config.sh index 83406ddb6..c9fb73fad 100644 --- a/edxp-core/template_override/config.sh +++ b/edxp-core/template_override/config.sh @@ -41,7 +41,7 @@ LATESTARTSERVICE=false print_modname() { ui_print "************************************" - ui_print " Riru - Ed Xposed v0.4.0.1 " + ui_print " Riru - Ed Xposed " ui_print "************************************" } diff --git a/edxp-core/template_override/riru_module.prop b/edxp-core/template_override/riru_module.prop deleted file mode 100644 index 25152672b..000000000 --- a/edxp-core/template_override/riru_module.prop +++ /dev/null @@ -1,5 +0,0 @@ -name=Ed Xposed -version=v0.4.0.1_beta-SNAPSHOT -versionCode=4010 -author=solohsu & MlgmXyysd -description=Magisk version of Xposed. Require Riru - Core installed. diff --git a/edxp-core/tpl/edconfig.tpl b/edxp-core/tpl/edconfig.tpl new file mode 100644 index 000000000..c5abe46c0 --- /dev/null +++ b/edxp-core/tpl/edconfig.tpl @@ -0,0 +1,5 @@ +version=90.0-$version ($backend) +arch=arm64 +minsdk=26 +maxsdk=28 +requires:fbe_aware=1 diff --git a/edxp-core/template_override/module.prop b/edxp-core/tpl/module.prop.tpl similarity index 62% rename from edxp-core/template_override/module.prop rename to edxp-core/tpl/module.prop.tpl index 9473fddbf..5e707e2f0 100644 --- a/edxp-core/template_override/module.prop +++ b/edxp-core/tpl/module.prop.tpl @@ -1,7 +1,7 @@ id=riru_edxposed name=Riru - Ed Xposed -version=v0.4.0.1_beta-SNAPSHOT -versionCode=4010 -author=solohsu & MlgmXyysd +version=${versionName} +versionCode=${versionCode} +author=${authorList} description=Magisk version of Xposed. Require Riru - Core installed. minMagisk=17000 diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/Main.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/Main.java index ef87ebb1c..ffccbd735 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/Main.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/Main.java @@ -1,19 +1,17 @@ package com.elderdrivers.riru.edxp; import android.annotation.SuppressLint; -import android.content.res.Resources; -import android.content.res.XResources; import android.os.Build; import android.os.Process; import com.elderdrivers.riru.common.KeepAll; -import com.elderdrivers.riru.edxp.sandhook.BuildConfig; import com.elderdrivers.riru.edxp.config.InstallerChooser; -import com.elderdrivers.riru.edxp.util.Utils; +import com.elderdrivers.riru.edxp.sandhook.BuildConfig; import com.elderdrivers.riru.edxp.sandhook.core.HookMethodResolver; import com.elderdrivers.riru.edxp.sandhook.entry.Router; import com.elderdrivers.riru.edxp.sandhook.proxy.BlackWhiteListProxy; import com.elderdrivers.riru.edxp.sandhook.proxy.NormalProxy; +import com.elderdrivers.riru.edxp.util.Utils; import com.swift.sandhook.xposedcompat.XposedCompat; import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge; @@ -152,5 +150,5 @@ public static void forkSystemServerPost(int pid) { public static native boolean initXResourcesNative(); - public static native void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes); + public static native boolean removeFinalFlagNative(Class clazz); } diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookProvider.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookProvider.java index b8279053b..d00024eb4 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookProvider.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookProvider.java @@ -1,7 +1,5 @@ package com.elderdrivers.riru.edxp.sandhook.config; -import android.content.res.Resources; -import android.content.res.XResources; import android.util.Log; import com.elderdrivers.riru.edxp.Main; @@ -67,7 +65,7 @@ public boolean initXResourcesNative() { } @Override - public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) { - Main.rewriteXmlReferencesNative(parserPtr, origRes, repRes); + public boolean removeFinalFlagNative(Class clazz) { + return Main.removeFinalFlagNative(clazz); } } diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java index 1240845e2..2f6b06eea 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java @@ -14,7 +14,6 @@ import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.WorkAroundHookInfo; import com.elderdrivers.riru.edxp.sandhook.entry.hooker.SystemMainHooker; import com.elderdrivers.riru.edxp.util.Utils; -import com.swift.sandhook.SandHookConfig; import com.swift.sandhook.xposedcompat.XposedCompat; import java.util.concurrent.atomic.AtomicBoolean; @@ -32,10 +31,14 @@ public class Router { static boolean useSandHook = false; + public static void initResourcesHook() { + startWorkAroundHook(); // for OnePlus devices + XposedBridge.initXResources(); + } + public static void prepare(boolean isSystem) { // this flag is needed when loadModules startsSystemServer = isSystem; -// InstallerChooser.setup(); } public static void checkHookState(String appDataDir) { @@ -124,8 +127,15 @@ public static void startWorkAroundHook() { } } - public static void onEnterChildProcess() { + public static void onForkStart() { + forkCompleted = false; + } + + public static void onForkFinish() { forkCompleted = true; + } + + public static void onEnterChildProcess() { DynamicBridge.onForkPost(); //enable compile in child process //SandHook.enableCompiler(!XposedInit.startsSystemServer); @@ -144,5 +154,6 @@ public static void logE(String prefix, Throwable throwable) { public static void injectConfig() { EdXpConfigGlobal.sConfig = new SandHookEdxpConfig(); EdXpConfigGlobal.sHookProvider = new SandHookProvider(); + XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName()); } } diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/BlackWhiteListProxy.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/BlackWhiteListProxy.java index fd565e66d..02b1fedac 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/BlackWhiteListProxy.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/BlackWhiteListProxy.java @@ -2,17 +2,17 @@ import android.text.TextUtils; +import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; +import com.elderdrivers.riru.edxp.sandhook.entry.Router; import com.elderdrivers.riru.edxp.util.ProcessUtils; import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.sandhook.entry.Router; import de.robv.android.xposed.XposedBridge; -import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; import static com.elderdrivers.riru.edxp.Main.isAppNeedHook; +import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; /** * 1. Non dynamic mode @@ -73,6 +73,8 @@ public static void forkSystemServerPost(int pid) { * Some details are different between main zygote and secondary zygote. */ private static void onForkPreForNonDynamicMode(boolean isSystemServer) { + Router.onForkStart(); + Router.initResourcesHook(); ConfigManager.setDynamicModulesMode(false); // set startsSystemServer flag used when loadModules Router.prepare(isSystemServer); @@ -92,20 +94,25 @@ private static void onForkPostCommon(boolean isSystemServer, String appDataDir, Main.niceName = niceName; final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); ConfigManager.setDynamicModulesMode(isDynamicModulesMode); - Router.onEnterChildProcess(); if (!isDynamicModulesMode) { Main.reopenFilesAfterForkNative(); } + Router.onEnterChildProcess(); if (!checkNeedHook(appDataDir, niceName)) { // if is blacklisted, just stop here + Router.onForkFinish(); return; } + if (isDynamicModulesMode) { + Router.initResourcesHook(); + } Router.prepare(isSystemServer); PrebuiltMethodsDeopter.deoptBootMethods(); Router.installBootstrapHooks(isSystemServer); if (isDynamicModulesMode) { Router.loadModulesSafely(false); } + Router.onForkFinish(); } private static boolean checkNeedHook(String appDataDir, String niceName) { diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/NormalProxy.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/NormalProxy.java index f63052d9b..476977aed 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/NormalProxy.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/NormalProxy.java @@ -1,7 +1,7 @@ package com.elderdrivers.riru.edxp.sandhook.proxy; -import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.Main; +import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; import com.elderdrivers.riru.edxp.sandhook.entry.Router; @@ -15,6 +15,8 @@ public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugF boolean startChildZygote, String instructionSet, String appDataDir) { // mainly for secondary zygote + Router.onForkStart(); + Router.initResourcesHook(); final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); ConfigManager.setDynamicModulesMode(isDynamicModulesMode); // call this to ensure the flag is set to false ASAP @@ -36,10 +38,13 @@ public static void forkAndSpecializePost(int pid, String appDataDir, String nice Router.onEnterChildProcess(); // load modules for each app process on its forked if dynamic modules mode is on Router.loadModulesSafely(false); + Router.onForkFinish(); } public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { + Router.onForkStart(); + Router.initResourcesHook(); final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); ConfigManager.setDynamicModulesMode(isDynamicModulesMode); // set startsSystemServer flag used when loadModules @@ -65,6 +70,7 @@ public static void forkSystemServerPost(int pid) { Router.onEnterChildProcess(); // reload module list if dynamic mode is on Router.loadModulesSafely(false); + Router.onForkFinish(); } } diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/Main.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/Main.java index 3f1019be0..1f76a7566 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/Main.java +++ b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/Main.java @@ -1,18 +1,16 @@ package com.elderdrivers.riru.edxp; import android.annotation.SuppressLint; -import android.content.res.Resources; -import android.content.res.XResources; import android.os.Build; import android.os.Process; import com.elderdrivers.riru.common.KeepAll; import com.elderdrivers.riru.edxp.config.InstallerChooser; +import com.elderdrivers.riru.edxp.util.Utils; import com.elderdrivers.riru.edxp.whale.core.HookMethodResolver; import com.elderdrivers.riru.edxp.whale.entry.Router; import com.elderdrivers.riru.edxp.whale.proxy.BlackWhiteListProxy; import com.elderdrivers.riru.edxp.whale.proxy.NormalProxy; -import com.elderdrivers.riru.edxp.util.Utils; import java.lang.reflect.Method; import java.util.Arrays; @@ -143,5 +141,5 @@ public static void forkSystemServerPost(int pid) { public static native boolean initXResourcesNative(); - public static native void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes); + public static native boolean removeFinalFlagNative(Class clazz); } diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleHookProvider.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleHookProvider.java index 79303fe38..2a9eb1d31 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleHookProvider.java +++ b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleHookProvider.java @@ -1,8 +1,5 @@ package com.elderdrivers.riru.edxp.whale.config; -import android.content.res.Resources; -import android.content.res.XResources; - import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.config.BaseHookProvider; import com.lody.whale.WhaleRuntime; @@ -64,7 +61,7 @@ public boolean initXResourcesNative() { } @Override - public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) { - Main.rewriteXmlReferencesNative(parserPtr, origRes, repRes); + public boolean removeFinalFlagNative(Class clazz) { + return Main.removeFinalFlagNative(clazz); } } diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java index cde849567..79753847d 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java +++ b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java @@ -5,8 +5,8 @@ import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.whale.config.WhaleHookProvider; import com.elderdrivers.riru.edxp.whale.config.WhaleEdxpConfig; +import com.elderdrivers.riru.edxp.whale.config.WhaleHookProvider; import com.elderdrivers.riru.edxp.whale.core.HookMain; import com.elderdrivers.riru.edxp.whale.entry.bootstrap.AppBootstrapHookInfo; import com.elderdrivers.riru.edxp.whale.entry.bootstrap.SysBootstrapHookInfo; @@ -25,11 +25,14 @@ public class Router { private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false); + public static void initResourcesHook() { + startWorkAroundHook(); // for OnePlus devices + XposedBridge.initXResources(); + } public static void prepare(boolean isSystem) { // this flag is needed when loadModules XposedInit.startsSystemServer = isSystem; -// InstallerChooser.setup(); } public static void checkHookState(String appDataDir) { @@ -101,10 +104,18 @@ public static void startWorkAroundHook() { WorkAroundHookInfo.class.getName()); } - public static void onEnterChildProcess() { + public static void onForkStart() { + forkCompleted = false; + } + + public static void onForkFinish() { forkCompleted = true; } + public static void onEnterChildProcess() { + + } + public static void logD(String prefix) { Utils.logD(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(), AndroidAppHelper.currentProcessName())); @@ -118,5 +129,6 @@ public static void logE(String prefix, Throwable throwable) { public static void injectConfig() { EdXpConfigGlobal.sConfig = new WhaleEdxpConfig(); EdXpConfigGlobal.sHookProvider = new WhaleHookProvider(); + XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName()); } } diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/BlackWhiteListProxy.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/BlackWhiteListProxy.java index 1e290d815..ea9fa7b59 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/BlackWhiteListProxy.java +++ b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/BlackWhiteListProxy.java @@ -73,6 +73,8 @@ public static void forkSystemServerPost(int pid) { * Some details are different between main zygote and secondary zygote. */ private static void onForkPreForNonDynamicMode(boolean isSystemServer) { + Router.onForkStart(); + Router.initResourcesHook(); ConfigManager.setDynamicModulesMode(false); // set startsSystemServer flag used when loadModules Router.prepare(isSystemServer); @@ -92,20 +94,25 @@ private static void onForkPostCommon(boolean isSystemServer, String appDataDir, Main.niceName = niceName; final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); ConfigManager.setDynamicModulesMode(isDynamicModulesMode); - Router.onEnterChildProcess(); if (!isDynamicModulesMode) { Main.reopenFilesAfterForkNative(); } + Router.onEnterChildProcess(); if (!checkNeedHook(appDataDir, niceName)) { // if is blacklisted, just stop here + Router.onForkFinish(); return; } + if (isDynamicModulesMode) { + Router.initResourcesHook(); + } Router.prepare(isSystemServer); PrebuiltMethodsDeopter.deoptBootMethods(); Router.installBootstrapHooks(isSystemServer); if (isDynamicModulesMode) { Router.loadModulesSafely(false); } + Router.onForkFinish(); } private static boolean checkNeedHook(String appDataDir, String niceName) { diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/NormalProxy.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/NormalProxy.java index 737567522..2327c6be3 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/NormalProxy.java +++ b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/NormalProxy.java @@ -15,6 +15,8 @@ public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugF boolean startChildZygote, String instructionSet, String appDataDir) { // mainly for secondary zygote + Router.onForkStart(); + Router.initResourcesHook(); final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); ConfigManager.setDynamicModulesMode(isDynamicModulesMode); // call this to ensure the flag is set to false ASAP @@ -36,10 +38,13 @@ public static void forkAndSpecializePost(int pid, String appDataDir, String nice Router.onEnterChildProcess(); // load modules for each app process on its forked if dynamic modules mode is on Router.loadModulesSafely(false); + Router.onForkFinish(); } public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { + Router.onForkStart(); + Router.initResourcesHook(); final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); ConfigManager.setDynamicModulesMode(isDynamicModulesMode); // set startsSystemServer flag used when loadModules @@ -65,6 +70,7 @@ public static void forkSystemServerPost(int pid) { Router.onEnterChildProcess(); // reload module list if dynamic mode is on Router.loadModulesSafely(false); + Router.onForkFinish(); } } diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/Main.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/Main.java index a781e6997..b0f6abeb4 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/Main.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/Main.java @@ -143,5 +143,5 @@ public static void forkSystemServerPost(int pid) { public static native boolean initXResourcesNative(); - public static native void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes); + public static native boolean removeFinalFlagNative(Class clazz); } diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaHookProvider.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaHookProvider.java index 4cbd0a373..0f810562e 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaHookProvider.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaHookProvider.java @@ -1,8 +1,5 @@ package com.elderdrivers.riru.edxp.yahfa.config; -import android.content.res.Resources; -import android.content.res.XResources; - import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.config.BaseHookProvider; import com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils; @@ -45,7 +42,7 @@ public boolean initXResourcesNative() { } @Override - public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) { - Main.rewriteXmlReferencesNative(parserPtr, origRes, repRes); + public boolean removeFinalFlagNative(Class clazz) { + return Main.removeFinalFlagNative(clazz); } } diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java index 57493cabd..ee5ae5bf5 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java @@ -3,7 +3,6 @@ import android.app.AndroidAppHelper; import android.text.TextUtils; -import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; import com.elderdrivers.riru.edxp.util.Utils; import com.elderdrivers.riru.edxp.yahfa.config.YahfaEdxpConfig; @@ -27,11 +26,14 @@ public class Router { private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false); + public static void initResourcesHook() { + startWorkAroundHook(); // for OnePlus devices + XposedBridge.initXResources(); + } public static void prepare(boolean isSystem) { // this flag is needed when loadModules XposedInit.startsSystemServer = isSystem; -// InstallerChooser.setup(); } public static void checkHookState(String appDataDir) { @@ -103,8 +105,15 @@ public static void startWorkAroundHook() { WorkAroundHookInfo.class.getName()); } - public static void onEnterChildProcess() { + public static void onForkStart() { + forkCompleted = false; + } + + public static void onForkFinish() { forkCompleted = true; + } + + public static void onEnterChildProcess() { DynamicBridge.onForkPost(); } @@ -121,5 +130,6 @@ public static void logE(String prefix, Throwable throwable) { public static void injectConfig() { EdXpConfigGlobal.sConfig = new YahfaEdxpConfig(); EdXpConfigGlobal.sHookProvider = new YahfaHookProvider(); + XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName()); } } diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/BlackWhiteListProxy.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/BlackWhiteListProxy.java index 5beb56ab9..5f2578c75 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/BlackWhiteListProxy.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/BlackWhiteListProxy.java @@ -5,9 +5,9 @@ import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.yahfa.entry.Router; import com.elderdrivers.riru.edxp.util.ProcessUtils; import com.elderdrivers.riru.edxp.util.Utils; +import com.elderdrivers.riru.edxp.yahfa.entry.Router; import de.robv.android.xposed.XposedBridge; @@ -73,6 +73,8 @@ public static void forkSystemServerPost(int pid) { * Some details are different between main zygote and secondary zygote. */ private static void onForkPreForNonDynamicMode(boolean isSystemServer) { + Router.onForkStart(); + Router.initResourcesHook(); ConfigManager.setDynamicModulesMode(false); // set startsSystemServer flag used when loadModules Router.prepare(isSystemServer); @@ -92,20 +94,25 @@ private static void onForkPostCommon(boolean isSystemServer, String appDataDir, Main.niceName = niceName; final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); ConfigManager.setDynamicModulesMode(isDynamicModulesMode); - Router.onEnterChildProcess(); if (!isDynamicModulesMode) { Main.reopenFilesAfterForkNative(); } + Router.onEnterChildProcess(); if (!checkNeedHook(appDataDir, niceName)) { // if is blacklisted, just stop here + Router.onForkFinish(); return; } + if (isDynamicModulesMode) { + Router.initResourcesHook(); + } Router.prepare(isSystemServer); PrebuiltMethodsDeopter.deoptBootMethods(); Router.installBootstrapHooks(isSystemServer); if (isDynamicModulesMode) { Router.loadModulesSafely(false); } + Router.onForkFinish(); } private static boolean checkNeedHook(String appDataDir, String niceName) { diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/NormalProxy.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/NormalProxy.java index 4fad6cdbf..c0bfcbf75 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/NormalProxy.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/NormalProxy.java @@ -15,6 +15,8 @@ public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugF boolean startChildZygote, String instructionSet, String appDataDir) { // mainly for secondary zygote + Router.onForkStart(); + Router.initResourcesHook(); final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); ConfigManager.setDynamicModulesMode(isDynamicModulesMode); // call this to ensure the flag is set to false ASAP @@ -36,10 +38,13 @@ public static void forkAndSpecializePost(int pid, String appDataDir, String nice Router.onEnterChildProcess(); // load modules for each app process on its forked if dynamic modules mode is on Router.loadModulesSafely(false); + Router.onForkFinish(); } public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { + Router.onForkStart(); + Router.initResourcesHook(); final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); ConfigManager.setDynamicModulesMode(isDynamicModulesMode); // set startsSystemServer flag used when loadModules @@ -65,6 +70,7 @@ public static void forkSystemServerPost(int pid) { Router.onEnterChildProcess(); // reload module list if dynamic mode is on Router.loadModulesSafely(false); + Router.onForkFinish(); } } diff --git a/hiddenapi-stubs/libs/framework-stub.jar b/hiddenapi-stubs/libs/framework-stub.jar index e68daf936..7688f4fd6 100644 Binary files a/hiddenapi-stubs/libs/framework-stub.jar and b/hiddenapi-stubs/libs/framework-stub.jar differ diff --git a/hiddenapi-stubs/src/main/java/xposed/dummy/XResourcesSuperClass.java b/hiddenapi-stubs/src/main/java/xposed/dummy/XResourcesSuperClass.java index 3c0f8bbad..16f38f301 100644 --- a/hiddenapi-stubs/src/main/java/xposed/dummy/XResourcesSuperClass.java +++ b/hiddenapi-stubs/src/main/java/xposed/dummy/XResourcesSuperClass.java @@ -16,4 +16,9 @@ protected XResourcesSuperClass() { super(null, null, null); throw new UnsupportedOperationException(); } + + protected XResourcesSuperClass(ClassLoader classLoader) { + super(classLoader); + throw new UnsupportedOperationException(); + } } diff --git a/hiddenapi-stubs/src/main/java/xposed/dummy/XTypedArraySuperClass.java b/hiddenapi-stubs/src/main/java/xposed/dummy/XTypedArraySuperClass.java index f27db4a1d..cefd760bd 100644 --- a/hiddenapi-stubs/src/main/java/xposed/dummy/XTypedArraySuperClass.java +++ b/hiddenapi-stubs/src/main/java/xposed/dummy/XTypedArraySuperClass.java @@ -13,8 +13,8 @@ */ public class XTypedArraySuperClass extends TypedArray { /** Dummy, will never be called (objects are transferred to this class only). */ - protected XTypedArraySuperClass(Resources resources, int[] data, int[] indices, int len) { - super(null, null, null, 0); + protected XTypedArraySuperClass(Resources resources) { + super(resources); throw new UnsupportedOperationException(); } } diff --git a/xposed-bridge/build.gradle b/xposed-bridge/build.gradle index b84841c6c..0d9a288a1 100644 --- a/xposed-bridge/build.gradle +++ b/xposed-bridge/build.gradle @@ -5,7 +5,7 @@ android { buildToolsVersion '28.0.3' defaultConfig { - minSdkVersion 23 + minSdkVersion 26 } sourceSets { diff --git a/xposed-bridge/src/main/java/android/content/res/XResources.java b/xposed-bridge/src/main/java/android/content/res/XResources.java index 412a7dc6b..8de7c840c 100644 --- a/xposed-bridge/src/main/java/android/content/res/XResources.java +++ b/xposed-bridge/src/main/java/android/content/res/XResources.java @@ -11,15 +11,12 @@ import android.text.Html; import android.util.AttributeSet; import android.util.DisplayMetrics; -import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; - import org.xmlpull.v1.XmlPullParser; import java.io.File; @@ -36,6 +33,8 @@ import de.robv.android.xposed.callbacks.XC_LayoutInflated; import de.robv.android.xposed.callbacks.XC_LayoutInflated.LayoutInflatedParam; import de.robv.android.xposed.callbacks.XCallback; +import xposed.dummy.XResourcesSuperClass; +import xposed.dummy.XTypedArraySuperClass; import static de.robv.android.xposed.XposedHelpers.decrementMethodDepth; import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; @@ -52,7 +51,7 @@ * be set using the methods made available via the API methods in this class. */ @SuppressWarnings("JniMissingFunction") -public class XResources extends Resources { +public class XResources extends XResourcesSuperClass { private static final SparseArray> sReplacements = new SparseArray<>(); private static final SparseArray> sResourceNames = new SparseArray<>(); @@ -80,10 +79,6 @@ protected LinkedList initialValue() { private String mResDir; private String mPackageName; - public XResources(AssetManager assets, DisplayMetrics metrics, Configuration config) { - super(assets, metrics, config); - } - public XResources(ClassLoader classLoader) { super(classLoader); } @@ -1136,9 +1131,7 @@ private static boolean isXmlCached(Resources res, int id) { return false; } - private static void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) { - EdXpConfigGlobal.getHookProvider().rewriteXmlReferencesNative(parserPtr, origRes, repRes); - } + private static native void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes); /** * Used to replace reference IDs in XMLs. @@ -1263,7 +1256,7 @@ private static int translateAttrId(String attrName, XResources origRes) { * Mainly used when inflating layouts. * @hide */ - public static class XTypedArray extends TypedArray { + public static class XTypedArray extends XTypedArraySuperClass { public XTypedArray(Resources resources) { super(resources); diff --git a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfigGlobal.java b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfigGlobal.java index 6ae7370ae..679920b57 100644 --- a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfigGlobal.java +++ b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfigGlobal.java @@ -1,15 +1,7 @@ package com.elderdrivers.riru.edxp.config; -import android.content.res.Resources; -import android.content.res.XResources; - import com.elderdrivers.riru.edxp.hook.HookProvider; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Member; - -import de.robv.android.xposed.XposedBridge; - public class EdXpConfigGlobal { public static volatile EdXpConfig sConfig; @@ -24,7 +16,7 @@ public static EdXpConfig getConfig() { public static HookProvider getHookProvider() { if (sHookProvider == null) { - return defaultHookProvider; + throw new IllegalArgumentException("sHookProvider should not be null."); } return sHookProvider; } @@ -47,59 +39,4 @@ public boolean isDynamicModulesMode() { return false; } }; - - - private static final HookProvider defaultHookProvider = new HookProvider() { - - @Override - public void hookMethod(Member method, XposedBridge.AdditionalHookInfo additionalInfo) { - - } - - @Override - public void unhookMethod(Member method) { - - } - - @Override - public Object invokeOriginalMethod(Member method, long methodId, Object thisObject, Object[] args) - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - return null; - } - - @Override - public Member findMethodNative(Member hookMethod) { - return hookMethod; - } - - @Override - public void deoptMethods(String packageName, ClassLoader classLoader) { - - } - - @Override - public long getMethodId(Member member) { - return 0; - } - - @Override - public Object findMethodNative(Class clazz, String methodName, String methodSig) { - return null; - } - - @Override - public void deoptMethodNative(Object method) { - - } - - @Override - public boolean initXResourcesNative() { - return false; - } - - @Override - public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) { - - } - }; } diff --git a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/hook/HookProvider.java b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/hook/HookProvider.java index a8fccd787..2a5539c69 100644 --- a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/hook/HookProvider.java +++ b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/hook/HookProvider.java @@ -1,8 +1,5 @@ package com.elderdrivers.riru.edxp.hook; -import android.content.res.Resources; -import android.content.res.XResources; - import java.lang.reflect.Member; import de.robv.android.xposed.XposedBridge; @@ -27,5 +24,5 @@ public interface HookProvider { boolean initXResourcesNative(); - void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes); + boolean removeFinalFlagNative(Class clazz); } diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java index d17111700..3a4665e82 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -1,29 +1,33 @@ package de.robv.android.xposed; -import android.annotation.SuppressLint; +import android.content.res.Resources; +import android.content.res.TypedArray; import android.util.Log; import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; -import java.io.File; -import java.io.IOException; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.nio.ByteBuffer; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import dalvik.system.InMemoryDexClassLoader; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.callbacks.XC_InitPackageResources; import de.robv.android.xposed.callbacks.XC_LoadPackage; +import external.com.android.dx.DexMaker; +import external.com.android.dx.TypeId; import static de.robv.android.xposed.XposedHelpers.getIntField; +import static de.robv.android.xposed.XposedHelpers.setObjectField; /** * This class contains most of Xposed's central logic, such as initialization and callbacks used by @@ -83,16 +87,52 @@ public static void main(String[] args) { // } // } - private static void initXResources() throws IOException { - // ed: no support for now - } + public static volatile ClassLoader dummyClassLoader = null; - @SuppressLint("SetWorldReadable") - private static File ensureSuperDexFile(String clz, Class realSuperClz, Class topClz) throws IOException { - XposedBridge.removeFinalFlagNative(realSuperClz); - File dexFile = DexCreator.ensure(clz, realSuperClz, topClz); - dexFile.setReadable(true, false); - return dexFile; + public static void initXResources() { + if (disableHooks) { + return; + } + String BASE_DIR = EdXpConfigGlobal.getConfig().getInstallerBaseDir(); + if (SELinuxHelper.getAppDataFileService().checkFileExists(BASE_DIR + "conf/disable_resources")) { + Log.w(TAG, "Found " + BASE_DIR + "conf/disable_resources, not hooking resources"); + XposedInit.disableResources = true; + return; + } + if (dummyClassLoader != null) { + return; + } + try { + Resources res = Resources.getSystem(); + Class resClass = res.getClass(); + Class taClass = TypedArray.class; + try { + TypedArray ta = res.obtainTypedArray(res.getIdentifier( + "preloaded_drawables", "array", "android")); + taClass = ta.getClass(); + ta.recycle(); + } catch (Resources.NotFoundException nfe) { + XposedBridge.log(nfe); + } + XposedBridge.removeFinalFlagNative(resClass); + XposedBridge.removeFinalFlagNative(taClass); + DexMaker dexMaker = new DexMaker(); + dexMaker.declare(TypeId.get("Lxposed/dummy/XResourcesSuperClass;"), + "XResourcesSuperClass.java", + Modifier.PUBLIC, TypeId.get(resClass)); + dexMaker.declare(TypeId.get("Lxposed/dummy/XTypedArraySuperClass;"), + "XTypedArraySuperClass.java", + Modifier.PUBLIC, TypeId.get(taClass)); + ClassLoader myCL = XposedBridge.class.getClassLoader(); + dummyClassLoader = new InMemoryDexClassLoader( + ByteBuffer.wrap(dexMaker.generate()), myCL.getParent()); + dummyClassLoader.loadClass("xposed.dummy.XResourcesSuperClass"); + dummyClassLoader.loadClass("xposed.dummy.XTypedArraySuperClass"); + setObjectField(myCL, "parent", dummyClassLoader); + } catch (Throwable throwable) { + XposedBridge.log(throwable); + XposedInit.disableResources = true; + } } // private static boolean hadInitErrors() { @@ -478,7 +518,9 @@ public static Object invokeOriginalMethod(Member method, Object thisObject, Obje private static native Object cloneToSubclassNative(Object obj, Class targetClazz); - private static native void removeFinalFlagNative(Class clazz); + private static void removeFinalFlagNative(Class clazz) { + EdXpConfigGlobal.getHookProvider().removeFinalFlagNative(clazz); + } // /*package*/ static native void closeFilesBeforeForkNative(); // /*package*/ static native void reopenFilesAfterForkNative(); diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java index 4a2d5b87d..bfe5184a3 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java @@ -57,8 +57,7 @@ public final class XposedInit { private static final String startClassName = ""; // ed: no support for tool process anymore private static final String INSTANT_RUN_CLASS = "com.android.tools.fd.runtime.BootstrapApplication"; - // TODO not supported yet - private static boolean disableResources = false; + public static boolean disableResources = false; private static final String[] XRESOURCES_CONFLICTING_PACKAGES = {"com.sygic.aura"}; private XposedInit() { @@ -82,20 +81,15 @@ public static void initForZygote(boolean isSystem) throws Throwable { } catch (NoSuchFieldError ignored) { } } - findAndHookMethod("android.app.ApplicationPackageManager", null, "getResourcesForApplication", - ApplicationInfo.class, new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - ApplicationInfo app = (ApplicationInfo) param.args[0]; - XResources.setPackageNameForResDir(app.packageName, - app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir); - } - }); + hookResources(); } - /*package*/ - public static void hookResources() throws Throwable { + private static void hookResources() throws Throwable { + + if (disableResources) { + return; + } String BASE_DIR = EdXpConfigGlobal.getConfig().getInstallerBaseDir(); @@ -111,6 +105,16 @@ public static void hookResources() throws Throwable { return; } + findAndHookMethod("android.app.ApplicationPackageManager", null, "getResourcesForApplication", + ApplicationInfo.class, new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + ApplicationInfo app = (ApplicationInfo) param.args[0]; + XResources.setPackageNameForResDir(app.packageName, + app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir); + } + }); + /* * getTopLevelResources(a) * -> getTopLevelResources(b)