Move libxposed to a standalone gradle module

This commit is contained in:
LoveSy 2023-01-02 17:27:37 +08:00 committed by LoveSy
parent 439537fd89
commit 53d75bd10e
25 changed files with 193 additions and 131 deletions

1
api/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

12
api/build.gradle.kts Normal file
View File

@ -0,0 +1,12 @@
plugins {
id("java-library")
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
dependencies {
compileOnly("androidx.annotation:annotation:1.5.0")
}

View File

@ -0,0 +1,4 @@
package android.content;
public abstract class Context {
}

View File

@ -0,0 +1,16 @@
package android.content;
public class ContextWrapper extends Context {
public ContextWrapper(Context base) {
throw new UnsupportedOperationException("STUB");
}
protected void attachBaseContext(Context base) {
throw new UnsupportedOperationException("STUB");
}
public Context getBaseContext() {
throw new UnsupportedOperationException("SUTB");
}
}

View File

@ -0,0 +1,4 @@
package android.content.pm;
public class ApplicationInfo {
}

View File

@ -0,0 +1,4 @@
package android.content.res;
public class AssetManager {
}

View File

@ -0,0 +1,4 @@
package android.content.res;
public class Configuration {
}

View File

@ -0,0 +1,13 @@
package android.content.res;
import android.util.DisplayMetrics;
public class Resources {
protected Resources(ClassLoader classLoader) {
throw new UnsupportedOperationException("STUB");
}
protected Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
throw new UnsupportedOperationException("STUB");
}
}

View File

@ -0,0 +1,7 @@
package android.content.res;
public class TypedArray {
protected TypedArray(Resources resources) {
throw new UnsupportedOperationException("STUB");
}
}

View File

@ -0,0 +1,4 @@
package android.os;
public class Bundle {
}

View File

@ -0,0 +1,4 @@
package android.util;
public class DisplayMetrics {
}

View File

@ -110,7 +110,8 @@ public interface XposedInterface {
<T> boolean deoptimize(@Nullable Constructor<T> constructor); <T> boolean deoptimize(@Nullable Constructor<T> constructor);
@Nullable XposedUtils getUtils(); @Nullable
XposedUtils getUtils();
void log(@NonNull String message); void log(@NonNull String message);

View File

@ -1,7 +1,6 @@
package io.github.libxposed; package io.github.libxposed;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.res.XposedResources;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;

View File

@ -1,14 +1,16 @@
package android.content.res; package io.github.libxposed;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
public abstract class XposedResources extends Resources { public abstract class XposedResources extends Resources {
@SuppressWarnings("deprecation")
public XposedResources(AssetManager assets, DisplayMetrics metrics, Configuration config) { public XposedResources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
super(assets, metrics, config); super(assets, metrics, config);
} }
public XposedResources(ClassLoader classLoader) { public XposedResources(ClassLoader classLoader) {
super(null, null, null); super(classLoader);
} }
} }

View File

@ -0,0 +1,10 @@
package io.github.libxposed;
import android.content.res.Resources;
import android.content.res.TypedArray;
public class XposedTypedArray extends TypedArray {
public XposedTypedArray(Resources resources) {
super(resources);
}
}

View File

