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

Commit 079d5f94 authored by James Mattis's avatar James Mattis
Browse files

Transmitting multiple default networks to netd

Updating ConnectivityService to transmit network information to netd as
part of supporting multiple default networks.

Bug: 176191930
Bug: 172347841
Test: atest FrameworksNetTests
atest NetworkStackTests
atest FrameworksNetIntegrationTests
atest NetworkStackIntegrationTests
atest CtsNetTestCasesLatestSdk

Change-Id: I5851a36e3c3ccb45f4cb3ff85e0fc1352f64dc70
parent de246e16
Loading
Loading
Loading
Loading
+125 −29
Original line number Diff line number Diff line
@@ -1227,6 +1227,14 @@ public class ConnectivityService extends IConnectivityManager.Stub

        mDnsManager = new DnsManager(mContext, mDnsResolver);
        registerPrivateDnsSettingsCallbacks();

        mNoServiceNetwork =  new NetworkAgentInfo(null,
                new Network(NO_SERVICE_NET_ID),
                new NetworkInfo(TYPE_NONE, 0, "", ""),
                new LinkProperties(), new NetworkCapabilities(), 0, mContext,
                null, new NetworkAgentConfig(), this, null,
                null, null, 0, INVALID_UID,
                mQosCallbackTracker);
    }

    private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
