diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/core/HookMain.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/core/HookMain.java index db1188c7..f8418450 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/core/HookMain.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/core/HookMain.java @@ -82,6 +82,7 @@ public class HookMain { } public static void backupAndHook(Object target, Method hook, Method backup) { + Utils.logD(String.format("target=%s, hook=%s, backup=%s", target, hook, backup)); if (target == null) { throw new IllegalArgumentException("null target method"); } @@ -108,7 +109,7 @@ public class HookMain { } } - private static Object findMethod(Class cls, String methodName, String methodSig) { + public static Object findMethod(Class cls, String methodName, String methodSig) { if (cls == null) { throw new IllegalArgumentException("null class"); } diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/MethodInfo.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/MethodInfo.java new file mode 100644 index 00000000..aa0d0273 --- /dev/null +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/MethodInfo.java @@ -0,0 +1,92 @@ +package com.elderdrivers.riru.xposed.dexmaker; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +public class MethodInfo { + + public String className; + public String classDesc; + public String methodName; + public String methodSig; + public Method method; + public Constructor constructor; + public boolean isConstructor; + public ClassLoader classLoader; + + public MethodInfo(Member member) { + if (member instanceof Method) { + method = (Method) member; + isConstructor = false; + classLoader = member.getDeclaringClass().getClassLoader(); + generateMethodInfo(); + } else if (member instanceof Constructor) { + constructor = (Constructor) member; + isConstructor = true; + classLoader = member.getDeclaringClass().getClassLoader(); + generateConstructorInfo(); + } else { + throw new IllegalArgumentException("member should be Method or Constructor"); + } + } + + private void generateConstructorInfo() { + methodName = ""; + className = constructor.getDeclaringClass().getName(); + generateCommonInfo(constructor.getParameterTypes(), void.class); + } + + private void generateMethodInfo() { + methodName = method.getName(); + className = method.getDeclaringClass().getName(); + generateCommonInfo(method.getParameterTypes(), method.getReturnType()); + } + + private void generateCommonInfo(Class[] parameterTypes, Class returnType) { + classDesc = "L" + className.replace(".", "/") + ";"; + StringBuilder builder = new StringBuilder(); + builder.append("("); + for (Class parameterType : parameterTypes) { + builder.append(getDescStr(parameterType)); + } + builder.append(")"); + builder.append(getDescStr(returnType)); + methodSig = builder.toString(); + } + + public Class getClassForSure() { + try { + return Class.forName(className, true, classLoader); + } catch (Throwable throwable) { + return null; + } + } + + public static String getDescStr(Class clazz) { + if (clazz.equals(boolean.class)) { + return "Z"; + } else if (clazz.equals(byte.class)) { + return "B"; + } else if (clazz.equals(char.class)) { + return "C"; + } else if (clazz.equals(double.class)) { + return "D"; + } else if (clazz.equals(float.class)) { + return "F"; + } else if (clazz.equals(int.class)) { + return "I"; + } else if (clazz.equals(long.class)) { + return "J"; + } else if (clazz.equals(short.class)) { + return "S"; + } else if (clazz.equals(void.class)) { + return "V"; + } else { + String prefix = clazz.isArray() ? "" : "L"; + String suffix = clazz.isArray() ? "" : ";"; + return prefix + clazz.getName().replace(".", "/") + suffix; + } + } + +} diff --git a/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java b/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java index e53dc1c2..07f2b55f 100644 --- a/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java +++ b/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -3,6 +3,10 @@ package de.robv.android.xposed; import android.annotation.SuppressLint; import android.util.Log; +import com.elderdrivers.riru.xposed.core.HookMain; +import com.elderdrivers.riru.xposed.dexmaker.DynamicBridge; +import com.elderdrivers.riru.xposed.dexmaker.MethodInfo; + import java.io.File; import java.io.IOException; import java.lang.reflect.AccessibleObject; @@ -17,7 +21,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import com.elderdrivers.riru.xposed.dexmaker.DynamicBridge; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.callbacks.XC_InitPackageResources; import de.robv.android.xposed.callbacks.XC_LoadPackage; @@ -194,11 +197,20 @@ public final class XposedBridge { returnType = null; } - AdditionalHookInfo additionalInfo = new AdditionalHookInfo(callbacks, parameterTypes, returnType); - hookMethodNative(hookMethod, declaringClass, slot, additionalInfo); - } + AdditionalHookInfo additionalInfo = new AdditionalHookInfo(callbacks, parameterTypes, returnType); + MethodInfo methodInfo = new MethodInfo(hookMethod); + declaringClass = methodInfo.getClassForSure(); + Member reflectMethod = (Member) HookMain.findMethod( + declaringClass, methodInfo.methodName, methodInfo.methodSig); + if (reflectMethod == null) { + Log.e(TAG, "method not found: name=" + + methodInfo.methodName + ", sig=" + methodInfo.methodSig); + reflectMethod = hookMethod; + } + hookMethodNative(reflectMethod, declaringClass, slot, additionalInfo); + } - return callback.new Unhook(hookMethod); + return callback.new Unhook(hookMethod); } /**