From af97488d58ac6aabe241272ef5c0feef8534474d Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Tue, 17 Jun 2025 23:30:29 +0800 Subject: [PATCH] manager: Add pseudo kernel and build time execution location settings --- .../com/sukisu/ultra/ui/screen/SuSFSConfig.kt | 75 +++++++++++++++++++ .../com/sukisu/ultra/ui/util/SuSFSManager.kt | 26 ++++++- .../ultra/ui/util/SuSFSModuleScripts.kt | 27 ++++--- .../src/main/res/values-zh-rCN/strings.xml | 5 ++ manager/app/src/main/res/values/strings.xml | 5 ++ 5 files changed, 126 insertions(+), 12 deletions(-) diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/SuSFSConfig.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/SuSFSConfig.kt index c03c4787..401c4e6c 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/SuSFSConfig.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/SuSFSConfig.kt @@ -120,6 +120,7 @@ fun SuSFSConfigScreen( var autoStartEnabled by remember { mutableStateOf(false) } var lastAppliedValue by remember { mutableStateOf("") } var lastAppliedBuildTime by remember { mutableStateOf("") } + var executeInPostFsData by remember { mutableStateOf(false) } // 新增:是否在post-fs-data中执行 // 路径管理相关状态 var susPaths by remember { mutableStateOf(emptySet()) } @@ -173,6 +174,7 @@ fun SuSFSConfigScreen( autoStartEnabled = SuSFSManager.isAutoStartEnabled(context) lastAppliedValue = SuSFSManager.getLastAppliedValue(context) lastAppliedBuildTime = SuSFSManager.getLastAppliedBuildTime(context) + executeInPostFsData = SuSFSManager.getExecuteInPostFsData(context) // 加载执行位置设置 susPaths = SuSFSManager.getSusPaths(context) susMounts = SuSFSManager.getSusMounts(context) tryUmounts = SuSFSManager.getTryUmounts(context) @@ -706,6 +708,8 @@ fun SuSFSConfigScreen( if (success) { lastAppliedValue = finalUnameValue lastAppliedBuildTime = finalBuildTimeValue + // 保存执行位置设置 + SuSFSManager.saveExecuteInPostFsData(context, executeInPostFsData) } isLoading = false } @@ -920,6 +924,8 @@ fun SuSFSConfigScreen( onUnameValueChange = { unameValue = it }, buildTimeValue = buildTimeValue, onBuildTimeValueChange = { buildTimeValue = it }, + executeInPostFsData = executeInPostFsData, + onExecuteInPostFsDataChange = { executeInPostFsData = it }, autoStartEnabled = autoStartEnabled, canEnableAutoStart = canEnableAutoStart, isLoading = isLoading, @@ -1024,18 +1030,23 @@ fun SuSFSConfigScreen( /** * 基本设置内容组件 */ +@OptIn(ExperimentalMaterial3Api::class) @Composable private fun BasicSettingsContent( unameValue: String, onUnameValueChange: (String) -> Unit, buildTimeValue: String, onBuildTimeValueChange: (String) -> Unit, + executeInPostFsData: Boolean, + onExecuteInPostFsDataChange: (Boolean) -> Unit, autoStartEnabled: Boolean, canEnableAutoStart: Boolean, isLoading: Boolean, onAutoStartToggle: (Boolean) -> Unit, context: android.content.Context ) { + var scriptLocationExpanded by remember { mutableStateOf(false) } + Column( modifier = Modifier .fillMaxSize() @@ -1093,6 +1104,65 @@ private fun BasicSettingsContent( shape = RoundedCornerShape(8.dp) ) + // 执行位置选择 + ExposedDropdownMenuBox( + expanded = scriptLocationExpanded, + onExpandedChange = { scriptLocationExpanded = !scriptLocationExpanded } + ) { + OutlinedTextField( + value = if (executeInPostFsData) + stringResource(R.string.susfs_execution_location_post_fs_data) + else + stringResource(R.string.susfs_execution_location_service), + onValueChange = { }, + readOnly = true, + label = { Text(stringResource(R.string.susfs_execution_location_label)) }, + trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = scriptLocationExpanded) }, + modifier = Modifier + .fillMaxWidth() + .menuAnchor(MenuAnchorType.PrimaryEditable, true), + shape = RoundedCornerShape(8.dp), + enabled = !isLoading + ) + ExposedDropdownMenu( + expanded = scriptLocationExpanded, + onDismissRequest = { scriptLocationExpanded = false } + ) { + DropdownMenuItem( + text = { + Column { + Text(stringResource(R.string.susfs_execution_location_service)) + Text( + stringResource(R.string.susfs_execution_location_service_description), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + }, + onClick = { + onExecuteInPostFsDataChange(false) + scriptLocationExpanded = false + } + ) + DropdownMenuItem( + text = { + Column { + Text(stringResource(R.string.susfs_execution_location_post_fs_data)) + Text( + stringResource(R.string.susfs_execution_location_post_fs_data_description), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + }, + onClick = { + onExecuteInPostFsDataChange(true) + scriptLocationExpanded = false + } + ) + } + } + // 当前值显示 Column( verticalArrangement = Arrangement.spacedBy(4.dp) @@ -1107,6 +1177,11 @@ private fun BasicSettingsContent( style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant ) + Text( + text = "当前执行位置: ${if (SuSFSManager.getExecuteInPostFsData(context)) "Post-FS-Data" else "Service"}", + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) } // 开机自启动开关 diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/util/SuSFSManager.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/util/SuSFSManager.kt index f174b9f4..58684676 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/util/SuSFSManager.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/ui/util/SuSFSManager.kt @@ -33,6 +33,7 @@ object SuSFSManager { private const val KEY_ANDROID_DATA_PATH = "android_data_path" private const val KEY_SDCARD_PATH = "sdcard_path" private const val KEY_ENABLE_LOG = "enable_log" + private const val KEY_EXECUTE_IN_POST_FS_DATA = "execute_in_post_fs_data" private const val SUSFS_BINARY_BASE_NAME = "ksu_susfs" private const val DEFAULT_UNAME = "default" private const val DEFAULT_BUILD_TIME = "default" @@ -119,6 +120,23 @@ object SuSFSManager { return getPrefs(context).getString(KEY_BUILD_TIME_VALUE, DEFAULT_BUILD_TIME) ?: DEFAULT_BUILD_TIME } + /** + * 保存执行位置设置 + */ + fun saveExecuteInPostFsData(context: Context, executeInPostFsData: Boolean) { + getPrefs(context).edit().apply { + putBoolean(KEY_EXECUTE_IN_POST_FS_DATA, executeInPostFsData) + apply() + } + } + + /** + * 获取执行位置设置 + */ + fun getExecuteInPostFsData(context: Context): Boolean { + return getPrefs(context).getBoolean(KEY_EXECUTE_IN_POST_FS_DATA, false) + } + /** * 保存最后应用的值 */ @@ -360,6 +378,7 @@ object SuSFSManager { // 获取配置信息 val unameValue = getUnameValue(context) val buildTimeValue = getBuildTimeValue(context) + val executeInPostFsData = getExecuteInPostFsData(context) val susPaths = getSusPaths(context) val susMounts = getSusMounts(context) val tryUmounts = getTryUmounts(context) @@ -370,7 +389,7 @@ object SuSFSManager { // 生成并创建service.sh val serviceScript = ScriptGenerator.generateServiceScript( targetPath, unameValue, buildTimeValue, susPaths, - androidDataPath, sdcardPath, enableLog + androidDataPath, sdcardPath, enableLog, executeInPostFsData ) val createServiceResult = shell.newJob() .add("cat > $MODULE_PATH/service.sh << 'EOF'\n$serviceScript\nEOF") @@ -381,7 +400,9 @@ object SuSFSManager { } // 生成并创建post-fs-data.sh - val postFsDataScript = ScriptGenerator.generatePostFsDataScript(targetPath) + val postFsDataScript = ScriptGenerator.generatePostFsDataScript( + targetPath, unameValue, buildTimeValue, executeInPostFsData + ) val createPostFsDataResult = shell.newJob() .add("cat > $MODULE_PATH/post-fs-data.sh << 'EOF'\n$postFsDataScript\nEOF") .add("chmod 755 $MODULE_PATH/post-fs-data.sh") @@ -731,6 +752,7 @@ object SuSFSManager { /** * 执行SuSFS命令设置uname和构建时间 */ + @SuppressLint("StringFormatMatches") suspend fun setUname(context: Context, unameValue: String, buildTimeValue: String): Boolean = withContext(Dispatchers.IO) { try { // 首先复制二进制文件到/data/adb/ksu/bin/ diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/util/SuSFSModuleScripts.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/util/SuSFSModuleScripts.kt index e8283fba..45f7a81e 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/util/SuSFSModuleScripts.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/ui/util/SuSFSModuleScripts.kt @@ -19,7 +19,8 @@ object ScriptGenerator { susPaths: Set, androidDataPath: String, sdcardPath: String, - enableLog: Boolean + enableLog: Boolean, + executeInPostFsData: Boolean = false ): String { return buildString { appendLine("#!/system/bin/sh") @@ -79,8 +80,8 @@ object ScriptGenerator { appendLine() } - // 设置uname和构建时间 - if (unameValue != "default" || buildTimeValue != "default") { + // 设置uname和构建时间 - 只有不在service中执行 + if (!executeInPostFsData && (unameValue != "default" || buildTimeValue != "default")) { appendLine("# 设置uname和构建时间") appendLine("\"\$SUSFS_BIN\" set_uname '$unameValue' '$buildTimeValue'") appendLine("echo \"\$(get_current_time): 设置uname为: $unameValue, 构建时间为: $buildTimeValue\" >> \"\$LOG_FILE\"") @@ -177,6 +178,9 @@ object ScriptGenerator { */ fun generatePostFsDataScript( targetPath: String, + unameValue: String, + buildTimeValue: String, + executeInPostFsData: Boolean = false ): String { return buildString { appendLine("#!/system/bin/sh") @@ -204,9 +208,15 @@ object ScriptGenerator { appendLine() appendLine("echo \"\$(get_current_time): Post-FS-Data脚本开始执行\" >> \"\$LOG_FILE\"") appendLine() - appendLine() - appendLine() - appendLine() + + // 设置uname和构建时间 - 只有在选择在post-fs-data中执行时才执行 + if (executeInPostFsData && (unameValue != "default" || buildTimeValue != "default")) { + appendLine("# 设置uname和构建时间") + appendLine("\"\$SUSFS_BIN\" set_uname '$unameValue' '$buildTimeValue'") + appendLine("echo \"\$(get_current_time): 设置uname为: $unameValue, 构建时间为: $buildTimeValue\" >> \"\$LOG_FILE\"") + appendLine() + } + appendLine("echo \"\$(get_current_time): Post-FS-Data脚本执行完成\" >> \"\$LOG_FILE\"") } } @@ -305,9 +315,6 @@ object ScriptGenerator { appendLine(" exit 1") appendLine("fi") appendLine() - appendLine() - appendLine() - appendLine() appendLine("echo \"\$(get_current_time): Boot-Completed脚本执行完成\" >> \"\$LOG_FILE\"") } } @@ -325,7 +332,7 @@ object ScriptGenerator { version=$moduleVersion versionCode=$moduleVersionCode author=ShirkNeko - description=SuSFS Manager Auto Configuration Module + description=SuSFS Manager Auto Configuration Module (自动生成请不要手动卸载或删除该模块! / Automatically generated Please do not manually uninstall or delete the module!) updateJson= """.trimIndent() } 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 1f19654f..65b7d492 100644 --- a/manager/app/src/main/res/values-zh-rCN/strings.xml +++ b/manager/app/src/main/res/values-zh-rCN/strings.xml @@ -522,4 +522,9 @@ 在模块详情中显示更新配置URL 显示更多模块信息 显示额外的模块信息,如更新配置URL等 + 执行位置 + Service + Post-FS-Data + 在系统服务启动后执行 + 在文件系统挂载后但系统完全启动前执行,可能会导致循环重启 diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml index 04282935..b63cb9c3 100644 --- a/manager/app/src/main/res/values/strings.xml +++ b/manager/app/src/main/res/values/strings.xml @@ -524,4 +524,9 @@ Display update JSON URL in module details Show More Module Info Display additional module information like update JSON URLs + Execution Location + Service + Post-FS-Data + Execute after system services start + Execute after file system is mounted but before system is fully booted,May cause a boot loop \ No newline at end of file