Optimize the error handling logic for loading and unloading modules, this will fix the file type error, and more detail handling-2
This commit is contained in:
@@ -49,6 +49,7 @@ import shirkneko.zako.sukisu.ui.theme.KernelSUTheme
|
|||||||
import shirkneko.zako.sukisu.ui.theme.loadCustomBackground
|
import shirkneko.zako.sukisu.ui.theme.loadCustomBackground
|
||||||
import shirkneko.zako.sukisu.ui.theme.loadThemeMode
|
import shirkneko.zako.sukisu.ui.theme.loadThemeMode
|
||||||
import shirkneko.zako.sukisu.ui.util.LocalSnackbarHost
|
import shirkneko.zako.sukisu.ui.util.LocalSnackbarHost
|
||||||
|
import shirkneko.zako.sukisu.ui.util.getKpmVersion
|
||||||
import shirkneko.zako.sukisu.ui.util.rootAvailable
|
import shirkneko.zako.sukisu.ui.util.rootAvailable
|
||||||
import shirkneko.zako.sukisu.ui.util.install
|
import shirkneko.zako.sukisu.ui.util.install
|
||||||
|
|
||||||
@@ -107,6 +108,7 @@ private fun BottomBar(navController: NavHostController) {
|
|||||||
val navigator = navController.rememberDestinationsNavigator()
|
val navigator = navController.rememberDestinationsNavigator()
|
||||||
val isManager = Natives.becomeManager(ksuApp.packageName)
|
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||||
val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable()
|
val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable()
|
||||||
|
val kpmVersion = getKpmVersion()
|
||||||
|
|
||||||
// 获取卡片颜色和透明度
|
// 获取卡片颜色和透明度
|
||||||
val cardColor = MaterialTheme.colorScheme.secondaryContainer
|
val cardColor = MaterialTheme.colorScheme.secondaryContainer
|
||||||
@@ -122,35 +124,69 @@ private fun BottomBar(navController: NavHostController) {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
BottomBarDestination.entries.forEach { destination ->
|
BottomBarDestination.entries.forEach { destination ->
|
||||||
if (!fullFeatured && destination.rootRequired) return@forEach
|
if (destination == BottomBarDestination.Kpm) {
|
||||||
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
|
if (kpmVersion.isNotEmpty() && !kpmVersion.startsWith("Error")) {
|
||||||
NavigationBarItem(
|
if (!fullFeatured && destination.rootRequired) return@forEach
|
||||||
selected = isCurrentDestOnBackStack,
|
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
|
||||||
onClick = {
|
NavigationBarItem(
|
||||||
if (isCurrentDestOnBackStack) {
|
selected = isCurrentDestOnBackStack,
|
||||||
navigator.popBackStack(destination.direction, false)
|
onClick = {
|
||||||
}
|
if (isCurrentDestOnBackStack) {
|
||||||
navigator.navigate(destination.direction) {
|
navigator.popBackStack(destination.direction, false)
|
||||||
popUpTo(NavGraphs.root) {
|
}
|
||||||
saveState = true
|
navigator.navigate(destination.direction) {
|
||||||
|
popUpTo(NavGraphs.root) {
|
||||||
|
saveState = true
|
||||||
|
}
|
||||||
|
launchSingleTop = true
|
||||||
|
restoreState = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon = {
|
||||||
|
if (isCurrentDestOnBackStack) {
|
||||||
|
Icon(destination.iconSelected, stringResource(destination.label))
|
||||||
|
} else {
|
||||||
|
Icon(destination.iconNotSelected, stringResource(destination.label))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label = { Text(stringResource(destination.label)) },
|
||||||
|
alwaysShowLabel = false,
|
||||||
|
colors = androidx.compose.material3.NavigationBarItemDefaults.colors(
|
||||||
|
unselectedTextColor = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!fullFeatured && destination.rootRequired) return@forEach
|
||||||
|
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
|
||||||
|
NavigationBarItem(
|
||||||
|
selected = isCurrentDestOnBackStack,
|
||||||
|
onClick = {
|
||||||
|
if (isCurrentDestOnBackStack) {
|
||||||
|
navigator.popBackStack(destination.direction, false)
|
||||||
}
|
}
|
||||||
launchSingleTop = true
|
navigator.navigate(destination.direction) {
|
||||||
restoreState = true
|
popUpTo(NavGraphs.root) {
|
||||||
}
|
saveState = true
|
||||||
},
|
}
|
||||||
icon = {
|
launchSingleTop = true
|
||||||
if (isCurrentDestOnBackStack) {
|
restoreState = true
|
||||||
Icon(destination.iconSelected, stringResource(destination.label))
|
}
|
||||||
} else {
|
},
|
||||||
Icon(destination.iconNotSelected, stringResource(destination.label))
|
icon = {
|
||||||
}
|
if (isCurrentDestOnBackStack) {
|
||||||
},
|
Icon(destination.iconSelected, stringResource(destination.label))
|
||||||
label = { Text(stringResource(destination.label)) },
|
} else {
|
||||||
alwaysShowLabel = false,
|
Icon(destination.iconNotSelected, stringResource(destination.label))
|
||||||
colors = androidx.compose.material3.NavigationBarItemDefaults.colors(
|
}
|
||||||
unselectedTextColor = MaterialTheme.colorScheme.onSurfaceVariant
|
},
|
||||||
|
label = { Text(stringResource(destination.label)) },
|
||||||
|
alwaysShowLabel = false,
|
||||||
|
colors = androidx.compose.material3.NavigationBarItemDefaults.colors(
|
||||||
|
unselectedTextColor = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,8 +21,8 @@ enum class BottomBarDestination(
|
|||||||
val rootRequired: Boolean,
|
val rootRequired: Boolean,
|
||||||
) {
|
) {
|
||||||
Home(HomeScreenDestination, R.string.home, Icons.Filled.Home, Icons.Outlined.Home, false),
|
Home(HomeScreenDestination, R.string.home, Icons.Filled.Home, Icons.Outlined.Home, false),
|
||||||
|
Kpm(KpmScreenDestination, R.string.kpm_title, Icons.Filled.Build, Icons.Outlined.Build, true),
|
||||||
SuperUser(SuperUserScreenDestination, R.string.superuser, Icons.Filled.Security, Icons.Outlined.Security, true),
|
SuperUser(SuperUserScreenDestination, R.string.superuser, Icons.Filled.Security, Icons.Outlined.Security, true),
|
||||||
Module(ModuleScreenDestination, R.string.module, Icons.Filled.Apps, Icons.Outlined.Apps, true),
|
Module(ModuleScreenDestination, R.string.module, Icons.Filled.Apps, Icons.Outlined.Apps, true),
|
||||||
Kpm(KpmScreenDestination, R.string.kpm_title, Icons.Filled.Build, Icons.Outlined.Build, true),
|
|
||||||
Settings(SettingScreenDestination, R.string.settings, Icons.Filled.Settings, Icons.Outlined.Settings, false),
|
Settings(SettingScreenDestination, R.string.settings, Icons.Filled.Settings, Icons.Outlined.Settings, false),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ import androidx.compose.animation.shrinkVertically
|
|||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import shirkneko.zako.sukisu.ui.theme.CardConfig
|
import shirkneko.zako.sukisu.ui.theme.CardConfig
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
|
import java.io.BufferedReader
|
||||||
|
import java.io.InputStreamReader
|
||||||
|
import java.util.Scanner
|
||||||
|
import java.util.zip.GZIPInputStream
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -333,6 +337,14 @@ private fun StatusCard(
|
|||||||
text = stringResource(R.string.home_module_count, getModuleCount()),
|
text = stringResource(R.string.home_module_count, getModuleCount()),
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
|
val kpmVersion = getKpmVersion()
|
||||||
|
if (kpmVersion.isNotEmpty() && !kpmVersion.startsWith("Error")) {
|
||||||
|
Spacer(Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.home_kpm_module, getKpmModuleCount()),
|
||||||
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
)
|
||||||
|
}
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
|
||||||
val suSFS = getSuSFS()
|
val suSFS = getSuSFS()
|
||||||
@@ -555,18 +567,28 @@ private fun InfoCard() {
|
|||||||
InfoCardItem(stringResource(R.string.home_selinux_status), getSELinuxStatus())
|
InfoCardItem(stringResource(R.string.home_selinux_status), getSELinuxStatus())
|
||||||
|
|
||||||
|
|
||||||
if (!isSimpleMode){
|
|
||||||
Spacer(Modifier.height(16.dp))
|
if (!isSimpleMode) {
|
||||||
val kpmVersion = getKpmVersion()
|
val kpmVersion = getKpmVersion()
|
||||||
val displayVersion = if (kpmVersion.isEmpty() || kpmVersion.startsWith("Error")) {
|
var displayVersion: String
|
||||||
stringResource(R.string.not_supported)
|
val isKpmConfigured = checkKpmConfigured()
|
||||||
|
|
||||||
|
if (kpmVersion.isEmpty() || kpmVersion.startsWith("Error")) {
|
||||||
|
val statusText = if (isKpmConfigured) {
|
||||||
|
stringResource(R.string.kernel_patched)
|
||||||
|
} else {
|
||||||
|
stringResource(R.string.kernel_not_enabled)
|
||||||
|
}
|
||||||
|
displayVersion = "${stringResource(R.string.not_supported)} ($statusText)"
|
||||||
} else {
|
} else {
|
||||||
kpmVersion
|
displayVersion = "${stringResource(R.string.supported)} ($kpmVersion)"
|
||||||
}
|
}
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
InfoCardItem(stringResource(R.string.home_kpm_version), displayVersion)
|
InfoCardItem(stringResource(R.string.home_kpm_version), displayVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!isSimpleMode) {
|
if (!isSimpleMode) {
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
@@ -645,4 +667,24 @@ private fun getDeviceModel(context: Context): String {
|
|||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Build.DEVICE
|
Build.DEVICE
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkKpmConfigured(): Boolean {
|
||||||
|
try {
|
||||||
|
val process = Runtime.getRuntime().exec("su -c cat /proc/config.gz")
|
||||||
|
val inputStream = process.inputStream
|
||||||
|
val gzipInputStream = GZIPInputStream(inputStream)
|
||||||
|
val reader = BufferedReader(InputStreamReader(gzipInputStream))
|
||||||
|
|
||||||
|
var line: String?
|
||||||
|
while (reader.readLine().also { line = it } != null) {
|
||||||
|
if (line?.contains("CONFIG_KPM=y") == true) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.close()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
@@ -4,8 +4,6 @@ import android.content.Intent
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.animation.core.Spring
|
|
||||||
import androidx.compose.animation.core.SpringSpec
|
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
@@ -92,6 +90,15 @@ fun KpmScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tempFile.name.endsWith(".kpm")) {
|
||||||
|
snackBarHost.showSnackbar(
|
||||||
|
message = "文件类型不正确,请选择 .kpm 文件",
|
||||||
|
duration = SnackbarDuration.Short
|
||||||
|
)
|
||||||
|
tempFile.delete()
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
|
||||||
val confirmResult = confirmDialog.awaitConfirm(
|
val confirmResult = confirmDialog.awaitConfirm(
|
||||||
title = kpmInstall,
|
title = kpmInstall,
|
||||||
content = kpmInstallConfirm,
|
content = kpmInstallConfirm,
|
||||||
@@ -102,10 +109,15 @@ fun KpmScreen(
|
|||||||
if (confirmResult == ConfirmResult.Confirmed) {
|
if (confirmResult == ConfirmResult.Confirmed) {
|
||||||
val success = loadingDialog.withLoading {
|
val success = loadingDialog.withLoading {
|
||||||
try {
|
try {
|
||||||
loadKpmModule(tempFile.absolutePath)
|
val loadResult = loadKpmModule(tempFile.absolutePath)
|
||||||
true
|
if (true && loadResult.startsWith("Error")) {
|
||||||
|
Log.e("KsuCli", "Failed to load KPM module: $loadResult")
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("KsuCli", "Failed to load KPM module: ${e.message}")
|
Log.e("KsuCli", "Failed to load KPM module: ${e.message}", e)
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,13 +246,19 @@ fun KpmScreen(
|
|||||||
if (confirmResult == ConfirmResult.Confirmed) {
|
if (confirmResult == ConfirmResult.Confirmed) {
|
||||||
val success = loadingDialog.withLoading {
|
val success = loadingDialog.withLoading {
|
||||||
try {
|
try {
|
||||||
unloadKpmModule(module.id)
|
val unloadResult = unloadKpmModule(module.id)
|
||||||
true
|
if (true && unloadResult.startsWith("Error")) {
|
||||||
|
Log.e("KsuCli", "Failed to unload KPM module: $unloadResult")
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("KsuCli", "Failed to unload KPM module: ${e.message}")
|
Log.e("KsuCli", "Failed to unload KPM module: ${e.message}", e)
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
viewModel.fetchModuleList()
|
viewModel.fetchModuleList()
|
||||||
snackBarHost.showSnackbar(
|
snackBarHost.showSnackbar(
|
||||||
|
|||||||
@@ -486,18 +486,16 @@ private fun getKpmmgrPath(): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun loadKpmModule(path: String, args: String? = null): Boolean {
|
fun loadKpmModule(path: String, args: String? = null): String {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
val cmd = "${getKpmmgrPath()} load $path ${args ?: ""}"
|
val cmd = "${getKpmmgrPath()} load $path ${args ?: ""}"
|
||||||
val result = ShellUtils.fastCmd(shell, cmd)
|
return ShellUtils.fastCmd(shell, cmd)
|
||||||
return result.contains("Success", ignoreCase = true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unloadKpmModule(name: String): Boolean {
|
fun unloadKpmModule(name: String): String {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
val cmd = "${getKpmmgrPath()} unload $name"
|
val cmd = "${getKpmmgrPath()} unload $name"
|
||||||
val result = ShellUtils.fastCmd(shell, cmd)
|
return ShellUtils.fastCmd(shell, cmd)
|
||||||
return result.trim().isEmpty() || result.trim() == "0"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getKpmModuleCount(): Int {
|
fun getKpmModuleCount(): Int {
|
||||||
|
|||||||
@@ -239,6 +239,11 @@
|
|||||||
<string name="kpm_control_success">成功</string>
|
<string name="kpm_control_success">成功</string>
|
||||||
<string name="kpm_control_failed">错误</string>
|
<string name="kpm_control_failed">错误</string>
|
||||||
<string name="not_supported">不支持</string>
|
<string name="not_supported">不支持</string>
|
||||||
|
<string name="supported">支持</string>
|
||||||
|
<string name="home_kpm_module">KPM 模块数:%d </string>
|
||||||
|
<string name="kpm_invalid_file">KPM 文件无效</string>
|
||||||
|
<string name="kernel_patched">内核未进行补丁</string>
|
||||||
|
<string name="kernel_not_enabled">内核未配置</string>
|
||||||
<string name="kernel_module_notice">以下内核模块功能由KernelPatch开发,经过修改后加入SukiSU Ultra的内核模块功能</string>
|
<string name="kernel_module_notice">以下内核模块功能由KernelPatch开发,经过修改后加入SukiSU Ultra的内核模块功能</string>
|
||||||
<string name="home_ContributionCard_kernelsu">SukiSU Ultra展望</string>
|
<string name="home_ContributionCard_kernelsu">SukiSU Ultra展望</string>
|
||||||
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra未来将会成为一个相对独立的KSU分支,但是依然感谢官方KernelSU和MKSU等做出的贡献</string>
|
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra未来将会成为一个相对独立的KSU分支,但是依然感谢官方KernelSU和MKSU等做出的贡献</string>
|
||||||
|
|||||||
@@ -245,4 +245,9 @@
|
|||||||
<string name="kpm_control_failed">failed</string>
|
<string name="kpm_control_failed">failed</string>
|
||||||
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but thanks to the official KernelSU and MKSU etc. for their contributions!</string>
|
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but thanks to the official KernelSU and MKSU etc. for their contributions!</string>
|
||||||
<string name="not_supported">unsupported</string>
|
<string name="not_supported">unsupported</string>
|
||||||
|
<string name="supported">supported</string>
|
||||||
|
<string name="home_kpm_module">Number of KPM modules:%d </string>
|
||||||
|
<string name="kpm_invalid_file">Invalid KPM file</string>
|
||||||
|
<string name="kernel_patched">Kernel not patched</string>
|
||||||
|
<string name="kernel_not_enabled">Kernel not configured</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user