Skip to content

Commit b831523

Browse files
authored
Allow uers to chose if inject loader dex (#19)
If we always inject loader dex, then modules with third party libraries might fail to find library classes since the default class loader is alway used before the the loader of the module package. Therefore, it is better to treat packages with isolated services as special cases.
1 parent 7c153f6 commit b831523

File tree

9 files changed

+38
-10
lines changed

9 files changed

+38
-10
lines changed

manager/src/main/java/org/lsposed/lspatch/Patcher.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ import org.lsposed.lspatch.share.PatchConfig
1111
import org.lsposed.patch.LSPatch
1212
import org.lsposed.patch.util.Logger
1313
import java.io.IOException
14+
import java.util.Collections.addAll
1415

1516
object Patcher {
1617

1718
class Options(
19+
private val injectDex: Boolean,
1820
private val config: PatchConfig,
1921
private val apkPaths: List<String>,
2022
private val embeddedModules: List<String>?
@@ -31,6 +33,7 @@ object Patcher {
3133
embeddedModules?.forEach {
3234
add("-m"); add(it)
3335
}
36+
if(injectDex) add("--injectdex")
3437
if (!MyKeyStore.useDefault) {
3538
addAll(arrayOf("-k", MyKeyStore.file.path, Configs.keyStorePassword, Configs.keyStoreAlias, Configs.keyStoreAliasPassword))
3639
}

manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchScreen.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,15 @@ private fun PatchOptionsBody(modifier: Modifier, onAddEmbed: () -> Unit) {
337337
title = stringResource(R.string.patch_override_version_code),
338338
desc = stringResource(R.string.patch_override_version_code_desc)
339339
)
340+
341+
SettingsCheckBox(
342+
modifier = Modifier.clickable { viewModel.injectDex = !viewModel.injectDex },
343+
checked = viewModel.injectDex,
344+
icon = Icons.Outlined.Code,
345+
title = stringResource(R.string.patch_inject_dex),
346+
desc = stringResource(R.string.patch_inject_dex_desc)
347+
)
348+
340349
var bypassExpanded by remember { mutableStateOf(false) }
341350
AnywhereDropdown(
342351
expanded = bypassExpanded,

manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/NewPatchViewModel.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class NewPatchViewModel : ViewModel() {
3838
var debuggable by mutableStateOf(false)
3939
var overrideVersionCode by mutableStateOf(false)
4040
var sigBypassLevel by mutableStateOf(2)
41+
var injectDex by mutableStateOf(false)
4142
var embeddedModules = emptyList<AppInfo>()
4243

4344
lateinit var patchApp: AppInfo
@@ -90,6 +91,7 @@ class NewPatchViewModel : ViewModel() {
9091
Log.d(TAG, "Submit patch")
9192
if (useManager) embeddedModules = emptyList()
9293
patchOptions = Patcher.Options(
94+
injectDex = injectDex,
9395
config = PatchConfig(useManager, debuggable, overrideVersionCode, sigBypassLevel, null, null),
9496
apkPaths = listOf(patchApp.app.sourceDir) + (patchApp.app.splitSourceDirs ?: emptyArray()),
9597
embeddedModules = embeddedModules.flatMap { listOf(it.app.sourceDir) + (it.app.splitSourceDirs ?: emptyArray()) }

manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/manage/AppManageViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class AppManageViewModel : ViewModel() {
117117
}
118118
}
119119
}
120-
Patcher.patch(logger, Patcher.Options(config, patchPaths, embeddedModulePaths))
120+
Patcher.patch(logger, Patcher.Options(false, config, patchPaths, embeddedModulePaths))
121121
val (status, message) = LSPPackageManager.install()
122122
if (status != PackageInstaller.STATUS_SUCCESS) throw RuntimeException(message)
123123
}

manager/src/main/res/values-zh-rCN/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,6 @@
8686
<string name="settings_keystore_wrong_alias">别名错误</string>
8787
<string name="settings_keystore_wrong_alias_password">别名密码错误</string>
8888
<string name="settings_detail_patch_logs">详细修补日志</string>
89+
<string name="patch_inject_dex">注入加载器 Dex</string>
90+
<string name="patch_inject_dex_desc">对那些需要孤立服务进程的应用程序,譬如说浏览器的渲染引擎,请勾选此选项以确保他们正常运行</string>
8991
</resources>

manager/src/main/res/values-zh-rTW/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,6 @@
8686
<string name="settings_keystore_wrong_alias">別名錯誤</string>
8787
<string name="settings_keystore_wrong_alias_password">別名密碼錯誤</string>
8888
<string name="settings_detail_patch_logs">詳細打包日誌</string>
89+
<string name="patch_inject_dex">注入加載器 Dex</string>
90+
<string name="patch_inject_dex_desc">對那些需要孤立服務進程的應用程序,譬如說瀏覽器的渲染引擎,請勾選此選項以確保他們正常運行</string>
8991
</resources>

manager/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,6 @@
9090
<string name="settings_keystore_wrong_alias">Wrong alias name</string>
9191
<string name="settings_keystore_wrong_alias_password">Wrong alias password</string>
9292
<string name="settings_detail_patch_logs">Detail patch logs</string>
93+
<string name="patch_inject_dex">Inject loader dex</string>
94+
<string name="patch_inject_dex_desc">For applications with isolated services, such as the render engines of browsers, please turn on this option to ensure that they work properly.</string>
9395
</resources>

patch/src/main/java/org/lsposed/patch/LSPatch.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import java.util.List;
4747
import java.util.Locale;
4848
import java.util.Objects;
49-
import java.util.Set;
5049
import java.util.stream.Collectors;
5150

5251
public class LSPatch {
@@ -79,6 +78,9 @@ public PatchError(String message, Throwable cause) {
7978
@Parameter(names = {"-l", "--sigbypasslv"}, description = "Signature bypass level. 0 (disable), 1 (pm), 2 (pm+openat). default 0")
8079
private int sigbypassLevel = 0;
8180

81+
@Parameter(names = {"--injectdex"}, description = "Inject directly the loder dex file into the original application package")
82+
private boolean injectDex = false;
83+
8284
@Parameter(names = {"-k", "--keystore"}, arity = 4, description = "Set custom signature keystore. Followed by 4 arguments: keystore path, keystore password, keystore alias, keystore alias password")
8385
private List<String> keystoreArgs = Arrays.asList(null, "123456", "key0", "123456");
8486

@@ -208,7 +210,7 @@ public void patch(File srcApkFile, File outputFile) throws PatchError, IOExcepti
208210

209211
String originalSignature = null;
210212
if (sigbypassLevel > 0) {
211-
originalSignature = ApkSignatureHelper.getApkSignInfo(srcApkFile.getAbsolutePath());
213+
originalSignature = ApkSignatureHelper.getApkSignInfo(srcApkFile.getAbsolutePath());
212214
if (originalSignature == null || originalSignature.isEmpty()) {
213215
throw new PatchError("get original signature failed");
214216
}
@@ -239,7 +241,8 @@ public void patch(File srcApkFile, File outputFile) throws PatchError, IOExcepti
239241
for (StoredEntry entry : srcZFile.entries()) {
240242
String name = entry.getCentralDirectoryHeader().getName();
241243
if (dstZFile.get(name) != null) continue;
242-
if (name.startsWith("META-INF") && (name.endsWith(".SF") || name.endsWith(".MF") || name.endsWith(".RSA"))) continue;
244+
if (name.startsWith("META-INF") && (name.endsWith(".SF") || name.endsWith(".MF") || name.endsWith(".RSA")))
245+
continue;
243246
srcZFile.addFileLink(name, name);
244247
}
245248
return;
@@ -266,11 +269,15 @@ public void patch(File srcApkFile, File outputFile) throws PatchError, IOExcepti
266269

267270
logger.i("Adding metaloader dex...");
268271
try (var is = getClass().getClassLoader().getResourceAsStream(Constants.META_LOADER_DEX_ASSET_PATH)) {
269-
var dexCount = srcZFile.entries().stream().filter(entry -> {
270-
var name = entry.getCentralDirectoryHeader().getName();
271-
return name.startsWith("classes") && name.endsWith(".dex");
272-
}).collect(Collectors.toList()).size() + 1;
273-
dstZFile.add("classes" + dexCount + ".dex", is);
272+
if (!injectDex) {
273+
dstZFile.add("classes.dex", is);
274+
} else {
275+
var dexCount = srcZFile.entries().stream().filter(entry -> {
276+
var name = entry.getCentralDirectoryHeader().getName();
277+
return name.startsWith("classes") && name.endsWith(".dex");
278+
}).collect(Collectors.toList()).size() + 1;
279+
dstZFile.add("classes" + dexCount + ".dex", is);
280+
}
274281
} catch (Throwable e) {
275282
throw new PatchError("Error when adding dex", e);
276283
}
@@ -307,6 +314,7 @@ public void patch(File srcApkFile, File outputFile) throws PatchError, IOExcepti
307314
for (StoredEntry entry : srcZFile.entries()) {
308315
String name = entry.getCentralDirectoryHeader().getName();
309316
if (dstZFile.get(name) != null) continue;
317+
if (!injectDex && name.startsWith("classes") && name.endsWith(".dex")) continue;
310318
if (name.equals("AndroidManifest.xml")) continue;
311319
if (name.startsWith("META-INF") && (name.endsWith(".SF") || name.endsWith(".MF") || name.endsWith(".RSA"))) continue;
312320
srcZFile.addFileLink(name, name);

0 commit comments

Comments
 (0)