Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b2363308 authored by Hunsuk Choi's avatar Hunsuk Choi
Browse files

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
parent f18e5a00
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -354,11 +354,26 @@ public class EmergencyStateTracker {
                            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 @@ public class EmergencyStateTracker {
            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);

+88 −0
Original line number Diff line number Diff line
@@ -2837,6 +2837,94 @@ public class EmergencyStateTrackerTest extends TelephonyTest {
        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();