From 107a34789efaa192bc7a1a55bb3cdea0d77d64c3 Mon Sep 17 00:00:00 2001 From: weishu Date: Thu, 20 Feb 2025 20:56:21 +0800 Subject: [PATCH] manager: refine flashing module utilities --- .../me/weishu/kernelsu/ui/screen/Flash.kt | 42 ++++++++--------- .../me/weishu/kernelsu/ui/screen/Module.kt | 4 +- .../java/me/weishu/kernelsu/ui/util/KsuCli.kt | 45 ++++++++++++------- 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Flash.kt b/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Flash.kt index c8bd8c86..4719004e 100644 --- a/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Flash.kt +++ b/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Flash.kt @@ -53,9 +53,10 @@ import kotlinx.coroutines.withContext import kotlinx.parcelize.Parcelize import me.weishu.kernelsu.R import me.weishu.kernelsu.ui.component.KeyEventBlocker +import me.weishu.kernelsu.ui.util.FlashResult import me.weishu.kernelsu.ui.util.LkmSelection import me.weishu.kernelsu.ui.util.LocalSnackbarHost -import me.weishu.kernelsu.ui.util.flashModule +import me.weishu.kernelsu.ui.util.flashModules import me.weishu.kernelsu.ui.util.installBoot import me.weishu.kernelsu.ui.util.reboot import me.weishu.kernelsu.ui.util.restoreBoot @@ -81,7 +82,7 @@ enum class FlashingStatus { fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { var text by rememberSaveable { mutableStateOf("") } - var tempText : String + var tempText: String val logContent = rememberSaveable { StringBuilder() } var showFloatAction by rememberSaveable { mutableStateOf(false) } @@ -98,16 +99,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { return@LaunchedEffect } withContext(Dispatchers.IO) { - flashIt(flashIt, onFinish = { showReboot, code -> - if (code != 0) { - text += "Error: exit code = $code.\nPlease save and check the log.\n" - } - if (showReboot) { - text += "\n\n\n" - showFloatAction = true - } - flashing = if (code == 0) FlashingStatus.SUCCESS else FlashingStatus.FAILED - }, onStdout = { + flashIt(flashIt, onStdout = { tempText = "$it\n" if (tempText.startsWith("")) { // clear command text = tempText.substring(6) @@ -117,7 +109,16 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { logContent.append(it).append("\n") }, onStderr = { logContent.append(it).append("\n") - }) + }).apply { + if (code != 0) { + text += "Error code: $code.\n $err Please save and check the log.\n" + } + if (showReboot) { + text += "\n\n\n" + showFloatAction = true + } + flashing = if (code == 0) FlashingStatus.SUCCESS else FlashingStatus.FAILED + } } } @@ -191,7 +192,7 @@ sealed class FlashIt : Parcelable { data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) : FlashIt() - data class FlashModule(val uri: Uri) : FlashIt() + data class FlashModules(val uri: List) : FlashIt() data object FlashRestore : FlashIt() @@ -199,25 +200,24 @@ sealed class FlashIt : Parcelable { } fun flashIt( - flashIt: FlashIt, onFinish: (Boolean, Int) -> Unit, + flashIt: FlashIt, onStdout: (String) -> Unit, onStderr: (String) -> Unit -) { - when (flashIt) { +): FlashResult { + return when (flashIt) { is FlashIt.FlashBoot -> installBoot( flashIt.boot, flashIt.lkm, flashIt.ota, - onFinish, onStdout, onStderr ) - is FlashIt.FlashModule -> flashModule(flashIt.uri, onFinish, onStdout, onStderr) + is FlashIt.FlashModules -> flashModules(flashIt.uri, onStdout, onStderr) - FlashIt.FlashRestore -> restoreBoot(onFinish, onStdout, onStderr) + FlashIt.FlashRestore -> restoreBoot(onStdout, onStderr) - FlashIt.FlashUninstall -> uninstallPermanently(onFinish, onStdout, onStderr) + FlashIt.FlashUninstall -> uninstallPermanently(onStdout, onStderr) } } diff --git a/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Module.kt b/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Module.kt index 9463d944..beddc887 100644 --- a/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Module.kt +++ b/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Module.kt @@ -209,7 +209,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) { val data = it.data ?: return@rememberLauncherForActivityResult val uri = data.data ?: return@rememberLauncherForActivityResult - navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(uri))) + navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(listOf(uri)))) viewModel.markNeedRefresh() @@ -254,7 +254,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) { modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), boxModifier = Modifier.padding(innerPadding), onInstallModule = { - navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(it))) + navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(listOf(it)))) }, onClickModule = { id, name, hasWebUi -> if (hasWebUi) { diff --git a/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt b/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt index 8b325848..7ab5a1b5 100644 --- a/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt +++ b/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt @@ -33,6 +33,11 @@ private fun getKsuDaemonPath(): String { return ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libksud.so" } +data class FlashResult(val code: Int, val err: String, val showReboot: Boolean) { + constructor(result: Shell.Result, showReboot: Boolean) : this(result.code, result.err.joinToString("\n"), showReboot) + constructor(result: Shell.Result) : this(result, result.isSuccess) +} + object KsuCli { val SHELL: Shell = createRootShell() val GLOBAL_MNT_SHELL: Shell = createRootShell(true) @@ -167,10 +172,9 @@ private fun flashWithIO( fun flashModule( uri: Uri, - onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit -): Boolean { +): FlashResult { val resolver = ksuApp.contentResolver with(resolver.openInputStream(uri)) { val file = File(ksuApp.cacheDir, "module.zip") @@ -183,11 +187,24 @@ fun flashModule( file.delete() - onFinish(result.isSuccess, result.code) - return result.isSuccess + return FlashResult(result) } } +fun flashModules( + uris: List, + onStdout: (String) -> Unit, + onStderr: (String) -> Unit +): FlashResult { + for (uri in uris) { + val result = flashModule(uri, onStdout, onStderr) + if (result.code != 0) { + return result + } + } + return FlashResult(0, "", true) +} + fun runModuleAction( moduleId: String, onStdout: (String) -> Unit, onStderr: (String) -> Unit ): Boolean { @@ -213,21 +230,19 @@ fun runModuleAction( } fun restoreBoot( - onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit -): Boolean { + onStdout: (String) -> Unit, onStderr: (String) -> Unit +): FlashResult { val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so") val result = flashWithIO("${getKsuDaemonPath()} boot-restore -f --magiskboot $magiskboot", onStdout, onStderr) - onFinish(result.isSuccess, result.code) - return result.isSuccess + return FlashResult(result) } fun uninstallPermanently( - onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit -): Boolean { + onStdout: (String) -> Unit, onStderr: (String) -> Unit +): FlashResult { val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so") val result = flashWithIO("${getKsuDaemonPath()} uninstall --magiskboot $magiskboot", onStdout, onStderr) - onFinish(result.isSuccess, result.code) - return result.isSuccess + return FlashResult(result) } suspend fun shrinkModules(): Boolean = withContext(Dispatchers.IO) { @@ -245,10 +260,9 @@ fun installBoot( bootUri: Uri?, lkm: LkmSelection, ota: Boolean, - onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit, -): Boolean { +): FlashResult { val resolver = ksuApp.contentResolver val bootFile = bootUri?.let { uri -> @@ -311,8 +325,7 @@ fun installBoot( lkmFile?.delete() // if boot uri is empty, it is direct install, when success, we should show reboot button - onFinish(bootUri == null && result.isSuccess, result.code) - return result.isSuccess + return FlashResult(result, bootUri == null && result.isSuccess) } fun reboot(reason: String = "") {