From 5c5e1755d62044cc8a42f77f95cb8258b8349e8f Mon Sep 17 00:00:00 2001 From: LoveSy Date: Sat, 18 Sep 2021 12:45:15 +0800 Subject: [PATCH] [core] Refactor pending hook (#1125) --- .../de/robv/android/xposed/LspHooker.java | 2 +- .../de/robv/android/xposed/PendingHooks.java | 23 ++++-------- .../lspd/yahfa/dexmaker/DynamicBridge.java | 36 +++++++++++-------- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/core/src/main/java/de/robv/android/xposed/LspHooker.java b/core/src/main/java/de/robv/android/xposed/LspHooker.java index 79f9b30f..a8c2044c 100644 --- a/core/src/main/java/de/robv/android/xposed/LspHooker.java +++ b/core/src/main/java/de/robv/android/xposed/LspHooker.java @@ -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; diff --git a/core/src/main/java/de/robv/android/xposed/PendingHooks.java b/core/src/main/java/de/robv/android/xposed/PendingHooks.java index 52c3cc37..5e87e904 100644 --- a/core/src/main/java/de/robv/android/xposed/PendingHooks.java +++ b/core/src/main/java/de/robv/android/xposed/PendingHooks.java @@ -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, ConcurrentHashMap> sPendingHooks = new ConcurrentHashMap<>(); - public synchronized static void hookPendingMethod(Class clazz) { - if (sPendingHooks.containsKey(clazz)) { - for (Map.Entry 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 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(); - } - } diff --git a/core/src/main/java/org/lsposed/lspd/yahfa/dexmaker/DynamicBridge.java b/core/src/main/java/org/lsposed/lspd/yahfa/dexmaker/DynamicBridge.java index b72c49ac..e0d58b5e 100644 --- a/core/src/main/java/org/lsposed/lspd/yahfa/dexmaker/DynamicBridge.java +++ b/core/src/main/java/org/lsposed/lspd/yahfa/dexmaker/DynamicBridge.java @@ -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 hookedInfo = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap 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."); }