• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.car.settings.inputmethod;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.content.pm.PackageManager;
22 import android.content.pm.PackageManager.NameNotFoundException;
23 import android.graphics.Color;
24 import android.graphics.drawable.ColorDrawable;
25 import android.graphics.drawable.Drawable;
26 import android.provider.Settings;
27 import android.text.TextUtils;
28 import android.view.inputmethod.InputMethodInfo;
29 import android.view.inputmethod.InputMethodManager;
30 import android.view.inputmethod.InputMethodSubtype;
31 
32 import androidx.annotation.NonNull;
33 import androidx.annotation.VisibleForTesting;
34 
35 import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
36 
37 import java.util.List;
38 
39 /** Keyboard utility class. */
40 public final class InputMethodUtil {
41     /**
42      * Delimiter for Enabled Input Methods' concatenated string.
43      */
44     public static final char INPUT_METHOD_DELIMITER = ':';
45     /**
46      * Splitter for Enabled Input Methods' concatenated string.
47      */
48     public static final TextUtils.SimpleStringSplitter sInputMethodSplitter =
49             new TextUtils.SimpleStringSplitter(INPUT_METHOD_DELIMITER);
50     @VisibleForTesting
51     static final Drawable NO_ICON = new ColorDrawable(Color.TRANSPARENT);
52 
InputMethodUtil()53     private InputMethodUtil() {
54     }
55 
56     /** Returns package icon. */
getPackageIcon(@onNull PackageManager packageManager, @NonNull InputMethodInfo inputMethodInfo)57     public static Drawable getPackageIcon(@NonNull PackageManager packageManager,
58             @NonNull InputMethodInfo inputMethodInfo) {
59         Drawable icon;
60         try {
61             icon = packageManager.getApplicationIcon(inputMethodInfo.getPackageName());
62         } catch (NameNotFoundException e) {
63             icon = NO_ICON;
64         }
65 
66         return icon;
67     }
68 
69     /** Returns package label. */
getPackageLabel(@onNull PackageManager packageManager, @NonNull InputMethodInfo inputMethodInfo)70     public static String getPackageLabel(@NonNull PackageManager packageManager,
71             @NonNull InputMethodInfo inputMethodInfo) {
72         return inputMethodInfo.loadLabel(packageManager).toString();
73     }
74 
75     /** Returns input method summary. */
getSummaryString(@onNull Context context, @NonNull InputMethodManager inputMethodManager, @NonNull InputMethodInfo inputMethodInfo)76     public static String getSummaryString(@NonNull Context context,
77             @NonNull InputMethodManager inputMethodManager,
78             @NonNull InputMethodInfo inputMethodInfo) {
79         List<InputMethodSubtype> subtypes =
80                 inputMethodManager.getEnabledInputMethodSubtypeList(
81                         inputMethodInfo, /* allowsImplicitlySelectedSubtypes= */ true);
82         return InputMethodAndSubtypeUtil.getSubtypeLocaleNameListAsSentence(
83                 subtypes, context, inputMethodInfo);
84     }
85 
86     /**
87      * Check if input method is enabled.
88      *
89      * @return {@code true} if the input method is enabled.
90      */
isInputMethodEnabled(ContentResolver resolver, InputMethodInfo inputMethodInfo)91     public static boolean isInputMethodEnabled(ContentResolver resolver,
92             InputMethodInfo inputMethodInfo) {
93         sInputMethodSplitter.setString(getEnabledInputMethodsConcatenatedIds(resolver));
94         while (sInputMethodSplitter.hasNext()) {
95             String inputMethodId = sInputMethodSplitter.next();
96             if (inputMethodId.equals(inputMethodInfo.getId())) {
97                 return true;
98             }
99         }
100         return false;
101     }
102 
103     /**
104      * Enable an input method using its InputMethodInfo.
105      */
enableInputMethod(ContentResolver resolver, InputMethodInfo inputMethodInfo)106     public static void enableInputMethod(ContentResolver resolver,
107             InputMethodInfo inputMethodInfo) {
108         if (isInputMethodEnabled(resolver, inputMethodInfo)) {
109             return;
110         }
111 
112         StringBuilder builder = new StringBuilder();
113         builder.append(getEnabledInputMethodsConcatenatedIds(resolver));
114 
115         if (!builder.toString().isEmpty()) {
116             builder.append(INPUT_METHOD_DELIMITER);
117         }
118 
119         builder.append(inputMethodInfo.getId());
120 
121         setEnabledInputMethodsConcatenatedIds(resolver, builder.toString());
122     }
123 
124     /**
125      * Disable an input method if its not the default system input method or if there exists another
126      * enabled input method that can also be set as the default system input method.
127      */
disableInputMethod(Context context, InputMethodManager inputMethodManager, InputMethodInfo inputMethodInfo)128     public static void disableInputMethod(Context context, InputMethodManager inputMethodManager,
129             InputMethodInfo inputMethodInfo) {
130         List<InputMethodInfo> enabledInputMethodInfos = inputMethodManager
131                 .getEnabledInputMethodList();
132         StringBuilder builder = new StringBuilder();
133 
134         boolean foundAnotherEnabledDefaultInputMethod = false;
135         boolean isSystemDefault = isDefaultInputMethod(context.getContentResolver(),
136                 inputMethodInfo);
137         for (InputMethodInfo enabledInputMethodInfo : enabledInputMethodInfos) {
138             if (enabledInputMethodInfo.getId().equals(inputMethodInfo.getId())) {
139                 continue;
140             }
141 
142             if (builder.length() > 0) {
143                 builder.append(INPUT_METHOD_DELIMITER);
144             }
145 
146             builder.append(enabledInputMethodInfo.getId());
147 
148             if (isSystemDefault && enabledInputMethodInfo.isDefault(context)) {
149                 foundAnotherEnabledDefaultInputMethod = true;
150                 setDefaultInputMethodId(context.getContentResolver(),
151                         enabledInputMethodInfo.getId());
152             }
153         }
154 
155         if (isSystemDefault && !foundAnotherEnabledDefaultInputMethod) {
156             return;
157         }
158 
159         setEnabledInputMethodsConcatenatedIds(context.getContentResolver(), builder.toString());
160     }
161 
getEnabledInputMethodsConcatenatedIds(ContentResolver resolver)162     private static String getEnabledInputMethodsConcatenatedIds(ContentResolver resolver) {
163         return Settings.Secure.getString(resolver, Settings.Secure.ENABLED_INPUT_METHODS);
164     }
165 
getDefaultInputMethodId(ContentResolver resolver)166     private static String getDefaultInputMethodId(ContentResolver resolver) {
167         return Settings.Secure.getString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD);
168     }
169 
isDefaultInputMethod(ContentResolver resolver, InputMethodInfo inputMethodInfo)170     private static boolean isDefaultInputMethod(ContentResolver resolver,
171             InputMethodInfo inputMethodInfo) {
172         return inputMethodInfo.getId().equals(getDefaultInputMethodId(resolver));
173     }
174 
setEnabledInputMethodsConcatenatedIds(ContentResolver resolver, String enabledInputMethodIds)175     private static void setEnabledInputMethodsConcatenatedIds(ContentResolver resolver,
176             String enabledInputMethodIds) {
177         Settings.Secure.putString(resolver, Settings.Secure.ENABLED_INPUT_METHODS,
178                 enabledInputMethodIds);
179     }
180 
setDefaultInputMethodId(ContentResolver resolver, String defaultInputMethodId)181     private static void setDefaultInputMethodId(ContentResolver resolver,
182             String defaultInputMethodId) {
183         Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD,
184                 defaultInputMethodId);
185     }
186 }
187