Merge pull request #228 from ElderDrivers/resources-hook
Resources hook for ROMs with custom Resources subclass
This commit is contained in:
commit
71449e2946
|
|
@ -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 abstract class BaseHookProvider implements HookProvider {
|
|||
public boolean initXResourcesNative() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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", "<init>", "(Ljava/lang/ClassLoader;)V"},
|
||||
{"android.content.res.MiuiResources", "<init>", "()V"},
|
||||
{"android.content.res.MiuiResources", "<init>", "(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 = {};
|
||||
|
|
|
|||
|
|
@ -19,8 +19,12 @@ public class PrebuiltMethodsDeopter {
|
|||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
/libs
|
||||
/obj
|
||||
/release
|
||||
/template_override/module.prop
|
||||
/template_override/riru_module.prop
|
||||
/template_override/system
|
||||
/template_override/system_x86
|
||||
*.iml
|
||||
|
|
@ -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(" ")
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
version=90.0-0.4.0.1-beta-SNAPSHOT ($backend)
|
||||
arch=arm64
|
||||
minsdk=23
|
||||
maxsdk=28
|
||||
requires:fbe_aware=1
|
||||
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <include/ByteOrder.h>
|
||||
#include <include/logging.h>
|
||||
#include <dlfcn.h>
|
||||
#include <java_hook/java_hook.h>
|
||||
#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<jclass>(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) {
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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 "************************************"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
version=90.0-$version ($backend)
|
||||
arch=arm64
|
||||
minsdk=26
|
||||
maxsdk=28
|
||||
requires:fbe_aware=1
|
||||
|
|
@ -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
|
||||
|
|
@ -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 class Main implements KeepAll {
|
|||
|
||||
public static native boolean initXResourcesNative();
|
||||
|
||||
public static native void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes);
|
||||
public static native boolean removeFinalFlagNative(Class clazz);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 class SandHookProvider extends BaseHookProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) {
|
||||
Main.rewriteXmlReferencesNative(parserPtr, origRes, repRes);
|
||||
public boolean removeFinalFlagNative(Class clazz) {
|
||||
return Main.removeFinalFlagNative(clazz);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.SysInnerHookInfo;
|
|||
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 class Router {
|
|||
}
|
||||
}
|
||||
|
||||
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 class Router {
|
|||
public static void injectConfig() {
|
||||
EdXpConfigGlobal.sConfig = new SandHookEdxpConfig();
|
||||
EdXpConfigGlobal.sHookProvider = new SandHookProvider();
|
||||
XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@ package com.elderdrivers.riru.edxp.sandhook.proxy;
|
|||
|
||||
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 class BlackWhiteListProxy {
|
|||
* 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 @@ public class BlackWhiteListProxy {
|
|||
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) {
|
||||
|
|
|
|||
|
|
@ -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 class NormalProxy {
|
|||
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 class NormalProxy {
|
|||
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 class NormalProxy {
|
|||
Router.onEnterChildProcess();
|
||||
// reload module list if dynamic mode is on
|
||||
Router.loadModulesSafely(false);
|
||||
Router.onForkFinish();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 class Main implements KeepAll {
|
|||
|
||||
public static native boolean initXResourcesNative();
|
||||
|
||||
public static native void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes);
|
||||
public static native boolean removeFinalFlagNative(Class clazz);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 class WhaleHookProvider extends BaseHookProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) {
|
||||
Main.rewriteXmlReferencesNative(parserPtr, origRes, repRes);
|
||||
public boolean removeFinalFlagNative(Class clazz) {
|
||||
return Main.removeFinalFlagNative(clazz);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import android.text.TextUtils;
|
|||
|
||||
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 class Router {
|
|||
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 class Router {
|
|||
public static void injectConfig() {
|
||||
EdXpConfigGlobal.sConfig = new WhaleEdxpConfig();
|
||||
EdXpConfigGlobal.sHookProvider = new WhaleHookProvider();
|
||||
XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ public class BlackWhiteListProxy {
|
|||
* 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 @@ public class BlackWhiteListProxy {
|
|||
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) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ public class NormalProxy {
|
|||
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 class NormalProxy {
|
|||
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 class NormalProxy {
|
|||
Router.onEnterChildProcess();
|
||||
// reload module list if dynamic mode is on
|
||||
Router.loadModulesSafely(false);
|
||||
Router.onForkFinish();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,5 +143,5 @@ public class Main implements KeepAll {
|
|||
|
||||
public static native boolean initXResourcesNative();
|
||||
|
||||
public static native void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes);
|
||||
public static native boolean removeFinalFlagNative(Class clazz);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 class YahfaHookProvider extends BaseHookProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) {
|
||||
Main.rewriteXmlReferencesNative(parserPtr, origRes, repRes);
|
||||
public boolean removeFinalFlagNative(Class clazz) {
|
||||
return Main.removeFinalFlagNative(clazz);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.elderdrivers.riru.edxp.yahfa.entry;
|
|||
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 class Router {
|
|||
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 class Router {
|
|||
public static void injectConfig() {
|
||||
EdXpConfigGlobal.sConfig = new YahfaEdxpConfig();
|
||||
EdXpConfigGlobal.sHookProvider = new YahfaHookProvider();
|
||||
XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ 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.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 class BlackWhiteListProxy {
|
|||
* 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 @@ public class BlackWhiteListProxy {
|
|||
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) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ public class NormalProxy {
|
|||
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 class NormalProxy {
|
|||
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 class NormalProxy {
|
|||
Router.onEnterChildProcess();
|
||||
// reload module list if dynamic mode is on
|
||||
Router.loadModulesSafely(false);
|
||||
Router.onForkFinish();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -16,4 +16,9 @@ public class XResourcesSuperClass extends Resources {
|
|||
super(null, null, null);
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected XResourcesSuperClass(ClassLoader classLoader) {
|
||||
super(classLoader);
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ import android.content.res.TypedArray;
|
|||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ android {
|
|||
buildToolsVersion '28.0.3'
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 23
|
||||
minSdkVersion 26
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
|
|
|||
|
|
@ -11,15 +11,12 @@ import android.os.Build;
|
|||
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.XposedBridge.CopyOnWriteSortedSet;
|
|||
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 @@ import static de.robv.android.xposed.XposedHelpers.incrementMethodDepth;
|
|||
* 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<HashMap<String, Object>> sReplacements = new SparseArray<>();
|
||||
private static final SparseArray<HashMap<String, ResourceNames>> sResourceNames = new SparseArray<>();
|
||||
|
||||
|
|
@ -80,10 +79,6 @@ public class XResources extends Resources {
|
|||
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 @@ public class XResources extends Resources {
|
|||
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 @@ public class XResources extends Resources {
|
|||
* Mainly used when inflating layouts.
|
||||
* @hide
|
||||
*/
|
||||
public static class XTypedArray extends TypedArray {
|
||||
public static class XTypedArray extends XTypedArraySuperClass {
|
||||
|
||||
public XTypedArray(Resources resources) {
|
||||
super(resources);
|
||||
|
|
|
|||
|
|
@ -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 class EdXpConfigGlobal {
|
|||
|
||||
public static HookProvider getHookProvider() {
|
||||
if (sHookProvider == null) {
|
||||
return defaultHookProvider;
|
||||
throw new IllegalArgumentException("sHookProvider should not be null.");
|
||||
}
|
||||
return sHookProvider;
|
||||
}
|
||||
|
|
@ -47,59 +39,4 @@ public class EdXpConfigGlobal {
|
|||
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) {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 final class XposedBridge {
|
|||
// }
|
||||
// }
|
||||
|
||||
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 final class XposedBridge {
|
|||
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -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 final class XposedInit {
|
|||
} 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 final class XposedInit {
|
|||
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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue