mamager: fix the crash of Superuser in multi-user environments

This commit is contained in:
ShirkNeko
2025-11-16 14:03:06 +08:00
parent 3a2d55237d
commit 19a67fb76c
3 changed files with 8 additions and 90 deletions

View File

@@ -2,45 +2,15 @@ package com.sukisu.ultra.ui.screen
import android.annotation.SuppressLint import android.annotation.SuppressLint
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.*
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandHorizontally import androidx.compose.animation.expandHorizontally
import androidx.compose.animation.expandVertically import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn import androidx.compose.animation.*
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.animation.shrinkHorizontally
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
@@ -52,34 +22,8 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.filled.Archive import androidx.compose.material3.*
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.GridView
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.RestoreFromTrash
import androidx.compose.material.icons.filled.Save
import androidx.compose.material.icons.filled.SearchOff
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material.icons.filled.VisibilityOff
import androidx.compose.material3.Checkbox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilterChip
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SheetState
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.PullToRefreshBox
@@ -383,7 +327,7 @@ private fun SuperUserContent(
.nestedScroll(scrollBehavior.nestedScrollConnection) .nestedScroll(scrollBehavior.nestedScrollConnection)
) { ) {
filteredAndSortedAppGroups.forEachIndexed { _, appGroup -> filteredAndSortedAppGroups.forEachIndexed { _, appGroup ->
item(key = appGroup.uid) { item(key = "${appGroup.uid}-${appGroup.mainApp.packageName}") {
AppGroupItem( AppGroupItem(
appGroup = appGroup, appGroup = appGroup,
isSelected = appGroup.packageNames.any { viewModel.selectedApps.contains(it) }, isSelected = appGroup.packageNames.any { viewModel.selectedApps.contains(it) },
@@ -413,7 +357,7 @@ private fun SuperUserContent(
) )
} }
items(appGroup.apps, key = { it.packageName }) { app -> items(appGroup.apps, key = { "${it.packageName}-${it.uid}" }) { app ->
AnimatedVisibility( AnimatedVisibility(
visible = expandedGroups.value.contains(appGroup.uid) && appGroup.apps.size > 1, visible = expandedGroups.value.contains(appGroup.uid) && appGroup.apps.size > 1,
enter = fadeIn() + expandVertically(), enter = fadeIn() + expandVertically(),

View File

@@ -85,11 +85,6 @@ class SuperUserViewModel : ViewModel() {
) : Parcelable { ) : Parcelable {
val packageName: String get() = packageInfo.packageName val packageName: String get() = packageInfo.packageName
val uid: Int get() = packageInfo.applicationInfo!!.uid val uid: Int get() = packageInfo.applicationInfo!!.uid
val allowSu: Boolean get() = profile?.allowSu == true
val hasCustomProfile: Boolean
get() = profile?.let {
if (it.allowSu) !it.rootUseDefault else !it.nonRootUseDefault
} ?: false
} }
@Parcelize @Parcelize
@@ -173,28 +168,6 @@ class SuperUserViewModel : ViewModel() {
prefs.edit { putString(KEY_CURRENT_SORT_TYPE, newSortType.persistKey) } prefs.edit { putString(KEY_CURRENT_SORT_TYPE, newSortType.persistKey) }
} }
private val sortedList by derivedStateOf {
val comparator = compareBy<AppInfo> {
when {
it.allowSu -> 0
it.hasCustomProfile -> 1
else -> 2
}
}.then(compareBy(Collator.getInstance(Locale.getDefault()), AppInfo::label))
apps.sortedWith(comparator).also { isRefreshing = false }
}
val appList by derivedStateOf {
sortedList.filter {
it.label.contains(search, true) ||
it.packageName.contains(search, true) ||
HanziToPinyin.getInstance().toPinyinString(it.label).contains(search, true)
}.filter {
it.uid == 2000 || showSystemApps ||
it.packageInfo.applicationInfo!!.flags.and(ApplicationInfo.FLAG_SYSTEM) == 0
}
}
fun toggleBatchMode() { fun toggleBatchMode() {
showBatchActions = !showBatchActions showBatchActions = !showBatchActions
if (!showBatchActions) clearSelection() if (!showBatchActions) clearSelection()

View File

@@ -760,4 +760,5 @@ Important Note:\n
<string name="apply_config">Apply Configuration</string> <string name="apply_config">Apply Configuration</string>
<string name="config_applied">Configuration applied to kernel</string> <string name="config_applied">Configuration applied to kernel</string>
<string name="mnt_detach">MNT_DETACH</string> <string name="mnt_detach">MNT_DETACH</string>
<string name="group_contains_apps">Contains %d apps</string>
</resources> </resources>