This is a follow up CL for a recent attempt to minimize the number of default enabled IMEs. - part1: I831502db502f4073c9c2f50ce7705a4e45e2e1e3 - part2: Ife93d909fb8a24471c425c903e2b7048826e17a3 - part3: I6571d464a46453934f0a8f5e79018a67a9a3c845 - part4: I871ccda787eb0f1099ba3574356c1da4b33681f3 In the above changes, InputMethodUtils.isValidSystemDefaultIme was deprecated in favor of InputMethodUtils.isSystemImeThatHasSubtypeOf. With this CL, InputMethodUtils.isValidSystemDefaultIme is not used by the setting app anymore and we can remove that method from InputMethodUtils finally. This is a pure code refactoring with preserving the current logic. Hence no behavior change is intended. Change-Id: Ie96b0d17745735db63eebe6fe1654f32d9b9a170
204 lines
7.6 KiB
Java
204 lines
7.6 KiB
Java
/*
|
|
* Copyright (C) 2013 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.settings.inputmethod;
|
|
|
|
import com.android.internal.inputmethod.InputMethodUtils;
|
|
import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
|
|
|
|
import android.app.ActivityManagerNative;
|
|
import android.content.Context;
|
|
import android.os.RemoteException;
|
|
import android.util.Log;
|
|
import android.util.Slog;
|
|
import android.view.inputmethod.InputMethodInfo;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
import android.view.inputmethod.InputMethodSubtype;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
|
|
/**
|
|
* This class is a wrapper for InputMethodSettings. You need to refresh internal states
|
|
* manually on some events when "InputMethodInfo"s and "InputMethodSubtype"s can be
|
|
* changed.
|
|
*/
|
|
// TODO: Consolidate this with {@link InputMethodAndSubtypeUtil}.
|
|
class InputMethodSettingValuesWrapper {
|
|
private static final String TAG = InputMethodSettingValuesWrapper.class.getSimpleName();
|
|
|
|
private static volatile InputMethodSettingValuesWrapper sInstance;
|
|
private final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>();
|
|
private final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<>();
|
|
private final InputMethodSettings mSettings;
|
|
private final InputMethodManager mImm;
|
|
private final HashSet<InputMethodInfo> mAsciiCapableEnabledImis = new HashSet<>();
|
|
|
|
static InputMethodSettingValuesWrapper getInstance(Context context) {
|
|
if (sInstance == null) {
|
|
synchronized (TAG) {
|
|
if (sInstance == null) {
|
|
sInstance = new InputMethodSettingValuesWrapper(context);
|
|
}
|
|
}
|
|
}
|
|
return sInstance;
|
|
}
|
|
|
|
private static int getDefaultCurrentUserId() {
|
|
try {
|
|
return ActivityManagerNative.getDefault().getCurrentUser().id;
|
|
} catch (RemoteException e) {
|
|
Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Ensure singleton
|
|
private InputMethodSettingValuesWrapper(Context context) {
|
|
mSettings = new InputMethodSettings(context.getResources(), context.getContentResolver(),
|
|
mMethodMap, mMethodList, getDefaultCurrentUserId());
|
|
mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
refreshAllInputMethodAndSubtypes();
|
|
}
|
|
|
|
void refreshAllInputMethodAndSubtypes() {
|
|
synchronized (mMethodMap) {
|
|
mMethodList.clear();
|
|
mMethodMap.clear();
|
|
final List<InputMethodInfo> imms = mImm.getInputMethodList();
|
|
mMethodList.addAll(imms);
|
|
for (InputMethodInfo imi : imms) {
|
|
mMethodMap.put(imi.getId(), imi);
|
|
}
|
|
updateAsciiCapableEnabledImis();
|
|
}
|
|
}
|
|
|
|
// TODO: Add a cts to ensure at least one AsciiCapableSubtypeEnabledImis exist
|
|
private void updateAsciiCapableEnabledImis() {
|
|
synchronized (mMethodMap) {
|
|
mAsciiCapableEnabledImis.clear();
|
|
final List<InputMethodInfo> enabledImis = mSettings.getEnabledInputMethodListLocked();
|
|
for (final InputMethodInfo imi : enabledImis) {
|
|
final int subtypeCount = imi.getSubtypeCount();
|
|
for (int i = 0; i < subtypeCount; ++i) {
|
|
final InputMethodSubtype subtype = imi.getSubtypeAt(i);
|
|
if (InputMethodUtils.SUBTYPE_MODE_KEYBOARD.equalsIgnoreCase(subtype.getMode())
|
|
&& subtype.isAsciiCapable()) {
|
|
mAsciiCapableEnabledImis.add(imi);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
List<InputMethodInfo> getInputMethodList() {
|
|
synchronized (mMethodMap) {
|
|
return mMethodList;
|
|
}
|
|
}
|
|
|
|
CharSequence getCurrentInputMethodName(Context context) {
|
|
synchronized (mMethodMap) {
|
|
final InputMethodInfo imi = mMethodMap.get(mSettings.getSelectedInputMethod());
|
|
if (imi == null) {
|
|
Log.w(TAG, "Invalid selected imi: " + mSettings.getSelectedInputMethod());
|
|
return "";
|
|
}
|
|
final InputMethodSubtype subtype = mImm.getCurrentInputMethodSubtype();
|
|
return InputMethodUtils.getImeAndSubtypeDisplayName(context, imi, subtype);
|
|
}
|
|
}
|
|
|
|
boolean isAlwaysCheckedIme(InputMethodInfo imi, Context context) {
|
|
final boolean isEnabled = isEnabledImi(imi);
|
|
synchronized (mMethodMap) {
|
|
if (mSettings.getEnabledInputMethodListLocked().size() <= 1 && isEnabled) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
final int enabledValidSystemNonAuxAsciiCapableImeCount =
|
|
getEnabledValidSystemNonAuxAsciiCapableImeCount(context);
|
|
if (enabledValidSystemNonAuxAsciiCapableImeCount > 1) {
|
|
return false;
|
|
}
|
|
|
|
if (enabledValidSystemNonAuxAsciiCapableImeCount == 1 && !isEnabled) {
|
|
return false;
|
|
}
|
|
|
|
if (!InputMethodUtils.isSystemIme(imi)) {
|
|
return false;
|
|
}
|
|
return isValidSystemNonAuxAsciiCapableIme(imi, context);
|
|
}
|
|
|
|
private int getEnabledValidSystemNonAuxAsciiCapableImeCount(Context context) {
|
|
int count = 0;
|
|
final List<InputMethodInfo> enabledImis;
|
|
synchronized (mMethodMap) {
|
|
enabledImis = mSettings.getEnabledInputMethodListLocked();
|
|
}
|
|
for (final InputMethodInfo imi : enabledImis) {
|
|
if (isValidSystemNonAuxAsciiCapableIme(imi, context)) {
|
|
++count;
|
|
}
|
|
}
|
|
if (count == 0) {
|
|
Log.w(TAG, "No \"enabledValidSystemNonAuxAsciiCapableIme\"s found.");
|
|
}
|
|
return count;
|
|
}
|
|
|
|
boolean isEnabledImi(InputMethodInfo imi) {
|
|
final List<InputMethodInfo> enabledImis;
|
|
synchronized (mMethodMap) {
|
|
enabledImis = mSettings.getEnabledInputMethodListLocked();
|
|
}
|
|
for (final InputMethodInfo tempImi : enabledImis) {
|
|
if (tempImi.getId().equals(imi.getId())) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
boolean isValidSystemNonAuxAsciiCapableIme(InputMethodInfo imi, Context context) {
|
|
if (imi.isAuxiliaryIme()) {
|
|
return false;
|
|
}
|
|
final Locale systemLocale = context.getResources().getConfiguration().locale;
|
|
if (InputMethodUtils.isSystemImeThatHasSubtypeOf(imi, context,
|
|
true /* checkDefaultAttribute */, systemLocale, false /* checkCountry */,
|
|
InputMethodUtils.SUBTYPE_MODE_ANY)) {
|
|
return true;
|
|
}
|
|
if (mAsciiCapableEnabledImis.isEmpty()) {
|
|
Log.w(TAG, "ascii capable subtype enabled imi not found. Fall back to English"
|
|
+ " Keyboard subtype.");
|
|
return InputMethodUtils.containsSubtypeOf(imi, Locale.ENGLISH, false /* checkCountry */,
|
|
InputMethodUtils.SUBTYPE_MODE_KEYBOARD);
|
|
}
|
|
return mAsciiCapableEnabledImis.contains(imi);
|
|
}
|
|
}
|