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

Commit 6e8ea539 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 13222886 from 73c4f11c to 25Q2-release

Change-Id: I42adbb2d06bcebea2f923df3666b77ba7f15261f
parents 744cae8c 73c4f11c
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -71,3 +71,14 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

# OWNER=hwangoo TARGET=25Q2
flag {
    name: "perform_cross_stack_redial_check_for_emergency_call"
    namespace: "telephony"
    description: "This flag performs a quick cross stack redial if the subscription is being invalid and an exception occurs, while an emergency call is in progress."
    bug:"389190613"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+26 −8
Original line number Diff line number Diff line
@@ -312,8 +312,24 @@ public class EmergencyStateTracker {
                    maybeNotifyTransportChangeCompleted(emergencyType, false);

                    if (emergencyType == EMERGENCY_TYPE_CALL) {
                        // If the emergency registration result(mLastEmergencyRegistrationResult) is
                        // null, it means that the emergency mode is not set properly on the modem.
                        // Therefore, based on the emergency registration result and current
                        // subscription status, the current phone is not available for an emergency
                        // call, so we check if an emergency call is possible through cross stack.
                        if (mFeatureFlags.performCrossStackRedialCheckForEmergencyCall()
                                && mLastEmergencyRegistrationResult == null
                                && mPhone != null
                                && !SubscriptionManager.isValidSubscriptionId(mPhone.getSubId())
                                && needToSwitchPhone(mPhone)) {
                            Rlog.i(TAG, "setEmergencyMode failed: need to switch stacks.");
                            mEmergencyMode = MODE_EMERGENCY_NONE;
                            completeEmergencyMode(emergencyType,
                                    DisconnectCause.EMERGENCY_PERM_FAILURE);
                        } else {
                            setIsInEmergencyCall(true);
                            completeEmergencyMode(emergencyType);
                        }

                        // Case 1) When the emergency call is setting the emergency mode and
                        // the emergency SMS is being sent, completes the SMS future also.
@@ -861,23 +877,25 @@ public class EmergencyStateTracker {

    private void completeEmergencyMode(@EmergencyType int emergencyType,
            @DisconnectCauses int result) {
        CompletableFuture<Integer> emergencyModeFuture = null;

        if (emergencyType == EMERGENCY_TYPE_CALL) {
            if (mCallEmergencyModeFuture != null && !mCallEmergencyModeFuture.isDone()) {
                mCallEmergencyModeFuture.complete(result);
            }
            emergencyModeFuture = mCallEmergencyModeFuture;

            if (result != DisconnectCause.NOT_DISCONNECTED) {
                clearEmergencyCallInfo();
            }
        } else if (emergencyType == EMERGENCY_TYPE_SMS) {
            if (mSmsEmergencyModeFuture != null && !mSmsEmergencyModeFuture.isDone()) {
                mSmsEmergencyModeFuture.complete(result);
            }
            emergencyModeFuture = mSmsEmergencyModeFuture;

            if (result != DisconnectCause.NOT_DISCONNECTED) {
                clearEmergencySmsInfo();
            }
        }

        if (emergencyModeFuture != null && !emergencyModeFuture.isDone()) {
            emergencyModeFuture.complete(result);
        }
    }

    /**
+4 −2
Original line number Diff line number Diff line
@@ -828,7 +828,9 @@ public class ContextFixture implements TestFixture<Context> {
        lenient().doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt(),
                anyString());
        lenient().doAnswer(invocation -> mNetworkId++).when(mNetwork).getNetId();
        lenient().doReturn(mNetwork).when(mConnectivityManager).registerNetworkAgent(
        lenient().doReturn(
                ConnectivityManager.MockHelpers.registerNetworkAgentResult(mNetwork, null))
                        .when(mConnectivityManager).registerNetworkAgent(
                                any(), any(), any(), any(), any(), any(), anyInt());

        lenient().doReturn(true).when(mEuiccManager).isEnabled();
+89 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.telephony.NetworkRegistrationInfo.DOMAIN_CS;
import static android.telephony.NetworkRegistrationInfo.DOMAIN_CS_PS;
import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING;
import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL;
import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS;

@@ -74,10 +75,12 @@ import androidx.test.filters.SmallTest;

import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.GsmCdmaPhone;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.PhoneSwitcher;
@@ -107,6 +110,12 @@ public class EmergencyStateTrackerTest extends TelephonyTest {
    private static final int TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS = 3000;
    private static final EmergencyRegistrationResult E_REG_RESULT = new EmergencyRegistrationResult(
            EUTRAN, REGISTRATION_STATE_HOME, DOMAIN_CS_PS, true, true, 0, 1, "001", "01", "US");
    private static final EmergencyRegistrationResult UNKNOWN_E_REG_RESULT =
            new EmergencyRegistrationResult(
                    AccessNetworkConstants.AccessNetworkType.UNKNOWN,
                    REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
                    NetworkRegistrationInfo.DOMAIN_UNKNOWN,
                    false, false, 0, 0, "", "", "");

    @Mock EmergencyStateTracker.PhoneFactoryProxy mPhoneFactoryProxy;
    @Mock EmergencyStateTracker.PhoneSwitcherProxy mPhoneSwitcherProxy;
@@ -125,6 +134,7 @@ public class EmergencyStateTrackerTest extends TelephonyTest {
                .when(mTelephonyManagerProxy).getSimState(anyInt());
        doReturn(true).when(mFeatureFlags).emergencyCallbackModeNotification();
        doReturn(true).when(mFeatureFlags).disableEcbmBasedOnRat();
        doReturn(true).when(mFeatureFlags).performCrossStackRedialCheckForEmergencyCall();
    }

    @After
@@ -3491,6 +3501,74 @@ public class EmergencyStateTrackerTest extends TelephonyTest {
        verify(phone1, never()).setEmergencyMode(anyInt(), any(Message.class));
    }

    @Test
    @SmallTest
    public void testSwitchPhoneWhenNonEmergencyNtnSessionInProgress() {
        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
        Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
                /* isRadioOn= */ true);
        setUpAsyncResultForSetEmergencyMode(
                phone0, UNKNOWN_E_REG_RESULT, RILConstants.INTERNAL_ERR);
        // Start an emergency call over Phone0
        CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(phone0,
                mTestConnection1, false);

        Phone phone1 = getPhone(1);
        // Phone0: Disable NTN
        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
                .when(phone0).getSubId();
        doReturn(TelephonyManager.SIM_STATE_ABSENT)
                .when(mTelephonyManagerProxy).getSimState(eq(0));
        // Phone1: Enable TN
        doReturn(2).when(phone1).getSubId();
        doReturn(TelephonyManager.SIM_STATE_READY)
                .when(mTelephonyManagerProxy).getSimState(eq(1));

        processAllMessages();

        verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
        assertFalse(emergencyStateTracker.isInEmergencyMode());
        assertTrue(future.isDone());
        // Expect: DisconnectCause#EMERGENCY_PERM_FAILURE
        assertEquals(future.getNow(DisconnectCause.NOT_DISCONNECTED),
                Integer.valueOf(DisconnectCause.EMERGENCY_PERM_FAILURE));
    }

    @Test
    @SmallTest
    public void testSwitchPhoneWhenNonEmergencyNtnSessionInProgressAndFlagDisabled() {
        doReturn(false).when(mFeatureFlags).performCrossStackRedialCheckForEmergencyCall();
        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
        Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
                /* isRadioOn= */ true);
        setUpAsyncResultForSetEmergencyMode(
                phone0, UNKNOWN_E_REG_RESULT, RILConstants.INTERNAL_ERR);
        // Start an emergency call over Phone0
        CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(phone0,
                mTestConnection1, false);

        Phone phone1 = getPhone(1);
        // Phone0: Disable NTN
        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
                .when(phone0).getSubId();
        doReturn(TelephonyManager.SIM_STATE_ABSENT)
                .when(mTelephonyManagerProxy).getSimState(eq(0));
        // Phone1: Enable TN
        doReturn(2).when(phone1).getSubId();
        doReturn(TelephonyManager.SIM_STATE_READY)
                .when(mTelephonyManagerProxy).getSimState(eq(1));

        processAllMessages();

        verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
        assertTrue(future.isDone());
        // Expect: DisconnectCause#NOT_DISCONNECTED
        assertEquals(future.getNow(DisconnectCause.NOT_DISCONNECTED),
                Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
    }

    private EmergencyStateTracker setupEmergencyStateTracker(
            boolean isSuplDdsSwitchRequiredForEmergencyCall) {
        doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();
@@ -3571,6 +3649,17 @@ public class EmergencyStateTrackerTest extends TelephonyTest {
        }).when(phone).setEmergencyMode(anyInt(), any(Message.class));
    }

    private void setUpAsyncResultForSetEmergencyMode(Phone phone,
            EmergencyRegistrationResult regResult, int rilError) {
        doAnswer((invocation) -> {
            Object[] args = invocation.getArguments();
            final Message msg = (Message) args[1];
            AsyncResult.forMessage(msg, regResult, CommandException.fromRilErrno(rilError));
            msg.sendToTarget();
            return null;
        }).when(phone).setEmergencyMode(anyInt(), any(Message.class));
    }

    private void setUpAsyncResultForExitEmergencyMode(Phone phone) {
        doAnswer((invocation) -> {
            Object[] args = invocation.getArguments();