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