[core] Fix resource hook in Android 12 (#1270)
This commit is contained in:
parent
4dc0705e75
commit
2388517b96
|
|
@ -53,6 +53,7 @@ import java.lang.reflect.Method;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
|
|
@ -101,46 +102,70 @@ public final class XposedInit {
|
|||
final Class<?> classGTLR;
|
||||
final Class<?> classResKey;
|
||||
final ThreadLocal<Object> latestResKey = new ThreadLocal<>();
|
||||
final String createResourceMethod;
|
||||
final ArrayList<String> createResourceMethods = new ArrayList<>();
|
||||
|
||||
classGTLR = android.app.ResourcesManager.class;
|
||||
classResKey = android.content.res.ResourcesKey.class;
|
||||
|
||||
if (Build.VERSION.SDK_INT < 30) {
|
||||
createResourceMethod = "getOrCreateResources";
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
createResourceMethods.add("createResources");
|
||||
createResourceMethods.add("createResourcesForActivity");
|
||||
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
|
||||
createResourceMethods.add("createResources");
|
||||
} else {
|
||||
createResourceMethod = "createResources";
|
||||
createResourceMethods.add("getOrCreateResources");
|
||||
}
|
||||
|
||||
hookAllMethods(classGTLR, createResourceMethod, new XC_MethodHook() {
|
||||
//noinspection TrivialFunctionalExpressionUsage
|
||||
final Class<?> classActivityRes = ((Callable<Class<?>>) () -> {
|
||||
try {
|
||||
return XposedHelpers.findClass("android.app.ResourcesManager$ActivityResource", classGTLR.getClassLoader());
|
||||
} catch (Throwable ignored) {
|
||||
return null;
|
||||
}
|
||||
}).call();
|
||||
|
||||
|
||||
var hooker = new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
// At least on OnePlus 5, the method has an additional parameter compared to AOSP.
|
||||
final int activityTokenIdx = getParameterIndexByType(param.method, IBinder.class);
|
||||
Object activityToken = null;
|
||||
try {
|
||||
final int activityTokenIdx = getParameterIndexByType(param.method, IBinder.class);
|
||||
activityToken = param.args[activityTokenIdx];
|
||||
} catch (NoSuchFieldError ignored) {
|
||||
}
|
||||
final int resKeyIdx = getParameterIndexByType(param.method, classResKey);
|
||||
|
||||
String resDir = (String) getObjectField(param.args[resKeyIdx], "mResDir");
|
||||
XResources newRes = cloneToXResources(param, resDir);
|
||||
if (newRes == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object activityToken = param.args[activityTokenIdx];
|
||||
//noinspection SynchronizeOnNonFinalField
|
||||
synchronized (param.thisObject) {
|
||||
ArrayList<WeakReference<Resources>> resourceReferences;
|
||||
ArrayList<Object> resourceReferences;
|
||||
if (activityToken != null) {
|
||||
Object activityResources = callMethod(param.thisObject, "getOrCreateActivityResourcesStructLocked", activityToken);
|
||||
//noinspection unchecked
|
||||
resourceReferences = (ArrayList<WeakReference<Resources>>) getObjectField(activityResources, "activityResources");
|
||||
resourceReferences = (ArrayList<Object>) getObjectField(activityResources, "activityResources");
|
||||
} else {
|
||||
//noinspection unchecked
|
||||
resourceReferences = (ArrayList<WeakReference<Resources>>) getObjectField(param.thisObject, "mResourceReferences");
|
||||
resourceReferences = (ArrayList<Object>) getObjectField(param.thisObject, "mResourceReferences");
|
||||
}
|
||||
if (classActivityRes == null) {
|
||||
resourceReferences.add(new WeakReference<>(newRes));
|
||||
} else {
|
||||
var activityRes = XposedHelpers.newInstance(classActivityRes);
|
||||
XposedHelpers.setObjectField(activityRes, "resources", new WeakReference<>(newRes));
|
||||
}
|
||||
resourceReferences.add(new WeakReference<>(newRes));
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
for (var createResourceMethod : createResourceMethods) {
|
||||
hookAllMethods(classGTLR, createResourceMethod, hooker);
|
||||
}
|
||||
|
||||
findAndHookMethod(TypedArray.class, "obtain", Resources.class, int.class,
|
||||
new XC_MethodHook() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue