[core] Refactor pending hook (#1125)
This commit is contained in:
parent
acbd6adc77
commit
5c5e1755d6
|
|
@ -26,7 +26,7 @@ import java.lang.reflect.Method;
|
|||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class LspHooker {
|
||||
private final XposedBridge.AdditionalHookInfo additionalInfo;
|
||||
public final XposedBridge.AdditionalHookInfo additionalInfo;
|
||||
private final Executable method;
|
||||
private final Method backup;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,35 +26,26 @@ import org.lsposed.lspd.yahfa.hooker.YahfaHooker;
|
|||
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public final class PendingHooks {
|
||||
|
||||
// GuardedBy("PendingHooks.class")
|
||||
private static final ConcurrentHashMap<Class<?>, ConcurrentHashMap<Executable, XposedBridge.AdditionalHookInfo>>
|
||||
sPendingHooks = new ConcurrentHashMap<>();
|
||||
|
||||
public synchronized static void hookPendingMethod(Class<?> clazz) {
|
||||
if (sPendingHooks.containsKey(clazz)) {
|
||||
for (Map.Entry<Executable, XposedBridge.AdditionalHookInfo> hook : sPendingHooks.get(clazz).entrySet()) {
|
||||
public static void hookPendingMethod(Class<?> clazz) {
|
||||
var record = sPendingHooks.remove(clazz);
|
||||
if (record != null) {
|
||||
for (var hook : record.entrySet()) {
|
||||
YahfaHooker.hookMethod(hook.getKey(), hook.getValue());
|
||||
}
|
||||
sPendingHooks.remove(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized static void recordPendingMethod(Method hookMethod,
|
||||
XposedBridge.AdditionalHookInfo additionalInfo) {
|
||||
ConcurrentHashMap<Executable, XposedBridge.AdditionalHookInfo> pending =
|
||||
sPendingHooks.computeIfAbsent(hookMethod.getDeclaringClass(), aClass -> new ConcurrentHashMap<>());
|
||||
public static void recordPendingMethod(Method hookMethod,
|
||||
XposedBridge.AdditionalHookInfo additionalInfo) {
|
||||
var pending = sPendingHooks.computeIfAbsent(hookMethod.getDeclaringClass(), aClass -> new ConcurrentHashMap<>());
|
||||
|
||||
pending.put(hookMethod, additionalInfo);
|
||||
recordPendingMethodNative(hookMethod, hookMethod.getDeclaringClass());
|
||||
}
|
||||
|
||||
public synchronized void cleanUp() {
|
||||
sPendingHooks.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,32 +28,40 @@ import java.lang.reflect.Member;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import de.robv.android.xposed.LspHooker;
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
||||
public final class DynamicBridge {
|
||||
private static final ConcurrentHashMap<Executable, LspHooker> hookedInfo = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<Executable, Object> lockers = new ConcurrentHashMap<>();
|
||||
|
||||
public static synchronized void hookMethod(Executable hookMethod, XposedBridge.AdditionalHookInfo additionalHookInfo) {
|
||||
public static void hookMethod(Executable hookMethod, XposedBridge.AdditionalHookInfo additionalHookInfo) {
|
||||
Utils.logD("hooking " + hookMethod);
|
||||
|
||||
if (hookedInfo.containsKey(hookMethod)) {
|
||||
Utils.logW("already hook method:" + hookMethod, new IllegalStateException());
|
||||
return;
|
||||
}
|
||||
|
||||
Utils.logD("start to generate class for: " + hookMethod);
|
||||
try {
|
||||
final HookerDexMaker dexMaker = new HookerDexMaker();
|
||||
dexMaker.start(hookMethod, additionalHookInfo);
|
||||
hookedInfo.put(hookMethod, dexMaker.getHooker());
|
||||
} catch (Throwable e) {
|
||||
Utils.logE("error occur when generating dex.", e);
|
||||
synchronized (lockers.computeIfAbsent(hookMethod, (m) -> new Object())) {
|
||||
var hooker = hookedInfo.getOrDefault(hookMethod, null);
|
||||
if (hooker == null) {
|
||||
Utils.logD("start to generate class for: " + hookMethod);
|
||||
try {
|
||||
final HookerDexMaker dexMaker = new HookerDexMaker();
|
||||
dexMaker.start(hookMethod, additionalHookInfo);
|
||||
hookedInfo.put(hookMethod, dexMaker.getHooker());
|
||||
} catch (Throwable e) {
|
||||
Utils.logE("error occur when generating dex.", e);
|
||||
}
|
||||
} else {
|
||||
for (var callback : additionalHookInfo.callbacks.getSnapshot())
|
||||
hooker.additionalInfo.callbacks.add((XC_MethodHook) callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Object invokeOriginalMethod(Member method, Object thisObject, Object[] args)
|
||||
throws InvocationTargetException, IllegalAccessException {
|
||||
LspHooker hooker = hookedInfo.get(method);
|
||||
if (!(method instanceof Executable)) {
|
||||
throw new IllegalArgumentException("Only methods or constructors can be invoked.");
|
||||
}
|
||||
LspHooker hooker = hookedInfo.getOrDefault(method, null);
|
||||
if (hooker == null) {
|
||||
throw new IllegalStateException("method not hooked, cannot call original method.");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue