Merge "When in guest mode, see "Exit guest" in user switcher" into tm-qpr-dev am: 1a38ab1cc0

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20590287

Change-Id: I3f45f7f8b856c464bee2450c531d92dad9cf1de6
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Brad Hinegardner
2022-12-02 16:33:21 +00:00
committed by Automerger Merge Worker
2 changed files with 114 additions and 34 deletions

View File

@@ -19,6 +19,8 @@ package com.android.systemui.user.ui.viewmodel
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import com.android.systemui.R
import com.android.systemui.common.shared.model.Text
import com.android.systemui.common.ui.drawable.CircularDrawable import com.android.systemui.common.ui.drawable.CircularDrawable
import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.user.domain.interactor.GuestUserInteractor import com.android.systemui.user.domain.interactor.GuestUserInteractor
@@ -144,7 +146,12 @@ private constructor(
): UserViewModel { ): UserViewModel {
return UserViewModel( return UserViewModel(
viewKey = model.id, viewKey = model.id,
name = model.name, name =
if (model.isGuest && model.isSelected) {
Text.Resource(R.string.guest_exit_quick_settings_button)
} else {
model.name
},
image = CircularDrawable(model.image), image = CircularDrawable(model.image),
isSelectionMarkerVisible = model.isSelected, isSelectionMarkerVisible = model.isSelected,
alpha = alpha =

View File

@@ -47,18 +47,14 @@ import com.android.systemui.user.shared.model.UserActionModel
import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.flow.toList import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.TestDispatcher import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.TestResult
import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@@ -89,7 +85,6 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
private lateinit var testDispatcher: TestDispatcher private lateinit var testDispatcher: TestDispatcher
private lateinit var testScope: TestScope private lateinit var testScope: TestScope
private lateinit var injectedScope: CoroutineScope
@Before @Before
fun setUp() { fun setUp() {
@@ -104,7 +99,6 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
testDispatcher = UnconfinedTestDispatcher() testDispatcher = UnconfinedTestDispatcher()
testScope = TestScope(testDispatcher) testScope = TestScope(testDispatcher)
injectedScope = CoroutineScope(testScope.coroutineContext + SupervisorJob())
userRepository = FakeUserRepository() userRepository = FakeUserRepository()
runBlocking { runBlocking {
userRepository.setSettings( userRepository.setSettings(
@@ -118,14 +112,14 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
powerRepository = FakePowerRepository() powerRepository = FakePowerRepository()
val refreshUsersScheduler = val refreshUsersScheduler =
RefreshUsersScheduler( RefreshUsersScheduler(
applicationScope = injectedScope, applicationScope = testScope.backgroundScope,
mainDispatcher = testDispatcher, mainDispatcher = testDispatcher,
repository = userRepository, repository = userRepository,
) )
val guestUserInteractor = val guestUserInteractor =
GuestUserInteractor( GuestUserInteractor(
applicationContext = context, applicationContext = context,
applicationScope = injectedScope, applicationScope = testScope.backgroundScope,
mainDispatcher = testDispatcher, mainDispatcher = testDispatcher,
backgroundDispatcher = testDispatcher, backgroundDispatcher = testDispatcher,
manager = manager, manager = manager,
@@ -154,7 +148,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
set(Flags.FULL_SCREEN_USER_SWITCHER, false) set(Flags.FULL_SCREEN_USER_SWITCHER, false)
}, },
manager = manager, manager = manager,
applicationScope = injectedScope, applicationScope = testScope.backgroundScope,
telephonyInteractor = telephonyInteractor =
TelephonyInteractor( TelephonyInteractor(
repository = FakeTelephonyRepository(), repository = FakeTelephonyRepository(),
@@ -175,7 +169,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
} }
@Test @Test
fun users() = selfCancelingTest { fun users() = testScope.runTest {
val userInfos = val userInfos =
listOf( listOf(
UserInfo( UserInfo(
@@ -210,26 +204,26 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
assertUserViewModel( assertUserViewModel(
viewModel = userViewModels.last()[0], viewModel = userViewModels.last()[0],
viewKey = 0, viewKey = 0,
name = "zero", name = Text.Loaded("zero"),
isSelectionMarkerVisible = true, isSelectionMarkerVisible = true,
) )
assertUserViewModel( assertUserViewModel(
viewModel = userViewModels.last()[1], viewModel = userViewModels.last()[1],
viewKey = 1, viewKey = 1,
name = "one", name = Text.Loaded("one"),
isSelectionMarkerVisible = false, isSelectionMarkerVisible = false,
) )
assertUserViewModel( assertUserViewModel(
viewModel = userViewModels.last()[2], viewModel = userViewModels.last()[2],
viewKey = 2, viewKey = 2,
name = "two", name = Text.Loaded("two"),
isSelectionMarkerVisible = false, isSelectionMarkerVisible = false,
) )
job.cancel() job.cancel()
} }
@Test @Test
fun `maximumUserColumns - few users`() = selfCancelingTest { fun `maximumUserColumns - few users`() = testScope.runTest {
setUsers(count = 2) setUsers(count = 2)
val values = mutableListOf<Int>() val values = mutableListOf<Int>()
val job = launch(testDispatcher) { underTest.maximumUserColumns.toList(values) } val job = launch(testDispatcher) { underTest.maximumUserColumns.toList(values) }
@@ -240,7 +234,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
} }
@Test @Test
fun `maximumUserColumns - many users`() = selfCancelingTest { fun `maximumUserColumns - many users`() = testScope.runTest {
setUsers(count = 5) setUsers(count = 5)
val values = mutableListOf<Int>() val values = mutableListOf<Int>()
val job = launch(testDispatcher) { underTest.maximumUserColumns.toList(values) } val job = launch(testDispatcher) { underTest.maximumUserColumns.toList(values) }
@@ -250,7 +244,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
} }
@Test @Test
fun `isOpenMenuButtonVisible - has actions - true`() = selfCancelingTest { fun `isOpenMenuButtonVisible - has actions - true`() = testScope.runTest {
setUsers(2) setUsers(2)
val isVisible = mutableListOf<Boolean>() val isVisible = mutableListOf<Boolean>()
@@ -261,7 +255,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
} }
@Test @Test
fun `isOpenMenuButtonVisible - no actions - false`() = selfCancelingTest { fun `isOpenMenuButtonVisible - no actions - false`() = testScope.runTest {
val userInfos = setUsers(2) val userInfos = setUsers(2)
userRepository.setSelectedUserInfo(userInfos[1]) userRepository.setSelectedUserInfo(userInfos[1])
keyguardRepository.setKeyguardShowing(true) keyguardRepository.setKeyguardShowing(true)
@@ -275,7 +269,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
} }
@Test @Test
fun menu() = selfCancelingTest { fun menu() = testScope.runTest {
val isMenuVisible = mutableListOf<Boolean>() val isMenuVisible = mutableListOf<Boolean>()
val job = launch(testDispatcher) { underTest.isMenuVisible.toList(isMenuVisible) } val job = launch(testDispatcher) { underTest.isMenuVisible.toList(isMenuVisible) }
assertThat(isMenuVisible.last()).isFalse() assertThat(isMenuVisible.last()).isFalse()
@@ -290,7 +284,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
} }
@Test @Test
fun `menu actions`() = selfCancelingTest { fun `menu actions`() = testScope.runTest {
setUsers(2) setUsers(2)
val actions = mutableListOf<List<UserActionViewModel>>() val actions = mutableListOf<List<UserActionViewModel>>()
val job = launch(testDispatcher) { underTest.menu.toList(actions) } val job = launch(testDispatcher) { underTest.menu.toList(actions) }
@@ -309,7 +303,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
} }
@Test @Test
fun `isFinishRequested - finishes when user is switched`() = selfCancelingTest { fun `isFinishRequested - finishes when user is switched`() = testScope.runTest {
val userInfos = setUsers(count = 2) val userInfos = setUsers(count = 2)
val isFinishRequested = mutableListOf<Boolean>() val isFinishRequested = mutableListOf<Boolean>()
val job = launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) } val job = launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) }
@@ -323,7 +317,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
} }
@Test @Test
fun `isFinishRequested - finishes when the screen turns off`() = selfCancelingTest { fun `isFinishRequested - finishes when the screen turns off`() = testScope.runTest {
setUsers(count = 2) setUsers(count = 2)
powerRepository.setInteractive(true) powerRepository.setInteractive(true)
val isFinishRequested = mutableListOf<Boolean>() val isFinishRequested = mutableListOf<Boolean>()
@@ -338,7 +332,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
} }
@Test @Test
fun `isFinishRequested - finishes when cancel button is clicked`() = selfCancelingTest { fun `isFinishRequested - finishes when cancel button is clicked`() = testScope.runTest {
setUsers(count = 2) setUsers(count = 2)
powerRepository.setInteractive(true) powerRepository.setInteractive(true)
val isFinishRequested = mutableListOf<Boolean>() val isFinishRequested = mutableListOf<Boolean>()
@@ -356,6 +350,93 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
job.cancel() job.cancel()
} }
@Test
fun `guest selected -- name is exit guest`() = testScope.runTest {
val userInfos =
listOf(
UserInfo(
/* id= */ 0,
/* name= */ "zero",
/* iconPath= */ "",
/* flags= */ UserInfo.FLAG_PRIMARY or UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL,
UserManager.USER_TYPE_FULL_SYSTEM,
),
UserInfo(
/* id= */ 1,
/* name= */ "one",
/* iconPath= */ "",
/* flags= */ UserInfo.FLAG_FULL,
UserManager.USER_TYPE_FULL_GUEST,
),
)
userRepository.setUserInfos(userInfos)
userRepository.setSelectedUserInfo(userInfos[1])
val userViewModels = mutableListOf<List<UserViewModel>>()
val job = launch(testDispatcher) { underTest.users.toList(userViewModels) }
assertThat(userViewModels.last()).hasSize(2)
assertUserViewModel(
viewModel = userViewModels.last()[0],
viewKey = 0,
name = Text.Loaded("zero"),
isSelectionMarkerVisible = false,
)
assertUserViewModel(
viewModel = userViewModels.last()[1],
viewKey = 1,
name = Text.Resource(
com.android.settingslib.R.string.guest_exit_quick_settings_button
),
isSelectionMarkerVisible = true,
)
job.cancel()
}
@Test
fun `guest not selected -- name is guest`() = testScope.runTest {
val userInfos =
listOf(
UserInfo(
/* id= */ 0,
/* name= */ "zero",
/* iconPath= */ "",
/* flags= */ UserInfo.FLAG_PRIMARY or UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL,
UserManager.USER_TYPE_FULL_SYSTEM,
),
UserInfo(
/* id= */ 1,
/* name= */ "one",
/* iconPath= */ "",
/* flags= */ UserInfo.FLAG_FULL,
UserManager.USER_TYPE_FULL_GUEST,
),
)
userRepository.setUserInfos(userInfos)
userRepository.setSelectedUserInfo(userInfos[0])
runCurrent()
val userViewModels = mutableListOf<List<UserViewModel>>()
val job = launch(testDispatcher) { underTest.users.toList(userViewModels) }
assertThat(userViewModels.last()).hasSize(2)
assertUserViewModel(
viewModel = userViewModels.last()[0],
viewKey = 0,
name = Text.Loaded("zero"),
isSelectionMarkerVisible = true,
)
assertUserViewModel(
viewModel = userViewModels.last()[1],
viewKey = 1,
name = Text.Loaded("one"),
isSelectionMarkerVisible = false,
)
job.cancel()
}
private suspend fun setUsers(count: Int): List<UserInfo> { private suspend fun setUsers(count: Int): List<UserInfo> {
val userInfos = val userInfos =
(0 until count).map { index -> (0 until count).map { index ->
@@ -384,26 +465,18 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
private fun assertUserViewModel( private fun assertUserViewModel(
viewModel: UserViewModel?, viewModel: UserViewModel?,
viewKey: Int, viewKey: Int,
name: String, name: Text,
isSelectionMarkerVisible: Boolean, isSelectionMarkerVisible: Boolean,
) { ) {
checkNotNull(viewModel) checkNotNull(viewModel)
assertThat(viewModel.viewKey).isEqualTo(viewKey) assertThat(viewModel.viewKey).isEqualTo(viewKey)
assertThat(viewModel.name).isEqualTo(Text.Loaded(name)) assertThat(viewModel.name).isEqualTo(name)
assertThat(viewModel.isSelectionMarkerVisible).isEqualTo(isSelectionMarkerVisible) assertThat(viewModel.isSelectionMarkerVisible).isEqualTo(isSelectionMarkerVisible)
assertThat(viewModel.alpha) assertThat(viewModel.alpha)
.isEqualTo(LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA) .isEqualTo(LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA)
assertThat(viewModel.onClicked).isNotNull() assertThat(viewModel.onClicked).isNotNull()
} }
private fun selfCancelingTest(
block: suspend TestScope.() -> Unit,
): TestResult =
testScope.runTest {
block()
injectedScope.coroutineContext[Job.Key]?.cancelAndJoin()
}
companion object { companion object {
private const val SUPERVISED_USER_CREATION_PACKAGE = "com.some.package" private const val SUPERVISED_USER_CREATION_PACKAGE = "com.some.package"
} }