• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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