12cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok/* 22cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * Copyright (C) 2011 The Android Open Source Project 32cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * 42cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * Licensed under the Apache License, Version 2.0 (the "License"); 52cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * you may not use this file except in compliance with the License. 62cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * You may obtain a copy of the License at 72cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * 82cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * http://www.apache.org/licenses/LICENSE-2.0 92cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * 102cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * Unless required by applicable law or agreed to in writing, software 112cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * distributed under the License is distributed on an "AS IS" BASIS, 122cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * See the License for the specific language governing permissions and 142cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok * limitations under the License. 152cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok */ 162cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok 172cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatokpackage com.android.inputmethod.compat; 182cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok 192cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatokimport android.text.TextUtils; 20610f1dc8553cf2ed97e763a06a19380c4a6cd636satokimport android.util.Log; 21610f1dc8553cf2ed97e763a06a19380c4a6cd636satok 22b2707856aba4fc9b063f26305f1fb603b19c1701satokimport java.lang.reflect.Constructor; 2324119dfd414f948b2da214c021cc76e06b3dd41csatokimport java.lang.reflect.Field; 2403a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaokaimport java.lang.reflect.InvocationTargetException; 25610f1dc8553cf2ed97e763a06a19380c4a6cd636satokimport java.lang.reflect.Method; 262cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok 271e11c44d1b5f9ddf593c5407cb14c458be0056f2Tadashi G. Takaokapublic final class CompatUtils { 28610f1dc8553cf2ed97e763a06a19380c4a6cd636satok private static final String TAG = CompatUtils.class.getSimpleName(); 292cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok 30298b4240f84344bbcd70b72dfb20806ba93ffd22Tadashi G. Takaoka private CompatUtils() { 31298b4240f84344bbcd70b72dfb20806ba93ffd22Tadashi G. Takaoka // This utility class is not publicly instantiable. 322cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok } 33610f1dc8553cf2ed97e763a06a19380c4a6cd636satok 34b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa public static Class<?> getClass(final String className) { 35610f1dc8553cf2ed97e763a06a19380c4a6cd636satok try { 36610f1dc8553cf2ed97e763a06a19380c4a6cd636satok return Class.forName(className); 3703a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } catch (final ClassNotFoundException e) { 38610f1dc8553cf2ed97e763a06a19380c4a6cd636satok return null; 39610f1dc8553cf2ed97e763a06a19380c4a6cd636satok } 40610f1dc8553cf2ed97e763a06a19380c4a6cd636satok } 41610f1dc8553cf2ed97e763a06a19380c4a6cd636satok 42b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa public static Method getMethod(final Class<?> targetClass, final String name, 43b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa final Class<?>... parameterTypes) { 4403a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka if (targetClass == null || TextUtils.isEmpty(name)) { 4503a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka return null; 4603a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } 47610f1dc8553cf2ed97e763a06a19380c4a6cd636satok try { 48610f1dc8553cf2ed97e763a06a19380c4a6cd636satok return targetClass.getMethod(name, parameterTypes); 4903a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } catch (final SecurityException | NoSuchMethodException e) { 50610f1dc8553cf2ed97e763a06a19380c4a6cd636satok // ignore 51610f1dc8553cf2ed97e763a06a19380c4a6cd636satok } 521fef530ec7626fa16777f52b48191e61db8f46d4satok return null; 53610f1dc8553cf2ed97e763a06a19380c4a6cd636satok } 54610f1dc8553cf2ed97e763a06a19380c4a6cd636satok 55b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa public static Field getField(final Class<?> targetClass, final String name) { 5603a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka if (targetClass == null || TextUtils.isEmpty(name)) { 5703a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka return null; 5803a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } 5924119dfd414f948b2da214c021cc76e06b3dd41csatok try { 6024119dfd414f948b2da214c021cc76e06b3dd41csatok return targetClass.getField(name); 6103a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } catch (final SecurityException | NoSuchFieldException e) { 6224119dfd414f948b2da214c021cc76e06b3dd41csatok // ignore 6324119dfd414f948b2da214c021cc76e06b3dd41csatok } 641fef530ec7626fa16777f52b48191e61db8f46d4satok return null; 6524119dfd414f948b2da214c021cc76e06b3dd41csatok } 6624119dfd414f948b2da214c021cc76e06b3dd41csatok 67b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa public static Constructor<?> getConstructor(final Class<?> targetClass, 68b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa final Class<?> ... types) { 6903a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka if (targetClass == null || types == null) { 7003a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka return null; 7103a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } 72b2707856aba4fc9b063f26305f1fb603b19c1701satok try { 73b2707856aba4fc9b063f26305f1fb603b19c1701satok return targetClass.getConstructor(types); 7403a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } catch (final SecurityException | NoSuchMethodException e) { 75b2707856aba4fc9b063f26305f1fb603b19c1701satok // ignore 76b2707856aba4fc9b063f26305f1fb603b19c1701satok } 771fef530ec7626fa16777f52b48191e61db8f46d4satok return null; 781fef530ec7626fa16777f52b48191e61db8f46d4satok } 791fef530ec7626fa16777f52b48191e61db8f46d4satok 80b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa public static Object newInstance(final Constructor<?> constructor, final Object ... args) { 8103a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka if (constructor == null) { 8203a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka return null; 8303a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } 841fef530ec7626fa16777f52b48191e61db8f46d4satok try { 851fef530ec7626fa16777f52b48191e61db8f46d4satok return constructor.newInstance(args); 8603a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } catch (final InstantiationException | IllegalAccessException | IllegalArgumentException 8703a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka | InvocationTargetException e) { 88a8d3d50970cecf961940efc0e908fbb2f9b35472Ken Wakasa Log.e(TAG, "Exception in newInstance", e); 891fef530ec7626fa16777f52b48191e61db8f46d4satok } 901fef530ec7626fa16777f52b48191e61db8f46d4satok return null; 91b2707856aba4fc9b063f26305f1fb603b19c1701satok } 92b2707856aba4fc9b063f26305f1fb603b19c1701satok 93b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa public static Object invoke(final Object receiver, final Object defaultValue, 94b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa final Method method, final Object... args) { 9503a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka if (method == null) { 9603a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka return defaultValue; 9703a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } 98610f1dc8553cf2ed97e763a06a19380c4a6cd636satok try { 99610f1dc8553cf2ed97e763a06a19380c4a6cd636satok return method.invoke(receiver, args); 10003a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } catch (final IllegalAccessException | IllegalArgumentException 10103a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka | InvocationTargetException e) { 102a8d3d50970cecf961940efc0e908fbb2f9b35472Ken Wakasa Log.e(TAG, "Exception in invoke", e); 103610f1dc8553cf2ed97e763a06a19380c4a6cd636satok } 1041fef530ec7626fa16777f52b48191e61db8f46d4satok return defaultValue; 105610f1dc8553cf2ed97e763a06a19380c4a6cd636satok } 106610f1dc8553cf2ed97e763a06a19380c4a6cd636satok 107b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa public static Object getFieldValue(final Object receiver, final Object defaultValue, 108b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa final Field field) { 10903a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka if (field == null) { 11003a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka return defaultValue; 11103a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } 11224119dfd414f948b2da214c021cc76e06b3dd41csatok try { 11324119dfd414f948b2da214c021cc76e06b3dd41csatok return field.get(receiver); 11403a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } catch (final IllegalAccessException | IllegalArgumentException e) { 115a8d3d50970cecf961940efc0e908fbb2f9b35472Ken Wakasa Log.e(TAG, "Exception in getFieldValue", e); 11624119dfd414f948b2da214c021cc76e06b3dd41csatok } 1171fef530ec7626fa16777f52b48191e61db8f46d4satok return defaultValue; 11824119dfd414f948b2da214c021cc76e06b3dd41csatok } 11924119dfd414f948b2da214c021cc76e06b3dd41csatok 120b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa public static void setFieldValue(final Object receiver, final Field field, final Object value) { 12103a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka if (field == null) { 12203a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka return; 12303a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } 12424119dfd414f948b2da214c021cc76e06b3dd41csatok try { 12524119dfd414f948b2da214c021cc76e06b3dd41csatok field.set(receiver, value); 12603a1c442aeddbd511be92e11465b6206d2ca976cTadashi G. Takaoka } catch (final IllegalAccessException | IllegalArgumentException e) { 127a8d3d50970cecf961940efc0e908fbb2f9b35472Ken Wakasa Log.e(TAG, "Exception in setFieldValue", e); 12824119dfd414f948b2da214c021cc76e06b3dd41csatok } 12924119dfd414f948b2da214c021cc76e06b3dd41csatok } 130fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa 131fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public static ClassWrapper getClassWrapper(final String className) { 132fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa return new ClassWrapper(getClass(className)); 133fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 134fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa 135fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public static final class ClassWrapper { 136fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa private final Class<?> mClass; 137fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public ClassWrapper(final Class<?> targetClass) { 138fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa mClass = targetClass; 139fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 140fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa 141fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public boolean exists() { 142fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa return mClass != null; 143fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 144fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa 145fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public <T> ToObjectMethodWrapper<T> getMethod(final String name, 146fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa final T defaultValue, final Class<?>... parameterTypes) { 1475f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka return new ToObjectMethodWrapper<>(CompatUtils.getMethod(mClass, name, parameterTypes), 148fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa defaultValue); 149fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 150fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa 151fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public ToIntMethodWrapper getPrimitiveMethod(final String name, final int defaultValue, 152fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa final Class<?>... parameterTypes) { 153fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa return new ToIntMethodWrapper(CompatUtils.getMethod(mClass, name, parameterTypes), 154fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa defaultValue); 155fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 156fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa 157fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public ToFloatMethodWrapper getPrimitiveMethod(final String name, final float defaultValue, 158fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa final Class<?>... parameterTypes) { 159fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa return new ToFloatMethodWrapper(CompatUtils.getMethod(mClass, name, parameterTypes), 160fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa defaultValue); 161fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 162fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa 163fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public ToBooleanMethodWrapper getPrimitiveMethod(final String name, 164fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa final boolean defaultValue, final Class<?>... parameterTypes) { 165fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa return new ToBooleanMethodWrapper(CompatUtils.getMethod(mClass, name, parameterTypes), 166fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa defaultValue); 167fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 168fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 169fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa 170fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public static final class ToObjectMethodWrapper<T> { 171fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa private final Method mMethod; 172fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa private final T mDefaultValue; 173fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public ToObjectMethodWrapper(final Method method, final T defaultValue) { 174fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa mMethod = method; 175fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa mDefaultValue = defaultValue; 176fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 177fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa @SuppressWarnings("unchecked") 178fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public T invoke(final Object receiver, final Object... args) { 179fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa return (T) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args); 180fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 181fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 182fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa 183fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public static final class ToIntMethodWrapper { 184fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa private final Method mMethod; 185fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa private final int mDefaultValue; 186fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public ToIntMethodWrapper(final Method method, final int defaultValue) { 187fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa mMethod = method; 188fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa mDefaultValue = defaultValue; 189fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 190fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public int invoke(final Object receiver, final Object... args) { 191fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa return (int) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args); 192fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 193fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 194fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa 195fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public static final class ToFloatMethodWrapper { 196fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa private final Method mMethod; 197fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa private final float mDefaultValue; 198fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public ToFloatMethodWrapper(final Method method, final float defaultValue) { 199fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa mMethod = method; 200fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa mDefaultValue = defaultValue; 201fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 202fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public float invoke(final Object receiver, final Object... args) { 203fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa return (float) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args); 204fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 205fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 206fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa 207fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public static final class ToBooleanMethodWrapper { 208fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa private final Method mMethod; 209fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa private final boolean mDefaultValue; 210fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public ToBooleanMethodWrapper(final Method method, final boolean defaultValue) { 211fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa mMethod = method; 212fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa mDefaultValue = defaultValue; 213fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 214fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa public boolean invoke(final Object receiver, final Object... args) { 215fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa return (boolean) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args); 216fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 217fa39ffcf8461ad6e53a86d8957ab892a3e367d16Yohei Yukawa } 2182cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok} 219