• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.tv.settings.inputmethod;
18 
19 import android.app.ActivityManager;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.pm.PackageManager;
23 import android.os.Bundle;
24 import android.os.RemoteException;
25 import android.os.UserHandle;
26 import android.provider.Settings;
27 import android.support.v17.preference.LeanbackPreferenceFragment;
28 import android.support.v7.preference.ListPreference;
29 import android.support.v7.preference.Preference;
30 import android.support.v7.preference.PreferenceScreen;
31 import android.text.TextUtils;
32 import android.util.ArraySet;
33 import android.util.Log;
34 import android.view.inputmethod.InputMethodInfo;
35 import android.view.inputmethod.InputMethodManager;
36 
37 import com.android.tv.settings.R;
38 
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.Set;
42 
43 /**
44  * Fragment for managing IMEs
45  */
46 public class KeyboardFragment extends LeanbackPreferenceFragment {
47     private static final String TAG = "KeyboardFragment";
48     private static final String KEY_CURRENT_KEYBOARD = "currentKeyboard";
49     private static final String KEY_MANAGE_KEYBOARDS = "manageKeyboards";
50 
51     private static final String KEY_KEYBOARD_SETTINGS_PREFIX = "keyboardSettings:";
52 
53     private InputMethodManager mInputMethodManager;
54 
55     /**
56      * @return New fragment instance
57      */
newInstance()58     public static KeyboardFragment newInstance() {
59         return new KeyboardFragment();
60     }
61 
62     @Override
onCreate(Bundle savedInstanceState)63     public void onCreate(Bundle savedInstanceState) {
64         mInputMethodManager =
65                 (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
66 
67         super.onCreate(savedInstanceState);
68     }
69 
70     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)71     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
72         final Context preferenceContext = getPreferenceManager().getContext();
73 
74         final PreferenceScreen screen =
75                 getPreferenceManager().createPreferenceScreen(preferenceContext);
76         screen.setTitle(R.string.system_keyboard);
77         setPreferenceScreen(screen);
78 
79         final ListPreference currentKeyboard = new ListPreference(preferenceContext);
80         currentKeyboard.setPersistent(false);
81         currentKeyboard.setTitle(R.string.title_current_keyboard);
82         currentKeyboard.setDialogTitle(R.string.title_current_keyboard);
83         currentKeyboard.setSummary("%s");
84         currentKeyboard.setKey(KEY_CURRENT_KEYBOARD);
85         currentKeyboard.setOnPreferenceChangeListener((preference, newValue) -> {
86             setInputMethod((String) newValue);
87             return true;
88         });
89         updateCurrentKeyboardPreference(currentKeyboard);
90         screen.addPreference(currentKeyboard);
91 
92         final Preference manageKeyboards = new Preference(preferenceContext);
93         manageKeyboards.setTitle(R.string.manage_keyboards);
94         manageKeyboards.setKey(KEY_MANAGE_KEYBOARDS);
95         manageKeyboards.setFragment(AvailableVirtualKeyboardFragment.class.getName());
96         screen.addPreference(manageKeyboards);
97 
98         updatePrefs();
99     }
100 
101     @Override
onResume()102     public void onResume() {
103         super.onResume();
104         updatePrefs();
105         final Preference currentKeyboard = findPreference(KEY_CURRENT_KEYBOARD);
106         if (currentKeyboard instanceof ListPreference) {
107             updateCurrentKeyboardPreference((ListPreference) currentKeyboard);
108         }
109     }
110 
updateCurrentKeyboardPreference(ListPreference currentKeyboardPref)111     private void updateCurrentKeyboardPreference(ListPreference currentKeyboardPref) {
112         final PackageManager packageManager = getActivity().getPackageManager();
113         List<InputMethodInfo> enabledInputMethodInfos = getEnabledSystemInputMethodList();
114         final List<CharSequence> entries = new ArrayList<>(enabledInputMethodInfos.size());
115         final List<CharSequence> values = new ArrayList<>(enabledInputMethodInfos.size());
116 
117         int defaultIndex = 0;
118         final String defaultId = Settings.Secure.getString(getActivity().getContentResolver(),
119                 Settings.Secure.DEFAULT_INPUT_METHOD);
120 
121         for (final InputMethodInfo info : enabledInputMethodInfos) {
122             entries.add(info.loadLabel(packageManager));
123             final String id = info.getId();
124             values.add(id);
125             if (TextUtils.equals(id, defaultId)) {
126                 defaultIndex = values.size() - 1;
127             }
128         }
129 
130         currentKeyboardPref.setEntries(entries.toArray(new CharSequence[entries.size()]));
131         currentKeyboardPref.setEntryValues(values.toArray(new CharSequence[values.size()]));
132         if (entries.size() > 0) {
133             currentKeyboardPref.setValueIndex(defaultIndex);
134         }
135     }
136 
updatePrefs()137     private void updatePrefs() {
138         final Context preferenceContext = getPreferenceManager().getContext();
139         final PackageManager packageManager = getActivity().getPackageManager();
140         List<InputMethodInfo> enabledInputMethodInfos = getEnabledSystemInputMethodList();
141 
142         final PreferenceScreen screen = getPreferenceScreen();
143 
144         final Set<String> enabledInputMethodKeys = new ArraySet<>(enabledInputMethodInfos.size());
145         // Add per-IME settings
146         for (final InputMethodInfo info : enabledInputMethodInfos) {
147             final Intent settingsIntent = getInputMethodSettingsIntent(info);
148             if (settingsIntent == null) {
149                 continue;
150             }
151             final String key = KEY_KEYBOARD_SETTINGS_PREFIX + info.getId();
152 
153             Preference preference = findPreference(key);
154             if (preference == null) {
155                 preference = new Preference(preferenceContext);
156                 screen.addPreference(preference);
157             }
158             preference.setTitle(info.loadLabel(packageManager));
159             preference.setKey(key);
160             preference.setIntent(settingsIntent);
161             enabledInputMethodKeys.add(key);
162         }
163 
164         for (int i = 0; i < screen.getPreferenceCount();) {
165             final Preference preference = screen.getPreference(i);
166             final String key = preference.getKey();
167             if (!TextUtils.isEmpty(key)
168                     && key.startsWith(KEY_KEYBOARD_SETTINGS_PREFIX)
169                     && !enabledInputMethodKeys.contains(key)) {
170                 screen.removePreference(preference);
171             } else {
172                 i++;
173             }
174         }
175     }
176 
setInputMethod(String imid)177     private void setInputMethod(String imid) {
178         if (imid == null) {
179             throw new IllegalArgumentException("Null ID");
180         }
181 
182         int userId;
183         try {
184             userId = ActivityManager.getService().getCurrentUser().id;
185             Settings.Secure.putStringForUser(getActivity().getContentResolver(),
186                     Settings.Secure.DEFAULT_INPUT_METHOD, imid, userId);
187 
188             Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
189             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
190             intent.putExtra("input_method_id", imid);
191             getActivity().sendBroadcastAsUser(intent, UserHandle.CURRENT);
192         } catch (RemoteException e) {
193             Log.d(TAG, "set default input method remote exception");
194         }
195     }
196 
getEnabledSystemInputMethodList()197     private List<InputMethodInfo> getEnabledSystemInputMethodList() {
198         List<InputMethodInfo> enabledInputMethodInfos =
199                 new ArrayList<>(mInputMethodManager.getEnabledInputMethodList());
200         // Filter auxiliary keyboards out
201         enabledInputMethodInfos.removeIf(InputMethodInfo::isAuxiliaryIme);
202         return enabledInputMethodInfos;
203     }
204 
getInputMethodSettingsIntent(InputMethodInfo imi)205     private Intent getInputMethodSettingsIntent(InputMethodInfo imi) {
206         final Intent intent;
207         final String settingsActivity = imi.getSettingsActivity();
208         if (!TextUtils.isEmpty(settingsActivity)) {
209             intent = new Intent(Intent.ACTION_MAIN);
210             intent.setClassName(imi.getPackageName(), settingsActivity);
211         } else {
212             intent = null;
213         }
214         return intent;
215     }
216 }
217