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.InputMethodInfo 22 import android.view.inputmethod.InputMethodManager 23 import com.android.systemui.dagger.SysUISingleton 24 import com.android.systemui.dagger.qualifiers.Background 25 import com.android.systemui.inputmethod.data.model.InputMethodModel 26 import dagger.Binds 27 import dagger.Module 28 import javax.inject.Inject 29 import kotlinx.coroutines.CoroutineDispatcher 30 import kotlinx.coroutines.flow.Flow 31 import kotlinx.coroutines.flow.asFlow 32 import kotlinx.coroutines.flow.map 33 import kotlinx.coroutines.withContext 34 35 /** Provides access to input-method related application state in the bouncer. */ 36 interface InputMethodRepository { 37 /** 38 * Creates and returns a new `Flow` of installed input methods that are enabled for the 39 * specified user. 40 * 41 * @param fetchSubtypes Whether to fetch the IME Subtypes as well (requires an additional IPC 42 * call for each IME, avoid if not needed). 43 * @see InputMethodManager.getEnabledInputMethodListAsUser 44 */ 45 suspend fun enabledInputMethods(userId: Int, fetchSubtypes: Boolean): Flow<InputMethodModel> 46 47 /** Returns enabled subtypes for the currently selected input method. */ 48 suspend fun selectedInputMethodSubtypes(): List<InputMethodModel.Subtype> 49 50 /** 51 * Shows the system's input method picker dialog. 52 * 53 * @param displayId The display ID on which to show the dialog. 54 * @param showAuxiliarySubtypes Whether to show auxiliary input method subtypes in the list of 55 * enabled IMEs. 56 * @see InputMethodManager.showInputMethodPickerFromSystem 57 */ 58 suspend fun showInputMethodPicker(displayId: Int, showAuxiliarySubtypes: Boolean) 59 } 60 61 @SysUISingleton 62 class InputMethodRepositoryImpl 63 @Inject 64 constructor( 65 @Background private val backgroundDispatcher: CoroutineDispatcher, 66 private val inputMethodManager: InputMethodManager, 67 ) : InputMethodRepository { 68 enabledInputMethodsnull69 override suspend fun enabledInputMethods( 70 userId: Int, 71 fetchSubtypes: Boolean 72 ): Flow<InputMethodModel> { 73 return withContext(backgroundDispatcher) { 74 inputMethodManager.getEnabledInputMethodListAsUser(UserHandle.of(userId)) 75 } 76 .asFlow() 77 .map { inputMethodInfo -> 78 InputMethodModel( 79 imeId = inputMethodInfo.id, 80 subtypes = 81 if (fetchSubtypes) { 82 enabledInputMethodSubtypes( 83 inputMethodInfo, 84 allowsImplicitlyEnabledSubtypes = true 85 ) 86 } else { 87 listOf() 88 } 89 ) 90 } 91 } 92 selectedInputMethodSubtypesnull93 override suspend fun selectedInputMethodSubtypes(): List<InputMethodModel.Subtype> { 94 return enabledInputMethodSubtypes( 95 inputMethodInfo = null, // Fetch subtypes for the currently-selected IME. 96 allowsImplicitlyEnabledSubtypes = false 97 ) 98 } 99 100 @SuppressLint("MissingPermission") showInputMethodPickernull101 override suspend fun showInputMethodPicker(displayId: Int, showAuxiliarySubtypes: Boolean) { 102 withContext(backgroundDispatcher) { 103 inputMethodManager.showInputMethodPickerFromSystem(showAuxiliarySubtypes, displayId) 104 } 105 } 106 107 /** 108 * Returns a list of enabled input method subtypes for the specified input method info. 109 * 110 * @param inputMethodInfo The [InputMethodInfo] whose subtypes list will be returned. If `null`, 111 * returns enabled subtypes for the currently selected [InputMethodInfo]. 112 * @param allowsImplicitlyEnabledSubtypes Whether to allow to return the implicitly enabled 113 * subtypes. If an input method info doesn't have enabled subtypes, the framework will 114 * implicitly enable subtypes according to the current system language. 115 * @see InputMethodManager.getEnabledInputMethodSubtypeList 116 */ enabledInputMethodSubtypesnull117 private suspend fun enabledInputMethodSubtypes( 118 inputMethodInfo: InputMethodInfo?, 119 allowsImplicitlyEnabledSubtypes: Boolean 120 ): List<InputMethodModel.Subtype> { 121 return withContext(backgroundDispatcher) { 122 inputMethodManager.getEnabledInputMethodSubtypeList( 123 inputMethodInfo, 124 allowsImplicitlyEnabledSubtypes 125 ) 126 } 127 .map { 128 InputMethodModel.Subtype( 129 subtypeId = it.subtypeId, 130 isAuxiliary = it.isAuxiliary, 131 ) 132 } 133 } 134 } 135 136 @Module 137 interface InputMethodRepositoryModule { repositorynull138 @Binds fun repository(impl: InputMethodRepositoryImpl): InputMethodRepository 139 } 140