blob: 0dbab44d433c18f88d1acd85194ff85a18d1ad92 [file] [log] [blame]
Abodunrinwa Toki976bb3f2016-01-20 18:43:20 +00001/*
2 * Copyright (C) 2016 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
17package com.android.settings.inputmethod;
18
Yohei Yukawa2cae5b82016-04-15 04:03:38 -070019import android.annotation.DrawableRes;
20import android.annotation.NonNull;
21import android.annotation.Nullable;
Abodunrinwa Toki976bb3f2016-01-20 18:43:20 +000022import android.app.Activity;
23import android.app.admin.DevicePolicyManager;
24import android.content.Context;
Yohei Yukawa2cae5b82016-04-15 04:03:38 -070025import android.content.pm.ApplicationInfo;
26import android.content.pm.PackageManager;
27import android.content.pm.ServiceInfo;
Abodunrinwa Toki976bb3f2016-01-20 18:43:20 +000028import android.content.res.Configuration;
Abodunrinwa Toki567ebd62016-01-23 16:37:37 +000029import android.graphics.Color;
30import android.graphics.drawable.ColorDrawable;
31import android.graphics.drawable.Drawable;
Abodunrinwa Toki976bb3f2016-01-20 18:43:20 +000032import android.os.Bundle;
33import android.support.v7.preference.PreferenceScreen;
34import android.view.inputmethod.InputMethodInfo;
35import android.view.inputmethod.InputMethodManager;
Tamas Berghammer265d3c22016-06-22 15:34:45 +010036import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Abodunrinwa Toki976bb3f2016-01-20 18:43:20 +000037import com.android.settings.R;
Abodunrinwa Toki976bb3f2016-01-20 18:43:20 +000038import com.android.settings.SettingsPreferenceFragment;
39
40import java.text.Collator;
41import java.util.ArrayList;
42import java.util.Collections;
43import java.util.Comparator;
44import java.util.List;
45
46public final class AvailableVirtualKeyboardFragment extends SettingsPreferenceFragment
47 implements InputMethodPreference.OnSavePreferenceListener {
48
49 private final ArrayList<InputMethodPreference> mInputMethodPreferenceList = new ArrayList<>();
50 private InputMethodSettingValuesWrapper mInputMethodSettingValues;
51 private InputMethodManager mImm;
52 private DevicePolicyManager mDpm;
53
54 @Override
55 public void onCreatePreferences(Bundle bundle, String s) {
56 Activity activity = getActivity();
57 PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(activity);
58 screen.setTitle(activity.getString(R.string.available_virtual_keyboard_category));
59 setPreferenceScreen(screen);
60 mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(activity);
61 mImm = activity.getSystemService(InputMethodManager.class);
62 mDpm = activity.getSystemService(DevicePolicyManager.class);
63 }
64
65 @Override
66 public void onResume() {
67 super.onResume();
68 // Refresh internal states in mInputMethodSettingValues to keep the latest
69 // "InputMethodInfo"s and "InputMethodSubtype"s
70 mInputMethodSettingValues.refreshAllInputMethodAndSubtypes();
71 updateInputMethodPreferenceViews();
72 }
73
74 @Override
75 public void onSaveInputMethodPreference(final InputMethodPreference pref) {
76 final boolean hasHardwareKeyboard = getResources().getConfiguration().keyboard
77 == Configuration.KEYBOARD_QWERTY;
78 InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(),
79 mImm.getInputMethodList(), hasHardwareKeyboard);
80 // Update input method settings and preference list.
81 mInputMethodSettingValues.refreshAllInputMethodAndSubtypes();
82 for (final InputMethodPreference p : mInputMethodPreferenceList) {
83 p.updatePreferenceViews();
84 }
85 }
86
87 @Override
Fan Zhang65076132016-08-08 10:25:13 -070088 public int getMetricsCategory() {
Jason Monk3e19fc52016-03-08 14:18:30 -050089 return MetricsEvent.ENABLE_VIRTUAL_KEYBOARDS;
Abodunrinwa Toki976bb3f2016-01-20 18:43:20 +000090 }
91
Yohei Yukawa2cae5b82016-04-15 04:03:38 -070092 @Nullable
93 private static Drawable loadDrawable(@NonNull final PackageManager packageManager,
94 @NonNull final String packageName, @DrawableRes final int resId,
95 @NonNull final ApplicationInfo applicationInfo) {
96 if (resId == 0) {
97 return null;
98 }
99 try {
100 return packageManager.getDrawable(packageName, resId, applicationInfo);
101 } catch (Exception e){
102 return null;
103 }
104 }
105
106 @NonNull
107 private static Drawable getInputMethodIcon(@NonNull final PackageManager packageManager,
108 @NonNull final InputMethodInfo imi) {
109 final ServiceInfo si = imi.getServiceInfo();
110 final ApplicationInfo ai = si.applicationInfo;
111 final String packageName = imi.getPackageName();
112 if (si == null || ai == null || packageName == null) {
113 return new ColorDrawable(Color.TRANSPARENT);
114 }
115 // We do not use ServiceInfo#loadLogo() and ServiceInfo#loadIcon here since those methods
116 // internally have some fallback rules, which we want to do manually.
117 Drawable drawable = loadDrawable(packageManager, packageName, si.logo, ai);
118 if (drawable != null) {
119 return drawable;
120 }
121 drawable = loadDrawable(packageManager, packageName, si.icon, ai);
122 if (drawable != null) {
123 return drawable;
124 }
125 // We do not use ApplicationInfo#loadLogo() and ApplicationInfo#loadIcon here since those
126 // methods internally have some fallback rules, which we want to do manually.
127 drawable = loadDrawable(packageManager, packageName, ai.logo, ai);
128 if (drawable != null) {
129 return drawable;
130 }
131 drawable = loadDrawable(packageManager, packageName, ai.icon, ai);
132 if (drawable != null) {
133 return drawable;
134 }
135 return new ColorDrawable(Color.TRANSPARENT);
136 }
137
Abodunrinwa Toki976bb3f2016-01-20 18:43:20 +0000138 private void updateInputMethodPreferenceViews() {
139 mInputMethodSettingValues.refreshAllInputMethodAndSubtypes();
140 // Clear existing "InputMethodPreference"s
141 mInputMethodPreferenceList.clear();
142 List<String> permittedList = mDpm.getPermittedInputMethodsForCurrentUser();
143 final Context context = getPrefContext();
Yohei Yukawa2cae5b82016-04-15 04:03:38 -0700144 final PackageManager packageManager = getActivity().getPackageManager();
Abodunrinwa Toki976bb3f2016-01-20 18:43:20 +0000145 final List<InputMethodInfo> imis = mInputMethodSettingValues.getInputMethodList();
146 final int N = (imis == null ? 0 : imis.size());
147 for (int i = 0; i < N; ++i) {
148 final InputMethodInfo imi = imis.get(i);
149 final boolean isAllowedByOrganization = permittedList == null
150 || permittedList.contains(imi.getPackageName());
151 final InputMethodPreference pref = new InputMethodPreference(
152 context, imi, true, isAllowedByOrganization, this);
Yohei Yukawa2cae5b82016-04-15 04:03:38 -0700153 pref.setIcon(getInputMethodIcon(packageManager, imi));
Abodunrinwa Toki976bb3f2016-01-20 18:43:20 +0000154 mInputMethodPreferenceList.add(pref);
155 }
156 final Collator collator = Collator.getInstance();
157 Collections.sort(mInputMethodPreferenceList, new Comparator<InputMethodPreference>() {
158 @Override
159 public int compare(InputMethodPreference lhs, InputMethodPreference rhs) {
160 return lhs.compareTo(rhs, collator);
161 }
162 });
163 getPreferenceScreen().removeAll();
164 for (int i = 0; i < N; ++i) {
165 final InputMethodPreference pref = mInputMethodPreferenceList.get(i);
166 pref.setOrder(i);
167 getPreferenceScreen().addPreference(pref);
168 InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref);
169 pref.updatePreferenceViews();
170 }
171 }
172}