PhoneNumberUtils.java revision db1f4993989bb03cae2f3e008d4db3e49577aa73
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.telephony; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemProperties; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Contacts; 25f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkeyimport android.provider.ContactsContract; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Editable; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.SpannableStringBuilder; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils; 2918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.comimport android.util.Log; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseIntArray; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 327850cdde66705152b859aafda875833acdda9653Libin Tangimport static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY; 3318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.comimport static com.android.internal.telephony.TelephonyProperties.PROPERTY_IDP_STRING; 347850cdde66705152b859aafda875833acdda9653Libin Tangimport static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY; 3518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Locale; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Matcher; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Pattern; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Various utilities for dealing with phone number strings. 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class PhoneNumberUtils 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Special characters 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (See "What is a phone number?" doc) 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 'p' --- GSM pause character, same as comma 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 'n' --- GSM wild character 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 'w' --- GSM wait character 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final char PAUSE = ','; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final char WAIT = ';'; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final char WILD = 'N'; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TOA = TON + NPI 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See TS 24.008 section 10.5.4.7 for details. 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * These are the only really useful TOA values 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int TOA_International = 0x91; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int TOA_Unknown = 0x81; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com static final String LOG_TAG = "PhoneNumberUtils"; 6618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static final boolean DBG = false; 6718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * global-phone-number = ["+"] 1*( DIGIT / written-sep ) 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * written-sep = ("-"/".") 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final Pattern GLOBAL_PHONE_NUMBER_PATTERN = 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Pattern.compile("[\\+]?[0-9.-]+"); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** True if c is ISO-LATIN characters 0-9 */ 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isISODigit (char c) { 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return c >= '0' && c <= '9'; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** True if c is ISO-LATIN characters 0-9, *, # */ 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static boolean 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project is12Key(char c) { 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (c >= '0' && c <= '9') || c == '*' || c == '#'; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** True if c is ISO-LATIN characters 0-9, *, # , +, WILD */ 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static boolean 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isDialable(char c) { 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+' || c == WILD; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** True if c is ISO-LATIN characters 0-9, *, # , + (no WILD) */ 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static boolean 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isReallyDialable(char c) { 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+'; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** True if c is ISO-LATIN characters 0-9, *, # , +, WILD, WAIT, PAUSE */ 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static boolean 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isNonSeparator(char c) { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+' 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || c == WILD || c == WAIT || c == PAUSE; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** This any anything to the right of this char is part of the 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * post-dial string (eg this is PAUSE or WAIT) 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static boolean 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isStartsPostDial (char c) { 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return c == PAUSE || c == WAIT; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** Returns true if ch is not dialable or alpha char */ 1159a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static boolean isSeparator(char ch) { 1169a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return !isDialable(ch) && !(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')); 1179a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 1189a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Extracts the phone number from an Intent. 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param intent the intent to get the number of 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context a context to use for database access 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the phone number that would be called by the intent, or 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>null</code> if the number cannot be found. 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String getNumberFromIntent(Intent intent, Context context) { 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String number = null; 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri uri = intent.getData(); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String scheme = uri.getScheme(); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (scheme.equals("tel")) { 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return uri.getSchemeSpecificPart(); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13760d45f0f0320801a16db2ad038453c098e98966cNicolas Catania // TODO: We don't check for SecurityException here (requires 13860d45f0f0320801a16db2ad038453c098e98966cNicolas Catania // READ_PHONE_STATE permission). 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (scheme.equals("voicemail")) { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return TelephonyManager.getDefault().getVoiceMailNumber(); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (context == null) { 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String type = intent.resolveType(context); 148f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey String phoneColumn = null; 149f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey 150f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey // Correctly read out the phone entry based on requested provider 151f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey final String authority = uri.getAuthority(); 152f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey if (Contacts.AUTHORITY.equals(authority)) { 153f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey phoneColumn = Contacts.People.Phones.NUMBER; 154f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey } else if (ContactsContract.AUTHORITY.equals(authority)) { 155f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey phoneColumn = ContactsContract.CommonDataKinds.Phone.NUMBER; 156f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey } 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 158f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey final Cursor c = context.getContentResolver().query(uri, new String[] { 159f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey phoneColumn 160f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey }, null, null, null); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c != null) { 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c.moveToFirst()) { 164f28ca902ad07ca3cf9c2f2e5d2d20dd58c0f13e5Jeff Sharkey number = c.getString(c.getColumnIndex(phoneColumn)); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.close(); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return number; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Extracts the network address portion and canonicalizes 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (filters out separators.) 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Network address portion is everything up to DTMF control digit 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * separators (pause or wait), but without non-dialable characters. 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Please note that the GSM wild character is allowed in the result. 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This must be resolved before dialing. 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Allows + only in the first position in the result string. 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns null if phoneNumber == null 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extractNetworkPortion(String phoneNumber) { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (phoneNumber == null) { 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = phoneNumber.length(); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder ret = new StringBuilder(len); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean firstCharAdded = false; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < len; i++) { 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = phoneNumber.charAt(i); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isDialable(c) && (c != '+' || !firstCharAdded)) { 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project firstCharAdded = true; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(c); 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (isStartsPostDial (c)) { 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret.toString(); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Strips separators from a phone number string. 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param phoneNumber phone number to strip. 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return phone string stripped of separators. 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String stripSeparators(String phoneNumber) { 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (phoneNumber == null) { 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = phoneNumber.length(); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder ret = new StringBuilder(len); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < len; i++) { 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = phoneNumber.charAt(i); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isNonSeparator(c)) { 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(c); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret.toString(); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** or -1 if both are negative */ 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static private int 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project minPositive (int a, int b) { 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (a >= 0 && b >= 0) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (a < b) ? a : b; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (a >= 0) { /* && b < 0 */ 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return a; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (b >= 0) { /* && a < 0 */ 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return b; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { /* a < 0 && b < 0 */ 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static void log(String msg) { 24618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com Log.d(LOG_TAG, msg); 24718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** index of the last character of the network portion 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (eg anything after is a post-dial string) 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static private int 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indexOfLastNetworkChar(String a) { 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int pIndex, wIndex; 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int origLength; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int trimIndex; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project origLength = a.length(); 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pIndex = a.indexOf(PAUSE); 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wIndex = a.indexOf(WAIT); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project trimIndex = minPositive(pIndex, wIndex); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (trimIndex < 0) { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return origLength - 1; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return trimIndex - 1; 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Extracts the post-dial sequence of DTMF control digits, pauses, and 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * waits. Strips separators. This string may be empty, but will not be null 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * unless phoneNumber == null. 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns null if phoneNumber == null 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extractPostDialPortion(String phoneNumber) { 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (phoneNumber == null) return null; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int trimIndex; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder ret = new StringBuilder(); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project trimIndex = indexOfLastNetworkChar (phoneNumber); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = trimIndex + 1, s = phoneNumber.length() 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ; i < s; i++ 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ) { 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = phoneNumber.charAt(i); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isNonSeparator(c)) { 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(c); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret.toString(); 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3019a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * Compare phone numbers a and b, return true if they're identical enough for caller ID purposes. 3029a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 3039a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa public static boolean compare(String a, String b) { 3049a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // We've used loose comparation at least Eclair, which may change in the future. 305db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar 3069a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return compare(a, b, false); 3079a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 3089a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 3099a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** 310db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar * Compare phone numbers a and b, and return true if they're identical 311db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar * enough for caller ID purposes. Checks a resource to determine whether 312db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar * to use a strict or loose comparison algorithm. 313db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar */ 314db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar public static boolean compare(Context context, String a, String b) { 315db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar boolean useStrict = context.getResources().getBoolean( 316db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar com.android.internal.R.bool.config_use_strict_phone_number_comparation); 317db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar return compare(a, b, useStrict); 318db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar } 319db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar 320db1f4993989bb03cae2f3e008d4db3e49577aa73Evan Millar /** 3219a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * @hide only for testing. 3229a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 3239a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa public static boolean compare(String a, String b, boolean useStrictComparation) { 3249a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return (useStrictComparation ? compareStrictly(a, b) : compareLoosely(a, b)); 3259a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 3269a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 3279a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Compare phone numbers a and b, return true if they're identical 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * enough for caller ID purposes. 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - Compares from right to left 33202b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang * - requires MIN_MATCH (7) characters to match 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - handles common trunk prefixes and international prefixes 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (basically, everything except the Russian trunk prefix) 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3369a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * Note that this method does not return false even when the two phone numbers 3379a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * are not exactly same; rather; we can call this method "similar()", not "equals()". 3389a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * 3399a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * @hide 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean 3429a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa compareLoosely(String a, String b) { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ia, ib; 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int matched; 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (a == null || b == null) return a == b; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (a.length() == 0 || b.length() == 0) { 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ia = indexOfLastNetworkChar (a); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ib = indexOfLastNetworkChar (b); 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project matched = 0; 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (ia >= 0 && ib >=0) { 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char ca, cb; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean skipCmp = false; 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ca = a.charAt(ia); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isDialable(ca)) { 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ia--; 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project skipCmp = true; 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cb = b.charAt(ib); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isDialable(cb)) { 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ib--; 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project skipCmp = true; 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!skipCmp) { 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cb != ca && ca != WILD && cb != WILD) { 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ia--; ib--; matched++; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (matched < MIN_MATCH) { 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int aLen = a.length(); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if the input strings match, but their lengths < MIN_MATCH, 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // treat them as equal. 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (aLen == b.length() && aLen == matched) { 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // At least one string has matched completely; 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (matched >= MIN_MATCH && (ia < 0 || ib < 0)) { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Now, what remains must be one of the following for a 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * match: 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - a '+' on one and a '00' or a '011' on the other 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - a '0' on one and a (+,00)<country code> on the other 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (for this, a '0' and a '00' prefix would have succeeded above) 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (matchIntlPrefix(a, ia + 1) 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && matchIntlPrefix (b, ib +1) 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (matchTrunkPrefix(a, ia + 1) 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && matchIntlPrefixAndCC(b, ib +1) 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (matchTrunkPrefix(b, ib + 1) 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && matchIntlPrefixAndCC(a, ia +1) 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ) { 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4299a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * @hide 4309a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 4319a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa public static boolean 4329a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa compareStrictly(String a, String b) { 4339a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return compareStrictly(a, b, true); 4349a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 4359a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 4369a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** 4379a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * @hide 4389a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 4399a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa public static boolean 4409a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa compareStrictly(String a, String b, boolean acceptInvalidCCCPrefix) { 4419a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (a == null || b == null) { 4429a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return a == b; 4439a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else if (a.length() == 0 && b.length() == 0) { 4449a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return false; 4459a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 4469a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 4479a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int forwardIndexA = 0; 4489a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int forwardIndexB = 0; 4499a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 4509a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa CountryCallingCodeAndNewIndex cccA = 4519a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa tryGetCountryCallingCodeAndNewIndex(a, acceptInvalidCCCPrefix); 4529a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa CountryCallingCodeAndNewIndex cccB = 4539a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa tryGetCountryCallingCodeAndNewIndex(b, acceptInvalidCCCPrefix); 4549a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa boolean bothHasCountryCallingCode = false; 4559a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa boolean okToIgnorePrefix = true; 4569a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa boolean trunkPrefixIsOmittedA = false; 4579a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa boolean trunkPrefixIsOmittedB = false; 4589a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (cccA != null && cccB != null) { 4599a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (cccA.countryCallingCode != cccB.countryCallingCode) { 4609a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // Different Country Calling Code. Must be different phone number. 4619a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return false; 4629a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 4639a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // When both have ccc, do not ignore trunk prefix. Without this, 4649a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // "+81123123" becomes same as "+810123123" (+81 == Japan) 4659a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa okToIgnorePrefix = false; 4669a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa bothHasCountryCallingCode = true; 4679a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa forwardIndexA = cccA.newIndex; 4689a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa forwardIndexB = cccB.newIndex; 4699a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else if (cccA == null && cccB == null) { 4709a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // When both do not have ccc, do not ignore trunk prefix. Without this, 4719a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // "123123" becomes same as "0123123" 4729a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa okToIgnorePrefix = false; 4739a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 4749a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (cccA != null) { 4759a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa forwardIndexA = cccA.newIndex; 4769a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 4779a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int tmp = tryGetTrunkPrefixOmittedIndex(b, 0); 4789a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (tmp >= 0) { 4799a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa forwardIndexA = tmp; 4809a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa trunkPrefixIsOmittedA = true; 4819a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 4829a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 4839a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (cccB != null) { 4849a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa forwardIndexB = cccB.newIndex; 4859a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 4869a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int tmp = tryGetTrunkPrefixOmittedIndex(b, 0); 4879a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (tmp >= 0) { 4889a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa forwardIndexB = tmp; 4899a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa trunkPrefixIsOmittedB = true; 4909a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 4919a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 4929a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 4939a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 4949a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int backwardIndexA = a.length() - 1; 4959a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int backwardIndexB = b.length() - 1; 4969a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa while (backwardIndexA >= forwardIndexA && backwardIndexB >= forwardIndexB) { 4979a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa boolean skip_compare = false; 4989a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa final char chA = a.charAt(backwardIndexA); 4999a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa final char chB = b.charAt(backwardIndexB); 5009a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (isSeparator(chA)) { 5019a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa backwardIndexA--; 5029a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa skip_compare = true; 5039a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5049a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (isSeparator(chB)) { 5059a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa backwardIndexB--; 5069a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa skip_compare = true; 5079a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5089a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 5099a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (!skip_compare) { 5109a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (chA != chB) { 5119a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return false; 5129a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5139a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa backwardIndexA--; 5149a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa backwardIndexB--; 5159a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5169a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5179a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 5189a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (okToIgnorePrefix) { 5199a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if ((trunkPrefixIsOmittedA && forwardIndexA <= backwardIndexA) || 5209a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa !checkPrefixIsIgnorable(a, forwardIndexA, backwardIndexA)) { 5219a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (acceptInvalidCCCPrefix) { 5229a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // Maybe the code handling the special case for Thailand makes the 5239a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // result garbled, so disable the code and try again. 5249a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // e.g. "16610001234" must equal to "6610001234", but with 5259a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // Thailand-case handling code, they become equal to each other. 5269a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // 5279a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // Note: we select simplicity rather than adding some complicated 5289a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // logic here for performance(like "checking whether remaining 5299a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // numbers are just 66 or not"), assuming inputs are small 5309a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // enough. 5319a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return compare(a, b, false); 5329a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 5339a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return false; 5349a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5359a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5369a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if ((trunkPrefixIsOmittedB && forwardIndexB <= backwardIndexB) || 5379a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa !checkPrefixIsIgnorable(b, forwardIndexA, backwardIndexB)) { 5389a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (acceptInvalidCCCPrefix) { 5399a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return compare(a, b, false); 5409a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 5419a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return false; 5429a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5439a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5449a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 5459a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // In the US, 1-650-555-1234 must be equal to 650-555-1234, 5469a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // while 090-1234-1234 must not be equalt to 90-1234-1234 in Japan. 5479a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // This request exists just in US (with 1 trunk (NDD) prefix). 5489a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // In addition, "011 11 7005554141" must not equal to "+17005554141", 5499a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // while "011 1 7005554141" must equal to "+17005554141" 5509a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // 5519a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // In this comparison, we ignore the prefix '1' just once, when 5529a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // - at least either does not have CCC, or 5539a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // - the remaining non-separator number is 1 5549a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa boolean maybeNamp = !bothHasCountryCallingCode; 5559a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa while (backwardIndexA >= forwardIndexA) { 5569a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa final char chA = a.charAt(backwardIndexA); 5579a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (isDialable(chA)) { 5589a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (maybeNamp && tryGetISODigit(chA) == 1) { 5599a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa maybeNamp = false; 5609a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 5619a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return false; 5629a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5639a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5649a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa backwardIndexA--; 5659a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5669a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa while (backwardIndexB >= forwardIndexB) { 5679a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa final char chB = b.charAt(backwardIndexB); 5689a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (isDialable(chB)) { 5699a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (maybeNamp && tryGetISODigit(chB) == 1) { 5709a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa maybeNamp = false; 5719a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 5729a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return false; 5739a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5749a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5759a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa backwardIndexB--; 5769a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5779a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5789a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 5799a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return true; 5809a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 5819a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 5829a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the rightmost MIN_MATCH (5) characters in the network portion 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in *reversed* order 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This can be used to do a database lookup against the column 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that stores getStrippedReversed() 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns null if phoneNumber == null 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toCallerIDMinMatch(String phoneNumber) { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String np = extractNetworkPortion(phoneNumber); 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return internalGetStrippedReversed(np, MIN_MATCH); 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the network portion reversed. 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This string is intended to go into an index column for a 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * database lookup. 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns null if phoneNumber == null 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getStrippedReversed(String phoneNumber) { 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String np = extractNetworkPortion(phoneNumber); 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (np == null) return null; 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return internalGetStrippedReversed(np, np.length()); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the last numDigits of the reversed phone number 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns null if np == null 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project internalGetStrippedReversed(String np, int numDigits) { 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (np == null) return null; 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder ret = new StringBuilder(numDigits); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int length = np.length(); 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = length - 1, s = length 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ; i >= 0 && (s - i) <= numDigits ; i-- 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ) { 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = np.charAt(i); 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(c); 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret.toString(); 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Basically: makes sure there's a + in front of a 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TOA_International number 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns null if s == null 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stringFromStringAndTOA(String s, int TOA) { 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (s == null) return null; 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (TOA == TOA_International && s.length() > 0 && s.charAt(0) != '+') { 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "+" + s; 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return s; 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the TOA for the given dial string 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Basically, returns TOA_International if there's a + prefix 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toaFromString(String s) { 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (s != null && s.length() > 0 && s.charAt(0) == '+') { 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return TOA_International; 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return TOA_Unknown; 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3GPP TS 24.008 10.5.4.7 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called Party BCD Number 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See Also TS 51.011 10.5.1 "dialing number/ssc string" 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and TS 11.11 "10.3.1 EF adn (Abbreviated dialing numbers)" 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param bytes the data buffer 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param offset should point to the TOA (aka. TON/NPI) octet after the length byte 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param length is the number of bytes including TOA byte 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and must be at least 2 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return partial string on invalid decode 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * FIXME(mkf) support alphanumeric address type 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * currently implemented in SMSMessage.getAddress() 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calledPartyBCDToString (byte[] bytes, int offset, int length) { 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean prependPlus = false; 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder ret = new StringBuilder(1 + length * 2); 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (length < 2) { 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ""; 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((bytes[offset] & 0xff) == TOA_International) { 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project prependPlus = true; 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project internalCalledPartyBCDFragmentToString( 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret, bytes, offset + 1, length - 1); 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prependPlus && ret.length() == 0) { 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the only thing there is a prepended plus, return "" 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ""; 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prependPlus) { 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is an "international number" and should have 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a plus prepended to the dialing number. But there 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // can also be Gsm MMI codes as defined in TS 22.030 6.5.2 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so we need to handle those also. 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // http://web.telia.com/~u47904776/gsmkode.htm is a 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // has a nice list of some of these GSM codes. 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Examples are: 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // **21*+886988171479# 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // **21*8311234567# 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // *21# 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // #21# 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // *#21# 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // *31#+11234567890 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // #31#+18311234567 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // #31#8311234567 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 18311234567 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // +18311234567# 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // +18311234567 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Odd ball cases that some phones handled 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // where there is no dialing number so they 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // append the "+" 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // *21#+ 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // **21#+ 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String retString = ret.toString(); 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Pattern p = Pattern.compile("(^[#*])(.*)([#*])(.*)(#)$"); 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Matcher m = p.matcher(retString); 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (m.matches()) { 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ("".equals(m.group(2))) { 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Started with two [#*] ends with # 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // So no dialing number and we'll just 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // append a +, this handles **21#+ 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = new StringBuilder(); 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(1)); 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(3)); 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(4)); 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(5)); 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append("+"); 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Starts with [#*] and ends with # 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Assume group 4 is a dialing number 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // such as *21*+1234554# 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = new StringBuilder(); 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(1)); 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(2)); 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(3)); 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append("+"); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(4)); 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(5)); 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p = Pattern.compile("(^[#*])(.*)([#*])(.*)"); 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project m = p.matcher(retString); 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (m.matches()) { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Starts with [#*] and only one other [#*] 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Assume the data after last [#*] is dialing 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // number (i.e. group 4) such as *31#+11234567890. 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This also includes the odd ball *21#+ 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = new StringBuilder(); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(1)); 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(2)); 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(3)); 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append("+"); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(m.group(4)); 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Does NOT start with [#*] just prepend '+' 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = new StringBuilder(); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append('+'); 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.append(retString); 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret.toString(); 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project internalCalledPartyBCDFragmentToString( 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb, byte [] bytes, int offset, int length) { 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = offset ; i < length + offset ; i++) { 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte b; 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c; 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c = bcdToChar((byte)(bytes[i] & 0xf)); 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == 0) { 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(c); 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // FIXME(mkf) TS 23.040 9.1.2.3 says 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "if a mobile receives 1111 in a position prior to 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the last semi-octet then processing shall commense with 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the next semi-octet and the intervening 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // semi-octet shall be ignored" 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // How does this jive with 24,008 10.5.4.7 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b = (byte)((bytes[i] >> 4) & 0xf); 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (b == 0xf && i + 1 == length + offset) { 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //ignore final 0xf 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c = bcdToChar(b); 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == 0) { 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(c); 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Like calledPartyBCDToString, but field does not start with a 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TOA byte. For example: SIM ADN extension fields 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calledPartyBCDFragmentToString(byte [] bytes, int offset, int length) { 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder ret = new StringBuilder(length * 2); 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project internalCalledPartyBCDFragmentToString(ret, bytes, offset, length); 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret.toString(); 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** returns 0 on invalid value */ 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static char 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bcdToChar(byte b) { 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (b < 0xa) { 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (char)('0' + b); 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else switch (b) { 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 0xa: return '*'; 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 0xb: return '#'; 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 0xc: return PAUSE; 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 0xd: return WILD; 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: return 0; 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static int 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project charToBCD(char c) { 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '0' && c <= '9') { 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return c - '0'; 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (c == '*') { 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0xa; 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (c == '#') { 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0xb; 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (c == PAUSE) { 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0xc; 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (c == WILD) { 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0xd; 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException ("invalid char for BCD " + c); 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return true iff the network portion of <code>address</code> is, 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as far as we can tell on the device, suitable for use as an SMS 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * destination address. 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean isWellFormedSmsAddress(String address) { 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String networkPortion = 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PhoneNumberUtils.extractNetworkPortion(address); 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (!(networkPortion.equals("+") 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || TextUtils.isEmpty(networkPortion))) 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && isDialable(networkPortion); 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean isGlobalPhoneNumber(String phoneNumber) { 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (TextUtils.isEmpty(phoneNumber)) { 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Matcher match = GLOBAL_PHONE_NUMBER_PATTERN.matcher(phoneNumber); 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return match.matches(); 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static boolean isDialable(String address) { 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0, count = address.length(); i < count; i++) { 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isDialable(address.charAt(i))) { 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 89818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static boolean isNonSeparator(String address) { 89918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com for (int i = 0, count = address.length(); i < count; i++) { 90018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (!isNonSeparator(address.charAt(i))) { 90118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return false; 90218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 90318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 90418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return true; 90518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9073a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink * Note: calls extractNetworkPortion(), so do not use for 9083a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink * SIM EF[ADN] style records 9093a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink * 9103a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink * Returns null if network portion is empty. 9113a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink */ 9123a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink public static byte[] 9133a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink networkPortionToCalledPartyBCD(String s) { 9143a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink String networkPortion = extractNetworkPortion(s); 9153a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink return numberToCalledPartyBCDHelper(networkPortion, false); 9163a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink } 9173a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink 9183a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink /** 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Same as {@link #networkPortionToCalledPartyBCD}, but includes a 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * one-byte length prefix. 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static byte[] 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project networkPortionToCalledPartyBCDWithLength(String s) { 9243a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink String networkPortion = extractNetworkPortion(s); 9253a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink return numberToCalledPartyBCDHelper(networkPortion, true); 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Convert a dialing number to BCD byte array 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param number dialing number string 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if the dialing number starts with '+', set to internationl TOA 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return BCD byte array 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static byte[] 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numberToCalledPartyBCD(String number) { 9373a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink return numberToCalledPartyBCDHelper(number, false); 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9413a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink * If includeLength is true, prepend a one-byte length value to 9423a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink * the return array. 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static byte[] 9453a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink numberToCalledPartyBCDHelper(String number, boolean includeLength) { 9463a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink int numberLenReal = number.length(); 9473a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink int numberLenEffective = numberLenReal; 9483a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink boolean hasPlus = number.indexOf('+') != -1; 9493a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink if (hasPlus) numberLenEffective--; 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9513a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink if (numberLenEffective == 0) return null; 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9533a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink int resultLen = (numberLenEffective + 1) / 2; // Encoded numbers require only 4 bits each. 9543a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink int extraBytes = 1; // Prepended TOA byte. 9553a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink if (includeLength) extraBytes++; // Optional prepended length byte. 9563a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink resultLen += extraBytes; 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9583a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink byte[] result = new byte[resultLen]; 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9603a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink int digitCount = 0; 9613a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink for (int i = 0; i < numberLenReal; i++) { 9623a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink char c = number.charAt(i); 9633a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink if (c == '+') continue; 9643a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink int shift = ((digitCount & 0x01) == 1) ? 4 : 0; 9653a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink result[extraBytes + (digitCount >> 1)] |= (byte)((charToBCD(c) & 0x0F) << shift); 9663a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink digitCount++; 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9693a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink // 1-fill any trailing odd nibble/quartet. 9703a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink if ((digitCount & 0x01) == 1) result[extraBytes + (digitCount >> 1)] |= 0xF0; 9713a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink 9723a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink int offset = 0; 9733a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink if (includeLength) result[offset++] = (byte)(resultLen - 1); 9743a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink result[offset] = (byte)(hasPlus ? TOA_International : TOA_Unknown); 9753a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink 9763a08cec99e104f74f28ba2463f00c8d4e6d1967eTammo Spalink return result; 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //================ Number formatting ========================= 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The current locale is unknown, look for a country code or don't format */ 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int FORMAT_UNKNOWN = 0; 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** NANP formatting */ 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int FORMAT_NANP = 1; 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Japanese formatting */ 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int FORMAT_JAPAN = 2; 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** List of country codes for countries that use the NANP */ 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String[] NANP_COUNTRIES = new String[] { 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "US", // United States 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "CA", // Canada 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "AS", // American Samoa 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "AI", // Anguilla 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "AG", // Antigua and Barbuda 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "BS", // Bahamas 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "BB", // Barbados 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "BM", // Bermuda 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "VG", // British Virgin Islands 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "KY", // Cayman Islands 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "DM", // Dominica 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "DO", // Dominican Republic 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "GD", // Grenada 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "GU", // Guam 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "JM", // Jamaica 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "PR", // Puerto Rico 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "MS", // Montserrat 10077850cdde66705152b859aafda875833acdda9653Libin Tang "MP", // Northern Mariana Islands 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "KN", // Saint Kitts and Nevis 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "LC", // Saint Lucia 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "VC", // Saint Vincent and the Grenadines 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "TT", // Trinidad and Tobago 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "TC", // Turks and Caicos Islands 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "VI", // U.S. Virgin Islands 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Breaks the given number down and formats it according to the rules 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for the country the number is from. 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param source the phone number to format 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return a locally acceptable formatting of the input, or the raw input if 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * formatting rules aren't known for the number 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String formatNumber(String source) { 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpannableStringBuilder text = new SpannableStringBuilder(source); 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project formatNumber(text, getFormatTypeForLocale(Locale.getDefault())); 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return text.toString(); 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the phone number formatting type for the given locale. 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param locale The locale of interest, usually {@link Locale#getDefault()} 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the formatting type for the given locale, or FORMAT_UNKNOWN if the formatting 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * rules are not known for the given locale 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getFormatTypeForLocale(Locale locale) { 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String country = locale.getCountry(); 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10407850cdde66705152b859aafda875833acdda9653Libin Tang return getFormatTypeFromCountryCode(country); 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Formats a phone number in-place. Currently only supports NANP formatting. 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text The number to be formatted, will be modified with the formatting 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param defaultFormattingType The default formatting rules to apply if the number does 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not begin with +<country_code> 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void formatNumber(Editable text, int defaultFormattingType) { 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int formatType = defaultFormattingType; 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (text.length() > 2 && text.charAt(0) == '+') { 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (text.charAt(1) == '1') { 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project formatType = FORMAT_NANP; 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (text.length() >= 3 && text.charAt(1) == '8' 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && text.charAt(2) == '1') { 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project formatType = FORMAT_JAPAN; 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (formatType) { 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case FORMAT_NANP: 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project formatNanpNumber(text); 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case FORMAT_JAPAN: 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project formatJapaneseNumber(text); 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int NANP_STATE_DIGIT = 1; 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int NANP_STATE_PLUS = 2; 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int NANP_STATE_ONE = 3; 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int NANP_STATE_DASH = 4; 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Formats a phone number in-place using the NANP formatting rules. Numbers will be formatted 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as: 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><code> 10845214376d2b1ce082765f766be1c7d56b50df74a7Ficus Kirkpatrick * xxxxx 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * xxx-xxxx 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * xxx-xxx-xxxx 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1-xxx-xxx-xxxx 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * +1-xxx-xxx-xxxx 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </code></p> 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text the number to be formatted, will be modified with the formatting 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void formatNanpNumber(Editable text) { 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int length = text.length(); 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (length > "+1-nnn-nnn-nnnn".length()) { 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The string is too long to be formatted 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 10985214376d2b1ce082765f766be1c7d56b50df74a7Ficus Kirkpatrick } else if (length <= 5) { 10995214376d2b1ce082765f766be1c7d56b50df74a7Ficus Kirkpatrick // The string is either a shortcode or too short to be formatted 11005214376d2b1ce082765f766be1c7d56b50df74a7Ficus Kirkpatrick return; 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11025214376d2b1ce082765f766be1c7d56b50df74a7Ficus Kirkpatrick 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence saved = text.subSequence(0, length); 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Strip the dashes first, as we're going to add them back 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int p = 0; 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (p < text.length()) { 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (text.charAt(p) == '-') { 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.delete(p, p + 1); 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p++; 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project length = text.length(); 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // When scanning the number we record where dashes need to be added, 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if they're non-0 at the end of the scan the dashes will be added in 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the proper places. 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dashPositions[] = new int[3]; 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numDashes = 0; 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int state = NANP_STATE_DIGIT; 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numDigits = 0; 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < length; i++) { 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = text.charAt(i); 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (c) { 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '1': 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (numDigits == 0 || state == NANP_STATE_PLUS) { 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state = NANP_STATE_ONE; 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // fall through 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '2': 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '3': 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '4': 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '5': 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '6': 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '7': 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '8': 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '9': 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '0': 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == NANP_STATE_PLUS) { 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Only NANP number supported for now 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.replace(0, length, saved); 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (state == NANP_STATE_ONE) { 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Found either +1 or 1, follow it up with a dash 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dashPositions[numDashes++] = i; 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (state != NANP_STATE_DASH && (numDigits == 3 || numDigits == 6)) { 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Found a digit that should be after a dash that isn't 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dashPositions[numDashes++] = i; 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state = NANP_STATE_DIGIT; 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numDigits++; 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '-': 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state = NANP_STATE_DASH; 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case '+': 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (i == 0) { 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Plus is only allowed as the first character 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state = NANP_STATE_PLUS; 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fall through 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Unknown character, bail on formatting 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.replace(0, length, saved); 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (numDigits == 7) { 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // With 7 digits we want xxx-xxxx, not xxx-xxx-x 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numDashes--; 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Actually put the dashes in place 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numDashes; i++) { 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int pos = dashPositions[i]; 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.replace(pos + i, pos + i, "-"); 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remove trailing dashes 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (len > 0) { 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (text.charAt(len - 1) == '-') { 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.delete(len - 1, len); 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len--; 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Formats a phone number in-place using the Japanese formatting rules. 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Numbers will be formatted as: 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><code> 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 03-xxxx-xxxx 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 090-xxxx-xxxx 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 0120-xxx-xxx 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * +81-3-xxxx-xxxx 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * +81-90-xxxx-xxxx 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </code></p> 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text the number to be formatted, will be modified with 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the formatting 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void formatJapaneseNumber(Editable text) { 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JapanesePhoneNumberFormatter.format(text); 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 121702b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // Three and four digit phone numbers for either special services, 121802b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // or 3-6 digit addresses from the network (eg carrier-originated SMS messages) should 121902b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // not match. 122002b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // 122102b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // This constant used to be 5, but SMS short codes has increased in length and 122202b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // can be easily 6 digits now days. Most countries have SMS short code length between 122302b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // 3 to 6 digits. The exceptions are 122402b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // 122502b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // Australia: Short codes are six or eight digits in length, starting with the prefix "19" 122602b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // followed by an additional four or six digits and two. 122702b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // Czech Republic: Codes are seven digits in length for MO and five (not billed) or 122802b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // eight (billed) for MT direction 122902b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // 123002b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // see http://en.wikipedia.org/wiki/Short_code#Regional_differences for reference 123102b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // 123202b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // However, in order to loose match 650-555-1212 and 555-1212, we need to set the min match 123302b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang // to 7. 123402b5948a4375dba5d287a59ba023eaf1e02b45dcWei Huang static final int MIN_MATCH = 7; 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * isEmergencyNumber: checks a given number against the list of 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * emergency numbers provided by the RIL and SIM card. 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param number the number to look up. 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return if the number is in the list of emergency numbers 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * listed in the ril / sim, then return true, otherwise false. 12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean isEmergencyNumber(String number) { 1245694bd8bf733aee372705e00d13964a20e5b16209Peng Zhu // If the number passed in is null, just return false: 1246694bd8bf733aee372705e00d13964a20e5b16209Peng Zhu if (number == null) return false; 1247694bd8bf733aee372705e00d13964a20e5b16209Peng Zhu 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Strip the separators from the number before comparing it 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to the list. 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project number = extractNetworkPortion(number); 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // retrieve the list of emergency numbers 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String numbers = SystemProperties.get("ro.ril.ecclist"); 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!TextUtils.isEmpty(numbers)) { 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // searches through the comma-separated list for a match, 12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // return true if one is found. 12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String emergencyNum : numbers.split(",")) { 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (emergencyNum.equals(number)) { 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no matches found against the list! 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //no ecclist system property, so use our own list. 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (number.equals("112") || number.equals("911")); 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 127260d45f0f0320801a16db2ad038453c098e98966cNicolas Catania * isVoiceMailNumber: checks a given number against the voicemail 127360d45f0f0320801a16db2ad038453c098e98966cNicolas Catania * number provided by the RIL and SIM card. The caller must have 127460d45f0f0320801a16db2ad038453c098e98966cNicolas Catania * the READ_PHONE_STATE credential. 127560d45f0f0320801a16db2ad038453c098e98966cNicolas Catania * 127660d45f0f0320801a16db2ad038453c098e98966cNicolas Catania * @param number the number to look up. 127760d45f0f0320801a16db2ad038453c098e98966cNicolas Catania * @return true if the number is in the list of voicemail. False 127860d45f0f0320801a16db2ad038453c098e98966cNicolas Catania * otherwise, including if the caller does not have the permission 127960d45f0f0320801a16db2ad038453c098e98966cNicolas Catania * to read the VM number. 128060d45f0f0320801a16db2ad038453c098e98966cNicolas Catania * @hide TODO: pending API Council approval 128160d45f0f0320801a16db2ad038453c098e98966cNicolas Catania */ 128260d45f0f0320801a16db2ad038453c098e98966cNicolas Catania public static boolean isVoiceMailNumber(String number) { 128360d45f0f0320801a16db2ad038453c098e98966cNicolas Catania String vmNumber; 128460d45f0f0320801a16db2ad038453c098e98966cNicolas Catania 128560d45f0f0320801a16db2ad038453c098e98966cNicolas Catania try { 128660d45f0f0320801a16db2ad038453c098e98966cNicolas Catania vmNumber = TelephonyManager.getDefault().getVoiceMailNumber(); 128760d45f0f0320801a16db2ad038453c098e98966cNicolas Catania } catch (SecurityException ex) { 128860d45f0f0320801a16db2ad038453c098e98966cNicolas Catania return false; 128960d45f0f0320801a16db2ad038453c098e98966cNicolas Catania } 129060d45f0f0320801a16db2ad038453c098e98966cNicolas Catania 129160d45f0f0320801a16db2ad038453c098e98966cNicolas Catania // Strip the separators from the number before comparing it 129260d45f0f0320801a16db2ad038453c098e98966cNicolas Catania // to the list. 129360d45f0f0320801a16db2ad038453c098e98966cNicolas Catania number = extractNetworkPortion(number); 129460d45f0f0320801a16db2ad038453c098e98966cNicolas Catania 129560d45f0f0320801a16db2ad038453c098e98966cNicolas Catania // compare tolerates null so we need to make sure that we 129660d45f0f0320801a16db2ad038453c098e98966cNicolas Catania // don't return true when both are null. 129760d45f0f0320801a16db2ad038453c098e98966cNicolas Catania return !TextUtils.isEmpty(number) && compare(number, vmNumber); 129860d45f0f0320801a16db2ad038453c098e98966cNicolas Catania } 129960d45f0f0320801a16db2ad038453c098e98966cNicolas Catania 130060d45f0f0320801a16db2ad038453c098e98966cNicolas Catania /** 13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Translates any alphabetic letters (i.e. [A-Za-z]) in the 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified phone number into the equivalent numeric digits, 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * according to the phone keypad letter mapping described in 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ITU E.161 and ISO/IEC 9995-8. 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the input string, with alpha letters converted to numeric 13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * digits using the phone keypad letter mapping. For example, 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * an input of "1-800-GOOG-411" will return "1-800-4664-411". 13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String convertKeypadLettersToDigits(String input) { 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (input == null) { 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return input; 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = input.length(); 13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len == 0) { 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return input; 13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] out = input.toCharArray(); 13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < len; i++) { 13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = out[i]; 13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If this char isn't in KEYPAD_MAP at all, just leave it alone. 13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out[i] = (char) KEYPAD_MAP.get(c, c); 13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new String(out); 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The phone keypad letter mapping (see ITU E.161 or ISO/IEC 9995-8.) 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TODO: This should come from a resource. 13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final SparseIntArray KEYPAD_MAP = new SparseIntArray(); 13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('a', '2'); KEYPAD_MAP.put('b', '2'); KEYPAD_MAP.put('c', '2'); 13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('A', '2'); KEYPAD_MAP.put('B', '2'); KEYPAD_MAP.put('C', '2'); 13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('d', '3'); KEYPAD_MAP.put('e', '3'); KEYPAD_MAP.put('f', '3'); 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('D', '3'); KEYPAD_MAP.put('E', '3'); KEYPAD_MAP.put('F', '3'); 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('g', '4'); KEYPAD_MAP.put('h', '4'); KEYPAD_MAP.put('i', '4'); 13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('G', '4'); KEYPAD_MAP.put('H', '4'); KEYPAD_MAP.put('I', '4'); 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('j', '5'); KEYPAD_MAP.put('k', '5'); KEYPAD_MAP.put('l', '5'); 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('J', '5'); KEYPAD_MAP.put('K', '5'); KEYPAD_MAP.put('L', '5'); 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('m', '6'); KEYPAD_MAP.put('n', '6'); KEYPAD_MAP.put('o', '6'); 13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('M', '6'); KEYPAD_MAP.put('N', '6'); KEYPAD_MAP.put('O', '6'); 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('p', '7'); KEYPAD_MAP.put('q', '7'); KEYPAD_MAP.put('r', '7'); KEYPAD_MAP.put('s', '7'); 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('P', '7'); KEYPAD_MAP.put('Q', '7'); KEYPAD_MAP.put('R', '7'); KEYPAD_MAP.put('S', '7'); 13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('t', '8'); KEYPAD_MAP.put('u', '8'); KEYPAD_MAP.put('v', '8'); 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('T', '8'); KEYPAD_MAP.put('U', '8'); KEYPAD_MAP.put('V', '8'); 13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('w', '9'); KEYPAD_MAP.put('x', '9'); KEYPAD_MAP.put('y', '9'); KEYPAD_MAP.put('z', '9'); 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KEYPAD_MAP.put('W', '9'); KEYPAD_MAP.put('X', '9'); KEYPAD_MAP.put('Y', '9'); KEYPAD_MAP.put('Z', '9'); 13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 136018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 136118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com //================ Plus Code formatting ========================= 136218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static final char PLUS_SIGN_CHAR = '+'; 136318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static final String PLUS_SIGN_STRING = "+"; 136418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static final String NANP_IDP_STRING = "011"; 136518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static final int NANP_LENGTH = 10; 136618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 136718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com /** 136818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * This function checks if there is a plus sign (+) in the passed-in dialing number. 136918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * If there is, it processes the plus sign based on the default telephone 137018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * numbering plan of the system when the phone is activated and the current 137118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * telephone numbering plan of the system that the phone is camped on. 137218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * Currently, we only support the case that the default and current telephone 137318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * numbering plans are North American Numbering Plan(NANP). 137418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * 137518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * The passed-in dialStr should only contain the valid format as described below, 137618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * 1) the 1st character in the dialStr should be one of the really dialable 137718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * characters listed below 137818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * ISO-LATIN characters 0-9, *, # , + 137918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * 2) the dialStr should already strip out the separator characters, 138018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * every character in the dialStr should be one of the non separator characters 138118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * listed below 138218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * ISO-LATIN characters 0-9, *, # , +, WILD, WAIT, PAUSE 138318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * 138418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * Otherwise, this function returns the dial string passed in 138518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * 13867850cdde66705152b859aafda875833acdda9653Libin Tang * @param dialStr the original dial string 13877850cdde66705152b859aafda875833acdda9653Libin Tang * @return the converted dial string if the current/default countries belong to NANP, 13887850cdde66705152b859aafda875833acdda9653Libin Tang * and if there is the "+" in the original dial string. Otherwise, the original dial 13897850cdde66705152b859aafda875833acdda9653Libin Tang * string returns. 13907850cdde66705152b859aafda875833acdda9653Libin Tang * 139118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * This API is for CDMA only 139218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * 139318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * @hide TODO: pending API Council approval 139418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com */ 139518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com public static String cdmaCheckAndProcessPlusCode(String dialStr) { 139618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (!TextUtils.isEmpty(dialStr)) { 139718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (isReallyDialable(dialStr.charAt(0)) && 139818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com isNonSeparator(dialStr)) { 13997850cdde66705152b859aafda875833acdda9653Libin Tang String currIso = SystemProperties.get(PROPERTY_OPERATOR_ISO_COUNTRY, ""); 14007850cdde66705152b859aafda875833acdda9653Libin Tang String defaultIso = SystemProperties.get(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, ""); 14017850cdde66705152b859aafda875833acdda9653Libin Tang if (!TextUtils.isEmpty(currIso) && !TextUtils.isEmpty(defaultIso)) { 14027850cdde66705152b859aafda875833acdda9653Libin Tang return cdmaCheckAndProcessPlusCodeByNumberFormat(dialStr, 14037850cdde66705152b859aafda875833acdda9653Libin Tang getFormatTypeFromCountryCode(currIso), 14047850cdde66705152b859aafda875833acdda9653Libin Tang getFormatTypeFromCountryCode(defaultIso)); 14057850cdde66705152b859aafda875833acdda9653Libin Tang } 140618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 140718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 140818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return dialStr; 140918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 141018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 141118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com /** 141218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * This function should be called from checkAndProcessPlusCode only 141318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * And it is used for test purpose also. 141418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * 141518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * It checks the dial string by looping through the network portion, 141618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * post dial portion 1, post dial porting 2, etc. If there is any 141718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * plus sign, then process the plus sign. 141818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * Currently, this function supports the plus sign conversion within NANP only. 141918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * Specifically, it handles the plus sign in the following ways: 14207850cdde66705152b859aafda875833acdda9653Libin Tang * 1)+1NANP,remove +, e.g. 142118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * +18475797000 is converted to 18475797000, 14227850cdde66705152b859aafda875833acdda9653Libin Tang * 2)+NANP or +non-NANP Numbers,replace + with the current NANP IDP, e.g, 14237850cdde66705152b859aafda875833acdda9653Libin Tang * +8475797000 is converted to 0118475797000, 142418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * +11875767800 is converted to 01111875767800 14257850cdde66705152b859aafda875833acdda9653Libin Tang * 3)+1NANP in post dial string(s), e.g. 14267850cdde66705152b859aafda875833acdda9653Libin Tang * 8475797000;+18475231753 is converted to 8475797000;18475231753 14277850cdde66705152b859aafda875833acdda9653Libin Tang * 142818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * 14297850cdde66705152b859aafda875833acdda9653Libin Tang * @param dialStr the original dial string 14307850cdde66705152b859aafda875833acdda9653Libin Tang * @param currFormat the numbering system of the current country that the phone is camped on 14317850cdde66705152b859aafda875833acdda9653Libin Tang * @param defaultFormat the numbering system of the country that the phone is activated on 14327850cdde66705152b859aafda875833acdda9653Libin Tang * @return the converted dial string if the current/default countries belong to NANP, 14337850cdde66705152b859aafda875833acdda9653Libin Tang * and if there is the "+" in the original dial string. Otherwise, the original dial 14347850cdde66705152b859aafda875833acdda9653Libin Tang * string returns. 143518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * 143618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * @hide 143718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com */ 14387850cdde66705152b859aafda875833acdda9653Libin Tang public static String 14397850cdde66705152b859aafda875833acdda9653Libin Tang cdmaCheckAndProcessPlusCodeByNumberFormat(String dialStr,int currFormat,int defaultFormt) { 144018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com String retStr = dialStr; 144118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 144218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // Checks if the plus sign character is in the passed-in dial string 144318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (dialStr != null && 144418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com dialStr.lastIndexOf(PLUS_SIGN_STRING) != -1) { 14457850cdde66705152b859aafda875833acdda9653Libin Tang // Format the string based on the rules for the country the number is from, 14467850cdde66705152b859aafda875833acdda9653Libin Tang // and the current country the phone is camped on. 14477850cdde66705152b859aafda875833acdda9653Libin Tang if ((currFormat == defaultFormt) && (currFormat == FORMAT_NANP)) { 14487850cdde66705152b859aafda875833acdda9653Libin Tang // Handle case where default and current telephone numbering plans are NANP. 14497850cdde66705152b859aafda875833acdda9653Libin Tang String postDialStr = null; 14507850cdde66705152b859aafda875833acdda9653Libin Tang String tempDialStr = dialStr; 14517850cdde66705152b859aafda875833acdda9653Libin Tang 14527850cdde66705152b859aafda875833acdda9653Libin Tang // Sets the retStr to null since the conversion will be performed below. 14537850cdde66705152b859aafda875833acdda9653Libin Tang retStr = null; 14547850cdde66705152b859aafda875833acdda9653Libin Tang if (DBG) log("checkAndProcessPlusCode,dialStr=" + dialStr); 14557850cdde66705152b859aafda875833acdda9653Libin Tang // This routine is to process the plus sign in the dial string by loop through 14567850cdde66705152b859aafda875833acdda9653Libin Tang // the network portion, post dial portion 1, post dial portion 2... etc. if 14577850cdde66705152b859aafda875833acdda9653Libin Tang // applied 14587850cdde66705152b859aafda875833acdda9653Libin Tang do { 14597850cdde66705152b859aafda875833acdda9653Libin Tang String networkDialStr; 146018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com networkDialStr = extractNetworkPortion(tempDialStr); 146118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // Handles the conversion within NANP 146218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com networkDialStr = processPlusCodeWithinNanp(networkDialStr); 14637850cdde66705152b859aafda875833acdda9653Libin Tang 14647850cdde66705152b859aafda875833acdda9653Libin Tang // Concatenates the string that is converted from network portion 14657850cdde66705152b859aafda875833acdda9653Libin Tang if (!TextUtils.isEmpty(networkDialStr)) { 14667850cdde66705152b859aafda875833acdda9653Libin Tang if (retStr == null) { 14677850cdde66705152b859aafda875833acdda9653Libin Tang retStr = networkDialStr; 14687850cdde66705152b859aafda875833acdda9653Libin Tang } else { 14697850cdde66705152b859aafda875833acdda9653Libin Tang retStr = retStr.concat(networkDialStr); 14707850cdde66705152b859aafda875833acdda9653Libin Tang } 147118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } else { 14727850cdde66705152b859aafda875833acdda9653Libin Tang // This should never happen since we checked the if dialStr is null 14737850cdde66705152b859aafda875833acdda9653Libin Tang // and if it contains the plus sign in the beginning of this function. 14747850cdde66705152b859aafda875833acdda9653Libin Tang // The plus sign is part of the network portion. 14757850cdde66705152b859aafda875833acdda9653Libin Tang Log.e("checkAndProcessPlusCode: null newDialStr", networkDialStr); 14767850cdde66705152b859aafda875833acdda9653Libin Tang return dialStr; 147718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 14787850cdde66705152b859aafda875833acdda9653Libin Tang postDialStr = extractPostDialPortion(tempDialStr); 14797850cdde66705152b859aafda875833acdda9653Libin Tang if (!TextUtils.isEmpty(postDialStr)) { 14807850cdde66705152b859aafda875833acdda9653Libin Tang int dialableIndex = findDialableIndexFromPostDialStr(postDialStr); 14817850cdde66705152b859aafda875833acdda9653Libin Tang 14827850cdde66705152b859aafda875833acdda9653Libin Tang // dialableIndex should always be greater than 0 14837850cdde66705152b859aafda875833acdda9653Libin Tang if (dialableIndex >= 1) { 14847850cdde66705152b859aafda875833acdda9653Libin Tang retStr = appendPwCharBackToOrigDialStr(dialableIndex, 14857850cdde66705152b859aafda875833acdda9653Libin Tang retStr,postDialStr); 14867850cdde66705152b859aafda875833acdda9653Libin Tang // Skips the P/W character, extracts the dialable portion 14877850cdde66705152b859aafda875833acdda9653Libin Tang tempDialStr = postDialStr.substring(dialableIndex); 14887850cdde66705152b859aafda875833acdda9653Libin Tang } else { 14897850cdde66705152b859aafda875833acdda9653Libin Tang // Non-dialable character such as P/W should not be at the end of 14907850cdde66705152b859aafda875833acdda9653Libin Tang // the dial string after P/W processing in CdmaConnection.java 14917850cdde66705152b859aafda875833acdda9653Libin Tang // Set the postDialStr to "" to break out of the loop 14927850cdde66705152b859aafda875833acdda9653Libin Tang if (dialableIndex < 0) { 14937850cdde66705152b859aafda875833acdda9653Libin Tang postDialStr = ""; 14947850cdde66705152b859aafda875833acdda9653Libin Tang } 14957850cdde66705152b859aafda875833acdda9653Libin Tang Log.e("wrong postDialStr=", postDialStr); 149618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 149718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 14987850cdde66705152b859aafda875833acdda9653Libin Tang if (DBG) log("checkAndProcessPlusCode,postDialStr=" + postDialStr); 14997850cdde66705152b859aafda875833acdda9653Libin Tang } while (!TextUtils.isEmpty(postDialStr) && !TextUtils.isEmpty(tempDialStr)); 15007850cdde66705152b859aafda875833acdda9653Libin Tang } else { 15017850cdde66705152b859aafda875833acdda9653Libin Tang // TODO: Support NANP international conversion and other telephone numbering plans. 15027850cdde66705152b859aafda875833acdda9653Libin Tang // Currently the phone is never used in non-NANP system, so return the original 15037850cdde66705152b859aafda875833acdda9653Libin Tang // dial string. 15047850cdde66705152b859aafda875833acdda9653Libin Tang Log.e("checkAndProcessPlusCode:non-NANP not supported", dialStr); 15057850cdde66705152b859aafda875833acdda9653Libin Tang } 150618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 150718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return retStr; 150818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 150918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 151018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // This function gets the default international dialing prefix 151118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static String getDefaultIdp( ) { 151218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com String ps = null; 151318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com SystemProperties.get(PROPERTY_IDP_STRING, ps); 151418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (TextUtils.isEmpty(ps)) { 151518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com ps = NANP_IDP_STRING; 151618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 151718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return ps; 151818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 151918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 152018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static boolean isTwoToNine (char c) { 152118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (c >= '2' && c <= '9') { 152218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return true; 152318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } else { 152418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return false; 152518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 152618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 152718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 15287850cdde66705152b859aafda875833acdda9653Libin Tang private static int getFormatTypeFromCountryCode (String country) { 15297850cdde66705152b859aafda875833acdda9653Libin Tang // Check for the NANP countries 15307850cdde66705152b859aafda875833acdda9653Libin Tang int length = NANP_COUNTRIES.length; 15317850cdde66705152b859aafda875833acdda9653Libin Tang for (int i = 0; i < length; i++) { 15327850cdde66705152b859aafda875833acdda9653Libin Tang if (NANP_COUNTRIES[i].compareToIgnoreCase(country) == 0) { 15337850cdde66705152b859aafda875833acdda9653Libin Tang return FORMAT_NANP; 15347850cdde66705152b859aafda875833acdda9653Libin Tang } 15357850cdde66705152b859aafda875833acdda9653Libin Tang } 15367850cdde66705152b859aafda875833acdda9653Libin Tang if ("jp".compareToIgnoreCase(country) == 0) { 15377850cdde66705152b859aafda875833acdda9653Libin Tang return FORMAT_JAPAN; 15387850cdde66705152b859aafda875833acdda9653Libin Tang } 15397850cdde66705152b859aafda875833acdda9653Libin Tang return FORMAT_UNKNOWN; 15407850cdde66705152b859aafda875833acdda9653Libin Tang } 15417850cdde66705152b859aafda875833acdda9653Libin Tang 154218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com /** 154318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * This function checks if the passed in string conforms to the NANP format 154418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * i.e. NXX-NXX-XXXX, N is any digit 2-9 and X is any digit 0-9 154518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com */ 154618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static boolean isNanp (String dialStr) { 154718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com boolean retVal = false; 154818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (dialStr != null) { 154918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (dialStr.length() == NANP_LENGTH) { 155018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (isTwoToNine(dialStr.charAt(0)) && 155118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com isTwoToNine(dialStr.charAt(3))) { 155218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com retVal = true; 155318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com for (int i=1; i<NANP_LENGTH; i++ ) { 155418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com char c=dialStr.charAt(i); 155518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (!PhoneNumberUtils.isISODigit(c)) { 155618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com retVal = false; 155718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com break; 155818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 155918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 156018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 156118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 156218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } else { 156318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com Log.e("isNanp: null dialStr passed in", dialStr); 156418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 156518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return retVal; 156618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 156718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 156818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com /** 156918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * This function checks if the passed in string conforms to 1-NANP format 157018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com */ 157118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static boolean isOneNanp(String dialStr) { 157218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com boolean retVal = false; 157318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (dialStr != null) { 157418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com String newDialStr = dialStr.substring(1); 157518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if ((dialStr.charAt(0) == '1') && isNanp(newDialStr)) { 157618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com retVal = true; 157718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 157818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } else { 157918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com Log.e("isOneNanp: null dialStr passed in", dialStr); 158018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 158118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return retVal; 158218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 158318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 158418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com /** 158518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * This function handles the plus code conversion within NANP CDMA network 158618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com * If the number format is 15877850cdde66705152b859aafda875833acdda9653Libin Tang * 1)+1NANP,remove +, 15887850cdde66705152b859aafda875833acdda9653Libin Tang * 2)other than +1NANP, any + numbers,replace + with the current IDP 158918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com */ 159018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static String processPlusCodeWithinNanp(String networkDialStr) { 159118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com String retStr = networkDialStr; 159218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 159318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (DBG) log("processPlusCodeWithinNanp,networkDialStr=" + networkDialStr); 159418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // If there is a plus sign at the beginning of the dial string, 159518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // Convert the plus sign to the default IDP since it's an international number 159618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (networkDialStr != null & 159718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com networkDialStr.charAt(0) == PLUS_SIGN_CHAR && 159818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com networkDialStr.length() > 1) { 159918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com String newStr = networkDialStr.substring(1); 16007850cdde66705152b859aafda875833acdda9653Libin Tang if (isOneNanp(newStr)) { 160118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // Remove the leading plus sign 160218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com retStr = newStr; 160318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } else { 160418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com String idpStr = getDefaultIdp(); 160518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // Replaces the plus sign with the default IDP 160618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com retStr = networkDialStr.replaceFirst("[+]", idpStr); 160718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 160818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 160918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (DBG) log("processPlusCodeWithinNanp,retStr=" + retStr); 161018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return retStr; 161118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 161218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 161318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // This function finds the index of the dialable character(s) 161418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // in the post dial string 161518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static int findDialableIndexFromPostDialStr(String postDialStr) { 161618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com for (int index = 0;index < postDialStr.length();index++) { 161718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com char c = postDialStr.charAt(index); 161818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (isReallyDialable(c)) { 161918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return index; 162018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 162118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 162218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return -1; 162318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 162418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 162518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // This function appends the non-diablable P/W character to the original 162618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // dial string based on the dialable index passed in 162718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com private static String 162818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com appendPwCharBackToOrigDialStr(int dialableIndex,String origStr, String dialStr) { 162918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com String retStr; 163018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com 163118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // There is only 1 P/W character before the dialable characters 163218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com if (dialableIndex == 1) { 163318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com StringBuilder ret = new StringBuilder(origStr); 163418e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com ret = ret.append(dialStr.charAt(0)); 163518e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com retStr = ret.toString(); 163618e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } else { 163718e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // It means more than 1 P/W characters in the post dial string, 163818e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com // appends to retStr 163918e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com String nonDigitStr = dialStr.substring(0,dialableIndex); 164018e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com retStr = origStr.concat(nonDigitStr); 164118e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 164218e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com return retStr; 164318e7b98c1c7e3cf340e39e93be67b777e7036cc4Tang@Motorola.com } 16449a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 16459a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa //===== Begining of utility methods used in compareLoosely() ===== 16469a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 16479a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** 16489a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * Phone numbers are stored in "lookup" form in the database 16499a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * as reversed strings to allow for caller ID lookup 16509a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * 16519a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * This method takes a phone number and makes a valid SQL "LIKE" 16529a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * string that will match the lookup form 16539a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * 16549a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 16559a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** all of a up to len must be an international prefix or 16569a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * separators/non-dialing digits 16579a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 16589a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static boolean 16599a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa matchIntlPrefix(String a, int len) { 16609a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /* '([^0-9*#+pwn]\+[^0-9*#+pwn] | [^0-9*#+pwn]0(0|11)[^0-9*#+pwn] )$' */ 16619a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /* 0 1 2 3 45 */ 16629a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 16639a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int state = 0; 16649a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa for (int i = 0 ; i < len ; i++) { 16659a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa char c = a.charAt(i); 16669a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 16679a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa switch (state) { 16689a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 0: 16699a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (c == '+') state = 1; 16709a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (c == '0') state = 2; 16719a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (isNonSeparator(c)) return false; 16729a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 16739a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 16749a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 2: 16759a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (c == '0') state = 3; 16769a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (c == '1') state = 4; 16779a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (isNonSeparator(c)) return false; 16789a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 16799a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 16809a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 4: 16819a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (c == '1') state = 5; 16829a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (isNonSeparator(c)) return false; 16839a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 16849a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 16859a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa default: 16869a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (isNonSeparator(c)) return false; 16879a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 16889a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 16899a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 16909a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 16919a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 16929a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return state == 1 || state == 3 || state == 5; 16939a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 16949a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 16959a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** all of 'a' up to len must be a (+|00|011)country code) 16969a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * We're fast and loose with the country code. Any \d{1,3} matches */ 16979a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static boolean 16989a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa matchIntlPrefixAndCC(String a, int len) { 16999a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /* [^0-9*#+pwn]*(\+|0(0|11)\d\d?\d? [^0-9*#+pwn] $ */ 17009a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /* 0 1 2 3 45 6 7 8 */ 17019a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17029a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int state = 0; 17039a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa for (int i = 0 ; i < len ; i++ ) { 17049a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa char c = a.charAt(i); 17059a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17069a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa switch (state) { 17079a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 0: 17089a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (c == '+') state = 1; 17099a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (c == '0') state = 2; 17109a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (isNonSeparator(c)) return false; 17119a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 17129a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17139a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 2: 17149a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (c == '0') state = 3; 17159a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (c == '1') state = 4; 17169a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (isNonSeparator(c)) return false; 17179a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 17189a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17199a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 4: 17209a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (c == '1') state = 5; 17219a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (isNonSeparator(c)) return false; 17229a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 17239a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17249a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 1: 17259a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 3: 17269a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 5: 17279a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (isISODigit(c)) state = 6; 17289a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (isNonSeparator(c)) return false; 17299a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 17309a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17319a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 6: 17329a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 7: 17339a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (isISODigit(c)) state++; 17349a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (isNonSeparator(c)) return false; 17359a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 17369a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17379a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa default: 17389a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (isNonSeparator(c)) return false; 17399a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 17409a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 17419a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17429a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return state == 6 || state == 7 || state == 8; 17439a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 17449a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17459a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** all of 'a' up to len must match non-US trunk prefix ('0') */ 17469a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static boolean 17479a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa matchTrunkPrefix(String a, int len) { 17489a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa boolean found; 17499a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17509a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa found = false; 17519a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17529a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa for (int i = 0 ; i < len ; i++) { 17539a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa char c = a.charAt(i); 17549a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17559a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (c == '0' && !found) { 17569a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa found = true; 17579a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else if (isNonSeparator(c)) { 17589a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return false; 17599a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 17609a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 17619a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17629a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return found; 17639a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 17649a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17659a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa //===== End of utility methods used only in compareLoosely() ===== 17669a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17679a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa //===== Beggining of utility methods used only in compareStrictly() ==== 17689a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17699a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /* 17709a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * If true, the number is country calling code. 17719a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 17729a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static final boolean COUNTLY_CALLING_CALL[] = { 17739a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa true, true, false, false, false, false, false, true, false, false, 17749a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa false, false, false, false, false, false, false, false, false, false, 17759a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa true, false, false, false, false, false, false, true, true, false, 17769a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa true, true, true, true, true, false, true, false, false, true, 17779a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa true, false, false, true, true, true, true, true, true, true, 17789a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa false, true, true, true, true, true, true, true, true, false, 17799a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa true, true, true, true, true, true, true, false, false, false, 17809a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa false, false, false, false, false, false, false, false, false, false, 17819a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa false, true, true, true, true, false, true, false, false, true, 17829a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa true, true, true, true, true, true, false, false, true, false, 17839a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa }; 17849a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static final int CCC_LENGTH = COUNTLY_CALLING_CALL.length; 17859a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17869a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** 17879a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * @return true when input is valid Country Calling Code. 17889a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 17899a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static boolean isCountryCallingCode(int countryCallingCodeCandidate) { 17909a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return countryCallingCodeCandidate > 0 && countryCallingCodeCandidate < CCC_LENGTH && 17919a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa COUNTLY_CALLING_CALL[countryCallingCodeCandidate]; 17929a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 17939a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 17949a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** 17959a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * Returns interger corresponding to the input if input "ch" is 17969a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * ISO-LATIN characters 0-9. 17979a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * Returns -1 otherwise 17989a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 17999a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static int tryGetISODigit(char ch) { 18009a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if ('0' <= ch && ch <= '9') { 18019a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return ch - '0'; 18029a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 18039a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return -1; 18049a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18059a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18069a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 18079a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static class CountryCallingCodeAndNewIndex { 18089a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa public final int countryCallingCode; 18099a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa public final int newIndex; 18109a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa public CountryCallingCodeAndNewIndex(int countryCode, int newIndex) { 18119a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa this.countryCallingCode = countryCode; 18129a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa this.newIndex = newIndex; 18139a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18149a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18159a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 18169a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /* 18179a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * Note that this function does not strictly care the country calling code with 18189a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * 3 length (like Morocco: +212), assuming it is enough to use the first two 18199a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * digit to compare two phone numbers. 18209a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 18219a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static CountryCallingCodeAndNewIndex tryGetCountryCallingCodeAndNewIndex( 18229a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa String str, boolean acceptThailandCase) { 18239a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // Rough regexp: 18249a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // ^[^0-9*#+]*((\+|0(0|11)\d\d?|166) [^0-9*#+] $ 18259a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // 0 1 2 3 45 6 7 89 18269a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // 18279a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // In all the states, this function ignores separator characters. 18289a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // "166" is the special case for the call from Thailand to the US. Uguu! 18299a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int state = 0; 18309a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int ccc = 0; 18319a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa final int length = str.length(); 18329a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa for (int i = 0 ; i < length ; i++ ) { 18339a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa char ch = str.charAt(i); 18349a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa switch (state) { 18359a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 0: 18369a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (ch == '+') state = 1; 18379a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (ch == '0') state = 2; 18389a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (ch == '1') { 18399a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (acceptThailandCase) { 18409a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa state = 8; 18419a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 18429a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return null; 18439a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18449a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else if (isDialable(ch)) { 18459a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return null; 18469a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18479a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 18489a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 18499a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 2: 18509a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (ch == '0') state = 3; 18519a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (ch == '1') state = 4; 18529a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (isDialable(ch)) { 18539a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return null; 18549a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18559a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 18569a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 18579a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 4: 18589a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (ch == '1') state = 5; 18599a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (isDialable(ch)) { 18609a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return null; 18619a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18629a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 18639a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 18649a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 1: 18659a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 3: 18669a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 5: 18679a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 6: 18689a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 7: 18699a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa { 18709a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int ret = tryGetISODigit(ch); 18719a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (ret > 0) { 18729a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa ccc = ccc * 10 + ret; 18739a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (ccc >= 100 || isCountryCallingCode(ccc)) { 18749a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return new CountryCallingCodeAndNewIndex(ccc, i + 1); 18759a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18769a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (state == 1 || state == 3 || state == 5) { 18779a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa state = 6; 18789a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 18799a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa state++; 18809a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18819a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else if (isDialable(ch)) { 18829a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return null; 18839a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18849a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18859a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 18869a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 8: 18879a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (ch == '6') state = 9; 18889a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa else if (isDialable(ch)) { 18899a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return null; 18909a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18919a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa break; 18929a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa case 9: 18939a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (ch == '6') { 18949a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return new CountryCallingCodeAndNewIndex(66, i + 1); 18959a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 18969a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return null; 18979a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 18989a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa default: 18999a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return null; 19009a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 19019a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 19029a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 19039a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return null; 19049a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 19059a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 19069a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** 19079a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * Currently this function simply ignore the first digit assuming it is 19089a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * trunk prefix. Actually trunk prefix is different in each country. 19099a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * 19109a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * e.g. 19119a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * "+79161234567" equals "89161234567" (Russian trunk digit is 8) 19129a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * "+33123456789" equals "0123456789" (French trunk digit is 0) 19139a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * 19149a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 19159a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static int tryGetTrunkPrefixOmittedIndex(String str, int currentIndex) { 19169a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int length = str.length(); 19179a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa for (int i = currentIndex ; i < length ; i++) { 19189a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa final char ch = str.charAt(i); 19199a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (tryGetISODigit(ch) >= 0) { 19209a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return i + 1; 19219a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else if (isDialable(ch)) { 19229a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return -1; 19239a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 19249a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 19259a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return -1; 19269a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 19279a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 19289a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa /** 19299a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * Return true if the prefix of "str" is "ignorable". Here, "ignorable" means 19309a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * that "str" has only one digit and separater characters. The one digit is 19319a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa * assumed to be trunk prefix. 19329a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa */ 19339a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa private static boolean checkPrefixIsIgnorable(final String str, 19349a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa int forwardIndex, int backwardIndex) { 19359a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa boolean trunk_prefix_was_read = false; 19369a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa while (backwardIndex >= forwardIndex) { 19379a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (tryGetISODigit(str.charAt(backwardIndex)) >= 0) { 19389a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa if (trunk_prefix_was_read) { 19399a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // More than one digit appeared, meaning that "a" and "b" 19409a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // is different. 19419a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return false; 19429a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else { 19439a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // Ignore just one digit, assuming it is trunk prefix. 19449a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa trunk_prefix_was_read = true; 19459a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 19469a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } else if (isDialable(str.charAt(backwardIndex))) { 19479a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa // Trunk prefix is a digit, not "*", "#"... 19489a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return false; 19499a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 19509a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa backwardIndex--; 19519a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 19529a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 19539a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa return true; 19549a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa } 19559a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa 19569a24bc563f28d8489c7178b93ff05f02e8b8a893Daisuke Miyakawa //==== End of utility methods used only in compareStrictly() ===== 19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1958