manager: make some shell op suspend

This commit is contained in:
weishu
2024-03-23 15:12:34 +08:00
parent c924c655df
commit 7451d0fb83
2 changed files with 40 additions and 52 deletions

View File

@@ -26,6 +26,7 @@ import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@@ -79,7 +80,7 @@ fun InstallScreen(navigator: DestinationsNavigator) {
} }
} }
val currentKmi = remember { getCurrentKmi() } val currentKmi by produceState(initialValue = "") { value = getCurrentKmi() }
val selectKmiDialog = rememberSelectKmiDialog { kmi -> val selectKmiDialog = rememberSelectKmiDialog { kmi ->
kmi?.let { kmi?.let {
@@ -107,17 +108,14 @@ fun InstallScreen(navigator: DestinationsNavigator) {
} }
val onLkmUpload = { val onLkmUpload = {
selectLkmLauncher.launch( selectLkmLauncher.launch(Intent(Intent.ACTION_GET_CONTENT).apply {
Intent(Intent.ACTION_GET_CONTENT).apply { type = "application/octet-stream"
type = "application/octet-stream" })
}
)
} }
Scaffold(topBar = { Scaffold(topBar = {
TopBar( TopBar(
onBack = { navigator.popBackStack() }, onBack = { navigator.popBackStack() }, onLkmUpload = onLkmUpload
onLkmUpload = onLkmUpload
) )
}) { }) {
Column(modifier = Modifier.padding(it)) { Column(modifier = Modifier.padding(it)) {
@@ -130,8 +128,7 @@ fun InstallScreen(navigator: DestinationsNavigator) {
.fillMaxWidth() .fillMaxWidth()
.padding(16.dp) .padding(16.dp)
) { ) {
Button( Button(modifier = Modifier.fillMaxWidth(),
modifier = Modifier.fillMaxWidth(),
enabled = installMethod != null, enabled = installMethod != null,
onClick = { onClick = {
onClickNext() onClickNext()
@@ -172,8 +169,7 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
val rootAvailable = rootAvailable() val rootAvailable = rootAvailable()
val isAbDevice = isAbDevice() val isAbDevice = isAbDevice()
val selectFileTip = stringResource( val selectFileTip = stringResource(
id = R.string.select_file_tip, id = R.string.select_file_tip, if (isInitBoot()) "init_boot" else "boot"
if (isInitBoot()) "init_boot" else "boot"
) )
val radioOptions = val radioOptions =
mutableListOf<InstallMethod>(InstallMethod.SelectFile(summary = selectFileTip)) mutableListOf<InstallMethod>(InstallMethod.SelectFile(summary = selectFileTip))
@@ -209,11 +205,9 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
when (option) { when (option) {
is InstallMethod.SelectFile -> { is InstallMethod.SelectFile -> {
selectImageLauncher.launch( selectImageLauncher.launch(Intent(Intent.ACTION_GET_CONTENT).apply {
Intent(Intent.ACTION_GET_CONTENT).apply { type = "application/octet-stream"
type = "application/octet-stream" })
}
)
} }
is InstallMethod.DirectInstall -> { is InstallMethod.DirectInstall -> {
@@ -263,51 +257,43 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
@Composable @Composable
fun rememberSelectKmiDialog(onSelected: (String?) -> Unit): DialogHandle { fun rememberSelectKmiDialog(onSelected: (String?) -> Unit): DialogHandle {
return rememberCustomDialog { dismiss -> return rememberCustomDialog { dismiss ->
val kmis = remember { val supportedKmi by produceState(initialValue = emptyList<String>()) {
getSupportedKmis() value = getSupportedKmis()
} }
val options = kmis.map { value -> val options = supportedKmi.map { value ->
ListOption( ListOption(
titleText = value titleText = value
) )
} }
var selection: String? = null var selection: String? = null
ListDialog( ListDialog(state = rememberUseCaseState(visible = true, onFinishedRequest = {
state = rememberUseCaseState(visible = true, onFinishedRequest = { onSelected(selection)
onSelected(selection) }, onCloseRequest = {
}, onCloseRequest = { dismiss()
dismiss() }), header = Header.Default(
}), title = stringResource(R.string.select_kmi),
header = Header.Default( ), selection = ListSelection.Single(
title = stringResource(R.string.select_kmi), showRadioButtons = true,
), options = options,
selection = ListSelection.Single( ) { _, option ->
showRadioButtons = true, selection = option.titleText
options = options, })
) { _, option ->
selection = option.titleText
}
)
} }
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun TopBar(onBack: () -> Unit = {}, onLkmUpload: () -> Unit = {}) { private fun TopBar(onBack: () -> Unit = {}, onLkmUpload: () -> Unit = {}) {
TopAppBar( TopAppBar(title = { Text(stringResource(R.string.install)) }, navigationIcon = {
title = { Text(stringResource(R.string.install)) }, IconButton(
navigationIcon = { onClick = onBack
IconButton( ) { Icon(Icons.Filled.ArrowBack, contentDescription = null) }
onClick = onBack }, actions = {
) { Icon(Icons.Filled.ArrowBack, contentDescription = null) } IconButton(onClick = onLkmUpload) {
}, Icon(Icons.Filled.FileUpload, contentDescription = null)
actions = {
IconButton(onClick = onLkmUpload) {
Icon(Icons.Filled.FileUpload, contentDescription = null)
}
} }
) })
} }
@Composable @Composable

View File

@@ -10,6 +10,8 @@ import com.topjohnwu.superuser.CallbackList
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.ShellUtils import com.topjohnwu.superuser.ShellUtils
import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFile
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import me.weishu.kernelsu.BuildConfig import me.weishu.kernelsu.BuildConfig
import me.weishu.kernelsu.Natives import me.weishu.kernelsu.Natives
@@ -270,17 +272,17 @@ fun isInitBoot(): Boolean {
.toInt() >= Build.VERSION_CODES.TIRAMISU .toInt() >= Build.VERSION_CODES.TIRAMISU
} }
fun getCurrentKmi(): String { suspend fun getCurrentKmi(): String = withContext(Dispatchers.IO) {
val shell = getRootShell() val shell = getRootShell()
val cmd = "boot-info current-kmi" val cmd = "boot-info current-kmi"
return ShellUtils.fastCmd(shell, "${getKsuDaemonPath()} $cmd") ShellUtils.fastCmd(shell, "${getKsuDaemonPath()} $cmd")
} }
fun getSupportedKmis(): List<String> { suspend fun getSupportedKmis(): List<String> = withContext(Dispatchers.IO) {
val shell = getRootShell() val shell = getRootShell()
val cmd = "boot-info supported-kmi" val cmd = "boot-info supported-kmi"
val out = shell.newJob().add("${getKsuDaemonPath()} $cmd").to(ArrayList(), null).exec().out val out = shell.newJob().add("${getKsuDaemonPath()} $cmd").to(ArrayList(), null).exec().out
return out.filter { it.isNotBlank() }.map { it.trim() } out.filter { it.isNotBlank() }.map { it.trim() }
} }
fun overlayFsAvailable(): Boolean { fun overlayFsAvailable(): Boolean {