diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 51922da2b4f77..e898aac4ff90b 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -1546,6 +1546,32 @@ public class PhoneNumberUtils return (number.startsWith("112") || number.startsWith("911")); } + /** + * Checks if a given number is an emergency number for a specific country. + * + * @param number the number to look up. + * @param defaultCountryIso the specific country which the number should be checked against + * @return if the number is an emergency number for the specific country, then return true, + * otherwise false + * @hide + */ + public static boolean isEmergencyNumber(String number, String defaultCountryIso) { + PhoneNumberUtil util = PhoneNumberUtil.getInstance(); + try { + PhoneNumber pn = util.parse(number, defaultCountryIso); + // libphonenumber guarantees short numbers such as emergency numbers are classified as + // invalid. Therefore, if the number passes the validation test, we believe it is not an + // emergency number. + // TODO: Compare against a list of country-specific known emergency numbers instead, once + // that has been collected. + if (util.isValidNumber(pn)) { + return false; + } + } catch (NumberParseException e) { + } + return isEmergencyNumber(number); + } + /** * isVoiceMailNumber: checks a given number against the voicemail * number provided by the RIL and SIM card. The caller must have diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index 25f8c8b18e3fb..7c37a65380a4d 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -254,7 +254,9 @@ public class CallerInfo { // Change the callerInfo number ONLY if it is an emergency number // or if it is the voicemail number. If it is either, take a // shortcut and skip the query. - if (PhoneNumberUtils.isEmergencyNumber(number)) { + Locale locale = context.getResources().getConfiguration().locale; + String countryIso = getCurrentCountryIso(context, locale); + if (PhoneNumberUtils.isEmergencyNumber(number, countryIso)) { return new CallerInfo().markAsEmergency(context); } else if (PhoneNumberUtils.isVoiceMailNumber(number)) { return new CallerInfo().markAsVoiceMail(); @@ -514,18 +516,8 @@ public class CallerInfo { PhoneNumberUtil util = PhoneNumberUtil.getInstance(); PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance(); - String countryIso; Locale locale = context.getResources().getConfiguration().locale; - CountryDetector detector = (CountryDetector) context.getSystemService( - Context.COUNTRY_DETECTOR); - if (detector != null) { - countryIso = detector.detectCountry().getCountryIso(); - } else { - countryIso = locale.getCountry(); - Log.w(TAG, "No CountryDetector; falling back to countryIso based on locale: " - + countryIso); - } - + String countryIso = getCurrentCountryIso(context, locale); PhoneNumber pn = null; try { if (VDBG) Log.v(TAG, "parsing '" + number @@ -545,6 +537,24 @@ public class CallerInfo { } } + /** + * @return The ISO 3166-1 two letters country code of the country the user + * is in. + */ + private static String getCurrentCountryIso(Context context, Locale locale) { + String countryIso; + CountryDetector detector = (CountryDetector) context.getSystemService( + Context.COUNTRY_DETECTOR); + if (detector != null) { + countryIso = detector.detectCountry().getCountryIso(); + } else { + countryIso = locale.getCountry(); + Log.w(TAG, "No CountryDetector; falling back to countryIso based on locale: " + + countryIso); + } + return countryIso; + } + /** * @return a string debug representation of this instance. */ diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index 2e8a7421b4d71..17734cac72c26 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -403,7 +403,9 @@ public class CallerInfoAsyncQuery { cw.number = number; // check to see if these are recognized numbers, and use shortcuts if we can. - if (PhoneNumberUtils.isEmergencyNumber(number)) { + CountryDetector detector = (CountryDetector) context.getSystemService( + Context.COUNTRY_DETECTOR); + if (PhoneNumberUtils.isEmergencyNumber(number, detector.detectCountry().getCountryIso())) { cw.event = EVENT_EMERGENCY_NUMBER; } else if (PhoneNumberUtils.isVoiceMailNumber(number)) { cw.event = EVENT_VOICEMAIL_NUMBER; diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java index 6e9d0f9da62de..d3e4b78fde9d2 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java @@ -536,4 +536,20 @@ public class PhoneNumberUtilsTest extends AndroidTestCase { // The given number was formatted. assertEquals("650-291-0000", PhoneNumberUtils.formatNumber("650-291-0000", null, "US")); } + @SmallTest + public void testIsEmergencyNumber() { + assertTrue(PhoneNumberUtils.isEmergencyNumber("911", "US")); + assertTrue(PhoneNumberUtils.isEmergencyNumber("112", "US")); + // The next two numbers are not valid phone numbers in the US, but can be used to trick the + // system to dial 911 and 112, which are emergency numbers in the US. For the purpose of + // addressing that, they are also classified as emergency numbers in the US. + assertTrue(PhoneNumberUtils.isEmergencyNumber("91112345", "US")); + assertTrue(PhoneNumberUtils.isEmergencyNumber("11212345", "US")); + // A valid mobile phone number from Singapore shouldn't be classified as an emergency number + // in Singapore, as 911 is not an emergency number there. + assertFalse(PhoneNumberUtils.isEmergencyNumber("91121234", "SG")); + // A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number + // in Brazil, as 112 is not an emergency number there. + assertFalse(PhoneNumberUtils.isEmergencyNumber("1121234567", "BR")); + } }