Merge "EmergencyNumber enhancement"
am: b158b12cbb
Change-Id: I3493e759d2c5b582b54e6145d0aa8767501f1528
This commit is contained in:
@@ -42609,10 +42609,10 @@ package android.telephony {
|
||||
method public static java.lang.String getStrippedReversed(java.lang.String);
|
||||
method public static final boolean is12Key(char);
|
||||
method public static final boolean isDialable(char);
|
||||
method public static boolean isEmergencyNumber(java.lang.String);
|
||||
method public static deprecated boolean isEmergencyNumber(java.lang.String);
|
||||
method public static boolean isGlobalPhoneNumber(java.lang.String);
|
||||
method public static boolean isISODigit(char);
|
||||
method public static boolean isLocalEmergencyNumber(android.content.Context, java.lang.String);
|
||||
method public static deprecated boolean isLocalEmergencyNumber(android.content.Context, java.lang.String);
|
||||
method public static final boolean isNonSeparator(char);
|
||||
method public static final boolean isReallyDialable(char);
|
||||
method public static final boolean isStartsPostDial(char);
|
||||
@@ -43328,11 +43328,13 @@ package android.telephony.emergency {
|
||||
method public java.util.List<java.lang.Integer> getEmergencyNumberSources();
|
||||
method public java.util.List<java.lang.Integer> getEmergencyServiceCategories();
|
||||
method public int getEmergencyServiceCategoryBitmask();
|
||||
method public java.lang.String getMnc();
|
||||
method public java.lang.String getNumber();
|
||||
method public boolean isFromSources(int);
|
||||
method public boolean isInEmergencyServiceCategories(int);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.telephony.emergency.EmergencyNumber> CREATOR;
|
||||
field public static final int EMERGENCY_NUMBER_SOURCE_DATABASE = 16; // 0x10
|
||||
field public static final int EMERGENCY_NUMBER_SOURCE_DEFAULT = 8; // 0x8
|
||||
field public static final int EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG = 4; // 0x4
|
||||
field public static final int EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING = 1; // 0x1
|
||||
|
||||
@@ -5470,6 +5470,7 @@ package android.telephony {
|
||||
method public int getVoiceActivationState();
|
||||
method public boolean handlePinMmi(java.lang.String);
|
||||
method public boolean handlePinMmiForSubscriber(int, java.lang.String);
|
||||
method public boolean isCurrentPotentialEmergencyNumber(java.lang.String);
|
||||
method public boolean isDataConnectivityPossible();
|
||||
method public deprecated boolean isIdle();
|
||||
method public deprecated boolean isOffhook();
|
||||
|
||||
@@ -67,7 +67,9 @@ import com.android.server.am.BatteryStatsService;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
@@ -196,6 +198,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
|
||||
private ArrayList<List<PhysicalChannelConfig>> mPhysicalChannelConfigs;
|
||||
|
||||
private Map<Integer, List<EmergencyNumber>> mEmergencyNumberList;
|
||||
|
||||
private int[] mSrvccState;
|
||||
|
||||
private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
@@ -233,8 +237,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
| PhoneStateListener.LISTEN_CELL_INFO;
|
||||
|
||||
static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
|
||||
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
|
||||
PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
|
||||
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
|
||||
| PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
|
||||
| PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST;
|
||||
|
||||
static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
|
||||
PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
|
||||
@@ -361,6 +366,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
mCellInfo = new ArrayList<List<CellInfo>>();
|
||||
mSrvccState = new int[numPhones];
|
||||
mPhysicalChannelConfigs = new ArrayList<List<PhysicalChannelConfig>>();
|
||||
mEmergencyNumberList = new HashMap<>();
|
||||
for (int i = 0; i < numPhones; i++) {
|
||||
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
|
||||
mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
|
||||
@@ -764,6 +770,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
remove(r.binder);
|
||||
}
|
||||
}
|
||||
if ((events & PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) != 0) {
|
||||
try {
|
||||
r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
|
||||
} catch (RemoteException ex) {
|
||||
remove(r.binder);
|
||||
}
|
||||
}
|
||||
if ((events & PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE) != 0) {
|
||||
try {
|
||||
r.callback.onPhoneCapabilityChanged(mPhoneCapability);
|
||||
@@ -1677,10 +1690,30 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
|
||||
|
||||
@Override
|
||||
public void notifyEmergencyNumberList(List<EmergencyNumber> emergencyNumberList) {
|
||||
// TODO checkPermission, modify Listener constent documentation
|
||||
// TODO implement multisim emergency number list update in listener
|
||||
// TODO implement PhoneStateListenerTest
|
||||
public void notifyEmergencyNumberList() {
|
||||
if (!checkNotifyPermission("notifyEmergencyNumberList()")) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (mRecords) {
|
||||
mEmergencyNumberList = TelephonyManager.getDefault().getCurrentEmergencyNumberList();
|
||||
|
||||
for (Record r : mRecords) {
|
||||
if (r.matchPhoneStateListenerEvent(
|
||||
PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST)) {
|
||||
try {
|
||||
r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
|
||||
if (VDBG) {
|
||||
log("notifyEmergencyNumberList: emergencyNumberList= "
|
||||
+ mEmergencyNumberList);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
mRemoveList.add(r.binder);
|
||||
}
|
||||
}
|
||||
}
|
||||
handleRemoveListLocked();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1724,6 +1757,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
pw.println("mPhoneCapability=" + mPhoneCapability);
|
||||
pw.println("mPreferredDataSubId=" + mPreferredDataSubId);
|
||||
pw.println("mRadioPowerState=" + mRadioPowerState);
|
||||
pw.println("mEmergencyNumberList=" + mEmergencyNumberList);
|
||||
|
||||
pw.decreaseIndent();
|
||||
|
||||
|
||||
@@ -1738,7 +1738,10 @@ public class PhoneNumberUtils {
|
||||
* @param number the number to look up.
|
||||
* @return true if the number is in the list of emergency numbers
|
||||
* listed in the RIL / SIM, otherwise return false.
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isEmergencyNumber(String number) {
|
||||
return isEmergencyNumber(getDefaultVoiceSubId(), number);
|
||||
}
|
||||
@@ -1751,8 +1754,13 @@ public class PhoneNumberUtils {
|
||||
* @param number the number to look up.
|
||||
* @return true if the number is in the list of emergency numbers
|
||||
* listed in the RIL / SIM, otherwise return false.
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)}
|
||||
* instead.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
@UnsupportedAppUsage
|
||||
public static boolean isEmergencyNumber(int subId, String number) {
|
||||
// Return true only if the specified number *exactly* matches
|
||||
@@ -1778,8 +1786,12 @@ public class PhoneNumberUtils {
|
||||
* listed in the RIL / SIM, *or* if the number starts with the
|
||||
* same digits as any of those emergency numbers.
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
|
||||
* instead.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isPotentialEmergencyNumber(String number) {
|
||||
return isPotentialEmergencyNumber(getDefaultVoiceSubId(), number);
|
||||
}
|
||||
@@ -1802,9 +1814,14 @@ public class PhoneNumberUtils {
|
||||
* @return true if the number is in the list of emergency numbers
|
||||
* listed in the RIL / SIM, *or* if the number starts with the
|
||||
* same digits as any of those emergency numbers.
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
|
||||
* instead.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
@Deprecated
|
||||
public static boolean isPotentialEmergencyNumber(int subId, String number) {
|
||||
// Check against the emergency numbers listed by the RIL / SIM,
|
||||
// and *don't* require an exact match.
|
||||
@@ -1867,8 +1884,12 @@ public class PhoneNumberUtils {
|
||||
* @return if the number is an emergency number for the specific country, then return true,
|
||||
* otherwise false
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)}
|
||||
* instead.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
@UnsupportedAppUsage
|
||||
public static boolean isEmergencyNumber(String number, String defaultCountryIso) {
|
||||
return isEmergencyNumber(getDefaultVoiceSubId(), number, defaultCountryIso);
|
||||
@@ -1882,8 +1903,13 @@ public class PhoneNumberUtils {
|
||||
* @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
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)}
|
||||
* instead.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isEmergencyNumber(int subId, String number, String defaultCountryIso) {
|
||||
return isEmergencyNumberInternal(subId, number,
|
||||
defaultCountryIso,
|
||||
@@ -1909,8 +1935,12 @@ public class PhoneNumberUtils {
|
||||
* country, *or* if the number starts with the same digits as
|
||||
* any of those emergency numbers.
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
|
||||
* instead.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isPotentialEmergencyNumber(String number, String defaultCountryIso) {
|
||||
return isPotentialEmergencyNumber(getDefaultVoiceSubId(), number, defaultCountryIso);
|
||||
}
|
||||
@@ -1934,8 +1964,13 @@ public class PhoneNumberUtils {
|
||||
* @return true if the number is an emergency number for the specific
|
||||
* country, *or* if the number starts with the same digits as
|
||||
* any of those emergency numbers.
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
|
||||
* instead.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isPotentialEmergencyNumber(int subId, String number,
|
||||
String defaultCountryIso) {
|
||||
return isEmergencyNumberInternal(subId, number,
|
||||
@@ -1983,92 +2018,7 @@ public class PhoneNumberUtils {
|
||||
private static boolean isEmergencyNumberInternal(int subId, String number,
|
||||
String defaultCountryIso,
|
||||
boolean useExactMatch) {
|
||||
// If the number passed in is null, just return false:
|
||||
if (number == null) return false;
|
||||
|
||||
// If the number passed in is a SIP address, return false, since the
|
||||
// concept of "emergency numbers" is only meaningful for calls placed
|
||||
// over the cell network.
|
||||
// (Be sure to do this check *before* calling extractNetworkPortionAlt(),
|
||||
// since the whole point of extractNetworkPortionAlt() is to filter out
|
||||
// any non-dialable characters (which would turn 'abc911def@example.com'
|
||||
// into '911', for example.))
|
||||
if (isUriNumber(number)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Strip the separators from the number before comparing it
|
||||
// to the list.
|
||||
number = extractNetworkPortionAlt(number);
|
||||
|
||||
String emergencyNumbers = "";
|
||||
int slotId = SubscriptionManager.getSlotIndex(subId);
|
||||
|
||||
// retrieve the list of emergency numbers
|
||||
// check read-write ecclist property first
|
||||
String ecclist = (slotId <= 0) ? "ril.ecclist" : ("ril.ecclist" + slotId);
|
||||
|
||||
emergencyNumbers = SystemProperties.get(ecclist, "");
|
||||
|
||||
Rlog.d(LOG_TAG, "slotId:" + slotId + " subId:" + subId + " country:"
|
||||
+ defaultCountryIso + " emergencyNumbers: " + emergencyNumbers);
|
||||
|
||||
if (TextUtils.isEmpty(emergencyNumbers)) {
|
||||
// then read-only ecclist property since old RIL only uses this
|
||||
emergencyNumbers = SystemProperties.get("ro.ril.ecclist");
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(emergencyNumbers)) {
|
||||
// searches through the comma-separated list for a match,
|
||||
// return true if one is found.
|
||||
for (String emergencyNum : emergencyNumbers.split(",")) {
|
||||
// It is not possible to append additional digits to an emergency number to dial
|
||||
// the number in Brazil - it won't connect.
|
||||
if (useExactMatch || "BR".equalsIgnoreCase(defaultCountryIso)) {
|
||||
if (number.equals(emergencyNum)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (number.startsWith(emergencyNum)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// no matches found against the list!
|
||||
return false;
|
||||
}
|
||||
|
||||
Rlog.d(LOG_TAG, "System property doesn't provide any emergency numbers."
|
||||
+ " Use embedded logic for determining ones.");
|
||||
|
||||
// If slot id is invalid, means that there is no sim card.
|
||||
// According spec 3GPP TS22.101, the following numbers should be
|
||||
// ECC numbers when SIM/USIM is not present.
|
||||
emergencyNumbers = ((slotId < 0) ? "112,911,000,08,110,118,119,999" : "112,911");
|
||||
|
||||
for (String emergencyNum : emergencyNumbers.split(",")) {
|
||||
if (useExactMatch) {
|
||||
if (number.equals(emergencyNum)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (number.startsWith(emergencyNum)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No ecclist system property, so use our own list.
|
||||
if (defaultCountryIso != null) {
|
||||
ShortNumberInfo info = ShortNumberInfo.getInstance();
|
||||
if (useExactMatch) {
|
||||
return info.isEmergencyNumber(number, defaultCountryIso);
|
||||
} else {
|
||||
return info.connectsToEmergencyNumber(number, defaultCountryIso);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return TelephonyManager.getDefault().isCurrentEmergencyNumber(number);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2078,7 +2028,11 @@ public class PhoneNumberUtils {
|
||||
* @param context the specific context which the number should be checked against
|
||||
* @return true if the specified number is an emergency number for the country the user
|
||||
* is currently in.
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)}
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isLocalEmergencyNumber(Context context, String number) {
|
||||
return isLocalEmergencyNumber(context, getDefaultVoiceSubId(), number);
|
||||
}
|
||||
@@ -2091,8 +2045,13 @@ public class PhoneNumberUtils {
|
||||
* @param context the specific context which the number should be checked against
|
||||
* @return true if the specified number is an emergency number for the country the user
|
||||
* is currently in.
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)}
|
||||
* instead.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
@UnsupportedAppUsage
|
||||
public static boolean isLocalEmergencyNumber(Context context, int subId, String number) {
|
||||
return isLocalEmergencyNumberInternal(subId, number,
|
||||
@@ -2120,8 +2079,13 @@ public class PhoneNumberUtils {
|
||||
* CountryDetector.
|
||||
*
|
||||
* @see android.location.CountryDetector
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
|
||||
* instead.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
@UnsupportedAppUsage
|
||||
public static boolean isPotentialLocalEmergencyNumber(Context context, String number) {
|
||||
return isPotentialLocalEmergencyNumber(context, getDefaultVoiceSubId(), number);
|
||||
@@ -2147,9 +2111,13 @@ public class PhoneNumberUtils {
|
||||
* @return true if the specified number is an emergency number for a local country, based on the
|
||||
* CountryDetector.
|
||||
*
|
||||
* @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
|
||||
* instead.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
@Deprecated
|
||||
public static boolean isPotentialLocalEmergencyNumber(Context context, int subId,
|
||||
String number) {
|
||||
return isLocalEmergencyNumberInternal(subId, number,
|
||||
@@ -2216,6 +2184,101 @@ public class PhoneNumberUtils {
|
||||
return isEmergencyNumberInternal(subId, number, countryIso, useExactMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Back-up old logics for {@link #isEmergencyNumberInternal} for legacy and deprecate purpose.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static boolean isEmergencyNumberInternal(String number, boolean useExactMatch,
|
||||
String defaultCountryIso) {
|
||||
// If the number passed in is null, just return false:
|
||||
if (number == null) return false;
|
||||
|
||||
// If the number passed in is a SIP address, return false, since the
|
||||
// concept of "emergency numbers" is only meaningful for calls placed
|
||||
// over the cell network.
|
||||
// (Be sure to do this check *before* calling extractNetworkPortionAlt(),
|
||||
// since the whole point of extractNetworkPortionAlt() is to filter out
|
||||
// any non-dialable characters (which would turn 'abc911def@example.com'
|
||||
// into '911', for example.))
|
||||
if (PhoneNumberUtils.isUriNumber(number)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Strip the separators from the number before comparing it
|
||||
// to the list.
|
||||
number = PhoneNumberUtils.extractNetworkPortionAlt(number);
|
||||
|
||||
String emergencyNumbers = "";
|
||||
int slotId = SubscriptionManager.getSlotIndex(getDefaultVoiceSubId());
|
||||
|
||||
// retrieve the list of emergency numbers
|
||||
// check read-write ecclist property first
|
||||
String ecclist = (slotId <= 0) ? "ril.ecclist" : ("ril.ecclist" + slotId);
|
||||
|
||||
emergencyNumbers = SystemProperties.get(ecclist, "");
|
||||
|
||||
Rlog.d(LOG_TAG, "slotId:" + slotId + " country:"
|
||||
+ defaultCountryIso + " emergencyNumbers: " + emergencyNumbers);
|
||||
|
||||
if (TextUtils.isEmpty(emergencyNumbers)) {
|
||||
// then read-only ecclist property since old RIL only uses this
|
||||
emergencyNumbers = SystemProperties.get("ro.ril.ecclist");
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(emergencyNumbers)) {
|
||||
// searches through the comma-separated list for a match,
|
||||
// return true if one is found.
|
||||
for (String emergencyNum : emergencyNumbers.split(",")) {
|
||||
// It is not possible to append additional digits to an emergency number to dial
|
||||
// the number in Brazil - it won't connect.
|
||||
if (useExactMatch || "BR".equalsIgnoreCase(defaultCountryIso)) {
|
||||
if (number.equals(emergencyNum)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (number.startsWith(emergencyNum)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// no matches found against the list!
|
||||
return false;
|
||||
}
|
||||
|
||||
Rlog.d(LOG_TAG, "System property doesn't provide any emergency numbers."
|
||||
+ " Use embedded logic for determining ones.");
|
||||
|
||||
// If slot id is invalid, means that there is no sim card.
|
||||
// According spec 3GPP TS22.101, the following numbers should be
|
||||
// ECC numbers when SIM/USIM is not present.
|
||||
emergencyNumbers = ((slotId < 0) ? "112,911,000,08,110,118,119,999" : "112,911");
|
||||
|
||||
for (String emergencyNum : emergencyNumbers.split(",")) {
|
||||
if (useExactMatch) {
|
||||
if (number.equals(emergencyNum)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (number.startsWith(emergencyNum)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No ecclist system property, so use our own list.
|
||||
if (defaultCountryIso != null) {
|
||||
ShortNumberInfo info = ShortNumberInfo.getInstance();
|
||||
if (useExactMatch) {
|
||||
return info.isEmergencyNumber(number, defaultCountryIso);
|
||||
} else {
|
||||
return info.connectsToEmergencyNumber(number, defaultCountryIso);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* isVoiceMailNumber: checks a given number against the voicemail
|
||||
* number provided by the RIL and SIM card. The caller must have
|
||||
|
||||
@@ -27,12 +27,14 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerExecutor;
|
||||
import android.os.Looper;
|
||||
import android.telephony.emergency.EmergencyNumber;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.telephony.IPhoneStateListener;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
@@ -313,6 +315,8 @@ public class PhoneStateListener {
|
||||
*
|
||||
* <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
|
||||
* app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
|
||||
*
|
||||
* @see #onEmergencyNumberListChanged
|
||||
*/
|
||||
public static final int LISTEN_EMERGENCY_NUMBER_LIST = 0x01000000;
|
||||
|
||||
@@ -626,6 +630,21 @@ public class PhoneStateListener {
|
||||
// default implementation empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked when the current emergency number list has changed
|
||||
*
|
||||
* @param emergencyNumberList Map including the key as the active subscription ID
|
||||
* (Note: if there is no active subscription, the key is
|
||||
* {@link SubscriptionManager#getDefaultSubscriptionId})
|
||||
* and the value as the list of {@link EmergencyNumber};
|
||||
* null if this information is not available.
|
||||
* @hide
|
||||
*/
|
||||
public void onEmergencyNumberListChanged(
|
||||
@NonNull Map<Integer, List<EmergencyNumber>> emergencyNumberList) {
|
||||
// default implementation empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked when OEM hook raw event is received. Requires
|
||||
* the READ_PRIVILEGED_PHONE_STATE permission.
|
||||
@@ -892,6 +911,16 @@ public class PhoneStateListener {
|
||||
() -> psl.onPhysicalChannelConfigurationChanged(configs)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEmergencyNumberListChanged(Map emergencyNumberList) {
|
||||
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
|
||||
if (psl == null) return;
|
||||
|
||||
Binder.withCleanCallingIdentity(
|
||||
() -> mExecutor.execute(
|
||||
() -> psl.onEmergencyNumberListChanged(emergencyNumberList)));
|
||||
}
|
||||
|
||||
public void onPhoneCapabilityChanged(PhoneCapability capability) {
|
||||
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
|
||||
if (psl == null) return;
|
||||
|
||||
@@ -9520,8 +9520,13 @@ public class TelephonyManager {
|
||||
/**
|
||||
* Get the emergency number list based on current locale, sim, default, modem and network.
|
||||
*
|
||||
* <p>The emergency number {@link EmergencyNumber} with higher display priority is located at
|
||||
* the smaller index in the returned list.
|
||||
* <p>In each returned list, the emergency number {@link EmergencyNumber} coming from higher
|
||||
* priority sources will be located at the smaller index; the priority order of sources are:
|
||||
* {@link EmergencyNumber#EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING} >
|
||||
* {@link EmergencyNumber#EMERGENCY_NUMBER_SOURCE_SIM} >
|
||||
* {@link EmergencyNumber#EMERGENCY_NUMBER_SOURCE_DATABASE} >
|
||||
* {@link EmergencyNumber#EMERGENCY_NUMBER_SOURCE_DEFAULT} >
|
||||
* {@link EmergencyNumber#EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG}
|
||||
*
|
||||
* <p>The subscriptions which the returned list would be based on, are all the active
|
||||
* subscriptions, no matter which subscription could be used to create TelephonyManager.
|
||||
@@ -9530,8 +9535,9 @@ public class TelephonyManager {
|
||||
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
|
||||
*
|
||||
* @return Map including the key as the active subscription ID (Note: if there is no active
|
||||
* subscription, the key is {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}) and the value
|
||||
* as the list of {@link EmergencyNumber}; null if this information is not available.
|
||||
* subscription, the key is {@link SubscriptionManager#getDefaultSubscriptionId}) and the value
|
||||
* as the list of {@link EmergencyNumber}; null if this information is not available; or throw
|
||||
* a SecurityException if the caller does not have the permission.
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@Nullable
|
||||
@@ -9552,8 +9558,13 @@ public class TelephonyManager {
|
||||
* Get the per-category emergency number list based on current locale, sim, default, modem
|
||||
* and network.
|
||||
*
|
||||
* <p>The emergency number {@link EmergencyNumber} with higher display priority is located at
|
||||
* the smaller index in the returned list.
|
||||
* <p>In each returned list, the emergency number {@link EmergencyNumber} coming from higher
|
||||
* priority sources will be located at the smaller index; the priority order of sources are:
|
||||
* {@link EmergencyNumber#EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING} >
|
||||
* {@link EmergencyNumber#EMERGENCY_NUMBER_SOURCE_SIM} >
|
||||
* {@link EmergencyNumber#EMERGENCY_NUMBER_SOURCE_DATABASE} >
|
||||
* {@link EmergencyNumber#EMERGENCY_NUMBER_SOURCE_DEFAULT} >
|
||||
* {@link EmergencyNumber#EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG}
|
||||
*
|
||||
* <p>The subscriptions which the returned list would be based on, are all the active
|
||||
* subscriptions, no matter which subscription could be used to create TelephonyManager.
|
||||
@@ -9574,8 +9585,9 @@ public class TelephonyManager {
|
||||
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
|
||||
* </ol>
|
||||
* @return Map including the key as the active subscription ID (Note: if there is no active
|
||||
* subscription, the key is {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}) and the value
|
||||
* as the list of {@link EmergencyNumber}; null if this information is not available.
|
||||
* subscription, the key is {@link SubscriptionManager#getDefaultSubscriptionId}) and the value
|
||||
* as the list of {@link EmergencyNumber}; null if this information is not available; or throw
|
||||
* a SecurityException if the caller does not have the permission.
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@Nullable
|
||||
@@ -9622,7 +9634,44 @@ public class TelephonyManager {
|
||||
if (telephony == null) {
|
||||
return false;
|
||||
}
|
||||
return telephony.isCurrentEmergencyNumber(number);
|
||||
return telephony.isCurrentEmergencyNumber(number, true);
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "isCurrentEmergencyNumber RemoteException", ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the supplied number is an emergency number based on current locale, sim, default,
|
||||
* modem and network.
|
||||
*
|
||||
* <p> Specifically, this method will return {@code true} if the specified number is an
|
||||
* emergency number, *or* if the number simply starts with the same digits as any current
|
||||
* emergency number.
|
||||
*
|
||||
* <p>The subscriptions which the identification would be based on, are all the active
|
||||
* subscriptions, no matter which subscription could be used to create TelephonyManager.
|
||||
*
|
||||
* <p>Requires permission: {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or
|
||||
* that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
|
||||
*
|
||||
* @param number - the number to look up
|
||||
* @return {@code true} if the given number is an emergency number or it simply starts with
|
||||
* the same digits of any current emergency number based on current locale, sim, modem and
|
||||
* network; {@code false} if it is not; or throw an SecurityException if the caller does not
|
||||
* have the required permission/privileges
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
public boolean isCurrentPotentialEmergencyNumber(@NonNull String number) {
|
||||
try {
|
||||
ITelephony telephony = getITelephony();
|
||||
if (telephony == null) {
|
||||
return false;
|
||||
}
|
||||
return telephony.isCurrentEmergencyNumber(number, false);
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "isCurrentEmergencyNumber RemoteException", ex);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.hardware.radio.V1_4.EmergencyNumberSource;
|
||||
import android.hardware.radio.V1_4.EmergencyServiceCategory;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.telephony.Rlog;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -150,6 +151,7 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
|
||||
@IntDef(flag = true, prefix = { "EMERGENCY_NUMBER_SOURCE_" }, value = {
|
||||
EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
|
||||
EMERGENCY_NUMBER_SOURCE_SIM,
|
||||
EMERGENCY_NUMBER_SOURCE_DATABASE,
|
||||
EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG,
|
||||
EMERGENCY_NUMBER_SOURCE_DEFAULT
|
||||
})
|
||||
@@ -169,6 +171,10 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
|
||||
* Reference: 3gpp 22.101, Section 10 - Emergency Calls
|
||||
*/
|
||||
public static final int EMERGENCY_NUMBER_SOURCE_SIM = EmergencyNumberSource.SIM;
|
||||
/**
|
||||
* Bit-field which indicates the number is from the platform-maintained database.
|
||||
*/
|
||||
public static final int EMERGENCY_NUMBER_SOURCE_DATABASE = 1 << 4;
|
||||
/** Bit-field which indicates the number is from the modem config. */
|
||||
public static final int EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG =
|
||||
EmergencyNumberSource.MODEM_CONFIG;
|
||||
@@ -187,21 +193,24 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
|
||||
EMERGENCY_NUMBER_SOURCE_SET = new HashSet<Integer>();
|
||||
EMERGENCY_NUMBER_SOURCE_SET.add(EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING);
|
||||
EMERGENCY_NUMBER_SOURCE_SET.add(EMERGENCY_NUMBER_SOURCE_SIM);
|
||||
EMERGENCY_NUMBER_SOURCE_SET.add(EMERGENCY_NUMBER_SOURCE_DATABASE);
|
||||
EMERGENCY_NUMBER_SOURCE_SET.add(EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG);
|
||||
EMERGENCY_NUMBER_SOURCE_SET.add(EMERGENCY_NUMBER_SOURCE_DEFAULT);
|
||||
}
|
||||
|
||||
private final String mNumber;
|
||||
private final String mCountryIso;
|
||||
private final String mMnc;
|
||||
private final int mEmergencyServiceCategoryBitmask;
|
||||
private final int mEmergencyNumberSourceBitmask;
|
||||
|
||||
/** @hide */
|
||||
public EmergencyNumber(@NonNull String number, @NonNull String countryIso,
|
||||
int emergencyServiceCategories,
|
||||
@NonNull String mnc, int emergencyServiceCategories,
|
||||
int emergencyNumberSources) {
|
||||
this.mNumber = number;
|
||||
this.mCountryIso = countryIso;
|
||||
this.mMnc = mnc;
|
||||
this.mEmergencyServiceCategoryBitmask = emergencyServiceCategories;
|
||||
this.mEmergencyNumberSourceBitmask = emergencyNumberSources;
|
||||
}
|
||||
@@ -210,6 +219,7 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
|
||||
public EmergencyNumber(Parcel source) {
|
||||
mNumber = source.readString();
|
||||
mCountryIso = source.readString();
|
||||
mMnc = source.readString();
|
||||
mEmergencyServiceCategoryBitmask = source.readInt();
|
||||
mEmergencyNumberSourceBitmask = source.readInt();
|
||||
}
|
||||
@@ -235,6 +245,15 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
|
||||
return mCountryIso;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Mobile Network Code of the emergency number.
|
||||
*
|
||||
* @return the Mobile Network Code of the emergency number.
|
||||
*/
|
||||
public String getMnc() {
|
||||
return mMnc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bitmask of emergency service categories of the emergency number.
|
||||
*
|
||||
@@ -338,6 +357,7 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mNumber);
|
||||
dest.writeString(mCountryIso);
|
||||
dest.writeString(mMnc);
|
||||
dest.writeInt(mEmergencyServiceCategoryBitmask);
|
||||
dest.writeInt(mEmergencyNumberSourceBitmask);
|
||||
}
|
||||
@@ -350,10 +370,10 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EmergencyNumber = " + "[Number]" + mNumber + " / [CountryIso]" + mCountryIso
|
||||
+ " / [ServiceCategories]"
|
||||
+ Integer.toBinaryString(mEmergencyServiceCategoryBitmask)
|
||||
+ " / [Sources]" + Integer.toBinaryString(mEmergencyNumberSourceBitmask);
|
||||
return "EmergencyNumber:" + "Number-" + mNumber + "|CountryIso-" + mCountryIso
|
||||
+ "|Mnc-" + mMnc
|
||||
+ "|ServiceCategories-" + Integer.toBinaryString(mEmergencyServiceCategoryBitmask)
|
||||
+ "|Sources-" + Integer.toBinaryString(mEmergencyNumberSourceBitmask);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -373,6 +393,7 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
|
||||
* The priority of sources are defined as follows:
|
||||
* EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING >
|
||||
* EMERGENCY_NUMBER_SOURCE_SIM >
|
||||
* EMERGENCY_NUMBER_SOURCE_DATABASE >
|
||||
* EMERGENCY_NUMBER_SOURCE_DEFAULT >
|
||||
* EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG
|
||||
*
|
||||
@@ -385,7 +406,9 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
|
||||
if (this.isFromSources(EMERGENCY_NUMBER_SOURCE_SIM)) {
|
||||
score += 1 << 3;
|
||||
}
|
||||
// TODO add a score if the number comes from Google's emergency number database
|
||||
if (this.isFromSources(EMERGENCY_NUMBER_SOURCE_DATABASE)) {
|
||||
score += 1 << 2;
|
||||
}
|
||||
if (this.isFromSources(EMERGENCY_NUMBER_SOURCE_DEFAULT)) {
|
||||
score += 1 << 1;
|
||||
}
|
||||
@@ -412,14 +435,104 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
|
||||
< emergencyNumber.getDisplayPriorityScore()) {
|
||||
return 1;
|
||||
} else {
|
||||
/**
|
||||
* TODO if both numbers have the same display priority score, the number matches the
|
||||
* Google's emergency number database has a higher display priority.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In-place merge same emergency numbers in the emergency number list.
|
||||
*
|
||||
* A unique EmergencyNumber has a unique combination of ‘number’, ‘mcc’, 'mnc' and
|
||||
* 'categories' fields. Multiple Emergency Number Sources should be merged into one bitfield
|
||||
* for the same EmergencyNumber.
|
||||
*
|
||||
* @param emergencyNumberList the emergency number list to process
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static void mergeSameNumbersInEmergencyNumberList(
|
||||
List<EmergencyNumber> emergencyNumberList) {
|
||||
if (emergencyNumberList == null) {
|
||||
return;
|
||||
}
|
||||
Set<EmergencyNumber> mergedEmergencyNumber = new HashSet<>();
|
||||
for (int i = 0; i < emergencyNumberList.size(); i++) {
|
||||
// Skip the check because it was merged.
|
||||
if (mergedEmergencyNumber.contains(emergencyNumberList.get(i))) {
|
||||
continue;
|
||||
}
|
||||
for (int j = i + 1; j < emergencyNumberList.size(); j++) {
|
||||
if (isSameEmergencyNumber(
|
||||
emergencyNumberList.get(i), emergencyNumberList.get(j))) {
|
||||
Rlog.e(LOG_TAG, "Found unexpected duplicate numbers: "
|
||||
+ emergencyNumberList.get(i) + " vs " + emergencyNumberList.get(j));
|
||||
// Set the merged emergency number in the current position
|
||||
emergencyNumberList.set(i, mergeNumbers(
|
||||
emergencyNumberList.get(i), emergencyNumberList.get(j)));
|
||||
// Mark the emergency number has been merged
|
||||
mergedEmergencyNumber.add(emergencyNumberList.get(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove the marked emergency number in the orignal list
|
||||
for (int i = 0; i < emergencyNumberList.size(); i++) {
|
||||
if (mergedEmergencyNumber.contains(emergencyNumberList.get(i))) {
|
||||
emergencyNumberList.remove(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if two emergency numbers are the same.
|
||||
*
|
||||
* A unique EmergencyNumber has a unique combination of ‘number’, ‘mcc’, 'mnc' and
|
||||
* 'categories' fields. Multiple Emergency Number Sources should be merged into one bitfield
|
||||
* for the same EmergencyNumber.
|
||||
*
|
||||
* @param first first EmergencyNumber to compare
|
||||
* @param second second EmergencyNumber to compare
|
||||
* @return true if they are the same EmergencyNumbers; false otherwise.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static boolean isSameEmergencyNumber(@NonNull EmergencyNumber first,
|
||||
@NonNull EmergencyNumber second) {
|
||||
if (!first.getNumber().equals(second.getNumber())) {
|
||||
return false;
|
||||
}
|
||||
if (!first.getCountryIso().equals(second.getCountryIso())) {
|
||||
return false;
|
||||
}
|
||||
if (!first.getMnc().equals(second.getMnc())) {
|
||||
return false;
|
||||
}
|
||||
if (first.getEmergencyServiceCategoryBitmask()
|
||||
!= second.getEmergencyServiceCategoryBitmask()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a merged EmergencyNumber for two numbers if they are the same.
|
||||
*
|
||||
* @param first first EmergencyNumber to compare
|
||||
* @param second second EmergencyNumber to compare
|
||||
* @return a merged EmergencyNumber or null if they are not the same EmergencyNumber
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static EmergencyNumber mergeNumbers(@NonNull EmergencyNumber first,
|
||||
@NonNull EmergencyNumber second) {
|
||||
if (isSameEmergencyNumber(first, second)) {
|
||||
return new EmergencyNumber(first.getNumber(), first.getCountryIso(), first.getMnc(),
|
||||
first.getEmergencyServiceCategoryBitmask(),
|
||||
first.getEmergencyNumberSourceBitmask()
|
||||
| second.getEmergencyNumberSourceBitmask());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<EmergencyNumber> CREATOR =
|
||||
new Parcelable.Creator<EmergencyNumber>() {
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.telephony.PhoneCapability;
|
||||
import android.telephony.PhysicalChannelConfig;
|
||||
import android.telephony.PreciseCallState;
|
||||
import android.telephony.PreciseDataConnectionState;
|
||||
import android.telephony.emergency.EmergencyNumber;
|
||||
|
||||
oneway interface IPhoneStateListener {
|
||||
void onServiceStateChanged(in ServiceState serviceState);
|
||||
@@ -51,8 +52,9 @@ oneway interface IPhoneStateListener {
|
||||
void onCarrierNetworkChange(in boolean active);
|
||||
void onUserMobileDataStateChanged(in boolean enabled);
|
||||
void onPhoneCapabilityChanged(in PhoneCapability capability);
|
||||
void onRadioPowerStateChanged(in int state);
|
||||
void onPreferredDataSubIdChanged(in int subId);
|
||||
void onRadioPowerStateChanged(in int state);
|
||||
void onEmergencyNumberListChanged(in Map emergencyNumberList);
|
||||
void onCallDisconnectCauseChanged(in int disconnectCause, in int preciseDisconnectCause);
|
||||
}
|
||||
|
||||
|
||||
@@ -1732,7 +1732,7 @@ interface ITelephony {
|
||||
/**
|
||||
* Identify if the number is emergency number, based on all the active subscriptions.
|
||||
*/
|
||||
boolean isCurrentEmergencyNumber(String number);
|
||||
boolean isCurrentEmergencyNumber(String number, boolean exactMatch);
|
||||
|
||||
/**
|
||||
* Return a list of certs in hex string from loaded carrier privileges access rules.
|
||||
|
||||
@@ -81,5 +81,5 @@ interface ITelephonyRegistry {
|
||||
void notifyPhoneCapabilityChanged(in PhoneCapability capability);
|
||||
void notifyPreferredDataSubIdChanged(int preferredSubId);
|
||||
void notifyRadioPowerStateChanged(in int state);
|
||||
void notifyEmergencyNumberList(in List<EmergencyNumber> emergencyNumberList);
|
||||
void notifyEmergencyNumberList();
|
||||
}
|
||||
|
||||
@@ -483,4 +483,5 @@ public interface RILConstants {
|
||||
int RIL_UNSOL_HAL_NON_RIL_BASE = 1100;
|
||||
int RIL_UNSOL_ICC_SLOT_STATUS = 1100;
|
||||
int RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG = 1101;
|
||||
int RIL_UNSOL_EMERGENCY_NUMBER_LIST = 1102;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user