Step 7-2: Removed redundant pop-ups from the susfs interface and fixed path issues (on Android 16).

This commit is contained in:
ShirkNeko
2025-11-23 13:32:06 +08:00
parent 5c80febdbd
commit 15fe454b6d
5 changed files with 181 additions and 266 deletions

View File

@@ -261,10 +261,11 @@ fun SuSFSConfigScreen(
editingPath = null editingPath = null
}, },
onConfirm = { path -> onConfirm = { path ->
val oldPath = editingPath
coroutineScope.launch { coroutineScope.launch {
isLoading = true isLoading = true
val success = if (editingPath != null) { val success = if (oldPath != null) {
SuSFSManager.editSusPath(context, editingPath!!, path) SuSFSManager.editSusPath(context, oldPath, path)
} else { } else {
SuSFSManager.addSusPath(context, path) SuSFSManager.addSusPath(context, path)
} }
@@ -289,10 +290,11 @@ fun SuSFSConfigScreen(
editingLoopPath = null editingLoopPath = null
}, },
onConfirm = { path -> onConfirm = { path ->
val oldPath = editingLoopPath
coroutineScope.launch { coroutineScope.launch {
isLoading = true isLoading = true
val success = if (editingLoopPath != null) { val success = if (oldPath != null) {
SuSFSManager.editSusLoopPath(context, editingLoopPath!!, path) SuSFSManager.editSusLoopPath(context, oldPath, path)
} else { } else {
SuSFSManager.addSusLoopPath(context, path) SuSFSManager.addSusLoopPath(context, path)
} }
@@ -317,10 +319,11 @@ fun SuSFSConfigScreen(
editingSusMap = null editingSusMap = null
}, },
onConfirm = { path -> onConfirm = { path ->
val oldPath = editingSusMap
coroutineScope.launch { coroutineScope.launch {
isLoading = true isLoading = true
val success = if (editingSusMap != null) { val success = if (oldPath != null) {
SuSFSManager.editSusMap(context, editingSusMap!!, path) SuSFSManager.editSusMap(context, oldPath, path)
} else { } else {
SuSFSManager.addSusMap(context, path) SuSFSManager.addSusMap(context, path)
} }
@@ -370,10 +373,11 @@ fun SuSFSConfigScreen(
editingUmount = null editingUmount = null
}, },
onConfirm = { path, mode -> onConfirm = { path, mode ->
val oldUmount = editingUmount
coroutineScope.launch { coroutineScope.launch {
isLoading = true isLoading = true
val success = if (editingUmount != null) { val success = if (oldUmount != null) {
SuSFSManager.editTryUmount(context, editingUmount!!, path, mode) SuSFSManager.editTryUmount(context, oldUmount, path, mode)
} else { } else {
SuSFSManager.addTryUmount(context, path, mode) SuSFSManager.addTryUmount(context, path, mode)
} }
@@ -397,12 +401,13 @@ fun SuSFSConfigScreen(
editingKstatConfig = null editingKstatConfig = null
}, },
onConfirm = { path, ino, dev, nlink, size, atime, atimeNsec, mtime, mtimeNsec, ctime, ctimeNsec, blocks, blksize -> onConfirm = { path, ino, dev, nlink, size, atime, atimeNsec, mtime, mtimeNsec, ctime, ctimeNsec, blocks, blksize ->
val oldConfig = editingKstatConfig
coroutineScope.launch { coroutineScope.launch {
isLoading = true isLoading = true
val success = if (editingKstatConfig != null) { val success = if (oldConfig != null) {
SuSFSManager.editKstatConfig( SuSFSManager.editKstatConfig(
context, context,
editingKstatConfig!!, oldConfig,
path, path,
ino, ino,
dev, dev,
@@ -442,10 +447,11 @@ fun SuSFSConfigScreen(
editingKstatPath = null editingKstatPath = null
}, },
onConfirm = { path -> onConfirm = { path ->
val oldPath = editingKstatPath
coroutineScope.launch { coroutineScope.launch {
isLoading = true isLoading = true
val success = if (editingKstatPath != null) { val success = if (oldPath != null) {
SuSFSManager.editAddKstat(context, editingKstatPath!!, path) SuSFSManager.editAddKstat(context, oldPath, path)
} else { } else {
SuSFSManager.addKstat(context, path) SuSFSManager.addKstat(context, path)
} }

View File

@@ -63,7 +63,7 @@ fun SusPathsContent(
val (appPathGroups, otherPaths) = remember(susPaths, superUserApps) { val (appPathGroups, otherPaths) = remember(susPaths, superUserApps) {
val appPathRegex = Regex(".*/Android/data/([^/]+)/?.*") val appPathRegex = Regex(".*/Android/data/([^/]+)/?.*")
val uidPathRegex = Regex("/sys/fs/cgroup/uid_([0-9]+)") val uidPathRegex = Regex("/sys/fs/cgroup(?:/[^/]+)*/uid_([0-9]+)")
val appPathMap = mutableMapOf<String, MutableList<String>>() val appPathMap = mutableMapOf<String, MutableList<String>>()
val uidToPackageMap = mutableMapOf<String, String>() val uidToPackageMap = mutableMapOf<String, String>()
val others = mutableListOf<String>() val others = mutableListOf<String>()

View File

@@ -10,6 +10,7 @@ import android.util.Log
import android.widget.Toast import android.widget.Toast
import com.sukisu.ultra.R import com.sukisu.ultra.R
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.io.SuFile
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@@ -58,7 +59,7 @@ object SuSFSManager {
const val MAX_SUSFS_VERSION = "2.0.0" const val MAX_SUSFS_VERSION = "2.0.0"
private const val BACKUP_FILE_EXTENSION = ".susfs_backup" private const val BACKUP_FILE_EXTENSION = ".susfs_backup"
private const val MEDIA_DATA_PATH = "/data/media/0/Android/data" private const val MEDIA_DATA_PATH = "/data/media/0/Android/data"
private const val CGROUP_UID_PATH_PREFIX = "/sys/fs/cgroup/uid_" private const val CGROUP_BASE_PATH = "/sys/fs/cgroup"
private const val SUSFS_BINARY_TARGET_NAME = "ksu_susfs" private const val SUSFS_BINARY_TARGET_NAME = "ksu_susfs"
data class SlotInfo(val slotName: String, val uname: String, val buildTime: String) data class SlotInfo(val slotName: String, val uname: String, val buildTime: String)
@@ -241,13 +242,17 @@ object SuSFSManager {
) )
val shell = Shell.getShell() val shell = Shell.getShell()
val result = shell.newJob().add("$binaryPath $command").exec() val result = shell.newJob().add("$binaryPath $command").exec()
SuSFSModuleManager.CommandResult( val commandResult = SuSFSModuleManager.CommandResult(
isSuccess = result.isSuccess, isSuccess = result.isSuccess,
output = result.out.joinToString("\n"), output = result.out.joinToString("\n"),
errorOutput = result.err.joinToString("\n") errorOutput = result.err.joinToString("\n")
) )
if (!commandResult.isSuccess) {
Log.e("SuSFSManager", "Command failed: $command, error: ${commandResult.errorOutput}")
}
commandResult
} catch (e: Exception) { } catch (e: Exception) {
Log.e("SuSFSManager", "Command execution failed", e) Log.e("SuSFSManager", "Exception executing command: $command", e)
SuSFSModuleManager.CommandResult(false, "", e.message ?: "Unknown error") SuSFSModuleManager.CommandResult(false, "", e.message ?: "Unknown error")
} }
} }
@@ -436,8 +441,7 @@ object SuSFSManager {
.exec() .exec()
result.isSuccess && outputList.isNotEmpty() && outputList[0].trim() == "exists" result.isSuccess && outputList.isNotEmpty() && outputList[0].trim() == "exists"
} catch (e: Exception) { } catch (_: Exception) {
Log.w("SuSFSManager", "Failed to check directory for ${appInfo.packageName}: ${e.message}")
false false
} }
if (exists) appInfo else null if (exists) appInfo else null
@@ -445,8 +449,7 @@ object SuSFSManager {
}.awaitAll().filterNotNull() }.awaitAll().filterNotNull()
filteredApps.sortedBy { it.appName } filteredApps.sortedBy { it.appName }
} catch (e: Exception) { } catch (_: Exception) {
e.printStackTrace()
emptyList() emptyList()
} }
} }
@@ -463,16 +466,52 @@ object SuSFSManager {
val packageManager = context.packageManager val packageManager = context.packageManager
val packageInfo = packageManager.getPackageInfo(packageName, 0) val packageInfo = packageManager.getPackageInfo(packageName, 0)
packageInfo.applicationInfo?.uid packageInfo.applicationInfo?.uid
} catch (e: Exception) { } catch (_: Exception) {
Log.w("SuSFSManager", "Failed to get UID for package $packageName: ${e.message}")
null null
} }
} }
private fun buildUidPath(uid: Int): String = "$CGROUP_UID_PATH_PREFIX$uid" private fun checkPathExists(path: String): Boolean {
return try {
val shell = try {
getRootShell()
} catch (_: Exception) {
null
}
val file = if (shell != null) {
SuFile(path).apply { setShell(shell) }
} else {
File(path)
}
file.exists() && file.isDirectory
} catch (_: Exception) {
false
}
}
private fun buildUidPath(uid: Int): String {
val possiblePaths = listOf(
"$CGROUP_BASE_PATH/uid_$uid",
"$CGROUP_BASE_PATH/apps/uid_$uid",
"$CGROUP_BASE_PATH/system/uid_$uid",
"$CGROUP_BASE_PATH/freezer/uid_$uid",
"$CGROUP_BASE_PATH/memory/uid_$uid",
"$CGROUP_BASE_PATH/cpuset/uid_$uid",
"$CGROUP_BASE_PATH/cpu/uid_$uid"
)
for (path in possiblePaths) {
if (checkPathExists(path)) {
return path
}
}
return possiblePaths[0]
}
// 快捷添加应用路径 // 快捷添加应用路径
@SuppressLint("StringFormatMatches")
suspend fun addAppPaths(context: Context, packageName: String): Boolean { suspend fun addAppPaths(context: Context, packageName: String): Boolean {
val androidDataPath = getAndroidDataPath(context) val androidDataPath = getAndroidDataPath(context)
getSdcardPath(context) getSdcardPath(context)
@@ -480,37 +519,28 @@ object SuSFSManager {
val path1 = "$androidDataPath/$packageName" val path1 = "$androidDataPath/$packageName"
val path2 = "$MEDIA_DATA_PATH/$packageName" val path2 = "$MEDIA_DATA_PATH/$packageName"
val uid = getAppUid(context, packageName) val uid = getAppUid(context, packageName) ?: return false
if (uid == null) {
Log.w("SuSFSManager", "Failed to get UID for package: $packageName")
return false
}
val path3 = buildUidPath(uid) val path3 = buildUidPath(uid)
var successCount = 0 var successCount = 0
val totalCount = 3
// 添加第一个路径Android/data路径 // 添加第一个路径Android/data路径
if (addSusPath(context, path1)) { if (addSusPathInternal(context, path1, showToast = false)) {
successCount++ successCount++
} }
// 添加第二个路径(媒体数据路径) // 添加第二个路径(媒体数据路径)
if (addSusPath(context, path2)) { if (addSusPathInternal(context, path2, showToast = false)) {
successCount++ successCount++
} }
// 添加第三个路径UID路径 // 添加第三个路径UID路径
if (addSusPath(context, path3)) { if (addSusPathInternal(context, path3, showToast = false)) {
successCount++ successCount++
} }
val success = successCount > 0 return successCount > 0
Log.d("SuSFSManager", "Added $successCount/$totalCount paths for $packageName (UID: $uid)")
return success
} }
// 获取所有配置的Map // 获取所有配置的Map
@@ -808,7 +838,6 @@ object SuSFSManager {
if (success) { if (success) {
saveEnableLogState(context, enabled) saveEnableLogState(context, enabled)
if (isAutoStartEnabled(context)) updateMagiskModule(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 return success
} }
@@ -819,11 +848,6 @@ object SuSFSManager {
if (success) { if (success) {
saveEnableAvcLogSpoofing(context, enabled) saveEnableAvcLogSpoofing(context, enabled)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, if (enabled)
context.getString(R.string.avc_log_spoofing_enabled)
else
context.getString(R.string.avc_log_spoofing_disabled)
)
} }
return success return success
} }
@@ -834,11 +858,6 @@ object SuSFSManager {
if (success) { if (success) {
saveHideSusMountsForAllProcs(context, hideForAll) saveHideSusMountsForAllProcs(context, hideForAll)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, if (hideForAll)
context.getString(R.string.susfs_hide_mounts_all_enabled)
else
context.getString(R.string.susfs_hide_mounts_all_disabled)
)
} }
return success return success
} }
@@ -851,34 +870,22 @@ object SuSFSManager {
saveUnameValue(context, unameValue) saveUnameValue(context, unameValue)
saveBuildTimeValue(context, buildTimeValue) saveBuildTimeValue(context, buildTimeValue)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, context.getString(R.string.susfs_uname_set_success, unameValue, buildTimeValue))
} }
return success return success
} }
// 添加SUS路径 // 添加SUS路径
@SuppressLint("StringFormatInvalid") @SuppressLint("StringFormatInvalid")
suspend fun addSusPath(context: Context, path: String): Boolean { private suspend fun addSusPathInternal(context: Context, path: String, showToast: Boolean = true): Boolean {
// 先设置路径配置 // 先设置路径配置
val androidDataPath = getAndroidDataPath(context) val androidDataPath = getAndroidDataPath(context)
val sdcardPath = getSdcardPath(context) val sdcardPath = getSdcardPath(context)
// 先设置Android Data路径 // 先设置Android Data路径
val androidDataSuccess = executeSusfsCommand(context, "set_android_data_root_path '$androidDataPath'") executeSusfsCommand(context, "set_android_data_root_path '$androidDataPath'")
if (androidDataSuccess) {
showToast(context, context.getString(R.string.susfs_android_data_path_set, androidDataPath))
}
// 再设置SD卡路径 // 再设置SD卡路径
val sdcardSuccess = executeSusfsCommand(context, "set_sdcard_root_path '$sdcardPath'") 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路径命令 // 执行添加SUS路径命令
val result = executeSusfsCommandWithOutput(context, "add_sus_path '$path'") val result = executeSusfsCommandWithOutput(context, "add_sus_path '$path'")
@@ -887,22 +894,21 @@ object SuSFSManager {
if (isActuallySuccessful) { if (isActuallySuccessful) {
saveSusPaths(context, getSusPaths(context) + path) saveSusPaths(context, getSusPaths(context) + path)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, context.getString(R.string.susfs_sus_path_added_success, path)) } else if (showToast) {
} else { val errorMsg = result.errorOutput.ifEmpty { context.getString(R.string.susfs_command_failed) }
val errorMessage = if (result.output.contains("not found, skip adding")) { showToast(context, errorMsg)
context.getString(R.string.susfs_path_not_found_error, path)
} else {
"${context.getString(R.string.susfs_command_failed)}\n${result.output}\n${result.errorOutput}"
}
showToast(context, errorMessage)
} }
return isActuallySuccessful return isActuallySuccessful
} }
@SuppressLint("StringFormatInvalid")
suspend fun addSusPath(context: Context, path: String): Boolean {
return addSusPathInternal(context, path, showToast = true)
}
suspend fun removeSusPath(context: Context, path: String): Boolean { suspend fun removeSusPath(context: Context, path: String): Boolean {
saveSusPaths(context, getSusPaths(context) - path) saveSusPaths(context, getSusPaths(context) - path)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, "SUS path removed: $path")
return true return true
} }
@@ -911,28 +917,25 @@ object SuSFSManager {
return try { return try {
val currentPaths = getSusPaths(context).toMutableSet() val currentPaths = getSusPaths(context).toMutableSet()
if (!currentPaths.remove(oldPath)) { if (!currentPaths.remove(oldPath)) {
showToast(context, "Original path not found: $oldPath") showToast(context, context.getString(R.string.susfs_command_failed))
return false return false
} }
saveSusPaths(context, currentPaths) saveSusPaths(context, currentPaths)
val success = addSusPath(context, newPath) val success = addSusPathInternal(context, newPath, showToast = false)
if (success) { if (!success) {
showToast(context, "SUS path updated: $oldPath -> $newPath")
return true
} else {
// 如果添加新路径失败,恢复旧路径 // 如果添加新路径失败,恢复旧路径
currentPaths.add(oldPath) currentPaths.add(oldPath)
saveSusPaths(context, currentPaths) saveSusPaths(context, currentPaths)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, "Failed to update path, reverted to original") showToast(context, context.getString(R.string.susfs_command_failed))
return false
} }
return success
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() Log.e("SuSFSManager", "Exception editing SUS path", e)
showToast(context, "Error updating SUS path: ${e.message}") showToast(context, context.getString(R.string.susfs_command_failed))
false false
} }
} }
@@ -944,10 +947,12 @@ object SuSFSManager {
} }
@SuppressLint("StringFormatInvalid") @SuppressLint("StringFormatInvalid")
suspend fun addSusLoopPath(context: Context, path: String): Boolean { private suspend fun addSusLoopPathInternal(context: Context, path: String, showToast: Boolean = true): Boolean {
// 检查路径是否有效 // 检查路径是否有效
if (!isValidLoopPath(path)) { if (!isValidLoopPath(path)) {
showToast(context, context.getString(R.string.susfs_loop_path_invalid_location)) if (showToast) {
showToast(context, context.getString(R.string.susfs_invalid_loop_path))
}
return false return false
} }
@@ -958,22 +963,21 @@ object SuSFSManager {
if (isActuallySuccessful) { if (isActuallySuccessful) {
saveSusLoopPaths(context, getSusLoopPaths(context) + path) saveSusLoopPaths(context, getSusLoopPaths(context) + path)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, context.getString(R.string.susfs_loop_path_added_success, path)) } else if (showToast) {
} else { val errorMsg = result.errorOutput.ifEmpty { context.getString(R.string.susfs_add_loop_path_failed) }
val errorMessage = if (result.output.contains("not found, skip adding")) { showToast(context, errorMsg)
context.getString(R.string.susfs_path_not_found_error, path)
} else {
"${context.getString(R.string.susfs_command_failed)}\n${result.output}\n${result.errorOutput}"
}
showToast(context, errorMessage)
} }
return isActuallySuccessful return isActuallySuccessful
} }
@SuppressLint("StringFormatInvalid")
suspend fun addSusLoopPath(context: Context, path: String): Boolean {
return addSusLoopPathInternal(context, path, showToast = true)
}
suspend fun removeSusLoopPath(context: Context, path: String): Boolean { suspend fun removeSusLoopPath(context: Context, path: String): Boolean {
saveSusLoopPaths(context, getSusLoopPaths(context) - path) saveSusLoopPaths(context, getSusLoopPaths(context) - path)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, context.getString(R.string.susfs_loop_path_removed, path))
return true return true
} }
@@ -981,54 +985,57 @@ object SuSFSManager {
suspend fun editSusLoopPath(context: Context, oldPath: String, newPath: String): Boolean { suspend fun editSusLoopPath(context: Context, oldPath: String, newPath: String): Boolean {
// 检查新路径是否有效 // 检查新路径是否有效
if (!isValidLoopPath(newPath)) { if (!isValidLoopPath(newPath)) {
showToast(context, context.getString(R.string.susfs_loop_path_invalid_location)) showToast(context, context.getString(R.string.susfs_invalid_loop_path))
return false return false
} }
return try { return try {
val currentPaths = getSusLoopPaths(context).toMutableSet() val currentPaths = getSusLoopPaths(context).toMutableSet()
if (!currentPaths.remove(oldPath)) { if (!currentPaths.remove(oldPath)) {
showToast(context, "Original loop path not found: $oldPath") showToast(context, context.getString(R.string.susfs_edit_loop_path_failed))
return false return false
} }
saveSusLoopPaths(context, currentPaths) saveSusLoopPaths(context, currentPaths)
val success = addSusLoopPath(context, newPath) val success = addSusLoopPathInternal(context, newPath, showToast = false)
if (success) { if (!success) {
showToast(context, context.getString(R.string.susfs_loop_path_updated, oldPath, newPath))
return true
} else {
// 如果添加新路径失败,恢复旧路径 // 如果添加新路径失败,恢复旧路径
currentPaths.add(oldPath) currentPaths.add(oldPath)
saveSusLoopPaths(context, currentPaths) saveSusLoopPaths(context, currentPaths)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, "Failed to update loop path, reverted to original") showToast(context, context.getString(R.string.susfs_edit_loop_path_failed))
return false
} }
return success
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() Log.e("SuSFSManager", "Exception editing SUS loop path", e)
showToast(context, "Error updating SUS loop path: ${e.message}") showToast(context, context.getString(R.string.susfs_edit_loop_path_failed))
false false
} }
} }
// 添加 SUS Maps // 添加 SUS Maps
suspend fun addSusMap(context: Context, map: String): Boolean { private suspend fun addSusMapInternal(context: Context, map: String, showToast: Boolean = true): Boolean {
val success = executeSusfsCommand(context, "add_sus_map '$map'") val result = executeSusfsCommandWithOutput(context, "add_sus_map '$map'")
val success = result.isSuccess
if (success) { if (success) {
saveSusMaps(context, getSusMaps(context) + map) saveSusMaps(context, getSusMaps(context) + map)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, context.getString(R.string.susfs_sus_map_added_success, map)) } else if (showToast) {
val errorMsg = result.errorOutput.ifEmpty { context.getString(R.string.susfs_add_map_failed) }
showToast(context, errorMsg)
} }
return success return success
} }
suspend fun addSusMap(context: Context, map: String): Boolean {
return addSusMapInternal(context, map, showToast = true)
}
suspend fun removeSusMap(context: Context, map: String): Boolean { suspend fun removeSusMap(context: Context, map: String): Boolean {
saveSusMaps(context, getSusMaps(context) - map) saveSusMaps(context, getSusMaps(context) - map)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, context.getString(R.string.susfs_sus_map_removed, map))
return true return true
} }
@@ -1036,51 +1043,44 @@ object SuSFSManager {
return try { return try {
val currentMaps = getSusMaps(context).toMutableSet() val currentMaps = getSusMaps(context).toMutableSet()
if (!currentMaps.remove(oldMap)) { if (!currentMaps.remove(oldMap)) {
showToast(context, "Original SUS map not found: $oldMap") showToast(context, context.getString(R.string.susfs_edit_map_failed))
return false return false
} }
saveSusMaps(context, currentMaps) saveSusMaps(context, currentMaps)
val success = addSusMap(context, newMap) val success = addSusMapInternal(context, newMap, showToast = false)
if (success) { if (!success) {
showToast(context, context.getString(R.string.susfs_sus_map_updated, oldMap, newMap))
return true
} else {
// 如果添加新映射失败,恢复旧映射 // 如果添加新映射失败,恢复旧映射
currentMaps.add(oldMap) currentMaps.add(oldMap)
saveSusMaps(context, currentMaps) saveSusMaps(context, currentMaps)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, "Failed to update SUS map, reverted to original") showToast(context, context.getString(R.string.susfs_edit_map_failed))
return false
} }
return success
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() Log.e("SuSFSManager", "Exception editing SUS map", e)
showToast(context, "Error updating SUS map: ${e.message}") showToast(context, context.getString(R.string.susfs_edit_map_failed))
false false
} }
} }
// 添加尝试卸载 // 添加尝试卸载
suspend fun addTryUmount(context: Context, path: String, mode: Int): Boolean { private suspend fun addTryUmountInternal(context: Context, path: String, mode: Int): Boolean {
val commandSuccess = executeSusfsCommand(context, "add_try_umount '$path' $mode") executeSusfsCommand(context, "add_try_umount '$path' $mode")
saveTryUmounts(context, getTryUmounts(context) + "$path|$mode") saveTryUmounts(context, getTryUmounts(context) + "$path|$mode")
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, if (commandSuccess) {
context.getString(R.string.susfs_try_umount_added_success, path)
} else {
context.getString(R.string.susfs_try_umount_added_saved, path)
})
return true return true
} }
suspend fun addTryUmount(context: Context, path: String, mode: Int): Boolean {
return addTryUmountInternal(context, path, mode)
}
suspend fun removeTryUmount(context: Context, umountEntry: String): Boolean { suspend fun removeTryUmount(context: Context, umountEntry: String): Boolean {
saveTryUmounts(context, getTryUmounts(context) - umountEntry) saveTryUmounts(context, getTryUmounts(context) - umountEntry)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
val path = umountEntry.split("|").firstOrNull() ?: umountEntry
showToast(context, "Removed Try to uninstall: $path")
return true return true
} }
@@ -1089,28 +1089,21 @@ object SuSFSManager {
return try { return try {
val currentUmounts = getTryUmounts(context).toMutableSet() val currentUmounts = getTryUmounts(context).toMutableSet()
if (!currentUmounts.remove(oldEntry)) { if (!currentUmounts.remove(oldEntry)) {
showToast(context, "Original umount entry not found: $oldEntry")
return false return false
} }
saveTryUmounts(context, currentUmounts) saveTryUmounts(context, currentUmounts)
val success = addTryUmount(context, newPath, newMode) val success = addTryUmountInternal(context, newPath, newMode)
if (success) { if (!success) {
showToast(context, "Try umount updated: $oldEntry -> $newPath|$newMode")
return true
} else {
// 如果添加新条目失败,恢复旧条目 // 如果添加新条目失败,恢复旧条目
currentUmounts.add(oldEntry) currentUmounts.add(oldEntry)
saveTryUmounts(context, currentUmounts) saveTryUmounts(context, currentUmounts)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, "Failed to update umount entry, reverted to original")
return false
} }
} catch (e: Exception) { return success
e.printStackTrace() } catch (_: Exception) {
showToast(context, "Error updating try umount: ${e.message}")
false false
} }
} }
@@ -1123,37 +1116,34 @@ object SuSFSManager {
if (success) { if (success) {
saveUmountForZygoteIsoService(context, enabled) saveUmountForZygoteIsoService(context, enabled)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, if (enabled)
context.getString(R.string.umount_zygote_iso_service_enabled)
else
context.getString(R.string.umount_zygote_iso_service_disabled)
)
} else {
showToast(context, context.getString(R.string.susfs_command_failed))
} }
return success return success
} }
// 添加kstat配置 // 添加kstat配置
suspend fun addKstatStatically(context: Context, path: String, ino: String, dev: String, nlink: String, private suspend fun addKstatStaticallyInternal(context: Context, path: String, ino: String, dev: String, nlink: String,
size: String, atime: String, atimeNsec: String, mtime: String, mtimeNsec: String, size: String, atime: String, atimeNsec: String, mtime: String, mtimeNsec: String,
ctime: String, ctimeNsec: String, blocks: String, blksize: String): Boolean { ctime: String, ctimeNsec: String, blocks: String, blksize: String
): Boolean {
val command = "add_sus_kstat_statically '$path' '$ino' '$dev' '$nlink' '$size' '$atime' '$atimeNsec' '$mtime' '$mtimeNsec' '$ctime' '$ctimeNsec' '$blocks' '$blksize'" val command = "add_sus_kstat_statically '$path' '$ino' '$dev' '$nlink' '$size' '$atime' '$atimeNsec' '$mtime' '$mtimeNsec' '$ctime' '$ctimeNsec' '$blocks' '$blksize'"
val success = executeSusfsCommand(context, command) val success = executeSusfsCommand(context, command)
if (success) { if (success) {
val configEntry = "$path|$ino|$dev|$nlink|$size|$atime|$atimeNsec|$mtime|$mtimeNsec|$ctime|$ctimeNsec|$blocks|$blksize" val configEntry = "$path|$ino|$dev|$nlink|$size|$atime|$atimeNsec|$mtime|$mtimeNsec|$ctime|$ctimeNsec|$blocks|$blksize"
saveKstatConfigs(context, getKstatConfigs(context) + configEntry) saveKstatConfigs(context, getKstatConfigs(context) + configEntry)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, context.getString(R.string.kstat_static_config_added, path))
} }
return success return success
} }
suspend fun addKstatStatically(context: Context, path: String, ino: String, dev: String, nlink: String,
size: String, atime: String, atimeNsec: String, mtime: String, mtimeNsec: String,
ctime: String, ctimeNsec: String, blocks: String, blksize: String): Boolean {
return addKstatStaticallyInternal(context, path, ino, dev, nlink, size, atime, atimeNsec, mtime, mtimeNsec, ctime, ctimeNsec, blocks, blksize)
}
suspend fun removeKstatConfig(context: Context, config: String): Boolean { suspend fun removeKstatConfig(context: Context, config: String): Boolean {
saveKstatConfigs(context, getKstatConfigs(context) - config) saveKstatConfigs(context, getKstatConfigs(context) - config)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
val path = config.split("|").firstOrNull() ?: config
showToast(context, context.getString(R.string.kstat_config_removed, path))
return true return true
} }
@@ -1165,48 +1155,45 @@ object SuSFSManager {
return try { return try {
val currentConfigs = getKstatConfigs(context).toMutableSet() val currentConfigs = getKstatConfigs(context).toMutableSet()
if (!currentConfigs.remove(oldConfig)) { if (!currentConfigs.remove(oldConfig)) {
showToast(context, "Original kstat config not found")
return false return false
} }
saveKstatConfigs(context, currentConfigs) saveKstatConfigs(context, currentConfigs)
val success = addKstatStatically(context, path, ino, dev, nlink, size, atime, atimeNsec, val success = addKstatStaticallyInternal(context, path, ino, dev, nlink, size, atime, atimeNsec,
mtime, mtimeNsec, ctime, ctimeNsec, blocks, blksize) mtime, mtimeNsec, ctime, ctimeNsec, blocks, blksize
)
if (success) { if (!success) {
showToast(context, context.getString(R.string.kstat_config_updated, path))
return true
} else {
// 如果添加新配置失败,恢复旧配置 // 如果添加新配置失败,恢复旧配置
currentConfigs.add(oldConfig) currentConfigs.add(oldConfig)
saveKstatConfigs(context, currentConfigs) saveKstatConfigs(context, currentConfigs)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, "Failed to update kstat config, reverted to original")
return false
} }
} catch (e: Exception) { return success
e.printStackTrace() } catch (
showToast(context, "Error updating kstat config: ${e.message}") _: Exception) {
false false
} }
} }
// 添加kstat路径 // 添加kstat路径
suspend fun addKstat(context: Context, path: String): Boolean { private suspend fun addKstatInternal(context: Context, path: String): Boolean {
val success = executeSusfsCommand(context, "add_sus_kstat '$path'") val success = executeSusfsCommand(context, "add_sus_kstat '$path'")
if (success) { if (success) {
saveAddKstatPaths(context, getAddKstatPaths(context) + path) saveAddKstatPaths(context, getAddKstatPaths(context) + path)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, context.getString(R.string.kstat_path_added, path))
} }
return success return success
} }
suspend fun addKstat(context: Context, path: String): Boolean {
return addKstatInternal(context, path)
}
suspend fun removeAddKstat(context: Context, path: String): Boolean { suspend fun removeAddKstat(context: Context, path: String): Boolean {
saveAddKstatPaths(context, getAddKstatPaths(context) - path) saveAddKstatPaths(context, getAddKstatPaths(context) - path)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, context.getString(R.string.kstat_path_removed, path))
return true return true
} }
@@ -1216,44 +1203,33 @@ object SuSFSManager {
return try { return try {
val currentPaths = getAddKstatPaths(context).toMutableSet() val currentPaths = getAddKstatPaths(context).toMutableSet()
if (!currentPaths.remove(oldPath)) { if (!currentPaths.remove(oldPath)) {
showToast(context, "Original kstat path not found: $oldPath")
return false return false
} }
saveAddKstatPaths(context, currentPaths) saveAddKstatPaths(context, currentPaths)
val success = addKstat(context, newPath) val success = addKstatInternal(context, newPath)
if (success) { if (!success) {
showToast(context, context.getString(R.string.kstat_path_updated, oldPath, newPath))
return true
} else {
// 如果添加新路径失败,恢复旧路径 // 如果添加新路径失败,恢复旧路径
currentPaths.add(oldPath) currentPaths.add(oldPath)
saveAddKstatPaths(context, currentPaths) saveAddKstatPaths(context, currentPaths)
if (isAutoStartEnabled(context)) updateMagiskModule(context) if (isAutoStartEnabled(context)) updateMagiskModule(context)
showToast(context, "Failed to update kstat path, reverted to original")
return false
} }
} catch (e: Exception) { return success
e.printStackTrace() } catch (_: Exception) {
showToast(context, "Error updating kstat path: ${e.message}")
false false
} }
} }
// 更新kstat // 更新kstat
suspend fun updateKstat(context: Context, path: String): Boolean { suspend fun updateKstat(context: Context, path: String): Boolean {
val success = executeSusfsCommand(context, "update_sus_kstat '$path'") return executeSusfsCommand(context, "update_sus_kstat '$path'")
if (success) showToast(context, context.getString(R.string.kstat_updated, path))
return success
} }
// 更新kstat全克隆 // 更新kstat全克隆
suspend fun updateKstatFullClone(context: Context, path: String): Boolean { suspend fun updateKstatFullClone(context: Context, path: String): Boolean {
val success = executeSusfsCommand(context, "update_sus_kstat_full_clone '$path'") return executeSusfsCommand(context, "update_sus_kstat_full_clone '$path'")
if (success) showToast(context, context.getString(R.string.kstat_full_clone_updated, path))
return success
} }
// 设置Android数据路径 // 设置Android数据路径
@@ -1295,14 +1271,14 @@ object SuSFSManager {
try { try {
if (enabled) { if (enabled) {
if (!hasConfigurationForAutoStart(context)) { if (!hasConfigurationForAutoStart(context)) {
showToast(context, context.getString(R.string.susfs_no_config_to_autostart)) Log.e("SuSFSManager", "No configuration available for auto start")
return@withContext false return@withContext false
} }
val targetPath = getSuSFSTargetPath() val targetPath = getSuSFSTargetPath()
if (!runCmdWithResult("test -f '$targetPath'").isSuccess) { if (!runCmdWithResult("test -f '$targetPath'").isSuccess) {
copyBinaryFromAssets(context) ?: run { copyBinaryFromAssets(context) ?: run {
showToast(context, context.getString(R.string.susfs_binary_not_found)) Log.e("SuSFSManager", "Failed to copy binary from assets for auto start")
return@withContext false return@withContext false
} }
} }
@@ -1310,24 +1286,21 @@ object SuSFSManager {
val success = SuSFSModuleManager.createMagiskModule(context) val success = SuSFSModuleManager.createMagiskModule(context)
if (success) { if (success) {
setAutoStartEnabled(context, true) setAutoStartEnabled(context, true)
showToast(context, context.getString(R.string.susfs_autostart_enabled_success, SuSFSModuleManager.getModulePath()))
} else { } else {
showToast(context, context.getString(R.string.susfs_autostart_enable_failed)) Log.e("SuSFSManager", "Failed to create Magisk module for auto start")
} }
success success
} else { } else {
val success = SuSFSModuleManager.removeMagiskModule() val success = SuSFSModuleManager.removeMagiskModule()
if (success) { if (success) {
setAutoStartEnabled(context, false) setAutoStartEnabled(context, false)
showToast(context, context.getString(R.string.susfs_autostart_disabled_success))
} else { } else {
showToast(context, context.getString(R.string.susfs_autostart_disable_failed)) Log.e("SuSFSManager", "Failed to remove Magisk module")
} }
success success
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() Log.e("SuSFSManager", "Exception configuring auto start: enabled=$enabled", e)
showToast(context, context.getString(R.string.susfs_autostart_error, e.message ?: "Unknown error"))
false false
} }
} }

View File

@@ -361,16 +361,11 @@
<!-- SuSFS Toast Messages --> <!-- SuSFS Toast Messages -->
<string name="susfs_binary_not_found">无法找到 ksu_susfs 文件</string> <string name="susfs_binary_not_found">无法找到 ksu_susfs 文件</string>
<string name="susfs_command_failed">SuSFS 命令执行失败</string> <string name="susfs_command_failed">SuSFS 命令执行失败</string>
<string name="susfs_uname_set_success" formatted="false">SuSFS 内核名称和构建时间设置成功: %s, %s</string>
<!-- SuSFS Settings Item --> <!-- SuSFS Settings Item -->
<!-- 开机自启动相关 --> <!-- 开机自启动相关 -->
<string name="susfs_autostart_title">开机自启动</string> <string name="susfs_autostart_title">开机自启动</string>
<string name="susfs_autostart_description">重启时自动应用所有非默认配置</string> <string name="susfs_autostart_description">重启时自动应用所有非默认配置</string>
<string name="susfs_autostart_requirement">需要添加配置后才能启用</string> <string name="susfs_autostart_requirement">需要添加配置后才能启用</string>
<string name="susfs_autostart_enable_failed">启用开机自启动失败</string>
<string name="susfs_autostart_disable_failed">禁用开机自启动失败</string>
<string name="susfs_autostart_error">开机自启动配置错误: %s</string>
<string name="susfs_no_config_to_autostart">没有可用的配置进行开机自启动</string>
<!-- SuSFS Tab Titles --> <!-- SuSFS Tab Titles -->
<string name="susfs_tab_basic_settings">基本设置</string> <string name="susfs_tab_basic_settings">基本设置</string>
<string name="susfs_tab_sus_paths">SuS 路径</string> <string name="susfs_tab_sus_paths">SuS 路径</string>
@@ -380,8 +375,6 @@
<!-- SuSFS Path Management --> <!-- SuSFS Path Management -->
<string name="susfs_add_sus_path">添加 SuS 路径</string> <string name="susfs_add_sus_path">添加 SuS 路径</string>
<string name="susfs_add_try_umount">添加尝试卸载</string> <string name="susfs_add_try_umount">添加尝试卸载</string>
<string name="susfs_sus_path_added_success">SuS 路径添加成功</string>
<string name="susfs_path_not_found_error">路径未找到错误</string>
<string name="susfs_path_label">路径</string> <string name="susfs_path_label">路径</string>
<string name="susfs_no_paths_configured">暂无 SuS 路径配置</string> <string name="susfs_no_paths_configured">暂无 SuS 路径配置</string>
<string name="susfs_no_umounts_configured">暂无尝试卸载配置</string> <string name="susfs_no_umounts_configured">暂无尝试卸载配置</string>
@@ -392,8 +385,6 @@
<string name="susfs_umount_mode_normal_short">普通</string> <string name="susfs_umount_mode_normal_short">普通</string>
<string name="susfs_umount_mode_detach_short">分离</string> <string name="susfs_umount_mode_detach_short">分离</string>
<string name="susfs_umount_mode_display">模式: %1$s (%2$s)</string> <string name="susfs_umount_mode_display">模式: %1$s (%2$s)</string>
<string name="susfs_try_umount_added_success">尝试 umount 路径添加成功: %s</string>
<string name="susfs_try_umount_added_saved">尝试 umount 路径保存成功: %s</string>
<!-- SuSFS Run Umount --> <!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories --> <!-- SuSFS Reset Categories -->
<string name="susfs_reset_paths_title">重置 SuS 路径</string> <string name="susfs_reset_paths_title">重置 SuS 路径</string>
@@ -424,8 +415,6 @@
<string name="susfs_enable_log_label">SuSFS 启用日志</string> <string name="susfs_enable_log_label">SuSFS 启用日志</string>
<string name="susfs_log_config_description">启用或者关闭 SuSFS 的日志</string> <string name="susfs_log_config_description">启用或者关闭 SuSFS 的日志</string>
<string name="susfs_log_config_title">SuSFS 日志配置</string> <string name="susfs_log_config_title">SuSFS 日志配置</string>
<string name="susfs_log_enabled">启用 SuSFS 日志</string>
<string name="susfs_log_disabled">关闭 SuSFS 日志</string>
<string name="susfs_execution_location_label">执行位置</string> <string name="susfs_execution_location_label">执行位置</string>
<string name="susfs_current_execution_location">当前执行位置:%s</string> <string name="susfs_current_execution_location">当前执行位置:%s</string>
<string name="susfs_execution_location_service">Service</string> <string name="susfs_execution_location_service">Service</string>
@@ -440,16 +429,8 @@
<string name="susfs_slot_use_build_time">使用构建时间</string> <string name="susfs_slot_use_build_time">使用构建时间</string>
<string name="susfs_slot_info_unavailable">无法获取槽位信息</string> <string name="susfs_slot_info_unavailable">无法获取槽位信息</string>
<!-- SuSFS 自启动相关字符串 --> <!-- SuSFS 自启动相关字符串 -->
<string name="susfs_autostart_enabled_success">SuSFS 自启动模块已启用,模块路径:%s</string>
<string name="susfs_autostart_disabled_success">SuSFS 自启动模块已禁用</string>
<!-- SuSFS Kstat相关字符串 --> <!-- SuSFS Kstat相关字符串 -->
<string name="susfs_tab_kstat_config">Kstat 配置</string> <string name="susfs_tab_kstat_config">Kstat 配置</string>
<string name="kstat_static_config_added">Kstat 静态配置已添加:%1$s</string>
<string name="kstat_config_removed">已移除 Kstat 配置:%1$s</string>
<string name="kstat_path_added">Kstat 路径已添加:%1$s</string>
<string name="kstat_path_removed">已移除 Kstat 路径:%1$s</string>
<string name="kstat_updated">Kstat 已更新:%1$s</string>
<string name="kstat_full_clone_updated">Kstat 完整克隆已更新:%1$s</string>
<string name="add_kstat_statically_title">添加 Kstat 静态配置</string> <string name="add_kstat_statically_title">添加 Kstat 静态配置</string>
<string name="file_or_directory_path_label">文件/目录路径</string> <string name="file_or_directory_path_label">文件/目录路径</string>
<string name="hint_use_default_value">提示:可以使用 "default" 来使用原始值</string> <string name="hint_use_default_value">提示:可以使用 "default" 来使用原始值</string>
@@ -469,11 +450,6 @@
<string name="susfs_hide_mounts_for_all_procs_label">对所有进程隐藏 SuS 挂载</string> <string name="susfs_hide_mounts_for_all_procs_label">对所有进程隐藏 SuS 挂载</string>
<string name="susfs_hide_mounts_for_all_procs_enabled_description">启用后SuS 挂载将对所有进程隐藏,包括 KSU 进程</string> <string name="susfs_hide_mounts_for_all_procs_enabled_description">启用后SuS 挂载将对所有进程隐藏,包括 KSU 进程</string>
<string name="susfs_hide_mounts_for_all_procs_disabled_description">禁用后SuS 挂载仅对非 KSU 进程隐藏KSU 进程可以看到挂载</string> <string name="susfs_hide_mounts_for_all_procs_disabled_description">禁用后SuS 挂载仅对非 KSU 进程隐藏KSU 进程可以看到挂载</string>
<string name="susfs_hide_mounts_all_enabled">已启用对所有进程隐藏 SuS 挂载</string>
<string name="susfs_hide_mounts_all_disabled">已禁用对所有进程隐藏 SuS 挂载</string>
<string name="susfs_android_data_path_set">Android Data 路径已设置为: %s</string>
<string name="susfs_sdcard_path_set">SDCard 路径已设置为: %s</string>
<string name="susfs_path_setup_warning">路径设置可能未完全成功,但将继续添加 SuS 路径</string>
<!-- 备份和还原相关字符串 --> <!-- 备份和还原相关字符串 -->
<string name="susfs_backup_title">备份</string> <string name="susfs_backup_title">备份</string>
<string name="susfs_backup_description">创建所有 SuSFS 配置的备份。备份文件将包含所有设置、路径和配置信息。</string> <string name="susfs_backup_description">创建所有 SuSFS 配置的备份。备份文件将包含所有设置、路径和配置信息。</string>
@@ -506,13 +482,9 @@
<string name="edit">编辑</string> <string name="edit">编辑</string>
<string name="delete">删除</string> <string name="delete">删除</string>
<string name="update">更新</string> <string name="update">更新</string>
<string name="kstat_config_updated">Kstat 配置更新</string>
<string name="kstat_path_updated">Kstat 路径更新</string>
<string name="susfs_update_full_clone">Susfs 完整克隆更新</string> <string name="susfs_update_full_clone">Susfs 完整克隆更新</string>
<string name="umount_zygote_iso_service">卸载 Zygote 隔离服务</string> <string name="umount_zygote_iso_service">卸载 Zygote 隔离服务</string>
<string name="umount_zygote_iso_service_description">启用此选项将在系统启动时卸载 Zygote 隔离服务挂载点</string> <string name="umount_zygote_iso_service_description">启用此选项将在系统启动时卸载 Zygote 隔离服务挂载点</string>
<string name="umount_zygote_iso_service_enabled">Zygote 隔离服务卸载已启用</string>
<string name="umount_zygote_iso_service_disabled">Zygote 隔离服务卸载已禁用</string>
<string name="app_paths_section">应用路径</string> <string name="app_paths_section">应用路径</string>
<string name="other_paths_section">其他路径</string> <string name="other_paths_section">其他路径</string>
<string name="add_custom_path">其他</string> <string name="add_custom_path">其他</string>
@@ -526,33 +498,29 @@
<string name="susfs_tab_sus_loop_paths">SuS 循环路径</string> <string name="susfs_tab_sus_loop_paths">SuS 循环路径</string>
<string name="susfs_add_sus_loop_path">添加 SuS 循环路径</string> <string name="susfs_add_sus_loop_path">添加 SuS 循环路径</string>
<string name="susfs_edit_sus_loop_path">编辑 SuS 循环路径</string> <string name="susfs_edit_sus_loop_path">编辑 SuS 循环路径</string>
<string name="susfs_loop_path_added_success">SuS 循环路径添加成功: %1$s</string>
<string name="susfs_loop_path_removed">SuS 循环路径已移除: %1$s</string>
<string name="susfs_loop_path_updated">SuS 循环路径已更新: %1$s -&gt; %2$s</string>
<string name="susfs_no_loop_paths_configured">未配置 SuS 循环路径</string> <string name="susfs_no_loop_paths_configured">未配置 SuS 循环路径</string>
<string name="susfs_reset_loop_paths_title">重置循环路径</string> <string name="susfs_reset_loop_paths_title">重置循环路径</string>
<string name="susfs_reset_loop_paths_message">确定要清空所有 SuS 循环路径吗?此操作无法撤销。</string> <string name="susfs_reset_loop_paths_message">确定要清空所有 SuS 循环路径吗?此操作无法撤销。</string>
<string name="susfs_loop_path_label">循环路径</string> <string name="susfs_loop_path_label">循环路径</string>
<string name="susfs_loop_path_restriction_warning">注意:只有不在 /storage/ 和 /sdcard/ 内的路径才能通过循环路径添加。</string> <string name="susfs_loop_path_restriction_warning">注意:只有不在 /storage/ 和 /sdcard/ 内的路径才能通过循环路径添加。</string>
<string name="susfs_loop_path_invalid_location">错误:循环路径不能位于 /storage/ 或 /sdcard/ 目录内</string> <string name="susfs_invalid_loop_path">无效的循环路径</string>
<string name="susfs_add_loop_path_failed">添加循环路径失败</string>
<string name="susfs_edit_loop_path_failed">编辑循环路径失败</string>
<string name="loop_paths_section">循环路径</string> <string name="loop_paths_section">循环路径</string>
<string name="add_loop_path">添加循环路径</string> <string name="add_loop_path">添加循环路径</string>
<!-- 循环路径功能描述 --> <!-- 循环路径功能描述 -->
<string name="sus_loop_paths_description_title">循环路径配置</string> <string name="sus_loop_paths_description_title">循环路径配置</string>
<string name="sus_loop_paths_description_text">循环路径会在每次非 root 用户应用或隔离服务启动时重新标记为 SUS_PATH。这有助于解决添加的路径可能因 inode 状态重置或内核中 inode 重新创建而失效的问题</string> <string name="sus_loop_paths_description_text">循环路径会在每次非 root 用户应用或隔离服务启动时重新标记为 SUS_PATH。这有助于解决添加的路径可能因 inode 状态重置或内核中 inode 重新创建而失效的问题</string>
<string name="avc_log_spoofing">AVC 日志欺骗</string> <string name="avc_log_spoofing">AVC 日志欺骗</string>
<string name="avc_log_spoofing_enabled">AVC 日志欺骗已启用</string>
<string name="avc_log_spoofing_disabled">AVC 日志欺骗已禁用</string>
<string name="avc_log_spoofing_description">禁用: 禁用在内核 AVC 日志中欺骗 \'su\' 的 sus tcontext。\n启用: 启用在内核 AVC 日志中将 \'su\' 的 sus tcontext 欺骗为 \'kernel\'</string> <string name="avc_log_spoofing_description">禁用: 禁用在内核 AVC 日志中欺骗 \'su\' 的 sus tcontext。\n启用: 启用在内核 AVC 日志中将 \'su\' 的 sus tcontext 欺骗为 \'kernel\'</string>
<!-- SUS Map related strings --> <!-- SUS Map related strings -->
<string name="susfs_tab_sus_maps">SUS映射</string> <string name="susfs_tab_sus_maps">SUS映射</string>
<string name="susfs_sus_map_label">库文件路径</string> <string name="susfs_sus_map_label">库文件路径</string>
<string name="susfs_add_sus_map">添加SUS映射</string> <string name="susfs_add_sus_map">添加SUS映射</string>
<string name="susfs_edit_sus_map">编辑SUS映射</string> <string name="susfs_edit_sus_map">编辑SUS映射</string>
<string name="susfs_sus_map_added_success">SUS映射添加成功: %1$s</string>
<string name="susfs_sus_map_removed">SUS映射已移除: %1$s</string>
<string name="susfs_sus_map_updated">SUS映射已更新: %1$s -&gt; %2$s</string>
<string name="susfs_no_sus_maps_configured">未配置SUS映射</string> <string name="susfs_no_sus_maps_configured">未配置SUS映射</string>
<string name="susfs_add_map_failed">添加SUS映射失败</string>
<string name="susfs_edit_map_failed">编辑SUS映射失败</string>
<string name="susfs_reset_sus_maps_title">重置SUS映射</string> <string name="susfs_reset_sus_maps_title">重置SUS映射</string>
<string name="susfs_reset_sus_maps_message">这将移除所有已配置的SUS映射。此操作无法撤销。</string> <string name="susfs_reset_sus_maps_message">这将移除所有已配置的SUS映射。此操作无法撤销。</string>
<string name="sus_maps_section">内存映射隐藏</string> <string name="sus_maps_section">内存映射隐藏</string>

View File

@@ -369,16 +369,11 @@
<!-- SuSFS Toast Messages --> <!-- SuSFS Toast Messages -->
<string name="susfs_binary_not_found">Cannot find ksu_susfs file</string> <string name="susfs_binary_not_found">Cannot find ksu_susfs file</string>
<string name="susfs_command_failed">SuSFS command execution failed</string> <string name="susfs_command_failed">SuSFS command execution failed</string>
<string name="susfs_uname_set_success" formatted="false">SuSFS uname and build time set successfully: %s, %s</string>
<!-- SuSFS Settings Item --> <!-- SuSFS Settings Item -->
<!-- 开机自启动相关 --> <!-- 开机自启动相关 -->
<string name="susfs_autostart_title">Auto Start</string> <string name="susfs_autostart_title">Auto Start</string>
<string name="susfs_autostart_description">Automatically apply all non-default configurations on reboot</string> <string name="susfs_autostart_description">Automatically apply all non-default configurations on reboot</string>
<string name="susfs_autostart_requirement">Configuration needs to be added to enable</string> <string name="susfs_autostart_requirement">Configuration needs to be added to enable</string>
<string name="susfs_autostart_enable_failed">Failed to enable auto start</string>
<string name="susfs_autostart_disable_failed">Failed to disable auto start</string>
<string name="susfs_autostart_error">Auto start configuration error: %s</string>
<string name="susfs_no_config_to_autostart">No available configuration for auto start</string>
<!-- SuSFS Tab Titles --> <!-- SuSFS Tab Titles -->
<string name="susfs_tab_basic_settings">Basic Settings</string> <string name="susfs_tab_basic_settings">Basic Settings</string>
<string name="susfs_tab_sus_paths">SUS Paths</string> <string name="susfs_tab_sus_paths">SUS Paths</string>
@@ -388,8 +383,6 @@
<!-- SuSFS Path Management --> <!-- SuSFS Path Management -->
<string name="susfs_add_sus_path">Add SUS Path</string> <string name="susfs_add_sus_path">Add SUS Path</string>
<string name="susfs_add_try_umount">Add Try Umount</string> <string name="susfs_add_try_umount">Add Try Umount</string>
<string name="susfs_sus_path_added_success">SUS path added successfully</string>
<string name="susfs_path_not_found_error">Path not found error</string>
<string name="susfs_path_label">Path</string> <string name="susfs_path_label">Path</string>
<string name="susfs_no_paths_configured">No SUS paths configured</string> <string name="susfs_no_paths_configured">No SUS paths configured</string>
<string name="susfs_no_umounts_configured">No try umount configured</string> <string name="susfs_no_umounts_configured">No try umount configured</string>
@@ -400,8 +393,6 @@
<string name="susfs_umount_mode_normal_short">Normal</string> <string name="susfs_umount_mode_normal_short">Normal</string>
<string name="susfs_umount_mode_detach_short">Detach</string> <string name="susfs_umount_mode_detach_short">Detach</string>
<string name="susfs_umount_mode_display">Mode: %1$s (%2$s)</string> <string name="susfs_umount_mode_display">Mode: %1$s (%2$s)</string>
<string name="susfs_try_umount_added_success">Try to umount path added successfully %s</string>
<string name="susfs_try_umount_added_saved">Attempted umount path save succeeded %s</string>
<!-- SuSFS Reset Categories --> <!-- SuSFS Reset Categories -->
<string name="susfs_reset_paths_title">Reset SUS Paths</string> <string name="susfs_reset_paths_title">Reset SUS Paths</string>
<string name="susfs_reset_paths_message">This will clear all SUS path configurations. Are you sure you want to continue?</string> <string name="susfs_reset_paths_message">This will clear all SUS path configurations. Are you sure you want to continue?</string>
@@ -431,8 +422,6 @@
<string name="susfs_enable_log_label">SuSFS Enable Log</string> <string name="susfs_enable_log_label">SuSFS Enable Log</string>
<string name="susfs_log_config_description">Enable or disable logging for SuSFS</string> <string name="susfs_log_config_description">Enable or disable logging for SuSFS</string>
<string name="susfs_log_config_title">SuSFS Logging Configuration</string> <string name="susfs_log_config_title">SuSFS Logging Configuration</string>
<string name="susfs_log_enabled">Enabling SuSFS Logging</string>
<string name="susfs_log_disabled">Turn off SuSFS logging</string>
<string name="susfs_execution_location_label">Execution Location</string> <string name="susfs_execution_location_label">Execution Location</string>
<string name="susfs_current_execution_location">Current execution location: %s</string> <string name="susfs_current_execution_location">Current execution location: %s</string>
<string name="susfs_execution_location_service">Service</string> <string name="susfs_execution_location_service">Service</string>
@@ -447,16 +436,8 @@
<string name="susfs_slot_use_build_time">Use Build Time</string> <string name="susfs_slot_use_build_time">Use Build Time</string>
<string name="susfs_slot_info_unavailable">Unable to retrieve slot information</string> <string name="susfs_slot_info_unavailable">Unable to retrieve slot information</string>
<!-- SuSFS 自启动相关字符串 --> <!-- SuSFS 自启动相关字符串 -->
<string name="susfs_autostart_enabled_success">SuSFS auto-start module enabled, module path: %s</string>
<string name="susfs_autostart_disabled_success">SuSFS auto-start module disabled</string>
<!-- SuSFS Kstat相关字符串 --> <!-- SuSFS Kstat相关字符串 -->
<string name="susfs_tab_kstat_config">Kstat Configuration</string> <string name="susfs_tab_kstat_config">Kstat Configuration</string>
<string name="kstat_static_config_added">Kstat static configuration added: %1$s</string>
<string name="kstat_config_removed">Kstat configuration removed: %1$s</string>
<string name="kstat_path_added">Kstat path added: %1$s</string>
<string name="kstat_path_removed">Kstat path removed: %1$s</string>
<string name="kstat_updated">Kstat updated: %1$s</string>
<string name="kstat_full_clone_updated">Kstat full clone updated: %1$s</string>
<string name="add_kstat_statically_title">Add Kstat Static Configuration</string> <string name="add_kstat_statically_title">Add Kstat Static Configuration</string>
<string name="file_or_directory_path_label">File/Directory Path</string> <string name="file_or_directory_path_label">File/Directory Path</string>
<string name="hint_use_default_value">Hint: You can use "default" to use the original value</string> <string name="hint_use_default_value">Hint: You can use "default" to use the original value</string>
@@ -476,11 +457,6 @@
<string name="susfs_hide_mounts_for_all_procs_label">Hide SUS mounts for all processes</string> <string name="susfs_hide_mounts_for_all_procs_label">Hide SUS mounts for all processes</string>
<string name="susfs_hide_mounts_for_all_procs_enabled_description">When enabled, SUS mounts will be hidden from all processes, including KSU processes</string> <string name="susfs_hide_mounts_for_all_procs_enabled_description">When enabled, SUS mounts will be hidden from all processes, including KSU processes</string>
<string name="susfs_hide_mounts_for_all_procs_disabled_description">When disabled, SUS mounts will only be hidden from non-KSU processes, KSU processes can see the mounts</string> <string name="susfs_hide_mounts_for_all_procs_disabled_description">When disabled, SUS mounts will only be hidden from non-KSU processes, KSU processes can see the mounts</string>
<string name="susfs_hide_mounts_all_enabled">Enabled hiding SUS mounts for all processes</string>
<string name="susfs_hide_mounts_all_disabled">Disabled hiding SUS mounts for all processes</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>
<!-- 备份和还原相关字符串 --> <!-- 备份和还原相关字符串 -->
<string name="susfs_backup_title">Backup</string> <string name="susfs_backup_title">Backup</string>
<string name="susfs_backup_description">Create a backup of all SuSFS configurations. The backup file will include all settings, paths, and configurations</string> <string name="susfs_backup_description">Create a backup of all SuSFS configurations. The backup file will include all settings, paths, and configurations</string>
@@ -513,13 +489,9 @@
<string name="edit">Edit</string> <string name="edit">Edit</string>
<string name="delete">Delete</string> <string name="delete">Delete</string>
<string name="update">Update</string> <string name="update">Update</string>
<string name="kstat_config_updated">Kstat config update</string>
<string name="kstat_path_updated">Kstat path update</string>
<string name="susfs_update_full_clone">Susfs update full clone</string> <string name="susfs_update_full_clone">Susfs update full clone</string>
<string name="umount_zygote_iso_service">Unmount Zygote Isolation Service</string> <string name="umount_zygote_iso_service">Unmount Zygote Isolation Service</string>
<string name="umount_zygote_iso_service_description">Enable this option to unmount Zygote isolation service mount points at system startup</string> <string name="umount_zygote_iso_service_description">Enable this option to unmount Zygote isolation service mount points at system startup</string>
<string name="umount_zygote_iso_service_enabled">Zygote isolation service unmount enabled</string>
<string name="umount_zygote_iso_service_disabled">Zygote isolation service unmount disabled</string>
<string name="app_paths_section">Application Path</string> <string name="app_paths_section">Application Path</string>
<string name="other_paths_section">Other paths</string> <string name="other_paths_section">Other paths</string>
<string name="add_custom_path">Other</string> <string name="add_custom_path">Other</string>
@@ -533,33 +505,29 @@
<string name="susfs_tab_sus_loop_paths">SUS Loop Paths</string> <string name="susfs_tab_sus_loop_paths">SUS Loop Paths</string>
<string name="susfs_add_sus_loop_path">Add SUS Loop Path</string> <string name="susfs_add_sus_loop_path">Add SUS Loop Path</string>
<string name="susfs_edit_sus_loop_path">Edit SUS Loop Path</string> <string name="susfs_edit_sus_loop_path">Edit SUS Loop Path</string>
<string name="susfs_loop_path_added_success">SUS loop path added successfully: %1$s</string>
<string name="susfs_loop_path_removed">SUS loop path removed: %1$s</string>
<string name="susfs_loop_path_updated">SUS loop path updated: %1$s -> %2$s</string>
<string name="susfs_no_loop_paths_configured">No SUS loop paths configured</string> <string name="susfs_no_loop_paths_configured">No SUS loop paths configured</string>
<string name="susfs_reset_loop_paths_title">Reset Loop Paths</string> <string name="susfs_reset_loop_paths_title">Reset Loop Paths</string>
<string name="susfs_reset_loop_paths_message">Are you sure you want to clear all SUS loop paths? This action cannot be undone</string> <string name="susfs_reset_loop_paths_message">Are you sure you want to clear all SUS loop paths? This action cannot be undone</string>
<string name="susfs_loop_path_label">Loop Path</string> <string name="susfs_loop_path_label">Loop Path</string>
<string name="susfs_loop_path_restriction_warning">Note: Only paths NOT inside /storage/ and /sdcard/ can be added via loop paths</string> <string name="susfs_loop_path_restriction_warning">Note: Only paths NOT inside /storage/ and /sdcard/ can be added via loop paths</string>
<string name="susfs_loop_path_invalid_location">Error: Loop paths cannot be inside /storage/ or /sdcard/ directories</string> <string name="susfs_invalid_loop_path">Invalid loop path</string>
<string name="susfs_add_loop_path_failed">Failed to add loop path</string>
<string name="susfs_edit_loop_path_failed">Failed to edit loop path</string>
<string name="loop_paths_section">Loop Paths</string> <string name="loop_paths_section">Loop Paths</string>
<string name="add_loop_path">Add Loop Path</string> <string name="add_loop_path">Add Loop Path</string>
<!-- 循环路径功能描述 --> <!-- 循环路径功能描述 -->
<string name="sus_loop_paths_description_title">Loop Path Configuration</string> <string name="sus_loop_paths_description_title">Loop Path Configuration</string>
<string name="sus_loop_paths_description_text">Loop paths are re-flagged as SUS_PATH on each non-root user app or isolated service startup. This helps address issues where added paths may have their inode status reset or inode re-created in the kernel</string> <string name="sus_loop_paths_description_text">Loop paths are re-flagged as SUS_PATH on each non-root user app or isolated service startup. This helps address issues where added paths may have their inode status reset or inode re-created in the kernel</string>
<string name="avc_log_spoofing">AVC Log Spoofing</string> <string name="avc_log_spoofing">AVC Log Spoofing</string>
<string name="avc_log_spoofing_enabled">AVC log spoofing has been enabled</string>
<string name="avc_log_spoofing_disabled">AVC log spoofing has been disabled</string>
<string name="avc_log_spoofing_description">Disabled: Disable spoofing the sus tcontext of \'su\' shown in avc log in kernel\nEnabled: Enable spoofing the sus tcontext of \'su\' with \'kernel\' shown in avc log in kernel</string> <string name="avc_log_spoofing_description">Disabled: Disable spoofing the sus tcontext of \'su\' shown in avc log in kernel\nEnabled: Enable spoofing the sus tcontext of \'su\' with \'kernel\' shown in avc log in kernel</string>
<!-- SUS Map related strings --> <!-- SUS Map related strings -->
<string name="susfs_tab_sus_maps">SUS Maps</string> <string name="susfs_tab_sus_maps">SUS Maps</string>
<string name="susfs_sus_map_label">Library Path</string> <string name="susfs_sus_map_label">Library Path</string>
<string name="susfs_add_sus_map">Add SUS Map</string> <string name="susfs_add_sus_map">Add SUS Map</string>
<string name="susfs_edit_sus_map">Edit SUS Map</string> <string name="susfs_edit_sus_map">Edit SUS Map</string>
<string name="susfs_sus_map_added_success">SUS map added successfully: %1$s</string>
<string name="susfs_sus_map_removed">SUS map removed: %1$s</string>
<string name="susfs_sus_map_updated">SUS map updated: %1$s -> %2$s</string>
<string name="susfs_no_sus_maps_configured">No SUS maps configured</string> <string name="susfs_no_sus_maps_configured">No SUS maps configured</string>
<string name="susfs_add_map_failed">Failed to add SUS map</string>
<string name="susfs_edit_map_failed">Failed to edit SUS map</string>
<string name="susfs_reset_sus_maps_title">Reset SUS Maps</string> <string name="susfs_reset_sus_maps_title">Reset SUS Maps</string>
<string name="susfs_reset_sus_maps_message">This will remove all configured SUS maps. This action cannot be undone.</string> <string name="susfs_reset_sus_maps_message">This will remove all configured SUS maps. This action cannot be undone.</string>
<string name="sus_maps_section">Memory Map Hiding</string> <string name="sus_maps_section">Memory Map Hiding</string>