manager: Add pseudo kernel and build time execution location settings
This commit is contained in:
@@ -120,6 +120,7 @@ fun SuSFSConfigScreen(
|
|||||||
var autoStartEnabled by remember { mutableStateOf(false) }
|
var autoStartEnabled by remember { mutableStateOf(false) }
|
||||||
var lastAppliedValue by remember { mutableStateOf("") }
|
var lastAppliedValue by remember { mutableStateOf("") }
|
||||||
var lastAppliedBuildTime by remember { mutableStateOf("") }
|
var lastAppliedBuildTime by remember { mutableStateOf("") }
|
||||||
|
var executeInPostFsData by remember { mutableStateOf(false) } // 新增:是否在post-fs-data中执行
|
||||||
|
|
||||||
// 路径管理相关状态
|
// 路径管理相关状态
|
||||||
var susPaths by remember { mutableStateOf(emptySet<String>()) }
|
var susPaths by remember { mutableStateOf(emptySet<String>()) }
|
||||||
@@ -173,6 +174,7 @@ fun SuSFSConfigScreen(
|
|||||||
autoStartEnabled = SuSFSManager.isAutoStartEnabled(context)
|
autoStartEnabled = SuSFSManager.isAutoStartEnabled(context)
|
||||||
lastAppliedValue = SuSFSManager.getLastAppliedValue(context)
|
lastAppliedValue = SuSFSManager.getLastAppliedValue(context)
|
||||||
lastAppliedBuildTime = SuSFSManager.getLastAppliedBuildTime(context)
|
lastAppliedBuildTime = SuSFSManager.getLastAppliedBuildTime(context)
|
||||||
|
executeInPostFsData = SuSFSManager.getExecuteInPostFsData(context) // 加载执行位置设置
|
||||||
susPaths = SuSFSManager.getSusPaths(context)
|
susPaths = SuSFSManager.getSusPaths(context)
|
||||||
susMounts = SuSFSManager.getSusMounts(context)
|
susMounts = SuSFSManager.getSusMounts(context)
|
||||||
tryUmounts = SuSFSManager.getTryUmounts(context)
|
tryUmounts = SuSFSManager.getTryUmounts(context)
|
||||||
@@ -706,6 +708,8 @@ fun SuSFSConfigScreen(
|
|||||||
if (success) {
|
if (success) {
|
||||||
lastAppliedValue = finalUnameValue
|
lastAppliedValue = finalUnameValue
|
||||||
lastAppliedBuildTime = finalBuildTimeValue
|
lastAppliedBuildTime = finalBuildTimeValue
|
||||||
|
// 保存执行位置设置
|
||||||
|
SuSFSManager.saveExecuteInPostFsData(context, executeInPostFsData)
|
||||||
}
|
}
|
||||||
isLoading = false
|
isLoading = false
|
||||||
}
|
}
|
||||||
@@ -920,6 +924,8 @@ fun SuSFSConfigScreen(
|
|||||||
onUnameValueChange = { unameValue = it },
|
onUnameValueChange = { unameValue = it },
|
||||||
buildTimeValue = buildTimeValue,
|
buildTimeValue = buildTimeValue,
|
||||||
onBuildTimeValueChange = { buildTimeValue = it },
|
onBuildTimeValueChange = { buildTimeValue = it },
|
||||||
|
executeInPostFsData = executeInPostFsData,
|
||||||
|
onExecuteInPostFsDataChange = { executeInPostFsData = it },
|
||||||
autoStartEnabled = autoStartEnabled,
|
autoStartEnabled = autoStartEnabled,
|
||||||
canEnableAutoStart = canEnableAutoStart,
|
canEnableAutoStart = canEnableAutoStart,
|
||||||
isLoading = isLoading,
|
isLoading = isLoading,
|
||||||
@@ -1024,18 +1030,23 @@ fun SuSFSConfigScreen(
|
|||||||
/**
|
/**
|
||||||
* 基本设置内容组件
|
* 基本设置内容组件
|
||||||
*/
|
*/
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun BasicSettingsContent(
|
private fun BasicSettingsContent(
|
||||||
unameValue: String,
|
unameValue: String,
|
||||||
onUnameValueChange: (String) -> Unit,
|
onUnameValueChange: (String) -> Unit,
|
||||||
buildTimeValue: String,
|
buildTimeValue: String,
|
||||||
onBuildTimeValueChange: (String) -> Unit,
|
onBuildTimeValueChange: (String) -> Unit,
|
||||||
|
executeInPostFsData: Boolean,
|
||||||
|
onExecuteInPostFsDataChange: (Boolean) -> Unit,
|
||||||
autoStartEnabled: Boolean,
|
autoStartEnabled: Boolean,
|
||||||
canEnableAutoStart: Boolean,
|
canEnableAutoStart: Boolean,
|
||||||
isLoading: Boolean,
|
isLoading: Boolean,
|
||||||
onAutoStartToggle: (Boolean) -> Unit,
|
onAutoStartToggle: (Boolean) -> Unit,
|
||||||
context: android.content.Context
|
context: android.content.Context
|
||||||
) {
|
) {
|
||||||
|
var scriptLocationExpanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@@ -1093,6 +1104,65 @@ private fun BasicSettingsContent(
|
|||||||
shape = RoundedCornerShape(8.dp)
|
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(
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
@@ -1107,6 +1177,11 @@ private fun BasicSettingsContent(
|
|||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
|
Text(
|
||||||
|
text = "当前执行位置: ${if (SuSFSManager.getExecuteInPostFsData(context)) "Post-FS-Data" else "Service"}",
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开机自启动开关
|
// 开机自启动开关
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ object SuSFSManager {
|
|||||||
private const val KEY_ANDROID_DATA_PATH = "android_data_path"
|
private const val KEY_ANDROID_DATA_PATH = "android_data_path"
|
||||||
private const val KEY_SDCARD_PATH = "sdcard_path"
|
private const val KEY_SDCARD_PATH = "sdcard_path"
|
||||||
private const val KEY_ENABLE_LOG = "enable_log"
|
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 SUSFS_BINARY_BASE_NAME = "ksu_susfs"
|
||||||
private const val DEFAULT_UNAME = "default"
|
private const val DEFAULT_UNAME = "default"
|
||||||
private const val DEFAULT_BUILD_TIME = "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
|
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 unameValue = getUnameValue(context)
|
||||||
val buildTimeValue = getBuildTimeValue(context)
|
val buildTimeValue = getBuildTimeValue(context)
|
||||||
|
val executeInPostFsData = getExecuteInPostFsData(context)
|
||||||
val susPaths = getSusPaths(context)
|
val susPaths = getSusPaths(context)
|
||||||
val susMounts = getSusMounts(context)
|
val susMounts = getSusMounts(context)
|
||||||
val tryUmounts = getTryUmounts(context)
|
val tryUmounts = getTryUmounts(context)
|
||||||
@@ -370,7 +389,7 @@ object SuSFSManager {
|
|||||||
// 生成并创建service.sh
|
// 生成并创建service.sh
|
||||||
val serviceScript = ScriptGenerator.generateServiceScript(
|
val serviceScript = ScriptGenerator.generateServiceScript(
|
||||||
targetPath, unameValue, buildTimeValue, susPaths,
|
targetPath, unameValue, buildTimeValue, susPaths,
|
||||||
androidDataPath, sdcardPath, enableLog
|
androidDataPath, sdcardPath, enableLog, executeInPostFsData
|
||||||
)
|
)
|
||||||
val createServiceResult = shell.newJob()
|
val createServiceResult = shell.newJob()
|
||||||
.add("cat > $MODULE_PATH/service.sh << 'EOF'\n$serviceScript\nEOF")
|
.add("cat > $MODULE_PATH/service.sh << 'EOF'\n$serviceScript\nEOF")
|
||||||
@@ -381,7 +400,9 @@ object SuSFSManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 生成并创建post-fs-data.sh
|
// 生成并创建post-fs-data.sh
|
||||||
val postFsDataScript = ScriptGenerator.generatePostFsDataScript(targetPath)
|
val postFsDataScript = ScriptGenerator.generatePostFsDataScript(
|
||||||
|
targetPath, unameValue, buildTimeValue, executeInPostFsData
|
||||||
|
)
|
||||||
val createPostFsDataResult = shell.newJob()
|
val createPostFsDataResult = shell.newJob()
|
||||||
.add("cat > $MODULE_PATH/post-fs-data.sh << 'EOF'\n$postFsDataScript\nEOF")
|
.add("cat > $MODULE_PATH/post-fs-data.sh << 'EOF'\n$postFsDataScript\nEOF")
|
||||||
.add("chmod 755 $MODULE_PATH/post-fs-data.sh")
|
.add("chmod 755 $MODULE_PATH/post-fs-data.sh")
|
||||||
@@ -731,6 +752,7 @@ object SuSFSManager {
|
|||||||
/**
|
/**
|
||||||
* 执行SuSFS命令设置uname和构建时间
|
* 执行SuSFS命令设置uname和构建时间
|
||||||
*/
|
*/
|
||||||
|
@SuppressLint("StringFormatMatches")
|
||||||
suspend fun setUname(context: Context, unameValue: String, buildTimeValue: String): Boolean = withContext(Dispatchers.IO) {
|
suspend fun setUname(context: Context, unameValue: String, buildTimeValue: String): Boolean = withContext(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
// 首先复制二进制文件到/data/adb/ksu/bin/
|
// 首先复制二进制文件到/data/adb/ksu/bin/
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ object ScriptGenerator {
|
|||||||
susPaths: Set<String>,
|
susPaths: Set<String>,
|
||||||
androidDataPath: String,
|
androidDataPath: String,
|
||||||
sdcardPath: String,
|
sdcardPath: String,
|
||||||
enableLog: Boolean
|
enableLog: Boolean,
|
||||||
|
executeInPostFsData: Boolean = false
|
||||||
): String {
|
): String {
|
||||||
return buildString {
|
return buildString {
|
||||||
appendLine("#!/system/bin/sh")
|
appendLine("#!/system/bin/sh")
|
||||||
@@ -79,8 +80,8 @@ object ScriptGenerator {
|
|||||||
appendLine()
|
appendLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置uname和构建时间
|
// 设置uname和构建时间 - 只有不在service中执行
|
||||||
if (unameValue != "default" || buildTimeValue != "default") {
|
if (!executeInPostFsData && (unameValue != "default" || buildTimeValue != "default")) {
|
||||||
appendLine("# 设置uname和构建时间")
|
appendLine("# 设置uname和构建时间")
|
||||||
appendLine("\"\$SUSFS_BIN\" set_uname '$unameValue' '$buildTimeValue'")
|
appendLine("\"\$SUSFS_BIN\" set_uname '$unameValue' '$buildTimeValue'")
|
||||||
appendLine("echo \"\$(get_current_time): 设置uname为: $unameValue, 构建时间为: $buildTimeValue\" >> \"\$LOG_FILE\"")
|
appendLine("echo \"\$(get_current_time): 设置uname为: $unameValue, 构建时间为: $buildTimeValue\" >> \"\$LOG_FILE\"")
|
||||||
@@ -177,6 +178,9 @@ object ScriptGenerator {
|
|||||||
*/
|
*/
|
||||||
fun generatePostFsDataScript(
|
fun generatePostFsDataScript(
|
||||||
targetPath: String,
|
targetPath: String,
|
||||||
|
unameValue: String,
|
||||||
|
buildTimeValue: String,
|
||||||
|
executeInPostFsData: Boolean = false
|
||||||
): String {
|
): String {
|
||||||
return buildString {
|
return buildString {
|
||||||
appendLine("#!/system/bin/sh")
|
appendLine("#!/system/bin/sh")
|
||||||
@@ -204,9 +208,15 @@ object ScriptGenerator {
|
|||||||
appendLine()
|
appendLine()
|
||||||
appendLine("echo \"\$(get_current_time): Post-FS-Data脚本开始执行\" >> \"\$LOG_FILE\"")
|
appendLine("echo \"\$(get_current_time): Post-FS-Data脚本开始执行\" >> \"\$LOG_FILE\"")
|
||||||
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()
|
||||||
appendLine()
|
}
|
||||||
appendLine()
|
|
||||||
appendLine("echo \"\$(get_current_time): Post-FS-Data脚本执行完成\" >> \"\$LOG_FILE\"")
|
appendLine("echo \"\$(get_current_time): Post-FS-Data脚本执行完成\" >> \"\$LOG_FILE\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,9 +315,6 @@ object ScriptGenerator {
|
|||||||
appendLine(" exit 1")
|
appendLine(" exit 1")
|
||||||
appendLine("fi")
|
appendLine("fi")
|
||||||
appendLine()
|
appendLine()
|
||||||
appendLine()
|
|
||||||
appendLine()
|
|
||||||
appendLine()
|
|
||||||
appendLine("echo \"\$(get_current_time): Boot-Completed脚本执行完成\" >> \"\$LOG_FILE\"")
|
appendLine("echo \"\$(get_current_time): Boot-Completed脚本执行完成\" >> \"\$LOG_FILE\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -325,7 +332,7 @@ object ScriptGenerator {
|
|||||||
version=$moduleVersion
|
version=$moduleVersion
|
||||||
versionCode=$moduleVersionCode
|
versionCode=$moduleVersionCode
|
||||||
author=ShirkNeko
|
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=
|
updateJson=
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -522,4 +522,9 @@
|
|||||||
<string name="show_module_update_json_summary">在模块详情中显示更新配置URL</string>
|
<string name="show_module_update_json_summary">在模块详情中显示更新配置URL</string>
|
||||||
<string name="show_more_module_info">显示更多模块信息</string>
|
<string name="show_more_module_info">显示更多模块信息</string>
|
||||||
<string name="show_more_module_info_summary">显示额外的模块信息,如更新配置URL等</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>
|
</resources>
|
||||||
|
|||||||
@@ -524,4 +524,9 @@
|
|||||||
<string name="show_module_update_json_summary">Display update JSON URL in module details</string>
|
<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">Show More Module Info</string>
|
||||||
<string name="show_more_module_info_summary">Display additional module information like update JSON URLs</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 booted,May cause a boot loop</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user