Implement some xposed utils
This commit is contained in:
parent
c77617c3e1
commit
58665b3105
|
|
@ -103,7 +103,7 @@ public abstract class XC_MethodHook extends XCallback {
|
|||
/**
|
||||
* Wraps information about the method call and allows to influence it.
|
||||
*/
|
||||
public static final class MethodHookParam <T> extends XCallback.Param implements XposedInterface.BeforeHookCallback<T>, XposedInterface.AfterHookCallback<T> {
|
||||
public static final class MethodHookParam <T extends Executable> extends XCallback.Param implements XposedInterface.BeforeHookCallback<T>, XposedInterface.AfterHookCallback<T> {
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
|
@ -115,7 +115,7 @@ public abstract class XC_MethodHook extends XCallback {
|
|||
/**
|
||||
* The hooked method/constructor.
|
||||
*/
|
||||
public Member method;
|
||||
public T method;
|
||||
|
||||
/**
|
||||
* The {@code this} reference for an instance method, or {@code null} for static methods.
|
||||
|
|
@ -193,7 +193,7 @@ public abstract class XC_MethodHook extends XCallback {
|
|||
@NonNull
|
||||
@Override
|
||||
public T getOrigin() {
|
||||
return (T) method;
|
||||
return method;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
@ -208,6 +208,17 @@ public abstract class XC_MethodHook extends XCallback {
|
|||
return args;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <U> U getArg(int index) {
|
||||
return (U) args[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> void setArg(int index, U value) {
|
||||
args[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void returnAndSkip(@Nullable Object returnValue) {
|
||||
setResult(returnValue);
|
||||
|
|
@ -221,7 +232,13 @@ public abstract class XC_MethodHook extends XCallback {
|
|||
@Nullable
|
||||
@Override
|
||||
public Object invokeOrigin(@Nullable Object thisObject, Object[] args) throws InvocationTargetException, IllegalAccessException {
|
||||
return HookBridge.invokeOriginalMethod((Executable) method, thisObject, args);
|
||||
return HookBridge.invokeOriginalMethod(method, thisObject, args);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object invokeOrigin() throws InvocationTargetException, IllegalAccessException {
|
||||
return HookBridge.invokeOriginalMethod(method, thisObject, args);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ public final class XposedBridge {
|
|||
}
|
||||
}
|
||||
|
||||
public static class AdditionalHookInfo<T> {
|
||||
public static class AdditionalHookInfo<T extends Executable> {
|
||||
private final Object params;
|
||||
|
||||
private AdditionalHookInfo(Executable method) {
|
||||
|
|
@ -421,7 +421,7 @@ public final class XposedBridge {
|
|||
|
||||
var array = ((Object[]) params);
|
||||
|
||||
var method = (Executable) array[0];
|
||||
var method = (T) array[0];
|
||||
var returnType = (Class<?>) array[1];
|
||||
var isStatic = (Boolean) array[2];
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ import java.io.FileOutputStream;
|
|||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
|
@ -59,7 +58,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.XposedInit;
|
||||
|
|
@ -762,14 +760,14 @@ public class LSPosedContext extends XposedContext {
|
|||
private <T, U extends Executable> MethodUnhooker<T, U> doHook(U hookMethod, int priority, T callback) {
|
||||
if (Modifier.isAbstract(hookMethod.getModifiers())) {
|
||||
throw new IllegalArgumentException("Cannot hook abstract methods: " + hookMethod);
|
||||
} else if (hookMethod.getDeclaringClass().getClassLoader() == XposedBridge.class.getClassLoader()) {
|
||||
} else if (hookMethod.getDeclaringClass().getClassLoader() == LSPosedContext.class.getClassLoader()) {
|
||||
throw new IllegalArgumentException("Do not allow hooking inner methods");
|
||||
} else if (hookMethod.getDeclaringClass() == Method.class && hookMethod.getName().equals("invoke")) {
|
||||
throw new IllegalArgumentException("Cannot hook Method.invoke");
|
||||
}
|
||||
|
||||
if (callback == null) {
|
||||
throw new IllegalArgumentException("callback should not be null!");
|
||||
throw new IllegalArgumentException("hooker should not be null!");
|
||||
}
|
||||
|
||||
if (HookBridge.hookMethod(hookMethod, XposedBridge.AdditionalHookInfo.class, priority, callback)) {
|
||||
|
|
@ -857,7 +855,7 @@ public class LSPosedContext extends XposedContext {
|
|||
return doHook(origin, priority, hooker);
|
||||
}
|
||||
|
||||
private static boolean deoptimize(@NonNull Executable method) {
|
||||
private static boolean doDeoptimize(@NonNull Executable method) {
|
||||
if (Modifier.isAbstract(method.getModifiers())) {
|
||||
throw new IllegalArgumentException("Cannot deoptimize abstract methods: " + method);
|
||||
} else if (Proxy.isProxyClass(method.getDeclaringClass())) {
|
||||
|
|
@ -868,12 +866,12 @@ public class LSPosedContext extends XposedContext {
|
|||
|
||||
@Override
|
||||
public boolean deoptimize(@NonNull Method method) {
|
||||
return deoptimize((Executable) method);
|
||||
return doDeoptimize(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean deoptimize(@NonNull Constructor<T> constructor) {
|
||||
return deoptimize((Executable) constructor);
|
||||
return doDeoptimize(constructor);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@ package org.lsposed.lspd.impl;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang3.ClassUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import io.github.libxposed.XposedUtils;
|
||||
|
||||
public class LSPosedUtils implements XposedUtils {
|
||||
|
|
@ -14,25 +19,53 @@ public class LSPosedUtils implements XposedUtils {
|
|||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Class<T> classByName(@NonNull String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
|
||||
throw new AbstractMethodError();
|
||||
public <T> Class<T> findClass(@NonNull String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
|
||||
return (Class<T>) ClassUtils.getClass(classLoader, className.replace('/', '.'), false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> Class<T> classOrNullByName(@NonNull String className, @Nullable ClassLoader classLoader) {
|
||||
throw new AbstractMethodError();
|
||||
public <T> Class<T> findClassOrNull(@NonNull String className, @Nullable ClassLoader classLoader) {
|
||||
try {
|
||||
return findClass(className, classLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Class<T> classByBinaryName(@NonNull String binaryClassName, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
|
||||
throw new AbstractMethodError();
|
||||
public Field findField(@NonNull Class<?> clazz, @NonNull String fieldName) throws NoSuchFieldException {
|
||||
try {
|
||||
return XposedHelpers.findField(clazz, fieldName);
|
||||
} catch (NoSuchFieldError e) {
|
||||
throw new NoSuchFieldException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Field findFieldOrNull(@NonNull Class<?> clazz, @NonNull String fieldName) {
|
||||
try {
|
||||
return findField(clazz, fieldName);
|
||||
} catch (NoSuchFieldException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Field findField(@NonNull String className, @NonNull String fieldName, @Nullable ClassLoader classLoader) throws ClassNotFoundException, NoSuchFieldException {
|
||||
var clazz = findClass(className, classLoader);
|
||||
return findField(clazz, fieldName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> Class<T> classOrNullByBinaryName(@NonNull String binaryClassName, @Nullable ClassLoader classLoader) {
|
||||
throw new AbstractMethodError();
|
||||
public Field findFieldOrNull(@NonNull String className, @NonNull String fieldName, @Nullable ClassLoader classLoader) {
|
||||
try {
|
||||
return findField(className, fieldName, classLoader);
|
||||
} catch (ClassNotFoundException | NoSuchFieldException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ public interface XposedInterface {
|
|||
@NonNull
|
||||
Object[] getArgs();
|
||||
|
||||
@Nullable
|
||||
<U> U getArg(int index);
|
||||
|
||||
<U> void setArg(int index, U value);
|
||||
|
||||
void returnAndSkip(@Nullable Object returnValue);
|
||||
|
||||
void throwAndSkip(@Nullable Throwable throwable);
|
||||
|
|
@ -28,6 +33,9 @@ public interface XposedInterface {
|
|||
@Nullable
|
||||
Object invokeOrigin(@Nullable Object thisObject, Object[] args) throws InvocationTargetException, IllegalAccessException;
|
||||
|
||||
@Nullable
|
||||
Object invokeOrigin() throws InvocationTargetException, IllegalAccessException;
|
||||
|
||||
<U> void setExtra(@NonNull String key, @Nullable U value) throws ConcurrentModificationException;
|
||||
}
|
||||
|
||||
|
|
@ -56,6 +64,9 @@ public interface XposedInterface {
|
|||
@Nullable
|
||||
Object invokeOrigin(@Nullable Object thisObject, Object[] args) throws InvocationTargetException, IllegalAccessException;
|
||||
|
||||
@Nullable
|
||||
Object invokeOrigin() throws InvocationTargetException, IllegalAccessException;
|
||||
|
||||
@Nullable
|
||||
<U> U getExtra(@NonNull String key);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,24 @@ package io.github.libxposed;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public interface XposedUtils {
|
||||
@NonNull
|
||||
<T> Class<T> classByName(@NonNull String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException;
|
||||
<T> Class<T> findClass(@NonNull String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException;
|
||||
|
||||
@Nullable
|
||||
<T> Class<T> classOrNullByName(@NonNull String className, @Nullable ClassLoader classLoader);
|
||||
<T> Class<T> findClassOrNull(@NonNull String className, @Nullable ClassLoader classLoader);
|
||||
|
||||
@NonNull
|
||||
<T> Class<T> classByBinaryName(@NonNull String binaryClassName, @Nullable ClassLoader classLoader) throws ClassNotFoundException;
|
||||
Field findField(@NonNull Class<?> clazz, @NonNull String fieldName) throws NoSuchFieldException;
|
||||
|
||||
@Nullable
|
||||
<T> Class<T> classOrNullByBinaryName(@NonNull String binaryClassName, @Nullable ClassLoader classLoader);
|
||||
Field findFieldOrNull(@NonNull Class<?> clazz, @NonNull String fieldName);
|
||||
|
||||
@NonNull
|
||||
Field findField(@NonNull String className, @NonNull String fieldName, @Nullable ClassLoader classLoader) throws ClassNotFoundException, NoSuchFieldException;
|
||||
|
||||
@Nullable
|
||||
Field findFieldOrNull(@NonNull String className, @NonNull String fieldName, @Nullable ClassLoader classLoader);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue