Merge "Store the reference to Phone to handle asynchronous response with the Phone"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 22d007e..461b18e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -424,6 +424,10 @@
"android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS" />
<action android:name=
"android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION" />
+ <action android:name=
+ "android.telephony.euicc.action.TRANSFER_EMBEDDED_SUBSCRIPTIONS" />
+ <action android:name=
+ "android.telephony.euicc.action.CONVERT_TO_EMBEDDED_SUBSCRIPTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 78a734a..200dc75 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -527,6 +527,8 @@
imsRcsController = ImsRcsController.init(this);
+ configLoader = CarrierConfigLoader.init(this);
+
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)) {
mImsStateCallbackController =
ImsStateCallbackController.make(this, PhoneFactory.getPhones().length);
@@ -538,8 +540,6 @@
ImsProvisioningController.make(this, PhoneFactory.getPhones().length);
}
- configLoader = CarrierConfigLoader.init(this);
-
// Create the CallNotifier singleton, which handles
// asynchronous events from the telephony layer (like
// launching the incoming-call UI when an incoming call comes
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index b7dfb77..5fe6717 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -143,6 +143,9 @@
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsConfigImplBase;
import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.satellite.ISatellitePositionUpdateCallback;
+import android.telephony.satellite.PointingInfo;
+import android.telephony.satellite.SatelliteManager;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.EventLog;
@@ -185,6 +188,7 @@
import com.android.internal.telephony.ProxyController;
import com.android.internal.telephony.RIL;
import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.RILUtils;
import com.android.internal.telephony.RadioInterfaceCapabilityController;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.SmsApplication;
@@ -251,6 +255,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
@@ -376,6 +381,10 @@
private static final int EVENT_IS_VONR_ENABLED_DONE = 116;
private static final int CMD_PURCHASE_PREMIUM_CAPABILITY = 117;
private static final int EVENT_PURCHASE_PREMIUM_CAPABILITY_DONE = 118;
+ private static final int CMD_START_SATELLITE_POSITION_UPDATES = 119;
+ private static final int EVENT_START_SATELLITE_POSITION_UPDATES_DONE = 120;
+ private static final int CMD_STOP_SATELLITE_POSITION_UPDATES = 121;
+ private static final int EVENT_STOP_SATELLITE_POSITION_UPDATES_DONE = 122;
// Parameters of select command.
private static final int SELECT_COMMAND = 0xA4;
private static final int SELECT_P1 = 0x04;
@@ -406,6 +415,8 @@
private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
private Set<Integer> mCarrierPrivilegeTestOverrideSubIds = new ArraySet<>();
+ private Map<Integer, SatellitePositionUpdateHandler> mSatellitePositionUpdateHandlers =
+ new ConcurrentHashMap<>();
private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
@@ -501,6 +512,46 @@
}
}
+ private static final class SatellitePositionUpdateHandler extends Handler {
+ public static final int EVENT_POSITION_UPDATE = 1;
+ public static final int EVENT_MESSAGE_TRANSFER_STATE_UPDATE = 2;
+
+ private final ISatellitePositionUpdateCallback mCallback;
+
+ SatellitePositionUpdateHandler(ISatellitePositionUpdateCallback callback, Looper looper) {
+ super(looper);
+ mCallback = callback;
+ }
+
+ @Override
+ public void handleMessage(@NonNull Message msg) {
+ switch (msg.what) {
+ case EVENT_POSITION_UPDATE: {
+ AsyncResult ar = (AsyncResult) msg.obj;
+ PointingInfo pointingInfo = (PointingInfo) ar.result;
+ try {
+ mCallback.onSatellitePositionUpdate(pointingInfo);
+ } catch (RemoteException e) {
+ loge("EVENT_POSITION_UPDATE RemoteException: " + e);
+ }
+ break;
+ }
+ case EVENT_MESSAGE_TRANSFER_STATE_UPDATE: {
+ AsyncResult ar = (AsyncResult) msg.obj;
+ int state = (int) ar.result;
+ try {
+ mCallback.onMessageTransferStateUpdate(state);
+ } catch (RemoteException e) {
+ loge("EVENT_MESSAGE_TRANSFER_STATE_UPDATE RemoteException: " + e);
+ }
+ break;
+ }
+ default:
+ loge("SatellitePositionUpdateHandler unknown event: " + msg.what);
+ }
+ }
+ }
+
/**
* A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
* request after sending. The main thread will notify the request when it is complete.
@@ -2247,6 +2298,76 @@
notifyRequester(request);
break;
+ case CMD_START_SATELLITE_POSITION_UPDATES: {
+ request = (MainThreadRequest) msg.obj;
+ onCompleted =
+ obtainMessage(EVENT_START_SATELLITE_POSITION_UPDATES_DONE, request);
+ Phone phone = getPhoneFromRequest(request);
+ if (phone != null) {
+ phone.startSatellitePositionUpdates(onCompleted);
+ } else {
+ loge("startSatellitePositionUpdates: No phone object");
+ request.result = SatelliteManager.SATELLITE_SERVICE_REQUEST_FAILED;
+ notifyRequester(request);
+ }
+ break;
+ }
+
+ case EVENT_START_SATELLITE_POSITION_UPDATES_DONE: {
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null) {
+ request.result = SatelliteManager.SATELLITE_SERVICE_SUCCESS;
+ } else {
+ request.result = SatelliteManager.SATELLITE_SERVICE_ERROR;
+ if (ar.exception instanceof CommandException) {
+ CommandException.Error error =
+ ((CommandException) (ar.exception)).getCommandError();
+ request.result = RILUtils.convertToSatelliteError(error);
+ loge("startSatellitePositionUpdates CommandException: " + ar.exception);
+ } else {
+ loge("startSatellitePositionUpdates unknown exception:" + ar.exception);
+ }
+ }
+ notifyRequester(request);
+ break;
+ }
+
+ case CMD_STOP_SATELLITE_POSITION_UPDATES: {
+ request = (MainThreadRequest) msg.obj;
+ onCompleted =
+ obtainMessage(EVENT_STOP_SATELLITE_POSITION_UPDATES_DONE, request);
+ Phone phone = getPhoneFromRequest(request);
+ if (phone != null) {
+ phone.stopSatellitePositionUpdates(onCompleted);
+ } else {
+ loge("stopSatellitePositionUpdates: No phone object");
+ request.result = SatelliteManager.SATELLITE_SERVICE_REQUEST_FAILED;
+ notifyRequester(request);
+ }
+ break;
+ }
+
+ case EVENT_STOP_SATELLITE_POSITION_UPDATES_DONE: {
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null) {
+ request.result = SatelliteManager.SATELLITE_SERVICE_SUCCESS;
+ } else {
+ request.result = SatelliteManager.SATELLITE_SERVICE_ERROR;
+ if (ar.exception instanceof CommandException) {
+ CommandException.Error error =
+ ((CommandException) (ar.exception)).getCommandError();
+ request.result = RILUtils.convertToSatelliteError(error);
+ loge("stopSatellitePositionUpdates CommandException: " + ar.exception);
+ } else {
+ loge("stopSatellitePositionUpdates unknown exception:" + ar.exception);
+ }
+ }
+ notifyRequester(request);
+ break;
+ }
+
default:
Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
break;
@@ -2953,6 +3074,10 @@
public boolean setRadioPower(boolean turnOn) {
enforceModifyPermission();
+ if (!turnOn) {
+ log("setRadioPower off: callingPackage=" + getCurrentPackageName());
+ }
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone defaultPhone = PhoneFactory.getDefaultPhone();
@@ -2971,6 +3096,10 @@
public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
enforceModifyPermission();
+ if (!turnOn) {
+ log("setRadioPowerForSubscriber off: subId=" + subId
+ + ",callingPackage=" + getCurrentPackageName());
+ }
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3005,6 +3134,8 @@
@TelephonyManager.RadioPowerReason int reason) {
enforceModifyPermission();
+ log("requestRadioPowerOffForReason: subId=" + subId
+ + ",reason=" + reason + ",callingPackage=" + getCurrentPackageName());
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3776,7 +3907,7 @@
}
private static void log(String msg) {
- Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
+ Log.d(LOG_TAG, msg);
}
private static void logv(String msg) {
@@ -6810,12 +6941,10 @@
// any network types which were set for security reasons.
if (mApp.checkCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE)
!= PERMISSION_GRANTED
- && (reason == TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G
- || reason == TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS)) {
+ && reason == TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G) {
throw new SecurityException(
"setAllowedNetworkTypesForReason cannot be called with carrier privileges for"
- + " reason "
- + reason);
+ + " reason " + reason);
}
if (!TelephonyManager.isValidAllowedNetworkTypesReason(reason)) {
loge("setAllowedNetworkTypesForReason: Invalid allowed network type reason: " + reason);
@@ -12038,6 +12167,94 @@
}
/**
+ * Start receiving satellite position updates.
+ * This can be called by the pointing UI when the user starts pointing to the satellite.
+ * Modem should continue to report the pointing input as the device or satellite moves.
+ *
+ * @param subId The subId to start satellite position updates for.
+ * @param callbackId The callback ID associating the public SatellitePositionUpdateCallback to
+ * the internal ISatellitePositionUpdateCallback below.
+ * @param callback The callback to notify of changes in satellite position.
+ * @return The result of the operation.
+ */
+ @Override
+ @SatelliteManager.SatelliteServiceResult public int startSatellitePositionUpdates(int subId,
+ int callbackId, @NonNull ISatellitePositionUpdateCallback callback) {
+ // TODO: check for SATELLITE_COMMUNICATION permission
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ loge("startSatellitePositionUpdates called with invalid subId: " + subId
+ + ". Retrying with default phone.");
+ phone = getDefaultPhone();
+ if (phone == null) {
+ loge("startSatellitePositionUpdates failed with no phone object.");
+ return SatelliteManager.SATELLITE_SERVICE_REQUEST_FAILED;
+ }
+ }
+
+ if (mSatellitePositionUpdateHandlers.containsKey(callbackId)) {
+ log("startSatellitePositionUpdates: callback already registered: " + callbackId);
+ return SatelliteManager.SATELLITE_SERVICE_SUCCESS;
+ }
+
+ SatellitePositionUpdateHandler handler =
+ new SatellitePositionUpdateHandler(callback, Looper.getMainLooper());
+ phone.registerForSatellitePointingInfoChanged(handler,
+ SatellitePositionUpdateHandler.EVENT_POSITION_UPDATE, null);
+ phone.registerForSatelliteMessagesTransferComplete(handler,
+ SatellitePositionUpdateHandler.EVENT_MESSAGE_TRANSFER_STATE_UPDATE, null);
+ mSatellitePositionUpdateHandlers.put(callbackId, handler);
+
+ int result = (int) sendRequest(CMD_START_SATELLITE_POSITION_UPDATES, null, subId);
+ if (DBG) log("startSatellitePositionUpdates result: " + result);
+ return result;
+ }
+
+ /**
+ * Stop receiving satellite position updates.
+ * This can be called by the pointing UI when the user stops pointing to the satellite.
+ *
+ * @param subId The subId to stop satellite position updates for.
+ * @param callbackId The ID of the callback that was passed in {@link
+ * #startSatellitePositionUpdates(int, int, ISatellitePositionUpdateCallback)}
+ * @return The result of the operation.
+ */
+ @Override
+ @SatelliteManager.SatelliteServiceResult public int stopSatellitePositionUpdates(int subId,
+ int callbackId) {
+ // TODO: check for SATELLITE_COMMUNICATION permission
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ loge("stopSatellitePositionUpdates called with invalid subId: " + subId
+ + ". Retrying with default phone.");
+ phone = getDefaultPhone();
+ if (phone == null) {
+ loge("stopSatellitePositionUpdates failed with no phone object.");
+ return SatelliteManager.SATELLITE_SERVICE_REQUEST_FAILED;
+ }
+ }
+
+ SatellitePositionUpdateHandler handler =
+ mSatellitePositionUpdateHandlers.remove(callbackId);
+ if (handler == null) {
+ loge("stopSatellitePositionUpdates: No SatellitePositionArgument");
+ return SatelliteManager.SATELLITE_SERVICE_REQUEST_FAILED;
+ } else {
+ phone.unregisterForSatellitePointingInfoChanged(handler);
+ phone.unregisterForSatelliteMessagesTransferComplete(handler);
+ }
+
+ if (!mSatellitePositionUpdateHandlers.isEmpty()) {
+ log("stopSatellitePositionUpdates: other listeners still exist.");
+ return SatelliteManager.SATELLITE_SERVICE_SUCCESS;
+ }
+
+ int result = (int) sendRequest(CMD_STOP_SATELLITE_POSITION_UPDATES, null, subId);
+ if (DBG) log("stopSatellitePositionUpdates result: " + result);
+ return result;
+ }
+
+ /**
* Check whether the caller (or self, if not processing an IPC) can read device identifiers.
*
* <p>This method behaves in one of the following ways:
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index f002e25..1858fe2 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -57,6 +57,7 @@
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.modules.utils.BasicShellCommandHandler;
import com.android.phone.callcomposer.CallComposerPictureManager;
+import com.android.phone.euicc.EuiccUiDispatcherActivity;
import com.android.phone.utils.CarrierAllowListInfo;
import java.io.IOException;
@@ -121,6 +122,9 @@
private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
private static final String CC_CLEAR_VALUES = "clear-values";
+ private static final String EUICC_SUBCOMMAND = "euicc";
+ private static final String EUICC_SET_UI_COMPONENT = "set-euicc-uicomponent";
+
private static final String GBA_SUBCOMMAND = "gba";
private static final String GBA_SET_SERVICE = "set-service";
private static final String GBA_GET_SERVICE = "get-service";
@@ -313,6 +317,8 @@
return handleDataTestModeCommand();
case END_BLOCK_SUPPRESSION:
return handleEndBlockSuppressionCommand();
+ case EUICC_SUBCOMMAND:
+ return handleEuiccCommand();
case GBA_SUBCOMMAND:
return handleGbaCommand();
case D2D_SUBCOMMAND:
@@ -608,6 +614,15 @@
pw.println(" is specified, it will choose the default voice SIM slot.");
}
+ private void onHelpEuicc() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("Euicc Commands:");
+ pw.println(" euicc set-euicc-uicomponent COMPONENT_NAME PACKAGE_NAME");
+ pw.println(" Sets the Euicc Ui-Component which handles EuiccService Actions.");
+ pw.println(" COMPONENT_NAME: The component name which handles UI Actions.");
+ pw.println(" PACKAGE_NAME: THe package name in which ui component belongs.");
+ }
+
private void onHelpGba() {
PrintWriter pw = getOutPrintWriter();
pw.println("Gba Commands:");
@@ -2058,6 +2073,35 @@
return 0;
}
+ private int handleEuiccCommand() {
+ String arg = getNextArg();
+ if (arg == null) {
+ onHelpEuicc();
+ return 0;
+ }
+
+ switch (arg) {
+ case EUICC_SET_UI_COMPONENT: {
+ return handleEuiccServiceCommand();
+ }
+ }
+ return -1;
+ }
+
+ private int handleEuiccServiceCommand() {
+ String uiComponent = getNextArg();
+ String packageName = getNextArg();
+ if (packageName == null || uiComponent == null) {
+ return -1;
+ }
+ EuiccUiDispatcherActivity.setTestEuiccUiComponent(packageName, uiComponent);
+ if (VDBG) {
+ Log.v(LOG_TAG, "euicc set-euicc-uicomponent " + uiComponent +" "
+ + packageName);
+ }
+ return 0;
+ }
+
private int handleRestartModemCommand() {
// Verify that the user is allowed to run the command. Only allowed in rooted device in a
// non user build.
diff --git a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
index 804611f..5da52d6 100644
--- a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
+++ b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
@@ -29,6 +29,7 @@
import android.permission.LegacyPermissionManager;
import android.service.euicc.EuiccService;
import android.telephony.euicc.EuiccManager;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -58,6 +59,8 @@
private LegacyPermissionManager mPermissionManager;
private boolean mGrantPermissionDone = false;
private ThreadPoolExecutor mExecutor;
+ // Used for CTS EuiccManager action verification
+ private static ComponentName mTestEuiccUiComponentName;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -94,6 +97,18 @@
}
}
+ /**
+ * This API used to set the Test EuiccUiComponent for CTS
+ * @param packageName package which handles the intent
+ * @param componentName ui component to be launched for testing
+ */
+ public static void setTestEuiccUiComponent(String packageName, String componentName) {
+ mTestEuiccUiComponentName = null;
+ if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(componentName)) {
+ mTestEuiccUiComponentName = new ComponentName(packageName, componentName);
+ }
+ }
+
@VisibleForTesting
@Nullable
Intent resolveEuiccUiIntent() {
@@ -109,6 +124,13 @@
return null;
}
+ if (mTestEuiccUiComponentName != null) {
+ Log.i(TAG, "Test mode");
+ euiccUiIntent.setComponent(mTestEuiccUiComponentName);
+ mTestEuiccUiComponentName = null;
+ return euiccUiIntent;
+ }
+
revokePermissionFromLuiApps(euiccUiIntent);
ActivityInfo activityInfo = findBestActivity(euiccUiIntent);
@@ -148,6 +170,12 @@
case EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION:
intent.setAction(EuiccService.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION);
break;
+ case EuiccManager.ACTION_TRANSFER_EMBEDDED_SUBSCRIPTIONS:
+ intent.setAction(EuiccService.ACTION_TRANSFER_EMBEDDED_SUBSCRIPTIONS);
+ break;
+ case EuiccManager.ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION:
+ intent.setAction(EuiccService.ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION);
+ break;
default:
Log.w(TAG, "Unsupported action: " + action);
return null;
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 9c9ddc9..8253f71 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -595,6 +595,30 @@
public void onSelectionTerminated(@DisconnectCauses int cause) {
if (mEmergencyCallDomainSelectionConnection != null) {
Log.i(this, "onSelectionTerminated cause=" + cause);
+
+ // Cross stack redial
+ if (cause == android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE
+ || cause == android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE) {
+ if (mEmergencyConnection != null) {
+ final boolean isPermanentFailure =
+ cause == android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE;
+ Log.i(this, "onSelectionTerminated trigger cross stack redial"
+ + " permanent=" + isPermanentFailure);
+ mDomainSelectionMainExecutor.execute(() -> {
+ Log.i(this, "onSelectionTerminated execute cross stack redial"
+ + " permanent=" + isPermanentFailure);
+ TelephonyConnection c = mEmergencyConnection;
+ Phone phone = mEmergencyCallDomainSelectionConnection.getPhone();
+ mEmergencyConnection.removeTelephonyConnectionListener(
+ mEmergencyConnectionListener);
+ mEmergencyStateTracker.endCall(
+ mEmergencyConnection.getTelecomCallId());
+ releaseEmergencyCallDomainSelection(true);
+ retryOutgoingOriginalConnection(c, phone, isPermanentFailure);
+ });
+ return;
+ }
+ }
mEmergencyCallDomainSelectionConnection = null;
if (mEmergencyConnection != null) {
mEmergencyConnection.hangup(android.telephony.DisconnectCause.OUT_OF_NETWORK);
@@ -658,7 +682,7 @@
@Override
public void onOriginalConnectionRetry(TelephonyConnection c, boolean isPermanentFailure) {
- retryOutgoingOriginalConnection(c, isPermanentFailure);
+ retryOutgoingOriginalConnection(c, c.getPhone(), isPermanentFailure);
}
};
@@ -1809,7 +1833,7 @@
// Update the mEmergencyRetryCache by removing the Phone used to call the last failed emergency
// number and then moving it to the back of the queue if it is not a permanent failure cause
// from the modem.
- private void updateCachedConnectionPhonePair(TelephonyConnection c,
+ private void updateCachedConnectionPhonePair(TelephonyConnection c, Phone phone,
boolean isPermanentFailure) {
// No cache exists, create a new one.
if (mEmergencyRetryCache == null) {
@@ -1824,7 +1848,7 @@
Queue<Phone> cachedPhones = mEmergencyRetryCache.second;
// Need to refer default phone considering ImsPhone because
// cachedPhones is a list that contains default phones.
- Phone phoneUsed = c.getPhone().getDefaultPhone();
+ Phone phoneUsed = phone.getDefaultPhone();
if (phoneUsed == null) {
return;
}
@@ -1853,9 +1877,10 @@
* This will continue until there are no more slots to dial on.
*/
@VisibleForTesting
- public void retryOutgoingOriginalConnection(TelephonyConnection c, boolean isPermanentFailure) {
- int phoneId = (c.getPhone() == null) ? -1 : c.getPhone().getPhoneId();
- updateCachedConnectionPhonePair(c, isPermanentFailure);
+ public void retryOutgoingOriginalConnection(TelephonyConnection c,
+ Phone phone, boolean isPermanentFailure) {
+ int phoneId = (phone == null) ? -1 : phone.getPhoneId();
+ updateCachedConnectionPhonePair(c, phone, isPermanentFailure);
// Pull next phone to use from the cache or null if it is empty
Phone newPhoneToUse = (mEmergencyRetryCache.second != null)
? mEmergencyRetryCache.second.peek() : null;
diff --git a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
index fa11a5d..d1eda18 100644
--- a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
@@ -68,6 +68,7 @@
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.BarringInfo;
import android.telephony.CarrierConfigManager;
+import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService;
import android.telephony.DomainSelectionService.SelectionAttributes;
import android.telephony.EmergencyRegResult;
@@ -106,6 +107,18 @@
private static final LocalLog sLocalLog = new LocalLog(LOG_SIZE);
+ private static final ArrayList<String> sAllowOnlyWithSimReady = new ArrayList<>();
+
+ static {
+ // b/177967010, JP
+ sAllowOnlyWithSimReady.add("jp"); // Japan
+ // b/198393826, DE
+ sAllowOnlyWithSimReady.add("de"); // Germany
+ // b/230443699, IN and SG
+ sAllowOnlyWithSimReady.add("in"); // India
+ sAllowOnlyWithSimReady.add("sg"); // Singapore
+ }
+
/**
* Network callback used to determine whether Wi-Fi is connected or not.
*/
@@ -167,6 +180,7 @@
private boolean mRequiresVoLteEnabled;
private boolean mLtePreferredAfterNrFailure;
private boolean mTryCsWhenPsFails;
+ private int mModemCount;
/** Indicates whether this instance is deactivated. */
private boolean mDestroyed = false;
@@ -228,6 +242,12 @@
private void handleScanResult(EmergencyRegResult result) {
logi("handleScanResult result=" + result);
+ // Detected the country and found that emergency calls are not allowed with this slot.
+ if (!allowEmergencyCalls(result)) {
+ terminateSelectionPermanentlyForSlot();
+ return;
+ }
+
if (result.getAccessNetwork() == UNKNOWN) {
if ((mPreferredNetworkScanType == SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE)
|| (mScanType == DomainSelectionService.SCAN_TYPE_FULL_SERVICE)) {
@@ -247,7 +267,7 @@
removeMessages(MSG_NETWORK_SCAN_TIMEOUT);
onWwanNetworkTypeSelected(result.getAccessNetwork());
- mIsScanRequested = false;
+ mCancelSignal = null;
}
@Override
@@ -318,11 +338,14 @@
mTransportSelectorCallback = cb;
mSelectionAttributes = attr;
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ mModemCount = tm.getActiveModemCount();
+
sendEmptyMessage(MSG_START_DOMAIN_SELECTION);
}
private void startDomainSelection() {
- logi("startDomainSelection");
+ logi("startDomainSelection modemCount=" + mModemCount);
updateCarrierConfiguration();
mDomainSelectionRequested = true;
if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
@@ -458,6 +481,12 @@
return;
}
+ if (!allowEmergencyCalls(mSelectionAttributes.getEmergencyRegResult())) {
+ // Detected the country and found that emergency calls are not allowed with this slot.
+ terminateSelectionPermanentlyForSlot();
+ return;
+ }
+
if (isWifiPreferred()) {
onWlanSelected();
return;
@@ -793,7 +822,7 @@
List<Integer> ratList = getImsNetworkTypeConfiguration();
if (ratList.contains(accessNetwork)) {
if (mIsEmergencyBarred) {
- logi("sgetSelectablePsNetworkType barred");
+ logi("getSelectablePsNetworkType barred");
return UNKNOWN;
}
if (accessNetwork == NGRAN) {
@@ -1100,6 +1129,36 @@
}
}
+ private boolean allowEmergencyCalls(EmergencyRegResult regResult) {
+ if (mModemCount < 2) return true;
+ if (regResult == null) {
+ loge("allowEmergencyCalls null regResult");
+ return true;
+ }
+
+ String iso = regResult.getIso();
+ if (sAllowOnlyWithSimReady.contains(iso)) {
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ int simState = tm.getSimState(getSlotId());
+ if (simState != TelephonyManager.SIM_STATE_READY) {
+ logi("allowEmergencyCalls not ready, simState=" + simState + ", iso=" + iso);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void terminateSelectionPermanentlyForSlot() {
+ logi("terminateSelectionPermanentlyForSlot");
+ mTransportSelectorCallback.onSelectionTerminated(DisconnectCause.EMERGENCY_PERM_FAILURE);
+
+ if (mIsScanRequested && mCancelSignal != null) {
+ mCancelSignal.cancel();
+ mCancelSignal = null;
+ }
+ }
+
private static String arrayToString(int[] intArray, IntFunction<String> func) {
int length = intArray.length;
StringBuilder sb = new StringBuilder("{");
diff --git a/src/com/android/services/telephony/rcs/TelephonyRcsService.java b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
index 13b3a7d..3a8ad62 100644
--- a/src/com/android/services/telephony/rcs/TelephonyRcsService.java
+++ b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
@@ -25,6 +25,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.util.Log;
@@ -351,23 +352,17 @@
private boolean doesSubscriptionSupportPresence(int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) return false;
- CarrierConfigManager carrierConfigManager =
- mContext.getSystemService(CarrierConfigManager.class);
- if (carrierConfigManager == null) return false;
- boolean supportsUce = carrierConfigManager.getConfigForSubId(subId).getBoolean(
- CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL);
- supportsUce |= carrierConfigManager.getConfigForSubId(subId).getBoolean(
- CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL);
+ boolean supportsUce = getConfig(subId,
+ CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, false /*default*/);
+ supportsUce |= getConfig(subId,
+ CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL, false /*default*/);
return supportsUce;
}
private boolean doesSubscriptionSupportSingleRegistration(int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) return false;
- CarrierConfigManager carrierConfigManager =
- mContext.getSystemService(CarrierConfigManager.class);
- if (carrierConfigManager == null) return false;
- return carrierConfigManager.getConfigForSubId(subId).getBoolean(
- CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL);
+ return getConfig(subId, CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+ false /*defaultValue*/);
}
private int getSubscriptionFromSlot(int slotId) {
@@ -384,6 +379,16 @@
}
/**
+ * @return the boolean result corresponding to a boolean {@link CarrierConfigManager} key.
+ */
+ private boolean getConfig(int subId, String key, boolean defaultValue) {
+ CarrierConfigManager c = mContext.getSystemService(CarrierConfigManager.class);
+ if (c == null) return defaultValue;
+ PersistableBundle b = c.getConfigForSubId(subId, key);
+ return b != null ? b.getBoolean(key, defaultValue) : defaultValue;
+ }
+
+ /**
* Dump this instance into a readable format for dumpsys usage.
*/
public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
index 720d235..111df53 100644
--- a/tests/src/com/android/TestContext.java
+++ b/tests/src/com/android/TestContext.java
@@ -17,6 +17,7 @@
package com.android;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import android.content.AttributionSource;
@@ -73,13 +74,12 @@
MockitoAnnotations.initMocks(this);
doAnswer((Answer<PersistableBundle>) invocation -> {
int subId = (int) invocation.getArguments()[0];
- if (subId < 0) {
- return new PersistableBundle();
- }
- PersistableBundle b = mCarrierConfigs.get(subId);
-
- return (b != null ? b : new PersistableBundle());
+ return getTestConfigs(subId);
}).when(mMockCarrierConfigManager).getConfigForSubId(anyInt());
+ doAnswer((Answer<PersistableBundle>) invocation -> {
+ int subId = (int) invocation.getArguments()[0];
+ return getTestConfigs(subId);
+ }).when(mMockCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
}
@Override
@@ -252,18 +252,16 @@
public void grantPermission(String permission) {
synchronized (mPermissionTable) {
- if (mPermissionTable != null && permission != null) {
- mPermissionTable.remove(STUB_PERMISSION_ENABLE_ALL);
- mPermissionTable.add(permission);
- }
+ if (permission == null) return;
+ mPermissionTable.remove(STUB_PERMISSION_ENABLE_ALL);
+ mPermissionTable.add(permission);
}
}
public void revokePermission(String permission) {
synchronized (mPermissionTable) {
- if (mPermissionTable != null && permission != null) {
- mPermissionTable.remove(permission);
- }
+ if (permission == null) return;
+ mPermissionTable.remove(permission);
}
}
@@ -281,6 +279,14 @@
return mReceiver;
}
+ private PersistableBundle getTestConfigs(int subId) {
+ if (subId < 0) {
+ return new PersistableBundle();
+ }
+ PersistableBundle b = getCarrierConfig(subId);
+ return (b != null ? b : new PersistableBundle());
+ }
+
private static void logd(String s) {
Log.d(TAG, s);
}
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 3d6a0aa..ba064e5 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -16,6 +16,8 @@
package com.android.services.telephony;
+import static android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE;
+import static android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE;
import static android.telephony.DisconnectCause.NOT_DISCONNECTED;
import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
import static android.telephony.NetworkRegistrationInfo.DOMAIN_CS;
@@ -55,6 +57,7 @@
import android.telecom.DisconnectCause;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
+import android.telephony.DomainSelectionService;
import android.telephony.RadioAccessFamily;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
@@ -76,6 +79,7 @@
import com.android.internal.telephony.PhoneInternalInterface.DialArgs;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.data.PhoneSwitcher;
+import com.android.internal.telephony.domainselection.DomainSelectionConnection;
import com.android.internal.telephony.domainselection.DomainSelectionResolver;
import com.android.internal.telephony.domainselection.EmergencyCallDomainSelectionConnection;
import com.android.internal.telephony.domainselection.NormalCallDomainSelectionConnection;
@@ -864,7 +868,8 @@
setPhones(phones);
c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
- mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), false /*isPermanentFailure*/);
// We never need to be notified in telecom that the PhoneAccount has changed, because it
// was redialed on the same slot
@@ -895,7 +900,8 @@
setPhones(phones);
c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
- mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), true /*isPermanentFailure*/);
// We never need to be notified in telecom that the PhoneAccount has changed, because it
// was never redialed
@@ -936,7 +942,8 @@
doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
slot1Phone);
- mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), false /*isPermanentFailure*/);
// The cache should still contain all of the Phones, since it was a temporary failure.
assertEquals(2, mTestConnectionService.mEmergencyRetryCache.second.size());
@@ -977,7 +984,8 @@
doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
slot1Phone);
- mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), true /*isPermanentFailure*/);
// The cache should only contain the slot1Phone.
assertEquals(1, mTestConnectionService.mEmergencyRetryCache.second.size());
@@ -1019,7 +1027,8 @@
slot1Phone);
// First Temporary failure
- mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), false /*isPermanentFailure*/);
// Set the Phone to the new phone that was just used to dial.
c.setMockPhone(slot1Phone);
// The cache should still contain all of the Phones, since it was a temporary failure.
@@ -1027,7 +1036,8 @@
// Make sure slot 1 is next in the queue.
assertEquals(slot1Phone, mTestConnectionService.mEmergencyRetryCache.second.peek());
// Second Temporary failure
- mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), false /*isPermanentFailure*/);
// Set the Phone to the new phone that was just used to dial.
c.setMockPhone(slot0Phone);
// The cache should still contain all of the Phones, since it was a temporary failure.
@@ -1074,7 +1084,8 @@
slot1Phone);
// First Permanent failure
- mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), true /*isPermanentFailure*/);
// Set the Phone to the new phone that was just used to dial.
c.setMockPhone(slot1Phone);
// The cache should only contain one phone
@@ -1082,7 +1093,8 @@
// Make sure slot 1 is next in the queue.
assertEquals(slot1Phone, mTestConnectionService.mEmergencyRetryCache.second.peek());
// Second Permanent failure
- mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), true /*isPermanentFailure*/);
// The cache should be empty
assertEquals(true, mTestConnectionService.mEmergencyRetryCache.second.isEmpty());
@@ -1631,6 +1643,98 @@
}
@Test
+ public void testOnSelectionTerminatedPerm() throws Exception {
+ setupForCallTest();
+
+ doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
+ .getDomainSelectionConnection(any(), anyInt(), eq(true));
+ doReturn(mPhone0).when(mEmergencyCallDomainSelectionConnection).getPhone();
+ doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+ doReturn(mImsPhone).when(mPhone0).getImsPhone();
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ ArgumentCaptor<DomainSelectionConnection.DomainSelectionConnectionCallback> callbackCaptor =
+ ArgumentCaptor.forClass(
+ DomainSelectionConnection.DomainSelectionConnectionCallback.class);
+
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(
+ any(), callbackCaptor.capture());
+
+ DomainSelectionConnection.DomainSelectionConnectionCallback callback =
+ callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ EmergencyCallDomainSelectionConnection ecdsc =
+ Mockito.mock(EmergencyCallDomainSelectionConnection.class);
+ doReturn(ecdsc).when(mDomainSelectionResolver)
+ .getDomainSelectionConnection(any(), anyInt(), eq(true));
+
+ callback.onSelectionTerminated(EMERGENCY_PERM_FAILURE);
+
+ ArgumentCaptor<DomainSelectionService.SelectionAttributes> attrCaptor =
+ ArgumentCaptor.forClass(
+ DomainSelectionService.SelectionAttributes.class);
+
+ verify(ecdsc).createEmergencyConnection(attrCaptor.capture(), any());
+
+ DomainSelectionService.SelectionAttributes attr = attrCaptor.getValue();
+
+ assertEquals(mPhone1.getPhoneId(), attr.getSlotId());
+ }
+
+ @Test
+ public void testOnSelectionTerminatedTemp() throws Exception {
+ setupForCallTest();
+
+ doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
+ .getDomainSelectionConnection(any(), anyInt(), eq(true));
+ doReturn(mPhone0).when(mEmergencyCallDomainSelectionConnection).getPhone();
+ doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+ doReturn(mImsPhone).when(mPhone0).getImsPhone();
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ ArgumentCaptor<DomainSelectionConnection.DomainSelectionConnectionCallback> callbackCaptor =
+ ArgumentCaptor.forClass(
+ DomainSelectionConnection.DomainSelectionConnectionCallback.class);
+
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(
+ any(), callbackCaptor.capture());
+
+ DomainSelectionConnection.DomainSelectionConnectionCallback callback =
+ callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ EmergencyCallDomainSelectionConnection ecdsc =
+ Mockito.mock(EmergencyCallDomainSelectionConnection.class);
+ doReturn(ecdsc).when(mDomainSelectionResolver)
+ .getDomainSelectionConnection(any(), anyInt(), eq(true));
+
+ callback.onSelectionTerminated(EMERGENCY_TEMP_FAILURE);
+
+ ArgumentCaptor<DomainSelectionService.SelectionAttributes> attrCaptor =
+ ArgumentCaptor.forClass(
+ DomainSelectionService.SelectionAttributes.class);
+
+ verify(ecdsc).createEmergencyConnection(attrCaptor.capture(), any());
+
+ DomainSelectionService.SelectionAttributes attr = attrCaptor.getValue();
+
+ assertEquals(mPhone1.getPhoneId(), attr.getSlotId());
+ }
+
+ @Test
public void testDomainSelectionWithMmiCode() {
//UT domain selection should not be handled by new domain selector.
doNothing().when(mContext).startActivity(any());
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
index c50c6b5..27b3f0a 100644
--- a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
@@ -80,6 +80,7 @@
import android.telephony.BarringInfo;
import android.telephony.CarrierConfigManager;
import android.telephony.CellIdentityLte;
+import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService;
import android.telephony.DomainSelectionService.SelectionAttributes;
import android.telephony.EmergencyRegResult;
@@ -1106,6 +1107,27 @@
verify(mTransportSelectorCallback, times(1)).onWlanSelected();
}
+ @Test
+ public void testDualSimInvalidSubscription() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
+ doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
+ .when(mTelephonyManager).getSimState(anyInt());
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "", "jp");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ verify(mTransportSelectorCallback, times(1))
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_PERM_FAILURE));
+ }
+
private void createSelector(int subId) throws Exception {
mDomainSelector = new EmergencyCallDomainSelector(
mContext, SLOT_0, subId, mHandlerThread.getLooper(),
@@ -1174,9 +1196,19 @@
@NetworkRegistrationInfo.Domain int domain,
boolean isVopsSupported, boolean isEmcBearerSupported, int emc, int emf,
@NonNull String mcc, @NonNull String mnc) {
+ return getEmergencyRegResult(accessNetwork, regState, domain, isVopsSupported,
+ isEmcBearerSupported, emc, emf, mcc, mnc, "");
+ }
+
+ private static EmergencyRegResult getEmergencyRegResult(
+ @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork,
+ @NetworkRegistrationInfo.RegistrationState int regState,
+ @NetworkRegistrationInfo.Domain int domain,
+ boolean isVopsSupported, boolean isEmcBearerSupported, int emc, int emf,
+ @NonNull String mcc, @NonNull String mnc, @NonNull String iso) {
return new EmergencyRegResult(accessNetwork, regState,
domain, isVopsSupported, isEmcBearerSupported,
- emc, emf, mcc, mnc, "");
+ emc, emf, mcc, mnc, iso);
}
private static PersistableBundle getDefaultPersistableBundle() {