manager: refine flash utilities

This commit is contained in:
Tiann
2025-02-20 23:45:04 +06:00
committed by rifsxd
parent 60d2ad39d6
commit 373025248d
2 changed files with 37 additions and 60 deletions
@@ -59,6 +59,7 @@ import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.KeyEventBlocker
import com.rifsxd.ksunext.ui.util.FlashResult
import com.rifsxd.ksunext.ui.util.LkmSelection
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.flashModule
@@ -80,38 +81,17 @@ enum class FlashingStatus {
// Lets you flash modules sequentially when mutiple zipUris are selected
fun flashModulesSequentially(
uris: List<Uri>,
onFinish: (Boolean, Int) -> Unit,
onStdout: (String) -> Unit,
onStderr: (String) -> Unit
) {
val iterator = uris.iterator()
// Start processing from the first module inside a coroutine
CoroutineScope(Dispatchers.IO).launch {
// Define the recursive function within the coroutine
suspend fun processNext() {
if (iterator.hasNext()) {
// Flash the current module
flashModule(iterator.next(), onFinish = { showReboot, code ->
// If successful, continue to the next one
if (code == 0) {
// Recursively call to process the next module
launch {
processNext()
}
} else {
onFinish(showReboot, code) // If failed, finish the process
}
}, onStdout, onStderr)
} else {
// No more modules to process, finish the process
onFinish(true, 0)
): FlashResult {
for (uri in uris) {
flashModule(uri, onStdout, onStderr).apply {
if (code != 0) {
return FlashResult(code, err, showReboot)
}
}
// Start the process
processNext()
}
return FlashResult(0, "", true)
}
/**
@@ -124,7 +104,7 @@ fun flashModulesSequentially(
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) }
@@ -145,16 +125,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)
@@ -164,7 +135,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
}
}
}
@@ -248,16 +228,15 @@ 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
)
@@ -49,6 +49,11 @@ fun getKsuDaemonPath(): String {
}
}
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)
@@ -190,10 +195,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")
@@ -206,9 +210,7 @@ fun flashModule(
file.delete()
onFinish(result.isSuccess, result.code)
return result.isSuccess
}
return FlashResult(result)
}
fun runModuleAction(
@@ -236,21 +238,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) {
@@ -268,10 +268,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 ->
@@ -334,8 +333,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 = "") {