UpstreamNetworkMonitor.java revision 3760999e347ae1cfa25087451638de8ddc79c9f6
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 193760999e347ae1cfa25087451638de8ddc79c9f6Erik Klineimport static android.net.ConnectivityManager.getNetworkTypeName; 203760999e347ae1cfa25087451638de8ddc79c9f6Erik Klineimport static android.net.ConnectivityManager.TYPE_NONE; 21dd8e8911c69dd68d268f892373b174bc7b422db8Erik Klineimport static android.net.ConnectivityManager.TYPE_MOBILE_DUN; 22dd8e8911c69dd68d268f892373b174bc7b422db8Erik Klineimport static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; 23dd8e8911c69dd68d268f892373b174bc7b422db8Erik Kline 249bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.content.Context; 25b583b03675492280ab87f1eff30c05709cafba23Erik Klineimport android.os.Handler; 26b583b03675492280ab87f1eff30c05709cafba23Erik Klineimport android.os.Looper; 279bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.ConnectivityManager; 289bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.ConnectivityManager.NetworkCallback; 299bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.LinkProperties; 309bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.Network; 319bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkCapabilities; 329bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkRequest; 339bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkState; 347747fd4ce055e8e1f6381062a58b867728f57d85Erik Klineimport android.net.util.SharedLog; 359bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.util.Log; 369bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 37885a9098cf19eaee5a164c5ca771aec5926f2efdErik Klineimport com.android.internal.annotations.VisibleForTesting; 389bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport com.android.internal.util.StateMachine; 399bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 409bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport java.util.HashMap; 419bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 429bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 439bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline/** 449bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * A class to centralize all the network and link properties information 459bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * pertaining to the current and any potential upstream network. 469bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * 479bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * Calling #start() registers two callbacks: one to track the system default 48d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * network and a second to observe all networks. The latter is necessary 49d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * while the expression of preferred upstreams remains a list of legacy 50d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * connectivity types. In future, this can be revisited. 519bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * 529bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * The methods and data members of this class are only to be accessed and 539bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * modified from the tethering master state machine thread. Any other 549bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * access semantics would necessitate the addition of locking. 559bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * 569bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * TODO: Move upstream selection logic here. 579bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * 58d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * All callback methods are run on the same thread as the specified target 59d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * state machine. This class does not require locking when accessed from this 60d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * thread. Access from other threads is not advised. 61d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * 629bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * @hide 639bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline */ 649bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klinepublic class UpstreamNetworkMonitor { 659bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private static final String TAG = UpstreamNetworkMonitor.class.getSimpleName(); 669bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private static final boolean DBG = false; 679bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private static final boolean VDBG = false; 689bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 699bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public static final int EVENT_ON_AVAILABLE = 1; 709bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public static final int EVENT_ON_CAPABILITIES = 2; 719bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public static final int EVENT_ON_LINKPROPERTIES = 3; 729bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public static final int EVENT_ON_LOST = 4; 739bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 7435bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline private static final int CALLBACK_LISTEN_ALL = 1; 7535bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline private static final int CALLBACK_TRACK_DEFAULT = 2; 7635bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline private static final int CALLBACK_MOBILE_REQUEST = 3; 77d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private final Context mContext; 797747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline private final SharedLog mLog; 809bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private final StateMachine mTarget; 81b583b03675492280ab87f1eff30c05709cafba23Erik Kline private final Handler mHandler; 829bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private final int mWhat; 839bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>(); 849bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private ConnectivityManager mCM; 85d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline private NetworkCallback mListenAllCallback; 869bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private NetworkCallback mDefaultNetworkCallback; 879bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private NetworkCallback mMobileNetworkCallback; 889bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private boolean mDunRequired; 89d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline private Network mCurrentDefault; 909bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 917747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, int what, SharedLog log) { 929bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mContext = ctx; 939bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mTarget = tgt; 94b583b03675492280ab87f1eff30c05709cafba23Erik Kline mHandler = mTarget.getHandler(); 959bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mWhat = what; 967747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline mLog = log.forSubComponent(TAG); 979bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 989bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 99885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline @VisibleForTesting 1007747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline public UpstreamNetworkMonitor( 1017747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline StateMachine tgt, int what, ConnectivityManager cm, SharedLog log) { 1027747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline this(null, tgt, what, log); 103885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline mCM = cm; 104885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline } 105885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline 1069bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void start() { 1079bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline stop(); 1089bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 109d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline final NetworkRequest listenAllRequest = new NetworkRequest.Builder() 110d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline .clearCapabilities().build(); 11135bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL); 112b583b03675492280ab87f1eff30c05709cafba23Erik Kline cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler); 1139bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 11435bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_TRACK_DEFAULT); 115b583b03675492280ab87f1eff30c05709cafba23Erik Kline cm().registerDefaultNetworkCallback(mDefaultNetworkCallback, mHandler); 1169bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1179bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1189bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void stop() { 1199bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline releaseMobileNetworkRequest(); 1209bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1219bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline releaseCallback(mDefaultNetworkCallback); 1229bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mDefaultNetworkCallback = null; 1239bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 124d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline releaseCallback(mListenAllCallback); 125d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline mListenAllCallback = null; 1269bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1279bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mNetworkMap.clear(); 1289bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1299bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 130efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline public void updateMobileRequiresDun(boolean dunRequired) { 1319bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline final boolean valueChanged = (mDunRequired != dunRequired); 1329bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mDunRequired = dunRequired; 1339bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (valueChanged && mobileNetworkRequested()) { 1349bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline releaseMobileNetworkRequest(); 1359bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline registerMobileNetworkRequest(); 1369bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1379bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1389bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1399bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public boolean mobileNetworkRequested() { 1409bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline return (mMobileNetworkCallback != null); 1419bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1429bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1439bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void registerMobileNetworkRequest() { 144efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline if (mMobileNetworkCallback != null) { 1457747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline mLog.e("registerMobileNetworkRequest() already registered"); 146efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline return; 147efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline } 1489bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 14935bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline // The following use of the legacy type system cannot be removed until 15035bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline // after upstream selection no longer finds networks by legacy type. 15135bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline // See also http://b/34364553 . 15235bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline final int legacyType = mDunRequired ? TYPE_MOBILE_DUN : TYPE_MOBILE_HIPRI; 15335bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline 15435bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline final NetworkRequest mobileUpstreamRequest = new NetworkRequest.Builder() 15535bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline .setCapabilities(ConnectivityManager.networkCapabilitiesForType(legacyType)) 15635bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline .build(); 1579bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1589bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline // The existing default network and DUN callbacks will be notified. 1599bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline // Therefore, to avoid duplicate notifications, we only register a no-op. 16035bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline mMobileNetworkCallback = new UpstreamNetworkCallback(CALLBACK_MOBILE_REQUEST); 1619bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 162efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline // TODO: Change the timeout from 0 (no onUnavailable callback) to some 163efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline // moderate callback timeout. This might be useful for updating some UI. 164efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline // Additionally, we log a message to aid in any subsequent debugging. 1657747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline mLog.i("requesting mobile upstream network: " + mobileUpstreamRequest); 1669bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 167b583b03675492280ab87f1eff30c05709cafba23Erik Kline cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, legacyType, mHandler); 1689bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1699bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1709bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void releaseMobileNetworkRequest() { 1719bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (mMobileNetworkCallback == null) return; 1729bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1739bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline cm().unregisterNetworkCallback(mMobileNetworkCallback); 1749bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mMobileNetworkCallback = null; 1759bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1769bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1779bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public NetworkState lookup(Network network) { 1789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline return (network != null) ? mNetworkMap.get(network) : null; 1799bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1809bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1813760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // So many TODOs here, but chief among them is: make this functionality an 1823760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // integral part of this class such that whenever a higher priority network 1833760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // becomes available and useful we (a) file a request to keep it up as 1843760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // necessary and (b) change all upstream tracking state accordingly (by 1853760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // passing LinkProperties up to Tethering). 1863760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // 1873760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // Next TODO: return NetworkState instead of just the type. 1883760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline public int selectPreferredUpstreamType(Iterable<Integer> preferredTypes) { 1893760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType( 1903760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline mNetworkMap.values(), preferredTypes); 1913760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 1923760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline mLog.log("preferred upstream type: " + getNetworkTypeName(typeStatePair.type)); 1933760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 1943760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline switch (typeStatePair.type) { 1953760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline case TYPE_MOBILE_DUN: 1963760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline case TYPE_MOBILE_HIPRI: 1973760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // If we're on DUN, put our own grab on it. 1983760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline registerMobileNetworkRequest(); 1993760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline break; 2003760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline case TYPE_NONE: 2013760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline break; 2023760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline default: 2033760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline /* If we've found an active upstream connection that's not DUN/HIPRI 2043760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline * we should stop any outstanding DUN/HIPRI start requests. 2053760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline * 2063760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline * If we found NONE we don't want to do this as we want any previous 2073760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline * requests to keep trying to bring up something we can use. 2083760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline */ 2093760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline releaseMobileNetworkRequest(); 2103760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline break; 2113760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 2123760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 2133760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline return typeStatePair.type; 2143760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 2153760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 216d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline private void handleAvailable(int callbackType, Network network) { 217d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline if (VDBG) Log.d(TAG, "EVENT_ON_AVAILABLE for " + network); 218d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 2199bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (!mNetworkMap.containsKey(network)) { 2209bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mNetworkMap.put(network, 2219bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline new NetworkState(null, null, null, network, null, null)); 2229bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 2239bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 224d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Always request whatever extra information we can, in case this 225d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // was already up when start() was called, in which case we would 226d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // not have been notified of any information that had not changed. 22735bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline switch (callbackType) { 22835bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline case CALLBACK_LISTEN_ALL: 22935bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline break; 230465c46d555c867caf40333db197ef97cff75a754Erik Kline 23135bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline case CALLBACK_TRACK_DEFAULT: 23232858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline if (mDefaultNetworkCallback == null) { 23332858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // The callback was unregistered in the interval between 234b583b03675492280ab87f1eff30c05709cafba23Erik Kline // ConnectivityService enqueueing onAvailable() and our 235b583b03675492280ab87f1eff30c05709cafba23Erik Kline // handling of it here on the mHandler thread. 236b583b03675492280ab87f1eff30c05709cafba23Erik Kline // 23732858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // Clean-up of this network entry is deferred to the 23832858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // handling of onLost() by other callbacks. 239b583b03675492280ab87f1eff30c05709cafba23Erik Kline // 240b583b03675492280ab87f1eff30c05709cafba23Erik Kline // These request*() calls can be deleted post oag/339444. 24132858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline return; 24232858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline } 24335bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline mCurrentDefault = network; 24435bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline break; 245465c46d555c867caf40333db197ef97cff75a754Erik Kline 24635bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline case CALLBACK_MOBILE_REQUEST: 24732858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline if (mMobileNetworkCallback == null) { 24832858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // The callback was unregistered in the interval between 249b583b03675492280ab87f1eff30c05709cafba23Erik Kline // ConnectivityService enqueueing onAvailable() and our 250b583b03675492280ab87f1eff30c05709cafba23Erik Kline // handling of it here on the mHandler thread. 251b583b03675492280ab87f1eff30c05709cafba23Erik Kline // 25232858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // Clean-up of this network entry is deferred to the 25332858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // handling of onLost() by other callbacks. 25432858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline return; 25532858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline } 25635bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline break; 257d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline } 2589bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 259d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Requesting updates for mListenAllCallback is not currently possible 260d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // because it's a "listen". Two possible solutions to getting updates 261d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // about networks without waiting for a change (which might never come) 262d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // are: 263d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // 264d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // [1] extend request{NetworkCapabilities,LinkProperties}() to 265d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // take a Network argument and have ConnectivityService do 266d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // what's required (if the network satisfies the request) 267d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // 268d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // [2] explicitly file a NetworkRequest for each connectivity type 269d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // listed as a preferred upstream and wait for these callbacks 270d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // to be notified (requires tracking many more callbacks). 271d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // 272d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Until this is addressed, networks that exist prior to the "listen" 273d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // registration and which do not subsequently change will not cause 274d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // us to learn their NetworkCapabilities nor their LinkProperties. 275d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 276d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // TODO: If sufficient information is available to select a more 277d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // preferable upstream, do so now and notify the target. 2789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline notifyTarget(EVENT_ON_AVAILABLE, network); 2799bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 2809bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 2819bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private void handleNetCap(Network network, NetworkCapabilities newNc) { 282d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline final NetworkState prev = mNetworkMap.get(network); 283d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline if (prev == null || newNc.equals(prev.networkCapabilities)) { 284d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Ignore notifications about networks for which we have not yet 285d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // received onAvailable() (should never happen) and any duplicate 286d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // notifications (e.g. matching more than one of our callbacks). 2879bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline return; 2889bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 289d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 2909bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (VDBG) { 2919bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s", 2929bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline network, newNc)); 2939bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 2949bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 295d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline mNetworkMap.put(network, new NetworkState( 296d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline null, prev.linkProperties, newNc, network, null, null)); 297d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // TODO: If sufficient information is available to select a more 298d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // preferable upstream, do so now and notify the target. 2999bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline notifyTarget(EVENT_ON_CAPABILITIES, network); 3009bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3019bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 3029bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private void handleLinkProp(Network network, LinkProperties newLp) { 303d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline final NetworkState prev = mNetworkMap.get(network); 304d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline if (prev == null || newLp.equals(prev.linkProperties)) { 305d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Ignore notifications about networks for which we have not yet 306d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // received onAvailable() (should never happen) and any duplicate 307d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // notifications (e.g. matching more than one of our callbacks). 3089bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline return; 3099bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 310d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 3119bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (VDBG) { 3129bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s", 3139bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline network, newLp)); 3149bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3159bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 316d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline mNetworkMap.put(network, new NetworkState( 317d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline null, newLp, prev.networkCapabilities, network, null, null)); 318d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // TODO: If sufficient information is available to select a more 319d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // preferable upstream, do so now and notify the target. 3209bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline notifyTarget(EVENT_ON_LINKPROPERTIES, network); 3219bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3229bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 323d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline private void handleLost(int callbackType, Network network) { 32435bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline if (callbackType == CALLBACK_TRACK_DEFAULT) { 325d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline mCurrentDefault = null; 326d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Receiving onLost() for a default network does not necessarily 327d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // mean the network is gone. We wait for a separate notification 328d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // on either the LISTEN_ALL or MOBILE_REQUEST callbacks before 329d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // clearing all state. 3309bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline return; 3319bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 332d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 333d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline if (!mNetworkMap.containsKey(network)) { 334d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Ignore loss of networks about which we had not previously 335d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // learned any information or for which we have already processed 336d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // an onLost() notification. 337d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline return; 3389bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 339d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 340d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline if (VDBG) Log.d(TAG, "EVENT_ON_LOST for " + network); 341d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 342d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // TODO: If sufficient information is available to select a more 343d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // preferable upstream, do so now and notify the target. Likewise, 344d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // if the current upstream network is gone, notify the target of the 345d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // fact that we now have no upstream at all. 3469bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline notifyTarget(EVENT_ON_LOST, mNetworkMap.remove(network)); 3479bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3489bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 3499bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline // Fetch (and cache) a ConnectivityManager only if and when we need one. 3509bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private ConnectivityManager cm() { 3519bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (mCM == null) { 352ea9cc488eb0f096c9fd402eff49e3d30f5b6de2eErik Kline // MUST call the String variant to be able to write unittests. 353ea9cc488eb0f096c9fd402eff49e3d30f5b6de2eErik Kline mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 3549bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3559bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline return mCM; 3569bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3579bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 3589bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline /** 359b583b03675492280ab87f1eff30c05709cafba23Erik Kline * A NetworkCallback class that handles information of interest directly 360b583b03675492280ab87f1eff30c05709cafba23Erik Kline * in the thread on which it is invoked. To avoid locking, this MUST be 361b583b03675492280ab87f1eff30c05709cafba23Erik Kline * run on the same thread as the target state machine's handler. 3629bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline */ 3639bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private class UpstreamNetworkCallback extends NetworkCallback { 364d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline private final int mCallbackType; 365d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 366d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline UpstreamNetworkCallback(int callbackType) { 367d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline mCallbackType = callbackType; 368d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline } 369d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 3709bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline @Override 3719bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void onAvailable(Network network) { 372b583b03675492280ab87f1eff30c05709cafba23Erik Kline handleAvailable(mCallbackType, network); 3739bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3749bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 3759bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline @Override 3769bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) { 377b583b03675492280ab87f1eff30c05709cafba23Erik Kline handleNetCap(network, newNc); 3789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3799bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 3809bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline @Override 3819bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void onLinkPropertiesChanged(Network network, LinkProperties newLp) { 382b583b03675492280ab87f1eff30c05709cafba23Erik Kline handleLinkProp(network, newLp); 3839bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3849bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 385b583b03675492280ab87f1eff30c05709cafba23Erik Kline // TODO: Handle onNetworkSuspended(); 386b583b03675492280ab87f1eff30c05709cafba23Erik Kline // TODO: Handle onNetworkResumed(); 387b583b03675492280ab87f1eff30c05709cafba23Erik Kline 3889bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline @Override 3899bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void onLost(Network network) { 390b583b03675492280ab87f1eff30c05709cafba23Erik Kline handleLost(mCallbackType, network); 391b583b03675492280ab87f1eff30c05709cafba23Erik Kline } 3929bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3939bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 3949bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private void releaseCallback(NetworkCallback cb) { 3959bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (cb != null) cm().unregisterNetworkCallback(cb); 3969bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3979bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 3989bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private void notifyTarget(int which, Network network) { 3999bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline notifyTarget(which, mNetworkMap.get(network)); 4009bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 4019bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 4029bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private void notifyTarget(int which, NetworkState netstate) { 4039bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mTarget.sendMessage(mWhat, which, 0, netstate); 4049bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 4053760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4063760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline static private class TypeStatePair { 4073760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline public int type = TYPE_NONE; 4083760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline public NetworkState ns = null; 4093760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 4103760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4113760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline static private TypeStatePair findFirstAvailableUpstreamByType( 4123760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline Iterable<NetworkState> netStates, Iterable<Integer> preferredTypes) { 4133760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline final TypeStatePair result = new TypeStatePair(); 4143760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4153760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline for (int type : preferredTypes) { 4163760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline NetworkCapabilities nc; 4173760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline try { 4183760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline nc = ConnectivityManager.networkCapabilitiesForType(type); 4193760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } catch (IllegalArgumentException iae) { 4203760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + 4213760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline ConnectivityManager.getNetworkTypeName(type)); 4223760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline continue; 4233760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 4243760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4253760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline for (NetworkState value : netStates) { 4263760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) { 4273760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline continue; 4283760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 4293760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4303760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline result.type = type; 4313760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline result.ns = value; 4323760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline return result; 4333760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 4343760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 4353760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4363760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline return result; 4373760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 4389bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline} 439