Home | History | Annotate | Download | only in latin
      1 /*
      2  * Copyright (C) 2012 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.inputmethod.latin;
     18 
     19 import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
     20 
     21 import android.content.Context;
     22 import android.view.inputmethod.InputMethodInfo;
     23 import android.view.inputmethod.InputMethodManager;
     24 import android.view.inputmethod.InputMethodSubtype;
     25 
     26 import java.util.Collections;
     27 import java.util.List;
     28 
     29 /**
     30  * Utility class for Input Method Framework
     31  */
     32 public final class ImfUtils {
     33     private ImfUtils() {
     34         // This utility class is not publicly instantiable.
     35     }
     36 
     37     private static InputMethodManager sInputMethodManager;
     38 
     39     public static InputMethodManager getInputMethodManager(Context context) {
     40         if (sInputMethodManager == null) {
     41             sInputMethodManager = (InputMethodManager)context.getSystemService(
     42                     Context.INPUT_METHOD_SERVICE);
     43         }
     44         return sInputMethodManager;
     45     }
     46 
     47     private static InputMethodInfo sInputMethodInfoOfThisIme;
     48 
     49     public static InputMethodInfo getInputMethodInfoOfThisIme(Context context) {
     50         if (sInputMethodInfoOfThisIme == null) {
     51             final InputMethodManager imm = getInputMethodManager(context);
     52             final String packageName = context.getPackageName();
     53             for (final InputMethodInfo imi : imm.getInputMethodList()) {
     54                 if (imi.getPackageName().equals(packageName))
     55                     return imi;
     56             }
     57             throw new RuntimeException("Can not find input method id for " + packageName);
     58         }
     59         return sInputMethodInfoOfThisIme;
     60     }
     61 
     62     public static String getInputMethodIdOfThisIme(Context context) {
     63         return getInputMethodInfoOfThisIme(context).getId();
     64     }
     65 
     66     public static boolean checkIfSubtypeBelongsToThisImeAndEnabled(Context context,
     67             InputMethodSubtype ims) {
     68         final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
     69         final InputMethodManager imm = getInputMethodManager(context);
     70         // TODO: Cache all subtypes of this IME for optimization
     71         final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(myImi, true);
     72         for (final InputMethodSubtype subtype : subtypes) {
     73             if (subtype.equals(ims)) {
     74                 return true;
     75             }
     76         }
     77         return false;
     78     }
     79 
     80     public static boolean checkIfSubtypeBelongsToThisIme(Context context,
     81             InputMethodSubtype ims) {
     82         final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
     83         final int count = myImi.getSubtypeCount();
     84         for (int i = 0; i < count; i++) {
     85             final InputMethodSubtype subtype = myImi.getSubtypeAt(i);
     86             if (subtype.equals(ims)) {
     87                 return true;
     88             }
     89         }
     90         return false;
     91     }
     92 
     93     public static InputMethodSubtype getCurrentInputMethodSubtype(Context context,
     94             InputMethodSubtype defaultSubtype) {
     95         final InputMethodManager imm = getInputMethodManager(context);
     96         final InputMethodSubtype currentSubtype = imm.getCurrentInputMethodSubtype();
     97         return (currentSubtype != null) ? currentSubtype : defaultSubtype;
     98     }
     99 
    100     public static boolean hasMultipleEnabledIMEsOrSubtypes(Context context,
    101             final boolean shouldIncludeAuxiliarySubtypes) {
    102         final InputMethodManager imm = getInputMethodManager(context);
    103         final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
    104         return hasMultipleEnabledSubtypes(context, shouldIncludeAuxiliarySubtypes, enabledImis);
    105     }
    106 
    107     public static boolean hasMultipleEnabledSubtypesInThisIme(Context context,
    108             final boolean shouldIncludeAuxiliarySubtypes) {
    109         final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
    110         final List<InputMethodInfo> imiList = Collections.singletonList(myImi);
    111         return hasMultipleEnabledSubtypes(context, shouldIncludeAuxiliarySubtypes, imiList);
    112     }
    113 
    114     private static boolean hasMultipleEnabledSubtypes(Context context,
    115             final boolean shouldIncludeAuxiliarySubtypes, List<InputMethodInfo> imiList) {
    116         final InputMethodManager imm = getInputMethodManager(context);
    117 
    118         // Number of the filtered IMEs
    119         int filteredImisCount = 0;
    120 
    121         for (InputMethodInfo imi : imiList) {
    122             // We can return true immediately after we find two or more filtered IMEs.
    123             if (filteredImisCount > 1) return true;
    124             final List<InputMethodSubtype> subtypes =
    125                     imm.getEnabledInputMethodSubtypeList(imi, true);
    126             // IMEs that have no subtypes should be counted.
    127             if (subtypes.isEmpty()) {
    128                 ++filteredImisCount;
    129                 continue;
    130             }
    131 
    132             int auxCount = 0;
    133             for (InputMethodSubtype subtype : subtypes) {
    134                 if (subtype.isAuxiliary()) {
    135                     ++auxCount;
    136                 }
    137             }
    138             final int nonAuxCount = subtypes.size() - auxCount;
    139 
    140             // IMEs that have one or more non-auxiliary subtypes should be counted.
    141             // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
    142             // subtypes should be counted as well.
    143             if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
    144                 ++filteredImisCount;
    145                 continue;
    146             }
    147         }
    148 
    149         if (filteredImisCount > 1) {
    150             return true;
    151         }
    152         final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(null, true);
    153         int keyboardCount = 0;
    154         // imm.getEnabledInputMethodSubtypeList(null, true) will return the current IME's
    155         // both explicitly and implicitly enabled input method subtype.
    156         // (The current IME should be LatinIME.)
    157         for (InputMethodSubtype subtype : subtypes) {
    158             if (KEYBOARD_MODE.equals(subtype.getMode())) {
    159                 ++keyboardCount;
    160             }
    161         }
    162         return keyboardCount > 1;
    163     }
    164 
    165     public static InputMethodSubtype findSubtypeByLocaleAndKeyboardLayoutSet(
    166             Context context, String localeString, String keyboardLayoutSetName) {
    167         final InputMethodInfo imi = getInputMethodInfoOfThisIme(context);
    168         final int count = imi.getSubtypeCount();
    169         for (int i = 0; i < count; i++) {
    170             final InputMethodSubtype subtype = imi.getSubtypeAt(i);
    171             final String layoutName = SubtypeLocale.getKeyboardLayoutSetName(subtype);
    172             if (localeString.equals(subtype.getLocale())
    173                     && keyboardLayoutSetName.equals(layoutName)) {
    174                 return subtype;
    175             }
    176         }
    177         return null;
    178     }
    179 
    180     public static void setAdditionalInputMethodSubtypes(Context context,
    181             InputMethodSubtype[] subtypes) {
    182         final InputMethodManager imm = getInputMethodManager(context);
    183         final String imiId = getInputMethodIdOfThisIme(context);
    184         imm.setAdditionalInputMethodSubtypes(imiId, subtypes);
    185     }
    186 }
    187