1 /* 2 * Copyright (C) 2017 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.dialer.dialpadview; 18 19 import android.content.Context; 20 import android.support.annotation.NonNull; 21 import android.support.v4.util.SimpleArrayMap; 22 import com.android.dialer.common.Assert; 23 import com.android.dialer.i18n.LocaleUtils; 24 25 /** A class containing character mappings for the dialpad. */ 26 public class DialpadCharMappings { 27 28 /** The character mapping for the Latin alphabet (the default mapping) */ 29 private static class Latin { 30 private static final String[] KEY_TO_CHARS = { 31 "+" /* 0 */, 32 "" /* 1 */, 33 "ABC" /* 2 */, 34 "DEF" /* 3 */, 35 "GHI" /* 4 */, 36 "JKL" /* 5 */, 37 "MNO" /* 6 */, 38 "PQRS" /* 7 */, 39 "TUV" /* 8 */, 40 "WXYZ" /* 9 */, 41 "" /* * */, 42 "" /* # */, 43 }; 44 45 private static final SimpleArrayMap<Character, Character> CHAR_TO_KEY = 46 getCharToKeyMap(KEY_TO_CHARS); 47 } 48 49 /** The character mapping for the Bulgarian alphabet */ 50 private static class Bul { 51 private static final String[] KEY_TO_CHARS = { 52 "" /* 0 */, 53 "" /* 1 */, 54 "АБВГ" /* 2 */, 55 "ДЕЖЗ" /* 3 */, 56 "ИЙКЛ" /* 4 */, 57 "МНО" /* 5 */, 58 "ПРС" /* 6 */, 59 "ТУФХ" /* 7 */, 60 "ЦЧШЩ" /* 8 */, 61 "ЪЬЮЯ" /* 9 */, 62 "" /* * */, 63 "" /* # */, 64 }; 65 66 private static final SimpleArrayMap<Character, Character> CHAR_TO_KEY = 67 getCharToKeyMap(KEY_TO_CHARS); 68 } 69 70 /** The character mapping for the Russian alphabet */ 71 private static class Rus { 72 private static final String[] KEY_TO_CHARS = { 73 "" /* 0 */, 74 "" /* 1 */, 75 "АБВГ" /* 2 */, 76 "ДЕЁЖЗ" /* 3 */, 77 "ИЙКЛ" /* 4 */, 78 "МНОП" /* 5 */, 79 "РСТУ" /* 6 */, 80 "ФХЦЧ" /* 7 */, 81 "ШЩЪЫ" /* 8 */, 82 "ЬЭЮЯ" /* 9 */, 83 "" /* * */, 84 "" /* # */, 85 }; 86 87 private static final SimpleArrayMap<Character, Character> CHAR_TO_KEY = 88 getCharToKeyMap(KEY_TO_CHARS); 89 } 90 91 /** The character mapping for the Ukrainian alphabet */ 92 private static class Ukr { 93 private static final String[] KEY_TO_CHARS = { 94 "" /* 0 */, 95 "" /* 1 */, 96 "АБВГҐ" /* 2 */, 97 "ДЕЄЖЗ" /* 3 */, 98 "ИІЇЙКЛ" /* 4 */, 99 "МНОП" /* 5 */, 100 "РСТУ" /* 6 */, 101 "ФХЦЧ" /* 7 */, 102 "ШЩ" /* 8 */, 103 "ЬЮЯ" /* 9 */, 104 "" /* * */, 105 "" /* # */, 106 }; 107 108 private static final SimpleArrayMap<Character, Character> CHAR_TO_KEY = 109 getCharToKeyMap(KEY_TO_CHARS); 110 } 111 112 // A map in which each key is an ISO 639-2 language code and the corresponding value is a 113 // character-key map. 114 private static final SimpleArrayMap<String, SimpleArrayMap<Character, Character>> 115 CHAR_TO_KEY_MAPS = new SimpleArrayMap<>(); 116 117 // A map in which each key is an ISO 639-2 language code and the corresponding value is an array 118 // defining a key-characters map. 119 private static final SimpleArrayMap<String, String[]> KEY_TO_CHAR_MAPS = new SimpleArrayMap<>(); 120 121 static { 122 CHAR_TO_KEY_MAPS.put("bul", Bul.CHAR_TO_KEY); 123 CHAR_TO_KEY_MAPS.put("rus", Rus.CHAR_TO_KEY); 124 CHAR_TO_KEY_MAPS.put("ukr", Ukr.CHAR_TO_KEY); 125 126 KEY_TO_CHAR_MAPS.put("bul", Bul.KEY_TO_CHARS); 127 KEY_TO_CHAR_MAPS.put("rus", Rus.KEY_TO_CHARS); 128 KEY_TO_CHAR_MAPS.put("ukr", Ukr.KEY_TO_CHARS); 129 } 130 131 /** 132 * Returns the character-key map of the ISO 639-2 language code of the 1st language preference or 133 * null if no character-key map for the language code is defined. 134 */ getCharToKeyMap(@onNull Context context)135 public static SimpleArrayMap<Character, Character> getCharToKeyMap(@NonNull Context context) { 136 return CHAR_TO_KEY_MAPS.get(LocaleUtils.getLocale(context).getISO3Language()); 137 } 138 139 /** 140 * Returns the character-key map of the provided ISO 639-2 language code. 141 * 142 * <p>Note: this method is for implementations of {@link 143 * com.android.dialer.smartdial.map.SmartDialMap} only. {@link #getCharToKeyMap(Context)} should 144 * be used for all other purposes. 145 * 146 * <p>It is the caller's responsibility to ensure the language code is valid and a character 147 * mapping is defined for that language. Otherwise, an exception will be thrown. 148 */ getCharToKeyMap(String languageCode)149 public static SimpleArrayMap<Character, Character> getCharToKeyMap(String languageCode) { 150 SimpleArrayMap<Character, Character> charToKeyMap = CHAR_TO_KEY_MAPS.get(languageCode); 151 152 return Assert.isNotNull( 153 charToKeyMap, "No character mappings can be found for language code '%s'", languageCode); 154 } 155 156 /** Returns the default character-key map (the one that uses the Latin alphabet). */ getDefaultCharToKeyMap()157 public static SimpleArrayMap<Character, Character> getDefaultCharToKeyMap() { 158 return Latin.CHAR_TO_KEY; 159 } 160 161 /** 162 * Returns the key-characters map of the given ISO 639-2 language code of the 1st language 163 * preference or null if no key-characters map for the language code is defined. 164 */ getKeyToCharsMap(@onNull Context context)165 static String[] getKeyToCharsMap(@NonNull Context context) { 166 return KEY_TO_CHAR_MAPS.get(LocaleUtils.getLocale(context).getISO3Language()); 167 } 168 169 /** Returns the default key-characters map (the one that uses the Latin alphabet). */ getDefaultKeyToCharsMap()170 public static String[] getDefaultKeyToCharsMap() { 171 return Latin.KEY_TO_CHARS; 172 } 173 174 /** 175 * Given a array representing a key-characters map, return its reverse map. 176 * 177 * <p>It is the caller's responsibility to ensure that 178 * 179 * <ul> 180 * <li>the array contains only 12 elements, 181 * <li>the 0th element ~ the 9th element are the mappings for keys "0" ~ "9", 182 * <li>the 10th element is for key "*", and 183 * <li>the 11th element is for key "#". 184 * </ul> 185 * 186 * @param keyToChars An array representing a key-characters map. It must satisfy the conditions 187 * above. 188 * @return A character-key map. 189 */ getCharToKeyMap( @onNull String[] keyToChars)190 private static SimpleArrayMap<Character, Character> getCharToKeyMap( 191 @NonNull String[] keyToChars) { 192 Assert.checkArgument(keyToChars.length == 12); 193 194 SimpleArrayMap<Character, Character> charToKeyMap = new SimpleArrayMap<>(); 195 196 for (int keyIndex = 0; keyIndex < keyToChars.length; keyIndex++) { 197 String chars = keyToChars[keyIndex]; 198 199 for (int j = 0; j < chars.length(); j++) { 200 char c = chars.charAt(j); 201 if (Character.isAlphabetic(c)) { 202 charToKeyMap.put(Character.toLowerCase(c), getKeyChar(keyIndex)); 203 } 204 } 205 } 206 207 return charToKeyMap; 208 } 209 210 /** Given a key index of the dialpad, returns the corresponding character. */ getKeyChar(int keyIndex)211 private static char getKeyChar(int keyIndex) { 212 Assert.checkArgument(0 <= keyIndex && keyIndex <= 11); 213 214 switch (keyIndex) { 215 case 10: 216 return '*'; 217 case 11: 218 return '#'; 219 default: 220 return (char) ('0' + keyIndex); 221 } 222 } 223 } 224