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 17package com.android.inputmethod.latin.utils; 18 19import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE; 20import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.ASCII_CAPABLE; 21import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.EMOJI_CAPABLE; 22import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE; 23import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; 24import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME; 25 26import android.content.Context; 27import android.os.Build; 28import android.test.AndroidTestCase; 29import android.test.suitebuilder.annotation.SmallTest; 30import android.view.inputmethod.InputMethodSubtype; 31 32import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils; 33 34import java.util.Locale; 35 36@SmallTest 37public class AdditionalSubtypeUtilsTests extends AndroidTestCase { 38 39 /** 40 * Predictable subtype ID for en_US dvorak layout. This is actually a hash code calculated as 41 * follows. 42 * <code> 43 * final boolean isAuxiliary = false; 44 * final boolean overrideImplicitlyEnabledSubtype = false; 45 * final int SUBTYPE_ID_EN_US_DVORAK = Arrays.hashCode(new Object[] { 46 * "en_US", 47 * "keyboard", 48 * "KeyboardLayoutSet=dvorak" 49 * + ",AsciiCapable" 50 * + ",UntranslatableReplacementStringInSubtypeName=Dvorak" 51 * + ",EmojiCapable" 52 * + ",isAdditionalSubtype", 53 * isAuxiliary, 54 * overrideImplicitlyEnabledSubtype }); 55 * </code> 56 */ 57 private static int SUBTYPE_ID_EN_US_DVORAK = 0xb3c0cc56; 58 private static String EXTRA_VALUE_EN_US_DVORAK_ICS = 59 "KeyboardLayoutSet=dvorak" + 60 ",AsciiCapable" + 61 ",isAdditionalSubtype"; 62 private static String EXTRA_VALUE_EN_US_DVORAK_JELLY_BEAN = 63 "KeyboardLayoutSet=dvorak" + 64 ",AsciiCapable" + 65 ",UntranslatableReplacementStringInSubtypeName=Dvorak" + 66 ",isAdditionalSubtype"; 67 private static String EXTRA_VALUE_EN_US_DVORAK_KITKAT = 68 "KeyboardLayoutSet=dvorak" + 69 ",AsciiCapable" + 70 ",UntranslatableReplacementStringInSubtypeName=Dvorak" + 71 ",EmojiCapable" + 72 ",isAdditionalSubtype"; 73 74 /** 75 * Predictable subtype ID for azerty layout. This is actually a hash code calculated as follows. 76 * <code> 77 * final boolean isAuxiliary = false; 78 * final boolean overrideImplicitlyEnabledSubtype = false; 79 * final int SUBTYPE_ID_ZZ_AZERTY = Arrays.hashCode(new Object[] { 80 * "zz", 81 * "keyboard", 82 * "KeyboardLayoutSet=azerty" 83 * + ",AsciiCapable" 84 * + ",EmojiCapable" 85 * + ",isAdditionalSubtype", 86 * isAuxiliary, 87 * overrideImplicitlyEnabledSubtype }); 88 * </code> 89 */ 90 private static int SUBTYPE_ID_ZZ_AZERTY = 0x5b6be697; 91 private static String EXTRA_VALUE_ZZ_AZERTY_ICS = 92 "KeyboardLayoutSet=azerty" + 93 ",AsciiCapable" + 94 ",isAdditionalSubtype"; 95 private static String EXTRA_VALUE_ZZ_AZERTY_KITKAT = 96 "KeyboardLayoutSet=azerty" + 97 ",AsciiCapable" + 98 ",EmojiCapable" + 99 ",isAdditionalSubtype"; 100 101 @Override 102 protected void setUp() throws Exception { 103 super.setUp(); 104 final Context context = getContext(); 105 SubtypeLocaleUtils.init(context); 106 } 107 108 private static void assertEnUsDvorak(InputMethodSubtype subtype) { 109 assertEquals("en_US", subtype.getLocale()); 110 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 111 assertEquals(EXTRA_VALUE_EN_US_DVORAK_KITKAT, subtype.getExtraValue()); 112 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 113 assertEquals(EXTRA_VALUE_EN_US_DVORAK_JELLY_BEAN, subtype.getExtraValue()); 114 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 115 assertEquals(EXTRA_VALUE_EN_US_DVORAK_ICS, subtype.getExtraValue()); 116 } 117 assertTrue(subtype.containsExtraValueKey(ASCII_CAPABLE)); 118 assertTrue(InputMethodSubtypeCompatUtils.isAsciiCapable(subtype)); 119 // TODO: Enable following test 120 // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 121 // assertTrue(InputMethodSubtypeCompatUtils.isAsciiCapableWithAPI(subtype)); 122 // } 123 assertTrue(subtype.containsExtraValueKey(EMOJI_CAPABLE)); 124 assertTrue(subtype.containsExtraValueKey(IS_ADDITIONAL_SUBTYPE)); 125 assertEquals("dvorak", subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET)); 126 assertEquals("Dvorak", subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)); 127 assertEquals(KEYBOARD_MODE, subtype.getMode()); 128 assertEquals(SUBTYPE_ID_EN_US_DVORAK, subtype.hashCode()); 129 } 130 131 private static void assertAzerty(InputMethodSubtype subtype) { 132 assertEquals("zz", subtype.getLocale()); 133 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 134 assertEquals(EXTRA_VALUE_ZZ_AZERTY_KITKAT, subtype.getExtraValue()); 135 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 136 assertEquals(EXTRA_VALUE_ZZ_AZERTY_ICS, subtype.getExtraValue()); 137 } 138 assertTrue(subtype.containsExtraValueKey(ASCII_CAPABLE)); 139 assertTrue(InputMethodSubtypeCompatUtils.isAsciiCapable(subtype)); 140 // TODO: Enable following test 141 // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 142 // assertTrue(InputMethodSubtypeCompatUtils.isAsciiCapableWithAPI(subtype)); 143 // } 144 assertTrue(subtype.containsExtraValueKey(EMOJI_CAPABLE)); 145 assertTrue(subtype.containsExtraValueKey(IS_ADDITIONAL_SUBTYPE)); 146 assertEquals("azerty", subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET)); 147 assertFalse(subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)); 148 assertEquals(KEYBOARD_MODE, subtype.getMode()); 149 assertEquals(SUBTYPE_ID_ZZ_AZERTY, subtype.hashCode()); 150 } 151 152 public void testRestorable() { 153 final InputMethodSubtype EN_US_DVORAK = 154 AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( 155 Locale.US.toString(), "dvorak"); 156 final InputMethodSubtype ZZ_AZERTY = 157 AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( 158 SubtypeLocaleUtils.NO_LANGUAGE, "azerty"); 159 assertEnUsDvorak(EN_US_DVORAK); 160 assertAzerty(ZZ_AZERTY); 161 162 // Make sure the subtype can be stored and restored in a deterministic manner. 163 final InputMethodSubtype[] subtypes = { EN_US_DVORAK, ZZ_AZERTY }; 164 final String prefSubtype = AdditionalSubtypeUtils.createPrefSubtypes(subtypes); 165 final InputMethodSubtype[] restoredSubtypes = 166 AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefSubtype); 167 assertEquals(2, restoredSubtypes.length); 168 final InputMethodSubtype restored_EN_US_DVORAK = restoredSubtypes[0]; 169 final InputMethodSubtype restored_ZZ_AZERTY = restoredSubtypes[1]; 170 171 assertEnUsDvorak(restored_EN_US_DVORAK); 172 assertAzerty(restored_ZZ_AZERTY); 173 } 174} 175