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