/* * Copyright (c) 2015, Motorola Mobility LLC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of Motorola Mobility nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package com.android.ims.internal; import android.content.Context; import android.os.Build; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; import java.util.List; import java.util.ArrayList; /** * @hide */ public class ContactNumberUtils { /** * Sample code: * * ContactNumberUtils mNumberUtils = ContactNumberUtils.getDefault(); * mNumberUtils.setContext(this); * * number = mNumberUtils.format(number); * int result = mNumberUtils.validate(number); * if (ContactNumberUtils.NUMBER_VALID == result) { * } */ public static ContactNumberUtils getDefault() { if(sInstance == null) { sInstance = new ContactNumberUtils(); } return sInstance; } public void setContext(Context context) { mContext = context; } /** * Format contact number to the common format * * @param phoneNumber read from contact db. * @return formatted contact number. */ public String format(final String phoneNumber) { String number = phoneNumber; if (TextUtils.isEmpty(number)) { return null; } if(number.startsWith("*67") || number.startsWith("*82")) { number = number.substring(3); if (TextUtils.isEmpty(number)) { return null; } } number = PhoneNumberUtils.stripSeparators(number); int len = number.length(); if (len == NUMBER_LENGTH_NO_AREA_CODE) { number = addAreaCode(number); } number = PhoneNumberUtils.normalizeNumber(number); len = number.length(); if (len == NUMBER_LENGTH_NORMAL) { if (!number.startsWith("+1")) { number = "+1" + number; } } else if (len == NUMBER_LENGTH_NORMAL + 1) { if (number.startsWith("1")) { number = "+" + number; } } else if(len >= NUMBER_LENGTH_NORMAL + 2) { if ((len >= NUMBER_LENGTH_NORMAL + 4) && (number.startsWith("011"))) { number = "+" + number.substring(3); } if (!number.startsWith("+")) { if (number.startsWith("1")) { number = "+" + number;; } else { number = "+1" + number; } } } if(number.length() > NUMBER_LENGTH_MAX) { return null; } return number; } /** * Contact nubmer error code. */ public static int NUMBER_VALID = 0; public static int NUMBER_EMERGENCY = 1; public static int NUMBER_SHORT_CODE = 2; public static int NUMBER_PRELOADED_ENTRY = 3; public static int NUMBER_FREE_PHONE = 4; public static int NUMBER_INVALID = 5; /** * Check if it is a valid contact number for presence * * @param phoneNumber read from contact db. * @return contact number error code. */ public int validate(final String phoneNumber) { String number = phoneNumber; if (TextUtils.isEmpty(number)) { return NUMBER_INVALID; } if(number.startsWith("*67") || number.startsWith("*82")) { number = number.substring(3); if (TextUtils.isEmpty(number)) { return NUMBER_INVALID; } } if(number.contains("*")) { return NUMBER_PRELOADED_ENTRY; } number = PhoneNumberUtils.stripSeparators(number); if (!number.equals(PhoneNumberUtils.convertKeypadLettersToDigits(number))) { return NUMBER_INVALID; } if (PhoneNumberUtils.isEmergencyNumber(number)) { return NUMBER_EMERGENCY; // TODO: To handle short code //} else if ((mContext != null) && PhoneNumberUtils.isN11Number(mContext, number)) { // return NUMBER_SHORT_CODE; } else if (number.startsWith("#")) { return NUMBER_PRELOADED_ENTRY; } else if (isInExcludedList(number)) { return NUMBER_FREE_PHONE; } int len = number.length(); if (len < NUMBER_LENGTH_NORMAL) { return NUMBER_INVALID; } number = format(number); if (number.startsWith("+")) { len = number.length(); // make sure the number after stripped the national number still be 10 digits if (len >= NUMBER_LENGTH_NORMAL + 2) { return NUMBER_VALID; } } return NUMBER_INVALID; } /** * Some utility functions for presence service only. * @hide */ public String[] format(List numbers) { if ((numbers == null) || (numbers.size() == 0)) { return null; } int size = numbers.size(); String[] outContactsArray = new String[size]; for (int i = 0; i < size; i++) { String number = numbers.get(i); outContactsArray[i] = format(number); if (DEBUG) { Log.d(TAG, "outContactsArray[" + i + "] = " + outContactsArray[i]); } } return outContactsArray; } public String[] format(String[] numbers) { if ((numbers == null) || (numbers.length == 0)) { return null; } int length = numbers.length; String[] outContactsArray = new String[length]; for (int i = 0; i < length; i++) { String number = numbers[i]; outContactsArray[i] = format(number); if (DEBUG) { Log.d(TAG, "outContactsArray[" + i + "] = " + outContactsArray[i]); } } return outContactsArray; } public int validate(List numbers) { if ((numbers == null) || (numbers.size() == 0)) { return NUMBER_INVALID; } int size = numbers.size(); for (int i = 0; i < size; i++) { String number = numbers.get(i); int result = validate(number); if (result != NUMBER_VALID) { return result; } } return NUMBER_VALID; } public int validate(String[] numbers) { if ((numbers == null) || (numbers.length == 0)) { return NUMBER_INVALID; } int length = numbers.length; for (int i = 0; i < length; i++) { String number = numbers[i]; int result = validate(number); if (result != NUMBER_VALID) { return result; } } return NUMBER_VALID; } /** * The logger related. */ private static final boolean DEBUG = Build.IS_DEBUGGABLE; private static final String TAG = "ContactNumberUtils"; /** * Contact number length. */ // As per E164 the maximum number length should be 15. // But as per implemention of libphonenumber it found longer length in Germany. // So we use the same length as libphonenumber. private int NUMBER_LENGTH_MAX = 17; private int NUMBER_LENGTH_NORMAL = 10; private int NUMBER_LENGTH_NO_AREA_CODE = 7; /** * Save the singleton instance. */ private static ContactNumberUtils sInstance = null; private Context mContext = null; /** * Constructor */ private ContactNumberUtils() { if (DEBUG) { Log.d(TAG, "ContactNumberUtils constructor"); } } /** * Add device's own area code to the number which length is 7. */ private String addAreaCode(String number) { if (mContext == null) { if (DEBUG) { Log.e(TAG, "mContext is null, please update context."); } return number; } String mdn = null; TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); mdn = tm.getLine1Number(); if ((mdn == null) || (mdn.length() == 0) || mdn.startsWith("00000")) { return number; } mdn = PhoneNumberUtils.stripSeparators(mdn); if (mdn.length() >= NUMBER_LENGTH_NORMAL) { mdn = mdn.substring(mdn.length() - NUMBER_LENGTH_NORMAL); } mdn = mdn.substring(0, 3); number = mdn + number; return number; } /** * The excluded number list. */ private static ArrayList sExcludes = null; private boolean isInExcludedList(String number){ if (sExcludes == null) { sExcludes = new ArrayList(); sExcludes.add("800"); sExcludes.add("822"); sExcludes.add("833"); sExcludes.add("844"); sExcludes.add("855"); sExcludes.add("866"); sExcludes.add("877"); sExcludes.add("880882"); sExcludes.add("888"); sExcludes.add("900"); sExcludes.add("911"); } String tempNumber = format(number); if(TextUtils.isEmpty(tempNumber)) { return true; //exclude empty/null string. } if(tempNumber.startsWith("1")) { tempNumber = tempNumber.substring(1); } else if(tempNumber.startsWith("+1")) { tempNumber = tempNumber.substring(2); } if(TextUtils.isEmpty(tempNumber)) { return true; //exclude empty/null string. } for (String num : sExcludes) { if(tempNumber.startsWith(num)) { return true; } } return false; } }