manager: hide root-related features if kernelsu version null (#71)

Related PR:
tiann#2483

Also attempting to address this:
tiann#2483 (comment)

Co-authored-by: rsuntk <rsuntk@yukiprjkt.my.id>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
This commit is contained in:
ShirkNeko
2025-04-20 22:30:23 +08:00
parent 1dd8651a1a
commit 5941fa1ec7
4 changed files with 83 additions and 54 deletions

View File

@@ -90,6 +90,14 @@ object Natives {
fun requireNewKernel(): Boolean { fun requireNewKernel(): Boolean {
return version < MINIMAL_SUPPORTED_KERNEL return version < MINIMAL_SUPPORTED_KERNEL
} }
fun isKsuValid(pkgName: String?): Boolean {
if (becomeManager(pkgName)) {
return true
} else {
return false
}
}
@Immutable @Immutable
@Parcelize @Parcelize

View File

@@ -283,22 +283,27 @@ private fun TopBar(
} }
var showDropdown by remember { mutableStateOf(false) } var showDropdown by remember { mutableStateOf(false) }
IconButton(onClick = { showDropdown = true }) { if (Natives.isKsuValid(ksuApp.packageName)) {
Icon(Icons.Filled.Refresh, stringResource(R.string.reboot)) IconButton(onClick = { showDropdown = true }) {
DropdownMenu(expanded = showDropdown, onDismissRequest = { showDropdown = false } Icon(Icons.Filled.Refresh, stringResource(R.string.reboot))
) { DropdownMenu(
expanded = showDropdown,
onDismissRequest = { showDropdown = false }
) {
RebootDropdownItem(id = R.string.reboot) RebootDropdownItem(id = R.string.reboot)
val pm = LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager? val pm =
@Suppress("DEPRECATION") LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) { @Suppress("DEPRECATION")
RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) {
RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace")
}
RebootDropdownItem(id = R.string.reboot_recovery, reason = "recovery")
RebootDropdownItem(id = R.string.reboot_bootloader, reason = "bootloader")
RebootDropdownItem(id = R.string.reboot_download, reason = "download")
RebootDropdownItem(id = R.string.reboot_edl, reason = "edl")
} }
RebootDropdownItem(id = R.string.reboot_recovery, reason = "recovery")
RebootDropdownItem(id = R.string.reboot_bootloader, reason = "bootloader")
RebootDropdownItem(id = R.string.reboot_download, reason = "download")
RebootDropdownItem(id = R.string.reboot_edl, reason = "edl")
} }
} }
}, },
@@ -307,6 +312,7 @@ private fun TopBar(
) )
} }
@Composable @Composable
private fun StatusCard( private fun StatusCard(
kernelVersion: KernelVersion, kernelVersion: KernelVersion,

View File

@@ -40,6 +40,7 @@ import zako.zako.zako.ui.theme.*
import zako.zako.zako.ui.util.* import zako.zako.zako.ui.util.*
import androidx.core.content.edit import androidx.core.content.edit
import zako.zako.zako.R import zako.zako.zako.R
import zako.zako.zako.*
fun saveCardConfig(context: Context) { fun saveCardConfig(context: Context) {
@@ -175,6 +176,7 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
) )
var showThemeColorDialog by remember { mutableStateOf(false) } var showThemeColorDialog by remember { mutableStateOf(false) }
val ksuIsValid = Natives.isKsuValid(ksuApp.packageName)
// 图片选择器 // 图片选择器
val pickImageLauncher = rememberLauncherForActivityResult( val pickImageLauncher = rememberLauncherForActivityResult(
@@ -208,17 +210,19 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
.padding(top = 12.dp) .padding(top = 12.dp)
) { ) {
// SELinux 开关 // SELinux 开关
SwitchItem( if (ksuIsValid) {
icon = Icons.Filled.Security, SwitchItem(
title = stringResource(R.string.selinux), icon = Icons.Filled.Security,
summary = if (selinuxEnabled) title = stringResource(R.string.selinux),
stringResource(R.string.selinux_enabled) else summary = if (selinuxEnabled)
stringResource(R.string.selinux_disabled), stringResource(R.string.selinux_enabled) else
checked = selinuxEnabled stringResource(R.string.selinux_disabled),
) { enabled -> checked = selinuxEnabled
val command = if (enabled) "setenforce 1" else "setenforce 0" ) { enabled ->
Shell.getShell().newJob().add(command).exec().let { result -> val command = if (enabled) "setenforce 1" else "setenforce 0"
if (result.isSuccess) selinuxEnabled = enabled Shell.getShell().newJob().add(command).exec().let { result ->
if (result.isSuccess) selinuxEnabled = enabled
}
} }
} }

View File

@@ -49,6 +49,7 @@ import kotlinx.coroutines.withContext
import zako.zako.zako.BuildConfig import zako.zako.zako.BuildConfig
import zako.zako.zako.Natives import zako.zako.zako.Natives
import zako.zako.zako.R import zako.zako.zako.R
import zako.zako.zako.*
import zako.zako.zako.ui.component.* import zako.zako.zako.ui.component.*
import zako.zako.zako.ui.theme.* import zako.zako.zako.ui.theme.*
import zako.zako.zako.ui.util.LocalSnackbarHost import zako.zako.zako.ui.util.LocalSnackbarHost
@@ -68,6 +69,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
// region 界面基础设置 // region 界面基础设置
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val snackBarHost = LocalSnackbarHost.current val snackBarHost = LocalSnackbarHost.current
val ksuIsValid = Natives.isKsuValid(ksuApp.packageName)
// endregion // endregion
Scaffold( Scaffold(
@@ -115,6 +117,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
// region 配置项列表 // region 配置项列表
// 配置文件模板入口 // 配置文件模板入口
val profileTemplate = stringResource(id = R.string.settings_profile_template) val profileTemplate = stringResource(id = R.string.settings_profile_template)
if (ksuIsValid) {
ListItem( ListItem(
leadingContent = { Icon(Icons.Filled.Fence, profileTemplate) }, leadingContent = { Icon(Icons.Filled.Fence, profileTemplate) },
headlineContent = { Text(profileTemplate) }, headlineContent = { Text(profileTemplate) },
@@ -123,34 +126,40 @@ fun SettingScreen(navigator: DestinationsNavigator) {
navigator.navigate(AppProfileTemplateScreenDestination) navigator.navigate(AppProfileTemplateScreenDestination)
} }
) )
}
// 卸载模块开关 // 卸载模块开关
var umountChecked by rememberSaveable { var umountChecked by rememberSaveable {
mutableStateOf(Natives.isDefaultUmountModules()) mutableStateOf(Natives.isDefaultUmountModules())
} }
SwitchItem(
icon = Icons.Filled.FolderDelete, if (ksuIsValid) {
title = stringResource(id = R.string.settings_umount_modules_default), SwitchItem(
summary = stringResource(id = R.string.settings_umount_modules_default_summary), icon = Icons.Filled.FolderDelete,
checked = umountChecked title = stringResource(id = R.string.settings_umount_modules_default),
) { summary = stringResource(id = R.string.settings_umount_modules_default_summary),
if (Natives.setDefaultUmountModules(it)) { checked = umountChecked
umountChecked = it ) {
} if (Natives.setDefaultUmountModules(it)) {
umountChecked = it
}
}
} }
// SU 禁用开关(仅在兼容版本显示) // SU 禁用开关(仅在兼容版本显示)
if (Natives.version >= Natives.MINIMAL_SUPPORTED_SU_COMPAT) { if (ksuIsValid) {
var isSuDisabled by rememberSaveable { if (Natives.version >= Natives.MINIMAL_SUPPORTED_SU_COMPAT) {
mutableStateOf(!Natives.isSuEnabled()) var isSuDisabled by rememberSaveable {
} mutableStateOf(!Natives.isSuEnabled())
SwitchItem( }
icon = Icons.Filled.RemoveModerator, SwitchItem(
title = stringResource(id = R.string.settings_disable_su), icon = Icons.Filled.RemoveModerator,
summary = stringResource(id = R.string.settings_disable_su_summary), title = stringResource(id = R.string.settings_disable_su),
checked = isSuDisabled, summary = stringResource(id = R.string.settings_disable_su_summary),
) { checked -> checked = isSuDisabled,
val shouldEnable = !checked ) { checked ->
if (Natives.setSuEnabled(shouldEnable)) { val shouldEnable = !checked
isSuDisabled = !shouldEnable if (Natives.setSuEnabled(shouldEnable)) {
isSuDisabled = !shouldEnable
}
} }
} }
} }
@@ -179,14 +188,16 @@ fun SettingScreen(navigator: DestinationsNavigator) {
prefs.getBoolean("enable_web_debugging", false) prefs.getBoolean("enable_web_debugging", false)
) )
} }
SwitchItem( if (Natives.isKsuValid(ksuApp.packageName)) {
icon = Icons.Filled.DeveloperMode, SwitchItem(
title = stringResource(id = R.string.enable_web_debugging), icon = Icons.Filled.DeveloperMode,
summary = stringResource(id = R.string.enable_web_debugging_summary), title = stringResource(id = R.string.enable_web_debugging),
checked = enableWebDebugging summary = stringResource(id = R.string.enable_web_debugging_summary),
) { checked = enableWebDebugging
prefs.edit { putBoolean("enable_web_debugging", it) } ) {
enableWebDebugging = it prefs.edit { putBoolean("enable_web_debugging", it) }
enableWebDebugging = it
}
} }
// 更多设置 // 更多设置
val newButtonTitle = stringResource(id = R.string.more_settings) val newButtonTitle = stringResource(id = R.string.more_settings)