Dynamically create XResourcesSuperClass and XTypedArraySuperClass
To support ROMs using custom Resources subclasses.
This commit is contained in:
parent
ee4d48c1b4
commit
7d5a72b683
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
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 {
|
||||
|
|
|
|||
|
|
@ -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<HashMap<String, Object>> sReplacements = new SparseArray<>();
|
||||
private static final SparseArray<HashMap<String, ResourceNames>> 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);
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue