Switch into mainline core branch
This commit is contained in:
parent
d7b508e731
commit
b89b425a53
|
|
@ -1,2 +0,0 @@
|
|||
/build
|
||||
/target
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
val androidCompileSdkVersion: Int by rootProject.extra
|
||||
val androidMinSdkVersion: Int by rootProject.extra
|
||||
val androidTargetSdkVersion: Int by rootProject.extra
|
||||
|
||||
val androidSourceCompatibility: JavaVersion by rootProject.extra
|
||||
val androidTargetCompatibility: JavaVersion by rootProject.extra
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
}
|
||||
|
||||
android {
|
||||
flavorDimensions += "api"
|
||||
productFlavors {
|
||||
create("Riru") {
|
||||
dimension = "api"
|
||||
}
|
||||
}
|
||||
|
||||
compileSdk = androidCompileSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdk = androidMinSdkVersion
|
||||
targetSdk = androidTargetSdkVersion
|
||||
|
||||
multiDexEnabled = false
|
||||
|
||||
signingConfigs.create("config") {
|
||||
val androidStoreFile = project.findProperty("androidStoreFile") as String?
|
||||
if (!androidStoreFile.isNullOrEmpty()) {
|
||||
storeFile = file(androidStoreFile)
|
||||
storePassword = project.property("androidStorePassword") as String
|
||||
keyAlias = project.property("androidKeyAlias") as String
|
||||
keyPassword = project.property("androidKeyPassword") as String
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = androidSourceCompatibility
|
||||
targetCompatibility = androidTargetCompatibility
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
isDebuggable = true
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
signingConfig = if (signingConfigs["config"].storeFile != null) signingConfigs["config"] else signingConfigs["debug"]
|
||||
}
|
||||
release {
|
||||
isDebuggable = false
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
signingConfig = if (signingConfigs["config"].storeFile != null) signingConfigs["config"] else signingConfigs["debug"]
|
||||
}
|
||||
}
|
||||
|
||||
lint {
|
||||
abortOnError = false
|
||||
}
|
||||
}
|
||||
|
||||
androidComponents.onVariants { variant ->
|
||||
val variantCapped = variant.name.capitalize()
|
||||
val variantLowered = variant.name.toLowerCase()
|
||||
|
||||
task<Copy>("copyDex$variantCapped") {
|
||||
dependsOn("assemble$variantCapped")
|
||||
from("$buildDir/intermediates/dex/$variantCapped/mergeDex$variantCapped/classes.dex")
|
||||
rename("classes.dex", "lsp.dex")
|
||||
into("${rootProject.projectDir}/out/assets/dex")
|
||||
}
|
||||
|
||||
task<Copy>("copySo$variantCapped") {
|
||||
dependsOn("assemble$variantCapped")
|
||||
from("$buildDir/intermediates/merged_native_libs/$variantCapped/out/lib")
|
||||
into("${rootProject.projectDir}/out/assets/so")
|
||||
}
|
||||
|
||||
task("copy$variantCapped") {
|
||||
dependsOn("copySo$variantCapped")
|
||||
dependsOn("copyDex$variantCapped")
|
||||
|
||||
doLast {
|
||||
println("Dex and so files has been copied to ${rootProject.projectDir}${File.separator}out")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(projects.hiddenapiStubs)
|
||||
implementation(projects.daemonService)
|
||||
implementation(projects.lspcore)
|
||||
implementation(projects.hiddenapiBridge)
|
||||
implementation(projects.share)
|
||||
implementation(projects.imanager)
|
||||
|
||||
implementation("com.google.code.gson:gson:2.9.0")
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.lsposed.lspatch">
|
||||
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:appComponentFactory="org.lsposed.lspatch.appstub.LSPAppComponentFactoryStub"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/sample_app_title"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true">
|
||||
<activity android:name="org.lsposed.lspatch.tester.MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<meta-data android:name="xposedmodule" android:value="true"/>
|
||||
<meta-data android:name="xposedminversion" android:value="53"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -1 +0,0 @@
|
|||
palceholder
|
||||
|
|
@ -1 +0,0 @@
|
|||
org.lsposed.lspatch.tester.Hook
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package org.lsposed.lspatch.tester;
|
||||
|
||||
import de.robv.android.xposed.IXposedHookLoadPackage;
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||
|
||||
public class Hook implements IXposedHookLoadPackage {
|
||||
@Override
|
||||
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
|
||||
XposedHelpers.findAndHookMethod("org.lsposed.lspatch.tester.MainActivity", lpparam.classLoader, "checkXposed2", new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
||||
param.setResult(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package org.lsposed.lspatch.tester;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.lsposed.lspatch.R;
|
||||
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
|
||||
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
XposedHelpers.findAndHookMethod(this.getClass(), "checkXposed", new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
|
||||
param.setResult(true);
|
||||
}
|
||||
});
|
||||
|
||||
TextView textView = findViewById(R.id.msg);
|
||||
if (checkXposed() && checkXposed2()) {
|
||||
textView.setText("ok");
|
||||
}
|
||||
else {
|
||||
textView.setText("fail");
|
||||
}
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
}
|
||||
|
||||
public boolean checkXposed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean checkXposed2() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="org.lsposed.lspatch.tester.MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/msg"
|
||||
android:textSize="50sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World!" />
|
||||
</RelativeLayout>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB |
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="sample_app_title">Xposed Module Loader</string>
|
||||
</resources>
|
||||
|
|
@ -1,23 +1,10 @@
|
|||
val androidMinSdkVersion: Int by rootProject.extra
|
||||
val androidTargetSdkVersion: Int by rootProject.extra
|
||||
val androidCompileSdkVersion: Int by rootProject.extra
|
||||
val androidBuildToolsVersion: String by rootProject.extra
|
||||
|
||||
val androidSourceCompatibility: JavaVersion by rootProject.extra
|
||||
val androidTargetCompatibility: JavaVersion by rootProject.extra
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk = androidCompileSdkVersion
|
||||
buildToolsVersion = androidBuildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdk = androidMinSdkVersion
|
||||
targetSdk = androidTargetSdkVersion
|
||||
|
||||
multiDexEnabled = false
|
||||
}
|
||||
|
||||
|
|
@ -27,11 +14,6 @@ android {
|
|||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = androidSourceCompatibility
|
||||
targetCompatibility = androidTargetCompatibility
|
||||
}
|
||||
}
|
||||
|
||||
androidComponents.onVariants { variant ->
|
||||
|
|
@ -55,7 +37,7 @@ androidComponents.onVariants { variant ->
|
|||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(projects.hiddenapiStubs)
|
||||
compileOnly(projects.hiddenapi.stubs)
|
||||
|
||||
implementation("de.upb.cs.swt:axml:2.1.2")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public class LSPAppComponentFactoryStub extends AppComponentFactory {
|
|||
vmInstructionSet.setAccessible(true);
|
||||
|
||||
String arch = (String) vmInstructionSet.invoke(getRuntime.invoke(null));
|
||||
String path = cl.getResource("assets/lspatch/lspd/" + arch + "/liblspd.so").getPath().substring(5);
|
||||
String path = cl.getResource("assets/lspatch/so/" + arch + "/liblspatch.so").getPath().substring(5);
|
||||
System.load(path);
|
||||
} catch (Throwable e) {
|
||||
Log.e("LSPatch", "load lspd error", e);
|
||||
|
|
|
|||
177
build.gradle.kts
177
build.gradle.kts
|
|
@ -1,14 +1,20 @@
|
|||
import com.android.build.api.dsl.ApplicationExtension
|
||||
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
|
||||
import com.android.build.gradle.BaseExtension
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.internal.storage.file.FileRepository
|
||||
|
||||
plugins {
|
||||
id("com.android.application") apply false
|
||||
id("com.android.library") apply false
|
||||
}
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
val agpVersion by extra("7.1.2")
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:$agpVersion")
|
||||
classpath("org.eclipse.jgit:org.eclipse.jgit:6.0.0.202111291000-r")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
|
||||
}
|
||||
|
|
@ -41,13 +47,6 @@ val androidBuildToolsVersion by extra("31.0.0")
|
|||
val androidSourceCompatibility by extra(JavaVersion.VERSION_11)
|
||||
val androidTargetCompatibility by extra(JavaVersion.VERSION_11)
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register<Delete>("clean") {
|
||||
delete(rootProject.buildDir)
|
||||
}
|
||||
|
|
@ -59,3 +58,163 @@ listOf("Debug", "Release").forEach { variant ->
|
|||
dependsOn(projects.manager.dependencyProject.tasks["build$variant"])
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.configureBaseExtension() {
|
||||
extensions.findByType(BaseExtension::class)?.run {
|
||||
compileSdkVersion(androidCompileSdkVersion)
|
||||
ndkVersion = androidCompileNdkVersion
|
||||
buildToolsVersion = androidBuildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdk = androidMinSdkVersion
|
||||
targetSdk = androidTargetSdkVersion
|
||||
versionCode = verCode
|
||||
versionName = verName
|
||||
|
||||
signingConfigs.create("config") {
|
||||
val androidStoreFile = project.findProperty("androidStoreFile") as String?
|
||||
if (!androidStoreFile.isNullOrEmpty()) {
|
||||
storeFile = file(androidStoreFile)
|
||||
storePassword = project.property("androidStorePassword") as String
|
||||
keyAlias = project.property("androidKeyAlias") as String
|
||||
keyPassword = project.property("androidKeyPassword") as String
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments += "-DEXTERNAL_ROOT=${File(rootDir.absolutePath, "core/external")}"
|
||||
arguments += "-DCORE_ROOT=${File(rootDir.absolutePath, "core/core/src/main/jni")}"
|
||||
abiFilters("arm64-v8a", "armeabi-v7a", "x86", "x86_64")
|
||||
val flags = arrayOf(
|
||||
"-Wall",
|
||||
"-Qunused-arguments",
|
||||
"-Wno-gnu-string-literal-operator-template",
|
||||
"-fno-rtti",
|
||||
"-fvisibility=hidden",
|
||||
"-fvisibility-inlines-hidden",
|
||||
"-fno-exceptions",
|
||||
"-fno-stack-protector",
|
||||
"-fomit-frame-pointer",
|
||||
"-Wno-builtin-macro-redefined",
|
||||
"-Wno-unused-value",
|
||||
"-D__FILE__=__FILE_NAME__",
|
||||
)
|
||||
cppFlags("-std=c++20", *flags)
|
||||
cFlags("-std=c18", *flags)
|
||||
arguments(
|
||||
"-DANDROID_STL=none",
|
||||
"-DVERSION_CODE=$verCode",
|
||||
"-DVERSION_NAME=$verName",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
targetCompatibility(androidTargetCompatibility)
|
||||
sourceCompatibility(androidSourceCompatibility)
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
all {
|
||||
signingConfig = if (signingConfigs["config"].storeFile != null) signingConfigs["config"] else signingConfigs["debug"]
|
||||
}
|
||||
named("debug") {
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments.addAll(
|
||||
arrayOf(
|
||||
"-DCMAKE_CXX_FLAGS_DEBUG=-Og",
|
||||
"-DCMAKE_C_FLAGS_DEBUG=-Og",
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
named("release") {
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
val flags = arrayOf(
|
||||
"-Wl,--exclude-libs,ALL",
|
||||
"-ffunction-sections",
|
||||
"-fdata-sections",
|
||||
"-Wl,--gc-sections",
|
||||
"-fno-unwind-tables",
|
||||
"-fno-asynchronous-unwind-tables",
|
||||
"-flto=thin",
|
||||
"-Wl,--thinlto-cache-policy,cache_size_bytes=300m",
|
||||
"-Wl,--thinlto-cache-dir=${buildDir.absolutePath}/.lto-cache",
|
||||
)
|
||||
cppFlags.addAll(flags)
|
||||
cFlags.addAll(flags)
|
||||
val configFlags = arrayOf(
|
||||
"-Oz",
|
||||
"-DNDEBUG"
|
||||
).joinToString(" ")
|
||||
arguments.addAll(
|
||||
arrayOf(
|
||||
"-DCMAKE_CXX_FLAGS_RELEASE=$configFlags",
|
||||
"-DCMAKE_CXX_FLAGS_RELWITHDEBINFO=$configFlags",
|
||||
"-DCMAKE_C_FLAGS_RELEASE=$configFlags",
|
||||
"-DCMAKE_C_FLAGS_RELWITHDEBINFO=$configFlags",
|
||||
"-DDEBUG_SYMBOLS_PATH=${buildDir.absolutePath}/symbols",
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extensions.findByType(ApplicationExtension::class)?.lint {
|
||||
abortOnError = true
|
||||
checkReleaseBuilds = false
|
||||
}
|
||||
|
||||
extensions.findByType(ApplicationAndroidComponentsExtension::class)?.let { androidComponents ->
|
||||
val optimizeReleaseRes = task("optimizeReleaseRes").doLast {
|
||||
val aapt2 = File(
|
||||
androidComponents.sdkComponents.sdkDirectory.get().asFile,
|
||||
"build-tools/${androidBuildToolsVersion}/aapt2"
|
||||
)
|
||||
val zip = java.nio.file.Paths.get(
|
||||
project.buildDir.path,
|
||||
"intermediates",
|
||||
"optimized_processed_res",
|
||||
"release",
|
||||
"resources-release-optimize.ap_"
|
||||
)
|
||||
val optimized = File("${zip}.opt")
|
||||
val cmd = exec {
|
||||
commandLine(
|
||||
aapt2, "optimize",
|
||||
"--collapse-resource-names",
|
||||
"--enable-sparse-encoding",
|
||||
"-o", optimized,
|
||||
zip
|
||||
)
|
||||
isIgnoreExitValue = false
|
||||
}
|
||||
if (cmd.exitValue == 0) {
|
||||
delete(zip)
|
||||
optimized.renameTo(zip.toFile())
|
||||
}
|
||||
}
|
||||
|
||||
tasks.whenTaskAdded {
|
||||
if (name == "optimizeReleaseResources") {
|
||||
finalizedBy(optimizeReleaseRes)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subprojects {
|
||||
plugins.withId("com.android.application") {
|
||||
configureBaseExtension()
|
||||
}
|
||||
plugins.withId("com.android.library") {
|
||||
configureBaseExtension()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
core
2
core
|
|
@ -1 +1 @@
|
|||
Subproject commit 216a6f00435b4ab00f5fadc80c1c3b1e7ac9b20c
|
||||
Subproject commit e0de4ca6d7c1757de85094672a8c069e6a90fb65
|
||||
|
|
@ -1,20 +1,8 @@
|
|||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
version_name=1.0
|
||||
version_code=1
|
||||
|
||||
android.experimental.enableNewResourceShrinker=true
|
||||
android.experimental.enableNewResourceShrinker.preciseShrinking=true
|
||||
android.enableAppCompileTimeRClass=true
|
||||
android.nonTransitiveRClass=true
|
||||
android.enableR8.fullMode=true
|
||||
android.useAndroidX=true
|
||||
|
||||
|
||||
agpVersion=7.1.2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
|
|||
|
|
@ -1,11 +1,3 @@
|
|||
val androidMinSdkVersion: Int by rootProject.extra
|
||||
val androidTargetSdkVersion: Int by rootProject.extra
|
||||
val androidCompileSdkVersion: Int by rootProject.extra
|
||||
val androidBuildToolsVersion: String by rootProject.extra
|
||||
|
||||
val androidSourceCompatibility: JavaVersion by rootProject.extra
|
||||
val androidTargetCompatibility: JavaVersion by rootProject.extra
|
||||
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
}
|
||||
|
|
@ -16,25 +8,13 @@ android {
|
|||
dimension = "api"
|
||||
}
|
||||
|
||||
compileSdk = androidCompileSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdk = androidMinSdkVersion
|
||||
targetSdk = androidTargetSdkVersion
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = androidSourceCompatibility
|
||||
targetCompatibility = androidTargetCompatibility
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":daemon-service"))
|
||||
api(projects.services.daemonService)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,8 @@
|
|||
import com.android.build.gradle.BaseExtension
|
||||
|
||||
val androidCompileSdkVersion: Int by rootProject.extra
|
||||
val androidMinSdkVersion: Int by rootProject.extra
|
||||
val androidTargetSdkVersion: Int by rootProject.extra
|
||||
|
||||
val defaultManagerPackageName: String by rootProject.extra
|
||||
val apiCode: Int by rootProject.extra
|
||||
val verCode: Int by rootProject.extra
|
||||
val verName: String by rootProject.extra
|
||||
val coreVerCode: Int by rootProject.extra
|
||||
val coreVerName: String by rootProject.extra
|
||||
|
||||
val androidSourceCompatibility: JavaVersion by rootProject.extra
|
||||
val androidTargetCompatibility: JavaVersion by rootProject.extra
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-parcelize")
|
||||
|
|
@ -21,14 +10,8 @@ plugins {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdk = androidCompileSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
applicationId = defaultManagerPackageName
|
||||
minSdk = androidMinSdkVersion
|
||||
targetSdk = androidTargetSdkVersion
|
||||
versionCode = verCode
|
||||
versionName = verName
|
||||
|
||||
buildConfigField("int", "API_CODE", """$apiCode""")
|
||||
buildConfigField("int", "CORE_VERSION_CODE", """$coreVerCode""")
|
||||
|
|
@ -39,15 +22,9 @@ android {
|
|||
release {
|
||||
isMinifyEnabled = true
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
signingConfig = projects.app.dependencyProject.extensions.getByName<BaseExtension>("android").buildTypes["release"].signingConfig
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = androidSourceCompatibility
|
||||
targetCompatibility = androidTargetCompatibility
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
|
|
@ -70,7 +47,7 @@ afterEvaluate {
|
|||
|
||||
task<Copy>("copy${variantCapped}Assets") {
|
||||
dependsOn(":appstub:copy$variantCapped")
|
||||
dependsOn(":app:copyRiru$variantCapped")
|
||||
dependsOn(":patch-loader:copy$variantCapped")
|
||||
tasks["merge${variantCapped}Assets"].dependsOn(this)
|
||||
|
||||
into("$buildDir/intermediates/assets/$variantLowered/merge${variantCapped}Assets")
|
||||
|
|
@ -92,11 +69,11 @@ dependencies {
|
|||
implementation("androidx.core:core-ktx:1.7.0")
|
||||
implementation("androidx.activity:activity-compose:1.5.0-alpha03")
|
||||
implementation("androidx.compose.material:material-icons-extended:1.1.1")
|
||||
implementation("androidx.compose.material3:material3:1.0.0-alpha06")
|
||||
implementation("androidx.compose.material3:material3:1.0.0-alpha07")
|
||||
implementation("androidx.compose.runtime:runtime-livedata:1.1.1")
|
||||
implementation("androidx.compose.ui:ui:1.1.1")
|
||||
implementation("androidx.compose.ui:ui-tooling:1.1.1")
|
||||
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-alpha03")
|
||||
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-alpha04")
|
||||
implementation("androidx.navigation:navigation-compose:2.5.0-alpha03")
|
||||
implementation("androidx.preference:preference:1.2.0")
|
||||
implementation("com.google.accompanist:accompanist-drawablepainter:0.24.2-alpha")
|
||||
|
|
|
|||
|
|
@ -35,13 +35,13 @@ val jar = tasks.jar.get()
|
|||
|
||||
tasks.register("buildDebug") {
|
||||
jar.dependsOn(":appstub:copyDebug")
|
||||
jar.dependsOn(":app:copyRiruDebug")
|
||||
jar.dependsOn(":patch-loader:copyDebug")
|
||||
dependsOn(tasks.build)
|
||||
}
|
||||
|
||||
tasks.register("buildRelease") {
|
||||
jar.dependsOn(":appstub:copyRelease")
|
||||
jar.dependsOn(":app:copyRiruRelease")
|
||||
jar.dependsOn(":patch-loader:copyRelease")
|
||||
dependsOn(tasks.build)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
/build
|
||||
/.cxx
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
plugins {
|
||||
id("com.android.application")
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
multiDexEnabled = false
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
isDebuggable = true
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
}
|
||||
release {
|
||||
isDebuggable = false
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path("src/main/jni/CMakeLists.txt")
|
||||
}
|
||||
}
|
||||
|
||||
lint {
|
||||
abortOnError = false
|
||||
}
|
||||
}
|
||||
|
||||
androidComponents.onVariants { variant ->
|
||||
val variantCapped = variant.name.capitalize()
|
||||
|
||||
task<Copy>("copyDex$variantCapped") {
|
||||
dependsOn("assemble$variantCapped")
|
||||
from("$buildDir/intermediates/dex/$variantCapped/mergeDex$variantCapped/classes.dex")
|
||||
rename("classes.dex", "lsp.dex")
|
||||
into("${rootProject.projectDir}/out/assets/dex")
|
||||
}
|
||||
|
||||
task<Copy>("copySo$variantCapped") {
|
||||
dependsOn("assemble$variantCapped")
|
||||
from(
|
||||
fileTree(
|
||||
"dir" to "$buildDir/intermediates/merged_native_libs/$variantCapped/out/lib",
|
||||
"include" to listOf("**/liblspatch.so")
|
||||
)
|
||||
)
|
||||
into("${rootProject.projectDir}/out/assets/so")
|
||||
}
|
||||
|
||||
task("copy$variantCapped") {
|
||||
dependsOn("copySo$variantCapped")
|
||||
dependsOn("copyDex$variantCapped")
|
||||
|
||||
doLast {
|
||||
println("Dex and so files has been copied to ${rootProject.projectDir}${File.separator}out")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(projects.hiddenapi.stubs)
|
||||
implementation(projects.core)
|
||||
implementation(projects.hiddenapi.bridge)
|
||||
implementation(projects.services.daemonService)
|
||||
implementation(projects.imanager)
|
||||
implementation(projects.share)
|
||||
|
||||
implementation("com.google.code.gson:gson:2.9.0")
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="org.lsposed.lspatch.loader" />
|
||||
|
|
@ -29,7 +29,7 @@ import org.lsposed.lspatch.manager.ModuleLoader;
|
|||
import org.lsposed.lspatch.share.Constants;
|
||||
import org.lsposed.lspatch.share.PatchConfig;
|
||||
import org.lsposed.lspd.config.ApplicationServiceClient;
|
||||
import org.lsposed.lspd.core.Main;
|
||||
import org.lsposed.lspd.core.Startup;
|
||||
import org.lsposed.lspd.models.Module;
|
||||
import org.lsposed.lspd.nativebridge.SigBypass;
|
||||
|
||||
|
|
@ -53,7 +53,6 @@ import java.util.zip.ZipFile;
|
|||
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.XposedInit;
|
||||
import hidden.HiddenApiBridge;
|
||||
|
||||
/**
|
||||
|
|
@ -104,10 +103,9 @@ public class LSPApplication extends ApplicationServiceClient {
|
|||
try {
|
||||
disableProfile(context);
|
||||
loadModules(context);
|
||||
Main.forkPostCommon(false, context.getDataDir().toString(), ActivityThread.currentProcessName());
|
||||
doHook(context);
|
||||
Startup.initXposed(false);
|
||||
Log.i(TAG, "Start loading modules");
|
||||
XposedInit.loadModules();
|
||||
Startup.bootstrapXposed(ActivityThread.currentProcessName());
|
||||
// WARN: Since it uses `XResource`, the following class should not be initialized
|
||||
// before forkPostCommon is invoke. Otherwise, you will get failure of XResources
|
||||
LSPLoader.initModules(appLoadedApk);
|
||||
|
|
@ -116,9 +114,11 @@ public class LSPApplication extends ApplicationServiceClient {
|
|||
switchClassLoader("mBaseClassLoader");
|
||||
switchClassLoader("mDefaultClassLoader");
|
||||
switchClassLoader("mClassLoader");
|
||||
doSigBypass(context);
|
||||
} catch (Throwable e) {
|
||||
Log.e(TAG, "Do hook", e);
|
||||
}
|
||||
Log.i(TAG, "LSPatch bootstrap completed");
|
||||
}
|
||||
|
||||
private static Context createLoadedApkWithContext() {
|
||||
|
|
@ -294,7 +294,7 @@ public class LSPApplication extends ApplicationServiceClient {
|
|||
return field.getInt(null);
|
||||
}
|
||||
|
||||
private static void byPassSignature(Context context) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
|
||||
private static void bypassSignature(Context context) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
|
||||
final int TRANSACTION_getPackageInfo = getTranscationId("android.content.pm.IPackageManager$Stub", "TRANSACTION_getPackageInfo");
|
||||
XposedHelpers.findAndHookMethod("android.os.BinderProxy", null, "transact", int.class, Parcel.class, Parcel.class, int.class, new XC_MethodHook() {
|
||||
@Override
|
||||
|
|
@ -359,10 +359,10 @@ public class LSPApplication extends ApplicationServiceClient {
|
|||
});
|
||||
}
|
||||
|
||||
private static void doHook(Context context) throws IllegalAccessException, ClassNotFoundException, IOException, NoSuchFieldException {
|
||||
private static void doSigBypass(Context context) throws IllegalAccessException, ClassNotFoundException, IOException, NoSuchFieldException {
|
||||
if (config.sigBypassLevel >= Constants.SIGBYPASS_LV_PM) {
|
||||
XLog.d(TAG, "Original signature: " + config.originalSignature.substring(0, 16) + "...");
|
||||
byPassSignature(context);
|
||||
bypassSignature(context);
|
||||
}
|
||||
if (config.sigBypassLevel >= Constants.SIGBYPASS_LV_PM_OPENAT) {
|
||||
String cacheApkPath;
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package org.lsposed.lspatch.loader.util;
|
||||
|
||||
|
||||
import org.lsposed.lspd.BuildConfig;
|
||||
import org.lsposed.lspatch.loader.BuildConfig;
|
||||
|
||||
public class XLog {
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.lsposed.lspd.nativebridge;
|
||||
|
||||
public class SigBypass {
|
||||
public static native void enableOpenatHook(String origApkPath, String cacheApkPath);
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
project(lspatch)
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
add_subdirectory(${CORE_ROOT} core)
|
||||
|
||||
aux_source_directory(src SRC_LIST)
|
||||
aux_source_directory(src/jni SRC_LIST)
|
||||
set(SRC_LIST ${SRC_LIST} api/patch_main.cpp)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED ${SRC_LIST})
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC include)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE src)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} core log)
|
||||
|
||||
if (DEFINED DEBUG_SYMBOLS_PATH)
|
||||
set(DEBUG_SYMBOLS_PATH ${DEBUG_SYMBOLS_PATH}/${API})
|
||||
message(STATUS "Debug symbols will be placed at ${DEBUG_SYMBOLS_PATH}")
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${DEBUG_SYMBOLS_PATH}/${ANDROID_ABI}
|
||||
COMMAND ${CMAKE_OBJCOPY} --only-keep-debug $<TARGET_FILE:${PROJECT_NAME}>
|
||||
${DEBUG_SYMBOLS_PATH}/${ANDROID_ABI}/${PROJECT_NAME}.debug
|
||||
COMMAND ${CMAKE_STRIP} --strip-all $<TARGET_FILE:${PROJECT_NAME}>
|
||||
COMMAND ${CMAKE_OBJCOPY} --add-gnu-debuglink ${DEBUG_SYMBOLS_PATH}/${ANDROID_ABI}/${PROJECT_NAME}.debug
|
||||
$<TARGET_FILE:${PROJECT_NAME}>)
|
||||
endif()
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* This file is part of LSPosed.
|
||||
*
|
||||
* LSPosed is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LSPosed is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (C) 2022 LSPosed Contributors
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Nullptr on 2022/3/17.
|
||||
//
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "patch_loader.h"
|
||||
|
||||
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
JNIEnv* env;
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
lspd::PatchLoader::Init();
|
||||
lspd::PatchLoader::GetInstance()->Load(env);
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// Created by loves on 6/19/2021.
|
||||
//
|
||||
|
||||
#ifndef LSPATCH_PROFILE_SAVER_H
|
||||
#define LSPATCH_PROFILE_SAVER_H
|
||||
|
||||
#include "utils/hook_helper.hpp"
|
||||
|
||||
using namespace lsplant;
|
||||
|
||||
namespace art {
|
||||
CREATE_MEM_HOOK_STUB_ENTRY(
|
||||
"_ZN3art12ProfileSaver20ProcessProfilingInfoEbPt",
|
||||
bool, ProcessProfilingInfo, (void * thiz, bool, uint16_t *), {
|
||||
LOGD("skipped profile saving");
|
||||
return true;
|
||||
});
|
||||
|
||||
CREATE_MEM_HOOK_STUB_ENTRY(
|
||||
"_ZN3art12ProfileSaver20ProcessProfilingInfoEbbPt",
|
||||
bool, ProcessProfilingInfoWithBool, (void * thiz, bool, bool, uint16_t *), {
|
||||
LOGD("skipped profile saving");
|
||||
return true;
|
||||
});
|
||||
|
||||
CREATE_HOOK_STUB_ENTRY(
|
||||
"execve",
|
||||
int, execve, (const char *pathname, const char *argv[], char *const envp[]), {
|
||||
if (strstr(pathname, "dex2oat")) {
|
||||
size_t count = 0;
|
||||
while (argv[count++] != nullptr);
|
||||
std::unique_ptr<const char *[]> new_args = std::make_unique<const char *[]>(
|
||||
count + 1);
|
||||
for (size_t i = 0; i < count - 1; ++i)
|
||||
new_args[i] = argv[i];
|
||||
new_args[count - 1] = "--inline-max-code-units=0";
|
||||
new_args[count] = nullptr;
|
||||
|
||||
LOGD("dex2oat by disable inline!");
|
||||
int ret = backup(pathname, new_args.get(), envp);
|
||||
return ret;
|
||||
}
|
||||
int ret = backup(pathname, argv, envp);
|
||||
return ret;
|
||||
});
|
||||
|
||||
|
||||
static void DisableInline(const HookHandler &handler) {
|
||||
HookSyms(handler, ProcessProfilingInfo, ProcessProfilingInfoWithBool);
|
||||
HookSymNoHandle(handler, reinterpret_cast<void*>(&::execve), execve);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //LSPATCH_PROFILE_SAVER_H
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* This file is part of LSPosed.
|
||||
*
|
||||
* LSPosed is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LSPosed is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (C) 2021 - 2022 LSPosed Contributors
|
||||
*/
|
||||
|
||||
#ifndef LSPATCH_OAT_FILE_MANAGER_H
|
||||
#define LSPATCH_OAT_FILE_MANAGER_H
|
||||
|
||||
#include "context.h"
|
||||
#include "utils/hook_helper.hpp"
|
||||
|
||||
using namespace lsplant;
|
||||
|
||||
namespace art {
|
||||
CREATE_MEM_HOOK_STUB_ENTRY(
|
||||
"_ZN3art14OatFileManager25RunBackgroundVerificationERKNSt3__16vectorIPKNS_7DexFileENS1_9allocatorIS5_EEEEP8_jobjectPKc",
|
||||
void, RunBackgroundVerificationWithContext,
|
||||
(void * thiz, const std::vector<const void *> &dex_files,
|
||||
jobject class_loader,
|
||||
const char *class_loader_context), {
|
||||
if (lspd::Context::GetInstance()->GetCurrentClassLoader() == nullptr) {
|
||||
LOGD("Disabled background verification");
|
||||
return;
|
||||
}
|
||||
backup(thiz, dex_files, class_loader, class_loader_context);
|
||||
});
|
||||
|
||||
CREATE_MEM_HOOK_STUB_ENTRY(
|
||||
"_ZN3art14OatFileManager25RunBackgroundVerificationERKNSt3__16vectorIPKNS_7DexFileENS1_9allocatorIS5_EEEEP8_jobject",
|
||||
void, RunBackgroundVerification,
|
||||
(void * thiz, const std::vector<const void *> &dex_files,
|
||||
jobject class_loader), {
|
||||
if (lspd::Context::GetInstance()->GetCurrentClassLoader() == nullptr) {
|
||||
LOGD("Disabled background verification");
|
||||
return;
|
||||
}
|
||||
backup(thiz, dex_files, class_loader);
|
||||
});
|
||||
|
||||
|
||||
static void DisableBackgroundVerification(const lsplant::HookHandler &handler) {
|
||||
const int api_level = lspd::GetAndroidApiLevel();
|
||||
if (api_level >= __ANDROID_API_Q__) {
|
||||
HookSyms(handler, RunBackgroundVerificationWithContext, RunBackgroundVerification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //LSPATCH_OAT_FILE_MANAGER_H
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// Created by VIP on 2021/4/25.
|
||||
//
|
||||
|
||||
#include "bypass_sig.h"
|
||||
#include "elf_util.h"
|
||||
#include "logging.h"
|
||||
#include "native_util.h"
|
||||
#include "patch_loader.h"
|
||||
#include "utils/hook_helper.hpp"
|
||||
#include "utils/jni_helper.hpp"
|
||||
|
||||
namespace lspd {
|
||||
|
||||
std::string apkPath;
|
||||
std::string redirectPath;
|
||||
|
||||
CREATE_HOOK_STUB_ENTRY(
|
||||
"__openat",
|
||||
int, __openat,
|
||||
(int fd, const char* pathname, int flag, int mode), {
|
||||
if (pathname == apkPath) {
|
||||
LOGD("redirect openat");
|
||||
return backup(fd, redirectPath.c_str(), flag, mode);
|
||||
}
|
||||
return backup(fd, pathname, flag, mode);
|
||||
});
|
||||
|
||||
LSP_DEF_NATIVE_METHOD(void, SigBypass, enableOpenatHook, jstring origApkPath, jstring cacheApkPath) {
|
||||
auto sym_openat = SandHook::ElfImg("libc.so").getSymbAddress<void *>("__openat");
|
||||
auto r = HookSymNoHandle(handler, sym_openat, __openat);
|
||||
if (!r) {
|
||||
LOGE("Hook __openat fail");
|
||||
return;
|
||||
}
|
||||
lsplant::JUTFString str1(env, origApkPath);
|
||||
lsplant::JUTFString str2(env, cacheApkPath);
|
||||
apkPath = str1.get();
|
||||
redirectPath = str2.get();
|
||||
LOGD("apkPath %s", apkPath.c_str());
|
||||
LOGD("redirectPath %s", redirectPath.c_str());
|
||||
}
|
||||
|
||||
static JNINativeMethod gMethods[] = {
|
||||
LSP_NATIVE_METHOD(SigBypass, enableOpenatHook, "(Ljava/lang/String;Ljava/lang/String;)V")
|
||||
};
|
||||
|
||||
void RegisterBypass(JNIEnv* env) {
|
||||
REGISTER_LSP_NATIVE_METHODS(SigBypass);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
namespace lspd {
|
||||
|
||||
void RegisterBypass(JNIEnv* env);
|
||||
|
||||
} // namespace lspd
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* This file is part of LSPosed.
|
||||
*
|
||||
* LSPosed is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LSPosed is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (C) 2022 LSPosed Contributors
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Nullptr on 2022/3/17.
|
||||
//
|
||||
|
||||
#include "art/runtime/oat_file_manager.h"
|
||||
#include "art/runtime/jit/profile_saver.h"
|
||||
#include "elf_util.h"
|
||||
#include "jni/bypass_sig.h"
|
||||
#include "native_hook.h"
|
||||
#include "native_util.h"
|
||||
#include "patch_loader.h"
|
||||
#include "symbol_cache.h"
|
||||
#include "utils/jni_helper.hpp"
|
||||
|
||||
using namespace lsplant;
|
||||
|
||||
namespace lspd {
|
||||
|
||||
void PatchLoader::LoadDex(JNIEnv* env, Context::PreloadedDex&& dex) {
|
||||
auto class_activity_thread = JNI_FindClass(env, "android/app/ActivityThread");
|
||||
auto class_activity_thread_app_bind_data = JNI_FindClass(env, "android/app/ActivityThread$AppBindData");
|
||||
auto class_loaded_apk = JNI_FindClass(env, "android/app/LoadedApk");
|
||||
|
||||
auto mid_current_activity_thread = JNI_GetStaticMethodID(env, class_activity_thread, "currentActivityThread",
|
||||
"()Landroid/app/ActivityThread;");
|
||||
auto mid_get_classloader = JNI_GetMethodID(env, class_loaded_apk, "getClassLoader", "()Ljava/lang/ClassLoader;");
|
||||
auto fid_m_bound_application = JNI_GetFieldID(env, class_activity_thread, "mBoundApplication",
|
||||
"Landroid/app/ActivityThread$AppBindData;");
|
||||
auto fid_info = JNI_GetFieldID(env, class_activity_thread_app_bind_data, "info", "Landroid/app/LoadedApk;");
|
||||
|
||||
auto activity_thread = JNI_CallStaticObjectMethod(env, class_activity_thread, mid_current_activity_thread);
|
||||
auto m_bound_application = JNI_GetObjectField(env, activity_thread, fid_m_bound_application);
|
||||
auto info = JNI_GetObjectField(env, m_bound_application, fid_info);
|
||||
auto stub_classloader = JNI_CallObjectMethod(env, info, mid_get_classloader);
|
||||
|
||||
if (!stub_classloader) [[unlikely]] {
|
||||
LOGE("getStubClassLoader failed!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
auto in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader");
|
||||
auto mid_init = JNI_GetMethodID(env, in_memory_classloader, "<init>",
|
||||
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
||||
auto byte_buffer_class = JNI_FindClass(env, "java/nio/ByteBuffer");
|
||||
auto dex_buffer = env->NewDirectByteBuffer(dex.data(), dex.size());
|
||||
if (auto my_cl = JNI_NewObject(env, in_memory_classloader, mid_init, dex_buffer, stub_classloader)) {
|
||||
inject_class_loader_ = JNI_NewGlobalRef(env, my_cl);
|
||||
} else {
|
||||
LOGE("InMemoryDexClassLoader creation failed!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
env->DeleteLocalRef(dex_buffer);
|
||||
}
|
||||
|
||||
void PatchLoader::InitHooks(JNIEnv* env, const lsplant::InitInfo& initInfo) {
|
||||
handler = initInfo;
|
||||
Context::InitHooks(env, handler);
|
||||
art::DisableInline(handler);
|
||||
art::DisableBackgroundVerification(handler);
|
||||
RegisterBypass(env);
|
||||
}
|
||||
|
||||
void PatchLoader::SetupEntryClass(JNIEnv* env) {
|
||||
if (auto entry_class = FindClassFromLoader(env, GetCurrentClassLoader(),
|
||||
"org.lsposed.lspatch.loader.LSPApplication")) {
|
||||
entry_class_ = JNI_NewGlobalRef(env, entry_class);
|
||||
}
|
||||
}
|
||||
|
||||
void PatchLoader::Load(JNIEnv* env) {
|
||||
InitSymbolCache(nullptr);
|
||||
lsplant::InitInfo initInfo{
|
||||
.inline_hooker = [](auto t, auto r) {
|
||||
void* bk = nullptr;
|
||||
return HookFunction(t, r, &bk) == RS_SUCCESS ? bk : nullptr;
|
||||
},
|
||||
.inline_unhooker = [](auto t) {
|
||||
return UnhookFunction(t) == RT_SUCCESS;
|
||||
},
|
||||
.art_symbol_resolver = [](auto symbol) {
|
||||
return GetArt()->getSymbAddress<void*>(symbol);
|
||||
},
|
||||
};
|
||||
InstallInlineHooks(initInfo);
|
||||
|
||||
auto stub = JNI_FindClass(env, "org/lsposed/lspatch/appstub/LSPAppComponentFactoryStub");
|
||||
auto dex_field = JNI_GetStaticFieldID(env, stub, "dex", "[B");
|
||||
|
||||
auto array = (jbyteArray) env->GetStaticObjectField(stub, dex_field);
|
||||
auto dex = PreloadedDex{env->GetByteArrayElements(array, nullptr), static_cast<size_t>(JNI_GetArrayLength(env, array))};
|
||||
|
||||
LoadDex(env, std::move(dex));
|
||||
InitHooks(env, initInfo);
|
||||
|
||||
SetupEntryClass(env);
|
||||
FindAndCall(env, "onLoad", "()V");
|
||||
}
|
||||
} // namespace lspd
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* This file is part of LSPosed.
|
||||
*
|
||||
* LSPosed is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LSPosed is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (C) 2022 LSPosed Contributors
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Nullptr on 2022/3/17.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "context.h"
|
||||
|
||||
namespace lspd {
|
||||
|
||||
inline lsplant::InitInfo handler;
|
||||
|
||||
class PatchLoader : public Context {
|
||||
public:
|
||||
inline static void Init() {
|
||||
instance_ = std::make_unique<PatchLoader>();
|
||||
}
|
||||
|
||||
inline static PatchLoader* GetInstance() {
|
||||
return static_cast<PatchLoader*>(instance_.get());
|
||||
}
|
||||
|
||||
void Load(JNIEnv* env);
|
||||
|
||||
protected:
|
||||
void InitHooks(JNIEnv* env, const lsplant::InitInfo& initInfo) override;
|
||||
|
||||
void LoadDex(JNIEnv* env, PreloadedDex&& dex) override;
|
||||
|
||||
void SetupEntryClass(JNIEnv* env) override;
|
||||
};
|
||||
} // namespace lspd
|
||||
|
|
@ -240,8 +240,8 @@ public class LSPatch {
|
|||
// copy so and dex files into the unzipped apk
|
||||
// do not put liblspd.so into apk!lib because x86 native bridge causes crash
|
||||
for (String arch : APK_LIB_PATH_ARRAY) {
|
||||
String entryName = "assets/lspatch/lspd/" + arch + "/liblspd.so";
|
||||
try (var is = getClass().getClassLoader().getResourceAsStream("assets/so/" + (arch.equals("arm") ? "armeabi-v7a" : (arch.equals("arm64") ? "arm64-v8a" : arch)) + "/liblspd.so")) {
|
||||
String entryName = "assets/lspatch/so/" + arch + "/liblspatch.so";
|
||||
try (var is = getClass().getClassLoader().getResourceAsStream("assets/so/" + (arch.equals("arm") ? "armeabi-v7a" : (arch.equals("arm64") ? "arm64-v8a" : arch)) + "/liblspatch.so")) {
|
||||
dstZFile.add(entryName, is, false); // no compress for so
|
||||
} catch (Throwable e) {
|
||||
// More exception info
|
||||
|
|
|
|||
|
|
@ -1,27 +1,50 @@
|
|||
rootProject.name = "LSPatch"
|
||||
|
||||
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
||||
|
||||
include(":daemon-service")
|
||||
include(":hiddenapi-bridge")
|
||||
include(":hiddenapi-stubs")
|
||||
include(":interface")
|
||||
include(":lspcore")
|
||||
include(":manager-service")
|
||||
pluginManagement {
|
||||
val agpVersion: String by settings
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
plugins {
|
||||
id("com.android.library") version agpVersion
|
||||
id("com.android.application") version agpVersion
|
||||
}
|
||||
}
|
||||
|
||||
project(":daemon-service").projectDir = file("core/daemon-service")
|
||||
project(":hiddenapi-bridge").projectDir = file("core/hiddenapi-bridge")
|
||||
project(":hiddenapi-stubs").projectDir = file("core/hiddenapi-stubs")
|
||||
project(":interface").projectDir = file("core/service/interface")
|
||||
project(":lspcore").projectDir = file("core/core")
|
||||
project(":manager-service").projectDir = file("core/manager-service")
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
include(":apkzlib")
|
||||
include(":app")
|
||||
include(":appstub")
|
||||
include(":axmlprinter")
|
||||
include(":imanager")
|
||||
include(":manager")
|
||||
include(":patch")
|
||||
include(":patch-jar")
|
||||
include(":share")
|
||||
rootProject.name = "LSPatch"
|
||||
include(
|
||||
":apkzlib",
|
||||
":appstub",
|
||||
":axmlprinter",
|
||||
":core",
|
||||
":hiddenapi:bridge",
|
||||
":hiddenapi:stubs",
|
||||
":imanager",
|
||||
":manager",
|
||||
":patch",
|
||||
":patch-jar",
|
||||
":patch-loader",
|
||||
":services:daemon-service",
|
||||
":services:manager-service",
|
||||
":services:xposed-service:interface",
|
||||
":share"
|
||||
)
|
||||
|
||||
project(":core").projectDir = file("core/core")
|
||||
project(":hiddenapi:bridge").projectDir = file("core/hiddenapi/bridge")
|
||||
project(":hiddenapi:stubs").projectDir = file("core/hiddenapi/stubs")
|
||||
project(":services:daemon-service").projectDir = file("core/services/daemon-service")
|
||||
project(":services:manager-service").projectDir = file("core/services/manager-service")
|
||||
project(":services:xposed-service:interface").projectDir = file("core/services/xposed-service/interface")
|
||||
|
||||
buildCache { local { removeUnusedEntriesAfterDays = 1 } }
|
||||
|
|
|
|||
Loading…
Reference in New Issue