Support bootstrapping loader dynamically for local mode (#118)

This commit is contained in:
Nullptr 2022-10-21 15:24:16 +08:00 committed by GitHub
parent 91b038ac16
commit f8888b81e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 176 additions and 104 deletions

View File

@ -1,4 +0,0 @@
-keep class org.lsposed.lspatch.appstub.LSPAppComponentFactoryStub {
public static byte[] dex;
<init>();
}

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.lsposed.lspatch.appstub">
</manifest>

View File

@ -1,43 +0,0 @@
package org.lsposed.lspatch.appstub;
import android.annotation.SuppressLint;
import android.app.AppComponentFactory;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Method;
import java.util.Objects;
@SuppressLint("UnsafeDynamicallyLoadedCode")
public class LSPAppComponentFactoryStub extends AppComponentFactory {
public static byte[] dex = null;
static {
var cl = Objects.requireNonNull(LSPAppComponentFactoryStub.class.getClassLoader());
try (var is = cl.getResourceAsStream("assets/lspatch/lsp.dex");
var os = new ByteArrayOutputStream()) {
byte[] buffer = new byte[8192];
int n;
while (-1 != (n = is.read(buffer))) {
os.write(buffer, 0, n);
}
dex = os.toByteArray();
} catch (Throwable e) {
Log.e("LSPatch", "load dex error", e);
}
try {
Class<?> VMRuntime = Class.forName("dalvik.system.VMRuntime");
Method getRuntime = VMRuntime.getDeclaredMethod("getRuntime");
getRuntime.setAccessible(true);
Method vmInstructionSet = VMRuntime.getDeclaredMethod("vmInstructionSet");
vmInstructionSet.setAccessible(true);
String arch = (String) vmInstructionSet.invoke(getRuntime.invoke(null));
String path = cl.getResource("assets/lspatch/so/" + arch + "/liblspatch.so").getPath().substring(5);
System.load(path);
} catch (Throwable e) {
throw new ExceptionInInitializerError(e);
}
}
}

View File

@ -58,7 +58,7 @@ tasks.register<Delete>("clean") {
listOf("Debug", "Release").forEach { variant -> listOf("Debug", "Release").forEach { variant ->
tasks.register("build$variant") { tasks.register("build$variant") {
description = "Build LSPatch with $variant" description = "Build LSPatch with $variant"
dependsOn(projects.patchJar.dependencyProject.tasks["build$variant"]) dependsOn(projects.jar.dependencyProject.tasks["build$variant"])
dependsOn(projects.manager.dependencyProject.tasks["build$variant"]) dependsOn(projects.manager.dependencyProject.tasks["build$variant"])
} }
} }

View File

@ -34,13 +34,13 @@ fun Jar.configure(variant: String) {
} }
tasks.register<Jar>("buildDebug") { tasks.register<Jar>("buildDebug") {
dependsOn(":appstub:copyDebug") dependsOn(":meta-loader:copyDebug")
dependsOn(":patch-loader:copyDebug") dependsOn(":patch-loader:copyDebug")
configure("debug") configure("debug")
} }
tasks.register<Jar>("buildRelease") { tasks.register<Jar>("buildRelease") {
dependsOn(":appstub:copyRelease") dependsOn(":meta-loader:copyRelease")
dependsOn(":patch-loader:copyRelease") dependsOn(":patch-loader:copyRelease")
configure("release") configure("release")
} }

View File

@ -18,6 +18,10 @@ android {
applicationId = defaultManagerPackageName applicationId = defaultManagerPackageName
} }
androidResources {
noCompress.add(".so")
}
buildTypes { buildTypes {
debug { debug {
isMinifyEnabled = true isMinifyEnabled = true
@ -58,7 +62,7 @@ afterEvaluate {
val variantCapped = variant.name.capitalize() val variantCapped = variant.name.capitalize()
task<Copy>("copy${variantCapped}Assets") { task<Copy>("copy${variantCapped}Assets") {
dependsOn(":appstub:copy$variantCapped") dependsOn(":meta-loader:copy$variantCapped")
dependsOn(":patch-loader:copy$variantCapped") dependsOn(":patch-loader:copy$variantCapped")
tasks["merge${variantCapped}Assets"].dependsOn(this) tasks["merge${variantCapped}Assets"].dependsOn(this)

View File

@ -1,6 +0,0 @@
package org.lsposed.lspatch
object Constants {
const val PATCH_FILE_SUFFIX = "-lspatched.apk"
}

View File

@ -4,9 +4,9 @@ import androidx.core.net.toUri
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.lsposed.lspatch.Constants.PATCH_FILE_SUFFIX
import org.lsposed.lspatch.config.Configs import org.lsposed.lspatch.config.Configs
import org.lsposed.lspatch.config.MyKeyStore import org.lsposed.lspatch.config.MyKeyStore
import org.lsposed.lspatch.share.Constants
import org.lsposed.lspatch.share.PatchConfig import org.lsposed.lspatch.share.PatchConfig
import org.lsposed.patch.LSPatch import org.lsposed.patch.LSPatch
import org.lsposed.patch.util.Logger import org.lsposed.patch.util.Logger
@ -47,10 +47,10 @@ object Patcher {
val root = DocumentFile.fromTreeUri(lspApp, uri) val root = DocumentFile.fromTreeUri(lspApp, uri)
?: throw IOException("DocumentFile is null") ?: throw IOException("DocumentFile is null")
root.listFiles().forEach { root.listFiles().forEach {
if (it.name?.endsWith(PATCH_FILE_SUFFIX) == true) it.delete() if (it.name?.endsWith(Constants.PATCH_FILE_SUFFIX) == true) it.delete()
} }
lspApp.tmpApkDir.walk() lspApp.tmpApkDir.walk()
.filter { it.name.endsWith(PATCH_FILE_SUFFIX) } .filter { it.name.endsWith(Constants.PATCH_FILE_SUFFIX) }
.forEach { apk -> .forEach { apk ->
val file = root.createFile("application/vnd.android.package-archive", apk.name) val file = root.createFile("application/vnd.android.package-archive", apk.name)
?: throw IOException("Failed to create output file") ?: throw IOException("Failed to create output file")

View File

@ -14,12 +14,14 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.KeyboardCapslock
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.SpanStyle
@ -41,6 +43,7 @@ import org.lsposed.lspatch.config.ConfigManager
import org.lsposed.lspatch.config.Configs import org.lsposed.lspatch.config.Configs
import org.lsposed.lspatch.database.entity.Module import org.lsposed.lspatch.database.entity.Module
import org.lsposed.lspatch.lspApp import org.lsposed.lspatch.lspApp
import org.lsposed.lspatch.share.Constants
import org.lsposed.lspatch.share.LSPConfig import org.lsposed.lspatch.share.LSPConfig
import org.lsposed.lspatch.ui.component.AnywhereDropdown import org.lsposed.lspatch.ui.component.AnywhereDropdown
import org.lsposed.lspatch.ui.component.AppItem import org.lsposed.lspatch.ui.component.AppItem
@ -136,6 +139,8 @@ fun AppManageBody(
items = viewModel.appList, items = viewModel.appList,
key = { it.first.app.packageName } key = { it.first.app.packageName }
) { ) {
val isRolling = it.second.useManager && it.second.lspConfig.VERSION_CODE >= Constants.MIN_ROLLING_VERSION_CODE
val canUpdateLoader = !isRolling && it.second.lspConfig.VERSION_CODE < LSPConfig.instance.VERSION_CODE
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) }
AnywhereDropdown( AnywhereDropdown(
expanded = expanded, expanded = expanded,
@ -148,6 +153,7 @@ fun AppManageBody(
label = it.first.label, label = it.first.label,
packageName = it.first.app.packageName, packageName = it.first.app.packageName,
additionalContent = { additionalContent = {
Row(verticalAlignment = Alignment.CenterVertically) {
Text( Text(
text = buildAnnotatedString { text = buildAnnotatedString {
val (text, color) = val (text, color) =
@ -155,12 +161,20 @@ fun AppManageBody(
else stringResource(R.string.patch_portable) to MaterialTheme.colorScheme.tertiary else stringResource(R.string.patch_portable) to MaterialTheme.colorScheme.tertiary
append(AnnotatedString(text, SpanStyle(color = color))) append(AnnotatedString(text, SpanStyle(color = color)))
append(" ") append(" ")
append(it.second.lspConfig.VERSION_CODE.toString()) if (isRolling) append(stringResource(R.string.manage_rolling))
else append(it.second.lspConfig.VERSION_CODE.toString())
}, },
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.SemiBold,
fontFamily = FontFamily.Serif, fontFamily = FontFamily.Serif,
style = MaterialTheme.typography.bodySmall style = MaterialTheme.typography.bodySmall
) )
if (canUpdateLoader) {
with(LocalDensity.current) {
val size = MaterialTheme.typography.bodySmall.fontSize * 1.2
Icon(Icons.Filled.KeyboardCapslock, null, Modifier.size(size.toDp()))
}
}
}
} }
) )
} }
@ -170,7 +184,7 @@ fun AppManageBody(
onClick = {}, enabled = false onClick = {}, enabled = false
) )
val shizukuUnavailable = stringResource(R.string.shizuku_unavailable) val shizukuUnavailable = stringResource(R.string.shizuku_unavailable)
if (it.second.lspConfig.VERSION_CODE < LSPConfig.instance.VERSION_CODE || BuildConfig.DEBUG) { if (canUpdateLoader || BuildConfig.DEBUG) {
DropdownMenuItem( DropdownMenuItem(
text = { Text(stringResource(R.string.manage_update_loader)) }, text = { Text(stringResource(R.string.manage_update_loader)) },
onClick = { onClick = {

View File

@ -20,10 +20,10 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import me.zhanghai.android.appiconloader.AppIconLoader import me.zhanghai.android.appiconloader.AppIconLoader
import org.lsposed.lspatch.Constants.PATCH_FILE_SUFFIX
import org.lsposed.lspatch.config.ConfigManager import org.lsposed.lspatch.config.ConfigManager
import org.lsposed.lspatch.config.Configs import org.lsposed.lspatch.config.Configs
import org.lsposed.lspatch.lspApp import org.lsposed.lspatch.lspApp
import org.lsposed.lspatch.share.Constants
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.text.Collator import java.text.Collator
@ -91,7 +91,7 @@ object LSPPackageManager {
val uri = Configs.storageDirectory?.toUri() ?: throw IOException("Uri is null") val uri = Configs.storageDirectory?.toUri() ?: throw IOException("Uri is null")
val root = DocumentFile.fromTreeUri(lspApp, uri) ?: throw IOException("DocumentFile is null") val root = DocumentFile.fromTreeUri(lspApp, uri) ?: throw IOException("DocumentFile is null")
root.listFiles().forEach { file -> root.listFiles().forEach { file ->
if (file.name?.endsWith(PATCH_FILE_SUFFIX) != true) return@forEach if (file.name?.endsWith(Constants.PATCH_FILE_SUFFIX) != true) return@forEach
Log.d(TAG, "Add ${file.name}") Log.d(TAG, "Add ${file.name}")
val input = lspApp.contentResolver.openInputStream(file.uri) val input = lspApp.contentResolver.openInputStream(file.uri)
?: throw IOException("Cannot open input stream") ?: throw IOException("Cannot open input stream")

View File

@ -29,6 +29,7 @@
<string name="screen_manage">Manage</string> <string name="screen_manage">Manage</string>
<string name="manage_loading">Loading</string> <string name="manage_loading">Loading</string>
<string name="manage_no_apps">No patched apps yet</string> <string name="manage_no_apps">No patched apps yet</string>
<string name="manage_rolling">Rolling</string>
<string name="manage_update_loader">Update loader</string> <string name="manage_update_loader">Update loader</string>
<string name="manage_update_loader_successfully">Update successfully</string> <string name="manage_update_loader_successfully">Update successfully</string>
<string name="manage_update_loader_failed">Update failed</string> <string name="manage_update_loader_failed">Update failed</string>

View File

@ -26,8 +26,8 @@ androidComponents.onVariants { variant ->
"$buildDir/intermediates/dex/$variantLowered/minify${variantCapped}WithR8" else "$buildDir/intermediates/dex/$variantLowered/minify${variantCapped}WithR8" else
"$buildDir/intermediates/dex/$variantLowered/mergeDex$variantCapped" "$buildDir/intermediates/dex/$variantLowered/mergeDex$variantCapped"
from(dexOutPath) from(dexOutPath)
rename("classes.dex", "loader.dex") rename("classes.dex", "metaloader.dex")
into("${rootProject.projectDir}/out/assets/dex") into("${rootProject.projectDir}/out/assets/lspatch")
} }
task("copy$variantCapped") { task("copy$variantCapped") {
@ -41,4 +41,5 @@ androidComponents.onVariants { variant ->
dependencies { dependencies {
compileOnly(projects.hiddenapi.stubs) compileOnly(projects.hiddenapi.stubs)
implementation(projects.share.java)
} }

4
meta-loader/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,4 @@
-keep class org.lsposed.lspatch.metaloader.LSPAppComponentFactoryStub {
public static byte[] dex;
<init>();
}

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="org.lsposed.lspatch.metaloader" />

View File

@ -0,0 +1,105 @@
package org.lsposed.lspatch.metaloader;
import android.annotation.SuppressLint;
import android.app.AppComponentFactory;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.os.Build;
import android.os.ServiceManager;
import android.util.JsonReader;
import android.util.Log;
import org.lsposed.lspatch.share.Constants;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.zip.ZipFile;
@SuppressLint("UnsafeDynamicallyLoadedCode")
public class LSPAppComponentFactoryStub extends AppComponentFactory {
private static final String TAG = "LSPatch-MetaLoader";
private static final Map<String, String> archToLib = Map.of(
"arm", "armeabi-v7a",
"arm64", "arm64-v8a",
"x86", "x86",
"x86_64", "x86_64"
);
public static byte[] dex;
static {
try {
var cl = Objects.requireNonNull(LSPAppComponentFactoryStub.class.getClassLoader());
Class<?> VMRuntime = Class.forName("dalvik.system.VMRuntime");
Method getRuntime = VMRuntime.getDeclaredMethod("getRuntime");
getRuntime.setAccessible(true);
Method vmInstructionSet = VMRuntime.getDeclaredMethod("vmInstructionSet");
vmInstructionSet.setAccessible(true);
String arch = (String) vmInstructionSet.invoke(getRuntime.invoke(null));
String libName = archToLib.get(arch);
boolean useManager = false;
String soPath;
try (var is = cl.getResourceAsStream(Constants.CONFIG_ASSET_PATH);
var reader = new JsonReader(new InputStreamReader(is))) {
reader.beginObject();
while (reader.hasNext()) {
var name = reader.nextName();
if (name.equals("useManager")) {
useManager = reader.nextBoolean();
break;
} else {
reader.skipValue();
}
}
}
if (useManager) {
Log.i(TAG, "Bootstrap loader from manager");
var ipm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
ApplicationInfo manager;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
manager = ipm.getApplicationInfo(Constants.MANAGER_PACKAGE_NAME, 0L, 0);
} else {
manager = ipm.getApplicationInfo(Constants.MANAGER_PACKAGE_NAME, 0, 0);
}
try (var zip = new ZipFile(new File(manager.sourceDir));
var is = zip.getInputStream(zip.getEntry(Constants.LOADER_DEX_ASSET_PATH));
var os = new ByteArrayOutputStream()) {
transfer(is, os);
dex = os.toByteArray();
}
soPath = manager.sourceDir + "!/assets/lspatch/so/" + libName + "/liblspatch.so";
} else {
Log.i(TAG, "Bootstrap loader from embedment");
try (var is = cl.getResourceAsStream(Constants.LOADER_DEX_ASSET_PATH);
var os = new ByteArrayOutputStream()) {
transfer(is, os);
dex = os.toByteArray();
}
soPath = cl.getResource("assets/lspatch/so/" + libName + "/liblspatch.so").getPath().substring(5);
}
System.load(soPath);
} catch (Throwable e) {
throw new ExceptionInInitializerError(e);
}
}
private static void transfer(InputStream is, OutputStream os) throws IOException {
byte[] buffer = new byte[8192];
int n;
while (-1 != (n = is.read(buffer))) {
os.write(buffer, 0, n);
}
}
}

View File

@ -27,8 +27,8 @@ androidComponents.onVariants { variant ->
task<Copy>("copyDex$variantCapped") { task<Copy>("copyDex$variantCapped") {
dependsOn("assemble$variantCapped") dependsOn("assemble$variantCapped")
from("$buildDir/intermediates/dex/${variant.name}/mergeDex$variantCapped/classes.dex") from("$buildDir/intermediates/dex/${variant.name}/mergeDex$variantCapped/classes.dex")
rename("classes.dex", "lsp.dex") rename("classes.dex", "loader.dex")
into("${rootProject.projectDir}/out/assets/dex") into("${rootProject.projectDir}/out/assets/lspatch")
} }
task<Copy>("copySo$variantCapped") { task<Copy>("copySo$variantCapped") {
@ -39,7 +39,7 @@ androidComponents.onVariants { variant ->
"include" to listOf("**/liblspatch.so") "include" to listOf("**/liblspatch.so")
) )
) )
into("${rootProject.projectDir}/out/assets/so") into("${rootProject.projectDir}/out/assets/lspatch/so")
} }
task("copy$variantCapped") { task("copy$variantCapped") {

View File

@ -108,7 +108,7 @@ namespace lspd {
}, },
}; };
auto stub = JNI_FindClass(env, "org/lsposed/lspatch/appstub/LSPAppComponentFactoryStub"); auto stub = JNI_FindClass(env, "org/lsposed/lspatch/metaloader/LSPAppComponentFactoryStub");
auto dex_field = JNI_GetStaticFieldID(env, stub, "dex", "[B"); auto dex_field = JNI_GetStaticFieldID(env, stub, "dex", "[B");
ScopedLocalRef<jbyteArray> array = JNI_GetStaticObjectField(env, stub, dex_field); ScopedLocalRef<jbyteArray> array = JNI_GetStaticObjectField(env, stub, dex_field);

View File

@ -1,7 +1,7 @@
package org.lsposed.patch; package org.lsposed.patch;
import static org.lsposed.lspatch.share.Constants.CONFIG_ASSET_PATH; import static org.lsposed.lspatch.share.Constants.CONFIG_ASSET_PATH;
import static org.lsposed.lspatch.share.Constants.DEX_ASSET_PATH; import static org.lsposed.lspatch.share.Constants.LOADER_DEX_ASSET_PATH;
import static org.lsposed.lspatch.share.Constants.ORIGINAL_APK_ASSET_PATH; import static org.lsposed.lspatch.share.Constants.ORIGINAL_APK_ASSET_PATH;
import static org.lsposed.lspatch.share.Constants.PROXY_APP_COMPONENT_FACTORY; import static org.lsposed.lspatch.share.Constants.PROXY_APP_COMPONENT_FACTORY;
@ -21,6 +21,7 @@ import com.wind.meditor.property.ModificationProperty;
import com.wind.meditor.utils.NodeValue; import com.wind.meditor.utils.NodeValue;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.lsposed.lspatch.share.Constants;
import org.lsposed.lspatch.share.LSPConfig; import org.lsposed.lspatch.share.LSPConfig;
import org.lsposed.lspatch.share.PatchConfig; import org.lsposed.lspatch.share.PatchConfig;
import org.lsposed.patch.util.ApkSignatureHelper; import org.lsposed.patch.util.ApkSignatureHelper;
@ -98,12 +99,6 @@ public class LSPatch {
"x86", "x86",
"x86_64" "x86_64"
)); ));
private static final HashSet<String> APK_LIB_PATH_ARRAY = new HashSet<>(Arrays.asList(
"arm",
"arm64",
"x86",
"x86_64"
));
private static final ZFileOptions Z_FILE_OPTIONS = new ZFileOptions().setAlignmentRule(AlignmentRules.compose( private static final ZFileOptions Z_FILE_OPTIONS = new ZFileOptions().setAlignmentRule(AlignmentRules.compose(
AlignmentRules.constantForSuffix(".so", 4096), AlignmentRules.constantForSuffix(".so", 4096),
@ -244,10 +239,10 @@ public class LSPatch {
logger.d("Adding native lib.."); logger.d("Adding native lib..");
// 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 liblspatch.so into apk!lib because x86 native bridge causes crash
for (String arch : APK_LIB_PATH_ARRAY) { for (String arch : ARCHES) {
String entryName = "assets/lspatch/so/" + arch + "/liblspatch.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")) { try (var is = getClass().getClassLoader().getResourceAsStream(entryName)) {
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
@ -258,14 +253,14 @@ public class LSPatch {
logger.d("Adding dex.."); logger.d("Adding dex..");
try (var is = getClass().getClassLoader().getResourceAsStream("assets/dex/loader.dex")) { try (var is = getClass().getClassLoader().getResourceAsStream(Constants.META_LOADER_DEX_ASSET_PATH)) {
dstZFile.add("classes.dex", is); dstZFile.add("classes.dex", is);
} catch (Throwable e) { } catch (Throwable e) {
throw new PatchError("Error when adding dex", e); throw new PatchError("Error when adding dex", e);
} }
try (var is = getClass().getClassLoader().getResourceAsStream("assets/dex/lsp.dex")) { try (var is = getClass().getClassLoader().getResourceAsStream(LOADER_DEX_ASSET_PATH)) {
dstZFile.add(DEX_ASSET_PATH, is); dstZFile.add(LOADER_DEX_ASSET_PATH, is);
} catch (Throwable e) { } catch (Throwable e) {
throw new PatchError("Error when adding assets", e); throw new PatchError("Error when adding assets", e);
} }

View File

@ -26,14 +26,14 @@ dependencyResolutionManagement {
rootProject.name = "LSPatch" rootProject.name = "LSPatch"
include( include(
":apkzlib", ":apkzlib",
":appstub",
":axmlprinter", ":axmlprinter",
":core", ":core",
":hiddenapi:bridge", ":hiddenapi:bridge",
":hiddenapi:stubs", ":hiddenapi:stubs",
":jar",
":manager", ":manager",
":meta-loader",
":patch", ":patch",
":patch-jar",
":patch-loader", ":patch-loader",
":services:daemon-service", ":services:daemon-service",
":services:manager-service", ":services:manager-service",

View File

@ -2,12 +2,16 @@ package org.lsposed.lspatch.share;
public class Constants { public class Constants {
final static public String DEX_ASSET_PATH = "assets/lspatch/lsp.dex";
final static public String CONFIG_ASSET_PATH = "assets/lspatch/config.json"; final static public String CONFIG_ASSET_PATH = "assets/lspatch/config.json";
final static public String LOADER_DEX_ASSET_PATH = "assets/lspatch/loader.dex";
final static public String META_LOADER_DEX_ASSET_PATH = "assets/lspatch/metaloader.dex";
final static public String ORIGINAL_APK_ASSET_PATH = "assets/lspatch/origin.apk"; final static public String ORIGINAL_APK_ASSET_PATH = "assets/lspatch/origin.apk";
final static public String PROXY_APP_COMPONENT_FACTORY = "org.lsposed.lspatch.appstub.LSPAppComponentFactoryStub"; final static public String PATCH_FILE_SUFFIX = "-lspatched.apk";
final static public String PROXY_APP_COMPONENT_FACTORY = "org.lsposed.lspatch.metaloader.LSPAppComponentFactoryStub";
final static public String MANAGER_PACKAGE_NAME = "org.lsposed.lspatch"; final static public String MANAGER_PACKAGE_NAME = "org.lsposed.lspatch";
final static public int MIN_ROLLING_VERSION_CODE = 341;
final static public int SIGBYPASS_LV_DISABLE = 0; final static public int SIGBYPASS_LV_DISABLE = 0;
final static public int SIGBYPASS_LV_PM = 1; final static public int SIGBYPASS_LV_PM = 1;
final static public int SIGBYPASS_LV_PM_OPENAT = 2; final static public int SIGBYPASS_LV_PM_OPENAT = 2;