manager: Add pseudo kernel and build time execution location settings

This commit is contained in:
ShirkNeko
2025-06-17 23:30:29 +08:00
parent 6b1f73aa3d
commit af97488d58
5 changed files with 126 additions and 12 deletions

View File

@@ -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<String>()) }
@@ -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
)
}
// 开机自启动开关

View File

@@ -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/

View File

@@ -19,7 +19,8 @@ object ScriptGenerator {
susPaths: Set<String>,
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()
// 设置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()
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()
}

View File

@@ -522,4 +522,9 @@
<string name="show_module_update_json_summary">在模块详情中显示更新配置URL</string>
<string name="show_more_module_info">显示更多模块信息</string>
<string name="show_more_module_info_summary">显示额外的模块信息如更新配置URL等</string>
<string name="susfs_execution_location_label">执行位置</string>
<string name="susfs_execution_location_service">Service</string>
<string name="susfs_execution_location_post_fs_data">Post-FS-Data</string>
<string name="susfs_execution_location_service_description">在系统服务启动后执行</string>
<string name="susfs_execution_location_post_fs_data_description">在文件系统挂载后但系统完全启动前执行,可能会导致循环重启</string>
</resources>

View File

@@ -524,4 +524,9 @@
<string name="show_module_update_json_summary">Display update JSON URL in module details</string>
<string name="show_more_module_info">Show More Module Info</string>
<string name="show_more_module_info_summary">Display additional module information like update JSON URLs</string>
<string name="susfs_execution_location_label">Execution Location</string>
<string name="susfs_execution_location_service">Service</string>
<string name="susfs_execution_location_post_fs_data">Post-FS-Data</string>
<string name="susfs_execution_location_service_description">Execute after system services start</string>
<string name="susfs_execution_location_post_fs_data_description">Execute after file system is mounted but before system is fully bootedMay cause a boot loop</string>
</resources>