From 7d5a72b68338ee4a1943169aefdd39a82ed56cd7 Mon Sep 17 00:00:00 2001 From: solohsu Date: Mon, 29 Apr 2019 23:16:24 +0800 Subject: [PATCH] Dynamically create XResourcesSuperClass and XTypedArraySuperClass To support ROMs using custom Resources subclasses. --- .../riru/edxp/sandhook/entry/Router.java | 3 +- .../riru/edxp/whale/entry/Router.java | 3 +- .../riru/edxp/yahfa/entry/Router.java | 3 +- hiddenapi-stubs/libs/framework-stub.jar | Bin 15348 -> 15372 bytes .../xposed/dummy/XResourcesSuperClass.java | 5 ++ .../xposed/dummy/XTypedArraySuperClass.java | 4 +- xposed-bridge/build.gradle | 2 +- .../java/android/content/res/XResources.java | 10 ++- .../de/robv/android/xposed/XposedBridge.java | 68 ++++++++++++++---- .../de/robv/android/xposed/XposedInit.java | 10 +-- 10 files changed, 79 insertions(+), 29 deletions(-) diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java index 1240845e..c6815620 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java @@ -33,9 +33,10 @@ public class Router { static boolean useSandHook = false; public static void prepare(boolean isSystem) { + startWorkAroundHook(); + XposedBridge.initXResources(); // this flag is needed when loadModules startsSystemServer = isSystem; -// InstallerChooser.setup(); } public static void checkHookState(String appDataDir) { diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java index cde84956..f0bc193c 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java +++ b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java @@ -27,9 +27,10 @@ public class Router { public static void prepare(boolean isSystem) { + startWorkAroundHook(); + XposedBridge.initXResources(); // this flag is needed when loadModules XposedInit.startsSystemServer = isSystem; -// InstallerChooser.setup(); } public static void checkHookState(String appDataDir) { diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java index 57493cab..c40a0d77 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java @@ -29,9 +29,10 @@ public class Router { public static void prepare(boolean isSystem) { + startWorkAroundHook(); + XposedBridge.initXResources(); // this flag is needed when loadModules XposedInit.startsSystemServer = isSystem; -// InstallerChooser.setup(); } public static void checkHookState(String appDataDir) { diff --git a/hiddenapi-stubs/libs/framework-stub.jar b/hiddenapi-stubs/libs/framework-stub.jar index a6755b2cdff7334b7c418a7400504d46ff5bf2ab..c0fba72ef7f318b649a15a2f8f76e2d687c246c2 100644 GIT binary patch delta 2248 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 Sh^u5> sReplacements = new SparseArray<>(); private static final SparseArray> sResourceNames = new SparseArray<>(); @@ -77,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); } @@ -1258,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); diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java index d1711170..3a4665e8 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -1,29 +1,33 @@ package de.robv.android.xposed; -import android.annotation.SuppressLint; +import android.content.res.Resources; +import android.content.res.TypedArray; import android.util.Log; import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; -import java.io.File; -import java.io.IOException; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.nio.ByteBuffer; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import dalvik.system.InMemoryDexClassLoader; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.callbacks.XC_InitPackageResources; import de.robv.android.xposed.callbacks.XC_LoadPackage; +import external.com.android.dx.DexMaker; +import external.com.android.dx.TypeId; import static de.robv.android.xposed.XposedHelpers.getIntField; +import static de.robv.android.xposed.XposedHelpers.setObjectField; /** * This class contains most of Xposed's central logic, such as initialization and callbacks used by @@ -83,16 +87,52 @@ public 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(); diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java index a5f68819..bfe5184a 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java @@ -57,8 +57,7 @@ public final class XposedInit { private static final String startClassName = ""; // ed: no support for tool process anymore private static final String INSTANT_RUN_CLASS = "com.android.tools.fd.runtime.BootstrapApplication"; - // TODO not supported yet - private static boolean disableResources = false; + public static boolean disableResources = false; private static final String[] XRESOURCES_CONFLICTING_PACKAGES = {"com.sygic.aura"}; private XposedInit() { @@ -86,8 +85,11 @@ public final class XposedInit { hookResources(); } - /*package*/ - public static void hookResources() throws Throwable { + private static void hookResources() throws Throwable { + + if (disableResources) { + return; + } String BASE_DIR = EdXpConfigGlobal.getConfig().getInstallerBaseDir();