diff options
7 files changed, 79 insertions, 39 deletions
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 c28cf348b9fc..a09189efa41b 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 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { 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 857cdce448ed..274880b484cc 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 @@ class InputMethodRepositoryTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) - whenever(inputMethodManager.getEnabledInputMethodSubtypeList(eq(null), anyBoolean())) - .thenReturn(listOf()) - underTest = InputMethodRepositoryImpl( backgroundDispatcher = kosmos.testDispatcher, @@ -71,10 +68,16 @@ class InputMethodRepositoryTest : SysuiTestCase() { 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 @@ class InputMethodRepositoryTest : SysuiTestCase() { 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 @@ class InputMethodRepositoryTest : SysuiTestCase() { ) ) - 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 @@ class InputMethodRepositoryTest : SysuiTestCase() { testScope.runTest { val displayId = 7 - underTest.showInputMethodPicker(displayId, /* showAuxiliarySubtypes = */ true) + underTest.showInputMethodPicker(displayId, /* showAuxiliarySubtypes= */ true) verify(inputMethodManager) .showInputMethodPickerFromSystem( @@ -118,7 +130,6 @@ class InputMethodRepositoryTest : SysuiTestCase() { } 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 d23ff2a817e9..8e6de2f04279 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 @@ class InputMethodInteractorTest : SysuiTestCase() { 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 bdc18b322ac0..0e19d8788320 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 @@ package com.android.systemui.inputmethod.data.model * @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 5f316c4495ec..c6fdc32e132a 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 @@ package com.android.systemui.inputmethod.data.repository 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 @@ import kotlinx.coroutines.withContext /** 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 @@ constructor( ) : 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 @@ constructor( } } - 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 @@ constructor( /** * 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 c54aa7f2c6a5..d3ef17859ac5 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 @@ constructor( * 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 8e4461dd5b1e..444baa048a03 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 @@ class FakeInputMethodRepository : InputMethodRepository { } 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 |