1 /* 2 * Copyright (C) 2014 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.keyboard; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.test.AndroidTestCase; 22 import android.view.ContextThemeWrapper; 23 import android.view.inputmethod.EditorInfo; 24 import android.view.inputmethod.InputMethodInfo; 25 import android.view.inputmethod.InputMethodSubtype; 26 27 import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils; 28 import com.android.inputmethod.keyboard.KeyboardLayoutSet.Builder; 29 import com.android.inputmethod.latin.R; 30 import com.android.inputmethod.latin.RichInputMethodManager; 31 import com.android.inputmethod.latin.RichInputMethodSubtype; 32 import com.android.inputmethod.latin.common.Constants; 33 import com.android.inputmethod.latin.settings.Settings; 34 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils; 35 import com.android.inputmethod.latin.utils.ResourceUtils; 36 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; 37 38 import java.util.ArrayList; 39 import java.util.Locale; 40 41 public abstract class KeyboardLayoutSetTestsBase extends AndroidTestCase { 42 // All input method subtypes of LatinIME. 43 private final ArrayList<InputMethodSubtype> mAllSubtypesList = new ArrayList<>(); 44 45 public interface SubtypeFilter { accept(final InputMethodSubtype subtype)46 public boolean accept(final InputMethodSubtype subtype); 47 } 48 49 public static final SubtypeFilter FILTER_IS_ASCII_CAPABLE = new SubtypeFilter() { 50 @Override 51 public boolean accept(InputMethodSubtype subtype) { 52 return InputMethodSubtypeCompatUtils.isAsciiCapable(subtype); 53 } 54 }; 55 56 public static final SubtypeFilter FILTER_IS_ADDITIONAL_SUBTYPE = new SubtypeFilter() { 57 @Override 58 public boolean accept(InputMethodSubtype subtype) { 59 return AdditionalSubtypeUtils.isAdditionalSubtype(subtype); 60 } 61 }; 62 63 private RichInputMethodManager mRichImm; 64 private InputMethodSubtype[] mSavedAdditionalSubtypes; 65 private int mScreenMetrics; 66 getKeyboardThemeForTests()67 protected abstract int getKeyboardThemeForTests(); 68 69 @Override setUp()70 protected void setUp() throws Exception { 71 super.setUp(); 72 final Context context = getContext(); 73 final Resources res = context.getResources(); 74 RichInputMethodManager.init(context); 75 mRichImm = RichInputMethodManager.getInstance(); 76 77 // Save and reset additional subtypes preference. 78 mSavedAdditionalSubtypes = mRichImm.getAdditionalSubtypes(); 79 final InputMethodSubtype[] predefinedAdditionalSubtypes = 80 AdditionalSubtypeUtils.createAdditionalSubtypesArray( 81 AdditionalSubtypeUtils.createPrefSubtypes( 82 res.getStringArray(R.array.predefined_subtypes))); 83 mRichImm.setAdditionalInputMethodSubtypes(predefinedAdditionalSubtypes); 84 85 final KeyboardTheme keyboardTheme = KeyboardTheme.searchKeyboardThemeById( 86 getKeyboardThemeForTests(), KeyboardTheme.KEYBOARD_THEMES); 87 setContext(new ContextThemeWrapper(getContext(), keyboardTheme.mStyleId)); 88 KeyboardLayoutSet.onKeyboardThemeChanged(); 89 90 mScreenMetrics = Settings.readScreenMetrics(res); 91 92 final InputMethodInfo imi = mRichImm.getInputMethodInfoOfThisIme(); 93 final int subtypeCount = imi.getSubtypeCount(); 94 for (int index = 0; index < subtypeCount; index++) { 95 mAllSubtypesList.add(imi.getSubtypeAt(index)); 96 } 97 } 98 99 @Override tearDown()100 protected void tearDown() throws Exception { 101 // Restore additional subtypes preference. 102 mRichImm.setAdditionalInputMethodSubtypes(mSavedAdditionalSubtypes); 103 super.tearDown(); 104 } 105 getAllSubtypesList()106 protected final ArrayList<InputMethodSubtype> getAllSubtypesList() { 107 return mAllSubtypesList; 108 } 109 getSubtypesFilteredBy( final SubtypeFilter filter)110 protected final ArrayList<InputMethodSubtype> getSubtypesFilteredBy( 111 final SubtypeFilter filter) { 112 final ArrayList<InputMethodSubtype> list = new ArrayList<>(); 113 for (final InputMethodSubtype subtype : mAllSubtypesList) { 114 if (filter.accept(subtype)) { 115 list.add(subtype); 116 } 117 } 118 return list; 119 } 120 isPhone()121 protected final boolean isPhone() { 122 return Constants.isPhone(mScreenMetrics); 123 } 124 getSubtype(final Locale locale, final String keyboardLayout)125 protected final InputMethodSubtype getSubtype(final Locale locale, 126 final String keyboardLayout) { 127 for (final InputMethodSubtype subtype : mAllSubtypesList) { 128 final Locale subtypeLocale = SubtypeLocaleUtils.getSubtypeLocale(subtype); 129 final String subtypeLayout = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype); 130 if (locale.equals(subtypeLocale) && keyboardLayout.equals(subtypeLayout)) { 131 // Found subtype that matches locale and keyboard layout. 132 return subtype; 133 } 134 } 135 for (final InputMethodSubtype subtype : getSubtypesFilteredBy(FILTER_IS_ASCII_CAPABLE)) { 136 final Locale subtypeLocale = SubtypeLocaleUtils.getSubtypeLocale(subtype); 137 if (locale.equals(subtypeLocale)) { 138 // Create additional subtype. 139 return AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( 140 locale.toString(), keyboardLayout); 141 } 142 } 143 throw new RuntimeException( 144 "Unknown subtype: locale=" + locale + " keyboardLayout=" + keyboardLayout); 145 } 146 createKeyboardLayoutSet(final InputMethodSubtype subtype, final EditorInfo editorInfo)147 protected KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype, 148 final EditorInfo editorInfo) { 149 return createKeyboardLayoutSet(subtype, editorInfo, false /* voiceInputKeyEnabled */, 150 false /* languageSwitchKeyEnabled */, false /* splitLayoutEnabled */); 151 } 152 createKeyboardLayoutSet(final InputMethodSubtype subtype, final EditorInfo editorInfo, final boolean voiceInputKeyEnabled, final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled)153 protected KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype, 154 final EditorInfo editorInfo, final boolean voiceInputKeyEnabled, 155 final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled) { 156 final Context context = getContext(); 157 final Resources res = context.getResources(); 158 final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res); 159 final int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res); 160 final Builder builder = new Builder(context, editorInfo); 161 builder.setKeyboardGeometry(keyboardWidth, keyboardHeight) 162 .setSubtype(RichInputMethodSubtype.getRichInputMethodSubtype(subtype)) 163 .setVoiceInputKeyEnabled(voiceInputKeyEnabled) 164 .setLanguageSwitchKeyEnabled(languageSwitchKeyEnabled) 165 .setSplitLayoutEnabledByUser(splitLayoutEnabled); 166 return builder.build(); 167 } 168 } 169