[flexiglass] Fetch InputMethod subtypes using the explicit user ID.

IME subtypes were being fetched without passing in a user ID, which
fetches them for the currently-selected user by default.

Fix: 354968281
Flag: com.android.systemui.scene_container
Test: Updated unit tests, and existing ones still pass.
Change-Id: I6d2ee05d6c816ecf23e8ec313a2a53e64d8db06f
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
index c28cf34..a09189e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
@@ -372,6 +372,7 @@
         nonAuxiliarySubtypes: Int,
     ): InputMethodModel {
         return InputMethodModel(
+            userId = UUID.randomUUID().mostSignificantBits.toInt(),
             imeId = UUID.randomUUID().toString(),
             subtypes =
                 List(auxiliarySubtypes + nonAuxiliarySubtypes) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputmethod/data/repository/InputMethodRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputmethod/data/repository/InputMethodRepositoryTest.kt
index 857cdce..274880b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputmethod/data/repository/InputMethodRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputmethod/data/repository/InputMethodRepositoryTest.kt
@@ -56,9 +56,6 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        whenever(inputMethodManager.getEnabledInputMethodSubtypeList(eq(null), anyBoolean()))
-            .thenReturn(listOf())
-
         underTest =
             InputMethodRepositoryImpl(
                 backgroundDispatcher = kosmos.testDispatcher,
@@ -71,10 +68,16 @@
         testScope.runTest {
             whenever(inputMethodManager.getEnabledInputMethodListAsUser(eq(USER_HANDLE)))
                 .thenReturn(listOf())
-            whenever(inputMethodManager.getEnabledInputMethodSubtypeList(any(), anyBoolean()))
+            whenever(
+                    inputMethodManager.getEnabledInputMethodSubtypeListAsUser(
+                        any(),
+                        anyBoolean(),
+                        eq(USER_HANDLE)
+                    )
+                )
                 .thenReturn(listOf())
 
-            assertThat(underTest.enabledInputMethods(USER_ID, fetchSubtypes = true).count())
+            assertThat(underTest.enabledInputMethods(USER_HANDLE, fetchSubtypes = true).count())
                 .isEqualTo(0)
         }
 
@@ -83,11 +86,20 @@
         testScope.runTest {
             val subtypeId = 123
             val isAuxiliary = true
+            val selectedImiId = "imiId"
+            val selectedImi = mock<InputMethodInfo>()
+            whenever(selectedImi.id).thenReturn(selectedImiId)
+            whenever(inputMethodManager.getCurrentInputMethodInfoAsUser(eq(USER_HANDLE)))
+                .thenReturn(selectedImi)
             whenever(inputMethodManager.getEnabledInputMethodListAsUser(eq(USER_HANDLE)))
-                .thenReturn(listOf(mock<InputMethodInfo>()))
-            whenever(inputMethodManager.getEnabledInputMethodSubtypeList(any(), anyBoolean()))
-                .thenReturn(listOf())
-            whenever(inputMethodManager.getEnabledInputMethodSubtypeList(eq(null), anyBoolean()))
+                .thenReturn(listOf(selectedImi))
+            whenever(
+                    inputMethodManager.getEnabledInputMethodSubtypeListAsUser(
+                        eq(selectedImiId),
+                        anyBoolean(),
+                        eq(USER_HANDLE)
+                    )
+                )
                 .thenReturn(
                     listOf(
                         InputMethodSubtype.InputMethodSubtypeBuilder()
@@ -97,7 +109,7 @@
                     )
                 )
 
-            val result = underTest.selectedInputMethodSubtypes()
+            val result = underTest.selectedInputMethodSubtypes(USER_HANDLE)
             assertThat(result).hasSize(1)
             assertThat(result.first().subtypeId).isEqualTo(subtypeId)
             assertThat(result.first().isAuxiliary).isEqualTo(isAuxiliary)
@@ -108,7 +120,7 @@
         testScope.runTest {
             val displayId = 7
 
-            underTest.showInputMethodPicker(displayId, /* showAuxiliarySubtypes = */ true)
+            underTest.showInputMethodPicker(displayId, /* showAuxiliarySubtypes= */ true)
 
             verify(inputMethodManager)
                 .showInputMethodPickerFromSystem(
@@ -118,7 +130,6 @@
         }
 
     companion object {
-        private const val USER_ID = 100
-        private val USER_HANDLE = UserHandle.of(USER_ID)
+        private val USER_HANDLE = UserHandle.of(100)
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputmethod/domain/interactor/InputMethodInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputmethod/domain/interactor/InputMethodInteractorTest.kt
index d23ff2a..8e6de2f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputmethod/domain/interactor/InputMethodInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputmethod/domain/interactor/InputMethodInteractorTest.kt
@@ -143,6 +143,7 @@
         nonAuxiliarySubtypes: Int,
     ): InputMethodModel {
         return InputMethodModel(
+            userId = UUID.randomUUID().mostSignificantBits.toInt(),
             imeId = UUID.randomUUID().toString(),
             subtypes =
                 List(auxiliarySubtypes + nonAuxiliarySubtypes) {
diff --git a/packages/SystemUI/src/com/android/systemui/inputmethod/data/model/InputMethodModel.kt b/packages/SystemUI/src/com/android/systemui/inputmethod/data/model/InputMethodModel.kt
index bdc18b3..0e19d87 100644
--- a/packages/SystemUI/src/com/android/systemui/inputmethod/data/model/InputMethodModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputmethod/data/model/InputMethodModel.kt
@@ -22,6 +22,8 @@
  * @see android.view.inputmethod.InputMethodInfo
  */
 data class InputMethodModel(
+    /** A unique ID for the user associated with this input method. */
+    val userId: Int,
     /** A unique ID for this input method. */
     val imeId: String,
     /** The subtypes of this IME (may be empty). */
diff --git a/packages/SystemUI/src/com/android/systemui/inputmethod/data/repository/InputMethodRepository.kt b/packages/SystemUI/src/com/android/systemui/inputmethod/data/repository/InputMethodRepository.kt
index 5f316c4..c6fdc32 100644
--- a/packages/SystemUI/src/com/android/systemui/inputmethod/data/repository/InputMethodRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputmethod/data/repository/InputMethodRepository.kt
@@ -18,7 +18,6 @@
 
 import android.annotation.SuppressLint
 import android.os.UserHandle
-import android.view.inputmethod.InputMethodInfo
 import android.view.inputmethod.InputMethodManager
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
@@ -34,18 +33,27 @@
 
 /** Provides access to input-method related application state in the bouncer. */
 interface InputMethodRepository {
+
     /**
      * Creates and returns a new `Flow` of installed input methods that are enabled for the
      * specified user.
      *
+     * @param user The user to query.
      * @param fetchSubtypes Whether to fetch the IME Subtypes as well (requires an additional IPC
      *   call for each IME, avoid if not needed).
      * @see InputMethodManager.getEnabledInputMethodListAsUser
      */
-    suspend fun enabledInputMethods(userId: Int, fetchSubtypes: Boolean): Flow<InputMethodModel>
+    suspend fun enabledInputMethods(
+        user: UserHandle,
+        fetchSubtypes: Boolean,
+    ): Flow<InputMethodModel>
 
-    /** Returns enabled subtypes for the currently selected input method. */
-    suspend fun selectedInputMethodSubtypes(): List<InputMethodModel.Subtype>
+    /**
+     * Returns enabled subtypes for the currently selected input method.
+     *
+     * @param user The user to query.
+     */
+    suspend fun selectedInputMethodSubtypes(user: UserHandle): List<InputMethodModel.Subtype>
 
     /**
      * Shows the system's input method picker dialog.
@@ -67,20 +75,22 @@
 ) : InputMethodRepository {
 
     override suspend fun enabledInputMethods(
-        userId: Int,
+        user: UserHandle,
         fetchSubtypes: Boolean
     ): Flow<InputMethodModel> {
         return withContext(backgroundDispatcher) {
-                inputMethodManager.getEnabledInputMethodListAsUser(UserHandle.of(userId))
+                inputMethodManager.getEnabledInputMethodListAsUser(user)
             }
             .asFlow()
             .map { inputMethodInfo ->
                 InputMethodModel(
+                    userId = user.identifier,
                     imeId = inputMethodInfo.id,
                     subtypes =
                         if (fetchSubtypes) {
                             enabledInputMethodSubtypes(
-                                inputMethodInfo,
+                                user = user,
+                                imeId = inputMethodInfo.id,
                                 allowsImplicitlyEnabledSubtypes = true
                             )
                         } else {
@@ -90,11 +100,19 @@
             }
     }
 
-    override suspend fun selectedInputMethodSubtypes(): List<InputMethodModel.Subtype> {
-        return enabledInputMethodSubtypes(
-            inputMethodInfo = null, // Fetch subtypes for the currently-selected IME.
-            allowsImplicitlyEnabledSubtypes = false
-        )
+    override suspend fun selectedInputMethodSubtypes(
+        user: UserHandle,
+    ): List<InputMethodModel.Subtype> {
+        val selectedIme = inputMethodManager.getCurrentInputMethodInfoAsUser(user)
+        return if (selectedIme == null) {
+            emptyList()
+        } else {
+            enabledInputMethodSubtypes(
+                user = user,
+                imeId = selectedIme.id,
+                allowsImplicitlyEnabledSubtypes = false
+            )
+        }
     }
 
     @SuppressLint("MissingPermission")
@@ -107,21 +125,23 @@
     /**
      * Returns a list of enabled input method subtypes for the specified input method info.
      *
-     * @param inputMethodInfo The [InputMethodInfo] whose subtypes list will be returned. If `null`,
-     *   returns enabled subtypes for the currently selected [InputMethodInfo].
+     * @param user The user to query.
+     * @param imeId The ID of the input method whose subtypes list will be returned.
      * @param allowsImplicitlyEnabledSubtypes Whether to allow to return the implicitly enabled
      *   subtypes. If an input method info doesn't have enabled subtypes, the framework will
      *   implicitly enable subtypes according to the current system language.
-     * @see InputMethodManager.getEnabledInputMethodSubtypeList
+     * @see InputMethodManager.getEnabledInputMethodSubtypeListAsUser
      */
     private suspend fun enabledInputMethodSubtypes(
-        inputMethodInfo: InputMethodInfo?,
+        user: UserHandle,
+        imeId: String,
         allowsImplicitlyEnabledSubtypes: Boolean
     ): List<InputMethodModel.Subtype> {
         return withContext(backgroundDispatcher) {
-                inputMethodManager.getEnabledInputMethodSubtypeList(
-                    inputMethodInfo,
-                    allowsImplicitlyEnabledSubtypes
+                inputMethodManager.getEnabledInputMethodSubtypeListAsUser(
+                    imeId,
+                    allowsImplicitlyEnabledSubtypes,
+                    user
                 )
             }
             .map {
diff --git a/packages/SystemUI/src/com/android/systemui/inputmethod/domain/interactor/InputMethodInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputmethod/domain/interactor/InputMethodInteractor.kt
index c54aa7f..d3ef178 100644
--- a/packages/SystemUI/src/com/android/systemui/inputmethod/domain/interactor/InputMethodInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputmethod/domain/interactor/InputMethodInteractor.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.inputmethod.domain.interactor
 
+import android.os.UserHandle
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.inputmethod.data.repository.InputMethodRepository
 import javax.inject.Inject
@@ -36,14 +37,16 @@
      * Method adapted from `com.android.inputmethod.latin.Utils`.
      */
     suspend fun hasMultipleEnabledImesOrSubtypes(userId: Int): Boolean {
+        val user = UserHandle.of(userId)
         // Count IMEs that either have no subtypes, or have at least one non-auxiliary subtype.
         val matchingInputMethods =
             repository
-                .enabledInputMethods(userId, fetchSubtypes = true)
+                .enabledInputMethods(user, fetchSubtypes = true)
                 .filter { ime -> ime.subtypes.isEmpty() || ime.subtypes.any { !it.isAuxiliary } }
                 .take(2) // Short-circuit if we find at least 2 matching IMEs.
 
-        return matchingInputMethods.count() > 1 || repository.selectedInputMethodSubtypes().size > 1
+        return matchingInputMethods.count() > 1 ||
+            repository.selectedInputMethodSubtypes(user).size > 1
     }
 
     /** Shows the system's input method picker dialog. */
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/inputmethod/data/repository/FakeInputMethodRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/inputmethod/data/repository/FakeInputMethodRepository.kt
index 8e4461d..444baa0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/inputmethod/data/repository/FakeInputMethodRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/inputmethod/data/repository/FakeInputMethodRepository.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.inputmethod.data.repository
 
+import android.os.UserHandle
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.inputmethod.data.model.InputMethodModel
 import kotlinx.coroutines.flow.Flow
@@ -40,14 +41,15 @@
     }
 
     override suspend fun enabledInputMethods(
-        userId: Int,
-        fetchSubtypes: Boolean,
+        user: UserHandle,
+        fetchSubtypes: Boolean
     ): Flow<InputMethodModel> {
-        return usersToEnabledInputMethods[userId] ?: flowOf()
+        return usersToEnabledInputMethods[user.identifier] ?: flowOf()
     }
 
-    override suspend fun selectedInputMethodSubtypes(): List<InputMethodModel.Subtype> =
-        selectedInputMethodSubtypes
+    override suspend fun selectedInputMethodSubtypes(
+        user: UserHandle,
+    ): List<InputMethodModel.Subtype> = selectedInputMethodSubtypes
 
     override suspend fun showInputMethodPicker(displayId: Int, showAuxiliarySubtypes: Boolean) {
         inputMethodPickerShownDisplayId = displayId