Update core & Listen app change broadcast & Crash when cannot connect to manager

This commit is contained in:
Nullptr 2022-07-10 23:25:23 +08:00
parent cb1ba36514
commit 8498da904c
No known key found for this signature in database
GPG Key ID: 0B9D02052FF536BD
9 changed files with 75 additions and 34 deletions

View File

@ -37,7 +37,7 @@ public class LSPAppComponentFactoryStub extends AppComponentFactory {
String path = cl.getResource("assets/lspatch/so/" + arch + "/liblspatch.so").getPath().substring(5);
System.load(path);
} catch (Throwable e) {
Log.e("LSPatch", "load lspd error", e);
throw new ExceptionInInitializerError(e);
}
}
}

2
core

@ -1 +1 @@
Subproject commit f3055202da32051de3508407d08838a7df62e872
Subproject commit 6ced1460180d61c647d2ae91e719e8598ca71b94

View File

@ -7,6 +7,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.lsposed.hiddenapibypass.HiddenApiBypass
import org.lsposed.lspatch.manager.AppBroadcastReceiver
import org.lsposed.lspatch.util.LSPPackageManager
import org.lsposed.lspatch.util.ShizukuApi
import java.io.File
@ -25,10 +26,10 @@ class LSPApplication : Application() {
HiddenApiBypass.addHiddenApiExemptions("");
lspApp = this
filesDir.mkdir()
tmpApkDir = cacheDir.resolve("apk")
tmpApkDir.mkdirs()
tmpApkDir = cacheDir.resolve("apk").also { it.mkdir() }
prefs = lspApp.getSharedPreferences("settings", Context.MODE_PRIVATE)
ShizukuApi.init()
AppBroadcastReceiver.register(this)
globalScope.launch { LSPPackageManager.fetchAppList() }
}
}

View File

@ -0,0 +1,39 @@
package org.lsposed.lspatch.manager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.util.Log
import kotlinx.coroutines.runBlocking
import org.lsposed.lspatch.util.LSPPackageManager
class AppBroadcastReceiver : BroadcastReceiver() {
companion object {
private const val TAG = "AppBroadcastReceiver"
private val actions = setOf(
Intent.ACTION_PACKAGE_ADDED,
Intent.ACTION_PACKAGE_REMOVED,
Intent.ACTION_PACKAGE_REPLACED
)
fun register(context: Context) {
val filter = IntentFilter().apply {
actions.forEach(::addAction)
addDataScheme("package")
}
context.registerReceiver(AppBroadcastReceiver(), filter)
}
}
override fun onReceive(context: Context, intent: Intent) {
if (intent.action in actions) {
runBlocking {
Log.i(TAG, "Received intent: $intent")
LSPPackageManager.fetchAppList()
}
}
}
}

View File

