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

Commit 5c351eb8 authored by markchien's avatar markchien Committed by android-build-merger
Browse files

Merge "Add UpstreamNetworkState for tethering"

am: 9b141cc2

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


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


    /**
    /**
     * Call when upstream NetworkState may be changed.
     * Call when UpstreamNetworkState may be changed.
     * If upstream has ipv6 for tethering, update this new NetworkState
     * If upstream has ipv6 for tethering, update this new UpstreamNetworkState
     * to IpServer. Otherwise stop ipv6 tethering on downstream interfaces.
     * to IpServer. Otherwise stop ipv6 tethering on downstream interfaces.
     */
     */
    public void updateUpstreamNetworkState(NetworkState ns) {
    public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
        if (VDBG) {
        if (VDBG) {
            Log.d(TAG, "updateUpstreamNetworkState: " + toDebugString(ns));
            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) {
        if (ns == null) {
            mUpstreamNetworkState = null;
            mUpstreamNetworkState = null;
        } else {
        } else {
            // Make a deep copy of the parts we need.
            // Make a deep copy of the parts we need.
            mUpstreamNetworkState = new NetworkState(
            mUpstreamNetworkState = new UpstreamNetworkState(
                    null,
                    new LinkProperties(ns.linkProperties),
                    new LinkProperties(ns.linkProperties),
                    new NetworkCapabilities(ns.networkCapabilities),
                    new NetworkCapabilities(ns.networkCapabilities),
                    new Network(ns.network),
                    new Network(ns.network));
                    null,
                    null);
        }
        }


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


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


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


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


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


        protected void setUpstreamNetwork(NetworkState ns) {
        protected void setUpstreamNetwork(UpstreamNetworkState ns) {
            InterfaceSet ifaces = null;
            InterfaceSet ifaces = null;
            if (ns != null) {
            if (ns != null) {
                // Find the interface with the default IPv4 route. It may be the
                // Find the interface with the default IPv4 route. It may be the
@@ -1357,7 +1356,7 @@ public class Tethering {
            }
            }
            notifyDownstreamsOfNewUpstreamIface(ifaces);
            notifyDownstreamsOfNewUpstreamIface(ifaces);
            if (ns != null && pertainsToCurrentUpstream(ns)) {
            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);
                handleNewUpstreamNetworkState(ns);
            } else if (mCurrentUpstreamIfaceSet == null) {
            } else if (mCurrentUpstreamIfaceSet == null) {
                // There are no available upstream networks.
                // 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);
            mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
            mOffload.updateUpstreamNetworkState(ns);
            mOffload.updateUpstreamNetworkState(ns);
        }
        }
@@ -1458,7 +1457,7 @@ public class Tethering {
                return;
                return;
            }
            }


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


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


            public void updateUpstreamNetworkState(NetworkState ns) {
            public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
                mOffloadController.setUpstreamLinkProperties(
                mOffloadController.setUpstreamLinkProperties(
                        (ns != null) ? ns.linkProperties : null);
                        (ns != null) ? ns.linkProperties : null);
            }
            }
+2 −3
Original line number Original line Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.server.connectivity.tethering;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.net.LinkProperties;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.net.NetworkCapabilities;
import android.net.NetworkState;
import android.net.RouteInfo;
import android.net.RouteInfo;
import android.net.util.InterfaceSet;
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.
     * 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.
     * @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) {
        if (ns == null) {
            return null;
            return null;
        }
        }
@@ -51,7 +50,7 @@ public final class TetheringInterfaceUtils {
     * Get the upstream interface for IPv6 tethering.
     * Get the upstream interface for IPv6 tethering.
     * @return null if there is no usable interface, or the interface name otherwise.
     * @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:
        // Broadly speaking:
        //
        //
        //     [1] does the upstream have an IPv6 default route?
        //     [1] does the upstream have an IPv6 default route?
+22 −22
Original line number Original line Diff line number Diff line
@@ -32,7 +32,6 @@ import android.net.LinkProperties;
import android.net.Network;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.util.PrefixUtils;
import android.net.util.PrefixUtils;
import android.net.util.SharedLog;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.Handler;
@@ -90,7 +89,7 @@ public class UpstreamNetworkMonitor {
    private final StateMachine mTarget;
    private final StateMachine mTarget;
    private final Handler mHandler;
    private final Handler mHandler;
    private final int mWhat;
    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 HashSet<IpPrefix> mLocalPrefixes;
    private ConnectivityManager mCM;
    private ConnectivityManager mCM;
    private EntitlementManager mEntitlementMgr;
    private EntitlementManager mEntitlementMgr;
@@ -236,7 +235,7 @@ public class UpstreamNetworkMonitor {
    /**
    /**
     * Select the first available network from |perferredTypes|.
     * Select the first available network from |perferredTypes|.
     */
     */
    public NetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) {
    public UpstreamNetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) {
        final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType(
        final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType(
                mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted());
                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.
     * preferred upstream would be DUN otherwise preferred upstream is the same as default network.
     * Returns null if no current upstream is available.
     * Returns null if no current upstream is available.
     */
     */
    public NetworkState getCurrentPreferredUpstream() {
    public UpstreamNetworkState getCurrentPreferredUpstream() {
        final NetworkState dfltState = (mDefaultInternetNetwork != null)
        final UpstreamNetworkState dfltState = (mDefaultInternetNetwork != null)
                ? mNetworkMap.get(mDefaultInternetNetwork)
                ? mNetworkMap.get(mDefaultInternetNetwork)
                : null;
                : null;
        if (isNetworkUsableAndNotCellular(dfltState)) return dfltState;
        if (isNetworkUsableAndNotCellular(dfltState)) return dfltState;
@@ -312,11 +311,11 @@ public class UpstreamNetworkMonitor {
        if (mNetworkMap.containsKey(network)) return;
        if (mNetworkMap.containsKey(network)) return;


        if (VDBG) Log.d(TAG, "onAvailable for " + network);
        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) {
    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)) {
        if (prev == null || newNc.equals(prev.networkCapabilities)) {
            // Ignore notifications about networks for which we have not yet
            // Ignore notifications about networks for which we have not yet
            // received onAvailable() (should never happen) and any duplicate
            // 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);
            mLog.logf("upstream network signal strength: %s -> %s", prevSignal, newSignal);
        }
        }


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


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


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


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


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


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


            nc.setSingleUid(Process.myUid());
            nc.setSingleUid(Process.myUid());


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


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


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


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


@@ -572,18 +571,19 @@ public class UpstreamNetworkMonitor {
               && nc.hasCapability(NET_CAPABILITY_NOT_VPN);
               && 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)
        return (ns != null) && (ns.networkCapabilities != null)
               && ns.networkCapabilities.hasCapability(netCap);
               && 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)
        return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null)
               && !isCellular(ns.networkCapabilities);
               && !isCellular(ns.networkCapabilities);
    }
    }


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


+51 −0
Original line number Original line 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