Optimize module loading under dynamic-modules mode
by only loading newly added or updated modules
This commit is contained in:
parent
be9105317f
commit
f6d2e3b62f
|
|
@ -1,4 +1,4 @@
|
|||
version: '0.4.4.6_alpha({build})'
|
||||
version: '0.4.4.7_alpha({build})'
|
||||
|
||||
environment:
|
||||
ANDROID_HOME: C:\android-sdk-windows
|
||||
|
|
|
|||
|
|
@ -72,10 +72,10 @@ public abstract class BaseRouter implements Router {
|
|||
}
|
||||
}
|
||||
|
||||
public void loadModulesSafely(boolean isInZygote) {
|
||||
public void loadModulesSafely(boolean isInZygote, boolean callInitZygote) {
|
||||
try {
|
||||
// FIXME some coredomain app can't reading modules.list
|
||||
XposedInit.loadModules(isInZygote);
|
||||
XposedInit.loadModules(isInZygote, callInitZygote);
|
||||
} catch (Exception exception) {
|
||||
Utils.logE("error loading module list", exception);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,8 +84,7 @@ public class BlackWhiteListProxy extends BaseProxy {
|
|||
// because installed hooks would be propagated to all child processes of zygote
|
||||
mRouter.startWorkAroundHook();
|
||||
// loadModules once for all child processes of zygote
|
||||
// TODO maybe just save initZygote callbacks and call them when whitelisted process forked?
|
||||
mRouter.loadModulesSafely(true);
|
||||
mRouter.loadModulesSafely(true, false);
|
||||
}
|
||||
|
||||
private void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) {
|
||||
|
|
@ -104,12 +103,15 @@ public class BlackWhiteListProxy extends BaseProxy {
|
|||
mRouter.prepare(isSystemServer);
|
||||
PrebuiltMethodsDeopter.deoptBootMethods();
|
||||
mRouter.installBootstrapHooks(isSystemServer);
|
||||
|
||||
// under dynamic modules mode, don't call initZygote when loadModule
|
||||
// cuz loaded module won't has that chance to do it
|
||||
if (isDynamicModulesMode) {
|
||||
mRouter.loadModulesSafely(false);
|
||||
} else {
|
||||
XposedBridge.callInitZygotes();
|
||||
XposedBridge.clearInitZygotes(); // one-time use
|
||||
mRouter.loadModulesSafely(false, false);
|
||||
}
|
||||
// call all initZygote callbacks
|
||||
XposedBridge.callInitZygotes();
|
||||
|
||||
mRouter.onForkFinish();
|
||||
}
|
||||
|
||||
|
|
@ -131,8 +133,6 @@ public class BlackWhiteListProxy extends BaseProxy {
|
|||
}
|
||||
|
||||
private static void onBlackListed() {
|
||||
XposedBridge.clearLoadedPackages();
|
||||
XposedBridge.clearInitPackageResources();
|
||||
XposedBridge.clearInitZygotes();
|
||||
XposedBridge.clearAllCallbacks();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ public class NormalProxy extends BaseProxy {
|
|||
// install bootstrap hooks for secondary zygote
|
||||
mRouter.installBootstrapHooks(false);
|
||||
// only load modules for secondary zygote
|
||||
mRouter.loadModulesSafely(true);
|
||||
mRouter.loadModulesSafely(true, true);
|
||||
}
|
||||
|
||||
public void forkAndSpecializePost(int pid, String appDataDir, String niceName) {
|
||||
|
|
@ -35,7 +35,7 @@ public class NormalProxy extends BaseProxy {
|
|||
mRouter.prepare(false);
|
||||
mRouter.onEnterChildProcess();
|
||||
// load modules for each app process on its forked if dynamic modules mode is on
|
||||
mRouter.loadModulesSafely(false);
|
||||
mRouter.loadModulesSafely(false, true);
|
||||
mRouter.onForkFinish();
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ public class NormalProxy extends BaseProxy {
|
|||
// loadModules have to be executed in zygote even isDynamicModules is false
|
||||
// because if not global hooks installed in initZygote might not be
|
||||
// propagated to processes not forked via forkAndSpecialize
|
||||
mRouter.loadModulesSafely(true);
|
||||
mRouter.loadModulesSafely(true, true);
|
||||
}
|
||||
|
||||
public void forkSystemServerPost(int pid) {
|
||||
|
|
@ -63,7 +63,9 @@ public class NormalProxy extends BaseProxy {
|
|||
mRouter.prepare(true);
|
||||
mRouter.onEnterChildProcess();
|
||||
// reload module list if dynamic mode is on
|
||||
mRouter.loadModulesSafely(false);
|
||||
if (ConfigManager.isDynamicModulesEnabled()) {
|
||||
mRouter.loadModulesSafely(false, true);
|
||||
}
|
||||
mRouter.onForkFinish();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public interface Router {
|
|||
|
||||
void installBootstrapHooks(boolean isSystem);
|
||||
|
||||
void loadModulesSafely(boolean isInZygote);
|
||||
void loadModulesSafely(boolean isInZygote, boolean callInitZygote);
|
||||
|
||||
void startBootstrapHook(boolean isSystem);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import org.gradle.internal.os.OperatingSystem
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
// Values set here will be overriden by AppVeyor, feel free to modify during development.
|
||||
def buildVersionName = 'v0.4.4.6_alpha'
|
||||
def buildVersionName = 'v0.4.4.7_alpha'
|
||||
def buildVersionCode = 10000
|
||||
|
||||
if (System.env.APPVEYOR_BUILD_VERSION != null) {
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ namespace edxp {
|
|||
variant_ = static_cast<Variant>(variant);
|
||||
}
|
||||
}
|
||||
LOGI("EdxpVariant: %d", variant_);
|
||||
|
||||
initialized_ = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ public class SandHookRouter extends BaseRouter {
|
|||
public void injectConfig() {
|
||||
EdXpConfigGlobal.sConfig = new SandHookEdxpConfig();
|
||||
EdXpConfigGlobal.sHookProvider = new SandHookProvider();
|
||||
XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,11 @@
|
|||
package com.elderdrivers.riru.edxp.whale.core;
|
||||
|
||||
import android.app.ActivityThread;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.res.CompatibilityInfo;
|
||||
|
||||
import com.elderdrivers.riru.edxp._hooker.impl.HandleBindApp;
|
||||
import com.elderdrivers.riru.edxp._hooker.impl.LoadedApkCstr;
|
||||
import com.elderdrivers.riru.edxp._hooker.yahfa.HandleBindAppHooker;
|
||||
import com.elderdrivers.riru.edxp._hooker.yahfa.LoadedApkConstructorHooker;
|
||||
import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
|
||||
import com.elderdrivers.riru.edxp.framework.Zygote;
|
||||
import com.elderdrivers.riru.edxp.proxy.BaseRouter;
|
||||
import com.elderdrivers.riru.edxp.whale.config.WhaleEdxpConfig;
|
||||
import com.elderdrivers.riru.edxp.whale.config.WhaleHookProvider;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
|
||||
public class WhaleRouter extends BaseRouter {
|
||||
|
||||
public void onEnterChildProcess() {
|
||||
|
|
@ -27,7 +16,6 @@ public class WhaleRouter extends BaseRouter {
|
|||
BaseRouter.useXposedApi = true;
|
||||
EdXpConfigGlobal.sConfig = new WhaleEdxpConfig();
|
||||
EdXpConfigGlobal.sHookProvider = new WhaleHookProvider();
|
||||
XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName());
|
||||
Zygote.allowFileAcrossFork("/system/lib/libwhale.edxp.so");
|
||||
Zygote.allowFileAcrossFork("/system/lib64/libwhale.edxp.so");
|
||||
Zygote.allowFileAcrossFork("/system/lib/libart.so");
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import com.elderdrivers.riru.edxp.yahfa.config.YahfaEdxpConfig;
|
|||
import com.elderdrivers.riru.edxp.yahfa.config.YahfaHookProvider;
|
||||
import com.elderdrivers.riru.edxp.yahfa.dexmaker.DynamicBridge;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
||||
public class YahfaRouter extends BaseRouter {
|
||||
|
||||
public void onEnterChildProcess() {
|
||||
|
|
@ -17,7 +15,6 @@ public class YahfaRouter extends BaseRouter {
|
|||
public void injectConfig() {
|
||||
EdXpConfigGlobal.sConfig = new YahfaEdxpConfig();
|
||||
EdXpConfigGlobal.sHookProvider = new YahfaHookProvider();
|
||||
XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,6 @@
|
|||
package de.robv.android.xposed;
|
||||
|
||||
public interface IModuleContext {
|
||||
|
||||
String getApkPath();
|
||||
}
|
||||
|
|
@ -25,12 +25,21 @@ public interface IXposedHookInitPackageResources extends IXposedMod {
|
|||
/** @hide */
|
||||
final class Wrapper extends XC_InitPackageResources {
|
||||
private final IXposedHookInitPackageResources instance;
|
||||
public Wrapper(IXposedHookInitPackageResources instance) {
|
||||
private final String apkPath;
|
||||
|
||||
public Wrapper(IXposedHookInitPackageResources instance, String apkPath) {
|
||||
this.instance = instance;
|
||||
this.apkPath = apkPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInitPackageResources(InitPackageResourcesParam resparam) throws Throwable {
|
||||
instance.handleInitPackageResources(resparam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getApkPath() {
|
||||
return apkPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,12 +26,20 @@ public interface IXposedHookLoadPackage extends IXposedMod {
|
|||
/** @hide */
|
||||
final class Wrapper extends XC_LoadPackage {
|
||||
private final IXposedHookLoadPackage instance;
|
||||
public Wrapper(IXposedHookLoadPackage instance) {
|
||||
private final String apkPath;
|
||||
|
||||
public Wrapper(IXposedHookLoadPackage instance, String apkPath) {
|
||||
this.instance = instance;
|
||||
this.apkPath = apkPath;
|
||||
}
|
||||
@Override
|
||||
public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
|
||||
instance.handleLoadPackage(lpparam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getApkPath() {
|
||||
return apkPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,5 +62,10 @@ public interface IXposedHookZygoteInit extends IXposedMod {
|
|||
// cause startupParam info is generated and saved along with instance here
|
||||
instance.initZygote(this.startupParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getApkPath() {
|
||||
return startupParam.modulePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -446,6 +446,12 @@ public final class XposedBridge {
|
|||
XCallback.callAll(new IXposedHookZygoteInit.StartupParam(sInitZygoteCallbacks));
|
||||
}
|
||||
|
||||
public static void clearAllCallbacks() {
|
||||
clearLoadedPackages();
|
||||
clearInitPackageResources();
|
||||
clearInitZygotes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept every call to the specified method and call a handler function instead.
|
||||
* @param method The method to intercept
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import android.os.Build;
|
|||
import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.os.ZygoteInit;
|
||||
|
|
@ -27,6 +28,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
|
@ -34,11 +36,17 @@ import java.util.zip.ZipFile;
|
|||
import dalvik.system.DexFile;
|
||||
import dalvik.system.PathClassLoader;
|
||||
import de.robv.android.xposed.callbacks.XC_InitPackageResources;
|
||||
import de.robv.android.xposed.callbacks.XC_InitZygote;
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||
import de.robv.android.xposed.callbacks.XCallback;
|
||||
import de.robv.android.xposed.services.BaseService;
|
||||
|
||||
import static de.robv.android.xposed.XposedBridge.clearAllCallbacks;
|
||||
import static de.robv.android.xposed.XposedBridge.hookAllConstructors;
|
||||
import static de.robv.android.xposed.XposedBridge.hookAllMethods;
|
||||
import static de.robv.android.xposed.XposedBridge.sInitPackageResourcesCallbacks;
|
||||
import static de.robv.android.xposed.XposedBridge.sInitZygoteCallbacks;
|
||||
import static de.robv.android.xposed.XposedBridge.sLoadedPackageCallbacks;
|
||||
import static de.robv.android.xposed.XposedHelpers.callMethod;
|
||||
import static de.robv.android.xposed.XposedHelpers.closeSilently;
|
||||
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
|
||||
|
|
@ -292,44 +300,104 @@ public final class XposedInit {
|
|||
/**
|
||||
* Try to load all modules defined in <code>INSTALLER_DATA_BASE_DIR/conf/modules.list</code>
|
||||
*/
|
||||
private static volatile AtomicBoolean modulesLoaded = new AtomicBoolean(false);
|
||||
private static final AtomicBoolean modulesLoaded = new AtomicBoolean(false);
|
||||
private static final Object moduleLoadLock = new Object();
|
||||
// @GuardedBy("moduleLoadLock")
|
||||
private static final ArraySet<String> loadedModules = new ArraySet<>();
|
||||
// @GuardedBy("moduleLoadLock")
|
||||
private static long lastModuleListModifiedTime = -1;
|
||||
|
||||
public static void loadModules(boolean isInZygote) throws IOException {
|
||||
public static boolean loadModules(boolean isInZygote, boolean callInitZygote) throws IOException {
|
||||
boolean hasLoaded = !modulesLoaded.compareAndSet(false, true);
|
||||
// dynamic module list mode doesn't apply to loading in zygote
|
||||
if (hasLoaded && (isInZygote || !EdXpConfigGlobal.getConfig().isDynamicModulesMode())) {
|
||||
return;
|
||||
}
|
||||
// FIXME module list is cleared but never could be reload again when using dynamic-module-list under multi-user environment
|
||||
XposedBridge.clearLoadedPackages();
|
||||
final String filename = EdXpConfigGlobal.getConfig().getInstallerBaseDir() + "conf/modules.list";
|
||||
BaseService service = SELinuxHelper.getAppDataFileService();
|
||||
if (!service.checkFileExists(filename)) {
|
||||
Log.e(TAG, "Cannot load any modules because " + filename + " was not found");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
synchronized (moduleLoadLock) {
|
||||
final String filename = EdXpConfigGlobal.getConfig().getInstallerBaseDir() + "conf/modules.list";
|
||||
BaseService service = SELinuxHelper.getAppDataFileService();
|
||||
if (!service.checkFileExists(filename)) {
|
||||
Log.e(TAG, "Cannot load any modules because " + filename + " was not found");
|
||||
// FIXME module list is cleared but never could be reload again
|
||||
// when using dynamic-module-list under multi-user environment
|
||||
clearAllCallbacks();
|
||||
return false;
|
||||
}
|
||||
|
||||
ClassLoader topClassLoader = XposedBridge.BOOTCLASSLOADER;
|
||||
ClassLoader parent;
|
||||
while ((parent = topClassLoader.getParent()) != null) {
|
||||
topClassLoader = parent;
|
||||
}
|
||||
long moduleListModifiedTime = service.getFileModificationTime(filename);
|
||||
if (lastModuleListModifiedTime == moduleListModifiedTime) {
|
||||
// module list has not changed
|
||||
return false;
|
||||
}
|
||||
|
||||
ClassLoader topClassLoader = XposedBridge.BOOTCLASSLOADER;
|
||||
ClassLoader parent;
|
||||
while ((parent = topClassLoader.getParent()) != null) {
|
||||
topClassLoader = parent;
|
||||
}
|
||||
|
||||
InputStream stream = service.getFileInputStream(filename);
|
||||
BufferedReader apks = new BufferedReader(new InputStreamReader(stream));
|
||||
ArraySet<String> newLoadedApk = new ArraySet<>();
|
||||
String apk;
|
||||
while ((apk = apks.readLine()) != null) {
|
||||
if (loadedModules.contains(apk)) {
|
||||
newLoadedApk.add(apk);
|
||||
} else {
|
||||
boolean loadSuccess = loadModule(apk, topClassLoader, callInitZygote);
|
||||
if (loadSuccess) {
|
||||
newLoadedApk.add(apk);
|
||||
}
|
||||
}
|
||||
}
|
||||
loadedModules.clear();
|
||||
loadedModules.addAll(newLoadedApk);
|
||||
apks.close();
|
||||
|
||||
// refresh callback according to current loaded module list
|
||||
pruneCallbacks(loadedModules);
|
||||
|
||||
lastModuleListModifiedTime = moduleListModifiedTime;
|
||||
|
||||
InputStream stream = service.getFileInputStream(filename);
|
||||
BufferedReader apks = new BufferedReader(new InputStreamReader(stream));
|
||||
String apk;
|
||||
while ((apk = apks.readLine()) != null) {
|
||||
loadModule(apk, topClassLoader);
|
||||
}
|
||||
apks.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
// remove deactivated or outdated module callbacks
|
||||
private static void pruneCallbacks(Set<String> loadedModules) {
|
||||
synchronized (moduleLoadLock) {
|
||||
Object[] loadedPkgSnapshot = sLoadedPackageCallbacks.getSnapshot();
|
||||
Object[] initPkgResSnapshot = sInitPackageResourcesCallbacks.getSnapshot();
|
||||
Object[] initZygoteSnapshot = sInitZygoteCallbacks.getSnapshot();
|
||||
for (Object loadedPkg : loadedPkgSnapshot) {
|
||||
if (loadedPkg instanceof IModuleContext) {
|
||||
if (!loadedModules.contains(((IModuleContext) loadedPkg).getApkPath())) {
|
||||
sLoadedPackageCallbacks.remove((XC_LoadPackage) loadedPkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Object initPkgRes : initPkgResSnapshot) {
|
||||
if (initPkgRes instanceof IModuleContext) {
|
||||
if (!loadedModules.contains(((IModuleContext) initPkgRes).getApkPath())) {
|
||||
sInitPackageResourcesCallbacks.remove((XC_InitPackageResources) initPkgRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Object initZygote : initZygoteSnapshot) {
|
||||
if (initZygote instanceof IModuleContext) {
|
||||
if (!loadedModules.contains(((IModuleContext) initZygote).getApkPath())) {
|
||||
sInitZygoteCallbacks.remove((XC_InitZygote) initZygote);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a module from an APK by calling the init(String) method for all classes defined
|
||||
* in <code>assets/xposed_init</code>.
|
||||
*/
|
||||
private static void loadModule(String apk, ClassLoader topClassLoader) {
|
||||
private static boolean loadModule(String apk, ClassLoader topClassLoader, boolean callInitZygote) {
|
||||
Log.i(TAG, "Loading modules from " + apk);
|
||||
|
||||
// todo remove this legacy logic
|
||||
|
|
@ -337,12 +405,12 @@ public final class XposedInit {
|
|||
if (!TextUtils.isEmpty(apk) && !TextUtils.isEmpty(blackListModulePackageName)
|
||||
&& apk.contains(blackListModulePackageName)) {
|
||||
Log.i(TAG, "We are going to take over black list's job...");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!new File(apk).exists()) {
|
||||
Log.e(TAG, " File does not exist");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
DexFile dexFile;
|
||||
|
|
@ -350,13 +418,13 @@ public final class XposedInit {
|
|||
dexFile = new DexFile(apk);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, " Cannot load module", e);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dexFile.loadClass(INSTANT_RUN_CLASS, topClassLoader) != null) {
|
||||
Log.e(TAG, " Cannot load module, please disable \"Instant Run\" in Android Studio.");
|
||||
closeSilently(dexFile);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dexFile.loadClass(XposedBridge.class.getName(), topClassLoader) != null) {
|
||||
|
|
@ -365,7 +433,7 @@ public final class XposedInit {
|
|||
Log.e(TAG, " This may cause strange issues and must be fixed by the module developer.");
|
||||
Log.e(TAG, " For details, see: http://api.xposed.info/using.html");
|
||||
closeSilently(dexFile);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
closeSilently(dexFile);
|
||||
|
|
@ -378,13 +446,13 @@ public final class XposedInit {
|
|||
if (zipEntry == null) {
|
||||
Log.e(TAG, " assets/xposed_init not found in the APK");
|
||||
closeSilently(zipFile);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
is = zipFile.getInputStream(zipEntry);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, " Cannot read assets/xposed_init in the APK", e);
|
||||
closeSilently(zipFile);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
ClassLoader mcl = new PathClassLoader(apk, XposedInit.class.getClassLoader());
|
||||
|
|
@ -414,24 +482,21 @@ public final class XposedInit {
|
|||
IXposedHookZygoteInit.StartupParam param = new IXposedHookZygoteInit.StartupParam();
|
||||
param.modulePath = apk;
|
||||
param.startsSystemServer = startsSystemServer;
|
||||
if (EdXpConfigGlobal.getConfig().isBlackWhiteListMode()
|
||||
&& !EdXpConfigGlobal.getConfig().isDynamicModulesMode()) {
|
||||
// postpone initZygote callbacks under black/white list mode
|
||||
// if dynamic modules mode is on, callback directly cause we
|
||||
// are already in app process here
|
||||
XposedBridge.hookInitZygote(new IXposedHookZygoteInit.Wrapper(
|
||||
(IXposedHookZygoteInit) moduleInstance, param));
|
||||
} else {
|
||||
// FIXME under dynamic modules mode, initZygote is called twice
|
||||
|
||||
XposedBridge.hookInitZygote(new IXposedHookZygoteInit.Wrapper(
|
||||
(IXposedHookZygoteInit) moduleInstance, param));
|
||||
if (callInitZygote) {
|
||||
((IXposedHookZygoteInit) moduleInstance).initZygote(param);
|
||||
}
|
||||
}
|
||||
|
||||
if (moduleInstance instanceof IXposedHookLoadPackage)
|
||||
XposedBridge.hookLoadPackage(new IXposedHookLoadPackage.Wrapper((IXposedHookLoadPackage) moduleInstance));
|
||||
XposedBridge.hookLoadPackage(new IXposedHookLoadPackage.Wrapper(
|
||||
(IXposedHookLoadPackage) moduleInstance, apk));
|
||||
|
||||
if (moduleInstance instanceof IXposedHookInitPackageResources)
|
||||
XposedBridge.hookInitPackageResources(new IXposedHookInitPackageResources.Wrapper((IXposedHookInitPackageResources) moduleInstance));
|
||||
XposedBridge.hookInitPackageResources(new IXposedHookInitPackageResources.Wrapper(
|
||||
(IXposedHookInitPackageResources) moduleInstance, apk));
|
||||
} else {
|
||||
if (moduleInstance instanceof IXposedHookCmdInit) {
|
||||
IXposedHookCmdInit.StartupParam param = new IXposedHookCmdInit.StartupParam();
|
||||
|
|
@ -442,10 +507,13 @@ public final class XposedInit {
|
|||
}
|
||||
} catch (Throwable t) {
|
||||
Log.e(TAG, " Failed to load class " + moduleClassName, t);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, " Failed to load module from " + apk, e);
|
||||
return false;
|
||||
} finally {
|
||||
closeSilently(is);
|
||||
closeSilently(zipFile);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
import de.robv.android.xposed.IModuleContext;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet;
|
||||
|
||||
|
|
@ -15,7 +16,7 @@ import de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet;
|
|||
* This class only keeps a priority for ordering multiple callbacks.
|
||||
* The actual (abstract) callback methods are added by subclasses.
|
||||
*/
|
||||
public abstract class XCallback implements Comparable<XCallback> {
|
||||
public abstract class XCallback implements Comparable<XCallback>, IModuleContext {
|
||||
/**
|
||||
* Callback priority, higher number means earlier execution.
|
||||
*
|
||||
|
|
@ -121,6 +122,11 @@ public abstract class XCallback implements Comparable<XCallback> {
|
|||
/** @hide */
|
||||
protected void call(Param param) throws Throwable {}
|
||||
|
||||
@Override
|
||||
public String getApkPath() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public int compareTo(XCallback other) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue