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;
|
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.deopt.PrebuiltMethodsDeopter;
|
||||||
import com.elderdrivers.riru.edxp.hook.HookProvider;
|
import com.elderdrivers.riru.edxp.hook.HookProvider;
|
||||||
|
|
||||||
|
|
@ -40,9 +37,4 @@ public abstract class BaseHookProvider implements HookProvider {
|
||||||
public boolean initXResourcesNative() {
|
public boolean initXResourcesNative() {
|
||||||
return false;
|
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 = {
|
private static final String[][] BOOT_IMAGE = {
|
||||||
// callers of Application#attach(Context)
|
// 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 = {};
|
private static final String[][] SYSTEM_SERVER = {};
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,12 @@ public class PrebuiltMethodsDeopter {
|
||||||
}
|
}
|
||||||
for (String[] caller : callers) {
|
for (String[] caller : callers) {
|
||||||
try {
|
try {
|
||||||
|
Class clazz = XposedHelpers.findClassIfExists(caller[0], cl);
|
||||||
|
if (clazz == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Object method = EdXpConfigGlobal.getHookProvider().findMethodNative(
|
Object method = EdXpConfigGlobal.getHookProvider().findMethodNative(
|
||||||
XposedHelpers.findClass(caller[0], cl), caller[1], caller[2]);
|
clazz, caller[1], caller[2]);
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
EdXpConfigGlobal.getHookProvider().deoptMethodNative(method);
|
EdXpConfigGlobal.getHookProvider().deoptMethodNative(method);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
/libs
|
/libs
|
||||||
/obj
|
/obj
|
||||||
/release
|
/release
|
||||||
|
/template_override/module.prop
|
||||||
|
/template_override/riru_module.prop
|
||||||
/template_override/system
|
/template_override/system
|
||||||
/template_override/system_x86
|
/template_override/system_x86
|
||||||
*.iml
|
*.iml
|
||||||
|
|
@ -2,13 +2,17 @@ import org.gradle.internal.os.OperatingSystem
|
||||||
|
|
||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
version "v0.4.0.1_beta-SNAPSHOT"
|
version "v0.4.1.2_beta"
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
|
versionCode = "4120"
|
||||||
module_name = "EdXposed"
|
module_name = "EdXposed"
|
||||||
jar_dest_dir = "${projectDir}/template_override/system/framework/"
|
jar_dest_dir = "${projectDir}/template_override/system/framework/"
|
||||||
is_windows = OperatingSystem.current().isWindows()
|
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 {
|
android {
|
||||||
|
|
@ -72,21 +76,34 @@ afterEvaluate {
|
||||||
|
|
||||||
backends.each { backend ->
|
backends.each { backend ->
|
||||||
|
|
||||||
def backendCapped = backend.capitalize()
|
|
||||||
def backendLowered = backend.toLowerCase()
|
def backendLowered = backend.toLowerCase()
|
||||||
|
def backendCapped = backendLowered.capitalize()
|
||||||
|
def authorList = property("${backendLowered}" + "_authors")
|
||||||
|
|
||||||
def zipTask = task("zip${backendCapped}${variantCapped}", type: Exec) {
|
def zipTask = task("zip${backendCapped}${variantCapped}", type: Exec) {
|
||||||
dependsOn cleanTemplate, copyDalvikdxJar, copyDexmakerJar
|
dependsOn cleanTemplate, copyDalvikdxJar, copyDexmakerJar
|
||||||
dependsOn tasks.getByPath(":edxp-${backendLowered}:makeAndCopy${variantCapped}")
|
dependsOn tasks.getByPath(":edxp-${backendLowered}:makeAndCopy${variantCapped}")
|
||||||
workingDir '..'
|
workingDir '..'
|
||||||
commandLine 'sh', 'build.sh', project.name,
|
commandLine 'sh', 'build.sh', project.name,
|
||||||
"${backendLowered}-${project.version}-${variantLowered}", "${module_name}"
|
"${backend}-${project.version}-${variantLowered}", "${module_name}"
|
||||||
doFirst {
|
doFirst {
|
||||||
copy {
|
copy {
|
||||||
from "${projectDir}/edconfig.tpl"
|
from "${projectDir}/tpl/edconfig.tpl"
|
||||||
into templateFrameworkPath
|
into templateFrameworkPath
|
||||||
rename "edconfig.tpl", "edconfig.jar"
|
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
|
dependsOn zipTask
|
||||||
workingDir "${projectDir}/release"
|
workingDir "${projectDir}/release"
|
||||||
def commands = ["adb", "push",
|
def commands = ["adb", "push",
|
||||||
"magisk-${module_name}-${backendLowered}-${project.version}-${variantLowered}.zip",
|
"magisk-${module_name}-${backend}-${project.version}-${variantLowered}.zip",
|
||||||
"/sdcard/"]
|
"/sdcard/"]
|
||||||
if (is_windows) {
|
if (is_windows) {
|
||||||
commandLine 'cmd', '/c', commands.join(" ")
|
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);
|
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[] = {
|
static JNINativeMethod hookMethods[] = {
|
||||||
{
|
{
|
||||||
"init",
|
"init",
|
||||||
|
|
@ -131,7 +144,7 @@ static JNINativeMethod hookMethods[] = {
|
||||||
"initXResourcesNative", "()Z", (void *) XposedBridge_initXResourcesNative
|
"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) {
|
|| strstr(thatDesc, "com/elderdrivers/riru/") != nullptr) {
|
||||||
return true;
|
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);
|
return (*isInSamePackageBackup)(thiz, that);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <include/ByteOrder.h>
|
#include <include/ByteOrder.h>
|
||||||
#include <include/logging.h>
|
#include <include/logging.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <java_hook/java_hook.h>
|
||||||
#include "resource_hook.h"
|
#include "resource_hook.h"
|
||||||
|
|
||||||
#define CLASS_XRESOURCES "android/content/res/XResources"
|
#define CLASS_XRESOURCES "android/content/res/XResources"
|
||||||
|
|
@ -44,7 +45,7 @@ bool prepareSymbols() {
|
||||||
#if defined(__LP64__)
|
#if defined(__LP64__)
|
||||||
"_ZNK7android12ResXMLParser18getAttributeNameIDEm"
|
"_ZNK7android12ResXMLParser18getAttributeNameIDEm"
|
||||||
#else
|
#else
|
||||||
"_ZNK7android12ResXMLParser18getAttributeNameIDEj"
|
"_ZNK7android12ResXMLParser18getAttributeNameIDEj"
|
||||||
#endif
|
#endif
|
||||||
));
|
));
|
||||||
if (!ResXMLParser_getAttributeNameID) {
|
if (!ResXMLParser_getAttributeNameID) {
|
||||||
|
|
@ -66,6 +67,15 @@ bool prepareSymbols() {
|
||||||
return true;
|
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) {
|
jboolean XposedBridge_initXResourcesNative(JNIEnv *env, jclass) {
|
||||||
classXResources = env->FindClass(CLASS_XRESOURCES);
|
classXResources = env->FindClass(CLASS_XRESOURCES);
|
||||||
if (classXResources == NULL) {
|
if (classXResources == NULL) {
|
||||||
|
|
@ -75,6 +85,12 @@ jboolean XposedBridge_initXResourcesNative(JNIEnv *env, jclass) {
|
||||||
}
|
}
|
||||||
classXResources = reinterpret_cast<jclass>(env->NewGlobalRef(classXResources));
|
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",
|
methodXResourcesTranslateResId = env->GetStaticMethodID(classXResources, "translateResId",
|
||||||
"(ILandroid/content/res/XResources;Landroid/content/res/Resources;)I");
|
"(ILandroid/content/res/XResources;Landroid/content/res/Resources;)I");
|
||||||
if (methodXResourcesTranslateResId == NULL) {
|
if (methodXResourcesTranslateResId == NULL) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#!/system/bin/sh
|
#!/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`
|
ANDROID_SDK=`getprop ro.build.version.sdk`
|
||||||
BUILD_DESC=`getprop ro.build.description`
|
BUILD_DESC=`getprop ro.build.description`
|
||||||
PRODUCT=`getprop ro.build.product`
|
PRODUCT=`getprop ro.build.product`
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ LATESTARTSERVICE=false
|
||||||
|
|
||||||
print_modname() {
|
print_modname() {
|
||||||
ui_print "************************************"
|
ui_print "************************************"
|
||||||
ui_print " Riru - Ed Xposed v0.4.0.1 "
|
ui_print " Riru - Ed Xposed "
|
||||||
ui_print "************************************"
|
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
|
id=riru_edxposed
|
||||||
name=Riru - Ed Xposed
|
name=Riru - Ed Xposed
|
||||||
version=v0.4.0.1_beta-SNAPSHOT
|
version=${versionName}
|
||||||
versionCode=4010
|
versionCode=${versionCode}
|
||||||
author=solohsu & MlgmXyysd
|
author=${authorList}
|
||||||
description=Magisk version of Xposed. Require Riru - Core installed.
|
description=Magisk version of Xposed. Require Riru - Core installed.
|
||||||
minMagisk=17000
|
minMagisk=17000
|
||||||
|
|
@ -1,19 +1,17 @@
|
||||||
package com.elderdrivers.riru.edxp;
|
package com.elderdrivers.riru.edxp;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.res.XResources;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
|
|
||||||
import com.elderdrivers.riru.common.KeepAll;
|
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.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.core.HookMethodResolver;
|
||||||
import com.elderdrivers.riru.edxp.sandhook.entry.Router;
|
import com.elderdrivers.riru.edxp.sandhook.entry.Router;
|
||||||
import com.elderdrivers.riru.edxp.sandhook.proxy.BlackWhiteListProxy;
|
import com.elderdrivers.riru.edxp.sandhook.proxy.BlackWhiteListProxy;
|
||||||
import com.elderdrivers.riru.edxp.sandhook.proxy.NormalProxy;
|
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.XposedCompat;
|
||||||
import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge;
|
import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge;
|
||||||
|
|
||||||
|
|
@ -152,5 +150,5 @@ public class Main implements KeepAll {
|
||||||
|
|
||||||
public static native boolean initXResourcesNative();
|
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;
|
package com.elderdrivers.riru.edxp.sandhook.config;
|
||||||
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.res.XResources;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.elderdrivers.riru.edxp.Main;
|
import com.elderdrivers.riru.edxp.Main;
|
||||||
|
|
@ -67,7 +65,7 @@ public class SandHookProvider extends BaseHookProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) {
|
public boolean removeFinalFlagNative(Class clazz) {
|
||||||
Main.rewriteXmlReferencesNative(parserPtr, origRes, repRes);
|
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.bootstrap.WorkAroundHookInfo;
|
||||||
import com.elderdrivers.riru.edxp.sandhook.entry.hooker.SystemMainHooker;
|
import com.elderdrivers.riru.edxp.sandhook.entry.hooker.SystemMainHooker;
|
||||||
import com.elderdrivers.riru.edxp.util.Utils;
|
import com.elderdrivers.riru.edxp.util.Utils;
|
||||||
import com.swift.sandhook.SandHookConfig;
|
|
||||||
import com.swift.sandhook.xposedcompat.XposedCompat;
|
import com.swift.sandhook.xposedcompat.XposedCompat;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
@ -32,10 +31,14 @@ public class Router {
|
||||||
|
|
||||||
static boolean useSandHook = false;
|
static boolean useSandHook = false;
|
||||||
|
|
||||||
|
public static void initResourcesHook() {
|
||||||
|
startWorkAroundHook(); // for OnePlus devices
|
||||||
|
XposedBridge.initXResources();
|
||||||
|
}
|
||||||
|
|
||||||
public static void prepare(boolean isSystem) {
|
public static void prepare(boolean isSystem) {
|
||||||
// this flag is needed when loadModules
|
// this flag is needed when loadModules
|
||||||
startsSystemServer = isSystem;
|
startsSystemServer = isSystem;
|
||||||
// InstallerChooser.setup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkHookState(String appDataDir) {
|
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;
|
forkCompleted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onEnterChildProcess() {
|
||||||
DynamicBridge.onForkPost();
|
DynamicBridge.onForkPost();
|
||||||
//enable compile in child process
|
//enable compile in child process
|
||||||
//SandHook.enableCompiler(!XposedInit.startsSystemServer);
|
//SandHook.enableCompiler(!XposedInit.startsSystemServer);
|
||||||
|
|
@ -144,5 +154,6 @@ public class Router {
|
||||||
public static void injectConfig() {
|
public static void injectConfig() {
|
||||||
EdXpConfigGlobal.sConfig = new SandHookEdxpConfig();
|
EdXpConfigGlobal.sConfig = new SandHookEdxpConfig();
|
||||||
EdXpConfigGlobal.sHookProvider = new SandHookProvider();
|
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 android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.elderdrivers.riru.edxp.Main;
|
||||||
import com.elderdrivers.riru.edxp.config.ConfigManager;
|
import com.elderdrivers.riru.edxp.config.ConfigManager;
|
||||||
import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter;
|
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.ProcessUtils;
|
||||||
import com.elderdrivers.riru.edxp.util.Utils;
|
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 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.Main.isAppNeedHook;
|
||||||
|
import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1. Non dynamic mode
|
* 1. Non dynamic mode
|
||||||
|
|
@ -73,6 +73,8 @@ public class BlackWhiteListProxy {
|
||||||
* Some details are different between main zygote and secondary zygote.
|
* Some details are different between main zygote and secondary zygote.
|
||||||
*/
|
*/
|
||||||
private static void onForkPreForNonDynamicMode(boolean isSystemServer) {
|
private static void onForkPreForNonDynamicMode(boolean isSystemServer) {
|
||||||
|
Router.onForkStart();
|
||||||
|
Router.initResourcesHook();
|
||||||
ConfigManager.setDynamicModulesMode(false);
|
ConfigManager.setDynamicModulesMode(false);
|
||||||
// set startsSystemServer flag used when loadModules
|
// set startsSystemServer flag used when loadModules
|
||||||
Router.prepare(isSystemServer);
|
Router.prepare(isSystemServer);
|
||||||
|
|
@ -92,20 +94,25 @@ public class BlackWhiteListProxy {
|
||||||
Main.niceName = niceName;
|
Main.niceName = niceName;
|
||||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
Router.onEnterChildProcess();
|
|
||||||
if (!isDynamicModulesMode) {
|
if (!isDynamicModulesMode) {
|
||||||
Main.reopenFilesAfterForkNative();
|
Main.reopenFilesAfterForkNative();
|
||||||
}
|
}
|
||||||
|
Router.onEnterChildProcess();
|
||||||
if (!checkNeedHook(appDataDir, niceName)) {
|
if (!checkNeedHook(appDataDir, niceName)) {
|
||||||
// if is blacklisted, just stop here
|
// if is blacklisted, just stop here
|
||||||
|
Router.onForkFinish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isDynamicModulesMode) {
|
||||||
|
Router.initResourcesHook();
|
||||||
|
}
|
||||||
Router.prepare(isSystemServer);
|
Router.prepare(isSystemServer);
|
||||||
PrebuiltMethodsDeopter.deoptBootMethods();
|
PrebuiltMethodsDeopter.deoptBootMethods();
|
||||||
Router.installBootstrapHooks(isSystemServer);
|
Router.installBootstrapHooks(isSystemServer);
|
||||||
if (isDynamicModulesMode) {
|
if (isDynamicModulesMode) {
|
||||||
Router.loadModulesSafely(false);
|
Router.loadModulesSafely(false);
|
||||||
}
|
}
|
||||||
|
Router.onForkFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkNeedHook(String appDataDir, String niceName) {
|
private static boolean checkNeedHook(String appDataDir, String niceName) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.elderdrivers.riru.edxp.sandhook.proxy;
|
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.Main;
|
||||||
|
import com.elderdrivers.riru.edxp.config.ConfigManager;
|
||||||
import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter;
|
import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter;
|
||||||
import com.elderdrivers.riru.edxp.sandhook.entry.Router;
|
import com.elderdrivers.riru.edxp.sandhook.entry.Router;
|
||||||
|
|
||||||
|
|
@ -15,6 +15,8 @@ public class NormalProxy {
|
||||||
boolean startChildZygote, String instructionSet,
|
boolean startChildZygote, String instructionSet,
|
||||||
String appDataDir) {
|
String appDataDir) {
|
||||||
// mainly for secondary zygote
|
// mainly for secondary zygote
|
||||||
|
Router.onForkStart();
|
||||||
|
Router.initResourcesHook();
|
||||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
// call this to ensure the flag is set to false ASAP
|
// call this to ensure the flag is set to false ASAP
|
||||||
|
|
@ -36,10 +38,13 @@ public class NormalProxy {
|
||||||
Router.onEnterChildProcess();
|
Router.onEnterChildProcess();
|
||||||
// load modules for each app process on its forked if dynamic modules mode is on
|
// load modules for each app process on its forked if dynamic modules mode is on
|
||||||
Router.loadModulesSafely(false);
|
Router.loadModulesSafely(false);
|
||||||
|
Router.onForkFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
||||||
long permittedCapabilities, long effectiveCapabilities) {
|
long permittedCapabilities, long effectiveCapabilities) {
|
||||||
|
Router.onForkStart();
|
||||||
|
Router.initResourcesHook();
|
||||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
// set startsSystemServer flag used when loadModules
|
// set startsSystemServer flag used when loadModules
|
||||||
|
|
@ -65,6 +70,7 @@ public class NormalProxy {
|
||||||
Router.onEnterChildProcess();
|
Router.onEnterChildProcess();
|
||||||
// reload module list if dynamic mode is on
|
// reload module list if dynamic mode is on
|
||||||
Router.loadModulesSafely(false);
|
Router.loadModulesSafely(false);
|
||||||
|
Router.onForkFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
package com.elderdrivers.riru.edxp;
|
package com.elderdrivers.riru.edxp;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.res.XResources;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
|
|
||||||
import com.elderdrivers.riru.common.KeepAll;
|
import com.elderdrivers.riru.common.KeepAll;
|
||||||
import com.elderdrivers.riru.edxp.config.InstallerChooser;
|
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.core.HookMethodResolver;
|
||||||
import com.elderdrivers.riru.edxp.whale.entry.Router;
|
import com.elderdrivers.riru.edxp.whale.entry.Router;
|
||||||
import com.elderdrivers.riru.edxp.whale.proxy.BlackWhiteListProxy;
|
import com.elderdrivers.riru.edxp.whale.proxy.BlackWhiteListProxy;
|
||||||
import com.elderdrivers.riru.edxp.whale.proxy.NormalProxy;
|
import com.elderdrivers.riru.edxp.whale.proxy.NormalProxy;
|
||||||
import com.elderdrivers.riru.edxp.util.Utils;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -143,5 +141,5 @@ public class Main implements KeepAll {
|
||||||
|
|
||||||
public static native boolean initXResourcesNative();
|
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;
|
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.Main;
|
||||||
import com.elderdrivers.riru.edxp.config.BaseHookProvider;
|
import com.elderdrivers.riru.edxp.config.BaseHookProvider;
|
||||||
import com.lody.whale.WhaleRuntime;
|
import com.lody.whale.WhaleRuntime;
|
||||||
|
|
@ -64,7 +61,7 @@ public class WhaleHookProvider extends BaseHookProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) {
|
public boolean removeFinalFlagNative(Class clazz) {
|
||||||
Main.rewriteXmlReferencesNative(parserPtr, origRes, repRes);
|
return Main.removeFinalFlagNative(clazz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import android.text.TextUtils;
|
||||||
|
|
||||||
import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
|
import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
|
||||||
import com.elderdrivers.riru.edxp.util.Utils;
|
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.WhaleEdxpConfig;
|
||||||
|
import com.elderdrivers.riru.edxp.whale.config.WhaleHookProvider;
|
||||||
import com.elderdrivers.riru.edxp.whale.core.HookMain;
|
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.AppBootstrapHookInfo;
|
||||||
import com.elderdrivers.riru.edxp.whale.entry.bootstrap.SysBootstrapHookInfo;
|
import com.elderdrivers.riru.edxp.whale.entry.bootstrap.SysBootstrapHookInfo;
|
||||||
|
|
@ -25,11 +25,14 @@ public class Router {
|
||||||
|
|
||||||
private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false);
|
private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
public static void initResourcesHook() {
|
||||||
|
startWorkAroundHook(); // for OnePlus devices
|
||||||
|
XposedBridge.initXResources();
|
||||||
|
}
|
||||||
|
|
||||||
public static void prepare(boolean isSystem) {
|
public static void prepare(boolean isSystem) {
|
||||||
// this flag is needed when loadModules
|
// this flag is needed when loadModules
|
||||||
XposedInit.startsSystemServer = isSystem;
|
XposedInit.startsSystemServer = isSystem;
|
||||||
// InstallerChooser.setup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkHookState(String appDataDir) {
|
public static void checkHookState(String appDataDir) {
|
||||||
|
|
@ -101,10 +104,18 @@ public class Router {
|
||||||
WorkAroundHookInfo.class.getName());
|
WorkAroundHookInfo.class.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onEnterChildProcess() {
|
public static void onForkStart() {
|
||||||
|
forkCompleted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onForkFinish() {
|
||||||
forkCompleted = true;
|
forkCompleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void onEnterChildProcess() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static void logD(String prefix) {
|
public static void logD(String prefix) {
|
||||||
Utils.logD(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(),
|
Utils.logD(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(),
|
||||||
AndroidAppHelper.currentProcessName()));
|
AndroidAppHelper.currentProcessName()));
|
||||||
|
|
@ -118,5 +129,6 @@ public class Router {
|
||||||
public static void injectConfig() {
|
public static void injectConfig() {
|
||||||
EdXpConfigGlobal.sConfig = new WhaleEdxpConfig();
|
EdXpConfigGlobal.sConfig = new WhaleEdxpConfig();
|
||||||
EdXpConfigGlobal.sHookProvider = new WhaleHookProvider();
|
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.
|
* Some details are different between main zygote and secondary zygote.
|
||||||
*/
|
*/
|
||||||
private static void onForkPreForNonDynamicMode(boolean isSystemServer) {
|
private static void onForkPreForNonDynamicMode(boolean isSystemServer) {
|
||||||
|
Router.onForkStart();
|
||||||
|
Router.initResourcesHook();
|
||||||
ConfigManager.setDynamicModulesMode(false);
|
ConfigManager.setDynamicModulesMode(false);
|
||||||
// set startsSystemServer flag used when loadModules
|
// set startsSystemServer flag used when loadModules
|
||||||
Router.prepare(isSystemServer);
|
Router.prepare(isSystemServer);
|
||||||
|
|
@ -92,20 +94,25 @@ public class BlackWhiteListProxy {
|
||||||
Main.niceName = niceName;
|
Main.niceName = niceName;
|
||||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
Router.onEnterChildProcess();
|
|
||||||
if (!isDynamicModulesMode) {
|
if (!isDynamicModulesMode) {
|
||||||
Main.reopenFilesAfterForkNative();
|
Main.reopenFilesAfterForkNative();
|
||||||
}
|
}
|
||||||
|
Router.onEnterChildProcess();
|
||||||
if (!checkNeedHook(appDataDir, niceName)) {
|
if (!checkNeedHook(appDataDir, niceName)) {
|
||||||
// if is blacklisted, just stop here
|
// if is blacklisted, just stop here
|
||||||
|
Router.onForkFinish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isDynamicModulesMode) {
|
||||||
|
Router.initResourcesHook();
|
||||||
|
}
|
||||||
Router.prepare(isSystemServer);
|
Router.prepare(isSystemServer);
|
||||||
PrebuiltMethodsDeopter.deoptBootMethods();
|
PrebuiltMethodsDeopter.deoptBootMethods();
|
||||||
Router.installBootstrapHooks(isSystemServer);
|
Router.installBootstrapHooks(isSystemServer);
|
||||||
if (isDynamicModulesMode) {
|
if (isDynamicModulesMode) {
|
||||||
Router.loadModulesSafely(false);
|
Router.loadModulesSafely(false);
|
||||||
}
|
}
|
||||||
|
Router.onForkFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkNeedHook(String appDataDir, String niceName) {
|
private static boolean checkNeedHook(String appDataDir, String niceName) {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ public class NormalProxy {
|
||||||
boolean startChildZygote, String instructionSet,
|
boolean startChildZygote, String instructionSet,
|
||||||
String appDataDir) {
|
String appDataDir) {
|
||||||
// mainly for secondary zygote
|
// mainly for secondary zygote
|
||||||
|
Router.onForkStart();
|
||||||
|
Router.initResourcesHook();
|
||||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
// call this to ensure the flag is set to false ASAP
|
// call this to ensure the flag is set to false ASAP
|
||||||
|
|
@ -36,10 +38,13 @@ public class NormalProxy {
|
||||||
Router.onEnterChildProcess();
|
Router.onEnterChildProcess();
|
||||||
// load modules for each app process on its forked if dynamic modules mode is on
|
// load modules for each app process on its forked if dynamic modules mode is on
|
||||||
Router.loadModulesSafely(false);
|
Router.loadModulesSafely(false);
|
||||||
|
Router.onForkFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
||||||
long permittedCapabilities, long effectiveCapabilities) {
|
long permittedCapabilities, long effectiveCapabilities) {
|
||||||
|
Router.onForkStart();
|
||||||
|
Router.initResourcesHook();
|
||||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
// set startsSystemServer flag used when loadModules
|
// set startsSystemServer flag used when loadModules
|
||||||
|
|
@ -65,6 +70,7 @@ public class NormalProxy {
|
||||||
Router.onEnterChildProcess();
|
Router.onEnterChildProcess();
|
||||||
// reload module list if dynamic mode is on
|
// reload module list if dynamic mode is on
|
||||||
Router.loadModulesSafely(false);
|
Router.loadModulesSafely(false);
|
||||||
|
Router.onForkFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,5 +143,5 @@ public class Main implements KeepAll {
|
||||||
|
|
||||||
public static native boolean initXResourcesNative();
|
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;
|
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.Main;
|
||||||
import com.elderdrivers.riru.edxp.config.BaseHookProvider;
|
import com.elderdrivers.riru.edxp.config.BaseHookProvider;
|
||||||
import com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils;
|
import com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils;
|
||||||
|
|
@ -45,7 +42,7 @@ public class YahfaHookProvider extends BaseHookProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) {
|
public boolean removeFinalFlagNative(Class clazz) {
|
||||||
Main.rewriteXmlReferencesNative(parserPtr, origRes, repRes);
|
return Main.removeFinalFlagNative(clazz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package com.elderdrivers.riru.edxp.yahfa.entry;
|
||||||
import android.app.AndroidAppHelper;
|
import android.app.AndroidAppHelper;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.elderdrivers.riru.edxp.Main;
|
|
||||||
import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
|
import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
|
||||||
import com.elderdrivers.riru.edxp.util.Utils;
|
import com.elderdrivers.riru.edxp.util.Utils;
|
||||||
import com.elderdrivers.riru.edxp.yahfa.config.YahfaEdxpConfig;
|
import com.elderdrivers.riru.edxp.yahfa.config.YahfaEdxpConfig;
|
||||||
|
|
@ -27,11 +26,14 @@ public class Router {
|
||||||
|
|
||||||
private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false);
|
private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
public static void initResourcesHook() {
|
||||||
|
startWorkAroundHook(); // for OnePlus devices
|
||||||
|
XposedBridge.initXResources();
|
||||||
|
}
|
||||||
|
|
||||||
public static void prepare(boolean isSystem) {
|
public static void prepare(boolean isSystem) {
|
||||||
// this flag is needed when loadModules
|
// this flag is needed when loadModules
|
||||||
XposedInit.startsSystemServer = isSystem;
|
XposedInit.startsSystemServer = isSystem;
|
||||||
// InstallerChooser.setup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkHookState(String appDataDir) {
|
public static void checkHookState(String appDataDir) {
|
||||||
|
|
@ -103,8 +105,15 @@ public class Router {
|
||||||
WorkAroundHookInfo.class.getName());
|
WorkAroundHookInfo.class.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onEnterChildProcess() {
|
public static void onForkStart() {
|
||||||
|
forkCompleted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onForkFinish() {
|
||||||
forkCompleted = true;
|
forkCompleted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onEnterChildProcess() {
|
||||||
DynamicBridge.onForkPost();
|
DynamicBridge.onForkPost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,5 +130,6 @@ public class Router {
|
||||||
public static void injectConfig() {
|
public static void injectConfig() {
|
||||||
EdXpConfigGlobal.sConfig = new YahfaEdxpConfig();
|
EdXpConfigGlobal.sConfig = new YahfaEdxpConfig();
|
||||||
EdXpConfigGlobal.sHookProvider = new YahfaHookProvider();
|
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.Main;
|
||||||
import com.elderdrivers.riru.edxp.config.ConfigManager;
|
import com.elderdrivers.riru.edxp.config.ConfigManager;
|
||||||
import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter;
|
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.ProcessUtils;
|
||||||
import com.elderdrivers.riru.edxp.util.Utils;
|
import com.elderdrivers.riru.edxp.util.Utils;
|
||||||
|
import com.elderdrivers.riru.edxp.yahfa.entry.Router;
|
||||||
|
|
||||||
import de.robv.android.xposed.XposedBridge;
|
import de.robv.android.xposed.XposedBridge;
|
||||||
|
|
||||||
|
|
@ -73,6 +73,8 @@ public class BlackWhiteListProxy {
|
||||||
* Some details are different between main zygote and secondary zygote.
|
* Some details are different between main zygote and secondary zygote.
|
||||||
*/
|
*/
|
||||||
private static void onForkPreForNonDynamicMode(boolean isSystemServer) {
|
private static void onForkPreForNonDynamicMode(boolean isSystemServer) {
|
||||||
|
Router.onForkStart();
|
||||||
|
Router.initResourcesHook();
|
||||||
ConfigManager.setDynamicModulesMode(false);
|
ConfigManager.setDynamicModulesMode(false);
|
||||||
// set startsSystemServer flag used when loadModules
|
// set startsSystemServer flag used when loadModules
|
||||||
Router.prepare(isSystemServer);
|
Router.prepare(isSystemServer);
|
||||||
|
|
@ -92,20 +94,25 @@ public class BlackWhiteListProxy {
|
||||||
Main.niceName = niceName;
|
Main.niceName = niceName;
|
||||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
Router.onEnterChildProcess();
|
|
||||||
if (!isDynamicModulesMode) {
|
if (!isDynamicModulesMode) {
|
||||||
Main.reopenFilesAfterForkNative();
|
Main.reopenFilesAfterForkNative();
|
||||||
}
|
}
|
||||||
|
Router.onEnterChildProcess();
|
||||||
if (!checkNeedHook(appDataDir, niceName)) {
|
if (!checkNeedHook(appDataDir, niceName)) {
|
||||||
// if is blacklisted, just stop here
|
// if is blacklisted, just stop here
|
||||||
|
Router.onForkFinish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isDynamicModulesMode) {
|
||||||
|
Router.initResourcesHook();
|
||||||
|
}
|
||||||
Router.prepare(isSystemServer);
|
Router.prepare(isSystemServer);
|
||||||
PrebuiltMethodsDeopter.deoptBootMethods();
|
PrebuiltMethodsDeopter.deoptBootMethods();
|
||||||
Router.installBootstrapHooks(isSystemServer);
|
Router.installBootstrapHooks(isSystemServer);
|
||||||
if (isDynamicModulesMode) {
|
if (isDynamicModulesMode) {
|
||||||
Router.loadModulesSafely(false);
|
Router.loadModulesSafely(false);
|
||||||
}
|
}
|
||||||
|
Router.onForkFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkNeedHook(String appDataDir, String niceName) {
|
private static boolean checkNeedHook(String appDataDir, String niceName) {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ public class NormalProxy {
|
||||||
boolean startChildZygote, String instructionSet,
|
boolean startChildZygote, String instructionSet,
|
||||||
String appDataDir) {
|
String appDataDir) {
|
||||||
// mainly for secondary zygote
|
// mainly for secondary zygote
|
||||||
|
Router.onForkStart();
|
||||||
|
Router.initResourcesHook();
|
||||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
// call this to ensure the flag is set to false ASAP
|
// call this to ensure the flag is set to false ASAP
|
||||||
|
|
@ -36,10 +38,13 @@ public class NormalProxy {
|
||||||
Router.onEnterChildProcess();
|
Router.onEnterChildProcess();
|
||||||
// load modules for each app process on its forked if dynamic modules mode is on
|
// load modules for each app process on its forked if dynamic modules mode is on
|
||||||
Router.loadModulesSafely(false);
|
Router.loadModulesSafely(false);
|
||||||
|
Router.onForkFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
||||||
long permittedCapabilities, long effectiveCapabilities) {
|
long permittedCapabilities, long effectiveCapabilities) {
|
||||||
|
Router.onForkStart();
|
||||||
|
Router.initResourcesHook();
|
||||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
// set startsSystemServer flag used when loadModules
|
// set startsSystemServer flag used when loadModules
|
||||||
|
|
@ -65,6 +70,7 @@ public class NormalProxy {
|
||||||
Router.onEnterChildProcess();
|
Router.onEnterChildProcess();
|
||||||
// reload module list if dynamic mode is on
|
// reload module list if dynamic mode is on
|
||||||
Router.loadModulesSafely(false);
|
Router.loadModulesSafely(false);
|
||||||
|
Router.onForkFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -16,4 +16,9 @@ public class XResourcesSuperClass extends Resources {
|
||||||
super(null, null, null);
|
super(null, null, null);
|
||||||
throw new UnsupportedOperationException();
|
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 {
|
public class XTypedArraySuperClass extends TypedArray {
|
||||||
/** Dummy, will never be called (objects are transferred to this class only). */
|
/** Dummy, will never be called (objects are transferred to this class only). */
|
||||||
protected XTypedArraySuperClass(Resources resources, int[] data, int[] indices, int len) {
|
protected XTypedArraySuperClass(Resources resources) {
|
||||||
super(null, null, null, 0);
|
super(resources);
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ android {
|
||||||
buildToolsVersion '28.0.3'
|
buildToolsVersion '28.0.3'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 23
|
minSdkVersion 26
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,12 @@ import android.os.Build;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
import java.io.File;
|
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;
|
||||||
import de.robv.android.xposed.callbacks.XC_LayoutInflated.LayoutInflatedParam;
|
import de.robv.android.xposed.callbacks.XC_LayoutInflated.LayoutInflatedParam;
|
||||||
import de.robv.android.xposed.callbacks.XCallback;
|
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.decrementMethodDepth;
|
||||||
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
|
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.
|
* be set using the methods made available via the API methods in this class.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("JniMissingFunction")
|
@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, Object>> sReplacements = new SparseArray<>();
|
||||||
private static final SparseArray<HashMap<String, ResourceNames>> sResourceNames = 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 mResDir;
|
||||||
private String mPackageName;
|
private String mPackageName;
|
||||||
|
|
||||||
public XResources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
|
|
||||||
super(assets, metrics, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
public XResources(ClassLoader classLoader) {
|
public XResources(ClassLoader classLoader) {
|
||||||
super(classLoader);
|
super(classLoader);
|
||||||
}
|
}
|
||||||
|
|
@ -1136,9 +1131,7 @@ public class XResources extends Resources {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes) {
|
private static native void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes);
|
||||||
EdXpConfigGlobal.getHookProvider().rewriteXmlReferencesNative(parserPtr, origRes, repRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to replace reference IDs in XMLs.
|
* Used to replace reference IDs in XMLs.
|
||||||
|
|
@ -1263,7 +1256,7 @@ public class XResources extends Resources {
|
||||||
* Mainly used when inflating layouts.
|
* Mainly used when inflating layouts.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static class XTypedArray extends TypedArray {
|
public static class XTypedArray extends XTypedArraySuperClass {
|
||||||
|
|
||||||
public XTypedArray(Resources resources) {
|
public XTypedArray(Resources resources) {
|
||||||
super(resources);
|
super(resources);
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,7 @@
|
||||||
package com.elderdrivers.riru.edxp.config;
|
package com.elderdrivers.riru.edxp.config;
|
||||||
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.res.XResources;
|
|
||||||
|
|
||||||
import com.elderdrivers.riru.edxp.hook.HookProvider;
|
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 class EdXpConfigGlobal {
|
||||||
|
|
||||||
public static volatile EdXpConfig sConfig;
|
public static volatile EdXpConfig sConfig;
|
||||||
|
|
@ -24,7 +16,7 @@ public class EdXpConfigGlobal {
|
||||||
|
|
||||||
public static HookProvider getHookProvider() {
|
public static HookProvider getHookProvider() {
|
||||||
if (sHookProvider == null) {
|
if (sHookProvider == null) {
|
||||||
return defaultHookProvider;
|
throw new IllegalArgumentException("sHookProvider should not be null.");
|
||||||
}
|
}
|
||||||
return sHookProvider;
|
return sHookProvider;
|
||||||
}
|
}
|
||||||
|
|
@ -47,59 +39,4 @@ public class EdXpConfigGlobal {
|
||||||
return false;
|
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;
|
package com.elderdrivers.riru.edxp.hook;
|
||||||
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.res.XResources;
|
|
||||||
|
|
||||||
import java.lang.reflect.Member;
|
import java.lang.reflect.Member;
|
||||||
|
|
||||||
import de.robv.android.xposed.XposedBridge;
|
import de.robv.android.xposed.XposedBridge;
|
||||||
|
|
@ -27,5 +24,5 @@ public interface HookProvider {
|
||||||
|
|
||||||
boolean initXResourcesNative();
|
boolean initXResourcesNative();
|
||||||
|
|
||||||
void rewriteXmlReferencesNative(long parserPtr, XResources origRes, Resources repRes);
|
boolean removeFinalFlagNative(Class clazz);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,33 @@
|
||||||
package de.robv.android.xposed;
|
package de.robv.android.xposed;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
|
import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.AccessibleObject;
|
import java.lang.reflect.AccessibleObject;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Member;
|
import java.lang.reflect.Member;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import dalvik.system.InMemoryDexClassLoader;
|
||||||
import de.robv.android.xposed.XC_MethodHook.MethodHookParam;
|
import de.robv.android.xposed.XC_MethodHook.MethodHookParam;
|
||||||
import de.robv.android.xposed.callbacks.XC_InitPackageResources;
|
import de.robv.android.xposed.callbacks.XC_InitPackageResources;
|
||||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
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.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
|
* 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 {
|
public static volatile ClassLoader dummyClassLoader = null;
|
||||||
// ed: no support for now
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SetWorldReadable")
|
public static void initXResources() {
|
||||||
private static File ensureSuperDexFile(String clz, Class<?> realSuperClz, Class<?> topClz) throws IOException {
|
if (disableHooks) {
|
||||||
XposedBridge.removeFinalFlagNative(realSuperClz);
|
return;
|
||||||
File dexFile = DexCreator.ensure(clz, realSuperClz, topClz);
|
}
|
||||||
dexFile.setReadable(true, false);
|
String BASE_DIR = EdXpConfigGlobal.getConfig().getInstallerBaseDir();
|
||||||
return dexFile;
|
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() {
|
// private static boolean hadInitErrors() {
|
||||||
|
|
@ -478,7 +518,9 @@ public final class XposedBridge {
|
||||||
|
|
||||||
private static native Object cloneToSubclassNative(Object obj, Class<?> targetClazz);
|
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 closeFilesBeforeForkNative();
|
||||||
// /*package*/ static native void reopenFilesAfterForkNative();
|
// /*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 startClassName = ""; // ed: no support for tool process anymore
|
||||||
|
|
||||||
private static final String INSTANT_RUN_CLASS = "com.android.tools.fd.runtime.BootstrapApplication";
|
private static final String INSTANT_RUN_CLASS = "com.android.tools.fd.runtime.BootstrapApplication";
|
||||||
// TODO not supported yet
|
public static boolean disableResources = false;
|
||||||
private static boolean disableResources = false;
|
|
||||||
private static final String[] XRESOURCES_CONFLICTING_PACKAGES = {"com.sygic.aura"};
|
private static final String[] XRESOURCES_CONFLICTING_PACKAGES = {"com.sygic.aura"};
|
||||||
|
|
||||||
private XposedInit() {
|
private XposedInit() {
|
||||||
|
|
@ -82,20 +81,15 @@ public final class XposedInit {
|
||||||
} catch (NoSuchFieldError ignored) {
|
} 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();
|
hookResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/
|
private static void hookResources() throws Throwable {
|
||||||
public static void hookResources() throws Throwable {
|
|
||||||
|
if (disableResources) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String BASE_DIR = EdXpConfigGlobal.getConfig().getInstallerBaseDir();
|
String BASE_DIR = EdXpConfigGlobal.getConfig().getInstallerBaseDir();
|
||||||
|
|
||||||
|
|
@ -111,6 +105,16 @@ public final class XposedInit {
|
||||||
return;
|
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(a)
|
||||||
* -> getTopLevelResources(b)
|
* -> getTopLevelResources(b)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue