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

Commit 60627011 authored by Jack Yu's avatar Jack Yu
Browse files

Fix race condition in data network

When data network is created, there is a window that
network capabilities are not created immediately. When data
network controller checks if the existing network can satisfied
the new network reuqest, this newly created network does not
have correct capabilities for data network controller to check.

Fixed by calling the update network capability method in data
network's constructor.

Fix: 229350075
Test: Manual && atest FrameworksTelephonyTests
Change-Id: I8dfd8a7e747d7dd21508e204239e81d285d3ae7f
parent 0415c5b2
Loading
Loading
Loading
Loading
+17 −9
Original line number Diff line number Diff line
@@ -801,6 +801,11 @@ public class DataNetwork extends StateMachine {
            @NonNull DataAllowedReason dataAllowedReason,
            @NonNull DataNetworkCallback callback) {
        super("DataNetwork", looper);
        // State machine should be initialized at the top of constructor. log() can be only used
        // after state machine initialized (because getCurrentState() crashes if state machine has
        // not started.)
        initializeStateMachine();

        mPhone = phone;
        mSubId = phone.getSubId();
        mRil = mPhone.mCi;
@@ -838,6 +843,17 @@ public class DataNetwork extends StateMachine {
            networkRequest.setState(TelephonyNetworkRequest.REQUEST_STATE_SATISFIED);
        }

        // Update the capabilities in the constructor is to make sure the data network has initial
        // capability immediately after created. Doing this connecting state creates the window that
        // DataNetworkController might check if existing data network's capability can satisfy the
        // next network request within this window.
        updateNetworkCapabilities();
    }

    /**
     * Initialize and start the state machine.
     */
    private void initializeStateMachine() {
        addState(mDefaultState);
        addState(mConnectingState, mDefaultState);
        addState(mConnectedState, mDefaultState);
@@ -845,13 +861,7 @@ public class DataNetwork extends StateMachine {
        addState(mDisconnectingState, mDefaultState);
        addState(mDisconnectedState, mDefaultState);
        setInitialState(mConnectingState);

        /**
         * This will trigger {@link DefaultState#enter()}, and then {@link ConnectingState#enter()}.
         * Check {@link StateMachine} class to see how Android state machine works.
         */
        start();
        // Do not add more stuffs here.
    }

    /**
@@ -1050,8 +1060,6 @@ public class DataNetwork extends StateMachine {
        public void enter() {
            sendMessageDelayed(EVENT_STUCK_IN_TRANSIENT_STATE,
                    mDataConfigManager.getAnomalyNetworkConnectingTimeoutMs());
            // Need to calculate the initial capabilities before creating the network agent.
            updateNetworkCapabilities();
            mNetworkAgent = createNetworkAgent();
            mInitialNetworkAgentId = mNetworkAgent.getId();
            mLogTag = "DN-" + mInitialNetworkAgentId + "-"
@@ -1804,8 +1812,8 @@ public class DataNetwork extends StateMachine {
            // This is the first time when network capabilities is created. The agent is not created
            // at this time. Just return here. The network capabilities will be used when network
            // agent is created.
            log("Initial capabilities " + mNetworkCapabilities);
            mNetworkCapabilities = nc;
            logl("Initial capabilities " + mNetworkCapabilities);
            return;
        }

+17 −0
Original line number Diff line number Diff line
@@ -976,4 +976,21 @@ public class DataNetworkTest extends TelephonyTest {
        assertThat(networkAgentConfig.legacySubType).isEqualTo(TelephonyManager.NETWORK_TYPE_LTE);
        assertThat(networkAgentConfig.skip464xlat).isTrue();
    }

    @Test
    public void testDataNetworkHasCapabilitiesAtBeginning() {
        DataNetworkController.NetworkRequestList
                networkRequestList = new DataNetworkController.NetworkRequestList();
        networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .build(), mPhone));
        mDataNetworkUT = new DataNetwork(mPhone, Looper.myLooper(), mDataServiceManagers,
                mInternetDataProfile, networkRequestList,
                AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                DataAllowedReason.NORMAL, mDataNetworkCallback);
        NetworkCapabilities caps = mDataNetworkUT.getNetworkCapabilities();
        assertThat(caps).isNotNull();
        assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)).isTrue();
        assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)).isTrue();
    }
}