Merge "system API getSimLocale"
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 2cd6885..36a7b99 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -86,6 +86,7 @@
import android.telephony.data.ApnSetting;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.gsm.GsmCellLocation;
+import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
@@ -93,6 +94,8 @@
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
+import android.telephony.ims.feature.MmTelFeature;
+import android.telephony.ims.stub.ImsConfigImplBase;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -130,6 +133,7 @@
import com.android.internal.telephony.SmsApplication.SmsApplicationData;
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.TelephonyPermissions;
+import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.euicc.EuiccConnector;
import com.android.internal.telephony.uicc.IccIoResult;
import com.android.internal.telephony.uicc.IccUtils;
@@ -153,9 +157,11 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
/**
* Implementation of the ITelephony interface.
@@ -257,6 +263,7 @@
private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
+ private static final String PREF_PROVISION_IMS_MMTEL_PREFIX = "provision_ims_mmtel_";
// The AID of ISD-R.
private static final String ISDR_AID = "A0000005591010FFFFFFFF8900000100";
@@ -2940,8 +2947,10 @@
final long identity = Binder.clearCallingIdentity();
try {
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
+ boolean isRoaming = TelephonyManager.from(
+ getPhone(subId).getContext()).isNetworkRoaming(subId);
ImsManager.getInstance(mApp,
- getSlotIndexOrException(subId)).setWfcNonPersistent(isCapable, mode);
+ getSlotIndexOrException(subId)).setWfcNonPersistent(isCapable, mode, isRoaming);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3063,15 +3072,249 @@
}
@Override
+ public void setImsProvisioningStatusForCapability(int subId, int capability, int tech,
+ boolean isProvisioned) {
+ if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
+ && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
+ throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
+ }
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
+ "setProvisioningStatusForCapability");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ loge("setImsProvisioningStatusForCapability: phone instance null for subid "
+ + subId);
+ return;
+ }
+ if (!doesImsCapabilityRequireProvisioning(phone.getContext(), subId, capability)) {
+ return;
+ }
+
+ // this capability requires provisioning, route to the correct API.
+ ImsManager ims = ImsManager.getInstance(mApp, getSlotIndex(subId));
+ switch (capability) {
+ case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE: {
+ if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
+ ims.setVolteProvisioned(isProvisioned);
+ } else if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN) {
+ ims.setWfcProvisioned(isProvisioned);
+ }
+ break;
+ }
+ case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO: {
+ // There is currently no difference in VT provisioning type.
+ ims.setVtProvisioned(isProvisioned);
+ break;
+ }
+ case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT: {
+ // There is no "deprecated" UT provisioning mechanism through ImsConfig, so
+ // change the capability of the feature instead if needed.
+ if (isMmTelCapabilityProvisionedInCache(subId, capability, tech)
+ == isProvisioned) {
+ // No change in provisioning.
+ return;
+ }
+ cacheMmTelCapabilityProvisioning(subId, capability, tech, isProvisioned);
+ try {
+ ims.changeMmTelCapability(capability, tech, isProvisioned);
+ } catch (ImsException e) {
+ loge("setImsProvisioningStatusForCapability: couldn't change UT capability"
+ + ", Exception" + e.getMessage());
+ }
+ break;
+ }
+ default: {
+ throw new IllegalArgumentException("Tried to set provisioning for capability '"
+ + capability + "', which does not require provisioning.");
+ }
+ }
+
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public boolean getImsProvisioningStatusForCapability(int subId, int capability, int tech) {
+ if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
+ && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
+ throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
+ }
+ enforceReadPrivilegedPermission("getProvisioningStatusForCapability");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ loge("getImsProvisioningStatusForCapability: phone instance null for subid "
+ + subId);
+ // We will fail with "true" as the provisioning status because this is the default
+ // if we do not require provisioning.
+ return true;
+ }
+
+ if (!doesImsCapabilityRequireProvisioning(phone.getContext(), subId, capability)) {
+ return true;
+ }
+
+ ImsManager ims = ImsManager.getInstance(mApp, getSlotIndex(subId));
+ switch (capability) {
+ case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE: {
+ if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
+ return ims.isVolteProvisionedOnDevice();
+ } else if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN) {
+ return ims.isWfcProvisionedOnDevice();
+ }
+ // This should never happen, since we are checking tech above to make sure it
+ // is either LTE or IWLAN.
+ throw new IllegalArgumentException("Invalid radio technology for voice "
+ + "capability.");
+ }
+ case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO: {
+ // There is currently no difference in VT provisioning type.
+ return ims.isVtProvisionedOnDevice();
+ }
+ case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT: {
+ // There is no "deprecated" UT provisioning mechanism, so get from shared prefs.
+ return isMmTelCapabilityProvisionedInCache(subId, capability, tech);
+ }
+ default: {
+ throw new IllegalArgumentException("Tried to get provisioning for capability '"
+ + capability + "', which does not require provisioning.");
+ }
+ }
+
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public boolean isMmTelCapabilityProvisionedInCache(int subId, int capability, int tech) {
+ if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
+ && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
+ throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
+ }
+ enforceReadPrivilegedPermission("isMmTelCapabilityProvisionedInCache");
+ int provisionedBits = getMmTelCapabilityProvisioningBitfield(subId, tech);
+ return (provisionedBits & capability) > 0;
+ }
+
+ @Override
+ public void cacheMmTelCapabilityProvisioning(int subId, int capability, int tech,
+ boolean isProvisioned) {
+ if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
+ && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
+ throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
+ }
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
+ "setProvisioningStatusForCapability");
+ int provisionedBits = getMmTelCapabilityProvisioningBitfield(subId, tech);
+ // If the current provisioning status for capability already matches isProvisioned,
+ // do nothing.
+ if (((provisionedBits & capability) > 0) == isProvisioned) {
+ return;
+ }
+ if (isProvisioned) {
+ setMmTelCapabilityProvisioningBitfield(subId, tech, (provisionedBits | capability));
+ } else {
+ setMmTelCapabilityProvisioningBitfield(subId, tech, (provisionedBits & ~capability));
+ }
+ }
+
+ /**
+ * @return the bitfield containing the MmTel provisioning for the provided subscription and
+ * technology. The bitfield should mirror the bitfield defined by
+ * {@link MmTelFeature.MmTelCapabilities.MmTelCapability}.
+ */
+ private int getMmTelCapabilityProvisioningBitfield(int subId, int tech) {
+ String key = getMmTelProvisioningKey(subId, tech);
+ // Default is no capabilities are provisioned.
+ return mTelephonySharedPreferences.getInt(key, 0 /*default*/);
+ }
+
+ /**
+ * Sets the MmTel capability provisioning bitfield (defined by
+ * {@link MmTelFeature.MmTelCapabilities.MmTelCapability}) for the subscription and
+ * technology specified.
+ *
+ * Note: This is a synchronous command and should not be called on UI thread.
+ */
+ private void setMmTelCapabilityProvisioningBitfield(int subId, int tech, int newField) {
+ final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
+ String key = getMmTelProvisioningKey(subId, tech);
+ editor.putInt(key, newField);
+ editor.commit();
+ }
+
+ private static String getMmTelProvisioningKey(int subId, int tech) {
+ // resulting key is provision_ims_mmtel_{subId}_{tech}
+ return PREF_PROVISION_IMS_MMTEL_PREFIX + subId + "_" + tech;
+ }
+
+ /**
+ * Query CarrierConfig to see if the specified capability requires provisioning for the
+ * carrier associated with the subscription id.
+ */
+ private boolean doesImsCapabilityRequireProvisioning(Context context, int subId,
+ int capability) {
+ CarrierConfigManager configManager = new CarrierConfigManager(context);
+ PersistableBundle c = configManager.getConfigForSubId(subId);
+ boolean requireUtProvisioning = c.getBoolean(
+ // By default, this config is true (even if there is no SIM). We also check to make
+ // sure the subscription needs provisioning here, so we do not need to check for
+ // the no-SIM case, where we would normally shortcut this to false.
+ CarrierConfigManager.KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL, true)
+ && c.getBoolean(CarrierConfigManager.KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL,
+ false);
+ boolean requireVoiceVtProvisioning = c.getBoolean(
+ CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, false);
+
+ // First check to make sure that the capability requires provisioning.
+ switch (capability) {
+ case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE:
+ // intentional fallthrough
+ case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO: {
+ if (requireVoiceVtProvisioning) {
+ // Voice and Video requires provisioning
+ return true;
+ }
+ break;
+ }
+ case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT: {
+ if (requireUtProvisioning) {
+ // UT requires provisioning
+ return true;
+ }
+ break;
+ }
+ }
+ return false;
+ }
+
+ @Override
public int getImsProvisioningInt(int subId, int key) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
+ }
enforceReadPrivilegedPermission("getImsProvisioningInt");
final long identity = Binder.clearCallingIdentity();
try {
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
- return ImsManager.getInstance(mApp,
- getSlotIndexOrException(subId)).getConfigInterface().getConfigInt(key);
+ int slotId = getSlotIndex(subId);
+ if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ Log.w(LOG_TAG, "getImsProvisioningInt: called with an inactive subscription '"
+ + subId + "' for key:" + key);
+ return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
+ }
+ return ImsManager.getInstance(mApp, slotId).getConfigInterface().getConfigInt(key);
} catch (ImsException e) {
- throw new IllegalArgumentException(e.getMessage());
+ Log.w(LOG_TAG, "getImsProvisioningInt: ImsService is not available for subscription '"
+ + subId + "' for key:" + key);
+ return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3079,14 +3322,24 @@
@Override
public String getImsProvisioningString(int subId, int key) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
+ }
enforceReadPrivilegedPermission("getImsProvisioningString");
final long identity = Binder.clearCallingIdentity();
try {
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
- return ImsManager.getInstance(mApp,
- getSlotIndexOrException(subId)).getConfigInterface().getConfigString(key);
+ int slotId = getSlotIndex(subId);
+ if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ Log.w(LOG_TAG, "getImsProvisioningString: called for an inactive subscription id '"
+ + subId + "' for key:" + key);
+ return ProvisioningManager.STRING_QUERY_RESULT_ERROR_GENERIC;
+ }
+ return ImsManager.getInstance(mApp, slotId).getConfigInterface().getConfigString(key);
} catch (ImsException e) {
- throw new IllegalArgumentException(e.getMessage());
+ Log.w(LOG_TAG, "getImsProvisioningString: ImsService is not available for sub '"
+ + subId + "' for key:" + key);
+ return ProvisioningManager.STRING_QUERY_RESULT_ERROR_NOT_READY;
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3094,15 +3347,25 @@
@Override
public int setImsProvisioningInt(int subId, int key, int value) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
+ }
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setImsProvisioningInt");
final long identity = Binder.clearCallingIdentity();
try {
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
- return ImsManager.getInstance(mApp,
- getSlotIndexOrException(subId)).getConfigInterface().setConfig(key, value);
+ int slotId = getSlotIndex(subId);
+ if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ Log.w(LOG_TAG, "setImsProvisioningInt: called with an inactive subscription id '"
+ + subId + "' for key:" + key);
+ return ImsConfigImplBase.CONFIG_RESULT_FAILED;
+ }
+ return ImsManager.getInstance(mApp, slotId).getConfigInterface().setConfig(key, value);
} catch (ImsException e) {
- throw new IllegalArgumentException(e.getMessage());
+ Log.w(LOG_TAG, "setImsProvisioningInt: ImsService unavailable for sub '" + subId
+ + "' for key:" + key);
+ return ImsConfigImplBase.CONFIG_RESULT_FAILED;
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3110,15 +3373,25 @@
@Override
public int setImsProvisioningString(int subId, int key, String value) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
+ }
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setImsProvisioningString");
final long identity = Binder.clearCallingIdentity();
try {
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
- return ImsManager.getInstance(mApp,
- getSlotIndexOrException(subId)).getConfigInterface().setConfig(key, value);
+ int slotId = getSlotIndex(subId);
+ if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ Log.w(LOG_TAG, "setImsProvisioningString: called with an inactive subscription id '"
+ + subId + "' for key:" + key);
+ return ImsConfigImplBase.CONFIG_RESULT_FAILED;
+ }
+ return ImsManager.getInstance(mApp, slotId).getConfigInterface().setConfig(key, value);
} catch (ImsException e) {
- throw new IllegalArgumentException(e.getMessage());
+ Log.w(LOG_TAG, "setImsProvisioningString: ImsService unavailable for sub '" + subId
+ + "' for key:" + key);
+ return ImsConfigImplBase.CONFIG_RESULT_FAILED;
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3132,6 +3405,14 @@
return slotId;
}
+ private int getSlotIndex(int subId) {
+ int slotId = SubscriptionManager.getSlotIndex(subId);
+ if (!SubscriptionManager.isValidSlotIndex(slotId)) {
+ return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+ }
+ return slotId;
+ }
+
/**
* Returns the network type for a subId
*/
@@ -6062,6 +6343,52 @@
}
}
+ /**
+ * Update emergency number list for test mode.
+ */
+ @Override
+ public void updateEmergencyNumberListTestMode(int action, EmergencyNumber num) {
+ TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+ "updateEmergencyNumberListTestMode");
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ for (Phone phone: PhoneFactory.getPhones()) {
+ EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
+ if (tracker != null) {
+ tracker.executeEmergencyNumberTestModeCommand(action, num);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Get the full emergency number list for test mode.
+ */
+ @Override
+ public List<String> getEmergencyNumberListTestMode() {
+ TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+ "getEmergencyNumberListTestMode");
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Set<String> emergencyNumbers = new HashSet<>();
+ for (Phone phone: PhoneFactory.getPhones()) {
+ EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
+ if (tracker != null) {
+ for (EmergencyNumber num : tracker.getEmergencyNumberList()) {
+ emergencyNumbers.add(num.getNumber());
+ }
+ }
+ }
+ return new ArrayList<>(emergencyNumbers);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
@Override
public List<String> getCertsFromCarrierPrivilegeAccessRules(int subId) {
enforceReadPrivilegedPermission("getCertsFromCarrierPrivilegeAccessRules");
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 9250118..956e0e2 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -22,11 +22,14 @@
import android.os.ShellCommand;
import android.os.UserHandle;
import android.telephony.SubscriptionManager;
+import android.telephony.emergency.EmergencyNumber;
import android.util.Log;
import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import java.io.PrintWriter;
+import java.util.ArrayList;
/**
* Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
@@ -44,6 +47,7 @@
private static final String IMS_SUBCOMMAND = "ims";
private static final String SMS_SUBCOMMAND = "sms";
private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
+ private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
private static final String IMS_SET_CARRIER_SERVICE = "set-ims-service";
private static final String IMS_GET_CARRIER_SERVICE = "get-ims-service";
@@ -79,6 +83,8 @@
}
case NUMBER_VERIFICATION_SUBCOMMAND:
return handleNumberVerificationCommand();
+ case EMERGENCY_NUMBER_TEST_MODE:
+ return handleEmergencyNumberTestModeCommand();
default: {
return handleDefaultCommands(cmd);
}
@@ -95,8 +101,11 @@
pw.println(" IMS Commands.");
pw.println(" sms");
pw.println(" SMS Commands.");
+ pw.println(" emergency-number-test-mode");
+ pw.println(" Emergency Number Test Mode Commands.");
onHelpIms();
onHelpSms();
+ onHelpEmergencyNumber();
}
private void onHelpIms() {
@@ -147,6 +156,20 @@
pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
}
+ private void onHelpEmergencyNumber() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("Emergency Number Test Mode Commands:");
+ pw.println(" emergency-number-test-mode ");
+ pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
+ + " the test mode");
+ pw.println(" -a <emergency number address>: add an emergency number address for the"
+ + " test mode, only allows '0'-'9', '*', or '#'.");
+ pw.println(" -c: clear the emergency number list in the test mode.");
+ pw.println(" -r <emergency number address>: remove an existing emergency number"
+ + " address added by the test mode, only allows '0'-'9', '*', or '#'.");
+ pw.println(" -p: get the full emergency number list in the test mode.");
+ }
+
private int handleImsCommand() {
String arg = getNextArg();
if (arg == null) {
@@ -172,6 +195,91 @@
return -1;
}
+ private int handleEmergencyNumberTestModeCommand() {
+ PrintWriter errPw = getErrPrintWriter();
+ String opt = getNextOption();
+ if (opt == null) {
+ onHelpEmergencyNumber();
+ return 0;
+ }
+
+ switch (opt) {
+ case "-a": {
+ String emergencyNumberCmd = getNextArgRequired();
+ if (emergencyNumberCmd == null
+ || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
+ errPw.println("An emergency number (only allow '0'-'9', '*', or '#') needs"
+ + " to be specified after -a in the command ");
+ return -1;
+ }
+ try {
+ mInterface.updateEmergencyNumberListTestMode(
+ EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
+ new EmergencyNumber(emergencyNumberCmd, "", "",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ new ArrayList<String>(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
+ } catch (RemoteException ex) {
+ Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
+ + ", error " + ex.getMessage());
+ errPw.println("Exception: " + ex.getMessage());
+ return -1;
+ }
+ break;
+ }
+ case "-c": {
+ try {
+ mInterface.updateEmergencyNumberListTestMode(
+ EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
+ } catch (RemoteException ex) {
+ Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
+ errPw.println("Exception: " + ex.getMessage());
+ return -1;
+ }
+ break;
+ }
+ case "-r": {
+ String emergencyNumberCmd = getNextArgRequired();
+ if (emergencyNumberCmd == null
+ || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
+ errPw.println("An emergency number (only allow '0'-'9', '*', or '#') needs"
+ + " to be specified after -r in the command ");
+ return -1;
+ }
+ try {
+ mInterface.updateEmergencyNumberListTestMode(
+ EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
+ new EmergencyNumber(emergencyNumberCmd, "", "",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ new ArrayList<String>(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
+ } catch (RemoteException ex) {
+ Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
+ + ", error " + ex.getMessage());
+ errPw.println("Exception: " + ex.getMessage());
+ return -1;
+ }
+ break;
+ }
+ case "-p": {
+ try {
+ getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
+ } catch (RemoteException ex) {
+ Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
+ errPw.println("Exception: " + ex.getMessage());
+ return -1;
+ }
+ break;
+ }
+ default:
+ onHelpEmergencyNumber();
+ break;
+ }
+ return 0;
+ }
+
private int handleNumberVerificationCommand() {
String arg = getNextArg();
if (arg == null) {