Merge changes Ib3989fc2,I053eec01,Ib0cbb23d into tm-qpr-dev am: f4ceebbadd am: 803cd364af

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

Change-Id: I583f6133ad91905eb540436c9ec798dccb87e088
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherControllerImpl.kt
index 1692656..af39eee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherControllerImpl.kt
@@ -30,7 +30,6 @@
 import com.android.systemui.user.data.source.UserRecord
 import com.android.systemui.user.domain.interactor.GuestUserInteractor
 import com.android.systemui.user.domain.interactor.UserInteractor
-import com.android.systemui.user.legacyhelper.data.LegacyUserDataHelper
 import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper
 import dagger.Lazy
 import java.io.PrintWriter
@@ -118,7 +117,7 @@
         dialogShower: UserSwitchDialogController.DialogShower?
     ) {
         if (useInteractor) {
-            userInteractor.selectUser(userId)
+            userInteractor.selectUser(userId, dialogShower)
         } else {
             _oldImpl.onUserSelected(userId, dialogShower)
         }
@@ -203,11 +202,7 @@
         dialogShower: UserSwitchDialogController.DialogShower?,
     ) {
         if (useInteractor) {
-            if (LegacyUserDataHelper.isUser(record)) {
-                userInteractor.selectUser(record.resolveId())
-            } else {
-                userInteractor.executeAction(LegacyUserDataHelper.toUserActionModel(record))
-            }
+            userInteractor.onRecordSelected(record, dialogShower)
         } else {
             _oldImpl.onUserListItemClicked(record, dialogShower)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
index 3014f39..919e699 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
@@ -220,7 +220,7 @@
             val result = withContext(backgroundDispatcher) { manager.aliveUsers }
 
             if (result != null) {
-                _userInfos.value = result
+                _userInfos.value = result.sortedBy { it.creationTime }
             }
         }
     }
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 a84238c..142a328 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
@@ -43,6 +43,7 @@
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.qs.user.UserSwitchDialogController
 import com.android.systemui.statusbar.policy.UserSwitcherController
 import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
 import com.android.systemui.user.data.repository.UserRepository
@@ -390,9 +391,24 @@
         guestUserInteractor.onDeviceBootCompleted()
     }
 
+    /** Switches to the user or executes the action represented by the given record. */
+    fun onRecordSelected(
+        record: UserRecord,
+        dialogShower: UserSwitchDialogController.DialogShower? = null,
+    ) {
+        if (LegacyUserDataHelper.isUser(record)) {
+            // It's safe to use checkNotNull around record.info because isUser only returns true
+            // if record.info is not null.
+            selectUser(checkNotNull(record.info).id, dialogShower)
+        } else {
+            executeAction(LegacyUserDataHelper.toUserActionModel(record), dialogShower)
+        }
+    }
+
     /** Switches to the user with the given user ID. */
     fun selectUser(
         newlySelectedUserId: Int,
+        dialogShower: UserSwitchDialogController.DialogShower? = null,
     ) {
         if (isNewImpl) {
             val currentlySelectedUserInfo = repository.getSelectedUserInfo()
@@ -428,22 +444,28 @@
                 return
             }
 
+            dialogShower?.dismiss()
+
             switchUser(newlySelectedUserId)
         } else {
-            controller.onUserSelected(newlySelectedUserId, /* dialogShower= */ null)
+            controller.onUserSelected(newlySelectedUserId, dialogShower)
         }
     }
 
     /** Executes the given action. */
