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 a6755b2c..c0fba72e 100644 Binary files a/hiddenapi-stubs/libs/framework-stub.jar and b/hiddenapi-stubs/libs/framework-stub.jar differ diff --git a/hiddenapi-stubs/src/main/java/xposed/dummy/XResourcesSuperClass.java b/hiddenapi-stubs/src/main/java/xposed/dummy/XResourcesSuperClass.java index 3c0f8bba..16f38f30 100644 --- a/hiddenapi-stubs/src/main/java/xposed/dummy/XResourcesSuperClass.java +++ b/hiddenapi-stubs/src/main/java/xposed/dummy/XResourcesSuperClass.java @@ -16,4 +16,9 @@ public class XResourcesSuperClass extends Resources { super(null, null, null); throw new UnsupportedOperationException(); } + + protected XResourcesSuperClass(ClassLoader classLoader) { + super(classLoader); + throw new UnsupportedOperationException(); + } } diff --git a/hiddenapi-stubs/src/main/java/xposed/dummy/XTypedArraySuperClass.java b/hiddenapi-stubs/src/main/java/xposed/dummy/XTypedArraySuperClass.java index f27db4a1..cefd760b 100644 --- a/hiddenapi-stubs/src/main/java/xposed/dummy/XTypedArraySuperClass.java +++ b/hiddenapi-stubs/src/main/java/xposed/dummy/XTypedArraySuperClass.java @@ -13,8 +13,8 @@ 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(); } } diff --git a/xposed-bridge/build.gradle b/xposed-bridge/build.gradle index b84841c6..0d9a288a 100644 --- a/xposed-bridge/build.gradle +++ b/xposed-bridge/build.gradle @@ -5,7 +5,7 @@ android { buildToolsVersion '28.0.3' defaultConfig { - minSdkVersion 23 + minSdkVersion 26 } sourceSets { diff --git a/xposed-bridge/src/main/java/android/content/res/XResources.java b/xposed-bridge/src/main/java/android/content/res/XResources.java index 5d208d26..8de7c840 100644 --- a/xposed-bridge/src/main/java/android/content/res/XResources.java +++ b/xposed-bridge/src/main/java/android/content/res/XResources.java @@ -33,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; @@ -49,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> 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();