UpstreamNetworkMonitor.java revision b583b03675492280ab87f1eff30c05709cafba23
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
19dd8e8911c69dd68d268f892373b174bc7b422db8Erik Klineimport static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
20dd8e8911c69dd68d268f892373b174bc7b422db8Erik Klineimport static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
21dd8e8911c69dd68d268f892373b174bc7b422db8Erik Kline
229bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.content.Context;
23b583b03675492280ab87f1eff30c05709cafba23Erik Klineimport android.os.Handler;
24b583b03675492280ab87f1eff30c05709cafba23Erik Klineimport android.os.Looper;
259bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.ConnectivityManager;
269bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.ConnectivityManager.NetworkCallback;
279bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.LinkProperties;
289bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.Network;
299bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkCapabilities;
309bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkRequest;
319bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkState;
329bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.util.Log;
339bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
34885a9098cf19eaee5a164c5ca771aec5926f2efdErik Klineimport com.android.internal.annotations.VisibleForTesting;
359bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport com.android.internal.util.StateMachine;
369bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
379bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport java.util.HashMap;
389bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
399bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
409bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline/**
419bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * A class to centralize all the network and link properties information
429bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * pertaining to the current and any potential upstream network.
439bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *
449bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * Calling #start() registers two callbacks: one to track the system default
45d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * network and a second to observe all networks.  The latter is necessary
46d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * while the expression of preferred upstreams remains a list of legacy
47d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * connectivity types.  In future, this can be revisited.
489bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *
499bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * The methods and data members of this class are only to be accessed and
509bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * modified from the tethering master state machine thread. Any other
519bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * access semantics would necessitate the addition of locking.
529bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *
539bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * TODO: Move upstream selection logic here.
549bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline *
55d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * All callback methods are run on the same thread as the specified target
56d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * state machine.  This class does not require locking when accessed from this
57d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * thread.  Access from other threads is not advised.
58d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline *
599bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * @hide
609bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline */
619bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klinepublic class UpstreamNetworkMonitor {
629bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private static final String TAG = UpstreamNetworkMonitor.class.getSimpleName();
639bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private static final boolean DBG = false;
649bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private static final boolean VDBG = false;
659bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
669bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public static final int EVENT_ON_AVAILABLE      = 1;
679bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public static final int EVENT_ON_CAPABILITIES   = 2;
689bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public static final int EVENT_ON_LINKPROPERTIES = 3;
699bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public static final int EVENT_ON_LOST           = 4;
709bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
7135bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline    private static final int CALLBACK_LISTEN_ALL = 1;
7235bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline    private static final int CALLBACK_TRACK_DEFAULT = 2;
7335bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline    private static final int CALLBACK_MOBILE_REQUEST = 3;
74d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline
759bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private final Context mContext;
769bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private final StateMachine mTarget;
77b583b03675492280ab87f1eff30c05709cafba23Erik Kline    private final Handler mHandler;
789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private final int mWhat;
799bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
809bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private ConnectivityManager mCM;
81d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline    private NetworkCallback mListenAllCallback;
829bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private NetworkCallback mDefaultNetworkCallback;
839bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private NetworkCallback mMobileNetworkCallback;
849bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private boolean mDunRequired;
85d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline    private Network mCurrentDefault;
869bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
879bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, int what) {
889bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mContext = ctx;
899bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mTarget = tgt;
90b583b03675492280ab87f1eff30c05709cafba23Erik Kline        mHandler = mTarget.getHandler();
919bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mWhat = what;
929bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
939bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
94885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline    @VisibleForTesting
95885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline    public UpstreamNetworkMonitor(StateMachine tgt, int what, ConnectivityManager cm) {
96885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline        this(null, tgt, what);
97885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline        mCM = cm;
98885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline    }
99885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline
1009bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public void start() {
1019bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        stop();
1029bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
103d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        final NetworkRequest listenAllRequest = new NetworkRequest.Builder()
104d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline                .clearCapabilities().build();
10535bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline        mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL);
106b583b03675492280ab87f1eff30c05709cafba23Erik Kline        cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler);
1079bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
10835bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline        mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_TRACK_DEFAULT);
109b583b03675492280ab87f1eff30c05709cafba23Erik Kline        cm().registerDefaultNetworkCallback(mDefaultNetworkCallback, mHandler);
1109bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1119bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1129bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public void stop() {
1139bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        releaseMobileNetworkRequest();
1149bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1159bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        releaseCallback(mDefaultNetworkCallback);
1169bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mDefaultNetworkCallback = null;
1179bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
118d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        releaseCallback(mListenAllCallback);
119d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        mListenAllCallback = null;
1209bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1219bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mNetworkMap.clear();
1229bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1239bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
124efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline    public void updateMobileRequiresDun(boolean dunRequired) {
1259bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        final boolean valueChanged = (mDunRequired != dunRequired);
1269bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mDunRequired = dunRequired;
1279bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (valueChanged && mobileNetworkRequested()) {
1289bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            releaseMobileNetworkRequest();
1299bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            registerMobileNetworkRequest();
1309bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
1319bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1329bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1339bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public boolean mobileNetworkRequested() {
1349bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        return (mMobileNetworkCallback != null);
1359bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1369bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1379bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public void registerMobileNetworkRequest() {
138efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline        if (mMobileNetworkCallback != null) {
139efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline            Log.e(TAG, "registerMobileNetworkRequest() already registered");
140efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline            return;
141efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline        }
1429bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
14335bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline        // The following use of the legacy type system cannot be removed until
14435bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline        // after upstream selection no longer finds networks by legacy type.
14535bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline        // See also http://b/34364553 .
14635bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline        final int legacyType = mDunRequired ? TYPE_MOBILE_DUN : TYPE_MOBILE_HIPRI;
14735bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline
14835bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline        final NetworkRequest mobileUpstreamRequest = new NetworkRequest.Builder()
14935bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline                .setCapabilities(ConnectivityManager.networkCapabilitiesForType(legacyType))
15035bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline                .build();
1519bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1529bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // The existing default network and DUN callbacks will be notified.
1539bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        // Therefore, to avoid duplicate notifications, we only register a no-op.
15435bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline        mMobileNetworkCallback = new UpstreamNetworkCallback(CALLBACK_MOBILE_REQUEST);
1559bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
156efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline        // TODO: Change the timeout from 0 (no onUnavailable callback) to some
157efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline        // moderate callback timeout. This might be useful for updating some UI.
158efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline        // Additionally, we log a message to aid in any subsequent debugging.
159efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline        Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
1609bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
161b583b03675492280ab87f1eff30c05709cafba23Erik Kline        cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, legacyType, mHandler);
1629bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1639bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1649bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public void releaseMobileNetworkRequest() {
1659bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (mMobileNetworkCallback == null) return;
1669bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1679bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        cm().unregisterNetworkCallback(mMobileNetworkCallback);
1689bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mMobileNetworkCallback = null;
1699bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1709bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
1719bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    public NetworkState lookup(Network network) {
1729bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        return (network != null) ? mNetworkMap.get(network) : null;
1739bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
1749bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
175d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline    private void handleAvailable(int callbackType, Network network) {
176d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        if (VDBG) Log.d(TAG, "EVENT_ON_AVAILABLE for " + network);
177d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline
1789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (!mNetworkMap.containsKey(network)) {
1799bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            mNetworkMap.put(network,
1809bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                    new NetworkState(null, null, null, network, null, null));
1819bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
1829bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
183d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // Always request whatever extra information we can, in case this
184d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // was already up when start() was called, in which case we would
185d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // not have been notified of any information that had not changed.
18635bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline        switch (callbackType) {
18735bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline            case CALLBACK_LISTEN_ALL:
18835bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline                break;
18935bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline            case CALLBACK_TRACK_DEFAULT:
19032858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                if (mDefaultNetworkCallback == null) {
19132858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                    // The callback was unregistered in the interval between
192b583b03675492280ab87f1eff30c05709cafba23Erik Kline                    // ConnectivityService enqueueing onAvailable() and our
193b583b03675492280ab87f1eff30c05709cafba23Erik Kline                    // handling of it here on the mHandler thread.
194b583b03675492280ab87f1eff30c05709cafba23Erik Kline                    //
19532858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                    // Clean-up of this network entry is deferred to the
19632858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                    // handling of onLost() by other callbacks.
197b583b03675492280ab87f1eff30c05709cafba23Erik Kline                    //
198b583b03675492280ab87f1eff30c05709cafba23Erik Kline                    // These request*() calls can be deleted post oag/339444.
19932858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                    return;
20032858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                }
20132858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline
20235bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline                cm().requestNetworkCapabilities(mDefaultNetworkCallback);
20335bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline                cm().requestLinkProperties(mDefaultNetworkCallback);
20435bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline                mCurrentDefault = network;
20535bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline                break;
20635bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline            case CALLBACK_MOBILE_REQUEST:
20732858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                if (mMobileNetworkCallback == null) {
20832858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                    // The callback was unregistered in the interval between
209b583b03675492280ab87f1eff30c05709cafba23Erik Kline                    // ConnectivityService enqueueing onAvailable() and our
210b583b03675492280ab87f1eff30c05709cafba23Erik Kline                    // handling of it here on the mHandler thread.
211b583b03675492280ab87f1eff30c05709cafba23Erik Kline                    //
21232858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                    // Clean-up of this network entry is deferred to the
21332858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                    // handling of onLost() by other callbacks.
214b583b03675492280ab87f1eff30c05709cafba23Erik Kline                    //
215b583b03675492280ab87f1eff30c05709cafba23Erik Kline                    // These request*() calls can be deleted post oag/339444.
21632858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                    return;
21732858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline                }
21832858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline
21935bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline                cm().requestNetworkCapabilities(mMobileNetworkCallback);
22035bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline                cm().requestLinkProperties(mMobileNetworkCallback);
22135bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline                break;
222d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        }
2239bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
224d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // Requesting updates for mListenAllCallback is not currently possible
225d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // because it's a "listen". Two possible solutions to getting updates
226d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // about networks without waiting for a change (which might never come)
227d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // are:
228d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        //
229d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        //     [1] extend request{NetworkCapabilities,LinkProperties}() to
230d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        //         take a Network argument and have ConnectivityService do
231d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        //         what's required (if the network satisfies the request)
232d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        //
233d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        //     [2] explicitly file a NetworkRequest for each connectivity type
234d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        //         listed as a preferred upstream and wait for these callbacks
235d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        //         to be notified (requires tracking many more callbacks).
236d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        //
237d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // Until this is addressed, networks that exist prior to the "listen"
238d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // registration and which do not subsequently change will not cause
239d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // us to learn their NetworkCapabilities nor their LinkProperties.
240d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline
241d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // TODO: If sufficient information is available to select a more
242d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // preferable upstream, do so now and notify the target.
2439bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        notifyTarget(EVENT_ON_AVAILABLE, network);
2449bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
2459bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2469bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void handleNetCap(Network network, NetworkCapabilities newNc) {
247d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        final NetworkState prev = mNetworkMap.get(network);
248d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        if (prev == null || newNc.equals(prev.networkCapabilities)) {
249d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // Ignore notifications about networks for which we have not yet
250d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // received onAvailable() (should never happen) and any duplicate
251d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // notifications (e.g. matching more than one of our callbacks).
2529bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            return;
2539bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
254d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline
2559bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (VDBG) {
2569bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s",
2579bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                    network, newNc));
2589bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2599bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
260d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        mNetworkMap.put(network, new NetworkState(
261d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline                null, prev.linkProperties, newNc, network, null, null));
262d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // TODO: If sufficient information is available to select a more
263d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // preferable upstream, do so now and notify the target.
2649bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        notifyTarget(EVENT_ON_CAPABILITIES, network);
2659bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
2669bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
2679bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void handleLinkProp(Network network, LinkProperties newLp) {
268d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        final NetworkState prev = mNetworkMap.get(network);
269d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        if (prev == null || newLp.equals(prev.linkProperties)) {
270d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // Ignore notifications about networks for which we have not yet
271d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // received onAvailable() (should never happen) and any duplicate
272d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // notifications (e.g. matching more than one of our callbacks).
2739bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            return;
2749bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
275d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline
2769bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (VDBG) {
2779bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s",
2789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline                    network, newLp));
2799bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
2809bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
281d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        mNetworkMap.put(network, new NetworkState(
282d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline                null, newLp, prev.networkCapabilities, network, null, null));
283d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // TODO: If sufficient information is available to select a more
284d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // preferable upstream, do so now and notify the target.
2859bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        notifyTarget(EVENT_ON_LINKPROPERTIES, network);
2869bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
2879bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
288d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline    private void handleLost(int callbackType, Network network) {
28935bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline        if (callbackType == CALLBACK_TRACK_DEFAULT) {
290d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            mCurrentDefault = null;
291d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // Receiving onLost() for a default network does not necessarily
292d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // mean the network is gone.  We wait for a separate notification
293d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // on either the LISTEN_ALL or MOBILE_REQUEST callbacks before
294d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // clearing all state.
2959bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            return;
2969bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
297d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline
298d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        if (!mNetworkMap.containsKey(network)) {
299d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // Ignore loss of networks about which we had not previously
300d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // learned any information or for which we have already processed
301d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            // an onLost() notification.
302d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            return;
3039bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
304d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline
305d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        if (VDBG) Log.d(TAG, "EVENT_ON_LOST for " + network);
306d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline
307d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // TODO: If sufficient information is available to select a more
308d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // preferable upstream, do so now and notify the target.  Likewise,
309d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // if the current upstream network is gone, notify the target of the
310d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        // fact that we now have no upstream at all.
3119bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        notifyTarget(EVENT_ON_LOST, mNetworkMap.remove(network));
3129bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
3139bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
3149bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    // Fetch (and cache) a ConnectivityManager only if and when we need one.
3159bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private ConnectivityManager cm() {
3169bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (mCM == null) {
3179bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline            mCM = mContext.getSystemService(ConnectivityManager.class);
3189bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
3199bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        return mCM;
3209bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
3219bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
3229bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    /**
323b583b03675492280ab87f1eff30c05709cafba23Erik Kline     * A NetworkCallback class that handles information of interest directly
324b583b03675492280ab87f1eff30c05709cafba23Erik Kline     * in the thread on which it is invoked. To avoid locking, this MUST be
325b583b03675492280ab87f1eff30c05709cafba23Erik Kline     * run on the same thread as the target state machine's handler.
3269bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline     */
3279bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private class UpstreamNetworkCallback extends NetworkCallback {
328d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        private final int mCallbackType;
329d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline
330d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        UpstreamNetworkCallback(int callbackType) {
331d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline            mCallbackType = callbackType;
332d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline        }
333d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline
3349bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        @Override
3359bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        public void onAvailable(Network network) {
336b583b03675492280ab87f1eff30c05709cafba23Erik Kline            checkExpectedThread();
337b583b03675492280ab87f1eff30c05709cafba23Erik Kline            handleAvailable(mCallbackType, network);
3389bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
3399bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
3409bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        @Override
3419bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
342b583b03675492280ab87f1eff30c05709cafba23Erik Kline            checkExpectedThread();
343b583b03675492280ab87f1eff30c05709cafba23Erik Kline            handleNetCap(network, newNc);
3449bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
3459bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
3469bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        @Override
3479bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
348b583b03675492280ab87f1eff30c05709cafba23Erik Kline            checkExpectedThread();
349b583b03675492280ab87f1eff30c05709cafba23Erik Kline            handleLinkProp(network, newLp);
3509bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
3519bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
352b583b03675492280ab87f1eff30c05709cafba23Erik Kline        // TODO: Handle onNetworkSuspended();
353b583b03675492280ab87f1eff30c05709cafba23Erik Kline        // TODO: Handle onNetworkResumed();
354b583b03675492280ab87f1eff30c05709cafba23Erik Kline
3559bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        @Override
3569bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        public void onLost(Network network) {
357b583b03675492280ab87f1eff30c05709cafba23Erik Kline            checkExpectedThread();
358b583b03675492280ab87f1eff30c05709cafba23Erik Kline            handleLost(mCallbackType, network);
359b583b03675492280ab87f1eff30c05709cafba23Erik Kline        }
360b583b03675492280ab87f1eff30c05709cafba23Erik Kline
361b583b03675492280ab87f1eff30c05709cafba23Erik Kline        private void checkExpectedThread() {
362b583b03675492280ab87f1eff30c05709cafba23Erik Kline            if (Looper.myLooper() != mHandler.getLooper()) {
363b583b03675492280ab87f1eff30c05709cafba23Erik Kline                Log.wtf(TAG, "Handling callback in unexpected thread.");
364b583b03675492280ab87f1eff30c05709cafba23Erik Kline            }
3659bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        }
3669bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
3679bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
3689bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void releaseCallback(NetworkCallback cb) {
3699bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        if (cb != null) cm().unregisterNetworkCallback(cb);
3709bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
3719bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
3729bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void notifyTarget(int which, Network network) {
3739bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        notifyTarget(which, mNetworkMap.get(network));
3749bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
3759bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline
3769bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    private void notifyTarget(int which, NetworkState netstate) {
3779bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline        mTarget.sendMessage(mWhat, which, 0, netstate);
3789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline    }
3799bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline}
380