manager: Optimize susfs management,
- solve some problems caused by new versions not taking effect
This commit is contained in:
@@ -77,7 +77,7 @@ fun AddPathDialog(
|
||||
enabled = newPath.isNotBlank() && !isLoading,
|
||||
shape = RoundedCornerShape(8.dp)
|
||||
) {
|
||||
Text(stringResource(R.string.susfs_add))
|
||||
Text(stringResource(R.string.add))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
@@ -186,7 +186,7 @@ fun AddTryUmountDialog(
|
||||
enabled = newUmountPath.isNotBlank() && !isLoading,
|
||||
shape = RoundedCornerShape(8.dp)
|
||||
) {
|
||||
Text(stringResource(R.string.susfs_add))
|
||||
Text(stringResource(R.string.add))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
@@ -431,7 +431,7 @@ fun AddKstatStaticallyDialog(
|
||||
enabled = newKstatPath.isNotBlank() && !isLoading,
|
||||
shape = RoundedCornerShape(8.dp)
|
||||
) {
|
||||
Text("添加")
|
||||
Text(stringResource(R.string.add))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
|
||||
@@ -97,7 +97,7 @@ fun SusPathsContent(
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(text = stringResource(R.string.susfs_add))
|
||||
Text(text = stringResource(R.string.add))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ fun SusMountsContent(
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(text = stringResource(R.string.susfs_add))
|
||||
Text(text = stringResource(R.string.add))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,7 +245,7 @@ fun TryUmountContent(
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(text = stringResource(R.string.susfs_add))
|
||||
Text(text = stringResource(R.string.add))
|
||||
}
|
||||
|
||||
if (tryUmounts.isNotEmpty()) {
|
||||
@@ -403,7 +403,7 @@ fun KstatConfigContent(
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(text = stringResource(R.string.susfs_add))
|
||||
Text(text = stringResource(R.string.add))
|
||||
}
|
||||
|
||||
Button(
|
||||
@@ -419,7 +419,7 @@ fun KstatConfigContent(
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(text = stringResource(R.string.susfs_add))
|
||||
Text(text = stringResource(R.string.add))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,13 +36,14 @@ 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 SUSFS_BINARY_BASE_NAME = "ksu_susfs"
|
||||
private const val DEFAULT_UNAME = "default"
|
||||
private const val DEFAULT_BUILD_TIME = "default"
|
||||
private const val MODULE_ID = "susfs_manager"
|
||||
private const val MODULE_PATH = "/data/adb/modules/$MODULE_ID"
|
||||
|
||||
private const val MIN_VERSION_FOR_HIDE_MOUNT = "1.5.8"
|
||||
|
||||
data class SlotInfo(val slotName: String, val uname: String, val buildTime: String)
|
||||
data class CommandResult(val isSuccess: Boolean, val output: String, val errorOutput: String = "")
|
||||
@@ -53,13 +54,46 @@ object SuSFSManager {
|
||||
val canConfigure: Boolean = false
|
||||
)
|
||||
|
||||
// 命令执行
|
||||
/**
|
||||
* 模块配置数据类
|
||||
*/
|
||||
data class ModuleConfig(
|
||||
val targetPath: String,
|
||||
val unameValue: String,
|
||||
val buildTimeValue: String,
|
||||
val executeInPostFsData: Boolean,
|
||||
val susPaths: Set<String>,
|
||||
val susMounts: Set<String>,
|
||||
val tryUmounts: Set<String>,
|
||||
val androidDataPath: String,
|
||||
val sdcardPath: String,
|
||||
val enableLog: Boolean,
|
||||
val kstatConfigs: Set<String>,
|
||||
val addKstatPaths: Set<String>,
|
||||
val hideSusMountsForAllProcs: Boolean,
|
||||
val support158: Boolean
|
||||
) {
|
||||
/**
|
||||
* 检查是否有需要自启动的配置
|
||||
*/
|
||||
fun hasAutoStartConfig(): Boolean {
|
||||
return unameValue != DEFAULT_UNAME ||
|
||||
buildTimeValue != DEFAULT_BUILD_TIME ||
|
||||
susPaths.isNotEmpty() ||
|
||||
susMounts.isNotEmpty() ||
|
||||
tryUmounts.isNotEmpty() ||
|
||||
kstatConfigs.isNotEmpty() ||
|
||||
addKstatPaths.isNotEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
// 基础工具方法
|
||||
private fun getPrefs(context: Context): SharedPreferences =
|
||||
context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||
|
||||
private fun getSuSFSVersionUse(): String = try {
|
||||
getSuSFSVersion()
|
||||
} catch (_: Exception) { "1.5.8" }
|
||||
} catch (_: Exception) { MIN_VERSION_FOR_HIDE_MOUNT }
|
||||
|
||||
private fun getSuSFSBinaryName(): String = "${SUSFS_BINARY_BASE_NAME}_${getSuSFSVersionUse().removePrefix("v")}"
|
||||
|
||||
@@ -78,7 +112,9 @@ object SuSFSManager {
|
||||
return CommandResult(result.isSuccess, result.out.joinToString("\n"), result.err.joinToString("\n"))
|
||||
}
|
||||
|
||||
// 版本比较
|
||||
/**
|
||||
* 版本比较方法
|
||||
*/
|
||||
private fun compareVersions(version1: String, version2: String): Int {
|
||||
val v1Parts = version1.removePrefix("v").split(".").map { it.toIntOrNull() ?: 0 }
|
||||
val v2Parts = version2.removePrefix("v").split(".").map { it.toIntOrNull() ?: 0 }
|
||||
@@ -97,16 +133,39 @@ object SuSFSManager {
|
||||
return 0
|
||||
}
|
||||
|
||||
// 检查当前SuSFS版本是否支持SUS挂载隐藏控制功能
|
||||
/**
|
||||
* 版本检查方法
|
||||
*/
|
||||
fun isSusVersion_1_5_8(): Boolean {
|
||||
return try {
|
||||
val currentVersion = getSuSFSVersion()
|
||||
compareVersions(currentVersion, "1.5.8") >= 0
|
||||
compareVersions(currentVersion, MIN_VERSION_FOR_HIDE_MOUNT) >= 0
|
||||
} catch (_: Exception) {
|
||||
true
|
||||
true // 默认支持新功能
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前模块配置
|
||||
*/
|
||||
private fun getCurrentModuleConfig(context: Context): ModuleConfig {
|
||||
return ModuleConfig(
|
||||
targetPath = getSuSFSTargetPath(),
|
||||
unameValue = getUnameValue(context),
|
||||
buildTimeValue = getBuildTimeValue(context),
|
||||
executeInPostFsData = getExecuteInPostFsData(context),
|
||||
susPaths = getSusPaths(context),
|
||||
susMounts = getSusMounts(context),
|
||||
tryUmounts = getTryUmounts(context),
|
||||
androidDataPath = getAndroidDataPath(context),
|
||||
sdcardPath = getSdcardPath(context),
|
||||
enableLog = getEnableLogState(context),
|
||||
kstatConfigs = getKstatConfigs(context),
|
||||
addKstatPaths = getAddKstatPaths(context),
|
||||
hideSusMountsForAllProcs = getHideSusMountsForAllProcs(context),
|
||||
support158 = isSusVersion_1_5_8()
|
||||
)
|
||||
}
|
||||
|
||||
// 配置存取方法
|
||||
fun saveUnameValue(context: Context, value: String) =
|
||||
@@ -143,8 +202,7 @@ object SuSFSManager {
|
||||
getPrefs(context).edit { putBoolean(KEY_EXECUTE_IN_POST_FS_DATA, executeInPostFsData) }
|
||||
if (isAutoStartEnabled(context)) {
|
||||
kotlinx.coroutines.CoroutineScope(Dispatchers.Default).launch {
|
||||
removeMagiskModule()
|
||||
createMagiskModule(context)
|
||||
updateMagiskModule(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,8 +261,6 @@ object SuSFSManager {
|
||||
fun getSdcardPath(context: Context): String =
|
||||
getPrefs(context).getString(KEY_SDCARD_PATH, "/sdcard") ?: "/sdcard"
|
||||
|
||||
|
||||
|
||||
// 槽位信息获取
|
||||
suspend fun getCurrentSlotInfo(): List<SlotInfo> = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
@@ -310,17 +366,19 @@ object SuSFSManager {
|
||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
private inline fun <reified T> Map<String, Any?>.getSetSafe(key: String): Set<T> {
|
||||
return when (val value = this[key]) {
|
||||
is Set<*> -> value.filterIsInstance<T>().toSet()
|
||||
else -> emptySet()
|
||||
}
|
||||
/**
|
||||
* 模块管理
|
||||
*/
|
||||
private suspend fun updateMagiskModule(context: Context): Boolean {
|
||||
return removeMagiskModule() && createMagiskModule(context)
|
||||
}
|
||||
|
||||
// 模块管理
|
||||
/**
|
||||
* 模块创建方法
|
||||
*/
|
||||
private suspend fun createMagiskModule(context: Context): Boolean = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val targetPath = getSuSFSTargetPath()
|
||||
val config = getCurrentModuleConfig(context)
|
||||
|
||||
// 创建模块目录
|
||||
if (!runCmdWithResult("mkdir -p $MODULE_PATH").isSuccess) return@withContext false
|
||||
@@ -329,44 +387,9 @@ object SuSFSManager {
|
||||
val moduleProp = ScriptGenerator.generateModuleProp(MODULE_ID)
|
||||
if (!runCmdWithResult("cat > $MODULE_PATH/module.prop << 'EOF'\n$moduleProp\nEOF").isSuccess) return@withContext false
|
||||
|
||||
// 获取配置
|
||||
val config = mapOf(
|
||||
"unameValue" to getUnameValue(context),
|
||||
"buildTimeValue" to getBuildTimeValue(context),
|
||||
"executeInPostFsData" to getExecuteInPostFsData(context),
|
||||
"susPaths" to getSusPaths(context),
|
||||
"susMounts" to getSusMounts(context),
|
||||
"tryUmounts" to getTryUmounts(context),
|
||||
"androidDataPath" to getAndroidDataPath(context),
|
||||
"sdcardPath" to getSdcardPath(context),
|
||||
"enableLog" to getEnableLogState(context),
|
||||
"kstatConfigs" to getKstatConfigs(context),
|
||||
"addKstatPaths" to getAddKstatPaths(context),
|
||||
"hideSusMountsForAllProcs" to getHideSusMountsForAllProcs(context)
|
||||
)
|
||||
// 生成并创建所有脚本文件
|
||||
val scripts = ScriptGenerator.generateAllScripts(config)
|
||||
|
||||
// 生成脚本
|
||||
val scripts = mapOf(
|
||||
"service.sh" to ScriptGenerator.generateServiceScript(
|
||||
targetPath, config["unameValue"] as String, config["buildTimeValue"] as String,
|
||||
config.getSetSafe<String>("susPaths"), config["enableLog"] as Boolean,
|
||||
config["executeInPostFsData"] as Boolean, config.getSetSafe<String>("kstatConfigs"),
|
||||
config.getSetSafe<String>("addKstatPaths")
|
||||
),
|
||||
"post-fs-data.sh" to ScriptGenerator.generatePostFsDataScript(
|
||||
targetPath, config["unameValue"] as String, config["buildTimeValue"] as String,
|
||||
config["executeInPostFsData"] as Boolean, config["androidDataPath"] as String,
|
||||
config["sdcardPath"] as String
|
||||
),
|
||||
"post-mount.sh" to ScriptGenerator.generatePostMountScript(
|
||||
targetPath, config.getSetSafe<String>("susMounts"), config.getSetSafe<String>("tryUmounts")
|
||||
),
|
||||
"boot-completed.sh" to ScriptGenerator.generateBootCompletedScript(
|
||||
targetPath, config["hideSusMountsForAllProcs"] as Boolean
|
||||
)
|
||||
)
|
||||
|
||||
// 创建脚本文件
|
||||
scripts.all { (filename, content) ->
|
||||
runCmdWithResult("cat > $MODULE_PATH/$filename << 'EOF'\n$content\nEOF").isSuccess &&
|
||||
runCmdWithResult("chmod 755 $MODULE_PATH/$filename").isSuccess
|
||||
@@ -386,7 +409,6 @@ object SuSFSManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 功能状态获取
|
||||
suspend fun getEnabledFeatures(context: Context): List<EnabledFeature> = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
@@ -430,7 +452,6 @@ object SuSFSManager {
|
||||
}.sortedBy { it.name }
|
||||
}
|
||||
|
||||
|
||||
private fun parseEnabledFeaturesFromStatus(context: Context, status: Natives.SusfsFeatureStatus): List<EnabledFeature> {
|
||||
val featureList = listOf(
|
||||
Triple("status_sus_path", context.getString(R.string.sus_path_feature_label), status.statusSusPath),
|
||||
@@ -461,7 +482,7 @@ object SuSFSManager {
|
||||
val success = executeSusfsCommand(context, "enable_log ${if (enabled) 1 else 0}")
|
||||
if (success) {
|
||||
saveEnableLogState(context, enabled)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
showToast(context, if (enabled) context.getString(R.string.susfs_log_enabled) else context.getString(R.string.susfs_log_disabled))
|
||||
}
|
||||
return success
|
||||
@@ -476,7 +497,7 @@ object SuSFSManager {
|
||||
val success = executeSusfsCommand(context, "hide_sus_mnts_for_all_procs ${if (hideForAll) 1 else 0}")
|
||||
if (success) {
|
||||
saveHideSusMountsForAllProcs(context, hideForAll)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
showToast(context, if (hideForAll)
|
||||
context.getString(R.string.susfs_hide_mounts_all_enabled)
|
||||
else
|
||||
@@ -493,7 +514,7 @@ object SuSFSManager {
|
||||
if (success) {
|
||||
saveUnameValue(context, unameValue)
|
||||
saveBuildTimeValue(context, buildTimeValue)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
showToast(context, context.getString(R.string.susfs_uname_set_success, unameValue, buildTimeValue))
|
||||
}
|
||||
return success
|
||||
@@ -502,12 +523,37 @@ object SuSFSManager {
|
||||
// 添加SUS路径
|
||||
@SuppressLint("StringFormatInvalid")
|
||||
suspend fun addSusPath(context: Context, path: String): Boolean {
|
||||
// 如果是1.5.8版本,先设置路径配置
|
||||
if (isSusVersion_1_5_8()) {
|
||||
// 获取当前配置的路径,如果没有配置则使用默认值
|
||||
val androidDataPath = getAndroidDataPath(context)
|
||||
val sdcardPath = getSdcardPath(context)
|
||||
|
||||
// 先设置Android Data路径
|
||||
val androidDataSuccess = executeSusfsCommand(context, "set_android_data_root_path '$androidDataPath'")
|
||||
if (androidDataSuccess) {
|
||||
showToast(context, context.getString(R.string.susfs_android_data_path_set, androidDataPath))
|
||||
}
|
||||
|
||||
// 再设置SD卡路径
|
||||
val sdcardSuccess = executeSusfsCommand(context, "set_sdcard_root_path '$sdcardPath'")
|
||||
if (sdcardSuccess) {
|
||||
showToast(context, context.getString(R.string.susfs_sdcard_path_set, sdcardPath))
|
||||
}
|
||||
|
||||
// 如果路径设置失败,记录但不阻止继续执行
|
||||
if (!androidDataSuccess || !sdcardSuccess) {
|
||||
showToast(context, context.getString(R.string.susfs_path_setup_warning))
|
||||
}
|
||||
}
|
||||
|
||||
// 执行添加SUS路径命令
|
||||
val result = executeSusfsCommandWithOutput(context, "add_sus_path '$path'")
|
||||
val isActuallySuccessful = result.isSuccess && !result.output.contains("not found, skip adding")
|
||||
|
||||
if (isActuallySuccessful) {
|
||||
saveSusPaths(context, getSusPaths(context) + path)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
showToast(context, context.getString(R.string.susfs_sus_path_added_success, path))
|
||||
} else {
|
||||
val errorMessage = if (result.output.contains("not found, skip adding")) {
|
||||
@@ -522,7 +568,7 @@ object SuSFSManager {
|
||||
|
||||
suspend fun removeSusPath(context: Context, path: String): Boolean {
|
||||
saveSusPaths(context, getSusPaths(context) - path)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
showToast(context, "SUS path removed: $path")
|
||||
return true
|
||||
}
|
||||
@@ -532,14 +578,14 @@ object SuSFSManager {
|
||||
val success = executeSusfsCommand(context, "add_sus_mount '$mount'")
|
||||
if (success) {
|
||||
saveSusMounts(context, getSusMounts(context) + mount)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
}
|
||||
return success
|
||||
}
|
||||
|
||||
suspend fun removeSusMount(context: Context, mount: String): Boolean {
|
||||
saveSusMounts(context, getSusMounts(context) - mount)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
showToast(context, "Removed SUS mount: $mount")
|
||||
return true
|
||||
}
|
||||
@@ -548,7 +594,7 @@ object SuSFSManager {
|
||||
suspend fun addTryUmount(context: Context, path: String, mode: Int): Boolean {
|
||||
val commandSuccess = executeSusfsCommand(context, "add_try_umount '$path' $mode")
|
||||
saveTryUmounts(context, getTryUmounts(context) + "$path|$mode")
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
|
||||
showToast(context, if (commandSuccess) {
|
||||
context.getString(R.string.susfs_try_umount_added_success, path)
|
||||
@@ -560,7 +606,7 @@ object SuSFSManager {
|
||||
|
||||
suspend fun removeTryUmount(context: Context, umountEntry: String): Boolean {
|
||||
saveTryUmounts(context, getTryUmounts(context) - umountEntry)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
val path = umountEntry.split("|").firstOrNull() ?: umountEntry
|
||||
showToast(context, "Removed Try to uninstall: $path")
|
||||
return true
|
||||
@@ -577,7 +623,7 @@ object SuSFSManager {
|
||||
if (success) {
|
||||
val configEntry = "$path|$ino|$dev|$nlink|$size|$atime|$atimeNsec|$mtime|$mtimeNsec|$ctime|$ctimeNsec|$blocks|$blksize"
|
||||
saveKstatConfigs(context, getKstatConfigs(context) + configEntry)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
showToast(context, context.getString(R.string.kstat_static_config_added, path))
|
||||
}
|
||||
return success
|
||||
@@ -585,7 +631,7 @@ object SuSFSManager {
|
||||
|
||||
suspend fun removeKstatConfig(context: Context, config: String): Boolean {
|
||||
saveKstatConfigs(context, getKstatConfigs(context) - config)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
val path = config.split("|").firstOrNull() ?: config
|
||||
showToast(context, context.getString(R.string.kstat_config_removed, path))
|
||||
return true
|
||||
@@ -596,7 +642,7 @@ object SuSFSManager {
|
||||
val success = executeSusfsCommand(context, "add_sus_kstat '$path'")
|
||||
if (success) {
|
||||
saveAddKstatPaths(context, getAddKstatPaths(context) + path)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
showToast(context, context.getString(R.string.kstat_path_added, path))
|
||||
}
|
||||
return success
|
||||
@@ -604,7 +650,7 @@ object SuSFSManager {
|
||||
|
||||
suspend fun removeAddKstat(context: Context, path: String): Boolean {
|
||||
saveAddKstatPaths(context, getAddKstatPaths(context) - path)
|
||||
if (isAutoStartEnabled(context)) createMagiskModule(context)
|
||||
if (isAutoStartEnabled(context)) updateMagiskModule(context)
|
||||
showToast(context, context.getString(R.string.kstat_path_removed, path))
|
||||
return true
|
||||
}
|
||||
@@ -623,16 +669,14 @@ object SuSFSManager {
|
||||
return success
|
||||
}
|
||||
|
||||
// 设置Android数据路径和SD卡路径
|
||||
// 设置Android数据路径
|
||||
suspend fun setAndroidDataPath(context: Context, path: String): Boolean {
|
||||
val success = executeSusfsCommand(context, "set_android_data_root_path '$path'")
|
||||
if (success) {
|
||||
saveAndroidDataPath(context, path)
|
||||
// 如果开机自启动已启用,立即更新模块脚本
|
||||
if (isAutoStartEnabled(context)) {
|
||||
kotlinx.coroutines.CoroutineScope(Dispatchers.Default).launch {
|
||||
removeMagiskModule()
|
||||
createMagiskModule(context)
|
||||
updateMagiskModule(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -644,29 +688,28 @@ object SuSFSManager {
|
||||
val success = executeSusfsCommand(context, "set_sdcard_root_path '$path'")
|
||||
if (success) {
|
||||
saveSdcardPath(context, path)
|
||||
// 如果开机自启动已启用,立即更新模块脚本
|
||||
if (isAutoStartEnabled(context)) {
|
||||
kotlinx.coroutines.CoroutineScope(Dispatchers.Default).launch {
|
||||
removeMagiskModule()
|
||||
createMagiskModule(context)
|
||||
updateMagiskModule(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
return success
|
||||
}
|
||||
|
||||
/**
|
||||
* 自启动配置检查
|
||||
*/
|
||||
fun hasConfigurationForAutoStart(context: Context): Boolean {
|
||||
val enabledFeatures = runBlocking { getEnabledFeatures(context) }
|
||||
return getUnameValue(context) != DEFAULT_UNAME ||
|
||||
getBuildTimeValue(context) != DEFAULT_BUILD_TIME ||
|
||||
getSusPaths(context).isNotEmpty() ||
|
||||
getSusMounts(context).isNotEmpty() ||
|
||||
getTryUmounts(context).isNotEmpty() ||
|
||||
getKstatConfigs(context).isNotEmpty() ||
|
||||
getAddKstatPaths(context).isNotEmpty() ||
|
||||
enabledFeatures.any { it.isEnabled }
|
||||
val config = getCurrentModuleConfig(context)
|
||||
return config.hasAutoStartConfig() || runBlocking {
|
||||
getEnabledFeatures(context).any { it.isEnabled }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自启动配置方法
|
||||
*/
|
||||
suspend fun configureAutoStart(context: Context, enabled: Boolean): Boolean = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
if (enabled) {
|
||||
|
||||
@@ -9,14 +9,22 @@ import android.annotation.SuppressLint
|
||||
object ScriptGenerator {
|
||||
|
||||
// 常量定义
|
||||
@SuppressLint("SdCardPath")
|
||||
private const val DEFAULT_ANDROID_DATA_PATH = "/sdcard/Android/data"
|
||||
@SuppressLint("SdCardPath")
|
||||
private const val DEFAULT_SDCARD_PATH = "/sdcard"
|
||||
private const val DEFAULT_UNAME = "default"
|
||||
private const val DEFAULT_BUILD_TIME = "default"
|
||||
private const val LOG_DIR = "/data/adb/ksu/log"
|
||||
|
||||
/**
|
||||
* 生成所有脚本文件
|
||||
*/
|
||||
fun generateAllScripts(config: SuSFSManager.ModuleConfig): Map<String, String> {
|
||||
return mapOf(
|
||||
"service.sh" to generateServiceScript(config),
|
||||
"post-fs-data.sh" to generatePostFsDataScript(config),
|
||||
"post-mount.sh" to generatePostMountScript(config),
|
||||
"boot-completed.sh" to generateBootCompletedScript(config)
|
||||
)
|
||||
}
|
||||
|
||||
// 日志相关的通用脚本片段
|
||||
private fun generateLogSetup(logFileName: String): String = """
|
||||
# 日志目录
|
||||
@@ -45,17 +53,7 @@ object ScriptGenerator {
|
||||
/**
|
||||
* 生成service.sh脚本内容
|
||||
*/
|
||||
@SuppressLint("SdCardPath")
|
||||
fun generateServiceScript(
|
||||
targetPath: String,
|
||||
unameValue: String,
|
||||
buildTimeValue: String,
|
||||
susPaths: Set<String>,
|
||||
enableLog: Boolean,
|
||||
executeInPostFsData: Boolean = false,
|
||||
kstatConfigs: Set<String> = emptySet(),
|
||||
addKstatPaths: Set<String> = emptySet()
|
||||
): String {
|
||||
private fun generateServiceScript(config: SuSFSManager.ModuleConfig): String {
|
||||
return buildString {
|
||||
appendLine("#!/system/bin/sh")
|
||||
appendLine("# SuSFS Service Script")
|
||||
@@ -63,21 +61,25 @@ object ScriptGenerator {
|
||||
appendLine()
|
||||
appendLine(generateLogSetup("susfs_service.log"))
|
||||
appendLine()
|
||||
appendLine(generateBinaryCheck(targetPath))
|
||||
appendLine(generateBinaryCheck(config.targetPath))
|
||||
appendLine()
|
||||
|
||||
// 设置日志启用状态
|
||||
generateLogSettingSection(enableLog)
|
||||
if (shouldConfigureInService(config)) {
|
||||
// 添加SUS路径 (仅在不支持隐藏挂载时)
|
||||
if (!config.support158 && config.susPaths.isNotEmpty()) {
|
||||
generateSusPathsSection(config.susPaths)
|
||||
}
|
||||
|
||||
// 添加SUS路径
|
||||
generateSusPathsSection(susPaths)
|
||||
// 添加Kstat配置
|
||||
generateKstatSection(config.kstatConfigs, config.addKstatPaths)
|
||||
|
||||
// 添加Kstat配置
|
||||
generateKstatSection(kstatConfigs, addKstatPaths)
|
||||
// 设置uname和构建时间
|
||||
generateUnameSection(config)
|
||||
|
||||
// 设置uname和构建时间
|
||||
generateUnameSection(unameValue, buildTimeValue, executeInPostFsData)
|
||||
}
|
||||
|
||||
// 添加日志设置
|
||||
generateLogSettingSection(config.enableLog)
|
||||
// 隐藏BL相关配置
|
||||
generateHideBlSection()
|
||||
|
||||
@@ -85,6 +87,16 @@ object ScriptGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否需要在service中配置
|
||||
*/
|
||||
private fun shouldConfigureInService(config: SuSFSManager.ModuleConfig): Boolean {
|
||||
return config.susPaths.isNotEmpty() ||
|
||||
config.kstatConfigs.isNotEmpty() ||
|
||||
config.addKstatPaths.isNotEmpty() ||
|
||||
(!config.executeInPostFsData && (config.unameValue != DEFAULT_UNAME || config.buildTimeValue != DEFAULT_BUILD_TIME))
|
||||
}
|
||||
|
||||
private fun StringBuilder.generateLogSettingSection(enableLog: Boolean) {
|
||||
appendLine("# 设置日志启用状态")
|
||||
val logValue = if (enableLog) 1 else 0
|
||||
@@ -137,15 +149,11 @@ object ScriptGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private fun StringBuilder.generateUnameSection(
|
||||
unameValue: String,
|
||||
buildTimeValue: String,
|
||||
executeInPostFsData: Boolean
|
||||
) {
|
||||
if (!executeInPostFsData && (unameValue != DEFAULT_UNAME || buildTimeValue != DEFAULT_BUILD_TIME)) {
|
||||
private fun StringBuilder.generateUnameSection(config: SuSFSManager.ModuleConfig) {
|
||||
if (!config.executeInPostFsData && (config.unameValue != DEFAULT_UNAME || config.buildTimeValue != DEFAULT_BUILD_TIME)) {
|
||||
appendLine("# 设置uname和构建时间")
|
||||
appendLine("\"${'$'}SUSFS_BIN\" set_uname '$unameValue' '$buildTimeValue'")
|
||||
appendLine("echo \"$(get_current_time): 设置uname为: $unameValue, 构建时间为: $buildTimeValue\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine("\"${'$'}SUSFS_BIN\" set_uname '${config.unameValue}' '${config.buildTimeValue}'")
|
||||
appendLine("echo \"$(get_current_time): 设置uname为: ${config.unameValue}, 构建时间为: ${config.buildTimeValue}\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine()
|
||||
}
|
||||
}
|
||||
@@ -246,44 +254,24 @@ object ScriptGenerator {
|
||||
/**
|
||||
* 生成post-fs-data.sh脚本内容
|
||||
*/
|
||||
fun generatePostFsDataScript(
|
||||
targetPath: String,
|
||||
unameValue: String,
|
||||
buildTimeValue: String,
|
||||
executeInPostFsData: Boolean = false,
|
||||
androidDataPath: String = DEFAULT_ANDROID_DATA_PATH,
|
||||
sdcardPath: String = DEFAULT_SDCARD_PATH
|
||||
): String {
|
||||
private fun generatePostFsDataScript(config: SuSFSManager.ModuleConfig): String {
|
||||
return buildString {
|
||||
appendLine("#!/system/bin/sh")
|
||||
appendLine("# SuSFS Post-FS-Data Script")
|
||||
appendLine("# 在文件系统挂载后但在系统完全启动前执行")
|
||||
appendLine("# 优先级最高的配置项")
|
||||
appendLine()
|
||||
appendLine(generateLogSetup("susfs_post_fs_data.log"))
|
||||
appendLine()
|
||||
appendLine(generateBinaryCheck(targetPath))
|
||||
appendLine(generateBinaryCheck(config.targetPath))
|
||||
appendLine()
|
||||
appendLine("echo \"$(get_current_time): Post-FS-Data脚本开始执行\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine()
|
||||
|
||||
// 路径设置
|
||||
appendLine("# 设置路径配置(优先级最高)")
|
||||
appendLine("# 设置Android Data路径")
|
||||
appendLine("\"${'$'}SUSFS_BIN\" set_android_data_root_path '$androidDataPath'")
|
||||
appendLine("echo \"$(get_current_time): Android Data路径设置为: $androidDataPath\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine()
|
||||
|
||||
appendLine("# 设置SD卡路径")
|
||||
appendLine("\"${'$'}SUSFS_BIN\" set_sdcard_root_path '$sdcardPath'")
|
||||
appendLine("echo \"$(get_current_time): SD卡路径设置为: $sdcardPath\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine()
|
||||
|
||||
// 设置uname和构建时间 - 只有在选择在post-fs-data中执行时才执行
|
||||
if (executeInPostFsData && (unameValue != DEFAULT_UNAME || buildTimeValue != DEFAULT_BUILD_TIME)) {
|
||||
if (config.executeInPostFsData && (config.unameValue != DEFAULT_UNAME || config.buildTimeValue != DEFAULT_BUILD_TIME)) {
|
||||
appendLine("# 设置uname和构建时间")
|
||||
appendLine("\"${'$'}SUSFS_BIN\" set_uname '$unameValue' '$buildTimeValue'")
|
||||
appendLine("echo \"$(get_current_time): 设置uname为: $unameValue, 构建时间为: $buildTimeValue\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine("\"${'$'}SUSFS_BIN\" set_uname '${config.unameValue}' '${config.buildTimeValue}'")
|
||||
appendLine("echo \"$(get_current_time): 设置uname为: ${config.unameValue}, 构建时间为: ${config.buildTimeValue}\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine()
|
||||
}
|
||||
|
||||
@@ -294,11 +282,7 @@ object ScriptGenerator {
|
||||
/**
|
||||
* 生成post-mount.sh脚本内容
|
||||
*/
|
||||
fun generatePostMountScript(
|
||||
targetPath: String,
|
||||
susMounts: Set<String>,
|
||||
tryUmounts: Set<String>
|
||||
): String {
|
||||
private fun generatePostMountScript(config: SuSFSManager.ModuleConfig): String {
|
||||
return buildString {
|
||||
appendLine("#!/system/bin/sh")
|
||||
appendLine("# SuSFS Post-Mount Script")
|
||||
@@ -308,13 +292,13 @@ object ScriptGenerator {
|
||||
appendLine()
|
||||
appendLine("echo \"$(get_current_time): Post-Mount脚本开始执行\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine()
|
||||
appendLine(generateBinaryCheck(targetPath))
|
||||
appendLine(generateBinaryCheck(config.targetPath))
|
||||
appendLine()
|
||||
|
||||
// 添加SUS挂载
|
||||
if (susMounts.isNotEmpty()) {
|
||||
if (config.susMounts.isNotEmpty()) {
|
||||
appendLine("# 添加SUS挂载")
|
||||
susMounts.forEach { mount ->
|
||||
config.susMounts.forEach { mount ->
|
||||
appendLine("\"${'$'}SUSFS_BIN\" add_sus_mount '$mount'")
|
||||
appendLine("echo \"$(get_current_time): 添加SUS挂载: $mount\" >> \"${'$'}LOG_FILE\"")
|
||||
}
|
||||
@@ -322,9 +306,9 @@ object ScriptGenerator {
|
||||
}
|
||||
|
||||
// 添加尝试卸载
|
||||
if (tryUmounts.isNotEmpty()) {
|
||||
if (config.tryUmounts.isNotEmpty()) {
|
||||
appendLine("# 添加尝试卸载")
|
||||
tryUmounts.forEach { umount ->
|
||||
config.tryUmounts.forEach { umount ->
|
||||
val parts = umount.split("|")
|
||||
if (parts.size == 2) {
|
||||
val path = parts[0]
|
||||
@@ -343,10 +327,7 @@ object ScriptGenerator {
|
||||
/**
|
||||
* 生成boot-completed.sh脚本内容
|
||||
*/
|
||||
fun generateBootCompletedScript(
|
||||
targetPath: String,
|
||||
hideSusMountsForAllProcs: Boolean = true
|
||||
): String {
|
||||
private fun generateBootCompletedScript(config: SuSFSManager.ModuleConfig): String {
|
||||
return buildString {
|
||||
appendLine("#!/system/bin/sh")
|
||||
appendLine("# SuSFS Boot-Completed Script")
|
||||
@@ -356,36 +337,49 @@ object ScriptGenerator {
|
||||
appendLine()
|
||||
appendLine("echo \"$(get_current_time): Boot-Completed脚本开始执行\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine()
|
||||
appendLine(generateBinaryCheck(targetPath))
|
||||
appendLine(generateBinaryCheck(config.targetPath))
|
||||
appendLine()
|
||||
|
||||
// SUS挂载隐藏控制仅限1.5.8及以上版本
|
||||
appendLine("# 设置SUS挂载隐藏控制(仅限1.5.8及以上版本)")
|
||||
appendLine("SUSFS_VERSION=$(${'$'}SUSFS_BIN show version 2>/dev/null | grep -o 'v[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+' | head -1)")
|
||||
appendLine("if [ -n \"${'$'}SUSFS_VERSION\" ]; then")
|
||||
appendLine(" VERSION_NUM=$(echo \"${'$'}SUSFS_VERSION\" | sed 's/v//' | awk -F. '{printf \"%d%02d%02d\", $1, $2, $3}')")
|
||||
appendLine(" if [ \"${'$'}VERSION_NUM\" -ge 10508 ]; then")
|
||||
val hideValue = if (hideSusMountsForAllProcs) 1 else 0
|
||||
appendLine(" \"${'$'}SUSFS_BIN\" hide_sus_mnts_for_all_procs $hideValue")
|
||||
appendLine(" echo \"$(get_current_time): SUS挂载隐藏控制设置为: ${if (hideSusMountsForAllProcs) "对所有进程隐藏" else "仅对非KSU进程隐藏"}\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine(" else")
|
||||
appendLine(" echo \"$(get_current_time): 当前版本 ${'$'}SUSFS_VERSION 不支持SUS挂载隐藏控制功能,需要1.5.8及以上版本\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine(" fi")
|
||||
appendLine("else")
|
||||
appendLine(" echo \"$(get_current_time): 无法获取SuSFS版本信息,跳过SUS挂载隐藏控制设置\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine("fi")
|
||||
appendLine()
|
||||
// 仅在支持隐藏挂载功能时执行相关配置
|
||||
if (config.support158) {
|
||||
// SUS挂载隐藏控制
|
||||
val hideValue = if (config.hideSusMountsForAllProcs) 1 else 0
|
||||
appendLine("# 设置SUS挂载隐藏控制")
|
||||
appendLine("\"${'$'}SUSFS_BIN\" hide_sus_mnts_for_all_procs $hideValue")
|
||||
appendLine("echo \"$(get_current_time): SUS挂载隐藏控制设置为: ${if (config.hideSusMountsForAllProcs) "对所有进程隐藏" else "仅对非KSU进程隐藏"}\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine()
|
||||
|
||||
// 路径设置和SUS路径设置
|
||||
if (config.susPaths.isNotEmpty()) {
|
||||
generatePathSettingSection(config.androidDataPath, config.sdcardPath)
|
||||
generateSusPathsSection(config.susPaths)
|
||||
}
|
||||
}
|
||||
|
||||
appendLine("echo \"$(get_current_time): Boot-Completed脚本执行完成\" >> \"${'$'}LOG_FILE\"")
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SdCardPath")
|
||||
private fun StringBuilder.generatePathSettingSection(androidDataPath: String, sdcardPath: String) {
|
||||
appendLine("# 路径配置")
|
||||
appendLine("# 设置Android Data路径")
|
||||
appendLine("until [ -d \"/sdcard/Android\" ]; do sleep 1; done")
|
||||
appendLine("\"${'$'}SUSFS_BIN\" set_android_data_root_path '$androidDataPath'")
|
||||
appendLine("echo \"$(get_current_time): Android Data路径设置为: $androidDataPath\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine()
|
||||
appendLine("# 设置SD卡路径")
|
||||
appendLine("\"${'$'}SUSFS_BIN\" set_sdcard_root_path '$sdcardPath'")
|
||||
appendLine("echo \"$(get_current_time): SD卡路径设置为: $sdcardPath\" >> \"${'$'}LOG_FILE\"")
|
||||
appendLine()
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成module.prop文件内容
|
||||
*/
|
||||
fun generateModuleProp(moduleId: String): String {
|
||||
val moduleVersion = "v1.0.0"
|
||||
val moduleVersionCode = "1000"
|
||||
val moduleVersion = "v1.0.1"
|
||||
val moduleVersionCode = "1001"
|
||||
|
||||
return """
|
||||
id=$moduleId
|
||||
|
||||
@@ -392,7 +392,6 @@
|
||||
<string name="susfs_tab_path_settings">パスの設定</string>
|
||||
<string name="susfs_tab_enabled_features">有効な機能のステータス</string>
|
||||
<!-- SuSFS Dialog Actions -->
|
||||
<string name="susfs_add">追加</string>
|
||||
<!-- SuSFS Path Management -->
|
||||
<string name="susfs_add_sus_path">SUS パスを追加</string>
|
||||
<string name="susfs_add_sus_mount">SUS マウントを追加</string>
|
||||
|
||||
@@ -393,7 +393,6 @@
|
||||
<string name="susfs_tab_path_settings">Настройки пути</string>
|
||||
<string name="susfs_tab_enabled_features">Статус включённых функций</string>
|
||||
<!-- SuSFS Dialog Actions -->
|
||||
<string name="susfs_add">Добавить</string>
|
||||
<!-- SuSFS Path Management -->
|
||||
<string name="susfs_add_sus_path">Добавить SUS путь</string>
|
||||
<string name="susfs_add_sus_mount">Добавить SUS монтирование</string>
|
||||
|
||||
@@ -391,7 +391,6 @@
|
||||
<string name="susfs_tab_path_settings">Yol Ayarları</string>
|
||||
<string name="susfs_tab_enabled_features">Etkinleştirilen Özellikler Durumu</string>
|
||||
<!-- SuSFS Dialog Actions -->
|
||||
<string name="susfs_add">Ekle</string>
|
||||
<!-- SuSFS Path Management -->
|
||||
<string name="susfs_add_sus_path">SUS Yolu Ekle</string>
|
||||
<string name="susfs_add_sus_mount">SUS Bağlama Noktası Ekle</string>
|
||||
|
||||
@@ -391,7 +391,6 @@
|
||||
<string name="susfs_tab_path_settings">Cài đặt Đường dẫn</string>
|
||||
<string name="susfs_tab_enabled_features">Trạng thái tính năng</string>
|
||||
<!-- SuSFS Dialog Actions -->
|
||||
<string name="susfs_add">Thêm</string>
|
||||
<!-- SuSFS Path Management -->
|
||||
<string name="susfs_add_sus_path">Thêm Đường dẫn SuS</string>
|
||||
<string name="susfs_add_sus_mount">Thêm SuS Mount</string>
|
||||
|
||||
@@ -391,7 +391,6 @@
|
||||
<string name="susfs_tab_path_settings">路径设置</string>
|
||||
<string name="susfs_tab_enabled_features">启用功能状态</string>
|
||||
<!-- SuSFS Dialog Actions -->
|
||||
<string name="susfs_add">添加</string>
|
||||
<!-- SuSFS Path Management -->
|
||||
<string name="susfs_add_sus_path">添加SUS路径</string>
|
||||
<string name="susfs_add_sus_mount">添加SUS挂载</string>
|
||||
@@ -519,4 +518,7 @@
|
||||
<string name="susfs_run">运行</string>
|
||||
<string name="kernel_simple_kernel">内核版本简洁模式</string>
|
||||
<string name="kernel_simple_kernel_summary">启用或禁用SukiSU内核版本显示的简洁模式</string>
|
||||
<string name="susfs_android_data_path_set">Android Data路径已设置为: %s</string>
|
||||
<string name="susfs_sdcard_path_set">SD卡路径已设置为: %s</string>
|
||||
<string name="susfs_path_setup_warning">路径设置可能未完全成功,但将继续添加SUS路径</string>
|
||||
</resources>
|
||||
|
||||
@@ -390,7 +390,6 @@
|
||||
<string name="susfs_tab_path_settings">路徑設定</string>
|
||||
<string name="susfs_tab_enabled_features">啟用功能狀態</string>
|
||||
<!-- SuSFS Dialog Actions -->
|
||||
<string name="susfs_add">添加</string>
|
||||
<!-- SuSFS Path Management -->
|
||||
<string name="susfs_add_sus_path">添加SUS路徑</string>
|
||||
<string name="susfs_add_sus_mount">添加SUS掛載</string>
|
||||
|
||||
@@ -391,7 +391,6 @@
|
||||
<string name="susfs_tab_path_settings">路徑設定</string>
|
||||
<string name="susfs_tab_enabled_features">啟用功能狀態</string>
|
||||
<!-- SuSFS Dialog Actions -->
|
||||
<string name="susfs_add">新增</string>
|
||||
<!-- SuSFS Path Management -->
|
||||
<string name="susfs_add_sus_path">新增 SUS 路徑</string>
|
||||
<string name="susfs_add_sus_mount">新增 SUS 掛載</string>
|
||||
|
||||
@@ -392,8 +392,6 @@
|
||||
<string name="susfs_tab_try_umount">Try Umount</string>
|
||||
<string name="susfs_tab_path_settings">Path Settings</string>
|
||||
<string name="susfs_tab_enabled_features">Enabled Features Status</string>
|
||||
<!-- SuSFS Dialog Actions -->
|
||||
<string name="susfs_add">Add</string>
|
||||
<!-- SuSFS Path Management -->
|
||||
<string name="susfs_add_sus_path">Add SUS Path</string>
|
||||
<string name="susfs_add_sus_mount">Add SUS Mount</string>
|
||||
@@ -521,4 +519,7 @@
|
||||
<string name="susfs_run">Run</string>
|
||||
<string name="kernel_simple_kernel">Kernel Version Concise Mode</string>
|
||||
<string name="kernel_simple_kernel_summary">Enable or disable the clean mode displayed by the SukiSU kernel version</string>
|
||||
<string name="susfs_android_data_path_set">Android Data path has been set to: %s</string>
|
||||
<string name="susfs_sdcard_path_set">SD card path has been set to: %s</string>
|
||||
<string name="susfs_path_setup_warning">Path setup may not be fully successful, but SUS paths will continue to be added</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user