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

Commit 0985f946 authored by James Mattis's avatar James Mattis
Browse files

Updates to handler logic for multilayer requests

Updates to ConnectivityService network request handler's logic to support
(or disallow support of) multilayer network requests.

Bug: 175239920
Bug: 171991028
Test: atest FrameworksNetTests
atest NetworkStackTests
atest FrameworksNetIntegrationTests
atest NetworkStackIntegrationTests
atest CtsNetTestCasesLatestSdk

Change-Id: Ic67cff950d72745d6508a0a037bd33f932d5132c
parent 46ac0539
Loading
Loading
Loading
Loading
+73 −34
Original line number Diff line number Diff line
@@ -3513,42 +3513,63 @@ public class ConnectivityService extends IConnectivityManager.Stub
        return null;
    }

    private void handleRegisterNetworkRequestWithIntent(Message msg) {
    private void handleRegisterNetworkRequestWithIntent(@NonNull final Message msg) {
        final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);

        NetworkRequestInfo existingRequest = findExistingNetworkRequestInfo(nri.mPendingIntent);
        // handleRegisterNetworkRequestWithIntent() doesn't apply to multilayer requests.
        ensureNotMultilayerRequest(nri, "handleRegisterNetworkRequestWithIntent");
        final NetworkRequestInfo existingRequest =
                findExistingNetworkRequestInfo(nri.mPendingIntent);
        if (existingRequest != null) { // remove the existing request.
            if (DBG) log("Replacing " + existingRequest.request + " with "
                    + nri.request + " because their intents matched.");
            handleReleaseNetworkRequest(existingRequest.request, getCallingUid(),
            if (DBG) {
                log("Replacing " + existingRequest.mRequests.get(0) + " with "
                        + nri.mRequests.get(0) + " because their intents matched.");
            }
            handleReleaseNetworkRequest(existingRequest.mRequests.get(0), getCallingUid(),
                    /* callOnUnavailable */ false);
        }
        handleRegisterNetworkRequest(nri);
    }

    private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
    private void handleRegisterNetworkRequest(@NonNull final NetworkRequestInfo nri) {
        ensureRunningOnConnectivityServiceThread();
        mNetworkRequests.put(nri.request, nri);
        mNetworkRequestInfoLogs.log("REGISTER " + nri);
        if (nri.request.isListen()) {
            for (NetworkAgentInfo network : mNetworkAgentInfos) {
                if (nri.request.networkCapabilities.hasSignalStrength() &&
                        network.satisfiesImmutableCapabilitiesOf(nri.request)) {
                    updateSignalStrengthThresholds(network, "REGISTER", nri.request);
        for (final NetworkRequest req : nri.mRequests) {
            mNetworkRequests.put(req, nri);
            if (req.isListen()) {
                for (final NetworkAgentInfo network : mNetworkAgentInfos) {
                    if (req.networkCapabilities.hasSignalStrength()
                            && network.satisfiesImmutableCapabilitiesOf(req)) {
                        updateSignalStrengthThresholds(network, "REGISTER", req);
                    }
                }
            }
        }
        rematchAllNetworksAndRequests();
        if (nri.request.isRequest() && nri.getSatisfier() == null) {
            sendUpdatedScoreToFactories(nri.request, null);
        // If an active request exists, return as its score has already been sent if needed.
        if (null != nri.getActiveRequest()) {
            return;
        }

        // As this request was not satisfied on rematch and thus never had any scores sent to the
        // factories, send null now for each request of type REQUEST.
        for (final NetworkRequest req : nri.mRequests) {
            if (!req.isRequest()) {
                continue;
            }
            sendUpdatedScoreToFactories(req, null);
        }
    }

    private void handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent,
            int callingUid) {
        NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
    private void handleReleaseNetworkRequestWithIntent(@NonNull final PendingIntent pendingIntent,
            final int callingUid) {
        final NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
        if (nri != null) {
            handleReleaseNetworkRequest(nri.request, callingUid, /* callOnUnavailable */ false);
            // handleReleaseNetworkRequestWithIntent() paths don't apply to multilayer requests.
            ensureNotMultilayerRequest(nri, "handleReleaseNetworkRequestWithIntent");
            handleReleaseNetworkRequest(
                    nri.mRequests.get(0),
                    callingUid,
                    /* callOnUnavailable */ false);
        }
    }

@@ -3652,30 +3673,45 @@ public class ConnectivityService extends IConnectivityManager.Stub
        return nri;
    }

    private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) {
    private void ensureNotMultilayerRequest(@NonNull final NetworkRequestInfo nri,
            final String callingMethod) {
        if (nri.isMultilayerRequest()) {
            throw new IllegalStateException(
                    callingMethod + " does not support multilayer requests.");
        }
    }

    private void handleTimedOutNetworkRequest(@NonNull final NetworkRequestInfo nri) {
        ensureRunningOnConnectivityServiceThread();
        if (mNetworkRequests.get(nri.request) == null) {
        // handleTimedOutNetworkRequest() is part of the requestNetwork() flow which works off of a
        // single NetworkRequest and thus does not apply to multilayer requests.
        ensureNotMultilayerRequest(nri, "handleTimedOutNetworkRequest");
        if (mNetworkRequests.get(nri.mRequests.get(0)) == null) {
            return;
        }
        if (nri.getSatisfier() != null) {
            return;
        }
        if (VDBG || (DBG && nri.request.isRequest())) {
            log("releasing " + nri.request + " (timeout)");
        if (VDBG || (DBG && nri.mRequests.get(0).isRequest())) {
            log("releasing " + nri.mRequests.get(0) + " (timeout)");
        }
        handleRemoveNetworkRequest(nri);
        callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
        callCallbackForRequest(
                nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
    }

    private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid,
            boolean callOnUnavailable) {
    private void handleReleaseNetworkRequest(@NonNull final NetworkRequest request,
            final int callingUid,
            final boolean callOnUnavailable) {
        final NetworkRequestInfo nri =
                getNriForAppRequest(request, callingUid, "release NetworkRequest");
        if (nri == null) {
            return;
        }
        if (VDBG || (DBG && nri.request.isRequest())) {
            log("releasing " + nri.request + " (release request)");
        // handleReleaseNetworkRequest() paths don't apply to multilayer requests.
        ensureNotMultilayerRequest(nri, "handleReleaseNetworkRequest");
        if (VDBG || (DBG && request.isRequest())) {
            log("releasing " + request + " (release request)");
        }
        handleRemoveNetworkRequest(nri);
        if (callOnUnavailable) {
@@ -5451,12 +5487,11 @@ public class ConnectivityService extends IConnectivityManager.Stub

    /**
     * Tracks info about the requester.
     * Also used to notice when the calling process dies so we can self-expire
     * Also used to notice when the calling process dies so as to self-expire
     */
    @VisibleForTesting
    protected class NetworkRequestInfo implements IBinder.DeathRecipient {
        final List<NetworkRequest> mRequests;
        final NetworkRequest request;

        // mSatisfier and mActiveRequest rely on one another therefore set them together.
        void setSatisfier(
@@ -5492,7 +5527,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
        final Messenger messenger;

        NetworkRequestInfo(NetworkRequest r, PendingIntent pi) {
            request = r;
            mRequests = initializeRequests(r);
            ensureAllNetworkRequestsHaveType(mRequests);
            mPendingIntent = pi;
@@ -5506,7 +5540,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
        NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder) {
            super();
            messenger = m;
            request = r;
            mRequests = initializeRequests(r);
            ensureAllNetworkRequestsHaveType(mRequests);
            mBinder = binder;
@@ -5961,13 +5994,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
    }

    @Override
    public void declareNetworkRequestUnfulfillable(NetworkRequest request) {
    public void declareNetworkRequestUnfulfillable(@NonNull final NetworkRequest request) {
        if (request.hasTransport(TRANSPORT_TEST)) {
            enforceNetworkFactoryOrTestNetworksPermission();
        } else {
            enforceNetworkFactoryPermission();
        }
        mHandler.post(() -> handleReleaseNetworkRequest(request, mDeps.getCallingUid(), true));
        final NetworkRequestInfo nri = mNetworkRequests.get(request);
        if (nri != null) {
            // declareNetworkRequestUnfulfillable() paths don't apply to multilayer requests.
            ensureNotMultilayerRequest(nri, "declareNetworkRequestUnfulfillable");
            mHandler.post(() -> handleReleaseNetworkRequest(
                    nri.mRequests.get(0), mDeps.getCallingUid(), true));
        }
    }

    // NOTE: Accessed on multiple threads, must be synchronized on itself.