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

Commit d8a44ba0 authored by Jack Yu's avatar Jack Yu Committed by Automerger Merge Worker
Browse files

Fixed IWLAN handover issues am: b4d5eaf6

Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/2032390

Change-Id: I5f868d737ad9e020620b73743d1bdf52870a6c8b
parents f8cbf271 b4d5eaf6
Loading
Loading
Loading
Loading
+36 −16
Original line number Diff line number Diff line
@@ -883,6 +883,8 @@ public class DataNetwork extends StateMachine {
    private final class ConnectedState extends State {
        @Override
        public void enter() {
            // Note that reaching here could mean from connecting -> connected, or from
            // handover -> connected.
            if (!mEverConnected) {
                // Transited from ConnectingState
                log("network connected.");
@@ -895,20 +897,13 @@ public class DataNetwork extends StateMachine {
                mQosCallbackTracker.updateSessions(mQosBearerSessions);
                mKeepaliveTracker = new KeepaliveTracker(mPhone,
                        getHandler().getLooper(), DataNetwork.this, mNetworkAgent);
                if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
                    registerForWwanEvents();
                }
            }

            notifyPreciseDataConnectionState();
            updateSuspendState();

            if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
                // Reaching here means
                // 1. The network was first time connected on cellular.
                // 2. The network handover successfully from IWLAN to cellular.
                // 3. The network failed to handover to IWLAN and re-entered connected state.
                // TODO: Correctly support (3) later. We do not need to perform the following works.
                registerForBandwidthUpdate();
                mKeepaliveTracker.registerForKeepaliveStatus();
            }
        }

        @Override
@@ -1057,6 +1052,24 @@ public class DataNetwork extends StateMachine {
        }
    }

    /**
     * Register for events that can only happen on cellular networks.
     */
    private void registerForWwanEvents() {
        registerForBandwidthUpdate();
        mKeepaliveTracker.registerForKeepaliveStatus();
        // Todo: Register for PCO events.
    }

    /**
     * Unregister for events that can only happen on cellular networks.
     */
    private void unregisterForWwanEvents() {
        unregisterForBandwidthUpdate();
        mKeepaliveTracker.unregisterForKeepaliveStatus();
        // Todo: Unregister for PCO events.
    }

    @Override
    protected void unhandledMessage(Message msg) {
        IState state = getCurrentState();
@@ -1521,8 +1534,8 @@ public class DataNetwork extends StateMachine {
            @Nullable DataCallResponse response) {
        logl("onSetupResponse: resultCode=" + DataServiceCallback.resultCodeToString(resultCode)
                + ", response=" + response);
        int failCause = getFailCauseFromDataCallResponse(resultCode, response);
        if (failCause == DataFailCause.NONE) {
        mFailCause = getFailCauseFromDataCallResponse(resultCode, response);
        if (mFailCause == DataFailCause.NONE) {
            updateDataNetwork(response);

            // TODO: Check if the cid already exists. If yes, should notify DNC and let it force
@@ -1553,7 +1566,7 @@ public class DataNetwork extends StateMachine {
            NetworkRequestList requestList = new NetworkRequestList(mAttachedNetworkRequestList);
            mDataNetworkCallback.invokeFromExecutor(()
                    -> mDataNetworkCallback.onSetupDataFailed(
                            DataNetwork.this, requestList, failCause, retryDelayMillis));
                            DataNetwork.this, requestList, mFailCause, retryDelayMillis));
            transitionTo(mDisconnectedState);
        }
    }
@@ -2092,14 +2105,21 @@ public class DataNetwork extends StateMachine {
            @Nullable DataCallResponse response, @Nullable DataHandoverRetryEntry retryEntry) {
        logl("onHandoverResponse: resultCode=" + DataServiceCallback.resultCodeToString(resultCode)
                + ", response=" + response);
        int failCause = getFailCauseFromDataCallResponse(resultCode, response);
        if (failCause == DataFailCause.NONE) {
        mFailCause = getFailCauseFromDataCallResponse(resultCode, response);
        if (mFailCause == DataFailCause.NONE) {
            // Clean up on the source transport.
            mDataServiceManagers.get(mTransport).deactivateDataCall(mCid.get(mTransport),
                    DataService.REQUEST_REASON_HANDOVER, null);
            // Switch the transport to the target.
            mTransport = DataUtils.getTargetTransport(mTransport);
            updateDataNetwork(response);
            if (mTransport != AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
                // Handover from WWAN to WLAN
                unregisterForWwanEvents();
            } else {
                // Handover from WLAN to WWAN
                registerForWwanEvents();
            }
            if (retryEntry != null) retryEntry.setState(DataRetryEntry.RETRY_STATE_SUCCEEDED);
            mDataNetworkCallback.invokeFromExecutor(
                    () -> mDataNetworkCallback.onHandoverSucceeded(DataNetwork.this));
@@ -2112,7 +2132,7 @@ public class DataNetwork extends StateMachine {
            if (retryEntry != null) retryEntry.setState(DataRetryEntry.RETRY_STATE_FAILED);
            mDataNetworkCallback.invokeFromExecutor(
                    () -> mDataNetworkCallback.onHandoverFailed(DataNetwork.this,
                            failCause, retry, handoverFailureMode));
                            mFailCause, retry, handoverFailureMode));
        }

        // No matter handover succeeded or not, transit back to connected state.
+79 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;

import java.net.InetAddress;
import java.util.ArrayList;
@@ -202,6 +203,8 @@ public class DataNetworkTest extends TelephonyTest {
        doReturn(true).when(mSST).isConcurrentVoiceAndDataAllowed();
        doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager)
                .getPreferredTransportByNetworkCapability(anyInt());
        doReturn(DataNetwork.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR)
                .when(mDataConfigManager).getBandwidthEstimateSource();
    }

    @After
@@ -425,4 +428,80 @@ public class DataNetworkTest extends TelephonyTest {
        assertThat(pdcsList.get(3).getTransportType())
                .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
    }

    @Test
    public void testHandover() {
        testCreateDataNetwork();

        setSuccessfulSetupDataResponse(mMockedWlanDataServiceManager, 456);
        // Now handover to IWLAN
        mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, null);
        processAllMessages();

        verify(mLinkBandwidthEstimator).unregisterForBandwidthChanged(
                eq(mDataNetworkUT.getHandler()));
        assertThat(mDataNetworkUT.getTransport())
                .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
        assertThat(mDataNetworkUT.getId()).isEqualTo(456);
        verify(mDataNetworkCallback).onHandoverSucceeded(eq(mDataNetworkUT));

        ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
                ArgumentCaptor.forClass(PreciseDataConnectionState.class);
        verify(mPhone, times(4)).notifyDataConnection(pdcsCaptor.capture());
        List<PreciseDataConnectionState> pdcsList = pdcsCaptor.getAllValues();

        assertThat(pdcsList).hasSize(4);
        assertThat(pdcsList.get(0).getState()).isEqualTo(TelephonyManager.DATA_CONNECTING);
        assertThat(pdcsList.get(1).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED);
        assertThat(pdcsList.get(2).getState())
                .isEqualTo(TelephonyManager.DATA_HANDOVER_IN_PROGRESS);
        assertThat(pdcsList.get(3).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED);

        // Now handover back to cellular
        Mockito.clearInvocations(mDataNetworkCallback);
        Mockito.clearInvocations(mLinkBandwidthEstimator);
        mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, null);
        processAllMessages();

        verify(mLinkBandwidthEstimator).registerForBandwidthChanged(
                eq(mDataNetworkUT.getHandler()), anyInt(), eq(null));
        assertThat(mDataNetworkUT.getTransport())
                .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        assertThat(mDataNetworkUT.getId()).isEqualTo(123);
        verify(mDataNetworkCallback).onHandoverSucceeded(eq(mDataNetworkUT));
    }

    @Test
    public void testHandoverFailed() {
        testCreateDataNetwork();

        setFailedSetupDataResponse(mMockedWlanDataServiceManager,
                DataServiceCallback.RESULT_ERROR_TEMPORARILY_UNAVAILABLE);
        // Now attempt to handover to IWLAN but fail it.
        mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, null);
        processAllMessages();

        verify(mDataNetworkCallback).onHandoverFailed(eq(mDataNetworkUT),
                eq(DataFailCause.SERVICE_TEMPORARILY_UNAVAILABLE), eq(-1L),
                eq(DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY));
        verify(mLinkBandwidthEstimator, never()).unregisterForBandwidthChanged(
                eq(mDataNetworkUT.getHandler()));
        assertThat(mDataNetworkUT.getTransport())
                .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        assertThat(mDataNetworkUT.getId()).isEqualTo(123);

        ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
                ArgumentCaptor.forClass(PreciseDataConnectionState.class);
        verify(mPhone, times(4)).notifyDataConnection(pdcsCaptor.capture());
        List<PreciseDataConnectionState> pdcsList = pdcsCaptor.getAllValues();

        assertThat(pdcsList).hasSize(4);
        assertThat(pdcsList.get(0).getState()).isEqualTo(TelephonyManager.DATA_CONNECTING);
        assertThat(pdcsList.get(1).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED);
        assertThat(pdcsList.get(2).getState())
                .isEqualTo(TelephonyManager.DATA_HANDOVER_IN_PROGRESS);
        assertThat(pdcsList.get(3).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED);
        assertThat(pdcsList.get(3).getLastCauseCode())
                .isEqualTo(DataFailCause.SERVICE_TEMPORARILY_UNAVAILABLE);
    }
}