-    fun executeAction(action: UserActionModel) {
+    fun executeAction(
+        action: UserActionModel,
+        dialogShower: UserSwitchDialogController.DialogShower? = null,
+    ) {
         if (isNewImpl) {
             when (action) {
                 UserActionModel.ENTER_GUEST_MODE ->
                     guestUserInteractor.createAndSwitchTo(
                         this::showDialog,
                         this::dismissDialog,
-                        this::selectUser,
-                    )
+                    ) { userId ->
+                        selectUser(userId, dialogShower)
+                    }
                 UserActionModel.ADD_USER -> {
                     val currentUser = repository.getSelectedUserInfo()
                     showDialog(
@@ -575,7 +597,7 @@
     }
 
     private fun switchUser(userId: Int) {
-        // TODO(b/246631653): track jank and lantecy like in the old impl.
+        // TODO(b/246631653): track jank and latency like in the old impl.
         refreshUsersScheduler.pause()
         try {
             activityManager.switchUser(userId)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplRefactoredTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplRefactoredTest.kt
index 4a8e055..d951f36 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplRefactoredTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplRefactoredTest.kt
@@ -120,6 +120,27 @@
         assertThat(underTest.lastSelectedNonGuestUserId).isEqualTo(selectedNonGuestUserId)
     }
 
+    @Test
+    fun `refreshUsers - sorts by creation time`() = runSelfCancelingTest {
+        underTest = create(this)
+        val unsortedUsers =
+            setUpUsers(
+                count = 3,
+                selectedIndex = 0,
+            )
+        unsortedUsers[0].creationTime = 900
+        unsortedUsers[1].creationTime = 700
+        unsortedUsers[2].creationTime = 999
+        val expectedUsers = listOf(unsortedUsers[1], unsortedUsers[0], unsortedUsers[2])
+        var userInfos: List<UserInfo>? = null
+        var selectedUserInfo: UserInfo? = null
+        underTest.userInfos.onEach { userInfos = it }.launchIn(this)
+        underTest.selectedUserInfo.onEach { selectedUserInfo = it }.launchIn(this)
+
+        underTest.refreshUsers()
+        assertThat(userInfos).isEqualTo(expectedUsers)
+    }
+
     private fun setUpUsers(
         count: Int,
         hasGuest: Boolean = false,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorRefactoredTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorRefactoredTest.kt
index 3d5695a..37c378c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorRefactoredTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorRefactoredTest.kt
@@ -47,7 +47,9 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 
 @SmallTest
@@ -73,6 +75,66 @@
     }
 
     @Test
+    fun `onRecordSelected - user`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            underTest.onRecordSelected(UserRecord(info = userInfos[1]), dialogShower)
+
+            verify(dialogShower).dismiss()
+            verify(activityManager).switchUser(userInfos[1].id)
+            Unit
+        }
+
+    @Test
+    fun `onRecordSelected - switch to guest user`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = true)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            underTest.onRecordSelected(UserRecord(info = userInfos.last()))
+
+            verify(activityManager).switchUser(userInfos.last().id)
+            Unit
+        }
+
+    @Test
+    fun `onRecordSelected - enter guest mode`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            val guestUserInfo = createUserInfo(id = 1337, name = "guest", isGuest = true)
+            whenever(manager.createGuest(any())).thenReturn(guestUserInfo)
+
+            underTest.onRecordSelected(UserRecord(isGuest = true), dialogShower)
+
+            verify(dialogShower).dismiss()
+            verify(manager).createGuest(any())
+            Unit
+        }
+
+    @Test
+    fun `onRecordSelected - action`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = true)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            underTest.onRecordSelected(UserRecord(isAddSupervisedUser = true), dialogShower)
+
+            verify(dialogShower, never()).dismiss()
+            verify(activityStarter).startActivity(any(), anyBoolean())
+        }
+
+    @Test
     fun `users - switcher enabled`() =
         runBlocking(IMMEDIATE) {
             val userInfos = createUserInfos(count = 3, includeGuest = true)
@@ -336,10 +398,14 @@
             var dialogRequest: ShowDialogRequestModel? = null
             val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
 
-            underTest.selectUser(newlySelectedUserId = guestUserInfo.id)
+            underTest.selectUser(
+                newlySelectedUserId = guestUserInfo.id,
+                dialogShower = dialogShower,
+            )
 
             assertThat(dialogRequest)
                 .isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java)
+            verify(dialogShower, never()).dismiss()
             job.cancel()
         }
 
@@ -355,10 +421,11 @@
             var dialogRequest: ShowDialogRequestModel? = null
             val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
 
-            underTest.selectUser(newlySelectedUserId = userInfos[0].id)
+            underTest.selectUser(newlySelectedUserId = userInfos[0].id, dialogShower = dialogShower)
 
             assertThat(dialogRequest)
                 .isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java)
+            verify(dialogShower, never()).dismiss()
             job.cancel()
         }
 
@@ -372,10 +439,11 @@
             var dialogRequest: ShowDialogRequestModel? = null
             val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
 
-            underTest.selectUser(newlySelectedUserId = userInfos[1].id)
+            underTest.selectUser(newlySelectedUserId = userInfos[1].id, dialogShower = dialogShower)
 
             assertThat(dialogRequest).isNull()
             verify(activityManager).switchUser(userInfos[1].id)
+            verify(dialogShower).dismiss()
             job.cancel()
         }
 
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 8465f4f..1680c36c 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
@@ -27,6 +27,7 @@
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.qs.user.UserSwitchDialogController
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.statusbar.policy.UserSwitcherController
 import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
@@ -46,6 +47,7 @@
     @Mock protected lateinit var deviceProvisionedController: DeviceProvisionedController
     @Mock protected lateinit var devicePolicyManager: DevicePolicyManager
     @Mock protected lateinit var uiEventLogger: UiEventLogger
+    @Mock protected lateinit var dialogShower: UserSwitchDialogController.DialogShower
 
     protected lateinit var underTest: UserInteractor