1 /* <lambda>null2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.inputmethod.data.repository 18 19 import android.annotation.SuppressLint 20 import android.os.UserHandle 21 import android.view.inputmethod.InputMethodManager 22 import com.android.systemui.dagger.SysUISingleton 23 import com.android.systemui.dagger.qualifiers.Background 24 import com.android.systemui.inputmethod.data.model.InputMethodModel 25 import dagger.Binds 26 import dagger.Module 27 import javax.inject.Inject 28 import kotlinx.coroutines.CoroutineDispatcher 29 import kotlinx.coroutines.flow.Flow 30 import kotlinx.coroutines.flow.asFlow 31 import kotlinx.coroutines.flow.map 32 import kotlinx.coroutines.withContext 33 34 /** Provides access to input-method related application state in the bouncer. */ 35 interface InputMethodRepository { 36 37 /** 38 * Creates and returns a new `Flow` of installed input methods that are enabled for the 39 * specified user. 40 * 41 * @param user The user to query. 42 * @param fetchSubtypes Whether to fetch the IME Subtypes as well (requires an additional IPC 43 * call for each IME, avoid if not needed). 44 * @see InputMethodManager.getEnabledInputMethodListAsUser 45 */ 46 suspend fun enabledInputMethods( 47 user: UserHandle, 48 fetchSubtypes: Boolean, 49 ): Flow<InputMethodModel> 50 51 /** 52 * Returns enabled subtypes for the currently selected input method. 53 * 54 * @param user The user to query. 55 */ 56 suspend fun selectedInputMethodSubtypes(user: UserHandle): List<InputMethodModel.Subtype> 57 58 /** 59 * Shows the system's input method picker dialog. 60 * 61 * @param displayId The display ID on which to show the dialog. 62 * @param showAuxiliarySubtypes Whether to show auxiliary input method subtypes in the list of 63 * enabled IMEs. 64 * @see InputMethodManager.showInputMethodPickerFromSystem 65 */ 66 suspend fun showInputMethodPicker(displayId: Int, showAuxiliarySubtypes: Boolean) 67 } 68 69 @SysUISingleton 70 class InputMethodRepositoryImpl 71 @Inject 72 constructor( 73 @Background private val backgroundDispatcher: CoroutineDispatcher, 74 private val inputMethodManager: InputMethodManager, 75 ) : InputMethodRepository { 76 enabledInputMethodsnull77 override suspend fun enabledInputMethods( 78 user: UserHandle, 79 fetchSubtypes: Boolean 80 ): Flow<InputMethodModel> { 81 return withContext(backgroundDispatcher) { 82 inputMethodManager.getEnabledInputMethodListAsUser(user) 83 } 84 .asFlow() 85 .map { inputMethodInfo -> 86 InputMethodModel( 87 userId = user.identifier, 88 imeId = inputMethodInfo.id, 89 subtypes = 90 if (fetchSubtypes) { 91 enabledInputMethodSubtypes( 92 user = user, 93 imeId = inputMethodInfo.id, 94 allowsImplicitlyEnabledSubtypes = true 95 ) 96 } else { 97 listOf() 98 } 99 ) 100 } 101 } 102 selectedInputMethodSubtypesnull103 override suspend fun selectedInputMethodSubtypes( 104 user: UserHandle, 105 ): List<InputMethodModel.Subtype> { 106 val selectedIme = inputMethodManager.getCurrentInputMethodInfoAsUser(user) 107 return if (selectedIme == null) { 108 emptyList() 109 } else { 110 enabledInputMethodSubtypes( 111 user = user, 112 imeId = selectedIme.id, 113 allowsImplicitlyEnabledSubtypes = false 114 ) 115 } 116 } 117 118 @SuppressLint("MissingPermission") showInputMethodPickernull119 override suspend fun showInputMethodPicker(displayId: Int, showAuxiliarySubtypes: Boolean) { 120 withContext(backgroundDispatcher) { 121 inputMethodManager.showInputMethodPickerFromSystem(showAuxiliarySubtypes, displayId) 122 } 123 } 124 125 /** 126 * Returns a list of enabled input method subtypes for the specified input method info. 127 * 128 * @param user The user to query. 129 * @param imeId The ID of the input method whose subtypes list will be returned. 130 * @param allowsImplicitlyEnabledSubtypes Whether to allow to return the implicitly enabled 131 * subtypes. If an input method info doesn't have enabled subtypes, the framework will 132 * implicitly enable subtypes according to the current system language. 133 * @see InputMethodManager.getEnabledInputMethodSubtypeListAsUser 134 */ enabledInputMethodSubtypesnull135 private suspend fun enabledInputMethodSubtypes( 136 user: UserHandle, 137 imeId: String, 138 allowsImplicitlyEnabledSubtypes: Boolean 139 ): List<InputMethodModel.Subtype> { 140 return withContext(backgroundDispatcher) { 141 inputMethodManager.getEnabledInputMethodSubtypeListAsUser( 142 imeId, 143 allowsImplicitlyEnabledSubtypes, 144 user 145 ) 146 } 147 .map { 148 InputMethodModel.Subtype( 149 subtypeId = it.subtypeId, 150 isAuxiliary = it.isAuxiliary, 151 ) 152 } 153 } 154 } 155 156 @Module 157 interface InputMethodRepositoryModule { repositorynull158 @Binds fun repository(impl: InputMethodRepositoryImpl): InputMethodRepository 159 } 160