@ -343,7 +343,6 @@ private fun DoPatchBody(modifier: Modifier, navigator: DestinationsNavigator) {
var installing by remember { mutableStateOf(false) }
if (installing) InstallDialog(viewModel.patchApp) { status, message ->
scope.launch {
LSPPackageManager.fetchAppList()
installing = false
if (status == PackageInstaller.STATUS_SUCCESS) {
lspApp.globalScope.launch { snackbarHost.showSnackbar(installSuccessfully) }

View File

@ -35,6 +35,7 @@ import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.result.NavResult
import com.ramcosta.composedestinations.result.ResultRecipient
import kotlinx.coroutines.launch
import org.lsposed.lspatch.BuildConfig
import org.lsposed.lspatch.R
import org.lsposed.lspatch.config.ConfigManager
import org.lsposed.lspatch.config.Configs
@ -99,7 +100,6 @@ fun AppManageBody(
val copyError = stringResource(R.string.copy_error)
LaunchedEffect(Unit) {
it.onSuccess {
LSPPackageManager.fetchAppList()
snackbarHost.showSnackbar(updateSuccessfully)
}.onFailure {
val result = snackbarHost.showSnackbar(updateFailed, copyError)
@ -143,7 +143,7 @@ fun AppManageBody(
)
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
val shizukuUnavailable = stringResource(R.string.shizuku_unavailable)
if (it.second.lspConfig.VERSION_CODE >= 319 && it.second.lspConfig.VERSION_CODE < LSPConfig.instance.VERSION_CODE) {
if (it.second.lspConfig.VERSION_CODE < LSPConfig.instance.VERSION_CODE || BuildConfig.DEBUG) {
DropdownMenuItem(
text = { Text(stringResource(R.string.manage_update_loader)) },
onClick = {
@ -194,7 +194,6 @@ fun AppManageBody(
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK) {
scope.launch {
LSPPackageManager.fetchAppList()
snackbarHost.showSnackbar(uninstallSuccessfully)
}
}

View File

@ -38,6 +38,7 @@ import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.ArrayList;
@ -82,6 +83,7 @@ public class LSPApplication {
return;
}
try {
Log.d(TAG, "Initialize service client");
ILSPApplicationService service;
if (config.useManager) {
@ -90,7 +92,6 @@ public class LSPApplication {
service = new LocalApplicationService(context);
}
try {
disableProfile(context);
Startup.initXposed(false, ActivityThread.currentProcessName(), service);
Log.i(TAG, "Bootstrap Xposed");
@ -106,7 +107,7 @@ public class LSPApplication {
switchClassLoader("mClassLoader");
doSigBypass(context);
} catch (Throwable e) {
Log.e(TAG, "Do hook", e);
throw new RuntimeException("Do hook", e);
}
Log.i(TAG, "LSPatch bootstrap completed");
}
@ -130,22 +131,22 @@ public class LSPApplication {
Log.i(TAG, "Use manager: " + config.useManager);
Log.i(TAG, "Signature bypass level: " + config.sigBypassLevel);
String originPath = appInfo.dataDir + "/cache/lspatch/origin/";
String cacheApkPath;
Path originPath = Paths.get(appInfo.dataDir, "cache/lspatch/origin/");
Path cacheApkPath;
try (ZipFile sourceFile = new ZipFile(appInfo.sourceDir)) {
cacheApkPath = originPath + sourceFile.getEntry(ORIGINAL_APK_ASSET_PATH).getCrc() + ".apk";
cacheApkPath = originPath.resolve(sourceFile.getEntry(ORIGINAL_APK_ASSET_PATH).getCrc() + ".apk");
}
appInfo.sourceDir = cacheApkPath;
appInfo.publicSourceDir = cacheApkPath;
appInfo.sourceDir = cacheApkPath.toString();
appInfo.publicSourceDir = cacheApkPath.toString();
appInfo.appComponentFactory = config.appComponentFactory;
if (!Files.exists(Paths.get(cacheApkPath))) {
if (!Files.exists(cacheApkPath)) {
Log.i(TAG, "Extract original apk");
FileUtils.deleteFolderIfExists(Paths.get(originPath));
Files.createDirectories(Paths.get(originPath));
FileUtils.deleteFolderIfExists(originPath);
Files.createDirectories(originPath);
try (InputStream is = baseClassLoader.getResourceAsStream(ORIGINAL_APK_ASSET_PATH)) {
Files.copy(is, Paths.get(cacheApkPath));
Files.copy(is, cacheApkPath);
}
}

View File

@ -9,7 +9,7 @@ import android.os.Environment;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;
import org.lsposed.lspd.models.Module;
import org.lsposed.lspd.service.ILSPApplicationService;
@ -22,15 +22,17 @@ public class RemoteApplicationService implements ILSPApplicationService {
private static final Uri PROVIDER = Uri.parse("content://" + MANAGER_PACKAGE_NAME + ".provider");
private ILSPApplicationService service;
private final ILSPApplicationService service;
public RemoteApplicationService(Context context) {
public RemoteApplicationService(Context context) throws RemoteException {
try {
Bundle back = context.getContentResolver().call(PROVIDER, "getBinder", null, null);
service = ILSPApplicationService.Stub.asInterface(back.getBinder("binder"));
if (service == null) throw new RemoteException("Binder is null");
} catch (Throwable e) {
Log.e("LSPatch", "Error when initializing RemoteApplicationServiceClient", e);
} catch (IllegalArgumentException | NullPointerException e) {
Toast.makeText(context, "Manager died", Toast.LENGTH_SHORT).show();
var r = new RemoteException("Failed to get manager binder");
r.initCause(e);
throw r;
}
}

View File

@ -111,8 +111,8 @@ namespace lspd {
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))};
ScopedLocalRef<jbyteArray> array = JNI_GetStaticObjectField(env, stub, dex_field);
auto dex = PreloadedDex {env->GetByteArrayElements(array.get(), nullptr), static_cast<size_t>(JNI_GetArrayLength(env, array))};
InitArtHooker(env, initInfo);
LoadDex(env, std::move(dex));