384 lines
12 KiB
Java
384 lines
12 KiB
Java
/*
|
|
* 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.
|
|
*
|
|
* Note: mContext must be set via setContext() before calling this method.
|
|
*
|
|
* @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;
|
|
}
|
|
|
|
boolean isEmergencyNumber;
|
|
if (mContext == null) {
|
|
Log.e(TAG, "context is unexpectedly null to provide emergency identification service");
|
|
isEmergencyNumber = false;
|
|
} else {
|
|
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
|
|
isEmergencyNumber = tm.isEmergencyNumber(number);
|
|
}
|
|
|
|
if (isEmergencyNumber) {
|
|
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;
|
|
}
|
|
}
|
|
|