Skip to content

Commit 1a81169

Browse files
author
David Brown
committed
Add "potential" variants for PhoneNumberUtils.isEmergencyNumber()
The phone app needs a way to distinguish between (a) numbers that are definitely emergency numbers, and (b) numbers that *might* result in an emergency call being dialed, but aren't specifically emergency numbers themselves. (The phone app needs this distinction in order to enforce the restriction that 3rd party apps should not be allowed to make emergency calls using the ACTION_CALL intent, while still making sure that the in-call UI only displays the "emergency call" state for numbers that are *definitely* emergency numbers. See bug 5493790 for the full details;) So this change adds a full set of "isPotentialEmergencyNumber()" methods to go along with the "isEmergencyNumber()" methods we've had all along. The "potential" variants behave identically to the original methods, *except* that they ultimately use number.startsWith() rather than number.equals() when comparing against the list of emergency numbers. TESTED: - Unit test 'PhoneNumberUtilsTest#testIsEmergencyNumber' passes. (The PhoneNumberUtilsTest class doesn't pass in its entirety, but it was broken before this change also.) - Also see the commit description of change Ib949fea3c0ce6b341a90e617a03ba3f22c69018b for the exact tests I ran against the phone app. This change should be submitted along with Change-Id: Ib949fea3c0ce6b341a90e617a03ba3f22c69018b in apps/Phone (but this change must go in first to avoid breaking the build.) Bug: 5493790 Change-Id: Ic528cfcc555734cdaf4ca8a18a50199771ba49b1
1 parent b445362 commit 1a81169

File tree

2 files changed

+244
-49
lines changed

2 files changed

+244
-49
lines changed

telephony/java/android/telephony/PhoneNumberUtils.java

Lines changed: 198 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,14 +1513,65 @@ public static String normalizeNumber(String phoneNumber) {
15131513
static final int MIN_MATCH = 7;
15141514

15151515
/**
1516-
* isEmergencyNumber: checks a given number against the list of
1517-
* emergency numbers provided by the RIL and SIM card.
1516+
* Checks a given number against the list of
1517+
* emergency numbers provided by the RIL and SIM card.
15181518
*
15191519
* @param number the number to look up.
1520-
* @return if the number is in the list of emergency numbers
1521-
* listed in the ril / sim, then return true, otherwise false.
1520+
* @return true if the number is in the list of emergency numbers
1521+
* listed in the RIL / SIM, otherwise return false.
15221522
*/
15231523
public static boolean isEmergencyNumber(String number) {
1524+
// Return true only if the specified number *exactly* matches
1525+
// one of the emergency numbers listed by the RIL / SIM.
1526+
return isEmergencyNumberInternal(number, true /* useExactMatch */);
1527+
}
1528+
1529+
/**
1530+
* Checks if given number might *potentially* result in
1531+
* a call to an emergency service on the current network.
1532+
*
1533+
* Specifically, this method will return true if the specified number
1534+
* is an emergency number according to the list managed by the RIL or
1535+
* SIM, *or* if the specified number simply starts with the same
1536+
* digits as any of the emergency numbers listed in the RIL / SIM.
1537+
*
1538+
* This method is intended for internal use by the phone app when
1539+
* deciding whether to allow ACTION_CALL intents from 3rd party apps
1540+
* (where we're required to *not* allow emergency calls to be placed.)
1541+
*
1542+
* @param number the number to look up.
1543+
* @return true if the number is in the list of emergency numbers
1544+
* listed in the RIL / SIM, *or* if the number starts with the
1545+
* same digits as any of those emergency numbers.
1546+
*
1547+
* @hide
1548+
*/
1549+
public static boolean isPotentialEmergencyNumber(String number) {
1550+
// Check against the emergency numbers listed by the RIL / SIM,
1551+
// and *don't* require an exact match.
1552+
return isEmergencyNumberInternal(number, false /* useExactMatch */);
1553+
}
1554+
1555+
/**
1556+
* Helper function for isEmergencyNumber(String) and
1557+
* isPotentialEmergencyNumber(String).
1558+
*
1559+
* @param number the number to look up.
1560+
*
1561+
* @param useExactMatch if true, consider a number to be an emergency
1562+
* number only if it *exactly* matches a number listed in
1563+
* the RIL / SIM. If false, a number is considered to be an
1564+
* emergency number if it simply starts with the same digits
1565+
* as any of the emergency numbers listed in the RIL / SIM.
1566+
* (Setting useExactMatch to false allows you to identify
1567+
* number that could *potentially* result in emergency calls
1568+
* since many networks will actually ignore trailing digits
1569+
* after a valid emergency number.)
1570+
*
1571+
* @return true if the number is in the list of emergency numbers
1572+
* listed in the RIL / sim, otherwise return false.
1573+
*/
1574+
private static boolean isEmergencyNumberInternal(String number, boolean useExactMatch) {
15241575
// If the number passed in is null, just return false:
15251576
if (number == null) return false;
15261577

@@ -1540,16 +1591,26 @@ public static boolean isEmergencyNumber(String number) {
15401591
// searches through the comma-separated list for a match,
15411592
// return true if one is found.
15421593
for (String emergencyNum : numbers.split(",")) {
1543-
if (number.startsWith(emergencyNum)) {
1544-
return true;
1594+
if (useExactMatch) {
1595+
if (number.equals(emergencyNum)) {
1596+
return true;
1597+
}
1598+
} else {
1599+
if (number.startsWith(emergencyNum)) {
1600+
return true;
1601+
}
15451602
}
15461603
}
15471604
// no matches found against the list!
15481605
return false;
15491606
}
15501607

1551-
//no ecclist system property, so use our own list.
1552-
return (number.startsWith("112") || number.startsWith("911"));
1608+
// No ecclist system property, so use our own list.
1609+
if (useExactMatch) {
1610+
return (number.equals("112") || number.equals("911"));
1611+
} else {
1612+
return (number.startsWith("112") || number.startsWith("911"));
1613+
}
15531614
}
15541615

15551616
/**
@@ -1559,31 +1620,81 @@ public static boolean isEmergencyNumber(String number) {
15591620
* @param defaultCountryIso the specific country which the number should be checked against
15601621
* @return if the number is an emergency number for the specific country, then return true,
15611622
* otherwise false
1623+
*
15621624
* @hide
15631625
*/
15641626
public static boolean isEmergencyNumber(String number, String defaultCountryIso) {
1565-
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
1566-
try {
1567-
PhoneNumber pn = util.parse(number, defaultCountryIso);
1568-
// libphonenumber guarantees short numbers such as emergency numbers are classified as
1569-
// invalid. Therefore, if the number passes the validation test, we believe it is not an
1570-
// emergency number.
1571-
// TODO: Compare against a list of country-specific known emergency numbers instead, once
1572-
// that has been collected.
1573-
if (util.isValidNumber(pn)) {
1574-
return false;
1575-
} else if ("BR".equalsIgnoreCase(defaultCountryIso) && number.length() >= 8) {
1576-
// This is to prevent Brazilian local numbers which start with 911 being incorrectly
1577-
// classified as emergency numbers. 911 is not an emergency number in Brazil; it is also
1578-
// not possible to append additional digits to an emergency number to dial the number in
1579-
// Brazil - it won't connect.
1580-
// TODO: Clean this up once a list of country-specific known emergency numbers is
1581-
// collected.
1582-
return false;
1583-
}
1584-
} catch (NumberParseException e) {
1585-
}
1586-
return isEmergencyNumber(number);
1627+
return isEmergencyNumberInternal(number,
1628+
defaultCountryIso,
1629+
true /* useExactMatch */);
1630+
}
1631+
1632+
/**
1633+
* Checks if a given number might *potentially* result in a call to an
1634+
* emergency service, for a specific country.
1635+
*
1636+
* Specifically, this method will return true if the specified number
1637+
* is an emergency number in the specified country, *or* if the number
1638+
* simply starts with the same digits as any emergency number for that
1639+
* country.
1640+
*
1641+
* This method is intended for internal use by the phone app when
1642+
* deciding whether to allow ACTION_CALL intents from 3rd party apps
1643+
* (where we're required to *not* allow emergency calls to be placed.)
1644+
*
1645+
* @param number the number to look up.
1646+
* @param defaultCountryIso the specific country which the number should be checked against
1647+
* @return true if the number is an emergency number for the specific
1648+
* country, *or* if the number starts with the same digits as
1649+
* any of those emergency numbers.
1650+
*
1651+
* @hide
1652+
*/
1653+
public static boolean isPotentialEmergencyNumber(String number, String defaultCountryIso) {
1654+
return isEmergencyNumberInternal(number,
1655+
defaultCountryIso,
1656+
false /* useExactMatch */);
1657+
}
1658+
1659+
/**
1660+
* Helper function for isEmergencyNumber(String, String) and
1661+
* isPotentialEmergencyNumber(String, String).
1662+
*
1663+
* @param number the number to look up.
1664+
* @param defaultCountryIso the specific country which the number should be checked against
1665+
* @param useExactMatch if true, consider a number to be an emergency
1666+
* number only if it *exactly* matches a number listed in
1667+
* the RIL / SIM. If false, a number is considered to be an
1668+
* emergency number if it simply starts with the same digits
1669+
* as any of the emergency numbers listed in the RIL / SIM.
1670+
*
1671+
* @return true if the number is an emergency number for the specified country.
1672+
*/
1673+
private static boolean isEmergencyNumberInternal(String number,
1674+
String defaultCountryIso,
1675+
boolean useExactMatch) {
1676+
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
1677+
try {
1678+
PhoneNumber pn = util.parse(number, defaultCountryIso);
1679+
// libphonenumber guarantees short numbers such as emergency numbers are classified as
1680+
// invalid. Therefore, if the number passes the validation test, we believe it is not an
1681+
// emergency number.
1682+
// TODO: Compare against a list of country-specific known emergency numbers instead, once
1683+
// that has been collected.
1684+
if (util.isValidNumber(pn)) {
1685+
return false;
1686+
} else if ("BR".equalsIgnoreCase(defaultCountryIso) && number.length() >= 8) {
1687+
// This is to prevent Brazilian local numbers which start with 911 being incorrectly
1688+
// classified as emergency numbers. 911 is not an emergency number in Brazil; it is also
1689+
// not possible to append additional digits to an emergency number to dial the number in
1690+
// Brazil - it won't connect.
1691+
// TODO: Clean this up once a list of country-specific known emergency numbers is
1692+
// collected.
1693+
return false;
1694+
}
1695+
} catch (NumberParseException e) {
1696+
}
1697+
return isEmergencyNumberInternal(number, useExactMatch);
15871698
}
15881699

15891700
/**
@@ -1592,12 +1703,66 @@ public static boolean isEmergencyNumber(String number, String defaultCountryIso)
15921703
*
15931704
* @param number the number to look up.
15941705
* @param context the specific context which the number should be checked against
1595-
* @return if a phone number is an emergency number for a local country, based on the
1596-
* CountryDetector.
1706+
* @return true if the specified number is an emergency number for a local country, based on the
1707+
* CountryDetector.
1708+
*
15971709
* @see android.location.CountryDetector
15981710
* @hide
15991711
*/
16001712
public static boolean isLocalEmergencyNumber(String number, Context context) {
1713+
return isLocalEmergencyNumberInternal(number,
1714+
context,
1715+
true /* useExactMatch */);
1716+
}
1717+
1718+
/**
1719+
* Checks if a given number might *potentially* result in a call to an
1720+
* emergency service, for the country that the user is in. The current
1721+
* country is determined using the CountryDetector.
1722+
*
1723+
* Specifically, this method will return true if the specified number
1724+
* is an emergency number in the current country, *or* if the number
1725+
* simply starts with the same digits as any emergency number for the
1726+
* current country.
1727+
*
1728+
* This method is intended for internal use by the phone app when
1729+
* deciding whether to allow ACTION_CALL intents from 3rd party apps
1730+
* (where we're required to *not* allow emergency calls to be placed.)
1731+
*
1732+
* @param number the number to look up.
1733+
* @param context the specific context which the number should be checked against
1734+
* @return true if the specified number is an emergency number for a local country, based on the
1735+
* CountryDetector.
1736+
*
1737+
* @see android.location.CountryDetector
1738+
* @hide
1739+
*/
1740+
public static boolean isPotentialLocalEmergencyNumber(String number, Context context) {
1741+
return isLocalEmergencyNumberInternal(number,
1742+
context,
1743+
false /* useExactMatch */);
1744+
}
1745+
1746+
/**
1747+
* Helper function for isLocalEmergencyNumber() and
1748+
* isPotentialLocalEmergencyNumber().
1749+
*
1750+
* @param number the number to look up.
1751+
* @param context the specific context which the number should be checked against
1752+
* @param useExactMatch if true, consider a number to be an emergency
1753+
* number only if it *exactly* matches a number listed in
1754+
* the RIL / SIM. If false, a number is considered to be an
1755+
* emergency number if it simply starts with the same digits
1756+
* as any of the emergency numbers listed in the RIL / SIM.
1757+
*
1758+
* @return true if the specified number is an emergency number for a
1759+
* local country, based on the CountryDetector.
1760+
*
1761+
* @see android.location.CountryDetector
1762+
*/
1763+
private static boolean isLocalEmergencyNumberInternal(String number,
1764+
Context context,
1765+
boolean useExactMatch) {
16011766
String countryIso;
16021767
CountryDetector detector = (CountryDetector) context.getSystemService(
16031768
Context.COUNTRY_DETECTOR);
@@ -1609,7 +1774,7 @@ public static boolean isLocalEmergencyNumber(String number, Context context) {
16091774
Log.w(LOG_TAG, "No CountryDetector; falling back to countryIso based on locale: "
16101775
+ countryIso);
16111776
}
1612-
return isEmergencyNumber(number, countryIso);
1777+
return isEmergencyNumberInternal(number, countryIso, useExactMatch);
16131778
}
16141779

16151780
/**

telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -550,21 +550,51 @@ public void testFormatDailabeNumber() {
550550
}
551551
@SmallTest
552552
public void testIsEmergencyNumber() {
553-
assertTrue(PhoneNumberUtils.isEmergencyNumber("911", "US"));
554-
assertTrue(PhoneNumberUtils.isEmergencyNumber("112", "US"));
555-
// The next two numbers are not valid phone numbers in the US, but can be used to trick the
556-
// system to dial 911 and 112, which are emergency numbers in the US. For the purpose of
557-
// addressing that, they are also classified as emergency numbers in the US.
558-
assertTrue(PhoneNumberUtils.isEmergencyNumber("91112345", "US"));
559-
assertTrue(PhoneNumberUtils.isEmergencyNumber("11212345", "US"));
560-
// A valid mobile phone number from Singapore shouldn't be classified as an emergency number
561-
// in Singapore, as 911 is not an emergency number there.
562-
assertFalse(PhoneNumberUtils.isEmergencyNumber("91121234", "SG"));
563-
// A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number
564-
// in Brazil, as 112 is not an emergency number there.
565-
assertFalse(PhoneNumberUtils.isEmergencyNumber("1121234567", "BR"));
566-
// A valid local phone number from Brazil shouldn't be classified as an emergency number in
567-
// Brazil.
568-
assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "BR"));
553+
// There are two parallel sets of tests here: one for the
554+
// regular isEmergencyNumber() method, and the other for
555+
// isPotentialEmergencyNumber().
556+
//
557+
// (The difference is that isEmergencyNumber() will return true
558+
// only if the specified number exactly matches an actual
559+
// emergency number, but isPotentialEmergencyNumber() will
560+
// return true if the specified number simply starts with the
561+
// same digits as any actual emergency number.)
562+
563+
// Tests for isEmergencyNumber():
564+
assertTrue(PhoneNumberUtils.isEmergencyNumber("911", "US"));
565+
assertTrue(PhoneNumberUtils.isEmergencyNumber("112", "US"));
566+
// The next two numbers are not valid phone numbers in the US,
567+
// so do not count as emergency numbers (but they *are* "potential"
568+
// emergency numbers; see below.)
569+
assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "US"));
570+
assertFalse(PhoneNumberUtils.isEmergencyNumber("11212345", "US"));
571+
// A valid mobile phone number from Singapore shouldn't be classified as an emergency number
572+
// in Singapore, as 911 is not an emergency number there.
573+
assertFalse(PhoneNumberUtils.isEmergencyNumber("91121234", "SG"));
574+
// A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number
575+
// in Brazil, as 112 is not an emergency number there.
576+
assertFalse(PhoneNumberUtils.isEmergencyNumber("1121234567", "BR"));
577+
// A valid local phone number from Brazil shouldn't be classified as an emergency number in
578+
// Brazil.
579+
assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "BR"));
580+
581+
// Tests for isPotentialEmergencyNumber():
582+
// These first two are obviously emergency numbers:
583+
assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("911", "US"));
584+
assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("112", "US"));
585+
// The next two numbers are not valid phone numbers in the US, but can be used to trick the
586+
// system to dial 911 and 112, which are emergency numbers in the US. For the purpose of
587+
// addressing that, they are also classified as "potential" emergency numbers in the US.
588+
assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("91112345", "US"));
589+
assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("11212345", "US"));
590+
// A valid mobile phone number from Singapore shouldn't be classified as an emergency number
591+
// in Singapore, as 911 is not an emergency number there.
592+
assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("91121234", "SG"));
593+
// A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number
594+
// in Brazil, as 112 is not an emergency number there.
595+
assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("1121234567", "BR"));
596+
// A valid local phone number from Brazil shouldn't be classified as an emergency number in
597+
// Brazil.
598+
assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("91112345", "BR"));
569599
}
570600
}

0 commit comments

Comments
 (0)