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

Commit 9b141cc2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add UpstreamNetworkState for tethering"

parents 01613151 b0aca967
Loading
Loading
Loading
Loading
+10 −17
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkState;
import android.net.RouteInfo;
import android.net.ip.IpServer;
import android.net.util.NetworkConstants;
@@ -72,7 +71,7 @@ public class IPv6TetheringCoordinator {
    private final LinkedList<Downstream> mActiveDownstreams;
    private final byte[] mUniqueLocalPrefix;
    private short mNextSubnetId;
    private NetworkState mUpstreamNetworkState;
    private UpstreamNetworkState mUpstreamNetworkState;

    public IPv6TetheringCoordinator(ArrayList<IpServer> notifyList, SharedLog log) {
        mNotifyList = notifyList;
@@ -115,11 +114,11 @@ public class IPv6TetheringCoordinator {
    }

    /**
     * Call when upstream NetworkState may be changed.
     * If upstream has ipv6 for tethering, update this new NetworkState
     * Call when UpstreamNetworkState may be changed.
     * If upstream has ipv6 for tethering, update this new UpstreamNetworkState
     * to IpServer. Otherwise stop ipv6 tethering on downstream interfaces.
     */
    public void updateUpstreamNetworkState(NetworkState ns) {
    public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
        if (VDBG) {
            Log.d(TAG, "updateUpstreamNetworkState: " + toDebugString(ns));
        }
@@ -144,18 +143,15 @@ public class IPv6TetheringCoordinator {
        }
    }

    private void setUpstreamNetworkState(NetworkState ns) {
    private void setUpstreamNetworkState(UpstreamNetworkState ns) {
        if (ns == null) {
            mUpstreamNetworkState = null;
        } else {
            // Make a deep copy of the parts we need.
            mUpstreamNetworkState = new NetworkState(
                    null,
            mUpstreamNetworkState = new UpstreamNetworkState(
                    new LinkProperties(ns.linkProperties),
                    new NetworkCapabilities(ns.networkCapabilities),
                    new Network(ns.network),
                    null,
                    null);
                    new Network(ns.network));
        }

        mLog.log("setUpstreamNetworkState: " + toDebugString(mUpstreamNetworkState));
@@ -295,14 +291,11 @@ public class IPv6TetheringCoordinator {
        return in6addr;
    }

    private static String toDebugString(NetworkState ns) {
    private static String toDebugString(UpstreamNetworkState ns) {
        if (ns == null) {
            return "NetworkState{null}";
            return "UpstreamNetworkState{null}";
        }
        return String.format("NetworkState{%s, %s, %s}",
                ns.network,
                ns.networkCapabilities,
                ns.linkProperties);
        return ns.toString();
    }

    private static void stopIPv6TetheringOn(IpServer ipServer) {
+7 −8
Original line number Diff line number Diff line
@@ -70,7 +70,6 @@ import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.NetworkState;
import android.net.NetworkUtils;
import android.net.TetherStatesParcel;
import android.net.TetheringConfigurationParcel;
@@ -1152,7 +1151,7 @@ public class Tethering {

    // Needed because the canonical source of upstream truth is just the
    // upstream interface set, |mCurrentUpstreamIfaceSet|.
    private boolean pertainsToCurrentUpstream(NetworkState ns) {
    private boolean pertainsToCurrentUpstream(UpstreamNetworkState ns) {
        if (ns != null && ns.linkProperties != null && mCurrentUpstreamIfaceSet != null) {
            for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
                if (mCurrentUpstreamIfaceSet.ifnames.contains(ifname)) {
@@ -1320,7 +1319,7 @@ public class Tethering {
            maybeDunSettingChanged();

            final TetheringConfiguration config = mConfig;
            final NetworkState ns = (config.chooseUpstreamAutomatically)
            final UpstreamNetworkState ns = (config.chooseUpstreamAutomatically)
                    ? mUpstreamNetworkMonitor.getCurrentPreferredUpstream()
                    : mUpstreamNetworkMonitor.selectPreferredUpstreamType(
                            config.preferredUpstreamIfaceTypes);
@@ -1341,7 +1340,7 @@ public class Tethering {
            }
        }

        protected void setUpstreamNetwork(NetworkState ns) {
        protected void setUpstreamNetwork(UpstreamNetworkState ns) {
            InterfaceSet ifaces = null;
            if (ns != null) {
                // Find the interface with the default IPv4 route. It may be the
@@ -1357,7 +1356,7 @@ public class Tethering {
            }
            notifyDownstreamsOfNewUpstreamIface(ifaces);
            if (ns != null && pertainsToCurrentUpstream(ns)) {
                // If we already have NetworkState for this network update it immediately.
                // If we already have UpstreamNetworkState for this network update it immediately.
                handleNewUpstreamNetworkState(ns);
            } else if (mCurrentUpstreamIfaceSet == null) {
                // There are no available upstream networks.
@@ -1394,7 +1393,7 @@ public class Tethering {
            }
        }

        protected void handleNewUpstreamNetworkState(NetworkState ns) {
        protected void handleNewUpstreamNetworkState(UpstreamNetworkState ns) {
            mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
            mOffload.updateUpstreamNetworkState(ns);
        }
@@ -1458,7 +1457,7 @@ public class Tethering {
                return;
            }

            final NetworkState ns = (NetworkState) o;
            final UpstreamNetworkState ns = (UpstreamNetworkState) o;

            if (ns == null || !pertainsToCurrentUpstream(ns)) {
                // TODO: In future, this is where upstream evaluation and selection
@@ -1728,7 +1727,7 @@ public class Tethering {
                mOffloadController.stop();
            }

            public void updateUpstreamNetworkState(NetworkState ns) {
            public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
                mOffloadController.setUpstreamLinkProperties(
                        (ns != null) ? ns.linkProperties : null);
            }
+2 −3
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.server.connectivity.tethering;
import android.annotation.Nullable;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.net.NetworkState;
import android.net.RouteInfo;
import android.net.util.InterfaceSet;

@@ -35,7 +34,7 @@ public final class TetheringInterfaceUtils {
     * Get upstream interfaces for tethering based on default routes for IPv4/IPv6.
     * @return null if there is no usable interface, or a set of at least one interface otherwise.
     */
    public static @Nullable InterfaceSet getTetheringInterfaces(NetworkState ns) {
    public static @Nullable InterfaceSet getTetheringInterfaces(UpstreamNetworkState ns) {
        if (ns == null) {
            return null;
        }
@@ -51,7 +50,7 @@ public final class TetheringInterfaceUtils {
     * Get the upstream interface for IPv6 tethering.
     * @return null if there is no usable interface, or the interface name otherwise.
     */
    public static @Nullable String getIPv6Interface(NetworkState ns) {
    public static @Nullable String getIPv6Interface(UpstreamNetworkState ns) {
        // Broadly speaking:
        //
        //     [1] does the upstream have an IPv6 default route?
+22 −22
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.util.PrefixUtils;
import android.net.util.SharedLog;
import android.os.Handler;
@@ -90,7 +89,7 @@ public class UpstreamNetworkMonitor {
    private final StateMachine mTarget;
    private final Handler mHandler;
    private final int mWhat;
    private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
    private final HashMap<Network, UpstreamNetworkState> mNetworkMap = new HashMap<>();
    private HashSet<IpPrefix> mLocalPrefixes;
    private ConnectivityManager mCM;
    private EntitlementManager mEntitlementMgr;
@@ -236,7 +235,7 @@ public class UpstreamNetworkMonitor {
    /**
     * Select the first available network from |perferredTypes|.
     */
    public NetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) {
    public UpstreamNetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) {
        final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType(
                mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted());

@@ -274,8 +273,8 @@ public class UpstreamNetworkMonitor {
     * preferred upstream would be DUN otherwise preferred upstream is the same as default network.
     * Returns null if no current upstream is available.
     */
    public NetworkState getCurrentPreferredUpstream() {
        final NetworkState dfltState = (mDefaultInternetNetwork != null)
    public UpstreamNetworkState getCurrentPreferredUpstream() {
        final UpstreamNetworkState dfltState = (mDefaultInternetNetwork != null)
                ? mNetworkMap.get(mDefaultInternetNetwork)
                : null;
        if (isNetworkUsableAndNotCellular(dfltState)) return dfltState;
@@ -312,11 +311,11 @@ public class UpstreamNetworkMonitor {
        if (mNetworkMap.containsKey(network)) return;

        if (VDBG) Log.d(TAG, "onAvailable for " + network);
        mNetworkMap.put(network, new NetworkState(null, null, null, network, null, null));
        mNetworkMap.put(network, new UpstreamNetworkState(null, null, network));
    }

    private void handleNetCap(Network network, NetworkCapabilities newNc) {
        final NetworkState prev = mNetworkMap.get(network);
        final UpstreamNetworkState prev = mNetworkMap.get(network);
        if (prev == null || newNc.equals(prev.networkCapabilities)) {
            // Ignore notifications about networks for which we have not yet
            // received onAvailable() (should never happen) and any duplicate
@@ -336,15 +335,15 @@ public class UpstreamNetworkMonitor {
            mLog.logf("upstream network signal strength: %s -> %s", prevSignal, newSignal);
        }

        mNetworkMap.put(network, new NetworkState(
                null, prev.linkProperties, newNc, network, null, null));
        mNetworkMap.put(network, new UpstreamNetworkState(
                prev.linkProperties, newNc, network));
        // TODO: If sufficient information is available to select a more
        // preferable upstream, do so now and notify the target.
        notifyTarget(EVENT_ON_CAPABILITIES, network);
    }

    private void handleLinkProp(Network network, LinkProperties newLp) {
        final NetworkState prev = mNetworkMap.get(network);
        final UpstreamNetworkState prev = mNetworkMap.get(network);
        if (prev == null || newLp.equals(prev.linkProperties)) {
            // Ignore notifications about networks for which we have not yet
            // received onAvailable() (should never happen) and any duplicate
@@ -357,8 +356,8 @@ public class UpstreamNetworkMonitor {
                    network, newLp));
        }

        mNetworkMap.put(network, new NetworkState(
                null, newLp, prev.networkCapabilities, network, null, null));
        mNetworkMap.put(network, new UpstreamNetworkState(
                newLp, prev.networkCapabilities, network));
        // TODO: If sufficient information is available to select a more
        // preferable upstream, do so now and notify the target.
        notifyTarget(EVENT_ON_LINKPROPERTIES, network);
@@ -509,11 +508,11 @@ public class UpstreamNetworkMonitor {

    private static class TypeStatePair {
        public int type = TYPE_NONE;
        public NetworkState ns = null;
        public UpstreamNetworkState ns = null;
    }

    private static TypeStatePair findFirstAvailableUpstreamByType(
            Iterable<NetworkState> netStates, Iterable<Integer> preferredTypes,
            Iterable<UpstreamNetworkState> netStates, Iterable<Integer> preferredTypes,
            boolean isCellularUpstreamPermitted) {
        final TypeStatePair result = new TypeStatePair();

@@ -532,7 +531,7 @@ public class UpstreamNetworkMonitor {

            nc.setSingleUid(Process.myUid());

            for (NetworkState value : netStates) {
            for (UpstreamNetworkState value : netStates) {
                if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) {
                    continue;
                }
@@ -546,10 +545,10 @@ public class UpstreamNetworkMonitor {
        return result;
    }

    private static HashSet<IpPrefix> allLocalPrefixes(Iterable<NetworkState> netStates) {
    private static HashSet<IpPrefix> allLocalPrefixes(Iterable<UpstreamNetworkState> netStates) {
        final HashSet<IpPrefix> prefixSet = new HashSet<>();

        for (NetworkState ns : netStates) {
        for (UpstreamNetworkState ns : netStates) {
            final LinkProperties lp = ns.linkProperties;
            if (lp == null) continue;
            prefixSet.addAll(PrefixUtils.localPrefixesFrom(lp));
@@ -563,7 +562,7 @@ public class UpstreamNetworkMonitor {
        return Integer.toString(nc.getSignalStrength());
    }

    private static boolean isCellular(NetworkState ns) {
    private static boolean isCellular(UpstreamNetworkState ns) {
        return (ns != null) && isCellular(ns.networkCapabilities);
    }

@@ -572,18 +571,19 @@ public class UpstreamNetworkMonitor {
               && nc.hasCapability(NET_CAPABILITY_NOT_VPN);
    }

    private static boolean hasCapability(NetworkState ns, int netCap) {
    private static boolean hasCapability(UpstreamNetworkState ns, int netCap) {
        return (ns != null) && (ns.networkCapabilities != null)
               && ns.networkCapabilities.hasCapability(netCap);
    }

    private static boolean isNetworkUsableAndNotCellular(NetworkState ns) {
    private static boolean isNetworkUsableAndNotCellular(UpstreamNetworkState ns) {
        return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null)
               && !isCellular(ns.networkCapabilities);
    }

    private static NetworkState findFirstDunNetwork(Iterable<NetworkState> netStates) {
        for (NetworkState ns : netStates) {
    private static UpstreamNetworkState findFirstDunNetwork(
            Iterable<UpstreamNetworkState> netStates) {
        for (UpstreamNetworkState ns : netStates) {
            if (isCellular(ns) && hasCapability(ns, NET_CAPABILITY_DUN)) return ns;
        }

+51 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.connectivity.tethering;

import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;

import androidx.annotation.NonNull;

/**
 * Snapshot of tethering upstream network state.
 */
public class UpstreamNetworkState {
    /** {@link LinkProperties}. */
    public final LinkProperties linkProperties;
    /** {@link NetworkCapabilities}. */
    public final NetworkCapabilities networkCapabilities;
    /** {@link Network}. */
    public final Network network;

    /** Constructs a new UpstreamNetworkState. */
    public UpstreamNetworkState(LinkProperties linkProperties,
            NetworkCapabilities networkCapabilities, Network network) {
        this.linkProperties = linkProperties;
        this.networkCapabilities = networkCapabilities;
        this.network = network;
    }

    @NonNull
    @Override
    public String toString() {
        return String.format("UpstreamNetworkState{%s, %s, %s}",
                network == null ? "null" : network,
                networkCapabilities == null ? "null" : networkCapabilities,
                linkProperties == null ? "null" : linkProperties);
    }
}
Loading