blob: 1ed03f9cd4ffe69b72b5244b25065b8f5ee44220 [file] [log] [blame]
/*
* 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<String> 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<String> 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<String> sExcludes = null;
private boolean isInExcludedList(String number){
if (sExcludes == null) {
sExcludes = new ArrayList<String>();
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;
}
}