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 {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk = androidCompileSdkVersion
|
|
||||||
buildToolsVersion = androidBuildToolsVersion
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = androidMinSdkVersion
|
|
||||||
targetSdk = androidTargetSdkVersion
|
|
||||||
|
|
||||||
multiDexEnabled = false
|
multiDexEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -27,11 +14,6 @@ android {
|
||||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility = androidSourceCompatibility
|
|
||||||
targetCompatibility = androidTargetCompatibility
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
androidComponents.onVariants { variant ->
|
androidComponents.onVariants { variant ->
|
||||||
|
|
@ -55,7 +37,7 @@ androidComponents.onVariants { variant ->
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(projects.hiddenapiStubs)
|
compileOnly(projects.hiddenapi.stubs)
|
||||||
|
|
||||||
implementation("de.upb.cs.swt:axml:2.1.2")
|
implementation("de.upb.cs.swt:axml:2.1.2")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,10 @@ public class LSPAppComponentFactoryStub extends AppComponentFactory {
|
||||||
vmInstructionSet.setAccessible(true);
|
vmInstructionSet.setAccessible(true);
|
||||||
|
|
||||||
String arch = (String) vmInstructionSet.invoke(getRuntime.invoke(null));
|
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);
|
System.load(path);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e("LSPatch", "load lspd error", 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.api.Git
|
||||||
import org.eclipse.jgit.internal.storage.file.FileRepository
|
import org.eclipse.jgit.internal.storage.file.FileRepository
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("com.android.application") apply false
|
||||||
|
id("com.android.library") apply false
|
||||||
|
}
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
val agpVersion by extra("7.1.2")
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("com.android.tools.build:gradle:$agpVersion")
|
|
||||||
classpath("org.eclipse.jgit:org.eclipse.jgit:6.0.0.202111291000-r")
|
classpath("org.eclipse.jgit:org.eclipse.jgit:6.0.0.202111291000-r")
|
||||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
|
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 androidSourceCompatibility by extra(JavaVersion.VERSION_11)
|
||||||
val androidTargetCompatibility by extra(JavaVersion.VERSION_11)
|
val androidTargetCompatibility by extra(JavaVersion.VERSION_11)
|
||||||
|
|
||||||
allprojects {
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register<Delete>("clean") {
|
tasks.register<Delete>("clean") {
|
||||||
delete(rootProject.buildDir)
|
delete(rootProject.buildDir)
|
||||||
}
|
}
|
||||||
|
|
@ -59,3 +58,163 @@ listOf("Debug", "Release").forEach { variant ->
|
||||||
dependsOn(projects.manager.dependencyProject.tasks["build$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.
|
android.experimental.enableNewResourceShrinker=true
|
||||||
# IDE (e.g. Android Studio) users:
|
android.experimental.enableNewResourceShrinker.preciseShrinking=true
|
||||||
# Gradle settings configured through the IDE *will override*
|
android.enableAppCompileTimeRClass=true
|
||||||
# any settings specified in this file.
|
android.nonTransitiveRClass=true
|
||||||
# For more details on how to configure your build environment visit
|
android.enableR8.fullMode=true
|
||||||
# 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.useAndroidX=true
|
android.useAndroidX=true
|
||||||
|
|
||||||
|
agpVersion=7.1.2
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
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
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
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 {
|
plugins {
|
||||||
id("com.android.library")
|
id("com.android.library")
|
||||||
}
|
}
|
||||||
|
|
@ -16,25 +8,13 @@ android {
|
||||||
dimension = "api"
|
dimension = "api"
|
||||||
}
|
}
|
||||||
|
|
||||||
compileSdk = androidCompileSdkVersion
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
minSdk = androidMinSdkVersion
|
|
||||||
targetSdk = androidTargetSdkVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility = androidSourceCompatibility
|
|
||||||
targetCompatibility = androidTargetCompatibility
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
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 defaultManagerPackageName: String by rootProject.extra
|
||||||
val apiCode: Int 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 coreVerCode: Int by rootProject.extra
|
||||||
val coreVerName: String by rootProject.extra
|
val coreVerName: String by rootProject.extra
|
||||||
|
|
||||||
val androidSourceCompatibility: JavaVersion by rootProject.extra
|
|
||||||
val androidTargetCompatibility: JavaVersion by rootProject.extra
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("kotlin-parcelize")
|
id("kotlin-parcelize")
|
||||||
|
|
@ -21,14 +10,8 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk = androidCompileSdkVersion
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = defaultManagerPackageName
|
applicationId = defaultManagerPackageName
|
||||||
minSdk = androidMinSdkVersion
|
|
||||||
targetSdk = androidTargetSdkVersion
|
|
||||||
versionCode = verCode
|
|
||||||
versionName = verName
|
|
||||||
|
|
||||||
buildConfigField("int", "API_CODE", """$apiCode""")
|
buildConfigField("int", "API_CODE", """$apiCode""")
|
||||||
buildConfigField("int", "CORE_VERSION_CODE", """$coreVerCode""")
|
buildConfigField("int", "CORE_VERSION_CODE", """$coreVerCode""")
|
||||||
|
|
@ -39,15 +22,9 @@ android {
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
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 {
|
kotlinOptions {
|
||||||
jvmTarget = "11"
|
jvmTarget = "11"
|
||||||
}
|
}
|
||||||
|
|
@ -70,7 +47,7 @@ afterEvaluate {
|
||||||
|
|
||||||
task<Copy>("copy${variantCapped}Assets") {
|
task<Copy>("copy${variantCapped}Assets") {
|
||||||
dependsOn(":appstub:copy$variantCapped")
|
dependsOn(":appstub:copy$variantCapped")
|
||||||
dependsOn(":app:copyRiru$variantCapped")
|
dependsOn(":patch-loader:copy$variantCapped")
|
||||||
tasks["merge${variantCapped}Assets"].dependsOn(this)
|
tasks["merge${variantCapped}Assets"].dependsOn(this)
|
||||||
|
|
||||||
into("$buildDir/intermediates/assets/$variantLowered/merge${variantCapped}Assets")
|
into("$buildDir/intermediates/assets/$variantLowered/merge${variantCapped}Assets")
|
||||||
|
|
@ -92,11 +69,11 @@ dependencies {
|
||||||
implementation("androidx.core:core-ktx:1.7.0")
|
implementation("androidx.core:core-ktx:1.7.0")
|
||||||
implementation("androidx.activity:activity-compose:1.5.0-alpha03")
|
implementation("androidx.activity:activity-compose:1.5.0-alpha03")
|
||||||
implementation("androidx.compose.material:material-icons-extended:1.1.1")
|
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.runtime:runtime-livedata:1.1.1")
|
||||||
implementation("androidx.compose.ui:ui:1.1.1")
|
implementation("androidx.compose.ui:ui:1.1.1")
|
||||||
implementation("androidx.compose.ui:ui-tooling: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.navigation:navigation-compose:2.5.0-alpha03")
|
||||||
implementation("androidx.preference:preference:1.2.0")
|
implementation("androidx.preference:preference:1.2.0")
|
||||||
implementation("com.google.accompanist:accompanist-drawablepainter:0.24.2-alpha")
|
implementation("com.google.accompanist:accompanist-drawablepainter:0.24.2-alpha")
|
||||||
|
|
|
||||||
|
|
@ -35,13 +35,13 @@ val jar = tasks.jar.get()
|
||||||
|
|
||||||
tasks.register("buildDebug") {
|
tasks.register("buildDebug") {
|
||||||
jar.dependsOn(":appstub:copyDebug")
|
jar.dependsOn(":appstub:copyDebug")
|
||||||
jar.dependsOn(":app:copyRiruDebug")
|
jar.dependsOn(":patch-loader:copyDebug")
|
||||||
dependsOn(tasks.build)
|
dependsOn(tasks.build)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("buildRelease") {
|
tasks.register("buildRelease") {
|
||||||
jar.dependsOn(":appstub:copyRelease")
|
jar.dependsOn(":appstub:copyRelease")
|
||||||
jar.dependsOn(":app:copyRiruRelease")
|
jar.dependsOn(":patch-loader:copyRelease")
|
||||||
dependsOn(tasks.build)
|
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.Constants;
|
||||||
import org.lsposed.lspatch.share.PatchConfig;
|
import org.lsposed.lspatch.share.PatchConfig;
|
||||||
import org.lsposed.lspd.config.ApplicationServiceClient;
|
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.models.Module;
|
||||||
import org.lsposed.lspd.nativebridge.SigBypass;
|
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.XC_MethodHook;
|
||||||
import de.robv.android.xposed.XposedHelpers;
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
import de.robv.android.xposed.XposedInit;
|
|
||||||
import hidden.HiddenApiBridge;
|
import hidden.HiddenApiBridge;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -104,10 +103,9 @@ public class LSPApplication extends ApplicationServiceClient {
|
||||||
try {
|
try {
|
||||||
disableProfile(context);
|
disableProfile(context);
|
||||||
loadModules(context);
|
loadModules(context);
|
||||||
Main.forkPostCommon(false, context.getDataDir().toString(), ActivityThread.currentProcessName());
|
Startup.initXposed(false);
|
||||||
doHook(context);
|
|
||||||
Log.i(TAG, "Start loading modules");
|
Log.i(TAG, "Start loading modules");
|
||||||
XposedInit.loadModules();
|
Startup.bootstrapXposed(ActivityThread.currentProcessName());
|
||||||
// WARN: Since it uses `XResource`, the following class should not be initialized
|
// WARN: Since it uses `XResource`, the following class should not be initialized
|
||||||
// before forkPostCommon is invoke. Otherwise, you will get failure of XResources
|
// before forkPostCommon is invoke. Otherwise, you will get failure of XResources
|
||||||
LSPLoader.initModules(appLoadedApk);
|
LSPLoader.initModules(appLoadedApk);
|
||||||
|
|
@ -116,9 +114,11 @@ public class LSPApplication extends ApplicationServiceClient {
|
||||||
switchClassLoader("mBaseClassLoader");
|
switchClassLoader("mBaseClassLoader");
|
||||||
switchClassLoader("mDefaultClassLoader");
|
switchClassLoader("mDefaultClassLoader");
|
||||||
switchClassLoader("mClassLoader");
|
switchClassLoader("mClassLoader");
|
||||||
|
doSigBypass(context);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e(TAG, "Do hook", e);
|
Log.e(TAG, "Do hook", e);
|
||||||
}
|
}
|
||||||
|
Log.i(TAG, "LSPatch bootstrap completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Context createLoadedApkWithContext() {
|
private static Context createLoadedApkWithContext() {
|
||||||
|
|
@ -294,7 +294,7 @@ public class LSPApplication extends ApplicationServiceClient {
|
||||||
return field.getInt(null);
|
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");
|
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() {
|
XposedHelpers.findAndHookMethod("android.os.BinderProxy", null, "transact", int.class, Parcel.class, Parcel.class, int.class, new XC_MethodHook() {
|
||||||
@Override
|
@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) {
|
if (config.sigBypassLevel >= Constants.SIGBYPASS_LV_PM) {
|
||||||
XLog.d(TAG, "Original signature: " + config.originalSignature.substring(0, 16) + "...");
|
XLog.d(TAG, "Original signature: " + config.originalSignature.substring(0, 16) + "...");
|
||||||
byPassSignature(context);
|
bypassSignature(context);
|
||||||
}
|
}
|
||||||
if (config.sigBypassLevel >= Constants.SIGBYPASS_LV_PM_OPENAT) {
|
if (config.sigBypassLevel >= Constants.SIGBYPASS_LV_PM_OPENAT) {
|
||||||
String cacheApkPath;
|
String cacheApkPath;
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package org.lsposed.lspatch.loader.util;
|
package org.lsposed.lspatch.loader.util;
|
||||||
|
|
||||||
|
import org.lsposed.lspatch.loader.BuildConfig;
|
||||||
import org.lsposed.lspd.BuildConfig;
|
|
||||||
|
|
||||||
public class XLog {
|
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
|
// copy so and dex files into the unzipped apk
|
||||||
// do not put liblspd.so into apk!lib because x86 native bridge causes crash
|
// do not put liblspd.so into apk!lib because x86 native bridge causes crash
|
||||||
for (String arch : APK_LIB_PATH_ARRAY) {
|
for (String arch : APK_LIB_PATH_ARRAY) {
|
||||||
String entryName = "assets/lspatch/lspd/" + 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)) + "/liblspd.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
|
dstZFile.add(entryName, is, false); // no compress for so
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// More exception info
|
// More exception info
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,50 @@
|
||||||
rootProject.name = "LSPatch"
|
|
||||||
|
|
||||||
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
||||||
|
|
||||||
include(":daemon-service")
|
pluginManagement {
|
||||||
include(":hiddenapi-bridge")
|
val agpVersion: String by settings
|
||||||
include(":hiddenapi-stubs")
|
repositories {
|
||||||
include(":interface")
|
gradlePluginPortal()
|
||||||
include(":lspcore")
|
google()
|
||||||
include(":manager-service")
|
mavenCentral()
|
||||||
|
}
|
||||||
|
plugins {
|
||||||
|
id("com.android.library") version agpVersion
|
||||||
|
id("com.android.application") version agpVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
project(":daemon-service").projectDir = file("core/daemon-service")
|
dependencyResolutionManagement {
|
||||||
project(":hiddenapi-bridge").projectDir = file("core/hiddenapi-bridge")
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
project(":hiddenapi-stubs").projectDir = file("core/hiddenapi-stubs")
|
repositories {
|
||||||
project(":interface").projectDir = file("core/service/interface")
|
google()
|
||||||
project(":lspcore").projectDir = file("core/core")
|
mavenCentral()
|
||||||
project(":manager-service").projectDir = file("core/manager-service")
|
}
|
||||||
|
}
|
||||||
|
|
||||||
include(":apkzlib")
|
rootProject.name = "LSPatch"
|
||||||
include(":app")
|
include(
|
||||||
include(":appstub")
|
":apkzlib",
|
||||||
include(":axmlprinter")
|
":appstub",
|
||||||
include(":imanager")
|
":axmlprinter",
|
||||||
include(":manager")
|
":core",
|
||||||
include(":patch")
|
":hiddenapi:bridge",
|
||||||
include(":patch-jar")
|
":hiddenapi:stubs",
|
||||||
include(":share")
|
":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