Fix resource hook on MediaTek (#1951)

This commit is contained in:
南宫雪珊 2022-05-19 04:57:35 +08:00 committed by GitHub
parent 05129a0dd8
commit 8febd8cc7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 7 deletions

View File

@ -20,10 +20,11 @@
package de.robv.android.xposed; package de.robv.android.xposed;
import static de.robv.android.xposed.XposedHelpers.setObjectField;
import android.app.ActivityThread; import android.app.ActivityThread;
import android.content.ContextWrapper;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.ResourcesImpl;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.util.Log; import android.util.Log;
@ -50,7 +51,6 @@ import de.robv.android.xposed.callbacks.XC_LoadPackage;
* 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
* the native side. It also includes methods to add new hooks. * the native side. It also includes methods to add new hooks.
*/ */
@SuppressWarnings("JniMissingFunction")
public final class XposedBridge { public final class XposedBridge {
/** /**
* The system class loader which can be used to locate Android framework classes. * The system class loader which can be used to locate Android framework classes.
@ -133,10 +133,29 @@ public final class XposedBridge {
ResourcesHook.makeInheritable(resClass); ResourcesHook.makeInheritable(resClass);
ResourcesHook.makeInheritable(taClass); ResourcesHook.makeInheritable(taClass);
ClassLoader myCL = XposedBridge.class.getClassLoader(); ClassLoader myCL = XposedBridge.class.getClassLoader();
assert myCL != null;
dummyClassLoader = ResourcesHook.buildDummyClassLoader(myCL.getParent(), resClass.getName(), taClass.getName()); dummyClassLoader = ResourcesHook.buildDummyClassLoader(myCL.getParent(), resClass.getName(), taClass.getName());
dummyClassLoader.loadClass("xposed.dummy.XResourcesSuperClass"); dummyClassLoader.loadClass("xposed.dummy.XResourcesSuperClass");
dummyClassLoader.loadClass("xposed.dummy.XTypedArraySuperClass"); dummyClassLoader.loadClass("xposed.dummy.XTypedArraySuperClass");
setObjectField(myCL, "parent", dummyClassLoader); XposedHelpers.setObjectField(myCL, "parent", dummyClassLoader);
var contextField = XposedHelpers.findFieldIfExists(ResourcesImpl.class, "mAppContext");
// Used by com.mediatek.res.AsyncDrawableCache.putCacheList
if (contextField != null) {
var mediatekCompat = new ContextWrapper(null) {
private final ApplicationInfo info = new ApplicationInfo();
@Override
public ApplicationInfo getApplicationInfo() {
info.processName = "system";
return info;
}
};
// This field will be updated to correct value
// after ContextImpl.createAppContext
contextField.set(null, mediatekCompat);
}
} catch (Throwable throwable) { } catch (Throwable throwable) {
XposedBridge.log(throwable); XposedBridge.log(throwable);
XposedInit.disableResources = true; XposedInit.disableResources = true;
@ -405,7 +424,7 @@ public final class XposedBridge {
} else { } else {
returnType = null; returnType = null;
} }
params = new Object[] { params = new Object[]{
method, method,
returnType, returnType,
isStatic, isStatic,

View File

@ -22,11 +22,13 @@ package org.lsposed.lspd.service;
import static org.lsposed.lspd.service.ServiceManager.TAG; import static org.lsposed.lspd.service.ServiceManager.TAG;
import static org.lsposed.lspd.service.ServiceManager.toGlobalNamespace; import static org.lsposed.lspd.service.ServiceManager.toGlobalNamespace;
import android.content.ContextWrapper;
import android.content.pm.ApplicationInfo;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.ResourcesImpl;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.Process; import android.os.Process;
import android.os.RemoteException;
import android.os.SELinux; import android.os.SELinux;
import android.os.SharedMemory; import android.os.SharedMemory;
import android.system.ErrnoException; import android.system.ErrnoException;
@ -134,12 +136,30 @@ public class ConfigFileManager {
Method addAssetPath = AssetManager.class.getDeclaredMethod("addAssetPath", String.class); Method addAssetPath = AssetManager.class.getDeclaredMethod("addAssetPath", String.class);
addAssetPath.setAccessible(true); addAssetPath.setAccessible(true);
//noinspection ConstantConditions //noinspection ConstantConditions
if ((int) addAssetPath.invoke(am, daemonApkPath.toString()) > 0) if ((int) addAssetPath.invoke(am, daemonApkPath.toString()) > 0) {
//noinspection deprecation //noinspection deprecation
res = new Resources(am, null, null); res = new Resources(am, null, null);
}
} catch (Throwable e) { } catch (Throwable e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));
} }
try {
@SuppressWarnings("JavaReflectionMemberAccess")
var contextField = ResourcesImpl.class.getDeclaredField("mAppContext");
contextField.setAccessible(true);
var mediatekCompat = new ContextWrapper(null) {
private final ApplicationInfo info = new ApplicationInfo();
@Override
public ApplicationInfo getApplicationInfo() {
info.processName = "system";
return info;
}
};
contextField.set(null, mediatekCompat);
} catch (Exception ignored) {
// Not a MediaTek device
}
} }
static void reloadConfiguration() { static void reloadConfiguration() {