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

Commit 65998ac0 authored by Hunsuk Choi's avatar Hunsuk Choi
Browse files

Restart ECBM timer if a new emergerncy call is dialed while in ECBM

Bug: 316249944
Test: atest EmergencyStateTrackerTest
Change-Id: I607acf016fc3093583a1167861c1c3ace41d7cb5
parent a5281200
Loading
Loading
Loading
Loading
+39 −21
Original line number Diff line number Diff line
@@ -512,6 +512,17 @@ public class EmergencyStateTracker {
            if (isSamePhone(mPhone, phone) && (!mActiveEmergencyCalls.isEmpty() || isInEcm())) {
                mOngoingCallId = callId;
                mIsTestEmergencyNumber = isTestEmergencyNumber;
                // Ensure that domain selector requests scan.
                mLastEmergencyRegResult = new EmergencyRegResult(
                        AccessNetworkConstants.AccessNetworkType.UNKNOWN,
                        NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN,
                        NetworkRegistrationInfo.DOMAIN_UNKNOWN, false, false, 0, 0, "", "", "");
                if (isInEcm()) {
                    // Remove pending exit ECM runnable.
                    mHandler.removeCallbacks(mExitEcmRunnable);
                    releaseWakeLock();
                    ((GsmCdmaPhone) mPhone).notifyEcbmTimerReset(Boolean.TRUE);
                }
                return CompletableFuture.completedFuture(DisconnectCause.NOT_DISCONNECTED);
            }

@@ -578,8 +589,7 @@ public class EmergencyStateTracker {
                // If the emergency call was initiated during the emergency callback mode,
                // the emergency callback mode should be restored when the emergency call is ended.
                if (mActiveEmergencyCalls.isEmpty()) {
                    setEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, MODE_EMERGENCY_CALLBACK,
                            MSG_SET_EMERGENCY_CALLBACK_MODE_DONE);
                    enterEmergencyCallbackMode();
                }
            } else {
                exitEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, false);
@@ -960,6 +970,10 @@ public class EmergencyStateTracker {
                // ECBM (see ImsPhone#handleEnterEmergencyCallbackMode)
                ((GsmCdmaPhone) mPhone).notifyEmergencyCallRegistrants(true);
            }
        } else {
            // Inform to reset the ECBM timer.
            ((GsmCdmaPhone) mPhone).notifyEcbmTimerReset(Boolean.FALSE);
        }

        // Set emergency mode on modem.
        setEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, MODE_EMERGENCY_CALLBACK,
@@ -974,7 +988,6 @@ public class EmergencyStateTracker {
        // We don't want to go to sleep while in ECM.
        if (mWakeLock != null) mWakeLock.acquire(delayInMillis);
    }
    }

    /**
     * Exits emergency callback mode and notifies relevant listeners.
@@ -991,14 +1004,7 @@ public class EmergencyStateTracker {
            }

            // Release wakeLock.
            if (mWakeLock != null && mWakeLock.isHeld()) {
                try {
                    mWakeLock.release();
                } catch (Exception e) {
                    // Ignore the exception if the system has already released this WakeLock.
                    Rlog.d(TAG, "WakeLock already released: " + e.toString());
                }
            }
            releaseWakeLock();

            GsmCdmaPhone gsmCdmaPhone = (GsmCdmaPhone) mPhone;
            // Send intents that ECM has changed.
@@ -1016,6 +1022,18 @@ public class EmergencyStateTracker {
        mPhone = null;
    }

    private void releaseWakeLock() {
        // Release wakeLock.
        if (mWakeLock != null && mWakeLock.isHeld()) {
            try {
                mWakeLock.release();
            } catch (Exception e) {
                // Ignore the exception if the system has already released this WakeLock.
                Rlog.d(TAG, "WakeLock already released: " + e.toString());
            }
        }
    }

    /**
     * Exits emergency callback mode and triggers runnable after exit response is received.
     */
