• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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.inputmethod.latin;
18 
19 import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
20 
21 import android.content.Context;
22 import android.view.inputmethod.InputMethodInfo;
23 import android.view.inputmethod.InputMethodManager;
24 import android.view.inputmethod.InputMethodSubtype;
25 
26 import java.util.Collections;
27 import java.util.List;
28 
29 /**
30  * Utility class for Input Method Framework
31  */
32 public class ImfUtils {
ImfUtils()33     private ImfUtils() {
34         // This utility class is not publicly instantiable.
35     }
36 
37     private static InputMethodManager sInputMethodManager;
38 
getInputMethodManager(Context context)39     public static InputMethodManager getInputMethodManager(Context context) {
40         if (sInputMethodManager == null) {
41             sInputMethodManager = (InputMethodManager)context.getSystemService(
42                     Context.INPUT_METHOD_SERVICE);
43         }
44         return sInputMethodManager;
45     }
46 
47     private static InputMethodInfo sInputMethodInfoOfThisIme;
48 
getInputMethodInfoOfThisIme(Context context)49     public static InputMethodInfo getInputMethodInfoOfThisIme(Context context) {
50         if (sInputMethodInfoOfThisIme == null) {
51             final InputMethodManager imm = getInputMethodManager(context);
52             final String packageName = context.getPackageName();
53             for (final InputMethodInfo imi : imm.getInputMethodList()) {
54                 if (imi.getPackageName().equals(packageName))
55                     return imi;
56             }
57             throw new RuntimeException("Can not find input method id for " + packageName);
58         }
59         return sInputMethodInfoOfThisIme;
60     }
61 
getInputMethodIdOfThisIme(Context context)62     public static String getInputMethodIdOfThisIme(Context context) {
63         return getInputMethodInfoOfThisIme(context).getId();
64     }
65 
checkIfSubtypeBelongsToThisImeAndEnabled(Context context, InputMethodSubtype ims)66     public static boolean checkIfSubtypeBelongsToThisImeAndEnabled(Context context,
67             InputMethodSubtype ims) {
68         final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
69         final InputMethodManager imm = getInputMethodManager(context);
70         // TODO: Cache all subtypes of this IME for optimization
71         final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(myImi, true);
72         for (final InputMethodSubtype subtype : subtypes) {
73             if (subtype.equals(ims)) {
74                 return true;
75             }
76         }
77         return false;
78     }
79 
checkIfSubtypeBelongsToThisIme(Context context, InputMethodSubtype ims)80     public static boolean checkIfSubtypeBelongsToThisIme(Context context,
81             InputMethodSubtype ims) {
82         final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
83         final int count = myImi.getSubtypeCount();
84         for (int i = 0; i < count; i++) {
85             final InputMethodSubtype subtype = myImi.getSubtypeAt(i);
86             if (subtype.equals(ims)) {
87                 return true;
88             }
89         }
90         return false;
91     }
92 
hasMultipleEnabledIMEsOrSubtypes(Context context, final boolean shouldIncludeAuxiliarySubtypes)93     public static boolean hasMultipleEnabledIMEsOrSubtypes(Context context,
94             final boolean shouldIncludeAuxiliarySubtypes) {
95         final InputMethodManager imm = getInputMethodManager(context);
96         final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
97         return hasMultipleEnabledSubtypes(context, shouldIncludeAuxiliarySubtypes, enabledImis);
98     }
99 
hasMultipleEnabledSubtypesInThisIme(Context context, final boolean shouldIncludeAuxiliarySubtypes)100     public static boolean hasMultipleEnabledSubtypesInThisIme(Context context,
101             final boolean shouldIncludeAuxiliarySubtypes) {
102         final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
103         final List<InputMethodInfo> imiList = Collections.singletonList(myImi);
104         return hasMultipleEnabledSubtypes(context, shouldIncludeAuxiliarySubtypes, imiList);
105     }
106 
hasMultipleEnabledSubtypes(Context context, final boolean shouldIncludeAuxiliarySubtypes, List<InputMethodInfo> imiList)107     private static boolean hasMultipleEnabledSubtypes(Context context,
108             final boolean shouldIncludeAuxiliarySubtypes, List<InputMethodInfo> imiList) {
109         final InputMethodManager imm = getInputMethodManager(context);
110 
111         // Number of the filtered IMEs
112         int filteredImisCount = 0;
113 
114         for (InputMethodInfo imi : imiList) {
115             // We can return true immediately after we find two or more filtered IMEs.
116             if (filteredImisCount > 1) return true;
117             final List<InputMethodSubtype> subtypes =
118                     imm.getEnabledInputMethodSubtypeList(imi, true);
119             // IMEs that have no subtypes should be counted.
120             if (subtypes.isEmpty()) {
121                 ++filteredImisCount;
122                 continue;
123             }
124 
125             int auxCount = 0;
126             for (InputMethodSubtype subtype : subtypes) {
127                 if (subtype.isAuxiliary()) {
128                     ++auxCount;
129                 }
130             }
131             final int nonAuxCount = subtypes.size() - auxCount;
132 
133             // IMEs that have one or more non-auxiliary subtypes should be counted.
134             // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
135             // subtypes should be counted as well.
136             if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
137                 ++filteredImisCount;
138                 continue;
139             }
140         }
141 
142         if (filteredImisCount > 1) {
143             return true;
144         }
145         final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(null, true);
146         int keyboardCount = 0;
147         // imm.getEnabledInputMethodSubtypeList(null, true) will return the current IME's
148         // both explicitly and implicitly enabled input method subtype.
149         // (The current IME should be LatinIME.)
150         for (InputMethodSubtype subtype : subtypes) {
151             if (KEYBOARD_MODE.equals(subtype.getMode())) {
152                 ++keyboardCount;
153             }
154         }
155         return keyboardCount > 1;
156     }
157 
findSubtypeByLocaleAndKeyboardLayoutSet( Context context, String localeString, String keyboardLayoutSetName)158     public static InputMethodSubtype findSubtypeByLocaleAndKeyboardLayoutSet(
159             Context context, String localeString, String keyboardLayoutSetName) {
160         final InputMethodInfo imi = getInputMethodInfoOfThisIme(context);
161         final int count = imi.getSubtypeCount();
162         for (int i = 0; i < count; i++) {
163             final InputMethodSubtype subtype = imi.getSubtypeAt(i);
164             final String layoutName = SubtypeLocale.getKeyboardLayoutSetName(subtype);
165             if (localeString.equals(subtype.getLocale())
166                     && keyboardLayoutSetName.equals(layoutName)) {
167                 return subtype;
168             }
169         }
170         return null;
171     }
172 
setAdditionalInputMethodSubtypes(Context context, InputMethodSubtype[] subtypes)173     public static void setAdditionalInputMethodSubtypes(Context context,
174             InputMethodSubtype[] subtypes) {
175         final InputMethodManager imm = getInputMethodManager(context);
176         final String imiId = getInputMethodIdOfThisIme(context);
177         imm.setAdditionalInputMethodSubtypes(imiId, subtypes);
178     }
179 }
180