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

Commit 7c02a887 authored by Erik Kline's avatar Erik Kline Committed by android-build-merger
Browse files

Merge \"More correctly track upstream network properties.\" into nyc-mr1-dev

am: 5cbbc02a

Change-Id: I8d6cbd8bb65b5c9f9701a76a34c3734db66edb27
parents 0f2a7ca0 5cbbc02a
Loading
Loading
Loading
Loading
+180 −46
Original line number Diff line number Diff line
@@ -1017,16 +1017,30 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
     * tethering master state machine thread for subsequent processing.
     */
    class UpstreamNetworkCallback extends NetworkCallback {
        @Override
        public void onAvailable(Network network) {
            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
                    UpstreamNetworkMonitor.EVENT_ON_AVAILABLE, 0, network);
        }

        @Override
        public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
                    UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES, 0,
                    new NetworkState(null, null, newNc, network, null, null));
        }

        @Override
        public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
            mTetherMasterSM.sendMessage(
                    TetherMasterSM.EVENT_UPSTREAM_LINKPROPERTIES_CHANGED,
            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
                    UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, 0,
                    new NetworkState(null, newLp, null, network, null, null));
        }

        @Override
        public void onLost(Network network) {
            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_LOST, network);
            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
                    UpstreamNetworkMonitor.EVENT_ON_LOST, 0, network);
        }
    }

