Implement callback
This commit is contained in:
parent
f68994f60a
commit
31674f589e
|
|
@ -39,6 +39,7 @@ import android.os.IBinder;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.lsposed.lspd.impl.LSPosedContext;
|
||||||
import org.lsposed.lspd.models.PreLoadedApk;
|
import org.lsposed.lspd.models.PreLoadedApk;
|
||||||
import org.lsposed.lspd.nativebridge.NativeAPI;
|
import org.lsposed.lspd.nativebridge.NativeAPI;
|
||||||
import org.lsposed.lspd.nativebridge.ResourcesHook;
|
import org.lsposed.lspd.nativebridge.ResourcesHook;
|
||||||
|
|
@ -57,6 +58,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import de.robv.android.xposed.callbacks.XC_InitPackageResources;
|
import de.robv.android.xposed.callbacks.XC_InitPackageResources;
|
||||||
import de.robv.android.xposed.callbacks.XCallback;
|
import de.robv.android.xposed.callbacks.XCallback;
|
||||||
import hidden.HiddenApiBridge;
|
import hidden.HiddenApiBridge;
|
||||||
|
import io.github.libxposed.XposedInterface;
|
||||||
|
import io.github.libxposed.XposedModuleInterface;
|
||||||
|
import io.github.libxposed.XposedResource;
|
||||||
|
|
||||||
public final class XposedInit {
|
public final class XposedInit {
|
||||||
private static final String TAG = XposedBridge.TAG;
|
private static final String TAG = XposedBridge.TAG;
|
||||||
|
|
@ -196,7 +200,7 @@ public final class XposedInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the returned resources with our subclass.
|
// Replace the returned resources with our subclass.
|
||||||
XResources newRes = new XResources(
|
var newRes = new XposedResource(
|
||||||
(ClassLoader) XposedHelpers.getObjectField(param.getResult(), "mClassLoader"));
|
(ClassLoader) XposedHelpers.getObjectField(param.getResult(), "mClassLoader"));
|
||||||
HiddenApiBridge.Resources_setImpl(newRes, (ResourcesImpl) XposedHelpers.getObjectField(param.getResult(), "mResourcesImpl"));
|
HiddenApiBridge.Resources_setImpl(newRes, (ResourcesImpl) XposedHelpers.getObjectField(param.getResult(), "mResourcesImpl"));
|
||||||
newRes.initObject(resDir);
|
newRes.initObject(resDir);
|
||||||
|
|
@ -208,6 +212,11 @@ public final class XposedInit {
|
||||||
resparam.packageName = packageName;
|
resparam.packageName = packageName;
|
||||||
resparam.res = newRes;
|
resparam.res = newRes;
|
||||||
XCallback.callAll(resparam);
|
XCallback.callAll(resparam);
|
||||||
|
|
||||||
|
var rlparam = new XposedModuleInterface.ResourceLoadedParam();
|
||||||
|
rlparam.packageName = packageName;
|
||||||
|
rlparam.res = newRes;
|
||||||
|
LSPosedContext.callOnResourceLoaded(rlparam, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
param.setResult(newRes);
|
param.setResult(newRes);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package io.github.libxposed;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
|
||||||
public abstract class XposedContext extends Context implements XposedInterface {
|
public abstract class XposedContext extends Context implements XposedInterface {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,25 @@ public class XposedContextWrapper extends ContextWrapper implements XposedInterf
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public XposedContext getBaseContext() {
|
final public XposedContext getBaseContext() {
|
||||||
return (XposedContext) super.getBaseContext();
|
return (XposedContext) super.getBaseContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hook() {
|
final public void hook() {
|
||||||
getBaseContext().hook();
|
getBaseContext().hook();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
final public void log(String message) {
|
||||||
|
getBaseContext().log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
final public void log(String message, Throwable throwable) {
|
||||||
|
getBaseContext().log(message, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
final protected void attachBaseContext(Context base) {
|
final protected void attachBaseContext(Context base) {
|
||||||
if (base instanceof XposedContext) {
|
if (base instanceof XposedContext) {
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,6 @@ package io.github.libxposed;
|
||||||
|
|
||||||
public interface XposedInterface {
|
public interface XposedInterface {
|
||||||
void hook();
|
void hook();
|
||||||
|
void log(String message);
|
||||||
|
void log(String message, Throwable throwable);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,31 @@
|
||||||
package io.github.libxposed;
|
package io.github.libxposed;
|
||||||
|
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public interface XposedModuleInterface {
|
public interface XposedModuleInterface {
|
||||||
default void onPackageLoaded() {
|
class PackageLoadedParam {
|
||||||
|
public String packageName;
|
||||||
|
public String processName;
|
||||||
|
public ClassLoader classLoader;
|
||||||
|
public ApplicationInfo appInfo;
|
||||||
|
public boolean isFirstApplication;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResourceLoadedParam {
|
||||||
|
public String packageName;
|
||||||
|
public XposedResource res;
|
||||||
|
}
|
||||||
|
|
||||||
|
default void onPackageLoaded(@NonNull PackageLoadedParam param, @Nullable Bundle extra) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default void onResourceLoaded() {
|
default void onResourceLoaded(@NonNull ResourceLoadedParam param, @Nullable Bundle extra) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package io.github.libxposed;
|
||||||
|
|
||||||
|
import android.content.res.XResources;
|
||||||
|
|
||||||
|
public class XposedResource extends XResources {
|
||||||
|
public XposedResource(ClassLoader classLoader) {
|
||||||
|
super(classLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,6 +27,7 @@ import android.app.AndroidAppHelper;
|
||||||
import android.app.LoadedApk;
|
import android.app.LoadedApk;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
import org.lsposed.lspd.impl.LSPosedContext;
|
||||||
import org.lsposed.lspd.util.Hookers;
|
import org.lsposed.lspd.util.Hookers;
|
||||||
import org.lsposed.lspd.util.MetaDataReader;
|
import org.lsposed.lspd.util.MetaDataReader;
|
||||||
import org.lsposed.lspd.util.Utils;
|
import org.lsposed.lspd.util.Utils;
|
||||||
|
|
@ -40,6 +41,7 @@ import de.robv.android.xposed.XC_MethodReplacement;
|
||||||
import de.robv.android.xposed.XposedBridge;
|
import de.robv.android.xposed.XposedBridge;
|
||||||
import de.robv.android.xposed.XposedHelpers;
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||||
|
import io.github.libxposed.XposedModuleInterface;
|
||||||
|
|
||||||
public class LoadedApkGetCLHooker extends XC_MethodHook {
|
public class LoadedApkGetCLHooker extends XC_MethodHook {
|
||||||
private final LoadedApk loadedApk;
|
private final LoadedApk loadedApk;
|
||||||
|
|
@ -95,6 +97,13 @@ public class LoadedApkGetCLHooker extends XC_MethodHook {
|
||||||
Hookers.logD("Call handleLoadedPackage: packageName=" + lpparam.packageName + " processName=" + lpparam.processName + " isFirstApplication=" + isFirstApplication + " classLoader=" + lpparam.classLoader + " appInfo=" + lpparam.appInfo);
|
Hookers.logD("Call handleLoadedPackage: packageName=" + lpparam.packageName + " processName=" + lpparam.processName + " isFirstApplication=" + isFirstApplication + " classLoader=" + lpparam.classLoader + " appInfo=" + lpparam.appInfo);
|
||||||
XC_LoadPackage.callAll(lpparam);
|
XC_LoadPackage.callAll(lpparam);
|
||||||
|
|
||||||
|
var plparam = new XposedModuleInterface.PackageLoadedParam();
|
||||||
|
plparam.packageName = packageName;
|
||||||
|
plparam.processName = processName;
|
||||||
|
plparam.classLoader = classLoader;
|
||||||
|
plparam.appInfo = loadedApk.getApplicationInfo();
|
||||||
|
plparam.isFirstApplication = isFirstApplication;
|
||||||
|
LSPosedContext.callOnPackageLoaded(plparam, null);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Hookers.logE("error when hooking LoadedApk#getClassLoader", t);
|
Hookers.logE("error when hooking LoadedApk#getClassLoader", t);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import de.robv.android.xposed.XposedHelpers;
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
import de.robv.android.xposed.XposedInit;
|
import de.robv.android.xposed.XposedInit;
|
||||||
|
|
@ -54,10 +56,34 @@ public class LSPosedContext extends XposedContext {
|
||||||
|
|
||||||
public static final String TAG = "LSPosedContext";
|
public static final String TAG = "LSPosedContext";
|
||||||
|
|
||||||
private final Context base;
|
static final Set<XposedModule> modules = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
LSPosedContext(Context base) {
|
private final Context base;
|
||||||
|
private final String packageName;
|
||||||
|
|
||||||
|
LSPosedContext(Context base, String packageName) {
|
||||||
this.base = base;
|
this.base = base;
|
||||||
|
this.packageName = packageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void callOnPackageLoaded(XposedModuleInterface.PackageLoadedParam param, Bundle extra) {
|
||||||
|
for (XposedModule module : modules) {
|
||||||
|
try {
|
||||||
|
module.onPackageLoaded(param, extra);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.e(TAG, "Error when calling onPackageLoaded of " + ((LSPosedContext) module.getBaseContext()).packageName, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void callOnResourceLoaded(XposedModuleInterface.ResourceLoadedParam param, Bundle extra) {
|
||||||
|
for (XposedModule module : modules) {
|
||||||
|
try {
|
||||||
|
module.onResourceLoaded(param, extra);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.e(TAG, "Error when calling onResourceLoaded of " + ((LSPosedContext) module.getBaseContext()).packageName, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean loadModules(ActivityThread at, Module module) {
|
public static boolean loadModules(ActivityThread at, Module module) {
|
||||||
|
|
@ -104,7 +130,7 @@ public class LSPosedContext extends XposedContext {
|
||||||
}
|
}
|
||||||
args[i] = null;
|
args[i] = null;
|
||||||
}
|
}
|
||||||
var ctx = new LSPosedContext((Context) ctor.newInstance(args));
|
var ctx = new LSPosedContext((Context) ctor.newInstance(args), module.packageName);
|
||||||
for (var entry : module.file.moduleClassNames) {
|
for (var entry : module.file.moduleClassNames) {
|
||||||
var moduleClass = ctx.getClassLoader().loadClass(entry);
|
var moduleClass = ctx.getClassLoader().loadClass(entry);
|
||||||
Log.d(TAG, " Loading class " + moduleClass);
|
Log.d(TAG, " Loading class " + moduleClass);
|
||||||
|
|
@ -112,11 +138,12 @@ public class LSPosedContext extends XposedContext {
|
||||||
Log.e(TAG, " This class doesn't implement any sub-interface of XposedModule, skipping it");
|
Log.e(TAG, " This class doesn't implement any sub-interface of XposedModule, skipping it");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (moduleClass.getMethod("onResourceLoaded").getDeclaringClass() != XposedModuleInterface.class) {
|
if (moduleClass.getMethod("onResourceLoaded", XposedModuleInterface.ResourceLoadedParam.class, Bundle.class).getDeclaringClass() != XposedModuleInterface.class) {
|
||||||
XposedInit.hookResources();
|
XposedInit.hookResources();
|
||||||
}
|
}
|
||||||
var moduleEntry = moduleClass.getConstructor(XposedContext.class);
|
var moduleEntry = moduleClass.getConstructor(XposedContext.class);
|
||||||
moduleEntry.newInstance(ctx);
|
var moduleContext = (XposedModule) moduleEntry.newInstance(ctx);
|
||||||
|
modules.add(moduleContext);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e(TAG, " Failed to load class " + moduleClass, e);
|
Log.e(TAG, " Failed to load class " + moduleClass, e);
|
||||||
}
|
}
|
||||||
|
|
@ -657,4 +684,14 @@ public class LSPosedContext extends XposedContext {
|
||||||
public void hook() {
|
public void hook() {
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log(String message) {
|
||||||
|
Log.i(TAG, packageName + ": " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log(String message, Throwable throwable) {
|
||||||
|
Log.e(TAG, packageName + ": " + message, throwable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue