manager: refine flashing module utilities
This commit is contained in:
@@ -53,9 +53,10 @@ import kotlinx.coroutines.withContext
|
|||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import me.weishu.kernelsu.R
|
import me.weishu.kernelsu.R
|
||||||
import me.weishu.kernelsu.ui.component.KeyEventBlocker
|
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.LkmSelection
|
||||||
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
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.installBoot
|
||||||
import me.weishu.kernelsu.ui.util.reboot
|
import me.weishu.kernelsu.ui.util.reboot
|
||||||
import me.weishu.kernelsu.ui.util.restoreBoot
|
import me.weishu.kernelsu.ui.util.restoreBoot
|
||||||
@@ -81,7 +82,7 @@ enum class FlashingStatus {
|
|||||||
fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||||
|
|
||||||
var text by rememberSaveable { mutableStateOf("") }
|
var text by rememberSaveable { mutableStateOf("") }
|
||||||
var tempText : String
|
var tempText: String
|
||||||
val logContent = rememberSaveable { StringBuilder() }
|
val logContent = rememberSaveable { StringBuilder() }
|
||||||
var showFloatAction by rememberSaveable { mutableStateOf(false) }
|
var showFloatAction by rememberSaveable { mutableStateOf(false) }
|
||||||
|
|
||||||
@@ -98,16 +99,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
|||||||
return@LaunchedEffect
|
return@LaunchedEffect
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
flashIt(flashIt, onFinish = { showReboot, code ->
|
flashIt(flashIt, onStdout = {
|
||||||
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 = {
|
|
||||||
tempText = "$it\n"
|
tempText = "$it\n"
|
||||||
if (tempText.startsWith("[H[J")) { // clear command
|
if (tempText.startsWith("[H[J")) { // clear command
|
||||||
text = tempText.substring(6)
|
text = tempText.substring(6)
|
||||||
@@ -117,7 +109,16 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
|||||||
logContent.append(it).append("\n")
|
logContent.append(it).append("\n")
|
||||||
}, onStderr = {
|
}, onStderr = {
|
||||||
logContent.append(it).append("\n")
|
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) :
|
data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) :
|
||||||
FlashIt()
|
FlashIt()
|
||||||
|
|
||||||
data class FlashModule(val uri: Uri) : FlashIt()
|
data class FlashModules(val uri: List<Uri>) : FlashIt()
|
||||||
|
|
||||||
data object FlashRestore : FlashIt()
|
data object FlashRestore : FlashIt()
|
||||||
|
|
||||||
@@ -199,25 +200,24 @@ sealed class FlashIt : Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun flashIt(
|
fun flashIt(
|
||||||
flashIt: FlashIt, onFinish: (Boolean, Int) -> Unit,
|
flashIt: FlashIt,
|
||||||
onStdout: (String) -> Unit,
|
onStdout: (String) -> Unit,
|
||||||
onStderr: (String) -> Unit
|
onStderr: (String) -> Unit
|
||||||
) {
|
): FlashResult {
|
||||||
when (flashIt) {
|
return when (flashIt) {
|
||||||
is FlashIt.FlashBoot -> installBoot(
|
is FlashIt.FlashBoot -> installBoot(
|
||||||
flashIt.boot,
|
flashIt.boot,
|
||||||
flashIt.lkm,
|
flashIt.lkm,
|
||||||
flashIt.ota,
|
flashIt.ota,
|
||||||
onFinish,
|
|
||||||
onStdout,
|
onStdout,
|
||||||
onStderr
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
|||||||
val data = it.data ?: return@rememberLauncherForActivityResult
|
val data = it.data ?: return@rememberLauncherForActivityResult
|
||||||
val uri = data.data ?: return@rememberLauncherForActivityResult
|
val uri = data.data ?: return@rememberLauncherForActivityResult
|
||||||
|
|
||||||
navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(uri)))
|
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(listOf(uri))))
|
||||||
|
|
||||||
viewModel.markNeedRefresh()
|
viewModel.markNeedRefresh()
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
|||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
boxModifier = Modifier.padding(innerPadding),
|
boxModifier = Modifier.padding(innerPadding),
|
||||||
onInstallModule = {
|
onInstallModule = {
|
||||||
navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(it)))
|
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(listOf(it))))
|
||||||
},
|
},
|
||||||
onClickModule = { id, name, hasWebUi ->
|
onClickModule = { id, name, hasWebUi ->
|
||||||
if (hasWebUi) {
|
if (hasWebUi) {
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ private fun getKsuDaemonPath(): String {
|
|||||||
return ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libksud.so"
|
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 {
|
object KsuCli {
|
||||||
val SHELL: Shell = createRootShell()
|
val SHELL: Shell = createRootShell()
|
||||||
val GLOBAL_MNT_SHELL: Shell = createRootShell(true)
|
val GLOBAL_MNT_SHELL: Shell = createRootShell(true)
|
||||||
@@ -167,10 +172,9 @@ private fun flashWithIO(
|
|||||||
|
|
||||||
fun flashModule(
|
fun flashModule(
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
onFinish: (Boolean, Int) -> Unit,
|
|
||||||
onStdout: (String) -> Unit,
|
onStdout: (String) -> Unit,
|
||||||
onStderr: (String) -> Unit
|
onStderr: (String) -> Unit
|
||||||
): Boolean {
|
): FlashResult {
|
||||||
val resolver = ksuApp.contentResolver
|
val resolver = ksuApp.contentResolver
|
||||||
with(resolver.openInputStream(uri)) {
|
with(resolver.openInputStream(uri)) {
|
||||||
val file = File(ksuApp.cacheDir, "module.zip")
|
val file = File(ksuApp.cacheDir, "module.zip")
|
||||||
@@ -183,11 +187,24 @@ fun flashModule(
|
|||||||
|
|
||||||
file.delete()
|
file.delete()
|
||||||
|
|
||||||
onFinish(result.isSuccess, result.code)
|
return FlashResult(result)
|
||||||
return result.isSuccess
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun flashModules(
|
||||||
|
uris: List<Uri>,
|
||||||
|
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(
|
fun runModuleAction(
|
||||||
moduleId: String, onStdout: (String) -> Unit, onStderr: (String) -> Unit
|
moduleId: String, onStdout: (String) -> Unit, onStderr: (String) -> Unit
|
||||||
): Boolean {
|
): Boolean {
|
||||||
@@ -213,21 +230,19 @@ fun runModuleAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun restoreBoot(
|
fun restoreBoot(
|
||||||
onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit
|
onStdout: (String) -> Unit, onStderr: (String) -> Unit
|
||||||
): Boolean {
|
): FlashResult {
|
||||||
val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so")
|
val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so")
|
||||||
val result = flashWithIO("${getKsuDaemonPath()} boot-restore -f --magiskboot $magiskboot", onStdout, onStderr)
|
val result = flashWithIO("${getKsuDaemonPath()} boot-restore -f --magiskboot $magiskboot", onStdout, onStderr)
|
||||||
onFinish(result.isSuccess, result.code)
|
return FlashResult(result)
|
||||||
return result.isSuccess
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun uninstallPermanently(
|
fun uninstallPermanently(
|
||||||
onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit
|
onStdout: (String) -> Unit, onStderr: (String) -> Unit
|
||||||
): Boolean {
|
): FlashResult {
|
||||||
val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so")
|
val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so")
|
||||||
val result = flashWithIO("${getKsuDaemonPath()} uninstall --magiskboot $magiskboot", onStdout, onStderr)
|
val result = flashWithIO("${getKsuDaemonPath()} uninstall --magiskboot $magiskboot", onStdout, onStderr)
|
||||||
onFinish(result.isSuccess, result.code)
|
return FlashResult(result)
|
||||||
return result.isSuccess
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun shrinkModules(): Boolean = withContext(Dispatchers.IO) {
|
suspend fun shrinkModules(): Boolean = withContext(Dispatchers.IO) {
|
||||||
@@ -245,10 +260,9 @@ fun installBoot(
|
|||||||
bootUri: Uri?,
|
bootUri: Uri?,
|
||||||
lkm: LkmSelection,
|
lkm: LkmSelection,
|
||||||
ota: Boolean,
|
ota: Boolean,
|
||||||
onFinish: (Boolean, Int) -> Unit,
|
|
||||||
onStdout: (String) -> Unit,
|
onStdout: (String) -> Unit,
|
||||||
onStderr: (String) -> Unit,
|
onStderr: (String) -> Unit,
|
||||||
): Boolean {
|
): FlashResult {
|
||||||
val resolver = ksuApp.contentResolver
|
val resolver = ksuApp.contentResolver
|
||||||
|
|
||||||
val bootFile = bootUri?.let { uri ->
|
val bootFile = bootUri?.let { uri ->
|
||||||
@@ -311,8 +325,7 @@ fun installBoot(
|
|||||||
lkmFile?.delete()
|
lkmFile?.delete()
|
||||||
|
|
||||||
// if boot uri is empty, it is direct install, when success, we should show reboot button
|
// if boot uri is empty, it is direct install, when success, we should show reboot button
|
||||||
onFinish(bootUri == null && result.isSuccess, result.code)
|
return FlashResult(result, bootUri == null && result.isSuccess)
|
||||||
return result.isSuccess
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reboot(reason: String = "") {
|
fun reboot(reason: String = "") {
|
||||||
|
|||||||
Reference in New Issue
Block a user