From 2fedb051b8a7df530466c2754d228ab34b5d20c0 Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Sun, 29 Jun 2025 17:50:39 +0800 Subject: [PATCH] manager: Add Hide Bootloader Scripts and Cleanup Tool Residue feature and switch --- .../com/sukisu/ultra/ui/screen/SuSFSConfig.kt | 138 +++++++++++++++++- .../com/sukisu/ultra/ui/util/SuSFSManager.kt | 34 ++++- .../ultra/ui/util/SuSFSModuleScripts.kt | 109 ++++++++++++-- .../src/main/res/values-zh-rCN/strings.xml | 6 +- manager/app/src/main/res/values/strings.xml | 6 +- 5 files changed, 271 insertions(+), 22 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 f72196b1..021e301d 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 @@ -129,6 +129,8 @@ fun SuSFSConfigScreen( var showConfirmReset by remember { mutableStateOf(false) } var autoStartEnabled by remember { mutableStateOf(false) } var executeInPostFsData by remember { mutableStateOf(false) } + var enableHideBl by remember { mutableStateOf(true) } + var enableCleanupResidue by remember { mutableStateOf(false) } // 槽位信息相关状态 var slotInfoList by remember { mutableStateOf(emptyList()) } @@ -276,6 +278,8 @@ fun SuSFSConfigScreen( kstatConfigs = SuSFSManager.getKstatConfigs(context) addKstatPaths = SuSFSManager.getAddKstatPaths(context) hideSusMountsForAllProcs = SuSFSManager.getHideSusMountsForAllProcs(context) + enableHideBl = SuSFSManager.getEnableHideBl(context) + enableCleanupResidue = SuSFSManager.getEnableCleanupResidue(context) loadSlotInfo() } @@ -442,6 +446,8 @@ fun SuSFSConfigScreen( kstatConfigs = SuSFSManager.getKstatConfigs(context) addKstatPaths = SuSFSManager.getAddKstatPaths(context) hideSusMountsForAllProcs = SuSFSManager.getHideSusMountsForAllProcs(context) + enableHideBl = SuSFSManager.getEnableHideBl(context) + enableCleanupResidue = SuSFSManager.getEnableCleanupResidue(context) } isLoading = false showRestoreConfirmDialog = false @@ -773,6 +779,8 @@ fun SuSFSConfigScreen( val success = SuSFSManager.setUname(context, finalUnameValue, finalBuildTimeValue) if (success) { SuSFSManager.saveExecuteInPostFsData(context, executeInPostFsData) + SuSFSManager.saveEnableHideBl(context, enableHideBl) + SuSFSManager.saveEnableCleanupResidue(context, enableCleanupResidue) } isLoading = false } @@ -1022,7 +1030,27 @@ fun SuSFSConfigScreen( onShowSlotInfo = { showSlotInfoDialog = true }, context = context, onShowBackupDialog = { showBackupDialog = true }, - onShowRestoreDialog = { showRestoreDialog = true } + onShowRestoreDialog = { showRestoreDialog = true }, + enableHideBl = enableHideBl, + onEnableHideBlChange = { enabled -> + enableHideBl = enabled + SuSFSManager.saveEnableHideBl(context, enabled) + if (SuSFSManager.isAutoStartEnabled(context)) { + coroutineScope.launch { + SuSFSManager.configureAutoStart(context, true) + } + } + }, + enableCleanupResidue = enableCleanupResidue, + onEnableCleanupResidueChange = { enabled -> + enableCleanupResidue = enabled + SuSFSManager.saveEnableCleanupResidue(context, enabled) + if (SuSFSManager.isAutoStartEnabled(context)) { + coroutineScope.launch { + SuSFSManager.configureAutoStart(context, true) + } + } + } ) } SuSFSTab.SUS_PATHS -> { @@ -1183,7 +1211,11 @@ private fun BasicSettingsContent( onShowSlotInfo: () -> Unit, context: android.content.Context, onShowBackupDialog: () -> Unit, - onShowRestoreDialog: () -> Unit + onShowRestoreDialog: () -> Unit, + enableHideBl: Boolean, + onEnableHideBlChange: (Boolean) -> Unit, + enableCleanupResidue: Boolean, + onEnableCleanupResidueChange: (Boolean) -> Unit ) { var scriptLocationExpanded by remember { mutableStateOf(false) } val isAbDevice = isAbDevice() @@ -1394,6 +1426,108 @@ private fun BasicSettingsContent( } } + // 隐藏BL脚本开关 + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surface + ), + shape = RoundedCornerShape(12.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(12.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1f) + ) { + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = Icons.Default.Security, + contentDescription = null, + tint = MaterialTheme.colorScheme.primary, + modifier = Modifier.size(18.dp) + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = stringResource(R.string.hide_bl_script), + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Medium, + color = MaterialTheme.colorScheme.onSurface + ) + } + Spacer(modifier = Modifier.height(6.dp)) + Text( + text = stringResource(R.string.hide_bl_script_description), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + lineHeight = 14.sp + ) + } + Switch( + checked = enableHideBl, + onCheckedChange = onEnableHideBlChange, + enabled = !isLoading + ) + } + } + + // 清理残留脚本开关 + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surface + ), + shape = RoundedCornerShape(12.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(12.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1f) + ) { + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = Icons.Default.CleaningServices, + contentDescription = null, + tint = MaterialTheme.colorScheme.primary, + modifier = Modifier.size(18.dp) + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = stringResource(R.string.cleanup_residue), + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Medium, + color = MaterialTheme.colorScheme.onSurface + ) + } + Spacer(modifier = Modifier.height(6.dp)) + Text( + text = stringResource(R.string.cleanup_residue_description), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + lineHeight = 14.sp + ) + } + Switch( + checked = enableCleanupResidue, + onCheckedChange = onEnableCleanupResidueChange, + enabled = !isLoading + ) + } + } + // 槽位信息按钮 if (isAbDevice) { Card( 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 ef00e2af..865bd9fd 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 @@ -39,6 +39,9 @@ object SuSFSManager { private const val KEY_KSTAT_CONFIGS = "kstat_configs" private const val KEY_ADD_KSTAT_PATHS = "add_kstat_paths" private const val KEY_HIDE_SUS_MOUNTS_FOR_ALL_PROCS = "hide_sus_mounts_for_all_procs" + private const val KEY_ENABLE_CLEANUP_RESIDUE = "enable_cleanup_residue" + private const val KEY_ENABLE_HIDE_BL = "enable_hide_bl" + // 常量 private const val SUSFS_BINARY_BASE_NAME = "ksu_susfs" @@ -129,7 +132,9 @@ object SuSFSManager { val kstatConfigs: Set, val addKstatPaths: Set, val hideSusMountsForAllProcs: Boolean, - val support158: Boolean + val support158: Boolean, + val enableHideBl: Boolean, + val enableCleanupResidue: Boolean ) { /** * 检查是否有需要自启动的配置 @@ -221,7 +226,9 @@ object SuSFSManager { kstatConfigs = getKstatConfigs(context), addKstatPaths = getAddKstatPaths(context), hideSusMountsForAllProcs = getHideSusMountsForAllProcs(context), - support158 = isSusVersion_1_5_8() + support158 = isSusVersion_1_5_8(), + enableHideBl = getEnableHideBl(context), + enableCleanupResidue = getEnableCleanupResidue(context), ) } @@ -269,6 +276,21 @@ object SuSFSManager { fun getHideSusMountsForAllProcs(context: Context): Boolean = getPrefs(context).getBoolean(KEY_HIDE_SUS_MOUNTS_FOR_ALL_PROCS, true) + // 隐藏BL锁脚本 + fun saveEnableHideBl(context: Context, enabled: Boolean) = + getPrefs(context).edit { putBoolean(KEY_ENABLE_HIDE_BL, enabled) } + + fun getEnableHideBl(context: Context): Boolean = + getPrefs(context).getBoolean(KEY_ENABLE_HIDE_BL, true) + + + // 清理残留配置 + fun saveEnableCleanupResidue(context: Context, enabled: Boolean) = + getPrefs(context).edit { putBoolean(KEY_ENABLE_CLEANUP_RESIDUE, enabled) } + + fun getEnableCleanupResidue(context: Context): Boolean = + getPrefs(context).getBoolean(KEY_ENABLE_CLEANUP_RESIDUE, false) + // 路径和配置管理 fun saveSusPaths(context: Context, paths: Set) = getPrefs(context).edit { putStringSet(KEY_SUS_PATHS, paths) } @@ -331,7 +353,9 @@ object SuSFSManager { KEY_EXECUTE_IN_POST_FS_DATA to getExecuteInPostFsData(context), KEY_KSTAT_CONFIGS to getKstatConfigs(context), KEY_ADD_KSTAT_PATHS to getAddKstatPaths(context), - KEY_HIDE_SUS_MOUNTS_FOR_ALL_PROCS to getHideSusMountsForAllProcs(context) + KEY_HIDE_SUS_MOUNTS_FOR_ALL_PROCS to getHideSusMountsForAllProcs(context), + KEY_ENABLE_HIDE_BL to getEnableHideBl(context), + KEY_ENABLE_CLEANUP_RESIDUE to getEnableCleanupResidue(context) ) } @@ -419,7 +443,7 @@ object SuSFSManager { } - // 还原配置到SharedPreferences + // 还原配置到SharedPreferences private fun restoreConfigurations(context: Context, configurations: Map) { val prefs = getPrefs(context) prefs.edit { @@ -570,7 +594,7 @@ object SuSFSManager { } /** - * 模块管理 + * 模块管理 */ private suspend fun updateMagiskModule(context: Context): Boolean { return removeMagiskModule() && createMagiskModule(context) 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 608cd3c0..712c8669 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 @@ -65,7 +65,26 @@ object ScriptGenerator { appendLine(generateBinaryCheck(config.targetPath)) appendLine() + // 添加日志设置 + generateLogSettingSection(config.enableLog) + + // 隐藏BL相关配置 + if (config.enableHideBl) { + generateHideBlSection() + } + + // 清理工具残留 + if (config.enableCleanupResidue) { + generateCleanupResidueSection() + } + if (shouldConfigureInService(config)) { + // 设置uname和构建时间 + generateUnameSection(config) + + // 添加Kstat配置 + generateKstatSection(config.kstatConfigs, config.addKstatPaths) + // 添加SUS路径 (仅在不支持隐藏挂载时) if (!config.support158 && config.susPaths.isNotEmpty()) { appendLine() @@ -73,20 +92,8 @@ object ScriptGenerator { appendLine("sleep 45") generateSusPathsSection(config.susPaths) } - - // 添加Kstat配置 - generateKstatSection(config.kstatConfigs, config.addKstatPaths) - - // 设置uname和构建时间 - generateUnameSection(config) - } - // 添加日志设置 - generateLogSettingSection(config.enableLog) - // 隐藏BL相关配置 - generateHideBlSection() - appendLine("echo \"$(get_current_time): Service脚本执行完成\" >> \"${'$'}LOG_FILE\"") } } @@ -120,6 +127,7 @@ object ScriptGenerator { } } + @SuppressLint("SdCardPath") private fun StringBuilder.generateKstatSection( kstatConfigs: Set, addKstatPaths: Set @@ -128,6 +136,7 @@ object ScriptGenerator { if (addKstatPaths.isNotEmpty()) { appendLine("# 添加Kstat路径") addKstatPaths.forEach { path -> + appendLine("until [ -d \"/sdcard/Android\" ]; do sleep 1; done") appendLine("\"${'$'}SUSFS_BIN\" add_sus_kstat '$path'") appendLine("echo \"$(get_current_time): 添加Kstat路径: $path\" >> \"${'$'}LOG_FILE\"") } @@ -142,9 +151,10 @@ object ScriptGenerator { if (parts.size >= 13) { val path = parts[0] val params = parts.drop(1).joinToString("' '", "'", "'") + appendLine("sleep 5") appendLine("\"${'$'}SUSFS_BIN\" add_sus_kstat_statically '$path' $params") appendLine("echo \"$(get_current_time): 添加Kstat静态配置: $path\" >> \"${'$'}LOG_FILE\"") - + appendLine("sleep 3") appendLine("\"${'$'}SUSFS_BIN\" update_sus_kstat '$path'") appendLine("echo \"$(get_current_time): 更新Kstat配置: $path\" >> \"${'$'}LOG_FILE\"") } @@ -258,6 +268,79 @@ object ScriptGenerator { appendLine() } + // 新增清理残留脚本生成函数 + private fun StringBuilder.generateCleanupResidueSection() { + appendLine("# 清理工具残留文件") + appendLine("echo \"$(get_current_time): 开始清理工具残留\" >> \"${'$'}LOG_FILE\"") + appendLine() + + // 定义需要清理的路径数组 + appendLine(""" + CLEANUP_PATHS=( + "/data/local/stryker/|Stryker残留" + "/data/system/AppRetention|AppRetention残留" + "/data/local/tmp/luckys|Luck Tool残留" + "/data/local/tmp/HyperCeiler|西米露残留" + "/data/local/tmp/simpleHook|simple Hook残留" + "/data/local/tmp/DisabledAllGoogleServices|谷歌省电模块残留" + "/data/local/MIO|解包软件" + "/data/DNA|解包软件" + "/data/local/tmp/cleaner_starter|质感清理残留" + "/data/local/tmp/byyang|" + "/data/local/tmp/mount_mask|" + "/data/local/tmp/mount_mark|" + "/data/local/tmp/scriptTMP|" + "/data/local/luckys|" + "/data/local/tmp/horae_control.log|" + "/data/gpu_freq_table.conf|" + "/storage/emulated/0/Download/advanced/|" + "/storage/emulated/0/Documents/advanced/|爱玩机" + "/storage/emulated/0/Android/naki/|旧版asoulopt" + "/data/swap_config.conf|scene附加模块2" + "/data/local/tmp/resetprop|" + "/dev/cpuset/AppOpt/|AppOpt模块" + "/storage/emulated/0/Android/Clash/|Clash for Magisk模块" + "/storage/emulated/0/Android/Yume-Yunyun/|网易云后台优化模块" + "/data/local/tmp/Surfing_update|Surfing模块缓存" + "/data/encore/custom_default_cpu_gov|encore模块" + "/data/encore/default_cpu_gov|encore模块" + "/data/local/tmp/yshell|" + "/data/local/tmp/encore_logo.png|" + "/storage/emulated/legacy/|" + "/storage/emulated/elgg/|" + "/data/system/junge/|" + ) + """.trimIndent()) + + appendLine() + appendLine(""" + TOTAL=${'$'}{#CLEANUP_PATHS[@]} + CURRENT=0 + + for item in "${'$'}{CLEANUP_PATHS[@]}"; do + ((CURRENT++)) + path="${'$'}{item%%|*}" + desc="${'$'}{item#*|}" + + if [ -n "${'$'}desc" ]; then + echo "$(get_current_time): [${'$'}CURRENT/${'$'}TOTAL] 清理: ${'$'}path (${'$'}desc)" >> "${'$'}LOG_FILE" + else + echo "$(get_current_time): [${'$'}CURRENT/${'$'}TOTAL] 清理: ${'$'}path" >> "${'$'}LOG_FILE" + fi + + if rm -rf "${'$'}path" 2>/dev/null; then + echo "$(get_current_time): ✓ 成功清理: ${'$'}path" >> "${'$'}LOG_FILE" + else + echo "$(get_current_time): ✗ 清理失败或不存在: ${'$'}path" >> "${'$'}LOG_FILE" + fi + done + """.trimIndent()) + + appendLine() + appendLine("echo \"$(get_current_time): 工具残留清理完成\" >> \"${'$'}LOG_FILE\"") + appendLine() + } + /** * 生成post-fs-data.sh脚本内容 */ 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 011b42cb..2f612645 100644 --- a/manager/app/src/main/res/values-zh-rCN/strings.xml +++ b/manager/app/src/main/res/values-zh-rCN/strings.xml @@ -529,7 +529,7 @@ 还原 从备份文件还原SuSFS配置。这将覆盖所有当前设置。 选择备份文件 - 配置还原成功,备份创建于 %s,来自设备:%s + 配置还原成功,备份创建于 %s,来自设备:%s 还原失败:%s 确认还原 这将覆盖所有当前的SuSFS配置。您确定要继续吗? @@ -537,4 +537,8 @@ 备份日期:%s 设备:%s 版本:%s + 隐藏BL脚本 + 启用隐藏Bootloader解锁状态脚本 + 清理工具残留 + 清理各种模块以及工具的残留文件和目录(可能会误删导致丢失以及无法启动,谨慎使用) diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml index 659a8077..ba8d338a 100644 --- a/manager/app/src/main/res/values/strings.xml +++ b/manager/app/src/main/res/values/strings.xml @@ -531,7 +531,7 @@ Restore Restore SuSFS configurations from a backup file. This will overwrite all current settings. Select Backup File - Configuration restored successfully from backup created on %s from device: %s + Configuration restored successfully from backup created on %s from device: %s Restore failed: %s Confirm Restore This will overwrite all current SuSFS configurations. Are you sure you want to continue? @@ -539,4 +539,8 @@ Backup Date: %s Device: %s Version: %s + Hide BL Script + Enable Hide Bootloader Unlock Status Scripts + Cleanup Residue + Clean up the residual files and directories of various modules and tools (may be deleted by mistake, resulting in loss and failure to start, use with caution)