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; 27f94833df7dbead3ebce2efeeae2b57fa0613c743Erik Klineimport android.os.Process; 289bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.ConnectivityManager; 299bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.ConnectivityManager.NetworkCallback; 303a5278f2c4d71a8f69ce1085da42904283d62785Erik Klineimport android.net.IpPrefix; 313a5278f2c4d71a8f69ce1085da42904283d62785Erik Klineimport android.net.LinkAddress; 329bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.LinkProperties; 339bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.Network; 349bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkCapabilities; 359bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkRequest; 369bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.net.NetworkState; 373a5278f2c4d71a8f69ce1085da42904283d62785Erik Klineimport android.net.util.NetworkConstants; 3832179ff81511e00aef31e8fda705be3df074ece6Erik Klineimport android.net.util.PrefixUtils; 397747fd4ce055e8e1f6381062a58b867728f57d85Erik Klineimport android.net.util.SharedLog; 409bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport android.util.Log; 419bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 42885a9098cf19eaee5a164c5ca771aec5926f2efdErik Klineimport com.android.internal.annotations.VisibleForTesting; 439bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport com.android.internal.util.StateMachine; 449bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 453a5278f2c4d71a8f69ce1085da42904283d62785Erik Klineimport java.util.Collections; 469bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klineimport java.util.HashMap; 473a5278f2c4d71a8f69ce1085da42904283d62785Erik Klineimport java.util.HashSet; 483a5278f2c4d71a8f69ce1085da42904283d62785Erik Klineimport java.util.Set; 499bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 509bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 519bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline/** 529bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * A class to centralize all the network and link properties information 539bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * pertaining to the current and any potential upstream network. 549bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * 559bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * Calling #start() registers two callbacks: one to track the system default 56d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * network and a second to observe all networks. The latter is necessary 57d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * while the expression of preferred upstreams remains a list of legacy 58d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * connectivity types. In future, this can be revisited. 599bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * 609bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * The methods and data members of this class are only to be accessed and 619bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * modified from the tethering master state machine thread. Any other 629bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * access semantics would necessitate the addition of locking. 639bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * 649bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * TODO: Move upstream selection logic here. 659bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * 66d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * All callback methods are run on the same thread as the specified target 67d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * state machine. This class does not require locking when accessed from this 68d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * thread. Access from other threads is not advised. 69d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline * 709bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline * @hide 719bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline */ 729bba340fd4edd5aea91d612a332f964b0d63cf34Erik Klinepublic class UpstreamNetworkMonitor { 739bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private static final String TAG = UpstreamNetworkMonitor.class.getSimpleName(); 749bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private static final boolean DBG = false; 759bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private static final boolean VDBG = false; 769bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 779bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public static final int EVENT_ON_AVAILABLE = 1; 789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public static final int EVENT_ON_CAPABILITIES = 2; 799bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public static final int EVENT_ON_LINKPROPERTIES = 3; 809bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public static final int EVENT_ON_LOST = 4; 8132179ff81511e00aef31e8fda705be3df074ece6Erik Kline public static final int NOTIFY_LOCAL_PREFIXES = 10; 829bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 8335bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline private static final int CALLBACK_LISTEN_ALL = 1; 8435bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline private static final int CALLBACK_TRACK_DEFAULT = 2; 8535bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline private static final int CALLBACK_MOBILE_REQUEST = 3; 86d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 879bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private final Context mContext; 887747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline private final SharedLog mLog; 899bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private final StateMachine mTarget; 90b583b03675492280ab87f1eff30c05709cafba23Erik Kline private final Handler mHandler; 919bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private final int mWhat; 929bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>(); 9332179ff81511e00aef31e8fda705be3df074ece6Erik Kline private HashSet<IpPrefix> mLocalPrefixes; 949bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private ConnectivityManager mCM; 95d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline private NetworkCallback mListenAllCallback; 969bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private NetworkCallback mDefaultNetworkCallback; 979bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private NetworkCallback mMobileNetworkCallback; 989bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private boolean mDunRequired; 9960caf7d29132262dd4a077b68daa807d22773524Erik Kline // The current system default network (not really used yet). 10060caf7d29132262dd4a077b68daa807d22773524Erik Kline private Network mDefaultInternetNetwork; 10160caf7d29132262dd4a077b68daa807d22773524Erik Kline // The current upstream network used for tethering. 10260caf7d29132262dd4a077b68daa807d22773524Erik Kline private Network mTetheringUpstreamNetwork; 1039bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1043a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) { 1059bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mContext = ctx; 1069bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mTarget = tgt; 107b583b03675492280ab87f1eff30c05709cafba23Erik Kline mHandler = mTarget.getHandler(); 1087747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline mLog = log.forSubComponent(TAG); 1093a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline mWhat = what; 11032179ff81511e00aef31e8fda705be3df074ece6Erik Kline mLocalPrefixes = new HashSet<>(); 1119bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1129bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 113885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline @VisibleForTesting 1147747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline public UpstreamNetworkMonitor( 1153a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline ConnectivityManager cm, StateMachine tgt, SharedLog log, int what) { 1163a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline this((Context) null, tgt, log, what); 117885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline mCM = cm; 118885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline } 119885a9098cf19eaee5a164c5ca771aec5926f2efdErik Kline 1209bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void start() { 1219bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline stop(); 1229bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 123d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline final NetworkRequest listenAllRequest = new NetworkRequest.Builder() 124d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline .clearCapabilities().build(); 12535bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL); 126b583b03675492280ab87f1eff30c05709cafba23Erik Kline cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler); 1279bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 12835bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_TRACK_DEFAULT); 129b583b03675492280ab87f1eff30c05709cafba23Erik Kline cm().registerDefaultNetworkCallback(mDefaultNetworkCallback, mHandler); 1309bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1319bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1329bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void stop() { 1339bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline releaseMobileNetworkRequest(); 1349bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1359bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline releaseCallback(mDefaultNetworkCallback); 1369bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mDefaultNetworkCallback = null; 13760caf7d29132262dd4a077b68daa807d22773524Erik Kline mDefaultInternetNetwork = null; 1389bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 139d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline releaseCallback(mListenAllCallback); 140d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline mListenAllCallback = null; 1419bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 14260caf7d29132262dd4a077b68daa807d22773524Erik Kline mTetheringUpstreamNetwork = null; 1439bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mNetworkMap.clear(); 1449bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1459bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 146efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline public void updateMobileRequiresDun(boolean dunRequired) { 1479bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline final boolean valueChanged = (mDunRequired != dunRequired); 1489bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mDunRequired = dunRequired; 1499bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (valueChanged && mobileNetworkRequested()) { 1509bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline releaseMobileNetworkRequest(); 1519bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline registerMobileNetworkRequest(); 1529bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1539bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1549bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1559bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public boolean mobileNetworkRequested() { 1569bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline return (mMobileNetworkCallback != null); 1579bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1589bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1599bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void registerMobileNetworkRequest() { 160efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline if (mMobileNetworkCallback != null) { 1617747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline mLog.e("registerMobileNetworkRequest() already registered"); 162efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline return; 163efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline } 1649bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 16535bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline // The following use of the legacy type system cannot be removed until 16635bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline // after upstream selection no longer finds networks by legacy type. 16735bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline // See also http://b/34364553 . 16835bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline final int legacyType = mDunRequired ? TYPE_MOBILE_DUN : TYPE_MOBILE_HIPRI; 16935bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline 17035bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline final NetworkRequest mobileUpstreamRequest = new NetworkRequest.Builder() 17135bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline .setCapabilities(ConnectivityManager.networkCapabilitiesForType(legacyType)) 17235bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline .build(); 1739bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1749bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline // The existing default network and DUN callbacks will be notified. 1759bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline // Therefore, to avoid duplicate notifications, we only register a no-op. 17635bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline mMobileNetworkCallback = new UpstreamNetworkCallback(CALLBACK_MOBILE_REQUEST); 1779bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 178efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline // TODO: Change the timeout from 0 (no onUnavailable callback) to some 179efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline // moderate callback timeout. This might be useful for updating some UI. 180efdd3f4ce04d3e1741831982ff86a58da6b542d3Erik Kline // Additionally, we log a message to aid in any subsequent debugging. 1817747fd4ce055e8e1f6381062a58b867728f57d85Erik Kline mLog.i("requesting mobile upstream network: " + mobileUpstreamRequest); 1829bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 183b583b03675492280ab87f1eff30c05709cafba23Erik Kline cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, legacyType, mHandler); 1849bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1859bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1869bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void releaseMobileNetworkRequest() { 1879bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (mMobileNetworkCallback == null) return; 1889bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1899bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline cm().unregisterNetworkCallback(mMobileNetworkCallback); 1909bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mMobileNetworkCallback = null; 1919bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 1929bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 1933760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // So many TODOs here, but chief among them is: make this functionality an 1943760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // integral part of this class such that whenever a higher priority network 1953760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // becomes available and useful we (a) file a request to keep it up as 1963760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // necessary and (b) change all upstream tracking state accordingly (by 1973760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // passing LinkProperties up to Tethering). 1983760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // 1993760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // Next TODO: return NetworkState instead of just the type. 2001e2897dcff865cc0f00079f2a3c7d5188811544fErik Kline public NetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) { 2013760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType( 2023760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline mNetworkMap.values(), preferredTypes); 2033760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 2043760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline mLog.log("preferred upstream type: " + getNetworkTypeName(typeStatePair.type)); 2053760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 2063760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline switch (typeStatePair.type) { 2073760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline case TYPE_MOBILE_DUN: 2083760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline case TYPE_MOBILE_HIPRI: 2093760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline // If we're on DUN, put our own grab on it. 2103760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline registerMobileNetworkRequest(); 2113760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline break; 2123760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline case TYPE_NONE: 2133760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline break; 2143760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline default: 2153760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline /* If we've found an active upstream connection that's not DUN/HIPRI 21660caf7d29132262dd4a077b68daa807d22773524Erik Kline * we should stop any outstanding DUN/HIPRI requests. 2173760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline * 2183760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline * If we found NONE we don't want to do this as we want any previous 2193760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline * requests to keep trying to bring up something we can use. 2203760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline */ 2213760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline releaseMobileNetworkRequest(); 2223760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline break; 2233760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 2243760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 2251e2897dcff865cc0f00079f2a3c7d5188811544fErik Kline return typeStatePair.ns; 2263760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 2273760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 22860caf7d29132262dd4a077b68daa807d22773524Erik Kline public void setCurrentUpstream(Network upstream) { 22960caf7d29132262dd4a077b68daa807d22773524Erik Kline mTetheringUpstreamNetwork = upstream; 23060caf7d29132262dd4a077b68daa807d22773524Erik Kline } 23160caf7d29132262dd4a077b68daa807d22773524Erik Kline 23232179ff81511e00aef31e8fda705be3df074ece6Erik Kline public Set<IpPrefix> getLocalPrefixes() { 23332179ff81511e00aef31e8fda705be3df074ece6Erik Kline return (Set<IpPrefix>) mLocalPrefixes.clone(); 2343a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline } 2353a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline 236d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline private void handleAvailable(int callbackType, Network network) { 237d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline if (VDBG) Log.d(TAG, "EVENT_ON_AVAILABLE for " + network); 238d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 2399bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (!mNetworkMap.containsKey(network)) { 2409bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline mNetworkMap.put(network, 2419bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline new NetworkState(null, null, null, network, null, null)); 2429bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 2439bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 244d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Always request whatever extra information we can, in case this 245d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // was already up when start() was called, in which case we would 246d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // not have been notified of any information that had not changed. 24735bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline switch (callbackType) { 24835bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline case CALLBACK_LISTEN_ALL: 24935bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline break; 250465c46d555c867caf40333db197ef97cff75a754Erik Kline 25135bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline case CALLBACK_TRACK_DEFAULT: 25232858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline if (mDefaultNetworkCallback == null) { 25332858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // The callback was unregistered in the interval between 254b583b03675492280ab87f1eff30c05709cafba23Erik Kline // ConnectivityService enqueueing onAvailable() and our 255b583b03675492280ab87f1eff30c05709cafba23Erik Kline // handling of it here on the mHandler thread. 256b583b03675492280ab87f1eff30c05709cafba23Erik Kline // 25732858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // Clean-up of this network entry is deferred to the 25832858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // handling of onLost() by other callbacks. 259b583b03675492280ab87f1eff30c05709cafba23Erik Kline // 260b583b03675492280ab87f1eff30c05709cafba23Erik Kline // These request*() calls can be deleted post oag/339444. 26132858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline return; 26232858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline } 26360caf7d29132262dd4a077b68daa807d22773524Erik Kline mDefaultInternetNetwork = network; 26435bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline break; 265465c46d555c867caf40333db197ef97cff75a754Erik Kline 26635bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline case CALLBACK_MOBILE_REQUEST: 26732858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline if (mMobileNetworkCallback == null) { 26832858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // The callback was unregistered in the interval between 269b583b03675492280ab87f1eff30c05709cafba23Erik Kline // ConnectivityService enqueueing onAvailable() and our 270b583b03675492280ab87f1eff30c05709cafba23Erik Kline // handling of it here on the mHandler thread. 271b583b03675492280ab87f1eff30c05709cafba23Erik Kline // 27232858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // Clean-up of this network entry is deferred to the 27332858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline // handling of onLost() by other callbacks. 27432858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline return; 27532858e14caa09fbb3eb4081f114f2a99181c9643Erik Kline } 27635bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline break; 277d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline } 2789bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 279d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Requesting updates for mListenAllCallback is not currently possible 280d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // because it's a "listen". Two possible solutions to getting updates 281d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // about networks without waiting for a change (which might never come) 282d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // are: 283d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // 284d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // [1] extend request{NetworkCapabilities,LinkProperties}() to 285d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // take a Network argument and have ConnectivityService do 286d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // what's required (if the network satisfies the request) 287d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // 288d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // [2] explicitly file a NetworkRequest for each connectivity type 289d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // listed as a preferred upstream and wait for these callbacks 290d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // to be notified (requires tracking many more callbacks). 291d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // 292d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Until this is addressed, networks that exist prior to the "listen" 293d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // registration and which do not subsequently change will not cause 294d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // us to learn their NetworkCapabilities nor their LinkProperties. 295d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 296d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // TODO: If sufficient information is available to select a more 297d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // preferable upstream, do so now and notify the target. 2989bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline notifyTarget(EVENT_ON_AVAILABLE, network); 2999bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3009bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 3019bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private void handleNetCap(Network network, NetworkCapabilities newNc) { 302d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline final NetworkState prev = mNetworkMap.get(network); 303d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline if (prev == null || newNc.equals(prev.networkCapabilities)) { 304d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Ignore notifications about networks for which we have not yet 305d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // received onAvailable() (should never happen) and any duplicate 306d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // notifications (e.g. matching more than one of our callbacks). 3079bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline return; 3089bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 309d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 3109bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (VDBG) { 3119bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s", 3129bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline network, newNc)); 3139bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3149bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 31560caf7d29132262dd4a077b68daa807d22773524Erik Kline // Log changes in upstream network signal strength, if available. 31660caf7d29132262dd4a077b68daa807d22773524Erik Kline if (network.equals(mTetheringUpstreamNetwork) && newNc.hasSignalStrength()) { 31760caf7d29132262dd4a077b68daa807d22773524Erik Kline final int newSignal = newNc.getSignalStrength(); 31860caf7d29132262dd4a077b68daa807d22773524Erik Kline final String prevSignal = getSignalStrength(prev.networkCapabilities); 31960caf7d29132262dd4a077b68daa807d22773524Erik Kline mLog.logf("upstream network signal strength: %s -> %s", prevSignal, newSignal); 32060caf7d29132262dd4a077b68daa807d22773524Erik Kline } 32160caf7d29132262dd4a077b68daa807d22773524Erik Kline 322d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline mNetworkMap.put(network, new NetworkState( 323d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline null, prev.linkProperties, newNc, network, null, null)); 324d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // TODO: If sufficient information is available to select a more 325d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // preferable upstream, do so now and notify the target. 3269bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline notifyTarget(EVENT_ON_CAPABILITIES, network); 3279bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3289bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 3299bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private void handleLinkProp(Network network, LinkProperties newLp) { 330d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline final NetworkState prev = mNetworkMap.get(network); 331d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline if (prev == null || newLp.equals(prev.linkProperties)) { 332d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Ignore notifications about networks for which we have not yet 333d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // received onAvailable() (should never happen) and any duplicate 334d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // notifications (e.g. matching more than one of our callbacks). 3359bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline return; 3369bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 337d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 3389bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (VDBG) { 3399bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s", 3409bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline network, newLp)); 3419bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3429bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 343d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline mNetworkMap.put(network, new NetworkState( 344d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline null, newLp, prev.networkCapabilities, network, null, null)); 345d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // TODO: If sufficient information is available to select a more 346d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // preferable upstream, do so now and notify the target. 3479bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline notifyTarget(EVENT_ON_LINKPROPERTIES, network); 3489bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3499bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 35060caf7d29132262dd4a077b68daa807d22773524Erik Kline private void handleSuspended(int callbackType, Network network) { 35160caf7d29132262dd4a077b68daa807d22773524Erik Kline if (callbackType != CALLBACK_LISTEN_ALL) return; 35260caf7d29132262dd4a077b68daa807d22773524Erik Kline if (!network.equals(mTetheringUpstreamNetwork)) return; 35360caf7d29132262dd4a077b68daa807d22773524Erik Kline mLog.log("SUSPENDED current upstream: " + network); 35460caf7d29132262dd4a077b68daa807d22773524Erik Kline } 35560caf7d29132262dd4a077b68daa807d22773524Erik Kline 35660caf7d29132262dd4a077b68daa807d22773524Erik Kline private void handleResumed(int callbackType, Network network) { 35760caf7d29132262dd4a077b68daa807d22773524Erik Kline if (callbackType != CALLBACK_LISTEN_ALL) return; 35860caf7d29132262dd4a077b68daa807d22773524Erik Kline if (!network.equals(mTetheringUpstreamNetwork)) return; 35960caf7d29132262dd4a077b68daa807d22773524Erik Kline mLog.log("RESUMED current upstream: " + network); 36060caf7d29132262dd4a077b68daa807d22773524Erik Kline } 36160caf7d29132262dd4a077b68daa807d22773524Erik Kline 362d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline private void handleLost(int callbackType, Network network) { 36335bf06c968ecbae502efd9cfb13fff9b7ddf9d6aErik Kline if (callbackType == CALLBACK_TRACK_DEFAULT) { 36460caf7d29132262dd4a077b68daa807d22773524Erik Kline mDefaultInternetNetwork = null; 365d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Receiving onLost() for a default network does not necessarily 366d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // mean the network is gone. We wait for a separate notification 367d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // on either the LISTEN_ALL or MOBILE_REQUEST callbacks before 368d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // clearing all state. 3699bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline return; 3709bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 371d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 372d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline if (!mNetworkMap.containsKey(network)) { 373d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // Ignore loss of networks about which we had not previously 374d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // learned any information or for which we have already processed 375d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // an onLost() notification. 376d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline return; 3779bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 378d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 379d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline if (VDBG) Log.d(TAG, "EVENT_ON_LOST for " + network); 380d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 381d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // TODO: If sufficient information is available to select a more 382d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // preferable upstream, do so now and notify the target. Likewise, 383d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // if the current upstream network is gone, notify the target of the 384d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline // fact that we now have no upstream at all. 3859bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline notifyTarget(EVENT_ON_LOST, mNetworkMap.remove(network)); 3869bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 3879bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 38832179ff81511e00aef31e8fda705be3df074ece6Erik Kline private void recomputeLocalPrefixes() { 38932179ff81511e00aef31e8fda705be3df074ece6Erik Kline final HashSet<IpPrefix> localPrefixes = allLocalPrefixes(mNetworkMap.values()); 39032179ff81511e00aef31e8fda705be3df074ece6Erik Kline if (!mLocalPrefixes.equals(localPrefixes)) { 39132179ff81511e00aef31e8fda705be3df074ece6Erik Kline mLocalPrefixes = localPrefixes; 39232179ff81511e00aef31e8fda705be3df074ece6Erik Kline notifyTarget(NOTIFY_LOCAL_PREFIXES, localPrefixes.clone()); 3933a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline } 3943a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline } 3953a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline 3969bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline // Fetch (and cache) a ConnectivityManager only if and when we need one. 3979bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private ConnectivityManager cm() { 3989bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (mCM == null) { 399ea9cc488eb0f096c9fd402eff49e3d30f5b6de2eErik Kline // MUST call the String variant to be able to write unittests. 400ea9cc488eb0f096c9fd402eff49e3d30f5b6de2eErik Kline mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 4019bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 4029bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline return mCM; 4039bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 4049bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 4059bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline /** 406b583b03675492280ab87f1eff30c05709cafba23Erik Kline * A NetworkCallback class that handles information of interest directly 407b583b03675492280ab87f1eff30c05709cafba23Erik Kline * in the thread on which it is invoked. To avoid locking, this MUST be 408b583b03675492280ab87f1eff30c05709cafba23Erik Kline * run on the same thread as the target state machine's handler. 4099bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline */ 4109bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private class UpstreamNetworkCallback extends NetworkCallback { 411d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline private final int mCallbackType; 412d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 413d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline UpstreamNetworkCallback(int callbackType) { 414d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline mCallbackType = callbackType; 415d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline } 416d2ec3919cb87931b2c143d0c1b98caf37039d882Erik Kline 4179bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline @Override 4189bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void onAvailable(Network network) { 419b583b03675492280ab87f1eff30c05709cafba23Erik Kline handleAvailable(mCallbackType, network); 4209bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 4219bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 4229bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline @Override 4239bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) { 424b583b03675492280ab87f1eff30c05709cafba23Erik Kline handleNetCap(network, newNc); 4259bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 4269bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 4279bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline @Override 4289bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void onLinkPropertiesChanged(Network network, LinkProperties newLp) { 429b583b03675492280ab87f1eff30c05709cafba23Erik Kline handleLinkProp(network, newLp); 43032179ff81511e00aef31e8fda705be3df074ece6Erik Kline recomputeLocalPrefixes(); 4319bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 4329bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 43360caf7d29132262dd4a077b68daa807d22773524Erik Kline @Override 43460caf7d29132262dd4a077b68daa807d22773524Erik Kline public void onNetworkSuspended(Network network) { 43560caf7d29132262dd4a077b68daa807d22773524Erik Kline handleSuspended(mCallbackType, network); 43660caf7d29132262dd4a077b68daa807d22773524Erik Kline } 43760caf7d29132262dd4a077b68daa807d22773524Erik Kline 43860caf7d29132262dd4a077b68daa807d22773524Erik Kline @Override 43960caf7d29132262dd4a077b68daa807d22773524Erik Kline public void onNetworkResumed(Network network) { 44060caf7d29132262dd4a077b68daa807d22773524Erik Kline handleResumed(mCallbackType, network); 44160caf7d29132262dd4a077b68daa807d22773524Erik Kline } 442b583b03675492280ab87f1eff30c05709cafba23Erik Kline 4439bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline @Override 4449bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline public void onLost(Network network) { 445b583b03675492280ab87f1eff30c05709cafba23Erik Kline handleLost(mCallbackType, network); 44632179ff81511e00aef31e8fda705be3df074ece6Erik Kline recomputeLocalPrefixes(); 447b583b03675492280ab87f1eff30c05709cafba23Erik Kline } 4489bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 4499bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 4509bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private void releaseCallback(NetworkCallback cb) { 4519bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline if (cb != null) cm().unregisterNetworkCallback(cb); 4529bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 4539bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 4549bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline private void notifyTarget(int which, Network network) { 4559bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline notifyTarget(which, mNetworkMap.get(network)); 4569bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 4579bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline 4583a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline private void notifyTarget(int which, Object obj) { 4593a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline mTarget.sendMessage(mWhat, which, 0, obj); 4609bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline } 4613760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4623a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline private static class TypeStatePair { 4633760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline public int type = TYPE_NONE; 4643760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline public NetworkState ns = null; 4653760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 4663760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4673a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline private static TypeStatePair findFirstAvailableUpstreamByType( 4683760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline Iterable<NetworkState> netStates, Iterable<Integer> preferredTypes) { 4693760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline final TypeStatePair result = new TypeStatePair(); 4703760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4713760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline for (int type : preferredTypes) { 4723760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline NetworkCapabilities nc; 4733760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline try { 4743760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline nc = ConnectivityManager.networkCapabilitiesForType(type); 4753760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } catch (IllegalArgumentException iae) { 4763760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + 4773760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline ConnectivityManager.getNetworkTypeName(type)); 4783760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline continue; 4793760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 480f94833df7dbead3ebce2efeeae2b57fa0613c743Erik Kline nc.setSingleUid(Process.myUid()); 4813760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4823760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline for (NetworkState value : netStates) { 4833760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) { 4843760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline continue; 4853760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 4863760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4873760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline result.type = type; 4883760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline result.ns = value; 4893760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline return result; 4903760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 4913760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 4923760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline 4933760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline return result; 4943760999e347ae1cfa25087451638de8ddc79c9f6Erik Kline } 4953a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline 49632179ff81511e00aef31e8fda705be3df074ece6Erik Kline private static HashSet<IpPrefix> allLocalPrefixes(Iterable<NetworkState> netStates) { 4973a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline final HashSet<IpPrefix> prefixSet = new HashSet<>(); 4983a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline 4993a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline for (NetworkState ns : netStates) { 50032179ff81511e00aef31e8fda705be3df074ece6Erik Kline final LinkProperties lp = ns.linkProperties; 50132179ff81511e00aef31e8fda705be3df074ece6Erik Kline if (lp == null) continue; 50232179ff81511e00aef31e8fda705be3df074ece6Erik Kline prefixSet.addAll(PrefixUtils.localPrefixesFrom(lp)); 5033a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline } 5043a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline 5053a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline return prefixSet; 5063a5278f2c4d71a8f69ce1085da42904283d62785Erik Kline } 50760caf7d29132262dd4a077b68daa807d22773524Erik Kline 50860caf7d29132262dd4a077b68daa807d22773524Erik Kline private static String getSignalStrength(NetworkCapabilities nc) { 50960caf7d29132262dd4a077b68daa807d22773524Erik Kline if (nc == null || !nc.hasSignalStrength()) return "unknown"; 51060caf7d29132262dd4a077b68daa807d22773524Erik Kline return Integer.toString(nc.getSignalStrength()); 51160caf7d29132262dd4a077b68daa807d22773524Erik Kline } 5129bba340fd4edd5aea91d612a332f964b0d63cf34Erik Kline} 513