@@ -3446,13 +3454,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
        propagateUnderlyingNetworkCapabilities(nai.network);
        // Remove all previously satisfied requests.
        for (int i = 0; i < nai.numNetworkRequests(); i++) {
            NetworkRequest request = nai.requestAt(i);
            final NetworkRequest request = nai.requestAt(i);
            final NetworkRequestInfo nri = mNetworkRequests.get(request);
            final NetworkAgentInfo currentNetwork = nri.getSatisfier();
            if (currentNetwork != null
                    && currentNetwork.network.getNetId() == nai.network.getNetId()) {
                // uid rules for this network will be removed in destroyNativeNetwork(nai).
                nri.setSatisfier(null, null);
                if (request.isRequest()) {
                    sendUpdatedScoreToFactories(request, null);
                }

                if (mDefaultRequest == nri) {
                    // TODO : make battery stats aware that since 2013 multiple interfaces may be
@@ -3709,7 +3720,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        if (mNetworkRequests.get(nri.mRequests.get(0)) == null) {
            return;
        }
        if (nri.getSatisfier() != null) {
        if (nri.getActiveRequest() != null) {
            return;
        }
        if (VDBG || (DBG && nri.mRequests.get(0).isRequest())) {
@@ -4951,6 +4962,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        }
    }

    // TODO This needs to be the default network that applies to the NAI.
    private Network[] underlyingNetworksOrDefault(Network[] underlyingNetworks) {
        final Network defaultNetwork = getNetwork(getDefaultNetwork());
        if (underlyingNetworks == null && defaultNetwork != null) {
@@ -5521,9 +5533,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
            mActiveRequest = activeRequest;
        }

        // The network currently satisfying this request, or null if none. Must only be touched
        // on the handler thread. This only makes sense for network requests and not for listens,
        // as defined by NetworkRequest#isRequest(). For listens, this is always null.
        // The network currently satisfying this NRI. Only one request in an NRI can have a
        // satisfier. For non-multilayer requests, only REQUEST-type requests can have a satisfier.
        @Nullable
        private NetworkAgentInfo mSatisfier;
        NetworkAgentInfo getSatisfier() {
@@ -5546,6 +5557,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
        final int mUid;
        final Messenger messenger;

        /**
         * Get the list of UIDs this nri applies to.
         */
        @NonNull
        private Set<UidRange> getUids() {
            // networkCapabilities.getUids() returns a defensive copy.
            // multilayer requests will all have the same uids so return the first one.
            final Set<UidRange> uids = null == mRequests.get(0).networkCapabilities.getUids()
                    ? new ArraySet<>() : mRequests.get(0).networkCapabilities.getUids();
            return uids;
        }

        NetworkRequestInfo(NetworkRequest r, PendingIntent pi) {
            mRequests = initializeRequests(r);
            ensureAllNetworkRequestsHaveType(mRequests);
@@ -5604,7 +5627,9 @@ public class ConnectivityService extends IConnectivityManager.Stub

        @Override
        public String toString() {
            return "uid/pid:" + mUid + "/" + mPid + " " + mRequests
            return "uid/pid:" + mUid + "/" + mPid + " active request Id: "
                    + (mActiveRequest == null ? null : mActiveRequest.requestId)
                    + " " + mRequests
                    + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
        }
    }
@@ -6064,6 +6089,26 @@ public class ConnectivityService extends IConnectivityManager.Stub
    @NonNull
    private final ArraySet<NetworkRequestInfo> mDefaultNetworkRequests = new ArraySet<>();

    private boolean isPerAppDefaultRequest(@NonNull final NetworkRequestInfo nri) {
        return (mDefaultNetworkRequests.contains(nri) && mDefaultRequest != nri);
    }

    /**
     * Determine if an nri is a managed default request that disallows default networking.
     * @param nri the request to evaluate
     * @return true if device-default networking is disallowed
     */
    private boolean isDefaultBlocked(@NonNull final NetworkRequestInfo nri) {
        // Check if this nri is a managed default that supports the default network at its
        // lowest priority request.
        final NetworkRequest defaultNetworkRequest = mDefaultRequest.mRequests.get(0);
        final NetworkCapabilities lowestPriorityNetCap =
                nri.mRequests.get(nri.mRequests.size() - 1).networkCapabilities;
        return isPerAppDefaultRequest(nri)
                && !(defaultNetworkRequest.networkCapabilities.equalRequestableCapabilities(
                        lowestPriorityNetCap));
    }

    // Request used to optionally keep mobile data active even when higher
    // priority networks like Wi-Fi are active.
    private final NetworkRequest mDefaultMobileDataRequest;
@@ -6075,6 +6120,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
    // Request used to optionally keep vehicle internal network always active
    private final NetworkRequest mDefaultVehicleRequest;

    // TODO replace with INetd.DUMMY_NET_ID when available.
    private static final int NO_SERVICE_NET_ID = 51;
    // Sentinel NAI used to direct apps with default networks that should have no connectivity to a
    // network with no service. This NAI should never be matched against, nor should any public API
    // ever return the associated network. For this reason, this NAI is not in the list of available
    // NAIs. It is used in computeNetworkReassignment() to be set as the satisfier for non-device
    // default requests that don't support using the device default network which will ultimately
    // allow ConnectivityService to use this no-service network when calling makeDefaultForApps().
    @VisibleForTesting
    final NetworkAgentInfo mNoServiceNetwork;

    // TODO: b/178729499 update this in favor of a method taking in a UID.
    // The NetworkAgentInfo currently satisfying the default request, if any.
    private NetworkAgentInfo getDefaultNetwork() {
@@ -6165,8 +6221,6 @@ public class ConnectivityService extends IConnectivityManager.Stub

        LinkProperties lp = new LinkProperties(linkProperties);

        // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
        // satisfies mDefaultRequest.
        final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
        final NetworkAgentInfo nai = new NetworkAgentInfo(na,
                new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
@@ -7233,20 +7287,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
            log("Switching to new default network for: " + nri + " using " + newDefaultNetwork);
        }

        try {
            // TODO http://b/176191930 update netd calls in follow-up CL for multinetwork changes.
        // Fix up the NetworkCapabilities of any networks that have this network as underlying.
        if (newDefaultNetwork != null) {
            propagateUnderlyingNetworkCapabilities(newDefaultNetwork.network);
        }

        // Set an app level managed default and return since further processing only applies to the
        // default network.
        if (mDefaultRequest != nri) {
            makeDefaultForApps(nri, oldDefaultNetwork, newDefaultNetwork);
            return;
        }

            if (null != newDefaultNetwork) {
                mNetd.networkSetDefault(newDefaultNetwork.network.getNetId());
            } else {
                mNetd.networkClearDefault();
            }
        } catch (RemoteException | ServiceSpecificException e) {
            loge("Exception setting default network :" + e);
        }
        makeDefaultNetwork(newDefaultNetwork);

        if (oldDefaultNetwork != null) {
            mLingerMonitor.noteLingerDefaultNetwork(oldDefaultNetwork, newDefaultNetwork);
@@ -7258,10 +7311,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
        updateTcpBufferSizes(null != newDefaultNetwork
                ? newDefaultNetwork.linkProperties.getTcpBufferSizes() : null);
        notifyIfacesChangedForNetworkStats();
        // Fix up the NetworkCapabilities of any networks that have this network as underlying.
        if (newDefaultNetwork != null) {
            propagateUnderlyingNetworkCapabilities(newDefaultNetwork.network);
        }

        // Log 0 -> X and Y -> X default network transitions, where X is the new default.
        final Network network = (newDefaultNetwork != null) ? newDefaultNetwork.network : null;
@@ -7285,6 +7334,49 @@ public class ConnectivityService extends IConnectivityManager.Stub
                prevNetwork, prevScore, prevLp, prevNc);
    }

    private void makeDefaultForApps(@NonNull final NetworkRequestInfo nri,
            @Nullable final NetworkAgentInfo oldDefaultNetwork,
            @Nullable final NetworkAgentInfo newDefaultNetwork) {
        try {
            if (VDBG) {
                log("Setting default network for " + nri
                        + " using UIDs " + nri.getUids()
                        + " with old network " + (oldDefaultNetwork != null
                        ? oldDefaultNetwork.network().getNetId() : "null")
                        + " and new network " + (newDefaultNetwork != null
                        ? newDefaultNetwork.network().getNetId() : "null"));
            }
            if (nri.getUids().isEmpty()) {
                throw new IllegalStateException("makeDefaultForApps called without specifying"
                        + " any applications to set as the default." + nri);
            }
            if (null != newDefaultNetwork) {
                mNetd.networkAddUidRanges(
                        newDefaultNetwork.network.getNetId(),
                        toUidRangeStableParcels(nri.getUids()));
            }
            if (null != oldDefaultNetwork) {
                mNetd.networkRemoveUidRanges(
                        oldDefaultNetwork.network.getNetId(),
                        toUidRangeStableParcels(nri.getUids()));
            }
        } catch (RemoteException | ServiceSpecificException e) {
            loge("Exception setting OEM network preference default network :" + e);
        }
    }

    private void makeDefaultNetwork(@Nullable final NetworkAgentInfo newDefaultNetwork) {
        try {
            if (null != newDefaultNetwork) {
                mNetd.networkSetDefault(newDefaultNetwork.network.getNetId());
            } else {
                mNetd.networkClearDefault();
            }
        } catch (RemoteException | ServiceSpecificException e) {
            loge("Exception setting default network :" + e);
        }
    }

    private void processListenRequests(@NonNull final NetworkAgentInfo nai) {
        // For consistency with previous behaviour, send onLost callbacks before onAvailable.
        processNewlyLostListenRequests(nai);
@@ -7406,9 +7498,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
            @Nullable final NetworkAgentInfo previousSatisfier,
            @Nullable final NetworkAgentInfo newSatisfier,
            final long now) {
        if (newSatisfier != null) {
        if (null != newSatisfier && mNoServiceNetwork != newSatisfier) {
            if (VDBG) log("rematch for " + newSatisfier.toShortString());
            if (previousSatisfier != null) {
            if (null != previousSatisfier && mNoServiceNetwork != previousSatisfier) {
                if (VDBG || DDBG) {
                    log("   accepting network in place of " + previousSatisfier.toShortString());
                }
@@ -7422,7 +7514,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                Log.wtf(TAG, "BUG: " + newSatisfier.toShortString() + " already has "
                        + newRequest);
            }
        } else {
        } else if (null != previousSatisfier) {
            if (DBG) {
                log("Network " + previousSatisfier.toShortString() + " stopped satisfying"
                        + " request " + previousRequest.requestId);
@@ -7473,7 +7565,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    break;
                }
            }
            if (bestNetwork != nri.mSatisfier) {
            if (null == bestNetwork && isDefaultBlocked(nri)) {
                // Remove default networking if disallowed for managed default requests.
                bestNetwork = mNoServiceNetwork;
            }
            if (nri.getSatisfier() != bestNetwork) {
                // bestNetwork may be null if no network can satisfy this request.
                changes.addRequestReassignment(new NetworkReassignment.RequestReassignment(
                        nri, nri.mActiveRequest, bestRequest, nri.getSatisfier(), bestNetwork));