summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt86
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt21
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/legacyhelper/data/LegacyUserDataHelper.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/shared/model/UserActionModel.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt10
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorKosmos.kt1
12 files changed, 136 insertions, 60 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 2845f6a2983a..e75f60736435 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -507,8 +507,8 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
0 /* flags */);
users.add(new UserRecord(info, null, false /* isGuest */, false /* isCurrent */,
false /* isAddUser */, false /* isRestricted */, true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */, null /* enforcedAdmin */,
- false /* isManageUsers */));
+ false /* isAddSupervisedUser */, false /* isSignOut */,
+ null /* enforcedAdmin */, false /* isManageUsers */));
}
return users;
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt
index 3eada258f616..07706414393b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt
@@ -27,6 +27,8 @@ import android.graphics.drawable.Drawable
import android.os.Process
import android.os.UserHandle
import android.os.UserManager
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -34,6 +36,7 @@ import com.android.internal.logging.UiEventLogger
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.Flags as AConfigFlags
+import com.android.systemui.Flags.FLAG_USER_SWITCHER_ADD_SIGN_OUT_OPTION
import com.android.systemui.GuestResetOrExitSessionReceiver
import com.android.systemui.GuestResumeSessionReceiver
import com.android.systemui.SysuiTestCase
@@ -68,6 +71,7 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertNotNull
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runCurrent
@@ -101,10 +105,13 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
@Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
@Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Mock private lateinit var userLogoutInteractor: UserLogoutInteractor
private val kosmos = testKosmos()
+ private val logoutEnabledStateFlow = MutableStateFlow<Boolean>(false)
private val testScope = kosmos.testScope
private lateinit var spyContext: Context
+
private lateinit var userRepository: FakeUserRepository
private lateinit var keyguardReply: KeyguardInteractorFactory.WithDependencies
private lateinit var keyguardRepository: FakeKeyguardRepository
@@ -118,6 +125,8 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
whenever(manager.getUserIcon(anyInt())).thenReturn(ICON)
whenever(manager.canAddMoreUsers(any())).thenReturn(true)
+ whenever(userLogoutInteractor.isLogoutEnabled).thenReturn(logoutEnabledStateFlow)
+
overrideResource(com.android.settingslib.R.drawable.ic_account_circle, GUEST_ICON)
overrideResource(R.dimen.max_avatar_size, 10)
overrideResource(
@@ -493,6 +502,42 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(FLAG_USER_SWITCHER_ADD_SIGN_OUT_OPTION)
+ fun actions_logoutEnabled_flagDisabled_signOutIsNotShown() {
+ createUserInteractor()
+ testScope.runTest {
+ val userInfos = createUserInfos(count = 1, includeGuest = false)
+ userRepository.setUserInfos(userInfos)
+ userRepository.setSelectedUserInfo(userInfos[0])
+ userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = false))
+ keyguardRepository.setKeyguardShowing(true)
+ logoutEnabledStateFlow.value = true
+
+ val value = collectLastValue(underTest.actions)
+
+ assertThat(value()).isEqualTo(emptyList<UserActionModel>())
+ }
+ }
+
+ @Test
+ @EnableFlags(FLAG_USER_SWITCHER_ADD_SIGN_OUT_OPTION)
+ fun actions_logoutEnabled_flagEnabled_signOutIsShown() {
+ createUserInteractor()
+ testScope.runTest {
+ val userInfos = createUserInfos(count = 1, includeGuest = false)
+ userRepository.setUserInfos(userInfos)
+ userRepository.setSelectedUserInfo(userInfos[0])
+ userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = false))
+ keyguardRepository.setKeyguardShowing(true)
+ logoutEnabledStateFlow.value = true
+
+ val value = collectLastValue(underTest.actions)
+
+ assertThat(value()).isEqualTo(listOf(UserActionModel.SIGN_OUT))
+ }
+ }
+
+ @Test
fun executeAction_addUser_dismissesDialogAndStartsActivity() {
createUserInteractor()
testScope.runTest {
@@ -569,14 +614,23 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
verify(uiEventLogger, times(1))
.log(MultiUserActionsEvent.CREATE_GUEST_FROM_USER_SWITCHER)
assertThat(dialogRequests)
- .contains(
- ShowDialogRequestModel.ShowUserCreationDialog(isGuest = true),
- )
+ .contains(ShowDialogRequestModel.ShowUserCreationDialog(isGuest = true))
verify(activityManager).switchUser(guestUserInfo.id)
}
}
@Test
+ fun executeAction_signOut() {
+ createUserInteractor()
+ testScope.runTest {
+ underTest.executeAction(UserActionModel.SIGN_OUT)
+ runCurrent()
+
+ verify(userLogoutInteractor).logOut()
+ }
+ }
+
+ @Test
fun selectUser_alreadySelectedGuestReSelected_exitGuestDialog() {
createUserInteractor()
testScope.runTest {
@@ -739,7 +793,7 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
spyContext,
- Intent(Intent.ACTION_LOCALE_CHANGED)
+ Intent(Intent.ACTION_LOCALE_CHANGED),
)
runCurrent()
@@ -972,7 +1026,7 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
50,
"Work Profile",
/* iconPath= */ "",
- /* flags= */ UserInfo.FLAG_MANAGED_PROFILE
+ /* flags= */ UserInfo.FLAG_MANAGED_PROFILE,
)
)
userRepository.setUserInfos(userInfos)
@@ -1010,7 +1064,7 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
userRepository.setSettings(
UserSwitcherSettingsModel(
isUserSwitcherEnabled = true,
- isAddUsersFromLockscreen = true
+ isAddUsersFromLockscreen = true,
)
)
@@ -1034,7 +1088,7 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
userRepository.setSettings(
UserSwitcherSettingsModel(
isUserSwitcherEnabled = true,
- isAddUsersFromLockscreen = true
+ isAddUsersFromLockscreen = true,
)
)
@@ -1068,7 +1122,7 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
whenever(
manager.hasUserRestrictionForUser(
UserManager.DISALLOW_ADD_USER,
- UserHandle.of(id)
+ UserHandle.of(id),
)
)
.thenReturn(true)
@@ -1170,7 +1224,7 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
whenever(
manager.hasUserRestrictionForUser(
UserManager.DISALLOW_ADD_USER,
- UserHandle.of(0)
+ UserHandle.of(0),
)
)
.thenReturn(true)
@@ -1195,7 +1249,7 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
model = model,
id = index,
isSelected = index == selectedIndex,
- isGuest = includeGuest && index == count - 1
+ isGuest = includeGuest && index == count - 1,
)
}
}
@@ -1263,14 +1317,12 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
assertThat(record.isSwitchToEnabled).isEqualTo(isSwitchToEnabled)
}
- private fun assertRecordForAction(
- record: UserRecord,
- type: UserActionModel,
- ) {
+ private fun assertRecordForAction(record: UserRecord, type: UserActionModel) {
assertThat(record.isGuest).isEqualTo(type == UserActionModel.ENTER_GUEST_MODE)
assertThat(record.isAddUser).isEqualTo(type == UserActionModel.ADD_USER)
assertThat(record.isAddSupervisedUser)
.isEqualTo(type == UserActionModel.ADD_SUPERVISED_USER)
+ assertThat(record.isSignOut).isEqualTo(type === UserActionModel.SIGN_OUT)
}
private fun createUserInteractor(startAsProcessUser: Boolean = true) {
@@ -1317,13 +1369,11 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
featureFlags = kosmos.fakeFeatureFlagsClassic,
userRestrictionChecker = mock(),
processWrapper = kosmos.processWrapper,
+ userLogoutInteractor = userLogoutInteractor,
)
}
- private fun createUserInfos(
- count: Int,
- includeGuest: Boolean,
- ): List<UserInfo> {
+ private fun createUserInfos(count: Int, includeGuest: Boolean): List<UserInfo> {
return (0 until count).map { index ->
val isGuest = includeGuest && index == count - 1
createUserInfo(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
index 5d51c6d16c5a..d51e66d6f3b0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
@@ -44,9 +44,12 @@ import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.user.domain.interactor.GuestUserInteractor
import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode
import com.android.systemui.user.domain.interactor.RefreshUsersScheduler
+import com.android.systemui.user.domain.interactor.UserLogoutInteractor
import com.android.systemui.user.domain.interactor.UserSwitcherInteractor
import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.toList
@@ -78,13 +81,13 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
@Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
@Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Mock private lateinit var userLogoutInteractor: UserLogoutInteractor
private lateinit var underTest: StatusBarUserChipViewModel
private val userRepository = FakeUserRepository()
private lateinit var guestUserInteractor: GuestUserInteractor
private lateinit var refreshUsersScheduler: RefreshUsersScheduler
-
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
@@ -92,6 +95,9 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
+ val logoutEnabledStateFlow = MutableStateFlow<Boolean>(false)
+ whenever(userLogoutInteractor.isLogoutEnabled).thenReturn(logoutEnabledStateFlow)
+
doAnswer { invocation ->
val userId = invocation.arguments[0] as Int
when (userId) {
@@ -251,9 +257,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
headlessSystemUserMode = headlessSystemUserMode,
applicationScope = testScope.backgroundScope,
telephonyInteractor =
- TelephonyInteractor(
- repository = FakeTelephonyRepository(),
- ),
+ TelephonyInteractor(repository = FakeTelephonyRepository()),
broadcastDispatcher = fakeBroadcastDispatcher,
keyguardUpdateMonitor = keyguardUpdateMonitor,
backgroundDispatcher = testDispatcher,
@@ -263,7 +267,8 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
guestUserInteractor = guestUserInteractor,
uiEventLogger = uiEventLogger,
userRestrictionChecker = mock(),
- processWrapper = ProcessWrapperFake(activityManager)
+ processWrapper = ProcessWrapperFake(activityManager),
+ userLogoutInteractor = userLogoutInteractor,
)
)
}
@@ -293,7 +298,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
USER_NAME_0.text!!,
/* iconPath */ "",
/* flags */ UserInfo.FLAG_FULL,
- /* userType */ UserManager.USER_TYPE_FULL_SYSTEM
+ /* userType */ UserManager.USER_TYPE_FULL_SYSTEM,
)
private val USER_1 =
@@ -302,7 +307,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
USER_NAME_1.text!!,
/* iconPath */ "",
/* flags */ UserInfo.FLAG_FULL,
- /* userType */ UserManager.USER_TYPE_FULL_SYSTEM
+ /* userType */ UserManager.USER_TYPE_FULL_SYSTEM,
)
private val USER_2 =
@@ -311,7 +316,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
USER_NAME_2.text!!,
/* iconPath */ "",
/* flags */ UserInfo.FLAG_FULL,
- /* userType */ UserManager.USER_TYPE_FULL_SYSTEM
+ /* userType */ UserManager.USER_TYPE_FULL_SYSTEM,
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index 8ff088f5d29b..087ccb83afe5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -44,6 +44,7 @@ import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.user.domain.interactor.GuestUserInteractor
import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode
import com.android.systemui.user.domain.interactor.RefreshUsersScheduler
+import com.android.systemui.user.domain.interactor.UserLogoutInteractor
import com.android.systemui.user.domain.interactor.UserSwitcherInteractor
import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper
import com.android.systemui.user.shared.model.UserActionModel
@@ -51,6 +52,7 @@ import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
@@ -79,6 +81,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
@Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
@Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Mock private lateinit var userLogoutInteractor: UserLogoutInteractor
private lateinit var underTest: UserSwitcherViewModel
@@ -94,6 +97,10 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
whenever(manager.canAddMoreUsers(any())).thenReturn(true)
whenever(manager.getUserSwitchability(any()))
.thenReturn(UserManager.SWITCHABILITY_STATUS_OK)
+
+ val logoutEnabledStateFlow = MutableStateFlow<Boolean>(false)
+ whenever(userLogoutInteractor.isLogoutEnabled).thenReturn(logoutEnabledStateFlow)
+
overrideResource(
com.android.internal.R.string.config_supervisedUserCreationPackage,
SUPERVISED_USER_CREATION_PACKAGE,
@@ -113,15 +120,11 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
UserInfo.FLAG_ADMIN or
UserInfo.FLAG_FULL,
UserManager.USER_TYPE_FULL_SYSTEM,
- ),
+ )
)
userRepository.setUserInfos(userInfos)
userRepository.setSelectedUserInfo(userInfos[0])
- userRepository.setSettings(
- UserSwitcherSettingsModel(
- isUserSwitcherEnabled = true,
- )
- )
+ userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
}
val refreshUsersScheduler =
@@ -163,9 +166,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
headlessSystemUserMode = headlessSystemUserMode,
applicationScope = testScope.backgroundScope,
telephonyInteractor =
- TelephonyInteractor(
- repository = FakeTelephonyRepository(),
- ),
+ TelephonyInteractor(repository = FakeTelephonyRepository()),
broadcastDispatcher = fakeBroadcastDispatcher,
keyguardUpdateMonitor = keyguardUpdateMonitor,
backgroundDispatcher = testDispatcher,
@@ -175,7 +176,8 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
guestUserInteractor = guestUserInteractor,
uiEventLogger = uiEventLogger,
userRestrictionChecker = mock(),
- processWrapper = ProcessWrapperFake(activityManager)
+ processWrapper = ProcessWrapperFake(activityManager),
+ userLogoutInteractor = userLogoutInteractor,
),
guestUserInteractor = guestUserInteractor,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt
index 4c6374b75f82..efab21fd9364 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt
@@ -37,7 +37,7 @@ protected constructor(
protected open val users: List<UserRecord>
get() = controller.users.filter {
(!controller.isKeyguardShowing || !it.isRestricted) &&
- (controller.isUserSwitcherEnabled || it.isCurrent)
+ (controller.isUserSwitcherEnabled || it.isCurrent || it.isSignOut)
}
init {
@@ -109,6 +109,7 @@ protected constructor(
item.isAddUser,
item.isGuest,
item.isAddSupervisedUser,
+ item.isSignOut,
isTablet,
item.isManageUsers,
)
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt b/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt
index d4fb5634bd1d..e16a51a6f6fa 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt
@@ -42,6 +42,8 @@ data class UserRecord(
@JvmField val isSwitchToEnabled: Boolean = false,
/** Whether this record represents an option to add another supervised user to the device. */
@JvmField val isAddSupervisedUser: Boolean = false,
+ /** Whether this record represents an option to sign out of the current user. */
+ @JvmField val isSignOut: Boolean = false,
/**
* An enforcing admin, if the user action represented by this record is disabled by the admin.
* If not disabled, this is `null`.
@@ -49,7 +51,7 @@ data class UserRecord(
@JvmField val enforcedAdmin: RestrictedLockUtils.EnforcedAdmin? = null,
/** Whether this record is to go to the Settings page to manage users. */
- @JvmField val isManageUsers: Boolean = false
+ @JvmField val isManageUsers: Boolean = false,
) {
/** Returns a new instance of [UserRecord] with its [isCurrent] set to the given value. */
fun copyWithIsCurrent(isCurrent: Boolean): UserRecord {
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt
index 163288b25b28..b82aefc1ac1c 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt
@@ -38,6 +38,7 @@ import com.android.internal.util.UserIcons
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.Flags.switchUserOnBg
+import com.android.systemui.Flags.userSwitcherAddSignOutOption
import com.android.systemui.SystemUISecondaryUserService
import com.android.systemui.animation.Expandable
import com.android.systemui.broadcast.BroadcastDispatcher
@@ -110,6 +111,7 @@ constructor(
private val uiEventLogger: UiEventLogger,
private val userRestrictionChecker: UserRestrictionChecker,
private val processWrapper: ProcessWrapper,
+ private val userLogoutInteractor: UserLogoutInteractor,
) {
/**
* Defines interface for classes that can be notified when the state of users on the device is
@@ -242,6 +244,12 @@ constructor(
) {
add(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
}
+ if (
+ userSwitcherAddSignOutOption() &&
+ userLogoutInteractor.isLogoutEnabled.value
+ ) {
+ add(UserActionModel.SIGN_OUT)
+ }
}
}
.flowOn(backgroundDispatcher)
@@ -261,7 +269,8 @@ constructor(
action = it,
selectedUserId = selectedUserInfo.id,
isRestricted =
- it != UserActionModel.ENTER_GUEST_MODE &&
+ it != UserActionModel.SIGN_OUT &&
+ it != UserActionModel.ENTER_GUEST_MODE &&
it != UserActionModel.NAVIGATE_TO_USER_MANAGEMENT &&
!settings.isAddUsersFromLockscreen,
)
@@ -499,6 +508,10 @@ constructor(
Intent(Settings.ACTION_USER_SETTINGS),
/* dismissShade= */ true,
)
+ UserActionModel.SIGN_OUT -> {
+ dismissDialog()
+ applicationScope.launch { userLogoutInteractor.logOut() }
+ }
}
}
@@ -583,9 +596,10 @@ constructor(
actionType = action,
isRestricted = isRestricted,
isSwitchToEnabled =
- canSwitchUsers(selectedUserId = selectedUserId, isAction = true) &&
- // If the user is auto-created is must not be currently resetting.
- !(isGuestUserAutoCreated && isGuestUserResetting),
+ action == UserActionModel.SIGN_OUT ||
+ (canSwitchUsers(selectedUserId = selectedUserId, isAction = true) &&
+ // If the user is auto-created is must not be currently resetting.
+ !(isGuestUserAutoCreated && isGuestUserResetting)),
userRestrictionChecker = userRestrictionChecker,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/legacyhelper/data/LegacyUserDataHelper.kt b/packages/SystemUI/src/com/android/systemui/user/legacyhelper/data/LegacyUserDataHelper.kt
index 80139bd6ac0c..23ca4ceda2de 100644
--- a/packages/SystemUI/src/com/android/systemui/user/legacyhelper/data/LegacyUserDataHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/legacyhelper/data/LegacyUserDataHelper.kt
@@ -74,6 +74,7 @@ object LegacyUserDataHelper {
isGuest = actionType == UserActionModel.ENTER_GUEST_MODE,
isAddUser = actionType == UserActionModel.ADD_USER,
isAddSupervisedUser = actionType == UserActionModel.ADD_SUPERVISED_USER,
+ isSignOut = actionType == UserActionModel.SIGN_OUT,
isRestricted = isRestricted,
isSwitchToEnabled = isSwitchToEnabled,
enforcedAdmin =
@@ -94,6 +95,7 @@ object LegacyUserDataHelper {
record.isAddSupervisedUser -> UserActionModel.ADD_SUPERVISED_USER
record.isGuest -> UserActionModel.ENTER_GUEST_MODE
record.isManageUsers -> UserActionModel.NAVIGATE_TO_USER_MANAGEMENT
+ record.isSignOut -> UserActionModel.SIGN_OUT
else -> error("Not a known action: $record")
}
}
@@ -105,15 +107,14 @@ object LegacyUserDataHelper {
private fun getEnforcedAdmin(
context: Context,
selectedUserId: Int,
- userRestrictionChecker: UserRestrictionChecker
+ userRestrictionChecker: UserRestrictionChecker,
): EnforcedAdmin? {
val admin =
userRestrictionChecker.checkIfRestrictionEnforced(
context,
UserManager.DISALLOW_ADD_USER,
selectedUserId,
- )
- ?: return null
+ ) ?: return null
return if (
!userRestrictionChecker.hasBaseUserRestriction(
@@ -145,11 +146,6 @@ object LegacyUserDataHelper {
val unscaledOrNull = manager.getUserIcon(userInfo.id) ?: return null
val avatarSize = context.resources.getDimensionPixelSize(R.dimen.max_avatar_size)
- return Bitmap.createScaledBitmap(
- unscaledOrNull,
- avatarSize,
- avatarSize,
- /* filter= */ true,
- )
+ return Bitmap.createScaledBitmap(unscaledOrNull, avatarSize, avatarSize, /* filter= */ true)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt b/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt
index 09cef1ed64fc..e7a3c23e9119 100644
--- a/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt
@@ -41,6 +41,7 @@ object LegacyUserUiHelper {
isAddUser: Boolean,
isGuest: Boolean,
isAddSupervisedUser: Boolean,
+ isSignOut: Boolean,
isTablet: Boolean = false,
isManageUsers: Boolean,
): Int {
@@ -52,6 +53,8 @@ object LegacyUserUiHelper {
com.android.settingslib.R.drawable.ic_account_circle
} else if (isAddSupervisedUser) {
com.android.settingslib.R.drawable.ic_add_supervised_user
+ } else if (isSignOut) {
+ com.android.internal.R.drawable.ic_logout
} else if (isManageUsers) {
R.drawable.ic_manage_users
} else {
@@ -81,6 +84,7 @@ object LegacyUserUiHelper {
isGuestUserResetting = isGuestUserResetting,
isAddUser = record.isAddUser,
isAddSupervisedUser = record.isAddSupervisedUser,
+ isSignOut = record.isSignOut,
isTablet = isTablet,
isManageUsers = record.isManageUsers,
)
@@ -111,10 +115,11 @@ object LegacyUserUiHelper {
isGuestUserResetting: Boolean,
isAddUser: Boolean,
isAddSupervisedUser: Boolean,
+ isSignOut: Boolean,
isTablet: Boolean = false,
isManageUsers: Boolean,
): Int {
- check(isGuest || isAddUser || isAddSupervisedUser || isManageUsers)
+ check(isGuest || isAddUser || isAddSupervisedUser || isManageUsers || isSignOut)
return when {
isGuest && isGuestUserAutoCreated && isGuestUserResetting ->
@@ -124,6 +129,7 @@ object LegacyUserUiHelper {
isGuest -> com.android.internal.R.string.guest_name
isAddUser -> com.android.settingslib.R.string.user_add_user
isAddSupervisedUser -> R.string.add_user_supervised
+ isSignOut -> com.android.internal.R.string.global_action_logout
isManageUsers -> R.string.manage_users
else -> error("This should never happen!")
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/shared/model/UserActionModel.kt b/packages/SystemUI/src/com/android/systemui/user/shared/model/UserActionModel.kt
index 823bf74dc0f0..7f67d7691bf5 100644
--- a/packages/SystemUI/src/com/android/systemui/user/shared/model/UserActionModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/shared/model/UserActionModel.kt
@@ -22,4 +22,5 @@ enum class UserActionModel {
ADD_USER,
ADD_SUPERVISED_USER,
NAVIGATE_TO_USER_MANAGEMENT,
+ SIGN_OUT,
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
index 4089889f4b1e..2e3af1c7ad00 100644
--- a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
@@ -129,9 +129,7 @@ constructor(
cancelButtonClicked || executedActionFinish || userSwitched
}
- private fun toViewModel(
- model: UserModel,
- ): UserViewModel {
+ private fun toViewModel(model: UserModel): UserViewModel {
return UserViewModel(
viewKey = model.id,
name =
@@ -152,14 +150,13 @@ constructor(
)
}
- private fun toViewModel(
- model: UserActionModel,
- ): UserActionViewModel {
+ private fun toViewModel(model: UserActionModel): UserActionViewModel {
return UserActionViewModel(
viewKey = model.ordinal.toLong(),
iconResourceId =
LegacyUserUiHelper.getUserSwitcherActionIconResourceId(
isAddSupervisedUser = model == UserActionModel.ADD_SUPERVISED_USER,
+ isSignOut = model == UserActionModel.SIGN_OUT,
isAddUser = model == UserActionModel.ADD_USER,
isGuest = model == UserActionModel.ENTER_GUEST_MODE,
isManageUsers = model == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
@@ -171,6 +168,7 @@ constructor(
isGuestUserAutoCreated = guestUserInteractor.isGuestUserAutoCreated,
isGuestUserResetting = guestUserInteractor.isGuestUserResetting,
isAddSupervisedUser = model == UserActionModel.ADD_SUPERVISED_USER,
+ isSignOut = model == UserActionModel.SIGN_OUT,
isAddUser = model == UserActionModel.ADD_USER,
isManageUsers = model == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
isTablet = true,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorKosmos.kt
index 1504df4ef6d0..6767300a22bc 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorKosmos.kt
@@ -55,5 +55,6 @@ val Kosmos.userSwitcherInteractor by
uiEventLogger = uiEventLogger,
userRestrictionChecker = userRestrictionChecker,
processWrapper = processWrapper,
+ userLogoutInteractor = userLogoutInteractor,
)
}