Drop v1 signature & UI improvement
This commit is contained in:
parent
b1691a95e2
commit
2e2c818de6
|
|
@ -25,8 +25,6 @@ object Patcher {
|
|||
add("-o"); add(lspApp.tmpApkDir.absolutePath)
|
||||
if (config.debuggable) add("-d")
|
||||
add("-l"); add(config.sigBypassLevel.toString())
|
||||
add("--v1"); add(config.v1.toString())
|
||||
add("--v2"); add(config.v2.toString())
|
||||
if (config.useManager) add("--manager")
|
||||
if (config.overrideVersionCode) add("-r")
|
||||
if (Configs.detailPatchLogs) add("-v")
|
||||
|
|
|
|||
|
|
@ -176,7 +176,6 @@ private fun sigBypassLvStr(level: Int) = when (level) {
|
|||
else -> throw IllegalArgumentException("Invalid sigBypassLv: $level")
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun PatchOptionsBody(modifier: Modifier, onAddEmbed: () -> Unit) {
|
||||
val viewModel = viewModel<NewPatchViewModel>()
|
||||
|
|
@ -236,34 +235,6 @@ private fun PatchOptionsBody(modifier: Modifier, onAddEmbed: () -> Unit) {
|
|||
title = stringResource(R.string.patch_override_version_code),
|
||||
desc = stringResource(R.string.patch_override_version_code_desc)
|
||||
)
|
||||
var signExpanded by remember { mutableStateOf(false) }
|
||||
AnywhereDropdown(
|
||||
expanded = signExpanded,
|
||||
onDismissRequest = { signExpanded = false },
|
||||
onClick = { signExpanded = true },
|
||||
surface = {
|
||||
SettingsItem(
|
||||
icon = Icons.Outlined.Edit,
|
||||
title = stringResource(R.string.patch_sign),
|
||||
desc = viewModel.sign
|
||||
.mapIndexedNotNull { index, on -> if (on) "V" + (index + 1) else null }
|
||||
.joinToString(" + ")
|
||||
.ifEmpty { "None" }
|
||||
)
|
||||
}
|
||||
) {
|
||||
repeat(2) { index ->
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Checkbox(checked = viewModel.sign[index], onCheckedChange = { viewModel.sign[index] = !viewModel.sign[index] })
|
||||
Text("V" + (index + 1))
|
||||
}
|
||||
},
|
||||
onClick = { viewModel.sign[index] = !viewModel.sign[index] }
|
||||
)
|
||||
}
|
||||
}
|
||||
var bypassExpanded by remember { mutableStateOf(false) }
|
||||
AnywhereDropdown(
|
||||
expanded = bypassExpanded,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ class NewPatchViewModel : ViewModel() {
|
|||
var useManager by mutableStateOf(true)
|
||||
var debuggable by mutableStateOf(false)
|
||||
var overrideVersionCode by mutableStateOf(false)
|
||||
val sign = mutableStateListOf(false, true)
|
||||
var sigBypassLevel by mutableStateOf(2)
|
||||
var embeddedModules = emptyList<AppInfo>()
|
||||
|
||||
|
|
@ -89,7 +88,7 @@ class NewPatchViewModel : ViewModel() {
|
|||
Log.d(TAG, "Submit patch")
|
||||
if (useManager) embeddedModules = emptyList()
|
||||
patchOptions = Patcher.Options(
|
||||
config = PatchConfig(useManager, debuggable, overrideVersionCode, sign[0], sign[1], sigBypassLevel, null, null),
|
||||
config = PatchConfig(useManager, debuggable, overrideVersionCode, sigBypassLevel, null, null),
|
||||
apkPaths = listOf(patchApp.app.sourceDir) + (patchApp.app.splitSourceDirs ?: emptyArray()),
|
||||
embeddedModules = embeddedModules.flatMap { listOf(it.app.sourceDir) + (it.app.splitSourceDirs ?: emptyArray()) }
|
||||
)
|
||||
|
|
|
|||
|
|
@ -21,12 +21,10 @@ import org.lsposed.lspatch.Constants.PATCH_FILE_SUFFIX
|
|||
import org.lsposed.lspatch.config.ConfigManager
|
||||
import org.lsposed.lspatch.config.Configs
|
||||
import org.lsposed.lspatch.lspApp
|
||||
import org.lsposed.patch.util.ManifestParser
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.text.Collator
|
||||
import java.util.*
|
||||
import java.util.zip.ZipFile
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
|
|
@ -150,9 +148,8 @@ object LSPPackageManager {
|
|||
suspend fun getAppInfoFromApks(apks: List<Uri>): Result<AppInfo> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
runCatching {
|
||||
val app = ApplicationInfo()
|
||||
if (apks.size > 1) app.splitSourceDirs = Array<String?>(apks.size - 1) { null }
|
||||
apks.forEachIndexed { index, uri ->
|
||||
var primary: ApplicationInfo? = null
|
||||
val splits = apks.mapNotNull { uri ->
|
||||
val src = DocumentFile.fromSingleUri(lspApp, uri)
|
||||
?: throw IOException("DocumentFile is null")
|
||||
val dst = lspApp.tmpApkDir.resolve(src.name!!)
|
||||
|
|
@ -163,21 +160,18 @@ object LSPPackageManager {
|
|||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
ZipFile(dst).use { zip ->
|
||||
val entry = zip.getEntry("AndroidManifest.xml")
|
||||
?: throw IOException("AndroidManifest.xml is not found")
|
||||
zip.getInputStream(entry).use {
|
||||
val info = ManifestParser.parseManifestFile(it)
|
||||
if (app.packageName != null && app.packageName != info.packageName) {
|
||||
throw IOException("Selected apks are not of the same app")
|
||||
if (primary == null) {
|
||||
primary = lspApp.packageManager.getPackageArchiveInfo(dst.absolutePath, 0)?.applicationInfo
|
||||
if (primary != null) return@mapNotNull null
|
||||
}
|
||||
app.packageName = info.packageName
|
||||
dst.absolutePath
|
||||
}
|
||||
}
|
||||
if (index == 0) app.sourceDir = dst.absolutePath
|
||||
else app.splitSourceDirs[index - 1] = dst.absolutePath
|
||||
}
|
||||
AppInfo(app, app.packageName)
|
||||
|
||||
// TODO: Check selected apks are from the same app
|
||||
if (primary == null) throw IllegalArgumentException("No primary apk")
|
||||
val label = lspApp.packageManager.getApplicationLabel(primary!!).toString()
|
||||
if (splits.isNotEmpty()) primary!!.splitSourceDirs = splits.toTypedArray()
|
||||
AppInfo(primary!!, label)
|
||||
}.recoverCatching { t ->
|
||||
cleanTmpApkDir()
|
||||
Log.e(TAG, "Failed to load apks", t)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@
|
|||
<string name="patch_portable_desc">Patch an app with modules embedded.\nThe patched app can run without the manager, but cannot be managed dynamically.\nPortable patched apps can be used on devices that do not have LSPatch Manager installed.</string>
|
||||
<string name="patch_embed_modules">Embed modules</string>
|
||||
<string name="patch_debuggable">Debuggable</string>
|
||||
<string name="patch_sign">Sign</string>
|
||||
<string name="patch_sigbypass">Signature bypass</string>
|
||||
<string name="patch_sigbypasslv0">lv0: Off</string>
|
||||
<string name="patch_sigbypasslv1">lv1: Bypass PM</string>
|
||||
|
|
|
|||
|
|
@ -79,12 +79,6 @@ public class LSPatch {
|
|||
@Parameter(names = {"-k", "--keystore"}, arity = 4, description = "Set custom signature keystore. Followed by 4 arguments: keystore path, keystore password, keystore alias, keystore alias password")
|
||||
private List<String> keystoreArgs = Arrays.asList(null, "123456", "key0", "123456");
|
||||
|
||||
@Parameter(names = {"--v1"}, arity = 1, description = "Sign with v1 signature")
|
||||
private boolean v1 = false;
|
||||
|
||||
@Parameter(names = {"--v2"}, arity = 1, description = "Sign with v2 signature")
|
||||
private boolean v2 = true;
|
||||
|
||||
@Parameter(names = {"--manager"}, description = "Use manager (Cannot work with embedding modules)")
|
||||
private boolean useManager = false;
|
||||
|
||||
|
|
@ -207,8 +201,7 @@ public class LSPatch {
|
|||
var entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(keystoreArgs.get(2), new KeyStore.PasswordProtection(keystoreArgs.get(3).toCharArray()));
|
||||
new SigningExtension(SigningOptions.builder()
|
||||
.setMinSdkVersion(28)
|
||||
.setV1SigningEnabled(v1)
|
||||
.setV2SigningEnabled(v2)
|
||||
.setV2SigningEnabled(true)
|
||||
.setCertificates((X509Certificate[]) entry.getCertificateChain())
|
||||
.setKey(entry.getPrivateKey())
|
||||
.build()).register(dstZFile);
|
||||
|
|
@ -239,7 +232,7 @@ public class LSPatch {
|
|||
|
||||
logger.i("Patching apk...");
|
||||
// modify manifest
|
||||
final var config = new PatchConfig(useManager, debuggableFlag, overrideVersionCode, v1, v2, sigbypassLevel, originalSignature, appComponentFactory);
|
||||
final var config = new PatchConfig(useManager, debuggableFlag, overrideVersionCode, sigbypassLevel, originalSignature, appComponentFactory);
|
||||
final var configBytes = new Gson().toJson(config).getBytes(StandardCharsets.UTF_8);
|
||||
final var metadata = Base64.getEncoder().encodeToString(configBytes);
|
||||
try (var is = new ByteArrayInputStream(modifyManifestFile(manifestEntry.open(), metadata))) {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ public class PatchConfig {
|
|||
public final boolean useManager;
|
||||
public final boolean debuggable;
|
||||
public final boolean overrideVersionCode;
|
||||
public final boolean v1;
|
||||
public final boolean v2;
|
||||
public final int sigBypassLevel;
|
||||
public final String originalSignature;
|
||||
public final String appComponentFactory;
|
||||
|
|
@ -16,8 +14,6 @@ public class PatchConfig {
|
|||
boolean useManager,
|
||||
boolean debuggable,
|
||||
boolean overrideVersionCode,
|
||||
boolean v1,
|
||||
boolean v2,
|
||||
int sigBypassLevel,
|
||||
String originalSignature,
|
||||
String appComponentFactory
|
||||
|
|
@ -25,8 +21,6 @@ public class PatchConfig {
|
|||
this.useManager = useManager;
|
||||
this.debuggable = debuggable;
|
||||
this.overrideVersionCode = overrideVersionCode;
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
this.sigBypassLevel = sigBypassLevel;
|
||||
this.originalSignature = originalSignature;
|
||||
this.appComponentFactory = appComponentFactory;
|
||||
|
|
|
|||
Loading…
Reference in New Issue