Toolbox v5.4.57版本的 MD5 值为:13657448575afd5a9dc4a1da7a3fb6cf
以下内容为反编译后的 XposedInit.java 源代码,内容仅作参考
package de.robv.android.xposed;
import android.app.ActivityThread;
import android.app.ResourcesManager;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.content.res.ResourcesImpl;
import android.content.res.ResourcesKey;
import android.content.res.TypedArray;
import android.content.res.XResources;
import android.os.Build;
import android.os.IBinder;
import android.os.Process;
import android.util.ArrayMap;
import android.util.Log;
import de.robv.android.xposed.IXposedHookInitPackageResources;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.IXposedHookZygoteInit;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_InitPackageResources;
import de.robv.android.xposed.callbacks.XCallback;
import hidden.HiddenApiBridge;
import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import org.lsposed.lspd.core.ApplicationServiceClient;
import org.lsposed.lspd.deopt.PrebuiltMethodsDeopter;
import org.lsposed.lspd.impl.LSPosedContext;
import org.lsposed.lspd.models.Module;
import org.lsposed.lspd.models.PreLoadedApk;
import org.lsposed.lspd.nativebridge.ResourcesHook;
import org.lsposed.lspd.util.LspModuleClassLoader;
import xposed.dummy.XResourcesSuperClass;
public final class XposedInit {
private static final String TAG = "LSPosed-Bridge";
public static volatile boolean disableResources = false;
public static boolean startsSystemServer = false;
public static AtomicBoolean resourceInit = new AtomicBoolean(false);
private static final Map<String, Optional<String>> loadedModules = new ConcurrentHashMap();
public static final Set<String> loadedPackagesInProcess = ConcurrentHashMap.newKeySet(1);
public static void hookResources() throws Throwable {
if (disableResources || !resourceInit.compareAndSet(false, true)) {
return;
}
PrebuiltMethodsDeopter.deoptResourceMethods();
if (!ResourcesHook.initXResourcesNative()) {
Log.e("LSPosed-Bridge", "Cannot hook resources");
disableResources = true;
return;
}
XposedHelpers.findAndHookMethod("android.app.ApplicationPackageManager", null, "getResourcesForApplication", ApplicationInfo.class, new XC_MethodHook() {
@Override
public void beforeHookedMethod(XC_MethodHook.MethodHookParam<?> methodHookParam) {
ApplicationInfo applicationInfo = (ApplicationInfo) methodHookParam.args[0];
XResources.setPackageNameForResDir(applicationInfo.packageName, applicationInfo.uid == Process.myUid() ? applicationInfo.sourceDir : applicationInfo.publicSourceDir);
}
});
ThreadLocal threadLocal = new ThreadLocal();
ArrayList arrayList = new ArrayList();
final Class<ResourcesKey> cls = ResourcesKey.class;
if (Build.VERSION.SDK_INT >= 31) {
arrayList.add("createResources");
arrayList.add("createResourcesForActivity");
} else if (Build.VERSION.SDK_INT == 30) {
arrayList.add("createResources");
} else {
arrayList.add("getOrCreateResources");
}
final Class<?> findClassIfExists = XposedHelpers.findClassIfExists("android.app.ResourcesManager$ActivityResource", ResourcesManager.class.getClassLoader());
XC_MethodHook xC_MethodHook = new XC_MethodHook() {
@Override
public void afterHookedMethod(XC_MethodHook.MethodHookParam<?> methodHookParam) {
Object obj;
ArrayList arrayList2;
Class cls2;
try {
obj = methodHookParam.args[XposedHelpers.getParameterIndexByType(methodHookParam.method, IBinder.class)];
} catch (NoSuchFieldError unused) {
obj = null;
}
XResources cloneToXResources = XposedInit.cloneToXResources(methodHookParam, (String) XposedHelpers.getObjectField(methodHookParam.args[XposedHelpers.getParameterIndexByType(methodHookParam.method, cls)], "mResDir"));
if (cloneToXResources == null) {
return;
}
synchronized (methodHookParam.thisObject) {
if (obj != null) {
arrayList2 = (ArrayList) XposedHelpers.getObjectField(XposedHelpers.callMethod(methodHookParam.thisObject, "getOrCreateActivityResourcesStructLocked", obj), "activityResources");
} else {
arrayList2 = (ArrayList) XposedHelpers.getObjectField(methodHookParam.thisObject, "mResourceReferences");
}
if (obj != null && (cls2 = findClassIfExists) != null) {
Object newInstance = XposedHelpers.newInstance(cls2, new Object[0]);
XposedHelpers.setObjectField(newInstance, "resources", new WeakReference(cloneToXResources));
arrayList2.add(newInstance);
}
arrayList2.add(new WeakReference(cloneToXResources));
}
}
};
Iterator it = arrayList.iterator();
while (it.hasNext()) {
XposedBridge.hookAllMethods(ResourcesManager.class, (String) it.next(), xC_MethodHook);
}
XposedHelpers.findAndHookMethod(TypedArray.class, "obtain", Resources.class, Integer.TYPE, new XC_MethodHook() {
@Override
public void afterHookedMethod(XC_MethodHook.MethodHookParam<?> methodHookParam) throws Throwable {
if (!(methodHookParam.getResult() instanceof XResources.XTypedArray) && (methodHookParam.args[0] instanceof XResources)) {
XResources.XTypedArray xTypedArray = new XResources.XTypedArray((Resources) methodHookParam.args[0]);
int intValue = ((Integer) methodHookParam.args[1]).intValue();
Method findMethodBestMatch = XposedHelpers.findMethodBestMatch((Class<?>) TypedArray.class, "resize", (Class<?>[]) new Class[]{Integer.TYPE});
findMethodBestMatch.setAccessible(true);
findMethodBestMatch.invoke(xTypedArray, Integer.valueOf(intValue));
methodHookParam.setResult(xTypedArray);
}
}
});
XResourcesSuperClass xResources = new XResources((ClassLoader) XposedHelpers.getObjectField(Resources.getSystem(), "mClassLoader"), null);
HiddenApiBridge.Resources_setImpl(xResources, (ResourcesImpl) XposedHelpers.getObjectField(Resources.getSystem(), "mResourcesImpl"));
XposedHelpers.setStaticObjectField(Resources.class, "mSystem", xResources);
XResources.init(threadLocal);
}
public static XResources cloneToXResources(XC_MethodHook.MethodHookParam<?> methodHookParam, String str) {
Object result = methodHookParam.getResult();
if (result == null || (result instanceof XResources)) {
return null;
}
?? xResources = new XResources((ClassLoader) XposedHelpers.getObjectField(methodHookParam.getResult(), "mClassLoader"), str);
HiddenApiBridge.Resources_setImpl(xResources, (ResourcesImpl) XposedHelpers.getObjectField(methodHookParam.getResult(), "mResourcesImpl"));
if (xResources.isFirstLoad()) {
String packageName = xResources.getPackageName();
XC_InitPackageResources.InitPackageResourcesParam initPackageResourcesParam = new XC_InitPackageResources.InitPackageResourcesParam(XposedBridge.sInitPackageResourcesCallbacks);
initPackageResourcesParam.packageName = packageName;
initPackageResourcesParam.res = xResources;
XCallback.callAll(initPackageResourcesParam);
}
methodHookParam.setResult(xResources);
return xResources;
}
public static Map<String, Optional<String>> getLoadedModules() {
return loadedModules;
}
public static void loadLegacyModules() {
ApplicationServiceClient.serviceClient.getLegacyModulesList().forEach(new Consumer() {
@Override
public final void accept(Object obj) {
XposedInit.lambda$loadLegacyModules$0((Module) obj);
}
});
}
public static void lambda$loadLegacyModules$0(Module module) {
String str = module.apkPath;
String str2 = module.packageName;
PreLoadedApk preLoadedApk = module.file;
Map<String, Optional<String>> map = loadedModules;
map.put(str2, Optional.of(str));
if (loadModule(str2, str, preLoadedApk)) {
return;
}
map.remove(str2);
}
public static void loadModules(final ActivityThread activityThread) {
final ArrayMap arrayMap = (ArrayMap) XposedHelpers.getObjectField(activityThread, "mPackages");
ApplicationServiceClient.serviceClient.getModulesList().forEach(new Consumer() {
@Override
public final void accept(Object obj) {
XposedInit.lambda$loadModules$1(activityThread, arrayMap, (Module) obj);
}
});
}
public static void lambda$loadModules$1(ActivityThread activityThread, ArrayMap arrayMap, Module module) {
Map<String, Optional<String>> map = loadedModules;
map.put(module.packageName, Optional.empty());
if (!LSPosedContext.loadModule(activityThread, module)) {
map.remove(module.packageName);
} else {
arrayMap.remove(module.packageName);
}
}
private static void initNativeModule(List<String> list) {
list.forEach(new XposedInit$$ExternalSyntheticLambda2());
}
private static boolean initModule(ClassLoader classLoader, String str, List<String> list) {
int i = 0;
for (String str2 : list) {
try {
Log.i("LSPosed-Bridge", " Loading class " + str2);
Class<?> loadClass = classLoader.loadClass(str2);
if (!IXposedMod.class.isAssignableFrom(loadClass)) {
Log.e("LSPosed-Bridge", " This class doesn't implement any sub-interface of IXposedMod, skipping it");
} else {
Object newInstance = loadClass.newInstance();
if (newInstance instanceof IXposedHookZygoteInit) {
IXposedHookZygoteInit.StartupParam startupParam = new IXposedHookZygoteInit.StartupParam();
startupParam.modulePath = str;
startupParam.startsSystemServer = startsSystemServer;
((IXposedHookZygoteInit) newInstance).initZygote(startupParam);
i++;
}
if (newInstance instanceof IXposedHookLoadPackage) {
XposedBridge.hookLoadPackage(new IXposedHookLoadPackage.Wrapper((IXposedHookLoadPackage) newInstance));
i++;
}
if (newInstance instanceof IXposedHookInitPackageResources) {
hookResources();
XposedBridge.hookInitPackageResources(new IXposedHookInitPackageResources.Wrapper((IXposedHookInitPackageResources) newInstance));
i++;
}
}
} catch (Throwable th) {
Log.e("LSPosed-Bridge", " Failed to load class " + str2, th);
}
}
return i > 0;
}
private static boolean loadModule(String str, String str2, PreLoadedApk preLoadedApk) {
Log.i("LSPosed-Bridge", "Loading legacy module " + str + " from " + str2);
StringBuilder sb = new StringBuilder();
for (String str3 : Process.is64Bit() ? Build.SUPPORTED_64_BIT_ABIS : Build.SUPPORTED_32_BIT_ABIS) {
sb.append(str2).append("!/lib/").append(str3).append(File.pathSeparator);
}
String sb2 = sb.toString();
ClassLoader classLoader = XposedInit.class.getClassLoader();
ClassLoader loadApk = LspModuleClassLoader.loadApk(str2, preLoadedApk.preLoadedDexes, sb2, classLoader);
try {
if (loadApk.loadClass(XposedBridge.class.getName()).getClassLoader() != classLoader) {
Log.e("LSPosed-Bridge", " Cannot load module: " + str);
Log.e("LSPosed-Bridge", " The Xposed API classes are compiled into the module's APK.");
Log.e("LSPosed-Bridge", " This may cause strange issues and must be fixed by the module developer.");
Log.e("LSPosed-Bridge", " For details, see: https://api.xposed.info/using.html");
return false;
}
initNativeModule(preLoadedApk.moduleLibraryNames);
return initModule(loadApk, str2, preLoadedApk.moduleClassNames);
} catch (ClassNotFoundException unused) {
return false;
}
}
}