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

Commit cb91adaa authored by Mengjun Leng's avatar Mengjun Leng Committed by Jack Yu
Browse files

Handle radio unavailable state properly

In case of connecting state, setup data call might be ignored because
data HAL service gets dead so that data network gets stuck in connecting
state for long time.

Fixed by handling radio unavailable event in default state if the data
network is on WWAN. Also added special handling if the data network is
in handover state.

Bug: 387056127
Test: atest DataNetworkTest
Test: Basic telephony functionality tests
Flag: EXEMPT bug fix

Change-Id: I0a18d82ea76fe7540888b4f4c14948b804c81d0d
parent 9f89dc83
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -1315,6 +1315,8 @@ public class DataNetwork extends StateMachine {
                mAccessNetworksManager.registerCallback(mAccessNetworksManagerCallback);
            }

            mRil.registerForNotAvailable(getHandler(), EVENT_RADIO_NOT_AVAILABLE, null);

            // Only add symmetric code here, for example, registering and unregistering.
            // DefaultState.enter() is the starting point in the life cycle of the DataNetwork,
            // and DefaultState.exit() is the end. For non-symmetric initializing works, put them
@@ -1355,6 +1357,7 @@ public class DataNetwork extends StateMachine {
                    .unregisterCallback(mDataSettingsManagerCallback);
            mRil.unregisterForPcoData(getHandler());
            mDataConfigManager.unregisterCallback(mDataConfigManagerCallback);
            mRil.unregisterForNotAvailable(getHandler());
        }

        @Override
@@ -1455,6 +1458,12 @@ public class DataNetwork extends StateMachine {
                            .transportTypeToString(msg.arg1) + " request.");
                    break;
                case EVENT_RADIO_NOT_AVAILABLE:
                    // Ignore this event when it isn't a WWAN data network.
                    if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
                        loge(eventToString(msg.what)
                                + ": ignored on IWLAN");
                        break;
                    }
                    mFailCause = DataFailCause.RADIO_NOT_AVAILABLE;
                    loge(eventToString(msg.what) + ": transition to disconnected state");
                    transitionTo(mDisconnectedState);
@@ -1878,6 +1887,19 @@ public class DataNetwork extends StateMachine {
                    log("Defer message " + eventToString(msg.what));
                    deferMessage(msg);
                    break;
                case EVENT_RADIO_NOT_AVAILABLE:
                    if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
                        // Defer the request until handover to IWLAN succeeds or fails.
                        log("Defer message " + eventToString(msg.what));
                        deferMessage(msg);
                    } else {
                        // If this is during handover to cellular, always tear down the network as
                        // we will never get success or failed response from the modem.
                        mFailCause = DataFailCause.RADIO_NOT_AVAILABLE;
                        loge(eventToString(msg.what) + ": transition to disconnected state");
                        transitionTo(mDisconnectedState);
                    }
                    break;
                case EVENT_NOTIFY_HANDOVER_STARTED_RESPONSE:
                    onStartHandover(msg.arg2, (DataHandoverRetryEntry) msg.obj);
                    break;
@@ -2054,7 +2076,6 @@ public class DataNetwork extends StateMachine {
    private void registerForWwanEvents() {
        registerForBandwidthUpdate();
        mKeepaliveTracker.registerForKeepaliveStatus();
        mRil.registerForNotAvailable(this.getHandler(), EVENT_RADIO_NOT_AVAILABLE, null);
    }

    /**
@@ -2063,7 +2084,6 @@ public class DataNetwork extends StateMachine {
    private void unregisterForWwanEvents() {
        unregisterForBandwidthUpdate();
        mKeepaliveTracker.unregisterForKeepaliveStatus();
        mRil.unregisterForNotAvailable(this.getHandler());
    }

    @Override
+73 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
@@ -1550,6 +1551,78 @@ public class DataNetworkTest extends TelephonyTest {
        assertThat(mDataNetworkUT.isConnected()).isFalse();
    }

    @Test
    public void testSetupDataCallOnRadioNotAvailable() throws Exception {
        NetworkRequestList networkRequestList = new NetworkRequestList();
        networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .build(), mPhone, mFeatureFlags));

        mDataNetworkUT = new DataNetwork(mPhone, mFeatureFlags, Looper.myLooper(),
        mDataServiceManagers, mInternetDataProfile, networkRequestList,
                AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                DataAllowedReason.NORMAL, mDataNetworkCallback);
        assertThat(mDataNetworkUT.isConnecting()).isTrue();

        mDataNetworkUT.sendMessage(4/*EVENT_RADIO_NOT_AVAILABLE*/);
        processAllMessages();

        assertThat(mDataNetworkUT.isConnected()).isFalse();
        verify(mDataNetworkCallback).onSetupDataFailed(eq(mDataNetworkUT), eq(
                networkRequestList), eq(DataFailCause.RADIO_NOT_AVAILABLE), anyLong());
    }

    @Test
    public void testHandoverToIwlanSuccessWithRadioNotAvailable() throws Exception {
        setupDataNetwork();

        setSuccessfulSetupDataResponse(mMockedWlanDataServiceManager, 456);
        TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
        replaceInstance(DataNetwork.class, "mNetworkAgent",
                mDataNetworkUT, mockNetworkAgent);
        // Now handover to IWLAN
        mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, null);
        mDataNetworkUT.sendMessage(4/*EVENT_RADIO_NOT_AVAILABLE*/);
        processAllMessages();

        assertThat(mDataNetworkUT.isConnected()).isTrue();
        assertThat(mDataNetworkUT.getTransport()).isEqualTo(
                AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
    }

    @Test
    public void testHandoverToIwlanFailedWithRadioNotAvailable() throws Exception {
        setupDataNetwork();

        setFailedSetupDataResponse(mMockedWlanDataServiceManager,
                DataServiceCallback.RESULT_ERROR_TEMPORARILY_UNAVAILABLE);

        TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
        replaceInstance(DataNetwork.class, "mNetworkAgent",
                mDataNetworkUT, mockNetworkAgent);
        // Now handover to IWLAN
        mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, null);
        mDataNetworkUT.sendMessage(4/*EVENT_RADIO_NOT_AVAILABLE*/);
        processAllMessages();

        assertThat(mDataNetworkUT.isConnected()).isFalse();
    }

    @Test
    public void testHandoverToCellularWithRadioNotAvailable() throws Exception {
        testCreateDataNetworkOnIwlan();

        TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
        replaceInstance(DataNetwork.class, "mNetworkAgent",
                mDataNetworkUT, mockNetworkAgent);
        // Now handover to IWLAN
        mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, null);
        mDataNetworkUT.sendMessage(4/*EVENT_RADIO_NOT_AVAILABLE*/);
        processAllMessages();

        assertThat(mDataNetworkUT.isConnected()).isFalse();
    }

    @Test
    public void testNetworkAgentConfig() throws Exception {
        createImsDataNetwork(false/*IsMmtel*/);