manager: Add Zygote isolation service uninstallation to susfs feature

This commit is contained in:
ShirkNeko
2025-06-30 15:32:47 +08:00
parent 3551441e42
commit 7ee1fd63f1
7 changed files with 135 additions and 3 deletions

View File

@@ -19,6 +19,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Folder import androidx.compose.material.icons.filled.Folder
import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Security
import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Storage import androidx.compose.material.icons.filled.Storage
import androidx.compose.material3.Button import androidx.compose.material3.Button
@@ -27,6 +28,7 @@ import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@@ -34,6 +36,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.sukisu.ultra.R import com.sukisu.ultra.R
import com.sukisu.ultra.ui.screen.extensions.AddKstatPathItemCard import com.sukisu.ultra.ui.screen.extensions.AddKstatPathItemCard
import com.sukisu.ultra.ui.screen.extensions.EmptyStateCard import com.sukisu.ultra.ui.screen.extensions.EmptyStateCard
@@ -42,6 +45,7 @@ import com.sukisu.ultra.ui.screen.extensions.KstatConfigItemCard
import com.sukisu.ultra.ui.screen.extensions.PathItemCard import com.sukisu.ultra.ui.screen.extensions.PathItemCard
import com.sukisu.ultra.ui.screen.extensions.SusMountHidingControlCard import com.sukisu.ultra.ui.screen.extensions.SusMountHidingControlCard
import com.sukisu.ultra.ui.util.SuSFSManager import com.sukisu.ultra.ui.util.SuSFSManager
import com.sukisu.ultra.ui.util.SuSFSManager.isSusVersion_1_5_8
/** /**
* SUS路径内容组件 * SUS路径内容组件
@@ -190,11 +194,13 @@ fun SusMountsContent(
@Composable @Composable
fun TryUmountContent( fun TryUmountContent(
tryUmounts: Set<String>, tryUmounts: Set<String>,
umountForZygoteIsoService: Boolean,
isLoading: Boolean, isLoading: Boolean,
onAddUmount: () -> Unit, onAddUmount: () -> Unit,
onRunUmount: () -> Unit, onRunUmount: () -> Unit,
onRemoveUmount: (String) -> Unit, onRemoveUmount: (String) -> Unit,
onEditUmount: ((String) -> Unit)? = null onEditUmount: ((String) -> Unit)? = null,
onToggleUmountForZygoteIsoService: (Boolean) -> Unit
) { ) {
Box(modifier = Modifier.fillMaxSize()) { Box(modifier = Modifier.fillMaxSize()) {
LazyColumn( LazyColumn(
@@ -202,6 +208,60 @@ fun TryUmountContent(
.fillMaxSize(), .fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(12.dp)
) { ) {
if (isSusVersion_1_5_8()) {
item {
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surface
),
shape = RoundedCornerShape(12.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.weight(1f)
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = Icons.Default.Security,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = stringResource(R.string.umount_zygote_iso_service),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.onSurface
)
}
Spacer(modifier = Modifier.height(6.dp))
Text(
text = stringResource(R.string.umount_zygote_iso_service_description),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
lineHeight = 14.sp
)
}
Switch(
checked = umountForZygoteIsoService,
onCheckedChange = onToggleUmountForZygoteIsoService,
enabled = !isLoading
)
}
}
}
}
if (tryUmounts.isEmpty()) { if (tryUmounts.isEmpty()) {
item { item {
EmptyStateCard( EmptyStateCard(

View File

@@ -148,6 +148,8 @@ fun SuSFSConfigScreen(
// SUS挂载隐藏控制状态 // SUS挂载隐藏控制状态
var hideSusMountsForAllProcs by remember { mutableStateOf(true) } var hideSusMountsForAllProcs by remember { mutableStateOf(true) }
var umountForZygoteIsoService by remember { mutableStateOf(false) }
// Kstat配置相关状态 // Kstat配置相关状态
var kstatConfigs by remember { mutableStateOf(emptySet<String>()) } var kstatConfigs by remember { mutableStateOf(emptySet<String>()) }
var addKstatPaths by remember { mutableStateOf(emptySet<String>()) } var addKstatPaths by remember { mutableStateOf(emptySet<String>()) }
@@ -287,6 +289,7 @@ fun SuSFSConfigScreen(
hideSusMountsForAllProcs = SuSFSManager.getHideSusMountsForAllProcs(context) hideSusMountsForAllProcs = SuSFSManager.getHideSusMountsForAllProcs(context)
enableHideBl = SuSFSManager.getEnableHideBl(context) enableHideBl = SuSFSManager.getEnableHideBl(context)
enableCleanupResidue = SuSFSManager.getEnableCleanupResidue(context) enableCleanupResidue = SuSFSManager.getEnableCleanupResidue(context)
umountForZygoteIsoService = SuSFSManager.getUmountForZygoteIsoService(context)
loadSlotInfo() loadSlotInfo()
} }
@@ -455,6 +458,7 @@ fun SuSFSConfigScreen(
hideSusMountsForAllProcs = SuSFSManager.getHideSusMountsForAllProcs(context) hideSusMountsForAllProcs = SuSFSManager.getHideSusMountsForAllProcs(context)
enableHideBl = SuSFSManager.getEnableHideBl(context) enableHideBl = SuSFSManager.getEnableHideBl(context)
enableCleanupResidue = SuSFSManager.getEnableCleanupResidue(context) enableCleanupResidue = SuSFSManager.getEnableCleanupResidue(context)
umountForZygoteIsoService = SuSFSManager.getUmountForZygoteIsoService(context)
} }
isLoading = false isLoading = false
showRestoreConfirmDialog = false showRestoreConfirmDialog = false
@@ -1171,6 +1175,7 @@ fun SuSFSConfigScreen(
SuSFSTab.TRY_UMOUNT -> { SuSFSTab.TRY_UMOUNT -> {
TryUmountContent( TryUmountContent(
tryUmounts = tryUmounts, tryUmounts = tryUmounts,
umountForZygoteIsoService = umountForZygoteIsoService,
isLoading = isLoading, isLoading = isLoading,
onAddUmount = { showAddUmountDialog = true }, onAddUmount = { showAddUmountDialog = true },
onRunUmount = { showRunUmountDialog = true }, onRunUmount = { showRunUmountDialog = true },
@@ -1186,9 +1191,20 @@ fun SuSFSConfigScreen(
onEditUmount = { umountEntry -> onEditUmount = { umountEntry ->
editingUmount = umountEntry editingUmount = umountEntry
showAddUmountDialog = true showAddUmountDialog = true
},
onToggleUmountForZygoteIsoService = { enabled ->
coroutineScope.launch {
isLoading = true
val success = SuSFSManager.setUmountForZygoteIsoService(context, enabled)
if (success) {
umountForZygoteIsoService = enabled
}
isLoading = false
}
} }
) )
} }
SuSFSTab.KSTAT_CONFIG -> { SuSFSTab.KSTAT_CONFIG -> {
KstatConfigContent( KstatConfigContent(
kstatConfigs = kstatConfigs, kstatConfigs = kstatConfigs,

View File

@@ -41,6 +41,7 @@ object SuSFSManager {
private const val KEY_HIDE_SUS_MOUNTS_FOR_ALL_PROCS = "hide_sus_mounts_for_all_procs" private const val KEY_HIDE_SUS_MOUNTS_FOR_ALL_PROCS = "hide_sus_mounts_for_all_procs"
private const val KEY_ENABLE_CLEANUP_RESIDUE = "enable_cleanup_residue" private const val KEY_ENABLE_CLEANUP_RESIDUE = "enable_cleanup_residue"
private const val KEY_ENABLE_HIDE_BL = "enable_hide_bl" private const val KEY_ENABLE_HIDE_BL = "enable_hide_bl"
private const val KEY_UMOUNT_FOR_ZYGOTE_ISO_SERVICE = "umount_for_zygote_iso_service"
// 常量 // 常量
@@ -134,7 +135,8 @@ object SuSFSManager {
val hideSusMountsForAllProcs: Boolean, val hideSusMountsForAllProcs: Boolean,
val support158: Boolean, val support158: Boolean,
val enableHideBl: Boolean, val enableHideBl: Boolean,
val enableCleanupResidue: Boolean val enableCleanupResidue: Boolean,
val umountForZygoteIsoService: Boolean
) { ) {
/** /**
* 检查是否有需要自启动的配置 * 检查是否有需要自启动的配置
@@ -229,6 +231,7 @@ object SuSFSManager {
support158 = isSusVersion_1_5_8(), support158 = isSusVersion_1_5_8(),
enableHideBl = getEnableHideBl(context), enableHideBl = getEnableHideBl(context),
enableCleanupResidue = getEnableCleanupResidue(context), enableCleanupResidue = getEnableCleanupResidue(context),
umountForZygoteIsoService = getUmountForZygoteIsoService(context),
) )
} }
@@ -291,6 +294,14 @@ object SuSFSManager {
fun getEnableCleanupResidue(context: Context): Boolean = fun getEnableCleanupResidue(context: Context): Boolean =
getPrefs(context).getBoolean(KEY_ENABLE_CLEANUP_RESIDUE, false) getPrefs(context).getBoolean(KEY_ENABLE_CLEANUP_RESIDUE, false)
// Zygote隔离服务卸载控制
fun saveUmountForZygoteIsoService(context: Context, enabled: Boolean) =
getPrefs(context).edit { putBoolean(KEY_UMOUNT_FOR_ZYGOTE_ISO_SERVICE, enabled) }
fun getUmountForZygoteIsoService(context: Context): Boolean =
getPrefs(context).getBoolean(KEY_UMOUNT_FOR_ZYGOTE_ISO_SERVICE, false)
// 路径和配置管理 // 路径和配置管理
fun saveSusPaths(context: Context, paths: Set<String>) = fun saveSusPaths(context: Context, paths: Set<String>) =
getPrefs(context).edit { putStringSet(KEY_SUS_PATHS, paths) } getPrefs(context).edit { putStringSet(KEY_SUS_PATHS, paths) }
@@ -355,7 +366,8 @@ object SuSFSManager {
KEY_ADD_KSTAT_PATHS to getAddKstatPaths(context), KEY_ADD_KSTAT_PATHS to getAddKstatPaths(context),
KEY_HIDE_SUS_MOUNTS_FOR_ALL_PROCS to getHideSusMountsForAllProcs(context), KEY_HIDE_SUS_MOUNTS_FOR_ALL_PROCS to getHideSusMountsForAllProcs(context),
KEY_ENABLE_HIDE_BL to getEnableHideBl(context), KEY_ENABLE_HIDE_BL to getEnableHideBl(context),
KEY_ENABLE_CLEANUP_RESIDUE to getEnableCleanupResidue(context) KEY_ENABLE_CLEANUP_RESIDUE to getEnableCleanupResidue(context),
KEY_UMOUNT_FOR_ZYGOTE_ISO_SERVICE to getUmountForZygoteIsoService(context),
) )
} }
@@ -880,6 +892,29 @@ object SuSFSManager {
suspend fun runTryUmount(context: Context): Boolean = executeSusfsCommand(context, "run_try_umount") suspend fun runTryUmount(context: Context): Boolean = executeSusfsCommand(context, "run_try_umount")
// Zygote隔离服务卸载控制
suspend fun setUmountForZygoteIsoService(context: Context, enabled: Boolean): Boolean {
if (!isSusVersion_1_5_8()) {
return false
}
val result = executeSusfsCommandWithOutput(context, "umount_for_zygote_iso_service ${if (enabled) 1 else 0}")
val success = result.isSuccess && result.output.isEmpty()
if (success) {
saveUmountForZygoteIsoService(context, enabled)
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
}
// 添加kstat配置 // 添加kstat配置
suspend fun addKstatStatically(context: Context, path: String, ino: String, dev: String, nlink: String, suspend fun addKstatStatically(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,

View File

@@ -372,10 +372,23 @@ object ScriptGenerator {
appendLine() appendLine()
} }
generateUmountZygoteIsoServiceSection(config.umountForZygoteIsoService, config.support158)
appendLine("echo \"$(get_current_time): Post-FS-Data脚本执行完成\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): Post-FS-Data脚本执行完成\" >> \"${'$'}LOG_FILE\"")
} }
} }
// 添加新的生成方法
private fun StringBuilder.generateUmountZygoteIsoServiceSection(umountForZygoteIsoService: Boolean, support158: Boolean) {
if (support158) {
appendLine("# 设置Zygote隔离服务卸载状态")
val umountValue = if (umountForZygoteIsoService) 1 else 0
appendLine("\"${'$'}SUSFS_BIN\" umount_for_zygote_iso_service $umountValue")
appendLine("echo \"$(get_current_time): Zygote隔离服务卸载设置为: ${if (umountForZygoteIsoService) "启用" else "禁用"}\" >> \"${'$'}LOG_FILE\"")
appendLine()
}
}
/** /**
* 生成post-mount.sh脚本内容 * 生成post-mount.sh脚本内容
*/ */

View File

@@ -553,4 +553,8 @@
<string name="kstat_config_updated">Kstat 配置更新</string> <string name="kstat_config_updated">Kstat 配置更新</string>
<string name="kstat_path_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_description">启用此选项将在系统启动时卸载Zygote隔离服务挂载点</string>
<string name="umount_zygote_iso_service_enabled">Zygote隔离服务卸载已启用</string>
<string name="umount_zygote_iso_service_disabled">Zygote隔离服务卸载已禁用</string>
</resources> </resources>

View File

@@ -555,4 +555,8 @@
<string name="kstat_config_updated">Kstat config update</string> <string name="kstat_config_updated">Kstat config update</string>
<string name="kstat_path_updated">Kstat path 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_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>
</resources> </resources>