1 /* 2 * Copyright (C) 2011 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.compat; 18 19 import android.content.Context; 20 import android.content.pm.ApplicationInfo; 21 import android.text.TextUtils; 22 import android.util.Log; 23 24 import com.android.inputmethod.latin.LatinImeLogger; 25 26 import java.lang.reflect.Method; 27 import java.util.Arrays; 28 import java.util.Locale; 29 30 // TODO: Override this class with the concrete implementation if we need to take care of the 31 // performance. 32 public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper { 33 private static final boolean DBG = LatinImeLogger.sDBG; 34 private static final String TAG = InputMethodSubtypeCompatWrapper.class.getSimpleName(); 35 private static final String DEFAULT_LOCALE = "en_US"; 36 private static final String DEFAULT_MODE = "keyboard"; 37 38 public static final Class<?> CLASS_InputMethodSubtype = 39 CompatUtils.getClass("android.view.inputmethod.InputMethodSubtype"); 40 private static final Method METHOD_getNameResId = 41 CompatUtils.getMethod(CLASS_InputMethodSubtype, "getNameResId"); 42 private static final Method METHOD_getIconResId = 43 CompatUtils.getMethod(CLASS_InputMethodSubtype, "getIconResId"); 44 private static final Method METHOD_getLocale = 45 CompatUtils.getMethod(CLASS_InputMethodSubtype, "getLocale"); 46 private static final Method METHOD_getMode = 47 CompatUtils.getMethod(CLASS_InputMethodSubtype, "getMode"); 48 private static final Method METHOD_getExtraValue = 49 CompatUtils.getMethod(CLASS_InputMethodSubtype, "getExtraValue"); 50 private static final Method METHOD_containsExtraValueKey = 51 CompatUtils.getMethod(CLASS_InputMethodSubtype, "containsExtraValueKey", String.class); 52 private static final Method METHOD_getExtraValueOf = 53 CompatUtils.getMethod(CLASS_InputMethodSubtype, "getExtraValueOf", String.class); 54 private static final Method METHOD_isAuxiliary = 55 CompatUtils.getMethod(CLASS_InputMethodSubtype, "isAuxiliary"); 56 private static final Method METHOD_getDisplayName = 57 CompatUtils.getMethod(CLASS_InputMethodSubtype, "getDisplayName", Context.class, 58 String.class, ApplicationInfo.class); 59 60 private final int mDummyNameResId; 61 private final int mDummyIconResId; 62 private final String mDummyLocale; 63 private final String mDummyMode; 64 private final String mDummyExtraValues; 65 66 public InputMethodSubtypeCompatWrapper(Object subtype) { 67 super((CLASS_InputMethodSubtype != null && CLASS_InputMethodSubtype.isInstance(subtype)) 68 ? subtype : null); 69 mDummyNameResId = 0; 70 mDummyIconResId = 0; 71 mDummyLocale = DEFAULT_LOCALE; 72 mDummyMode = DEFAULT_MODE; 73 mDummyExtraValues = ""; 74 } 75 76 // Constructor for creating a dummy subtype. 77 public InputMethodSubtypeCompatWrapper(int nameResId, int iconResId, String locale, 78 String mode, String extraValues) { 79 super(null); 80 if (DBG) { 81 Log.d(TAG, "CreateInputMethodSubtypeCompatWrapper"); 82 } 83 mDummyNameResId = nameResId; 84 mDummyIconResId = iconResId; 85 mDummyLocale = locale != null ? locale : ""; 86 mDummyMode = mode != null ? mode : ""; 87 mDummyExtraValues = extraValues != null ? extraValues : ""; 88 } 89 90 public int getNameResId() { 91 if (mObj == null) return mDummyNameResId; 92 return (Integer)CompatUtils.invoke(mObj, 0, METHOD_getNameResId); 93 } 94 95 public int getIconResId() { 96 if (mObj == null) return mDummyIconResId; 97 return (Integer)CompatUtils.invoke(mObj, 0, METHOD_getIconResId); 98 } 99 100 public String getLocale() { 101 if (mObj == null) return mDummyLocale; 102 final String s = (String)CompatUtils.invoke(mObj, null, METHOD_getLocale); 103 return s != null ? s : DEFAULT_LOCALE; 104 } 105 106 public String getMode() { 107 if (mObj == null) return mDummyMode; 108 String s = (String)CompatUtils.invoke(mObj, null, METHOD_getMode); 109 if (TextUtils.isEmpty(s)) return DEFAULT_MODE; 110 return s; 111 } 112 113 public String getExtraValue() { 114 if (mObj == null) return mDummyExtraValues; 115 return (String)CompatUtils.invoke(mObj, null, METHOD_getExtraValue); 116 } 117 118 public boolean containsExtraValueKey(String key) { 119 return (Boolean)CompatUtils.invoke(mObj, false, METHOD_containsExtraValueKey, key); 120 } 121 122 public String getExtraValueOf(String key) { 123 return (String)CompatUtils.invoke(mObj, null, METHOD_getExtraValueOf, key); 124 } 125 126 public boolean isAuxiliary() { 127 return (Boolean)CompatUtils.invoke(mObj, false, METHOD_isAuxiliary); 128 } 129 130 public CharSequence getDisplayName(Context context, String packageName, 131 ApplicationInfo appInfo) { 132 if (mObj != null) { 133 return (CharSequence)CompatUtils.invoke( 134 mObj, "", METHOD_getDisplayName, context, packageName, appInfo); 135 } 136 137 // The code below are based on {@link InputMethodSubtype#getDisplayName}. 138 139 final Locale locale = new Locale(getLocale()); 140 final String localeStr = locale.getDisplayName(); 141 if (getNameResId() == 0) { 142 return localeStr; 143 } 144 final CharSequence subtypeName = context.getText(getNameResId()); 145 if (!TextUtils.isEmpty(localeStr)) { 146 return String.format(subtypeName.toString(), localeStr); 147 } else { 148 return localeStr; 149 } 150 } 151 152 public boolean isDummy() { 153 return !hasOriginalObject(); 154 } 155 156 @Override 157 public boolean equals(Object o) { 158 if (o instanceof InputMethodSubtypeCompatWrapper) { 159 InputMethodSubtypeCompatWrapper subtype = (InputMethodSubtypeCompatWrapper)o; 160 if (mObj == null) { 161 // easy check of dummy subtypes 162 return (mDummyNameResId == subtype.mDummyNameResId 163 && mDummyIconResId == subtype.mDummyIconResId 164 && mDummyLocale.equals(subtype.mDummyLocale) 165 && mDummyMode.equals(subtype.mDummyMode) 166 && mDummyExtraValues.equals(subtype.mDummyExtraValues)); 167 } 168 return mObj.equals(subtype.getOriginalObject()); 169 } else { 170 return mObj.equals(o); 171 } 172 } 173 174 @Override 175 public int hashCode() { 176 if (mObj == null) { 177 return hashCodeInternal(mDummyNameResId, mDummyIconResId, mDummyLocale, 178 mDummyMode, mDummyExtraValues); 179 } 180 return mObj.hashCode(); 181 } 182 183 private static int hashCodeInternal(int nameResId, int iconResId, String locale, 184 String mode, String extraValue) { 185 return Arrays 186 .hashCode(new Object[] { nameResId, iconResId, locale, mode, extraValue }); 187 } 188 } 189