+162 −0
Original line number Diff line number Diff line
@@ -1956,6 +1956,168 @@ public class EmergencyStateTrackerTest extends TelephonyTest {
        assertFalse(testEst.isEmergencyCallbackModeSupported());
    }

    /**
     * Test that new emergency call is dialed while in emergency callback mode and completes.
     */
    @Test
    @SmallTest
    public void exitEmergencyCallbackMode_NewEmergencyCallDialedAndCompletes() {
        // Setup EmergencyStateTracker
        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
        // Create test Phone
        GsmCdmaPhone testPhone = (GsmCdmaPhone) setupTestPhoneForEmergencyCall(
                /* isRoaming= */ true, /* isRadioOn= */ true);
        setUpAsyncResultForSetEmergencyMode(testPhone, E_REG_RESULT);
        setUpAsyncResultForExitEmergencyMode(testPhone);
        // Start emergency call then enter ECM
        CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
                TEST_CALL_ID, false);
        processAllMessages();

        // Set call to ACTIVE
        emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, TEST_CALL_ID);
        emergencyStateTracker.onEmergencyCallDomainUpdated(
                PhoneConstants.PHONE_TYPE_IMS, TEST_CALL_ID);
        // Set ecm as supported
        setEcmSupportedConfig(testPhone, /* ecmSupported= */ true);
        // End call to enter ECM
        emergencyStateTracker.endCall(TEST_CALL_ID);
        processAllMessages();

        // verify ecbm states are correct
        assertTrue(emergencyStateTracker.isInEcm());
        assertTrue(emergencyStateTracker.isInImsEcm());
        assertFalse(emergencyStateTracker.isInCdmaEcm());

        // 2nd call while in emergency callback mode
        unused = emergencyStateTracker.startEmergencyCall(testPhone,
                TEST_CALL_ID, false);
        emergencyStateTracker.onEmergencyTransportChanged(
                EmergencyStateTracker.EMERGENCY_TYPE_CALL, MODE_EMERGENCY_WWAN);
        processAllMessages();
        processAllFutureMessages();

        // verify ecbm states are not changed.
        assertTrue(emergencyStateTracker.isInEcm());
        assertTrue(emergencyStateTracker.isInImsEcm());
        assertFalse(emergencyStateTracker.isInCdmaEcm());

        // Verify exitEmergencyMode() is not called.
        verify(testPhone, never()).exitEmergencyMode(any(Message.class));

        // Verify ECBM timer cancel.
        verify(testPhone).notifyEcbmTimerReset(eq(Boolean.TRUE));

        // Set call to ACTIVE
        emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, TEST_CALL_ID);
        emergencyStateTracker.onEmergencyCallDomainUpdated(
                PhoneConstants.PHONE_TYPE_IMS, TEST_CALL_ID);
        // End call to enter ECM
        emergencyStateTracker.endCall(TEST_CALL_ID);
        processAllMessages();

        // verify ecbm states are correct
        assertTrue(emergencyStateTracker.isInEcm());
        assertTrue(emergencyStateTracker.isInImsEcm());
        assertFalse(emergencyStateTracker.isInCdmaEcm());

        // Verify ECBM timer reset.
        verify(testPhone).notifyEcbmTimerReset(eq(Boolean.FALSE));

        // Verify exitEmergencyMode() is not called.
        verify(testPhone, never()).exitEmergencyMode(any(Message.class));

        processAllFutureMessages();

        // Ensure ECBM states are all correctly false after we exit.
        assertFalse(emergencyStateTracker.isInEcm());
        assertFalse(emergencyStateTracker.isInImsEcm());
        assertFalse(emergencyStateTracker.isInCdmaEcm());

        // Verify exitEmergencyMode() is called.
        verify(testPhone).exitEmergencyMode(any(Message.class));
    }

    /**
     * Test that new emergency call is dialed while in emergency callback mode and it fails.
     */
    @Test
    @SmallTest
    public void exitEmergencyCallbackMode_NewEmergencyCallDialedAndFails() {
        // Setup EmergencyStateTracker
        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
        // Create test Phone
        GsmCdmaPhone testPhone = (GsmCdmaPhone) setupTestPhoneForEmergencyCall(
                /* isRoaming= */ true, /* isRadioOn= */ true);
        setUpAsyncResultForSetEmergencyMode(testPhone, E_REG_RESULT);
        setUpAsyncResultForExitEmergencyMode(testPhone);
        // Start emergency call then enter ECM
        CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
                TEST_CALL_ID, false);
        processAllMessages();

        // Set call to ACTIVE
        emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, TEST_CALL_ID);
        emergencyStateTracker.onEmergencyCallDomainUpdated(
                PhoneConstants.PHONE_TYPE_IMS, TEST_CALL_ID);
        // Set ecm as supported
        setEcmSupportedConfig(testPhone, /* ecmSupported= */ true);
        // End call to enter ECM
        emergencyStateTracker.endCall(TEST_CALL_ID);
        processAllMessages();

        // verify ecbm states are correct
        assertTrue(emergencyStateTracker.isInEcm());
        assertTrue(emergencyStateTracker.isInImsEcm());
        assertFalse(emergencyStateTracker.isInCdmaEcm());

        // 2nd call while in emergency callback mode
        unused = emergencyStateTracker.startEmergencyCall(testPhone,
                TEST_CALL_ID, false);
        emergencyStateTracker.onEmergencyTransportChanged(
                EmergencyStateTracker.EMERGENCY_TYPE_CALL, MODE_EMERGENCY_WWAN);
        processAllMessages();
        processAllFutureMessages();

        // verify ecbm states are not changed.
        assertTrue(emergencyStateTracker.isInEcm());
        assertTrue(emergencyStateTracker.isInImsEcm());
        assertFalse(emergencyStateTracker.isInCdmaEcm());

        // Verify exitEmergencyMode() is not called.
        verify(testPhone, never()).exitEmergencyMode(any(Message.class));

        // Verify ECBM timer cancel.
        verify(testPhone).notifyEcbmTimerReset(eq(Boolean.TRUE));

        // End call to return to ECM
        emergencyStateTracker.endCall(TEST_CALL_ID);
        processAllMessages();

        // verify ecbm states are correct
        assertTrue(emergencyStateTracker.isInEcm());
        assertTrue(emergencyStateTracker.isInImsEcm());
        assertFalse(emergencyStateTracker.isInCdmaEcm());

        // Verify ECBM timer reset.
        verify(testPhone).notifyEcbmTimerReset(eq(Boolean.FALSE));

        // Verify exitEmergencyMode() is not called.
        verify(testPhone, never()).exitEmergencyMode(any(Message.class));

        processAllFutureMessages();

        // Ensure ECBM states are all correctly false after we exit.
        assertFalse(emergencyStateTracker.isInEcm());
        assertFalse(emergencyStateTracker.isInImsEcm());
        assertFalse(emergencyStateTracker.isInCdmaEcm());

        // Verify exitEmergencyMode() is called.
        verify(testPhone).exitEmergencyMode(any(Message.class));
    }

    private EmergencyStateTracker setupEmergencyStateTracker(
            boolean isSuplDdsSwitchRequiredForEmergencyCall) {
        doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();