Synchronize the execution of exitEmergencyMode and setEmergencyMode
In switching stacks for cross sim redialing, the execution order of
exitEmergencyMode on SIM1 and setEmergencyMode on SIM2 should be
synchronized.
To ensure the execution order, make setEmergencyMode be delayed
until exitEmergencyMode completes.
Bug: 331902867
Test: atest EmergencyStateTrackerTest
Change-Id: I847e0e1e79f9f8547f4568746aaf607e66dfbec8
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index 1c8b696..25d94cf 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -354,11 +354,26 @@
mOnEcmExitCompleteRunnable.run();
mOnEcmExitCompleteRunnable = null;
}
+ if (mPhone != null && mEmergencyMode == MODE_EMERGENCY_WWAN) {
+ // In cross sim redialing.
+ setEmergencyModeInProgress(true);
+ mWasEmergencyModeSetOnModem = true;
+ mPhone.setEmergencyMode(MODE_EMERGENCY_WWAN,
+ mHandler.obtainMessage(MSG_SET_EMERGENCY_MODE_DONE,
+ Integer.valueOf(EMERGENCY_TYPE_CALL)));
+ }
} else if (emergencyType == EMERGENCY_TYPE_SMS) {
if (mIsEmergencyCallStartedDuringEmergencySms) {
mIsEmergencyCallStartedDuringEmergencySms = false;
turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL,
mIsTestEmergencyNumber);
+ } else if (mPhone != null && mEmergencyMode == MODE_EMERGENCY_WWAN) {
+ // Starting emergency call while exiting emergency mode
+ setEmergencyModeInProgress(true);
+ mWasEmergencyModeSetOnModem = true;
+ mPhone.setEmergencyMode(MODE_EMERGENCY_WWAN,
+ mHandler.obtainMessage(MSG_SET_EMERGENCY_MODE_DONE,
+ Integer.valueOf(EMERGENCY_TYPE_CALL)));
} else if (mIsEmergencySmsStartedDuringScbm) {
mIsEmergencySmsStartedDuringScbm = false;
setEmergencyMode(mSmsPhone, emergencyType,
@@ -713,6 +728,16 @@
maybeNotifyTransportChangeCompleted(emergencyType, false);
return;
}
+
+ if (emergencyType == EMERGENCY_TYPE_CALL
+ && mode == MODE_EMERGENCY_WWAN
+ && isEmergencyModeInProgress() && !isInEmergencyMode()) {
+ // In cross sim redialing or ending emergency SMS, exitEmergencyMode is not completed.
+ mEmergencyMode = mode;
+ Rlog.i(TAG, "setEmergencyMode wait for the completion of exitEmergencyMode");
+ return;
+ }
+
mEmergencyMode = mode;
setEmergencyModeInProgress(true);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
index 699ee7b..ce85e53 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -2837,6 +2837,94 @@
verify(mContext, never()).sendStickyBroadcastAsUser(any(), any());
}
+ @Test
+ @SmallTest
+ public void testEnsureExecutionOrderOfExitEmergencyModeThenSetEmergencyMode() {
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+ /* isRadioOn= */ true);
+ setUpAsyncResultForSetEmergencyMode(phone0, E_REG_RESULT);
+
+ // First trial
+ CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(phone0,
+ mTestConnection1, false);
+ processAllMessages();
+
+ assertTrue(emergencyStateTracker.isInEmergencyMode());
+ assertTrue(emergencyStateTracker.isInEmergencyCall());
+ verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
+ emergencyStateTracker.endCall(mTestConnection1);
+ processAllMessages();
+
+ verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+ verify(phone0).exitEmergencyMode(msgCaptor.capture());
+
+ Message msg = msgCaptor.getValue();
+
+ assertNotNull(msg);
+
+ // Second trial
+ CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(phone0,
+ mTestConnection2, false);
+ processAllMessages();
+
+ assertFalse(future.isDone());
+ verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ AsyncResult.forMessage(msg, null, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+ }
+
+ @Test
+ @SmallTest
+ public void testEnsureExecutionOrderOfExitEmergencyModeThenSetEmergencyModeWithSms() {
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ false,
+ /* isRadioOn= */ true);
+ setUpAsyncResultForSetEmergencyMode(phone0, E_REG_RESULT);
+ CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone0,
+ TEST_SMS_ID, false);
+ processAllMessages();
+
+ assertTrue(emergencyStateTracker.isInEmergencyMode());
+ verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ assertTrue(emergencyStateTracker.getEmergencyRegistrationResult().equals(E_REG_RESULT));
+ // Expect: DisconnectCause#NOT_DISCONNECTED.
+ assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
+ Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
+
+ ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_CS);
+
+ verify(phone0).exitEmergencyMode(msgCaptor.capture());
+
+ Message msg = msgCaptor.getValue();
+
+ assertNotNull(msg);
+
+ // Dial emergency call
+ future = emergencyStateTracker.startEmergencyCall(phone0,
+ mTestConnection2, false);
+ processAllMessages();
+
+ assertFalse(future.isDone());
+ verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ AsyncResult.forMessage(msg, null, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+ }
+
private EmergencyStateTracker setupEmergencyStateTracker(
boolean isSuplDdsSwitchRequiredForEmergencyCall) {
doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();