diff --git a/manager/app/src/main/cpp/jni.cc b/manager/app/src/main/cpp/jni.cc
index be5ce544..681c0138 100644
--- a/manager/app/src/main/cpp/jni.cc
+++ b/manager/app/src/main/cpp/jni.cc
@@ -87,6 +87,8 @@ Java_me_weishu_kernelsu_Natives_getAppProfile(JNIEnv *env, jobject, jstring pkg,
env->ReleaseStringUTFChars(pkg, cpkg);
app_profile profile = {};
+ profile.version = KSU_APP_PROFILE_VER;
+
strcpy(profile.key, key);
profile.current_uid = uid;
@@ -197,8 +199,9 @@ Java_me_weishu_kernelsu_Natives_setAppProfile(JNIEnv *env, jobject clazz, jobjec
auto umountModules = env->GetBooleanField(profile, umountModulesField);
app_profile p = {};
- strcpy(p.key, p_key);
+ p.version = KSU_APP_PROFILE_VER;
+ strcpy(p.key, p_key);
p.allow_su = allowSu;
p.current_uid = currentUid;
diff --git a/manager/app/src/main/cpp/ksu.h b/manager/app/src/main/cpp/ksu.h
index 0926fa55..b7dec766 100644
--- a/manager/app/src/main/cpp/ksu.h
+++ b/manager/app/src/main/cpp/ksu.h
@@ -9,14 +9,11 @@ bool become_manager(const char *);
int get_version();
-bool allow_su(int uid, bool allow);
-
bool get_allow_list(int *uids, int *size);
-bool get_deny_list(int *uids, int *size);
-
bool is_safe_mode();
+#define KSU_APP_PROFILE_VER 1
#define KSU_MAX_PACKAGE_NAME 256
// NGROUPS_MAX for Linux is 65535 generally, but we only supports 32 groups.
#define KSU_MAX_GROUPS 32
@@ -26,6 +23,8 @@ using p_key_t = char[KSU_MAX_PACKAGE_NAME];
struct app_profile {
+ int32_t version;
+
// this is usually the package of the app, but can be other value for special apps
p_key_t key;
int32_t current_uid;
diff --git a/manager/app/src/main/java/me/weishu/kernelsu/Natives.kt b/manager/app/src/main/java/me/weishu/kernelsu/Natives.kt
index 9e87acd0..c32a1bd5 100644
--- a/manager/app/src/main/java/me/weishu/kernelsu/Natives.kt
+++ b/manager/app/src/main/java/me/weishu/kernelsu/Natives.kt
@@ -11,8 +11,9 @@ import kotlinx.parcelize.Parcelize
*/
object Natives {
// minimal supported kernel version
- // 10915: allowlist breaking change
- const val MINIMAL_SUPPORTED_KERNEL = 10916
+ // 10915: allowlist breaking change, add app profile
+ // 10929: app profile struct add 'version' field
+ const val MINIMAL_SUPPORTED_KERNEL = 10929
init {
System.loadLibrary("kernelsu")
@@ -38,6 +39,27 @@ object Natives {
external fun getAppProfile(key: String?, uid: Int): Profile
external fun setAppProfile(profile: Profile?): Boolean
+ private const val NON_ROOT_DEFAULT_PROFILE_KEY = "$"
+ private const val ROOT_DEFAULT_PROFILE_KEY = "#"
+ private const val NOBODY_UID = 9999
+
+ fun setDefaultUmountModules(umountModules: Boolean): Boolean {
+ Profile(
+ NON_ROOT_DEFAULT_PROFILE_KEY,
+ NOBODY_UID,
+ false,
+ umountModules = umountModules
+ ).let {
+ return setAppProfile(it)
+ }
+ }
+
+ fun isDefaultUmountModules(): Boolean {
+ getAppProfile(NON_ROOT_DEFAULT_PROFILE_KEY, NOBODY_UID).let {
+ return it.umountModules
+ }
+ }
+
fun requireNewKernel(): Boolean {
return version < MINIMAL_SUPPORTED_KERNEL
}
@@ -73,6 +95,7 @@ object Natives {
Global,
Individual,
}
- constructor(): this("")
+
+ constructor() : this("")
}
}
\ No newline at end of file
diff --git a/manager/app/src/main/java/me/weishu/kernelsu/ui/component/SettingsItem.kt b/manager/app/src/main/java/me/weishu/kernelsu/ui/component/SettingsItem.kt
index ab62136e..7143b23e 100644
--- a/manager/app/src/main/java/me/weishu/kernelsu/ui/component/SettingsItem.kt
+++ b/manager/app/src/main/java/me/weishu/kernelsu/ui/component/SettingsItem.kt
@@ -12,6 +12,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
fun SwitchItem(
icon: ImageVector? = null,
title: String,
+ summary: String? = null,
checked: Boolean,
onCheckedChange: (Boolean) -> Unit
) {
@@ -25,6 +26,11 @@ fun SwitchItem(
trailingContent = {
Switch(checked = checked, onCheckedChange = onCheckedChange)
},
+ supportingContent = {
+ if (summary != null) {
+ Text(summary)
+ }
+ }
)
}
diff --git a/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Settings.kt b/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Settings.kt
index 88477319..03216b5e 100644
--- a/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Settings.kt
+++ b/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Settings.kt
@@ -6,8 +6,12 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
+import androidx.compose.material.icons.filled.BugReport
+import androidx.compose.material.icons.filled.ContactPage
+import androidx.compose.material.icons.filled.RemoveModerator
import androidx.compose.material3.*
import androidx.compose.runtime.*
+import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
@@ -18,9 +22,11 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.weishu.kernelsu.BuildConfig
+import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.R
import me.weishu.kernelsu.ui.component.AboutDialog
import me.weishu.kernelsu.ui.component.LoadingDialog
+import me.weishu.kernelsu.ui.component.SwitchItem
import me.weishu.kernelsu.ui.util.LocalDialogHost
import me.weishu.kernelsu.ui.util.getBugreportFile
@@ -49,7 +55,23 @@ fun SettingScreen(navigator: DestinationsNavigator) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val dialogHost = LocalDialogHost.current
+
+ var umountChecked by rememberSaveable {
+ mutableStateOf(Natives.isDefaultUmountModules())
+ }
+ SwitchItem(
+ icon = Icons.Filled.RemoveModerator,
+ title = stringResource(id = R.string.settings_umount_modules_default),
+ summary = stringResource(id = R.string.settings_umount_modules_default_summary),
+ checked = umountChecked
+ ) {
+ if (Natives.setDefaultUmountModules(it)) {
+ umountChecked = it
+ }
+ }
+
ListItem(
+ leadingContent = { Icon(Icons.Filled.BugReport, stringResource(id = R.string.send_log)) },
headlineContent = { Text(stringResource(id = R.string.send_log)) },
modifier = Modifier.clickable {
scope.launch {
@@ -83,6 +105,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
val about = stringResource(id = R.string.about)
ListItem(
+ leadingContent = { Icon(Icons.Filled.ContactPage, stringResource(id = R.string.about)) },
headlineContent = { Text(about) },
modifier = Modifier.clickable {
showAboutDialog.value = true
diff --git a/manager/app/src/main/res/values-zh-rCN/strings.xml b/manager/app/src/main/res/values-zh-rCN/strings.xml
index 96d85297..db885b8a 100644
--- a/manager/app/src/main/res/values-zh-rCN/strings.xml
+++ b/manager/app/src/main/res/values-zh-rCN/strings.xml
@@ -61,7 +61,10 @@
支持开发
KernelSU 将保持免费和开源,向开发者捐赠以表示支持。
加入我们的 %2$s 频道
加入我们的 QQ 频道]]>
+ 卸载模块
当前内核版本 %d 过低,管理器无法正常工作,请升级内核版本至 %d 或以上!
+ 默认卸载模块
+ App Profile 中卸载模块的全局默认值,如果启用,将会为没有设置 Profile 的应用移除所有模块针对系统的修改
应用
全局
白名单
diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml
index a2ada6c8..a9965745 100644
--- a/manager/app/src/main/res/values/strings.xml
+++ b/manager/app/src/main/res/values/strings.xml
@@ -79,4 +79,6 @@
Failed to update root profile for %s
Failed to update app profile for %s
The current kernel version %d is too low for the manager to function properly. Please upgrade to version %d or higher!
+ Umount modules by default
+ The global default value for uninstalling modules in App Profiles. If enabled, it will remove all module modifications to the system for applications that do not have a Profile set.