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 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 boolean hasMultipleEnabledIMEsOrSubtypes(Context context,
     94             final boolean shouldIncludeAuxiliarySubtypes) {
     95         final InputMethodManager imm = getInputMethodManager(context);
     96         final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
     97         return hasMultipleEnabledSubtypes(context, shouldIncludeAuxiliarySubtypes, enabledImis);
     98     }
     99 
    100     public static boolean hasMultipleEnabledSubtypesInThisIme(Context context,
    101             final boolean shouldIncludeAuxiliarySubtypes) {
    102         final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
    103         final List<InputMethodInfo> imiList = Collections.singletonList(myImi);
    104         return hasMultipleEnabledSubtypes(context, shouldIncludeAuxiliarySubtypes, imiList);
    105     }
    106 
    107     private static boolean hasMultipleEnabledSubtypes(Context context,
    108             final boolean shouldIncludeAuxiliarySubtypes, List<InputMethodInfo> imiList) {
    109         final InputMethodManager imm = getInputMethodManager(context);
    110 
    111         // Number of the filtered IMEs
    112         int filteredImisCount = 0;
    113 
    114         for (InputMethodInfo imi : imiList) {
    115             // We can return true immediately after we find two or more filtered IMEs.
    116             if (filteredImisCount > 1) return true;
    117             final List<InputMethodSubtype> subtypes =
    118                     imm.getEnabledInputMethodSubtypeList(imi, true);
    119             // IMEs that have no subtypes should be counted.
    120             if (subtypes.isEmpty()) {
    121                 ++filteredImisCount;
    122                 continue;
    123             }
    124 
    125             int auxCount = 0;
    126             for (InputMethodSubtype subtype : subtypes) {
    127                 if (subtype.isAuxiliary()) {
    128                     ++auxCount;
    129                 }
    130             }
    131             final int nonAuxCount = subtypes.size() - auxCount;
    132 
    133             // IMEs that have one or more non-auxiliary subtypes should be counted.
    134             // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
    135             // subtypes should be counted as well.
    136             if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
    137                 ++filteredImisCount;
    138                 continue;
    139             }
    140         }
    141 
    142         if (filteredImisCount > 1) {
    143             return true;
    144         }
    145         final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(null, true);
    146         int keyboardCount = 0;
    147         // imm.getEnabledInputMethodSubtypeList(null, true) will return the current IME's
    148         // both explicitly and implicitly enabled input method subtype.
    149         // (The current IME should be LatinIME.)
    150         for (InputMethodSubtype subtype : subtypes) {
    151             if (KEYBOARD_MODE.equals(subtype.getMode())) {
    152                 ++keyboardCount;
    153             }
    154         }
    155         return keyboardCount > 1;
    156     }
    157 
    158     public static InputMethodSubtype findSubtypeByLocaleAndKeyboardLayoutSet(
    159             Context context, String localeString, String keyboardLayoutSetName) {
    160         final InputMethodInfo imi = getInputMethodInfoOfThisIme(context);
    161         final int count = imi.getSubtypeCount();
    162         for (int i = 0; i < count; i++) {
    163             final InputMethodSubtype subtype = imi.getSubtypeAt(i);
    164             final String layoutName = SubtypeLocale.getKeyboardLayoutSetName(subtype);
    165             if (localeString.equals(subtype.getLocale())
    166                     && keyboardLayoutSetName.equals(layoutName)) {
    167                 return subtype;
    168             }
    169         }
    170         return null;
    171     }
    172 
    173     public static void setAdditionalInputMethodSubtypes(Context context,
    174             InputMethodSubtype[] subtypes) {
    175         final InputMethodManager imm = getInputMethodManager(context);
    176         final String imiId = getInputMethodIdOfThisIme(context);
    177         imm.setAdditionalInputMethodSubtypes(imiId, subtypes);
    178     }
    179 }
    180