UpstreamNetworkMonitor.java revision 885a9098cf19eaee5a164c5ca771aec5926f2efd
19bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline/*
29bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * Copyright (C) 2017 The Android Open Source Project
39bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *
49bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * Licensed under the Apache License, Version 2.0 (the "License");
59bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * you may not use this file except in compliance with the License.
69bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * You may obtain a copy of the License at
79bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *
89bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *      http://www.apache.org/licenses/LICENSE-2.0
99bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *
109bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * Unless required by applicable law or agreed to in writing, software
119bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * distributed under the License is distributed on an "AS IS" BASIS,
129bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * See the License for the specific language governing permissions and
149bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * limitations under the License.
159bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline */
169bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
179bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klinepackage com.android.server.connectivity.tethering;
189bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
199bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.content.Context;
209bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.ConnectivityManager;
219bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.ConnectivityManager.NetworkCallback;
229bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.LinkProperties;
239bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.Network;
249bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkCapabilities;
259bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkRequest;
269bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkState;
279bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.util.Log;
289bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
29885a9098cf19eaee5a164c5ca771aec5926f2efdErik Klineimport com.android.internal.annotations.VisibleForTesting;
309bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport com.android.internal.util.StateMachine;
319bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
329bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport java.util.HashMap;
339bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
349bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
359bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline/**
369bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * A class to centralize all the network and link properties information
379bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * pertaining to the current and any potential upstream network.
389bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *
399bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * Calling #start() registers two callbacks: one to track the system default
409bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * network and a second to specifically observe TYPE_MOBILE_DUN networks.
419bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *
429bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * The methods and data members of this class are only to be accessed and
439bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * modified from the tethering master state machine thread. Any other
449bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * access semantics would necessitate the addition of locking.
459bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *
469bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * TODO: Move upstream selection logic here.
479bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *
489bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * @hide
499bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline */
509bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klinepublic class UpstreamNetworkMonitor {
519bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private static final String TAG = UpstreamNetworkMonitor.class.getSimpleName();
529bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private static final boolean DBG = false;
539bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private static final boolean VDBG = false;
549bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
559bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public static final int EVENT_ON_AVAILABLE      = 1;
569bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public static final int EVENT_ON_CAPABILITIES   = 2;
579bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public static final int EVENT_ON_LINKPROPERTIES = 3;
589bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public static final int EVENT_ON_LOST           = 4;
599bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
609bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private final Context mContext;
619bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private final StateMachine mTarget;
629bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private final int mWhat;
639bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
649bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private ConnectivityManager mCM;
659bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private NetworkCallback mDefaultNetworkCallback;
669bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private NetworkCallback mDunTetheringCallback;
679bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private NetworkCallback mMobileNetworkCallback;
689bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private boolean mDunRequired;
699bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
709bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, int what) {
719bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mContext = ctx;
729bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mTarget = tgt;
739bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mWhat = what;
749bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
759bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
76885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline    @VisibleForTesting
77885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline    public UpstreamNetworkMonitor(StateMachine tgt, int what, ConnectivityManager cm) {
78885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline        this(null, tgt, what);
79885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline        mCM = cm;
80885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline    }
81885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline
829bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public void start() {
839bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        stop();
849bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
859bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mDefaultNetworkCallback = new UpstreamNetworkCallback();
869bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        cm().registerDefaultNetworkCallback(mDefaultNetworkCallback);
879bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
889bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        final NetworkRequest dunTetheringRequest = new NetworkRequest.Builder()
899bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
909bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
919bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
929bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                .build();
939bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mDunTetheringCallback = new UpstreamNetworkCallback();
949bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        cm().registerNetworkCallback(dunTetheringRequest, mDunTetheringCallback);
959bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
969bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
979bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public void stop() {
989bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        releaseMobileNetworkRequest();
999bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1009bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        releaseCallback(mDefaultNetworkCallback);
1019bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mDefaultNetworkCallback = null;
1029bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1039bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        releaseCallback(mDunTetheringCallback);
1049bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mDunTetheringCallback = null;
1059bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1069bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mNetworkMap.clear();
1079bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1089bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1099bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public void mobileUpstreamRequiresDun(boolean dunRequired) {
1109bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        final boolean valueChanged = (mDunRequired != dunRequired);
1119bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mDunRequired = dunRequired;
1129bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (valueChanged && mobileNetworkRequested()) {
1139bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            releaseMobileNetworkRequest();
1149bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            registerMobileNetworkRequest();
1159bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
1169bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1179bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1189bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public boolean mobileNetworkRequested() {
1199bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        return (mMobileNetworkCallback != null);
1209bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1219bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1229bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public void registerMobileNetworkRequest() {
1239bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (mMobileNetworkCallback != null) return;
1249bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1259bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        final NetworkRequest.Builder builder = new NetworkRequest.Builder()
1269bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
1279bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (mDunRequired) {
1289bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
1299bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                   .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
1309bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        } else {
1319bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
1329bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
1339bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        final NetworkRequest mobileUpstreamRequest = builder.build();
1349bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1359bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // The existing default network and DUN callbacks will be notified.
1369bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // Therefore, to avoid duplicate notifications, we only register a no-op.
1379bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mMobileNetworkCallback = new NetworkCallback();
1389bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1399bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // TODO: Change the timeout from 0 (no onUnavailable callback) to use some
1409bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // moderate callback time (once timeout callbacks are implemented). This might
1419bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // be useful for updating some UI. Additionally, we should definitely log a
1429bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // message to aid in any subsequent debugging
1439bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (DBG) Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
1449bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1459bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback);
1469bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1479bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1489bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public void releaseMobileNetworkRequest() {
1499bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (mMobileNetworkCallback == null) return;
1509bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1519bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        cm().unregisterNetworkCallback(mMobileNetworkCallback);
1529bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mMobileNetworkCallback = null;
1539bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1549bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1559bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public NetworkState lookup(Network network) {
1569bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        return (network != null) ? mNetworkMap.get(network) : null;
1579bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1589bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1599bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void handleAvailable(Network network) {
1609bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (VDBG) {
1619bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            Log.d(TAG, "EVENT_ON_AVAILABLE for " + network);
1629bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
1639bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (!mNetworkMap.containsKey(network)) {
1649bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            mNetworkMap.put(network,
1659bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                    new NetworkState(null, null, null, network, null, null));
1669bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
1679bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1689bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        final ConnectivityManager cm = cm();
1699bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1709bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (mDefaultNetworkCallback != null) {
1719bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            cm.requestNetworkCapabilities(mDefaultNetworkCallback);
1729bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            cm.requestLinkProperties(mDefaultNetworkCallback);
1739bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
1749bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1759bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // Requesting updates for mDunTetheringCallback is not
1769bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // necessary. Because it's a listen, it will already have
1779bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // heard all NetworkCapabilities and LinkProperties updates
1789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // since UpstreamNetworkMonitor was started. Because we
1799bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // start UpstreamNetworkMonitor before chooseUpstreamType()
1809bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // is ever invoked (it can register a DUN request) this is
1819bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // mostly safe. However, if a DUN network is already up for
1829bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // some reason (unlikely, because DUN is restricted and,
1839bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // unless the DUN network is shared with another APN, only
1849bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // the system can request it and this is the only part of
1859bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // the system that requests it) we won't know its
1869bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // LinkProperties or NetworkCapabilities.
1879bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1889bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        notifyTarget(EVENT_ON_AVAILABLE, network);
1899bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1909bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1919bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void handleNetCap(Network network, NetworkCapabilities newNc) {
1929bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (!mNetworkMap.containsKey(network)) {
1939bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            // Ignore updates for networks for which we have not yet
1949bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            // received onAvailable() - which should never happen -
1959bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            // or for which we have already received onLost().
1969bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            return;
1979bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
1989bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (VDBG) {
1999bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s",
2009bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                    network, newNc));
2019bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2029bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2039bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        final NetworkState prev = mNetworkMap.get(network);
2049bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mNetworkMap.put(network,
2059bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                new NetworkState(null, prev.linkProperties, newNc,
2069bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                                 network, null, null));
2079bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        notifyTarget(EVENT_ON_CAPABILITIES, network);
2089bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
2099bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2109bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void handleLinkProp(Network network, LinkProperties newLp) {
2119bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (!mNetworkMap.containsKey(network)) {
2129bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            // Ignore updates for networks for which we have not yet
2139bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            // received onAvailable() - which should never happen -
2149bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            // or for which we have already received onLost().
2159bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            return;
2169bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2179bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (VDBG) {
2189bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s",
2199bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                    network, newLp));
2209bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2219bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2229bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        final NetworkState prev = mNetworkMap.get(network);
2239bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mNetworkMap.put(network,
2249bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                new NetworkState(null, newLp, prev.networkCapabilities,
2259bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                                 network, null, null));
2269bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        notifyTarget(EVENT_ON_LINKPROPERTIES, network);
2279bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
2289bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2299bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void handleLost(Network network) {
2309bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (!mNetworkMap.containsKey(network)) {
2319bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            // Ignore updates for networks for which we have not yet
2329bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            // received onAvailable() - which should never happen -
2339bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            // or for which we have already received onLost().
2349bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            return;
2359bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2369bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (VDBG) {
2379bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            Log.d(TAG, "EVENT_ON_LOST for " + network);
2389bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2399bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        notifyTarget(EVENT_ON_LOST, mNetworkMap.remove(network));
2409bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
2419bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2429bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    // Fetch (and cache) a ConnectivityManager only if and when we need one.
2439bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private ConnectivityManager cm() {
2449bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (mCM == null) {
2459bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            mCM = mContext.getSystemService(ConnectivityManager.class);
2469bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2479bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        return mCM;
2489bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
2499bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2509bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    /**
2519bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline     * A NetworkCallback class that relays information of interest to the
2529bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline     * tethering master state machine thread for subsequent processing.
2539bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline     */
2549bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private class UpstreamNetworkCallback extends NetworkCallback {
2559bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        @Override
2569bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        public void onAvailable(Network network) {
2579bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            mTarget.getHandler().post(() -> handleAvailable(network));
2589bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2599bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2609bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        @Override
2619bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
2629bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            mTarget.getHandler().post(() -> handleNetCap(network, newNc));
2639bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2649bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2659bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        @Override
2669bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
2679bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            mTarget.getHandler().post(() -> handleLinkProp(network, newLp));
2689bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2699bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2709bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        @Override
2719bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        public void onLost(Network network) {
2729bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            mTarget.getHandler().post(() -> handleLost(network));
2739bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2749bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
2759bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2769bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void releaseCallback(NetworkCallback cb) {
2779bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (cb != null) cm().unregisterNetworkCallback(cb);
2789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
2799bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2809bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void notifyTarget(int which, Network network) {
2819bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        notifyTarget(which, mNetworkMap.get(network));
2829bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
2839bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2849bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void notifyTarget(int which, NetworkState netstate) {
2859bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mTarget.sendMessage(mWhat, which, 0, netstate);
2869bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
2879bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline}
288