Files
app_Settings/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java
Yohei Yukawa 143a686947 Stop using a deprecated constructor of InputMethodSettings.
This is a follow up CL to my previous CL [1], which added a new
constructor to InputMethodSettings to support File-Based
Encryption (FBE).

Settings app is the only remaining package that depends on the previous
constructor.  To completely deprecate the previous one, this CL lets the
caller switch to the new constructor.

Note that this CL does not change the initial parameters of
InputMethodSettings.  In other words this is a mechanical code
clean-up.

  [1] I9c6f9bb3d51174198e5f73588637f87ea0d90e11
      5db2f16f15549c490c9541602a96f42bef984acb

Bug: 26279466
Change-Id: I09cba4066b95c4a9e89a3e4f83d75b97882502dc
2016-03-16 20:50:28 -07:00

204 lines
7.7 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 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 com.android.internal.inputmethod.InputMethodUtils;
import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
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(), false /* copyOnWrite */);
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);
}
}