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

Commit 3cfa5c66 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I832ddcc8,Id54258d0 into tm-dev

* changes:
  Fixed a crash when data network does not have PCO
  Fixed a race condition for early arrived PCO data
parents 0a6dbf64 06c7cada
Loading
Loading
Loading
Loading
+54 −35
Original line number Diff line number Diff line
@@ -628,10 +628,10 @@ public class DataNetwork extends StateMachine {
    private @NonNull DataAllowedReason mDataAllowedReason;

    /**
     * PCO (Protocol Configuration Options) data received from the network. Key is the PCO id, value
     * is the PCO content.
     * PCO (Protocol Configuration Options) data received from the network. The first key is the
     * cid of the PCO data, the second key is the PCO id, the value is the PCO data.
     */
    private final @NonNull Map<Integer, PcoData> mPcoData = new ArrayMap<>();
    private final @NonNull Map<Integer, Map<Integer, PcoData>> mPcoData = new ArrayMap<>();

    /** The QOS bearer sessions. */
    private final @NonNull List<QosBearerSession> mQosBearerSessions = new ArrayList<>();
@@ -983,6 +983,7 @@ public class DataNetwork extends StateMachine {
        public void enter() {
            logv("Registering all events.");
            mDataConfigManager.registerForConfigUpdate(getHandler(), EVENT_DATA_CONFIG_UPDATED);
            mRil.registerForPcoData(getHandler(), EVENT_PCO_DATA_RECEIVED, null);
            mPhone.getDisplayInfoController().registerForTelephonyDisplayInfoChanged(
                    getHandler(), EVENT_DISPLAY_INFO_CHANGED, null);
            mPhone.getServiceStateTracker().registerForServiceStateChanged(getHandler(),
@@ -1035,6 +1036,7 @@ public class DataNetwork extends StateMachine {
            mPhone.getDisplayInfoController().unregisterForTelephonyDisplayInfoChanged(
                    getHandler());
            mDataConfigManager.unregisterForConfigUpdate(getHandler());
            mRil.unregisterForPcoData(getHandler());
        }

        @Override
@@ -1081,9 +1083,13 @@ public class DataNetwork extends StateMachine {
                    updateNetworkCapabilities();
                    break;
                }
                case EVENT_PCO_DATA_RECEIVED: {
                    AsyncResult ar = (AsyncResult) msg.obj;
                    onPcoDataReceived((PcoData) ar.result);
                    break;
                }
                case EVENT_BANDWIDTH_ESTIMATE_FROM_MODEM_CHANGED:
                case EVENT_TEAR_DOWN_NETWORK:
                case EVENT_PCO_DATA_RECEIVED:
                case EVENT_STUCK_IN_TRANSIENT_STATE:
                case EVENT_DISPLAY_INFO_CHANGED:
                case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET:
@@ -1162,7 +1168,6 @@ public class DataNetwork extends StateMachine {
                    break;
                case EVENT_START_HANDOVER:
                case EVENT_TEAR_DOWN_NETWORK:
                case EVENT_PCO_DATA_RECEIVED:
                case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET:
                    // Defer the request until connected or disconnected.
                    log("Defer message " + eventToString(msg.what));
@@ -1229,6 +1234,13 @@ public class DataNetwork extends StateMachine {
                }
            }

            // If we've ever received PCO data before connected, now it's the time to
            // process it.
            mPcoData.getOrDefault(mCid.get(mTransport), Collections.emptyMap())
                    .forEach((pcoId, pcoData) -> {
                        onPcoDataChanged(pcoData);
                    });

            notifyPreciseDataConnectionState();
            updateSuspendState();
        }
@@ -1279,10 +1291,6 @@ public class DataNetwork extends StateMachine {
                case EVENT_SUBSCRIPTION_PLAN_OVERRIDE:
                    updateMeteredAndCongested();
                    break;
                case EVENT_PCO_DATA_RECEIVED:
                    ar = (AsyncResult) msg.obj;
                    onPcoDataReceived((PcoData) ar.result);
                    break;
                case EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE:
                    int resultCode = msg.arg1;
                    onDeactivateResponse(resultCode);
@@ -1353,10 +1361,6 @@ public class DataNetwork extends StateMachine {
                    onHandoverResponse(resultCode, dataCallResponse,
                            (DataHandoverRetryEntry) msg.obj);
                    break;
                case EVENT_PCO_DATA_RECEIVED:
                    AsyncResult ar = (AsyncResult) msg.obj;
                    onPcoDataReceived((PcoData) ar.result);
                    break;
                case EVENT_STUCK_IN_TRANSIENT_STATE:
                    reportAnomaly("Data service did not respond the handover request within "
                            + TimeUnit.MILLISECONDS.toSeconds(
@@ -1545,7 +1549,6 @@ public class DataNetwork extends StateMachine {
    private void registerForWwanEvents() {
        registerForBandwidthUpdate();
        mKeepaliveTracker.registerForKeepaliveStatus();
        mRil.registerForPcoData(this.getHandler(), EVENT_PCO_DATA_RECEIVED, null);
    }

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

    @Override
@@ -3111,8 +3113,6 @@ public class DataNetwork extends StateMachine {
            mDataProfile = mHandoverDataProfile;
            updateDataNetwork(response);
            if (mTransport != AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
                // Handover from WWAN to WLAN
                mPcoData.clear();
                unregisterForWwanEvents();
            } else {
                // Handover from WLAN to WWAN
@@ -3139,15 +3139,12 @@ public class DataNetwork extends StateMachine {
    }

    /**
     * Called when receiving PCO (Protocol Configuration Options) data from the cellular network.
     * Called when PCO data changes.
     *
     * @param pcoData PCO data.
     * @param pcoData The PCO data.
     */
    private void onPcoDataReceived(@NonNull PcoData pcoData) {
        if (pcoData.cid != getId()) return;
        PcoData oldData = mPcoData.put(pcoData.pcoId, pcoData);
        if (!Objects.equals(oldData, pcoData)) {
            log("onPcoDataReceived: " + pcoData);
    private void onPcoDataChanged(@NonNull PcoData pcoData) {
        log("onPcoDataChanged: " + pcoData);
        mDataNetworkCallback.invokeFromExecutor(
                () -> mDataNetworkCallback.onPcoDataChanged(DataNetwork.this));
        if (mDataProfile.getApnSetting() != null) {
@@ -3162,13 +3159,35 @@ public class DataNetwork extends StateMachine {
            }
        }
    }

    /**
     * Called when receiving PCO (Protocol Configuration Options) data from the cellular network.
     *
     * @param pcoData PCO data.
     */
    private void onPcoDataReceived(@NonNull PcoData pcoData) {
        // Save all the PCO data received, even though it might be unrelated to this data network.
        // The network might be still in connecting state. Save all now and use it when entering
        // connected state.
        log("onPcoDataReceived: " + pcoData);
        PcoData oldData = mPcoData.computeIfAbsent(pcoData.cid, m -> new ArrayMap<>())
                .put(pcoData.pcoId, pcoData);
        if (getId() == INVALID_CID || pcoData.cid != getId()) return;
        if (!Objects.equals(oldData, pcoData)) {
            onPcoDataChanged(pcoData);
        }
    }

    /**
     * @return The PCO data received from the network.
     * @return The PCO data map of the network. The key is the PCO id, the value is the PCO data.
     * An empty map if PCO data is not available (or when the network is on IWLAN).
     */
    public @NonNull Map<Integer, PcoData> getPcoData() {
        return mPcoData;
        if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
                || mCid.get(mTransport) == INVALID_CID) {
            return Collections.emptyMap();
        }
        return mPcoData.getOrDefault(mCid.get(mTransport), Collections.emptyMap());
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -3005,7 +3005,7 @@ public class DataNetworkController extends Handler {
            }

            if (nrAdvancedCapableByPco != mNrAdvancedCapableByPco) {
                log("onPcoDataChanged: mNrAdvancedCapableByPco = " + mNrAdvancedCapableByPco);
                log("onPcoDataChanged: mNrAdvancedCapableByPco = " + nrAdvancedCapableByPco);
                mNrAdvancedCapableByPco = nrAdvancedCapableByPco;
                mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor(
                        () -> callback.onNrAdvancedCapableByPcoChanged(mNrAdvancedCapableByPco)));
+70 −0
Original line number Diff line number Diff line
@@ -2341,6 +2341,76 @@ public class DataNetworkControllerTest extends TelephonyTest {
        verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(false));
    }

    @Test
    public void testNrAdvancedByEarlyPco() {
        Mockito.reset(mMockedWwanDataServiceManager);
        mDataNetworkControllerUT.addNetworkRequest(
                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
        processAllMessages();

        // PCO data arrives before data network entering connected state.
        mSimulatedCommands.triggerPcoData(1, "IPV6", 1234, new byte[]{1});
        processAllMessages();

        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
        verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class),
                anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(),
                messageCaptor.capture());

        // Send setup data call complete message.
        Message msg = messageCaptor.getValue();
        msg.getData().putParcelable("data_call_response",
                createDataCallResponse(1, DataCallResponse.LINK_STATUS_ACTIVE));
        msg.arg1 = DataServiceCallback.RESULT_SUCCESS;
        msg.sendToTarget();
        processAllMessages();

        verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(true));
    }

    @Test
    public void testNrAdvancedByPcoMultipleNetworks() throws Exception {
        testSetupDataNetwork();
        setSuccessfulSetupDataResponse(mMockedDataServiceManagers
                .get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), 2);
        testSetupImsDataNetwork();

        verify(mMockedDataNetworkControllerCallback, never())
                .onNrAdvancedCapableByPcoChanged(anyBoolean());
        mSimulatedCommands.triggerPcoData(2, "IPV6", 1234, new byte[]{1});
        processAllMessages();
        verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(true));
    }

    @Test
    public void testNrAdvancedByEarlyUnrelatedPco() {
        Mockito.reset(mMockedWwanDataServiceManager);
        mDataNetworkControllerUT.addNetworkRequest(
                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
        processAllMessages();

        // Unrelated PCO data arrives before data network entering connected state.
        mSimulatedCommands.triggerPcoData(2, "IPV6", 1234, new byte[]{1});
        processAllMessages();

        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
        verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class),
                anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(),
                messageCaptor.capture());

        // Send setup data call complete message.
        Message msg = messageCaptor.getValue();
        msg.getData().putParcelable("data_call_response",
                createDataCallResponse(1, DataCallResponse.LINK_STATUS_ACTIVE));
        msg.arg1 = DataServiceCallback.RESULT_SUCCESS;
        msg.sendToTarget();
        processAllMessages();

        verify(mMockedDataNetworkControllerCallback, never()).onNrAdvancedCapableByPcoChanged(
                anyBoolean());
    }


    @Test
    public void testSetupDataNetworkVcnManaged() throws Exception {
        // VCN managed