Merge "EmergencyNumber enhancement"

am: b158b12cbb

Change-Id: I3493e759d2c5b582b54e6145d0aa8767501f1528
This commit is contained in:
Shuo Qian
2018-12-28 10:20:41 -08:00
committed by android-build-merger
11 changed files with 410 additions and 116 deletions

View File

@@ -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

View File

@@ -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();

View File

@@ -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();

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -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();
}

View File

@@ -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;
}