@ -17,17 +17,6 @@
* Copyright (C) 2021 - 2022 LSPosed Contributors * Copyright (C) 2021 - 2022 LSPosed Contributors
*/ */
import com.android.build.api.instrumentation.AsmClassVisitorFactory
import com.android.build.api.instrumentation.ClassContext
import com.android.build.api.instrumentation.ClassData
import com.android.build.api.instrumentation.InstrumentationParameters
import com.android.build.api.instrumentation.InstrumentationScope
import com.android.build.api.instrumentation.FramesComputationMode
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.Type
val apiCode: Int by rootProject.extra val apiCode: Int by rootProject.extra
val verName: String by rootProject.extra val verName: String by rootProject.extra
val verCode: Int by rootProject.extra val verCode: Int by rootProject.extra
@ -64,112 +53,6 @@ copy {
into("src/main/jni/src/") into("src/main/jni/src/")
} }
abstract class ExampleClassVisitorFactory : AsmClassVisitorFactory<InstrumentationParameters.None> {
override fun createClassVisitor(
classContext: ClassContext, nextClassVisitor: ClassVisitor
): ClassVisitor {
return object : ClassVisitor(Opcodes.ASM9, nextClassVisitor) {
override fun visit(
version: Int,
access: Int,
name: String?,
signature: String?,
superName: String?,
interfaces: Array<out String>?
) {
val newSuperName = "xposed/dummy/X${superName?.substringAfterLast('/')}SuperClass"
println("replace super class of $name to $newSuperName")
super.visit(
version,
access,
name,
signature,
newSuperName,
interfaces
)
}
override fun visitMethod(
access: Int,
name: String?,
descriptor: String?,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor {
return object : MethodVisitor(
Opcodes.ASM9, super.visitMethod(
access,
name,
descriptor,
signature,
exceptions
)
) {
override fun visitVarInsn(opcode: Int, `var`: Int) {
}
override fun visitInsn(opcode: Int) {
if (opcode != Opcodes.ACONST_NULL) {
super.visitInsn(opcode)
}
}
override fun visitMaxs(maxStack: Int, maxLocals: Int) {
super.visitMaxs(
if (maxLocals > maxStack) maxLocals else maxStack,
maxLocals
)
}
override fun visitMethodInsn(
opcode: Int,
owner: String?,
name: String?,
instDescriptor: String?,
isInterface: Boolean
) {
if (opcode == Opcodes.INVOKESPECIAL) {
for (i in 0 .. Type.getMethodType(descriptor).argumentTypes.size) {
super.visitVarInsn(Opcodes.ALOAD, i)
}
val newOwner =
"xposed/dummy/X${owner?.substringAfterLast('/')}SuperClass"
println("replace method call of $owner.$name$instDescriptor to $newOwner.$name$descriptor")
super.visitMethodInsn(
opcode,
newOwner,
name,
descriptor,
isInterface
)
} else {
super.visitMethodInsn(
opcode,
owner,
name,
instDescriptor,
isInterface
)
}
}
}
}
}
}
override fun isInstrumentable(classData: ClassData): Boolean {
return classData.className.startsWith("android.content.res.Xposed")
}
}
androidComponents.onVariants { variant ->
variant.instrumentation.transformClassesWith(
ExampleClassVisitorFactory::class.java, InstrumentationScope.PROJECT
) {}
variant.instrumentation.setAsmFramesComputationMode(FramesComputationMode.COPY_FRAMES)
}
dependencies { dependencies {
implementation("org.apache.commons:commons-lang3:3.12.0") implementation("org.apache.commons:commons-lang3:3.12.0")
implementation("de.upb.cs.swt:axml:2.1.3") implementation("de.upb.cs.swt:axml:2.1.3")
@ -178,4 +61,5 @@ dependencies {
implementation(projects.hiddenapi.bridge) implementation(projects.hiddenapi.bridge)
implementation(projects.services.daemonService) implementation(projects.services.daemonService)
implementation(projects.services.managerService) implementation(projects.services.managerService)
implementation(projects.api)
} }

View File

@ -66,7 +66,8 @@ import de.robv.android.xposed.XposedInit;
import de.robv.android.xposed.callbacks.XC_LayoutInflated; import de.robv.android.xposed.callbacks.XC_LayoutInflated;
import de.robv.android.xposed.callbacks.XC_LayoutInflated.LayoutInflatedParam; import de.robv.android.xposed.callbacks.XC_LayoutInflated.LayoutInflatedParam;
import de.robv.android.xposed.callbacks.XCallback; import de.robv.android.xposed.callbacks.XCallback;
import xposed.dummy.XTypedArraySuperClass; import io.github.libxposed.XposedResources;
import io.github.libxposed.XposedTypedArray;
/** /**
* {@link android.content.res.Resources} subclass that allows replacing individual resources. * {@link android.content.res.Resources} subclass that allows replacing individual resources.

View File

@ -1,7 +0,0 @@
package android.content.res;
public class XposedTypedArray extends TypedArray {
public XposedTypedArray(Resources resources) {
super();
}
}

View File

@ -21,7 +21,6 @@
package de.robv.android.xposed.callbacks; package de.robv.android.xposed.callbacks;
import android.content.res.XResources; import android.content.res.XResources;
import android.content.res.XposedResources;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -31,6 +30,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
import de.robv.android.xposed.IXposedHookInitPackageResources; import de.robv.android.xposed.IXposedHookInitPackageResources;
import io.github.libxposed.XposedModuleInterface; import io.github.libxposed.XposedModuleInterface;
import io.github.libxposed.XposedResources;
/** /**
* This class is only used for internal purposes, except for the {@link InitPackageResourcesParam} * This class is only used for internal purposes, except for the {@link InitPackageResourcesParam}

View File

@ -23,6 +23,15 @@ import org.apache.tools.ant.filters.ReplaceTokens
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.security.MessageDigest import java.security.MessageDigest
import java.util.Locale import java.util.Locale
import com.android.build.api.instrumentation.AsmClassVisitorFactory
import com.android.build.api.instrumentation.ClassContext
import com.android.build.api.instrumentation.ClassData
import com.android.build.api.instrumentation.InstrumentationParameters
import com.android.build.api.instrumentation.InstrumentationScope
import com.android.build.api.instrumentation.FramesComputationMode
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
plugins { plugins {
id("com.android.application") id("com.android.application")
@ -321,5 +330,94 @@ task<Exec>("reRunApp") {
finalizedBy(reRunDaemon) finalizedBy(reRunDaemon)
} }
abstract class ExampleClassVisitorFactory :
AsmClassVisitorFactory<InstrumentationParameters.None> {
override fun createClassVisitor(
classContext: ClassContext,
nextClassVisitor: ClassVisitor
): ClassVisitor {
return object :
ClassVisitor(Opcodes.ASM9, nextClassVisitor) {
override fun visit(
version: Int,
access: Int,
name: String?,
signature: String?,
superName: String?,
interfaces: Array<out String>?
) {
val newSuperName = "xposed/dummy/X${superName?.substringAfterLast('/')}SuperClass"
println("replace super class of $name to $newSuperName")
super.visit(
version,
access,
name,
signature,
newSuperName,
interfaces
)
}
override fun visitMethod(
access: Int,
name: String?,
descriptor: String?,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor {
return object : MethodVisitor(
Opcodes.ASM9, super.visitMethod(
access,
name,
descriptor,
signature,
exceptions
)
) {
override fun visitMethodInsn(
opcode: Int,
owner: String?,
name: String?,
instDescriptor: String?,
isInterface: Boolean
) {
if (opcode == Opcodes.INVOKESPECIAL) {
val newOwner =
"xposed/dummy/X${owner?.substringAfterLast('/')}SuperClass"
println("replace method call of $owner.$name$instDescriptor to $newOwner.$name$descriptor")
super.visitMethodInsn(
opcode,
newOwner,
name,
descriptor,
isInterface
)
} else {
super.visitMethodInsn(
opcode,
owner,
name,
instDescriptor,
isInterface
)
}
}
}
}
}
}
override fun isInstrumentable(classData: ClassData): Boolean {
return classData.className == "io.github.libxposed.XposedResources" || classData.className == "io.github.libxposed.XposedTypedArray"
}
}
androidComponents.onVariants { variant ->
variant.instrumentation.transformClassesWith(
ExampleClassVisitorFactory::class.java, InstrumentationScope.ALL
) {}
variant.instrumentation.setAsmFramesComputationMode(FramesComputationMode.COPY_FRAMES)
}
evaluationDependsOn(":app") evaluationDependsOn(":app")
evaluationDependsOn(":daemon") evaluationDependsOn(":daemon")

View File

@ -30,6 +30,7 @@ dependencyResolutionManagement {
rootProject.name = "LSPosed" rootProject.name = "LSPosed"
include( include(
":app", ":app",
":api",
":core", ":core",
":daemon", ":daemon",
":dex2oat", ":dex2oat",