No XposedContext

This commit is contained in:
Nullptr 2023-08-15 17:36:22 +08:00
parent b581d269a3
commit 844d2984a0
No known key found for this signature in database
5 changed files with 190 additions and 249 deletions

View File

@ -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.<br/>
* This class should be extended by the Xposed framework as the implementation of Xposed interfaces.<br/>
* Modules should not use this class directly.
*/
public abstract class XposedContext extends Context implements XposedInterface {
}

View File

@ -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<Method> hook(@NonNull Method origin, @NonNull Class<? extends Hooker> hooker) {
return getBaseContext().hook(origin, hooker);
}
/**
* {@inheritDoc}
*/
@NonNull
@Override
public final MethodUnhooker<Method> hook(@NonNull Method origin, int priority, @NonNull Class<? extends Hooker> hooker) {
return getBaseContext().hook(origin, priority, hooker);
}
/**
* {@inheritDoc}
*/
@NonNull
@Override
public final <T> MethodUnhooker<Constructor<T>> hook(@NonNull Constructor<T> origin, @NonNull Class<? extends Hooker> hooker) {
return getBaseContext().hook(origin, hooker);
}
/**
* {@inheritDoc}
*/
@NonNull
@Override
public final <T> MethodUnhooker<Constructor<T>> hook(@NonNull Constructor<T> origin, int priority, @NonNull Class<? extends Hooker> hooker) {
return getBaseContext().hook(origin, priority, hooker);
}
/**
* {@inheritDoc}
*/
@Override
public final boolean deoptimize(@NonNull Method method) {
return getBaseContext().deoptimize(method);
}
/**
* {@inheritDoc}
*/
@Override
public final <T> boolean deoptimize(@NonNull Constructor<T> 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> T newInstanceOrigin(@NonNull Constructor<T> constructor, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException, InstantiationException {
return getBaseContext().newInstanceOrigin(constructor, args);
}
/**
* {@inheritDoc}
*/
@NonNull
@Override
public final <T, U> U newInstanceSpecial(@NonNull Constructor<T> constructor, @NonNull Class<U> 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();
}
}
}

View File

@ -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();
}

View File

@ -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<Method> hook(@NonNull Method origin, @NonNull Class<? extends Hooker> hooker) {
return mBase.hook(origin, hooker);
}
@NonNull
@Override
public final MethodUnhooker<Method> hook(@NonNull Method origin, int priority, @NonNull Class<? extends Hooker> hooker) {
return mBase.hook(origin, priority, hooker);
}
@NonNull
@Override
public final <T> MethodUnhooker<Constructor<T>> hook(@NonNull Constructor<T> origin, @NonNull Class<? extends Hooker> hooker) {
return mBase.hook(origin, hooker);
}
@NonNull
@Override
public final <T> MethodUnhooker<Constructor<T>> hook(@NonNull Constructor<T> origin, int priority, @NonNull Class<? extends Hooker> hooker) {
return mBase.hook(origin, priority, hooker);
}
@Override
public final boolean deoptimize(@NonNull Method method) {
return mBase.deoptimize(method);
}
@Override
public final <T> boolean deoptimize(@NonNull Constructor<T> 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> T newInstanceOrigin(@NonNull Constructor<T> constructor, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException, InstantiationException {
return mBase.newInstanceOrigin(constructor, args);
}
@NonNull
@Override
public final <T, U> U newInstanceSpecial(@NonNull Constructor<T> constructor, @NonNull Class<U> 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();
}
}

View File

@ -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.<br/>
* 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);
}
}