@@ -1045,6 +1059,11 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
     * could/should be moved here.
     */
    class UpstreamNetworkMonitor {
        static final int EVENT_ON_AVAILABLE      = 1;
        static final int EVENT_ON_CAPABILITIES   = 2;
        static final int EVENT_ON_LINKPROPERTIES = 3;
        static final int EVENT_ON_LOST           = 4;

        final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
        NetworkCallback mDefaultNetworkCallback;
        NetworkCallback mDunTetheringCallback;
@@ -1079,33 +1098,107 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
            mNetworkMap.clear();
        }

        // Returns true if these updated LinkProperties pertain to the current
        // upstream network interface, false otherwise (or if there is not
        // currently any upstream tethering interface).
        boolean processLinkPropertiesChanged(NetworkState networkState) {
            if (networkState == null ||
                    networkState.network == null ||
                    networkState.linkProperties == null) {
                return false;
        NetworkState lookup(Network network) {
            return (network != null) ? mNetworkMap.get(network) : null;
        }

            mNetworkMap.put(networkState.network, networkState);
        NetworkState processCallback(int arg1, Object obj) {
            switch (arg1) {
                case EVENT_ON_AVAILABLE: {
                    final Network network = (Network) obj;
                    if (VDBG) {
                        Log.d(TAG, "EVENT_ON_AVAILABLE for " + network);
                    }
                    if (!mNetworkMap.containsKey(network)) {
                        mNetworkMap.put(network,
                                new NetworkState(null, null, null, network, null, null));
                    }

            if (mCurrentUpstreamIface != null) {
                for (String ifname : networkState.linkProperties.getAllInterfaceNames()) {
                    if (mCurrentUpstreamIface.equals(ifname)) {
                        return true;
                    final ConnectivityManager cm = getConnectivityManager();

                    if (mDefaultNetworkCallback != null) {
                        cm.requestNetworkCapabilities(mDefaultNetworkCallback);
                        cm.requestLinkProperties(mDefaultNetworkCallback);
                    }

                    // Requesting updates for mDunTetheringCallback is not
                    // necessary. Because it's a listen, it will already have
                    // heard all NetworkCapabilities and LinkProperties updates
                    // since UpstreamNetworkMonitor was started. Because we
                    // start UpstreamNetworkMonitor before chooseUpstreamType()
                    // is ever invoked (it can register a DUN request) this is
                    // mostly safe. However, if a DUN network is already up for
                    // some reason (unlikely, because DUN is restricted and,
                    // unless the DUN network is shared with another APN, only
                    // the system can request it and this is the only part of
                    // the system that requests it) we won't know its
                    // LinkProperties or NetworkCapabilities.

                    return mNetworkMap.get(network);
                }
                case EVENT_ON_CAPABILITIES: {
                    final NetworkState ns = (NetworkState) obj;
                    if (!mNetworkMap.containsKey(ns.network)) {
                        // Ignore updates for networks for which we have not yet
                        // received onAvailable() - which should never happen -
                        // or for which we have already received onLost().
                        return null;
                    }
                    if (VDBG) {
                        Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s",
                                ns.network, ns.networkCapabilities));
                    }

                    final NetworkState prev = mNetworkMap.get(ns.network);
                    mNetworkMap.put(ns.network,
                            new NetworkState(null, prev.linkProperties, ns.networkCapabilities,
                                             ns.network, null, null));
                    return mNetworkMap.get(ns.network);
                }
                case EVENT_ON_LINKPROPERTIES: {
                    final NetworkState ns = (NetworkState) obj;
                    if (!mNetworkMap.containsKey(ns.network)) {
                        // Ignore updates for networks for which we have not yet
                        // received onAvailable() - which should never happen -
                        // or for which we have already received onLost().
                        return null;
                    }
                    if (VDBG) {
                        Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s",
                                ns.network, ns.linkProperties));
                    }

                    final NetworkState prev = mNetworkMap.get(ns.network);
                    mNetworkMap.put(ns.network,
                            new NetworkState(null, ns.linkProperties, prev.networkCapabilities,
                                             ns.network, null, null));
                    return mNetworkMap.get(ns.network);
                }
                case EVENT_ON_LOST: {
                    final Network network = (Network) obj;
                    if (VDBG) {
                        Log.d(TAG, "EVENT_ON_LOST for " + network);
                    }
                    return mNetworkMap.remove(network);
                }
                default:
                    return null;
            }
        }
            return false;
    }

        void processNetworkLost(Network network) {
            if (network != null) {
                mNetworkMap.remove(network);
    // Needed because the canonical source of upstream truth is just the
    // upstream interface name, |mCurrentUpstreamIface|.  This is ripe for
    // future simplification, once the upstream Network is canonical.
    boolean pertainsToCurrentUpstream(NetworkState ns) {
        if (ns != null && ns.linkProperties != null && mCurrentUpstreamIface != null) {
            for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
                if (mCurrentUpstreamIface.equals(ifname)) {
                    return true;
                }
            }
        }
        return false;
    }

    class TetherMasterSM extends StateMachine {
@@ -1120,8 +1213,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
        static final int CMD_RETRY_UPSTREAM                     = BASE_MASTER + 4;
        // Events from NetworkCallbacks that we process on the master state
        // machine thread on behalf of the UpstreamNetworkMonitor.
        static final int EVENT_UPSTREAM_LINKPROPERTIES_CHANGED  = BASE_MASTER + 5;
        static final int EVENT_UPSTREAM_LOST                    = BASE_MASTER + 6;
        static final int EVENT_UPSTREAM_CALLBACK                = BASE_MASTER + 5;

        private State mInitialState;
        private State mTetherModeAliveState;
@@ -1278,6 +1370,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
            }

            protected void chooseUpstreamType(boolean tryCell) {
                final ConnectivityManager cm = getConnectivityManager();
                int upType = ConnectivityManager.TYPE_NONE;
                String iface = null;

@@ -1292,8 +1385,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                    }

                    for (Integer netType : mUpstreamIfaceTypes) {
                        NetworkInfo info =
                                getConnectivityManager().getNetworkInfo(netType.intValue());
                        NetworkInfo info = cm.getNetworkInfo(netType.intValue());
                        if ((info != null) && info.isConnected()) {
                            upType = netType.intValue();
                            break;
@@ -1334,9 +1426,9 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                        break;
                }

                Network network = null;
                if (upType != ConnectivityManager.TYPE_NONE) {
                    LinkProperties linkProperties =
                            getConnectivityManager().getLinkProperties(upType);
                    LinkProperties linkProperties = cm.getLinkProperties(upType);
                    if (linkProperties != null) {
                        // Find the interface with the default IPv4 route. It may be the
                        // interface described by linkProperties, or one of the interfaces
@@ -1353,7 +1445,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                    }

                    if (iface != null) {
                        Network network = getConnectivityManager().getNetworkForType(upType);
                        network = cm.getNetworkForType(upType);
                        if (network == null) {
                            Log.e(TAG, "No Network for upstream type " + upType + "!");
                        }
@@ -1361,6 +1453,13 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                    }
                }
                notifyTetheredOfNewUpstreamIface(iface);
                NetworkState ns = mUpstreamNetworkMonitor.lookup(network);
                if (ns != null && pertainsToCurrentUpstream(ns)) {
                    // If we already have NetworkState for this network examine
                    // it immediately, because there likely will be no second
                    // EVENT_ON_AVAILABLE (it was already received).
                    handleNewUpstreamNetworkState(ns);
                }
            }

            protected void setDnsForwarders(final Network network, final LinkProperties lp) {
@@ -1393,6 +1492,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                            ifaceName);
                }
            }

            protected void handleNewUpstreamNetworkState(NetworkState ns) {
                mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
            }
        }

        private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0);
