InputMethodSettingValuesWrapper.java revision 993f6ecf4065501433271b5fd5daf21a6f3ae586
1/*
2 * Copyright (C) 2013 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
19import com.android.internal.inputmethod.InputMethodUtils;
20import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
21
22import android.app.ActivityManagerNative;
23import android.content.Context;
24import android.os.RemoteException;
25import android.util.Log;
26import android.util.Slog;
27import android.view.inputmethod.InputMethodInfo;
28import android.view.inputmethod.InputMethodManager;
29import android.view.inputmethod.InputMethodSubtype;
30
31import java.util.ArrayList;
32import java.util.HashMap;
33import java.util.List;
34import java.util.Locale;
35
36/**
37 * This class is a wrapper for InputMethodSettings. You need to refresh internal states
38 * manually on some events when "InputMethodInfo"s and "InputMethodSubtype"s can be
39 * changed.
40 */
41public class InputMethodSettingValuesWrapper {
42    private static final String TAG = InputMethodSettingValuesWrapper.class.getSimpleName();
43    private static final Locale ENGLISH_LOCALE = new Locale("en");
44
45    private static volatile InputMethodSettingValuesWrapper sInstance;
46    private final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
47    private final HashMap<String, InputMethodInfo> mMethodMap =
48            new HashMap<String, InputMethodInfo>();
49    private final InputMethodSettings mSettings;
50    private final InputMethodManager mImm;
51
52    public static InputMethodSettingValuesWrapper getInstance(Context context) {
53        if (sInstance == null) {
54            synchronized(TAG) {
55                if (sInstance == null) {
56                    sInstance = new InputMethodSettingValuesWrapper(context);
57                }
58            }
59        }
60        return sInstance;
61    }
62
63    private static int getDefaultCurrentUserId() {
64        try {
65            return ActivityManagerNative.getDefault().getCurrentUser().id;
66        } catch (RemoteException e) {
67            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
68        }
69        return 0;
70    }
71
72    // Ensure singleton
73    private InputMethodSettingValuesWrapper(Context context) {
74        mSettings =
75                new InputMethodSettings(context.getResources(), context.getContentResolver(),
76                        mMethodMap, mMethodList, getDefaultCurrentUserId());
77        mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
78        refreshAllInputMethodAndSubtypes();
79    }
80
81    public void refreshAllInputMethodAndSubtypes() {
82        synchronized (mMethodMap) {
83            mMethodList.clear();
84            mMethodMap.clear();
85            final List<InputMethodInfo> imms = mImm.getInputMethodList();
86            mMethodList.addAll(imms);
87            for (InputMethodInfo imi : imms) {
88                mMethodMap.put(imi.getId(), imi);
89            }
90        }
91    }
92
93    public List<InputMethodInfo> getInputMethodList() {
94        synchronized (mMethodMap) {
95            return mMethodList;
96        }
97    }
98
99    public CharSequence getCurrentInputMethodName(Context context) {
100        synchronized (mMethodMap) {
101            final InputMethodInfo imi = mMethodMap.get(mSettings.getSelectedInputMethod());
102            if (imi == null) {
103                Log.w(TAG, "Invalid selected imi: " + mSettings.getSelectedInputMethod());
104                return "";
105            }
106            final InputMethodSubtype subtype = mImm.getCurrentInputMethodSubtype();
107            return InputMethodUtils.getImeAndSubtypeDisplayName(context, imi, subtype);
108        }
109    }
110
111    public boolean isAlwaysCheckedIme(InputMethodInfo imi, Context context) {
112        if (getInputMethodList().size() <= 1) {
113            return true;
114        }
115        if (!InputMethodUtils.isSystemIme(imi)) {
116            return false;
117        }
118        return isValidSystemNonAuxAsciiCapableIme(imi, context);
119    }
120
121    private static boolean isValidSystemNonAuxAsciiCapableIme(
122            InputMethodInfo imi, Context context) {
123        if (imi.isAuxiliaryIme()) {
124            return false;
125        }
126        if (InputMethodUtils.isValidSystemDefaultIme(true /* isSystemReady */, imi, context)) {
127            return true;
128        }
129        return InputMethodUtils.containsSubtypeOf(
130                imi, ENGLISH_LOCALE.getLanguage(), null /* mode */);
131    }
132}
133