From 844d2984a02651fb66771cf4907d4ad68490e6c9 Mon Sep 17 00:00:00 2001 From: Nullptr Date: Tue, 15 Aug 2023 17:36:22 +0800 Subject: [PATCH] No XposedContext --- .../github/libxposed/api/XposedContext.java | 12 - .../libxposed/api/XposedContextWrapper.java | 209 ------------------ .../github/libxposed/api/XposedInterface.java | 57 ++--- .../libxposed/api/XposedInterfaceWrapper.java | 155 +++++++++++++ .../io/github/libxposed/api/XposedModule.java | 6 +- 5 files changed, 190 insertions(+), 249 deletions(-) delete mode 100644 api/src/main/java/io/github/libxposed/api/XposedContext.java delete mode 100644 api/src/main/java/io/github/libxposed/api/XposedContextWrapper.java create mode 100644 api/src/main/java/io/github/libxposed/api/XposedInterfaceWrapper.java diff --git a/api/src/main/java/io/github/libxposed/api/XposedContext.java b/api/src/main/java/io/github/libxposed/api/XposedContext.java deleted file mode 100644 index db2401c..0000000 --- a/api/src/main/java/io/github/libxposed/api/XposedContext.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.libxposed.api; - -import android.content.Context; - -/** - * Independent {@link Context} for each Xposed module loaded into the target process.
- * This class should be extended by the Xposed framework as the implementation of Xposed interfaces.
- * Modules should not use this class directly. - */ -public abstract class XposedContext extends Context implements XposedInterface { - -} diff --git a/api/src/main/java/io/github/libxposed/api/XposedContextWrapper.java b/api/src/main/java/io/github/libxposed/api/XposedContextWrapper.java deleted file mode 100644 index d4cb5fc..0000000 --- a/api/src/main/java/io/github/libxposed/api/XposedContextWrapper.java +++ /dev/null @@ -1,209 +0,0 @@ -package io.github.libxposed.api; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.ContextWrapper; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.ByteBuffer; - -import io.github.libxposed.api.utils.DexParser; - -/** - * Wrap of {@link XposedContext} used by the modules for the purpose of shielding framework implementation details. - */ -@SuppressWarnings({"unused"}) -@SuppressLint("DiscouragedApi") -public class XposedContextWrapper extends ContextWrapper implements XposedInterface { - - XposedContextWrapper(@NonNull XposedContext base) { - super(base); - } - - XposedContextWrapper(@NonNull XposedContextWrapper base) { - super(base); - } - - /** - * Gets the Xposed API version of current implementation. - * - * @return API version - */ - public final int getAPIVersion() { - return API; - } - - /** - * Gets the implementation {@link XposedContext}. Should not be used by modules. - */ - @NonNull - @Override - public final XposedContext getBaseContext() { - return (XposedContext) super.getBaseContext(); - } - - /** - * {@inheritDoc} - */ - @NonNull - @Override - public final String getFrameworkName() { - return getBaseContext().getFrameworkName(); - } - - /** - * {@inheritDoc} - */ - @NonNull - @Override - public final String getFrameworkVersion() { - return getBaseContext().getFrameworkVersion(); - } - - /** - * {@inheritDoc} - */ - @Override - public final long getFrameworkVersionCode() { - return getBaseContext().getFrameworkVersionCode(); - } - - /** - * {@inheritDoc} - */ - @Override - public final int getFrameworkPrivilege() { - return getBaseContext().getFrameworkPrivilege(); - } - - /** - * {@inheritDoc} - */ - @NonNull - @Override - public final MethodUnhooker hook(@NonNull Method origin, @NonNull Class hooker) { - return getBaseContext().hook(origin, hooker); - } - - /** - * {@inheritDoc} - */ - @NonNull - @Override - public final MethodUnhooker hook(@NonNull Method origin, int priority, @NonNull Class hooker) { - return getBaseContext().hook(origin, priority, hooker); - } - - /** - * {@inheritDoc} - */ - @NonNull - @Override - public final MethodUnhooker> hook(@NonNull Constructor origin, @NonNull Class hooker) { - return getBaseContext().hook(origin, hooker); - } - - /** - * {@inheritDoc} - */ - @NonNull - @Override - public final MethodUnhooker> hook(@NonNull Constructor origin, int priority, @NonNull Class hooker) { - return getBaseContext().hook(origin, priority, hooker); - } - - /** - * {@inheritDoc} - */ - @Override - public final boolean deoptimize(@NonNull Method method) { - return getBaseContext().deoptimize(method); - } - - /** - * {@inheritDoc} - */ - @Override - public final boolean deoptimize(@NonNull Constructor constructor) { - return getBaseContext().deoptimize(constructor); - } - - /** - * {@inheritDoc} - */ - @Nullable - @Override - public final Object invokeOrigin(@NonNull Method method, @Nullable Object thisObject, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException { - return getBaseContext().invokeOrigin(method, thisObject, args); - } - - /** - * {@inheritDoc} - */ - @Nullable - @Override - public final Object invokeSpecial(@NonNull Method method, @NonNull Object thisObject, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException { - return getBaseContext().invokeSpecial(method, thisObject, args); - } - - /** - * {@inheritDoc} - */ - @NonNull - @Override - public final T newInstanceOrigin(@NonNull Constructor constructor, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException, InstantiationException { - return getBaseContext().newInstanceOrigin(constructor, args); - } - - /** - * {@inheritDoc} - */ - @NonNull - @Override - public final U newInstanceSpecial(@NonNull Constructor constructor, @NonNull Class subClass, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException, InstantiationException { - return getBaseContext().newInstanceSpecial(constructor, subClass, args); - } - - /** - * {@inheritDoc} - */ - @Override - public final void log(@NonNull String message) { - getBaseContext().log(message); - } - - /** - * {@inheritDoc} - */ - @Override - public final void log(@NonNull String message, @NonNull Throwable throwable) { - getBaseContext().log(message, throwable); - } - - /** - * {@inheritDoc} - */ - @Nullable - @Override - public final DexParser parseDex(@NonNull ByteBuffer dexData, boolean includeAnnotations) throws IOException { - return getBaseContext().parseDex(dexData, includeAnnotations); - } - - /** - * {@inheritDoc} - */ - @Override - protected final void attachBaseContext(Context base) { - if (base instanceof XposedContext || base instanceof XposedContextWrapper) { - super.attachBaseContext(base); - } else { - throw new IllegalArgumentException(); - } - } -} diff --git a/api/src/main/java/io/github/libxposed/api/XposedInterface.java b/api/src/main/java/io/github/libxposed/api/XposedInterface.java index a8fbf55..87939e8 100644 --- a/api/src/main/java/io/github/libxposed/api/XposedInterface.java +++ b/api/src/main/java/io/github/libxposed/api/XposedInterface.java @@ -47,7 +47,7 @@ public interface XposedInterface { int FRAMEWORK_PRIVILEGE_APP = 2; /** * Indicates that the framework is embedded in the hooked app, - * which means {@link #getSharedPreferences} will be null and remote file is unsupported. + * which means {@link #getRemotePreferences} will be null and remote file is unsupported. */ int FRAMEWORK_PRIVILEGE_EMBEDDED = 3; @@ -443,42 +443,49 @@ public interface XposedInterface { @Nullable DexParser parseDex(@NonNull ByteBuffer dexData, boolean includeAnnotations) throws IOException; - - // Methods the same with Context - /** - * Gets remote preferences stored in Xposed framework. Note that those are read-only in hooked apps. + * Gets the application info of the module. * - * @see Context#getSharedPreferences(String, int) + * @see Context#getApplicationInfo() */ - SharedPreferences getSharedPreferences(String name, int mode); - - /** - * Open a remote file stored in Xposed framework. - * - * @see Context#openFileInput(String) - */ - FileInputStream openFileInput(String name) throws FileNotFoundException; - - /** - * List all remote files stored in Xposed framework. Note that you can only access files created by - * your own module app with XposedService. - * - * @see Context#fileList() - */ - String[] fileList(); + @NonNull + ApplicationInfo getApplicationInfo(); /** * Gets resources of the module. * * @see Context#getResources() */ + @NonNull Resources getResources(); /** - * Gets the application info of the module. + * Gets remote preferences stored in Xposed framework. Note that those are read-only in hooked apps. * - * @see Context#getApplicationInfo() + * @param group Group name + * @return The preferences, null if the group does not exists + * @throws UnsupportedOperationException If the framework is embedded */ - ApplicationInfo getApplicationInfo(); + @Nullable + SharedPreferences getRemotePreferences(@NonNull String group); + + /** + * Open an InputStream to read a file from the module's shared data directory. + * + * @param name File name, must not contain path separators and . or .. + * @return The InputStream + * @throws FileNotFoundException If the file does not exist or the path is forbidden + * @throws UnsupportedOperationException If the framework is embedded + */ + @NonNull + FileInputStream openRemoteFileInput(@NonNull String name) throws FileNotFoundException; + + /** + * List all files in the module's shared data directory. + * + * @return The file list + * @throws UnsupportedOperationException If the framework is embedded + */ + @NonNull + String[] listRemoteFiles(); } diff --git a/api/src/main/java/io/github/libxposed/api/XposedInterfaceWrapper.java b/api/src/main/java/io/github/libxposed/api/XposedInterfaceWrapper.java new file mode 100644 index 0000000..c435f4e --- /dev/null +++ b/api/src/main/java/io/github/libxposed/api/XposedInterfaceWrapper.java @@ -0,0 +1,155 @@ +package io.github.libxposed.api; + +import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.content.res.Resources; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; + +import io.github.libxposed.api.utils.DexParser; + +/** + * Wrap of {@link XposedInterface} used by the modules for the purpose of shielding framework implementation details. + */ +public class XposedInterfaceWrapper implements XposedInterface { + + private final XposedInterface mBase; + + XposedInterfaceWrapper(@NonNull XposedInterface base) { + mBase = base; + } + + @NonNull + @Override + public final String getFrameworkName() { + return mBase.getFrameworkName(); + } + + @NonNull + @Override + public final String getFrameworkVersion() { + return mBase.getFrameworkVersion(); + } + + @Override + public final long getFrameworkVersionCode() { + return mBase.getFrameworkVersionCode(); + } + + @Override + public final int getFrameworkPrivilege() { + return mBase.getFrameworkPrivilege(); + } + + @NonNull + @Override + public final MethodUnhooker hook(@NonNull Method origin, @NonNull Class hooker) { + return mBase.hook(origin, hooker); + } + + @NonNull + @Override + public final MethodUnhooker hook(@NonNull Method origin, int priority, @NonNull Class hooker) { + return mBase.hook(origin, priority, hooker); + } + + @NonNull + @Override + public final MethodUnhooker> hook(@NonNull Constructor origin, @NonNull Class hooker) { + return mBase.hook(origin, hooker); + } + + @NonNull + @Override + public final MethodUnhooker> hook(@NonNull Constructor origin, int priority, @NonNull Class hooker) { + return mBase.hook(origin, priority, hooker); + } + + @Override + public final boolean deoptimize(@NonNull Method method) { + return mBase.deoptimize(method); + } + + @Override + public final boolean deoptimize(@NonNull Constructor constructor) { + return mBase.deoptimize(constructor); + } + + @Nullable + @Override + public final Object invokeOrigin(@NonNull Method method, @Nullable Object thisObject, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException { + return mBase.invokeOrigin(method, thisObject, args); + } + + @Nullable + @Override + public final Object invokeSpecial(@NonNull Method method, @NonNull Object thisObject, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException { + return mBase.invokeSpecial(method, thisObject, args); + } + + @NonNull + @Override + public final T newInstanceOrigin(@NonNull Constructor constructor, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException, InstantiationException { + return mBase.newInstanceOrigin(constructor, args); + } + + @NonNull + @Override + public final U newInstanceSpecial(@NonNull Constructor constructor, @NonNull Class subClass, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException, InstantiationException { + return mBase.newInstanceSpecial(constructor, subClass, args); + } + + @Override + public final void log(@NonNull String message) { + mBase.log(message); + } + + @Override + public final void log(@NonNull String message, @NonNull Throwable throwable) { + mBase.log(message, throwable); + } + + @Nullable + @Override + public final DexParser parseDex(@NonNull ByteBuffer dexData, boolean includeAnnotations) throws IOException { + return mBase.parseDex(dexData, includeAnnotations); + } + + @Override + public SharedPreferences getRemotePreferences(@NonNull String name) { + return mBase.getRemotePreferences(name); + } + + @NonNull + @Override + public ApplicationInfo getApplicationInfo() { + return mBase.getApplicationInfo(); + } + + @NonNull + @Override + public Resources getResources() { + return mBase.getResources(); + } + + @NonNull + @Override + public FileInputStream openRemoteFileInput(@NonNull String name) throws FileNotFoundException { + return mBase.openRemoteFileInput(name); + } + + @NonNull + @Override + public String[] listRemoteFiles() { + return mBase.listRemoteFiles(); + } +} diff --git a/api/src/main/java/io/github/libxposed/api/XposedModule.java b/api/src/main/java/io/github/libxposed/api/XposedModule.java index 904b462..b2e1a03 100644 --- a/api/src/main/java/io/github/libxposed/api/XposedModule.java +++ b/api/src/main/java/io/github/libxposed/api/XposedModule.java @@ -7,15 +7,15 @@ import androidx.annotation.NonNull; * Entry classes will be instantiated exactly once for each process. */ @SuppressWarnings("unused") -public abstract class XposedModule extends XposedContextWrapper implements XposedModuleInterface { +public abstract class XposedModule extends XposedInterfaceWrapper implements XposedModuleInterface { /** * Instantiates a new Xposed module.
* When the module is loaded into the target process, the constructor will be called. * - * @param base The base context provided by the framework, should not be used by the module + * @param base The implementation interface provided by the framework, should not be used by the module * @param param Information about the process in which the module is loaded */ - public XposedModule(@NonNull XposedContext base, @NonNull ModuleLoadedParam param) { + public XposedModule(@NonNull XposedInterface base, @NonNull ModuleLoadedParam param) { super(base); } }