manager: make some shell op suspend
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user