diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java index 57a00c9a16205..b6b657ec82f69 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java @@ -204,15 +204,6 @@ public class UserDetailView extends PseudoGridView { Trace.endSection(); } - @Override - public void onUserListItemClicked(@NonNull UserRecord record, - @Nullable UserSwitchDialogController.DialogShower dialogShower) { - if (dialogShower != null) { - mDialogShower.dismiss(); - } - super.onUserListItemClicked(record, dialogShower); - } - public void linkToViewGroup(ViewGroup viewGroup) { PseudoGridView.ViewGroupAdapterBridge.link(viewGroup, this); } 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 68d30d3f3d1e2..2b4f51c630438 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt @@ -60,7 +60,7 @@ protected constructor( * animation to and from the parent dialog. */ @JvmOverloads - open fun onUserListItemClicked( + fun onUserListItemClicked( record: UserRecord, dialogShower: DialogShower? = null, ) { diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt index 7a885bc8d2e23..c0ba3cc352b06 100644 --- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt @@ -443,7 +443,8 @@ constructor( ) ) } - UserActionModel.ADD_SUPERVISED_USER -> + UserActionModel.ADD_SUPERVISED_USER -> { + dismissDialog() activityStarter.startActivity( Intent() .setAction(UserManager.ACTION_CREATE_SUPERVISED_USER) @@ -451,6 +452,7 @@ constructor( .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), /* dismissShade= */ true, ) + } UserActionModel.NAVIGATE_TO_USER_MANAGEMENT -> activityStarter.startActivity( Intent(Settings.ACTION_USER_SETTINGS), diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt b/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt index d4512309f6c61..79721b370c21f 100644 --- a/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt @@ -66,12 +66,6 @@ constructor( private fun startHandlingDialogShowRequests() { applicationScope.get().launch { interactor.get().dialogShowRequests.filterNotNull().collect { request -> - currentDialog?.let { - if (it.isShowing) { - it.cancel() - } - } - val (dialog, dialogCuj) = when (request) { is ShowDialogRequestModel.ShowAddUserDialog -> diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt index 08a90b79089e5..18e40f6339551 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt @@ -30,7 +30,6 @@ import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingManagerFake import com.android.systemui.qs.QSUserSwitcherEvent -import com.android.systemui.qs.user.UserSwitchDialogController import com.android.systemui.statusbar.policy.UserSwitcherController import com.android.systemui.user.data.source.UserRecord import org.junit.Assert.assertEquals @@ -42,7 +41,6 @@ import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock -import org.mockito.Mockito.mock import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @@ -152,15 +150,6 @@ class UserDetailViewAdapterTest : SysuiTestCase() { assertNull(adapter.users.find { it.isManageUsers }) } - @Test - fun clickDismissDialog() { - val shower: UserSwitchDialogController.DialogShower = - mock(UserSwitchDialogController.DialogShower::class.java) - adapter.injectDialogShower(shower) - adapter.onUserListItemClicked(createUserRecord(current = true, guest = false), shower) - verify(shower).dismiss() - } - private fun createUserRecord(current: Boolean, guest: Boolean) = UserRecord( UserInfo(0 /* id */, "name", 0 /* flags */), diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt index 5beb2b389349a..5cd415d934756 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt @@ -36,6 +36,7 @@ import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Text +import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository @@ -60,12 +61,12 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.nullable import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.TestCoroutineScope -import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -73,10 +74,12 @@ import org.junit.runners.JUnit4 import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock +import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations +@OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(JUnit4::class) class UserInteractorTest : SysuiTestCase() { @@ -93,7 +96,7 @@ class UserInteractorTest : SysuiTestCase() { private lateinit var underTest: UserInteractor - private lateinit var testCoroutineScope: TestCoroutineScope + private lateinit var testScope: TestScope private lateinit var userRepository: FakeUserRepository private lateinit var keyguardRepository: FakeKeyguardRepository private lateinit var telephonyRepository: FakeTelephonyRepository @@ -117,11 +120,12 @@ class UserInteractorTest : SysuiTestCase() { userRepository = FakeUserRepository() keyguardRepository = FakeKeyguardRepository() telephonyRepository = FakeTelephonyRepository() - testCoroutineScope = TestCoroutineScope() + val testDispatcher = StandardTestDispatcher() + testScope = TestScope(testDispatcher) val refreshUsersScheduler = RefreshUsersScheduler( - applicationScope = testCoroutineScope, - mainDispatcher = IMMEDIATE, + applicationScope = testScope.backgroundScope, + mainDispatcher = testDispatcher, repository = userRepository, ) underTest = @@ -134,21 +138,21 @@ class UserInteractorTest : SysuiTestCase() { repository = keyguardRepository, ), manager = manager, - applicationScope = testCoroutineScope, + applicationScope = testScope.backgroundScope, telephonyInteractor = TelephonyInteractor( repository = telephonyRepository, ), broadcastDispatcher = fakeBroadcastDispatcher, - backgroundDispatcher = IMMEDIATE, + backgroundDispatcher = testDispatcher, activityManager = activityManager, refreshUsersScheduler = refreshUsersScheduler, guestUserInteractor = GuestUserInteractor( applicationContext = context, - applicationScope = testCoroutineScope, - mainDispatcher = IMMEDIATE, - backgroundDispatcher = IMMEDIATE, + applicationScope = testScope.backgroundScope, + mainDispatcher = testDispatcher, + backgroundDispatcher = testDispatcher, manager = manager, repository = userRepository, deviceProvisionedController = deviceProvisionedController, @@ -164,7 +168,7 @@ class UserInteractorTest : SysuiTestCase() { @Test fun `onRecordSelected - user`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 3, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) @@ -179,7 +183,7 @@ class UserInteractorTest : SysuiTestCase() { @Test fun `onRecordSelected - switch to guest user`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 3, includeGuest = true) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) @@ -193,7 +197,7 @@ class UserInteractorTest : SysuiTestCase() { @Test fun `onRecordSelected - enter guest mode`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 3, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) @@ -202,6 +206,7 @@ class UserInteractorTest : SysuiTestCase() { whenever(manager.createGuest(any())).thenReturn(guestUserInfo) underTest.onRecordSelected(UserRecord(isGuest = true), dialogShower) + runCurrent() verify(dialogShower).dismiss() verify(manager).createGuest(any()) @@ -210,7 +215,7 @@ class UserInteractorTest : SysuiTestCase() { @Test fun `onRecordSelected - action`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 3, includeGuest = true) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) @@ -224,81 +229,72 @@ class UserInteractorTest : SysuiTestCase() { @Test fun `users - switcher enabled`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 3, includeGuest = true) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) - var value: List? = null - val job = underTest.users.onEach { value = it }.launchIn(this) - assertUsers(models = value, count = 3, includeGuest = true) + val value = collectLastValue(underTest.users) - job.cancel() + assertUsers(models = value(), count = 3, includeGuest = true) } @Test fun `users - switches to second user`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) - var value: List? = null - val job = underTest.users.onEach { value = it }.launchIn(this) + val value = collectLastValue(underTest.users) userRepository.setSelectedUserInfo(userInfos[1]) - assertUsers(models = value, count = 2, selectedIndex = 1) - job.cancel() + assertUsers(models = value(), count = 2, selectedIndex = 1) } @Test fun `users - switcher not enabled`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = false)) - var value: List? = null - val job = underTest.users.onEach { value = it }.launchIn(this) - assertUsers(models = value, count = 1) - - job.cancel() + val value = collectLastValue(underTest.users) + assertUsers(models = value(), count = 1) } @Test fun selectedUser() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) - var value: UserModel? = null - val job = underTest.selectedUser.onEach { value = it }.launchIn(this) - assertUser(value, id = 0, isSelected = true) + val value = collectLastValue(underTest.selectedUser) + assertUser(value(), id = 0, isSelected = true) userRepository.setSelectedUserInfo(userInfos[1]) - assertUser(value, id = 1, isSelected = true) - - job.cancel() + assertUser(value(), id = 1, isSelected = true) } @Test fun `actions - device unlocked`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) keyguardRepository.setKeyguardShowing(false) - var value: List? = null - val job = underTest.actions.onEach { value = it }.launchIn(this) + val value = collectLastValue(underTest.actions) - assertThat(value) + runCurrent() + + assertThat(value()) .isEqualTo( listOf( UserActionModel.ENTER_GUEST_MODE, @@ -307,13 +303,11 @@ class UserInteractorTest : SysuiTestCase() { UserActionModel.NAVIGATE_TO_USER_MANAGEMENT, ) ) - - job.cancel() } @Test fun `actions - device unlocked - full screen`() = - runBlocking(IMMEDIATE) { + testScope.runTest { featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true) val userInfos = createUserInfos(count = 2, includeGuest = false) @@ -321,10 +315,9 @@ class UserInteractorTest : SysuiTestCase() { userRepository.setSelectedUserInfo(userInfos[0]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) keyguardRepository.setKeyguardShowing(false) - var value: List? = null - val job = underTest.actions.onEach { value = it }.launchIn(this) + val value = collectLastValue(underTest.actions) - assertThat(value) + assertThat(value()) .isEqualTo( listOf( UserActionModel.ADD_USER, @@ -333,46 +326,38 @@ class UserInteractorTest : SysuiTestCase() { UserActionModel.NAVIGATE_TO_USER_MANAGEMENT, ) ) - - job.cancel() } @Test fun `actions - device unlocked user not primary - empty list`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[1]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) keyguardRepository.setKeyguardShowing(false) - var value: List? = null - val job = underTest.actions.onEach { value = it }.launchIn(this) + val value = collectLastValue(underTest.actions) - assertThat(value).isEqualTo(emptyList()) - - job.cancel() + assertThat(value()).isEqualTo(emptyList()) } @Test fun `actions - device unlocked user is guest - empty list`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = true) assertThat(userInfos[1].isGuest).isTrue() userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[1]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) keyguardRepository.setKeyguardShowing(false) - var value: List? = null - val job = underTest.actions.onEach { value = it }.launchIn(this) + val value = collectLastValue(underTest.actions) - assertThat(value).isEqualTo(emptyList()) - - job.cancel() + assertThat(value()).isEqualTo(emptyList()) } @Test fun `actions - device locked add from lockscreen set - full list`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) @@ -383,10 +368,9 @@ class UserInteractorTest : SysuiTestCase() { ) ) keyguardRepository.setKeyguardShowing(false) - var value: List? = null - val job = underTest.actions.onEach { value = it }.launchIn(this) + val value = collectLastValue(underTest.actions) - assertThat(value) + assertThat(value()) .isEqualTo( listOf( UserActionModel.ENTER_GUEST_MODE, @@ -395,13 +379,11 @@ class UserInteractorTest : SysuiTestCase() { UserActionModel.NAVIGATE_TO_USER_MANAGEMENT, ) ) - - job.cancel() } @Test fun `actions - device locked add from lockscreen set - full list - full screen`() = - runBlocking(IMMEDIATE) { + testScope.runTest { featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true) val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) @@ -413,10 +395,9 @@ class UserInteractorTest : SysuiTestCase() { ) ) keyguardRepository.setKeyguardShowing(false) - var value: List? = null - val job = underTest.actions.onEach { value = it }.launchIn(this) + val value = collectLastValue(underTest.actions) - assertThat(value) + assertThat(value()) .isEqualTo( listOf( UserActionModel.ADD_USER, @@ -425,39 +406,33 @@ class UserInteractorTest : SysuiTestCase() { UserActionModel.NAVIGATE_TO_USER_MANAGEMENT, ) ) - - job.cancel() } @Test fun `actions - device locked - only manage user is shown`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) keyguardRepository.setKeyguardShowing(true) - var value: List? = null - val job = underTest.actions.onEach { value = it }.launchIn(this) + val value = collectLastValue(underTest.actions) - assertThat(value).isEqualTo(listOf(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)) - - job.cancel() + assertThat(value()).isEqualTo(listOf(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)) } @Test fun `executeAction - add user - dialog shown`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) keyguardRepository.setKeyguardShowing(false) - var dialogRequest: ShowDialogRequestModel? = null - val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this) + val dialogRequest = collectLastValue(underTest.dialogShowRequests) val dialogShower: UserSwitchDialogController.DialogShower = mock() underTest.executeAction(UserActionModel.ADD_USER, dialogShower) - assertThat(dialogRequest) + assertThat(dialogRequest()) .isEqualTo( ShowDialogRequestModel.ShowAddUserDialog( userHandle = userInfos[0].userHandle, @@ -468,14 +443,12 @@ class UserInteractorTest : SysuiTestCase() { ) underTest.onDialogShown() - assertThat(dialogRequest).isNull() - - job.cancel() + assertThat(dialogRequest()).isNull() } @Test - fun `executeAction - add supervised user - starts activity`() = - runBlocking(IMMEDIATE) { + fun `executeAction - add supervised user - dismisses dialog and starts activity`() = + testScope.runTest { underTest.executeAction(UserActionModel.ADD_SUPERVISED_USER) val intentCaptor = kotlinArgumentCaptor() @@ -487,7 +460,7 @@ class UserInteractorTest : SysuiTestCase() { @Test fun `executeAction - navigate to manage users`() = - runBlocking(IMMEDIATE) { + testScope.runTest { underTest.executeAction(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT) val intentCaptor = kotlinArgumentCaptor() @@ -497,7 +470,7 @@ class UserInteractorTest : SysuiTestCase() { @Test fun `executeAction - guest mode`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) @@ -505,110 +478,103 @@ class UserInteractorTest : SysuiTestCase() { val guestUserInfo = createUserInfo(id = 1337, name = "guest", isGuest = true) whenever(manager.createGuest(any())).thenReturn(guestUserInfo) val dialogRequests = mutableListOf() - val showDialogsJob = - underTest.dialogShowRequests - .onEach { - dialogRequests.add(it) - if (it != null) { - underTest.onDialogShown() - } + backgroundScope.launch { + underTest.dialogShowRequests.collect { + dialogRequests.add(it) + if (it != null) { + underTest.onDialogShown() } - .launchIn(this) - val dismissDialogsJob = - underTest.dialogDismissRequests - .onEach { - if (it != null) { - underTest.onDialogDismissed() - } + } + } + backgroundScope.launch { + underTest.dialogDismissRequests.collect { + if (it != null) { + underTest.onDialogDismissed() } - .launchIn(this) + } + } underTest.executeAction(UserActionModel.ENTER_GUEST_MODE) + runCurrent() assertThat(dialogRequests) .contains( ShowDialogRequestModel.ShowUserCreationDialog(isGuest = true), ) verify(activityManager).switchUser(guestUserInfo.id) - - showDialogsJob.cancel() - dismissDialogsJob.cancel() } @Test fun `selectUser - already selected guest re-selected - exit guest dialog`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = true) val guestUserInfo = userInfos[1] assertThat(guestUserInfo.isGuest).isTrue() userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(guestUserInfo) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) - var dialogRequest: ShowDialogRequestModel? = null - val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this) + val dialogRequest = collectLastValue(underTest.dialogShowRequests) underTest.selectUser( newlySelectedUserId = guestUserInfo.id, dialogShower = dialogShower, ) - assertThat(dialogRequest) + assertThat(dialogRequest()) .isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java) verify(dialogShower, never()).dismiss() - job.cancel() } @Test fun `selectUser - currently guest non-guest selected - exit guest dialog`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = true) val guestUserInfo = userInfos[1] assertThat(guestUserInfo.isGuest).isTrue() userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(guestUserInfo) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) - var dialogRequest: ShowDialogRequestModel? = null - val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this) + val dialogRequest = collectLastValue(underTest.dialogShowRequests) underTest.selectUser(newlySelectedUserId = userInfos[0].id, dialogShower = dialogShower) - assertThat(dialogRequest) + assertThat(dialogRequest()) .isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java) verify(dialogShower, never()).dismiss() - job.cancel() } @Test fun `selectUser - not currently guest - switches users`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) - var dialogRequest: ShowDialogRequestModel? = null - val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this) + val dialogRequest = collectLastValue(underTest.dialogShowRequests) underTest.selectUser(newlySelectedUserId = userInfos[1].id, dialogShower = dialogShower) - assertThat(dialogRequest).isNull() + assertThat(dialogRequest()).isNull() verify(activityManager).switchUser(userInfos[1].id) verify(dialogShower).dismiss() - job.cancel() } @Test fun `Telephony call state changes - refreshes users`() = - runBlocking(IMMEDIATE) { + testScope.runTest { + runCurrent() + val refreshUsersCallCount = userRepository.refreshUsersCallCount telephonyRepository.setCallState(1) + runCurrent() assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1) } @Test fun `User switched broadcast`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) @@ -617,9 +583,11 @@ class UserInteractorTest : SysuiTestCase() { val callback2: UserInteractor.UserCallback = mock() underTest.addCallback(callback1) underTest.addCallback(callback2) + runCurrent() val refreshUsersCallCount = userRepository.refreshUsersCallCount userRepository.setSelectedUserInfo(userInfos[1]) + runCurrent() fakeBroadcastDispatcher.registeredReceivers.forEach { it.onReceive( context, @@ -627,16 +595,17 @@ class UserInteractorTest : SysuiTestCase() { .putExtra(Intent.EXTRA_USER_HANDLE, userInfos[1].id), ) } + runCurrent() - verify(callback1).onUserStateChanged() - verify(callback2).onUserStateChanged() + verify(callback1, atLeastOnce()).onUserStateChanged() + verify(callback2, atLeastOnce()).onUserStateChanged() assertThat(userRepository.secondaryUserId).isEqualTo(userInfos[1].id) assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1) } @Test fun `User info changed broadcast`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) @@ -649,12 +618,14 @@ class UserInteractorTest : SysuiTestCase() { ) } + runCurrent() + assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1) } @Test fun `System user unlocked broadcast - refresh users`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) @@ -667,13 +638,14 @@ class UserInteractorTest : SysuiTestCase() { .putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_SYSTEM), ) } + runCurrent() assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1) } @Test fun `Non-system user unlocked broadcast - do not refresh users`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) @@ -691,14 +663,14 @@ class UserInteractorTest : SysuiTestCase() { @Test fun userRecords() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 3, includeGuest = false) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) keyguardRepository.setKeyguardShowing(false) - testCoroutineScope.advanceUntilIdle() + runCurrent() assertRecords( records = underTest.userRecords.value, @@ -717,7 +689,7 @@ class UserInteractorTest : SysuiTestCase() { @Test fun userRecordsFullScreen() = - runBlocking(IMMEDIATE) { + testScope.runTest { featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true) val userInfos = createUserInfos(count = 3, includeGuest = false) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) @@ -725,7 +697,7 @@ class UserInteractorTest : SysuiTestCase() { userRepository.setSelectedUserInfo(userInfos[0]) keyguardRepository.setKeyguardShowing(false) - testCoroutineScope.advanceUntilIdle() + runCurrent() assertRecords( records = underTest.userRecords.value, @@ -744,7 +716,7 @@ class UserInteractorTest : SysuiTestCase() { @Test fun selectedUserRecord() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 3, includeGuest = true) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) userRepository.setUserInfos(userInfos) @@ -762,64 +734,54 @@ class UserInteractorTest : SysuiTestCase() { @Test fun `users - secondary user - guest user can be switched to`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 3, includeGuest = true) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[1]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) - var res: List? = null - val job = underTest.users.onEach { res = it }.launchIn(this) - assertThat(res?.size == 3).isTrue() - assertThat(res?.find { it.isGuest }).isNotNull() - job.cancel() + val res = collectLastValue(underTest.users) + assertThat(res()?.size == 3).isTrue() + assertThat(res()?.find { it.isGuest }).isNotNull() } @Test fun `users - secondary user - no guest action`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 3, includeGuest = true) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[1]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) - var res: List? = null - val job = underTest.actions.onEach { res = it }.launchIn(this) - assertThat(res?.find { it == UserActionModel.ENTER_GUEST_MODE }).isNull() - job.cancel() + val res = collectLastValue(underTest.actions) + assertThat(res()?.find { it == UserActionModel.ENTER_GUEST_MODE }).isNull() } @Test fun `users - secondary user - no guest user record`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 3, includeGuest = true) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[1]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) - var res: List? = null - val job = underTest.userRecords.onEach { res = it }.launchIn(this) - assertThat(res?.find { it.isGuest }).isNull() - job.cancel() + assertThat(underTest.userRecords.value.find { it.isGuest }).isNull() } @Test fun `show user switcher - full screen disabled - shows dialog switcher`() = - runBlocking(IMMEDIATE) { - var dialogRequest: ShowDialogRequestModel? = null + testScope.runTest { val expandable = mock() underTest.showUserSwitcher(context, expandable) - val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this) + val dialogRequest = collectLastValue(underTest.dialogShowRequests) // Dialog is shown. - assertThat(dialogRequest) + assertThat(dialogRequest()) .isEqualTo(ShowDialogRequestModel.ShowUserSwitcherDialog(expandable)) underTest.onDialogShown() - assertThat(dialogRequest).isNull() - - job.cancel() + assertThat(dialogRequest()).isNull() } @Test @@ -850,8 +812,8 @@ class UserInteractorTest : SysuiTestCase() { @Test fun `users - secondary user - managed profile is not included`() = - runBlocking(IMMEDIATE) { - var userInfos = createUserInfos(count = 3, includeGuest = false).toMutableList() + testScope.runTest { + val userInfos = createUserInfos(count = 3, includeGuest = false).toMutableList() userInfos.add( UserInfo( 50, @@ -864,23 +826,19 @@ class UserInteractorTest : SysuiTestCase() { userRepository.setSelectedUserInfo(userInfos[1]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) - var res: List? = null - val job = underTest.users.onEach { res = it }.launchIn(this) - assertThat(res?.size == 3).isTrue() - job.cancel() + val res = collectLastValue(underTest.users) + assertThat(res()?.size == 3).isTrue() } @Test fun `current user is not primary and user switcher is disabled`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val userInfos = createUserInfos(count = 2, includeGuest = false) userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[1]) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = false)) - var selectedUser: UserModel? = null - val job = underTest.selectedUser.onEach { selectedUser = it }.launchIn(this) - assertThat(selectedUser).isNotNull() - job.cancel() + val selectedUser = collectLastValue(underTest.selectedUser) + assertThat(selectedUser()).isNotNull() } private fun assertUsers( @@ -1018,7 +976,6 @@ class UserInteractorTest : SysuiTestCase() { } companion object { - private val IMMEDIATE = Dispatchers.Main.immediate private val ICON = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) private val GUEST_ICON: Drawable = mock() private const val SUPERVISED_USER_CREATION_APP_PACKAGE = "supervisedUserCreation"