@@ -1582,11 +1685,18 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                        chooseUpstreamType(mTryCell);
                        mTryCell = !mTryCell;
                        break;
                    case EVENT_UPSTREAM_LINKPROPERTIES_CHANGED:
                        NetworkState state = (NetworkState) message.obj;
                        if (mUpstreamNetworkMonitor.processLinkPropertiesChanged(state)) {
                            setDnsForwarders(state.network, state.linkProperties);
                        } else if (mCurrentUpstreamIface == null) {
                    case EVENT_UPSTREAM_CALLBACK: {
                        // First: always update local state about every network.
                        final NetworkState ns = mUpstreamNetworkMonitor.processCallback(
                                message.arg1, message.obj);

                        if (ns == null || !pertainsToCurrentUpstream(ns)) {
                            // TODO: In future, this is where upstream evaluation and selection
                            // could be handled for notifications which include sufficient data.
                            // For example, after CONNECTIVITY_ACTION listening is removed, here
                            // is where we could observe a Wi-Fi network becoming available and
                            // passing validation.
                            if (mCurrentUpstreamIface == null) {
                                // If we have no upstream interface, try to run through upstream
                                // selection again.  If, for example, IPv4 connectivity has shown up
                                // after IPv6 (e.g., 464xlat became available) we want the chance to
@@ -1594,12 +1704,36 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                                chooseUpstreamType(false);
                            }
                            break;
                    case EVENT_UPSTREAM_LOST:
                        // TODO: Re-evaluate possible upstreams. Currently upstream reevaluation
                        // is triggered via received CONNECTIVITY_ACTION broadcasts that result
                        // in being passed a TetherMasterSM.CMD_UPSTREAM_CHANGED.
                        mUpstreamNetworkMonitor.processNetworkLost((Network) message.obj);
                        }

                        switch (message.arg1) {
                            case UpstreamNetworkMonitor.EVENT_ON_AVAILABLE:
                                // The default network changed, or DUN connected
                                // before this callback was processed. Updates
                                // for the current NetworkCapabilities and
                                // LinkProperties have been requested (default
                                // request) or are being sent shortly (DUN). Do
                                // nothing until they arrive; if no updates
                                // arrive there's nothing to do.
                                break;
                            case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES:
                                handleNewUpstreamNetworkState(ns);
                                break;
                            case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
                                setDnsForwarders(ns.network, ns.linkProperties);
                                handleNewUpstreamNetworkState(ns);
                                break;
                            case UpstreamNetworkMonitor.EVENT_ON_LOST:
                                // TODO: Re-evaluate possible upstreams. Currently upstream
                                // reevaluation is triggered via received CONNECTIVITY_ACTION
                                // broadcasts that result in being passed a
                                // TetherMasterSM.CMD_UPSTREAM_CHANGED.
                                break;
                            default:
                                break;
                        }
                        break;
                    }
                    default:
                        retValue = false;
                        break;