NetworkControllerImpl.java revision b36becff0831e48e208495a2c4ccf1a7330aeb58
1af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock/* 2af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * Copyright (C) 2010 The Android Open Source Project 3af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * 4af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * Licensed under the Apache License, Version 2.0 (the "License"); 5af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * you may not use this file except in compliance with the License. 6af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * You may obtain a copy of the License at 7af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * 8af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * http://www.apache.org/licenses/LICENSE-2.0 9af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * 10af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * Unless required by applicable law or agreed to in writing, software 11af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * distributed under the License is distributed on an "AS IS" BASIS, 12af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * See the License for the specific language governing permissions and 14af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * limitations under the License. 15af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock */ 16af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 17af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockpackage com.android.systemui.statusbar.policy; 18af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 19403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colittiimport static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; 20403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colittiimport static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; 21403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colittiimport static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 22403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colittiimport static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; 23403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colittiimport static android.net.NetworkCapabilities.TRANSPORT_WIFI; 24af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.content.BroadcastReceiver; 25af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.content.Context; 26af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.content.Intent; 27af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.content.IntentFilter; 28af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.content.res.Resources; 29af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.net.ConnectivityManager; 30403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colittiimport android.net.NetworkCapabilities; 31af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.net.NetworkInfo; 32af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.net.wifi.WifiConfiguration; 33af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.net.wifi.WifiInfo; 34af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.net.wifi.WifiManager; 35af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.os.AsyncTask; 36af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.os.Bundle; 37af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.os.Handler; 38af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.os.Message; 39af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.os.Messenger; 40af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.provider.Settings; 41af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.telephony.PhoneStateListener; 42af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.telephony.ServiceState; 43af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.telephony.SignalStrength; 44b574627ebc383d35cf8212ee241b191b26518a0dJason Monkimport android.telephony.SubscriptionInfo; 45b574627ebc383d35cf8212ee241b191b26518a0dJason Monkimport android.telephony.SubscriptionManager; 46b574627ebc383d35cf8212ee241b191b26518a0dJason Monkimport android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 47af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.telephony.TelephonyManager; 48b574627ebc383d35cf8212ee241b191b26518a0dJason Monkimport android.text.TextUtils; 49d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monkimport android.text.format.DateFormat; 50af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.util.Log; 513aaabd71242bf8aedb8edb87565943460a79226dJason Monkimport android.util.SparseArray; 52af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 53e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monkimport com.android.internal.annotations.VisibleForTesting; 54af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport com.android.internal.telephony.IccCardConstants; 55b574627ebc383d35cf8212ee241b191b26518a0dJason Monkimport com.android.internal.telephony.PhoneConstants; 56af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport com.android.internal.telephony.TelephonyIntents; 57af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport com.android.internal.telephony.cdma.EriInfo; 58af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport com.android.internal.util.AsyncChannel; 59af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport com.android.systemui.DemoMode; 60af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport com.android.systemui.R; 61af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 62af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport java.io.FileDescriptor; 63af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport java.io.PrintWriter; 64af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport java.util.ArrayList; 65403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colittiimport java.util.BitSet; 66b574627ebc383d35cf8212ee241b191b26518a0dJason Monkimport java.util.Collections; 67b574627ebc383d35cf8212ee241b191b26518a0dJason Monkimport java.util.Comparator; 68d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monkimport java.util.HashMap; 69af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport java.util.List; 70af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport java.util.Locale; 71d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monkimport java.util.Map; 72d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monkimport java.util.Objects; 73af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 74af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock/** Platform implementation of the network controller. **/ 75af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockpublic class NetworkControllerImpl extends BroadcastReceiver 76af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock implements NetworkController, DemoMode { 77af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock // debug 78d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static final String TAG = "NetworkController"; 79d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 80d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // additional diagnostics, but not logspew 81d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static final boolean CHATTY = Log.isLoggable(TAG + ".Chat", Log.DEBUG); 82b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Save the previous SignalController.States of all SignalControllers for dumps. 83d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static final boolean RECORD_HISTORY = true; 84b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // If RECORD_HISTORY how many to save, must be a power of 2. 85d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static final int HISTORY_SIZE = 16; 86d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 87d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private static final int INET_CONDITION_THRESHOLD = 50; 88d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 89d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final Context mContext; 90d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final TelephonyManager mPhone; 91d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final WifiManager mWifiManager; 92d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final ConnectivityManager mConnectivityManager; 93b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private final SubscriptionManager mSubscriptionManager; 94d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final boolean mHasMobileDataFeature; 953aaabd71242bf8aedb8edb87565943460a79226dJason Monk private Config mConfig; 96d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 97d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Subcontrollers. 98d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @VisibleForTesting 99d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final WifiSignalController mWifiSignalController; 100d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @VisibleForTesting 101b574627ebc383d35cf8212ee241b191b26518a0dJason Monk final Map<Integer, MobileSignalController> mMobileSignalControllers = 102b574627ebc383d35cf8212ee241b191b26518a0dJason Monk new HashMap<Integer, MobileSignalController>(); 103b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // When no SIMs are around at setup, and one is added later, it seems to default to the first 104b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // SIM for most actions. This may be null if there aren't any SIMs around. 105b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private MobileSignalController mDefaultSignalController; 1060e2400fb16f5a52f755d8a2dc2a4688cf0c9a247Jason Monk private final AccessPointControllerImpl mAccessPoints; 107d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final MobileDataControllerImpl mMobileDataController; 108af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 109403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti // Network types that replace the carrier label if the device does not support mobile data. 110af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private boolean mBluetoothTethered = false; 111403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti private boolean mEthernetConnected = false; 112af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 113403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti // state of inet connection 114af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private boolean mConnected = false; 115d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private boolean mInetCondition; // Used for Logging and demo. 116af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 117403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti // BitSets indicating which network transport types (e.g., TRANSPORT_WIFI, TRANSPORT_MOBILE) are 118403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti // connected and validated, respectively. 119403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti private final BitSet mConnectedTransports = new BitSet(); 120403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti private final BitSet mValidatedTransports = new BitSet(); 121403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti 122d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // States that don't belong to a subcontroller. 123af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private boolean mAirplaneMode = false; 124b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private boolean mHasNoSims; 125af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private Locale mLocale = null; 126b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // This list holds our ordering. 127b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private List<SubscriptionInfo> mCurrentSubscriptions 128b574627ebc383d35cf8212ee241b191b26518a0dJason Monk = new ArrayList<SubscriptionInfo>(); 129af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 130d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // All the callbacks. 131d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private ArrayList<EmergencyListener> mEmergencyListeners = new ArrayList<EmergencyListener>(); 132d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private ArrayList<CarrierLabelListener> mCarrierListeners = 133d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk new ArrayList<CarrierLabelListener>(); 134d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>(); 135d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks = 136d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk new ArrayList<NetworkSignalChangedCallback>(); 137b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private boolean mListening; 1387f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock 139403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti // The current user ID. 140403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti private int mCurrentUserId; 141403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti 142af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock /** 143af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * Construct this controller object and register for updates. 144af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock */ 145af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public NetworkControllerImpl(Context context) { 146f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE), 147f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE), 14829f7a7b0ae2264651c176ef50cc21cf9131247e3Jason Monk (WifiManager) context.getSystemService(Context.WIFI_SERVICE), 149b574627ebc383d35cf8212ee241b191b26518a0dJason Monk SubscriptionManager.from(context), Config.readConfig(context), 150b574627ebc383d35cf8212ee241b191b26518a0dJason Monk new AccessPointControllerImpl(context), new MobileDataControllerImpl(context)); 151f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk registerListeners(); 152f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk } 153f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk 154f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk @VisibleForTesting 155f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk NetworkControllerImpl(Context context, ConnectivityManager connectivityManager, 156b574627ebc383d35cf8212ee241b191b26518a0dJason Monk TelephonyManager telephonyManager, WifiManager wifiManager, 157b574627ebc383d35cf8212ee241b191b26518a0dJason Monk SubscriptionManager subManager, Config config, 158d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk AccessPointControllerImpl accessPointController, 159d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk MobileDataControllerImpl mobileDataController) { 160af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mContext = context; 161b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mConfig = config; 162af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 163b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSubscriptionManager = subManager; 164f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk mConnectivityManager = connectivityManager; 165f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk mHasMobileDataFeature = 166f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); 167af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 168af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock // telephony 169e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monk mPhone = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 170af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 171af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock // wifi 172f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk mWifiManager = wifiManager; 173e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monk 174d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mLocale = mContext.getResources().getConfiguration().locale; 17529f7a7b0ae2264651c176ef50cc21cf9131247e3Jason Monk mAccessPoints = accessPointController; 17629f7a7b0ae2264651c176ef50cc21cf9131247e3Jason Monk mMobileDataController = mobileDataController; 177d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mMobileDataController.setNetworkController(this); 178d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // TODO: Find a way to move this into MobileDataController. 179d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mMobileDataController.setCallback(new MobileDataControllerImpl.Callback() { 180e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monk @Override 181e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monk public void onMobileDataEnabled(boolean enabled) { 182e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monk notifyMobileDataEnabled(enabled); 183e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monk } 184e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monk }); 185d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature, 186d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSignalsChangedCallbacks, mSignalClusters, this); 187d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 188d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it 189b574627ebc383d35cf8212ee241b191b26518a0dJason Monk updateAirplaneMode(true /* force callback */); 1900e2400fb16f5a52f755d8a2dc2a4688cf0c9a247Jason Monk mAccessPoints.setNetworkController(this); 191e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monk } 192e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monk 193f13b4b39f266e43239e40e3bf7d6997600555068Jason Monk private void registerListeners() { 194b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { 195b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mobileSignalController.registerListener(); 196b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 197b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSubscriptionManager.registerOnSubscriptionsChangedListener(mSubscriptionListener); 198e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monk 199af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock // broadcasts 200af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock IntentFilter filter = new IntentFilter(); 201af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock filter.addAction(WifiManager.RSSI_CHANGED_ACTION); 202af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 203af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 204af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 205b574627ebc383d35cf8212ee241b191b26518a0dJason Monk filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); 206b574627ebc383d35cf8212ee241b191b26518a0dJason Monk filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); 207af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION); 20823dd176915fc118563e510647f048589c12e78e5Lorenzo Colitti filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE); 209af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); 210af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 211af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 212e0cdb6079e9e9e8b87a71d67ef5aa1dc0e3e6840Jason Monk mContext.registerReceiver(this, filter); 213b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mListening = true; 214b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 215b574627ebc383d35cf8212ee241b191b26518a0dJason Monk updateMobileControllers(); 216b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock } 217b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock 218d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private void unregisterListeners() { 219b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mListening = false; 220b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { 221b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mobileSignalController.unregisterListener(); 222b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 223b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSubscriptionManager.unregisterOnSubscriptionsChangedListener(mSubscriptionListener); 224d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mContext.unregisterReceiver(this); 225d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 226d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 2270e2400fb16f5a52f755d8a2dc2a4688cf0c9a247Jason Monk public int getConnectedWifiLevel() { 2280e2400fb16f5a52f755d8a2dc2a4688cf0c9a247Jason Monk return mWifiSignalController.getState().level; 2290e2400fb16f5a52f755d8a2dc2a4688cf0c9a247Jason Monk } 2300e2400fb16f5a52f755d8a2dc2a4688cf0c9a247Jason Monk 2315d325074b14e102a90c211a8d7b65316158ac0e4Jason Monk @Override 232d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public AccessPointController getAccessPointController() { 233d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return mAccessPoints; 2345d325074b14e102a90c211a8d7b65316158ac0e4Jason Monk } 2355d325074b14e102a90c211a8d7b65316158ac0e4Jason Monk 2365d325074b14e102a90c211a8d7b65316158ac0e4Jason Monk @Override 237d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public MobileDataController getMobileDataController() { 238d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return mMobileDataController; 239d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 240d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 241d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void addEmergencyListener(EmergencyListener listener) { 242d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mEmergencyListeners.add(listener); 243b574627ebc383d35cf8212ee241b191b26518a0dJason Monk listener.setEmergencyCallsOnly(isEmergencyOnly()); 244d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 245d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 246d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void addCarrierLabel(CarrierLabelListener listener) { 247d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCarrierListeners.add(listener); 248d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk refreshCarrierLabel(); 2495d325074b14e102a90c211a8d7b65316158ac0e4Jason Monk } 2505d325074b14e102a90c211a8d7b65316158ac0e4Jason Monk 251b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock private void notifyMobileDataEnabled(boolean enabled) { 252b574627ebc383d35cf8212ee241b191b26518a0dJason Monk final int length = mSignalsChangedCallbacks.size(); 253d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < length; i++) { 254d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSignalsChangedCallbacks.get(i).onMobileDataEnabled(enabled); 255b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock } 256af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 257af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 258af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public boolean hasMobileDataFeature() { 259af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock return mHasMobileDataFeature; 260af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 261af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 262af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public boolean hasVoiceCallingFeature() { 263af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; 264af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 265af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 266b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private MobileSignalController getDataController() { 267b574627ebc383d35cf8212ee241b191b26518a0dJason Monk int dataSubId = SubscriptionManager.getDefaultDataSubId(); 268a54bf6583380cf328b9858d942b4c387c6163f0fWink Saville if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) { 269b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (DEBUG) Log.e(TAG, "No data sim selected"); 270b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return mDefaultSignalController; 271b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 272b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (mMobileSignalControllers.containsKey(dataSubId)) { 273b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return mMobileSignalControllers.get(dataSubId); 274b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 275c846632762f0579d504d90e5b986183779fcf034Dan Sandler if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + dataSubId); 276b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return mDefaultSignalController; 277b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 278b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 279d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public String getMobileNetworkName() { 280b574627ebc383d35cf8212ee241b191b26518a0dJason Monk MobileSignalController controller = getDataController(); 281b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return controller != null ? controller.getState().networkName : ""; 282af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 283af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 284d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public boolean isEmergencyOnly() { 285b574627ebc383d35cf8212ee241b191b26518a0dJason Monk int voiceSubId = SubscriptionManager.getDefaultVoiceSubId(); 286a54bf6583380cf328b9858d942b4c387c6163f0fWink Saville if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) { 287a54bf6583380cf328b9858d942b4c387c6163f0fWink Saville for (MobileSignalController mobileSignalController : 288a54bf6583380cf328b9858d942b4c387c6163f0fWink Saville mMobileSignalControllers.values()) { 289b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (!mobileSignalController.isEmergencyOnly()) { 290b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return false; 291b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 292b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 293b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 294b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (mMobileSignalControllers.containsKey(voiceSubId)) { 295b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return mMobileSignalControllers.get(voiceSubId).isEmergencyOnly(); 296b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 297c846632762f0579d504d90e5b986183779fcf034Dan Sandler if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId); 298b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Something is wrong, better assume we can't make calls... 299b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return true; 300af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 301af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 302d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 303d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Emergency status may have changed (triggered by MobileSignalController), 304d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * so we should recheck and send out the state to listeners. 305d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 306d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk void recalculateEmergency() { 307d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final boolean emergencyOnly = isEmergencyOnly(); 308b574627ebc383d35cf8212ee241b191b26518a0dJason Monk final int length = mEmergencyListeners.size(); 309d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < length; i++) { 310d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mEmergencyListeners.get(i).setEmergencyCallsOnly(emergencyOnly); 311d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 312b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // If the emergency has a chance to change, then so does the carrier 313b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // label. 314b574627ebc383d35cf8212ee241b191b26518a0dJason Monk refreshCarrierLabel(); 315af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 316af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 317af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void addSignalCluster(SignalCluster cluster) { 318af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mSignalClusters.add(cluster); 319b574627ebc383d35cf8212ee241b191b26518a0dJason Monk cluster.setSubs(mCurrentSubscriptions); 320d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk cluster.setIsAirplaneMode(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON, 321d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk R.string.accessibility_airplane_mode); 322b574627ebc383d35cf8212ee241b191b26518a0dJason Monk cluster.setNoSims(mHasNoSims); 323d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiSignalController.notifyListeners(); 324b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { 325b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mobileSignalController.notifyListeners(); 326b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 327af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 328af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 329af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) { 330af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mSignalsChangedCallbacks.add(cb); 331d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk cb.onAirplaneModeChanged(mAirplaneMode); 332b574627ebc383d35cf8212ee241b191b26518a0dJason Monk cb.onNoSimVisibleChanged(mHasNoSims); 333d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiSignalController.notifyListeners(); 334b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { 335b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mobileSignalController.notifyListeners(); 336b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 337af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 338af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 339af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void removeNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) { 340af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mSignalsChangedCallbacks.remove(cb); 341af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 342af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 343af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock @Override 344af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void setWifiEnabled(final boolean enabled) { 345af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock new AsyncTask<Void, Void, Void>() { 346af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock @Override 347af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock protected Void doInBackground(Void... args) { 348af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock // Disable tethering if enabling Wifi 349af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock final int wifiApState = mWifiManager.getWifiApState(); 350af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock if (enabled && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) || 351d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) { 352af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mWifiManager.setWifiApEnabled(null, false); 353af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 354af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 355af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mWifiManager.setWifiEnabled(enabled); 356af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock return null; 357af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 358af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock }.execute(); 359af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 360af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 361b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock @Override 362403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti public void onUserSwitched(int newUserId) { 363403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mCurrentUserId = newUserId; 364403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mAccessPoints.onUserSwitched(newUserId); 365403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti updateConnectivity(); 366403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti refreshCarrierLabel(); 367403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti } 368403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti 369403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti @Override 370d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void onReceive(Context context, Intent intent) { 371d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (CHATTY) { 372d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Log.d(TAG, "onReceive: intent=" + intent); 373f7f00ea9d3b648bd3491091188bc7a3615ae4affJohn Spurlock } 374d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final String action = intent.getAction(); 375d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) || 376d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { 377403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti updateConnectivity(); 378d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk refreshCarrierLabel(); 379d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 3803aaabd71242bf8aedb8edb87565943460a79226dJason Monk mConfig = Config.readConfig(mContext); 3813aaabd71242bf8aedb8edb87565943460a79226dJason Monk handleConfigurationChanged(); 382d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 383d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk refreshLocale(); 384d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk updateAirplaneMode(false); 385d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk refreshCarrierLabel(); 386b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED)) { 387b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // We are using different subs now, we might be able to make calls. 388b574627ebc383d35cf8212ee241b191b26518a0dJason Monk recalculateEmergency(); 389b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { 390b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Notify every MobileSignalController so they can know whether they are the 391b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // data sim or not. 392b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController controller : mMobileSignalControllers.values()) { 393b574627ebc383d35cf8212ee241b191b26518a0dJason Monk controller.handleBroadcast(intent); 394b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 395b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { 396b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Might have different subscriptions now. 397b574627ebc383d35cf8212ee241b191b26518a0dJason Monk updateMobileControllers(); 398b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } else { 399b574627ebc383d35cf8212ee241b191b26518a0dJason Monk int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, 400b574627ebc383d35cf8212ee241b191b26518a0dJason Monk SubscriptionManager.INVALID_SUBSCRIPTION_ID); 401a54bf6583380cf328b9858d942b4c387c6163f0fWink Saville if (SubscriptionManager.isValidSubscriptionId(subId)) { 402b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (mMobileSignalControllers.containsKey(subId)) { 403b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mMobileSignalControllers.get(subId).handleBroadcast(intent); 404b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } else { 405b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Can't find this subscription... We must be out of date. 406b574627ebc383d35cf8212ee241b191b26518a0dJason Monk updateMobileControllers(); 407b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 408b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } else { 409b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // No sub id, must be for the wifi. 410b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mWifiSignalController.handleBroadcast(intent); 411b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 412b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 413b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 414b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 4153aaabd71242bf8aedb8edb87565943460a79226dJason Monk @VisibleForTesting 4163aaabd71242bf8aedb8edb87565943460a79226dJason Monk void handleConfigurationChanged() { 4173aaabd71242bf8aedb8edb87565943460a79226dJason Monk for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { 4183aaabd71242bf8aedb8edb87565943460a79226dJason Monk mobileSignalController.setConfiguration(mConfig); 4193aaabd71242bf8aedb8edb87565943460a79226dJason Monk } 4203aaabd71242bf8aedb8edb87565943460a79226dJason Monk refreshLocale(); 4213aaabd71242bf8aedb8edb87565943460a79226dJason Monk refreshCarrierLabel(); 4223aaabd71242bf8aedb8edb87565943460a79226dJason Monk } 4233aaabd71242bf8aedb8edb87565943460a79226dJason Monk 424b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private void updateMobileControllers() { 425b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (!mListening) { 426b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return; 427b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 428b574627ebc383d35cf8212ee241b191b26518a0dJason Monk List<SubscriptionInfo> subscriptions = mSubscriptionManager.getActiveSubscriptionInfoList(); 429c9f0571302a59b171ff16fa049e9727503ca2986Jason Monk if (subscriptions == null) { 430c9f0571302a59b171ff16fa049e9727503ca2986Jason Monk subscriptions = Collections.emptyList(); 431c9f0571302a59b171ff16fa049e9727503ca2986Jason Monk } 432b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // If there have been no relevant changes to any of the subscriptions, we can leave as is. 433b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (hasCorrectMobileControllers(subscriptions)) { 434b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Even if the controllers are correct, make sure we have the right no sims state. 435b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Such as on boot, don't need any controllers, because there are no sims, 436b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // but we still need to update the no sim state. 437b574627ebc383d35cf8212ee241b191b26518a0dJason Monk updateNoSims(); 438b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return; 439b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 440b574627ebc383d35cf8212ee241b191b26518a0dJason Monk setCurrentSubscriptions(subscriptions); 441b574627ebc383d35cf8212ee241b191b26518a0dJason Monk updateNoSims(); 442b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 443b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 44421d05a08d8ab632608980371d78990890029f4e4Jason Monk @VisibleForTesting 44521d05a08d8ab632608980371d78990890029f4e4Jason Monk protected void updateNoSims() { 44621d05a08d8ab632608980371d78990890029f4e4Jason Monk boolean hasNoSims = mHasMobileDataFeature && mMobileSignalControllers.size() == 0; 447b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (hasNoSims != mHasNoSims) { 448b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mHasNoSims = hasNoSims; 449b574627ebc383d35cf8212ee241b191b26518a0dJason Monk notifyListeners(); 450b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 451b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 452b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 453b574627ebc383d35cf8212ee241b191b26518a0dJason Monk @VisibleForTesting 454b574627ebc383d35cf8212ee241b191b26518a0dJason Monk void setCurrentSubscriptions(List<SubscriptionInfo> subscriptions) { 455b574627ebc383d35cf8212ee241b191b26518a0dJason Monk Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() { 456b574627ebc383d35cf8212ee241b191b26518a0dJason Monk @Override 457b574627ebc383d35cf8212ee241b191b26518a0dJason Monk public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) { 458b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return lhs.getSimSlotIndex() == rhs.getSimSlotIndex() 459b574627ebc383d35cf8212ee241b191b26518a0dJason Monk ? lhs.getSubscriptionId() - rhs.getSubscriptionId() 460b574627ebc383d35cf8212ee241b191b26518a0dJason Monk : lhs.getSimSlotIndex() - rhs.getSimSlotIndex(); 461b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 462b574627ebc383d35cf8212ee241b191b26518a0dJason Monk }); 463b574627ebc383d35cf8212ee241b191b26518a0dJason Monk final int length = mSignalClusters.size(); 464b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (int i = 0; i < length; i++) { 465b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSignalClusters.get(i).setSubs(subscriptions); 466b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 467b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mCurrentSubscriptions = subscriptions; 468b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 469b574627ebc383d35cf8212ee241b191b26518a0dJason Monk HashMap<Integer, MobileSignalController> cachedControllers = 470b574627ebc383d35cf8212ee241b191b26518a0dJason Monk new HashMap<Integer, MobileSignalController>(mMobileSignalControllers); 471b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mMobileSignalControllers.clear(); 472b574627ebc383d35cf8212ee241b191b26518a0dJason Monk final int num = subscriptions.size(); 473b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (int i = 0; i < num; i++) { 474b574627ebc383d35cf8212ee241b191b26518a0dJason Monk int subId = subscriptions.get(i).getSubscriptionId(); 475b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // If we have a copy of this controller already reuse it, otherwise make a new one. 476b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (cachedControllers.containsKey(subId)) { 477b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mMobileSignalControllers.put(subId, cachedControllers.get(subId)); 478b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } else { 479b574627ebc383d35cf8212ee241b191b26518a0dJason Monk MobileSignalController controller = new MobileSignalController(mContext, mConfig, 480b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mHasMobileDataFeature, mPhone, mSignalsChangedCallbacks, mSignalClusters, 481b574627ebc383d35cf8212ee241b191b26518a0dJason Monk this, subscriptions.get(i)); 482b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mMobileSignalControllers.put(subId, controller); 483b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (subscriptions.get(i).getSimSlotIndex() == 0) { 484b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mDefaultSignalController = controller; 485b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 486b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (mListening) { 487b574627ebc383d35cf8212ee241b191b26518a0dJason Monk controller.registerListener(); 488b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 489b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 490b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 491b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (mListening) { 492b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (Integer key : cachedControllers.keySet()) { 493b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (cachedControllers.get(key) == mDefaultSignalController) { 494b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mDefaultSignalController = null; 495b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 496b574627ebc383d35cf8212ee241b191b26518a0dJason Monk cachedControllers.get(key).unregisterListener(); 497b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 498d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 49925d8a48e7348c939a3f829fe87e47857307bdbf9Jason Monk // There may be new MobileSignalControllers around, make sure they get the current 50025d8a48e7348c939a3f829fe87e47857307bdbf9Jason Monk // inet condition and airplane mode. 50125d8a48e7348c939a3f829fe87e47857307bdbf9Jason Monk pushConnectivityToSignals(); 50225d8a48e7348c939a3f829fe87e47857307bdbf9Jason Monk updateAirplaneMode(true /* force */); 503b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 504b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 505b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) { 506c9f0571302a59b171ff16fa049e9727503ca2986Jason Monk if (allSubscriptions.size() != mMobileSignalControllers.size()) { 507c9f0571302a59b171ff16fa049e9727503ca2986Jason Monk return false; 508b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 509b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (SubscriptionInfo info : allSubscriptions) { 510b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (!mMobileSignalControllers.containsKey(info.getSubscriptionId())) { 511b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return false; 512b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 513b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 514b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return true; 515b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock } 516b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock 517d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private void updateAirplaneMode(boolean force) { 518d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(), 519d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Settings.Global.AIRPLANE_MODE_ON, 0) == 1); 520d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (airplaneMode != mAirplaneMode || force) { 521d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mAirplaneMode = airplaneMode; 522b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { 523b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mobileSignalController.setAirplaneMode(mAirplaneMode); 524b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 525b574627ebc383d35cf8212ee241b191b26518a0dJason Monk notifyListeners(); 526d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk refreshCarrierLabel(); 527d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 528b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock } 529b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock 530d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private void refreshLocale() { 531d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Locale current = mContext.getResources().getConfiguration().locale; 532b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (!current.equals(mLocale)) { 533d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mLocale = current; 534d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk notifyAllListeners(); 535d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 536b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock } 537b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock 538d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 539b574627ebc383d35cf8212ee241b191b26518a0dJason Monk * Forces update of all callbacks on both SignalClusters and 540b574627ebc383d35cf8212ee241b191b26518a0dJason Monk * NetworkSignalChangedCallbacks. 541b574627ebc383d35cf8212ee241b191b26518a0dJason Monk */ 542d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private void notifyAllListeners() { 543b574627ebc383d35cf8212ee241b191b26518a0dJason Monk notifyListeners(); 544b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { 545b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mobileSignalController.notifyListeners(); 546b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 547d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiSignalController.notifyListeners(); 548c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi } 549c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi 550b574627ebc383d35cf8212ee241b191b26518a0dJason Monk /** 551b574627ebc383d35cf8212ee241b191b26518a0dJason Monk * Notifies listeners of changes in state of to the NetworkController, but 552b574627ebc383d35cf8212ee241b191b26518a0dJason Monk * does not notify for any info on SignalControllers, for that call 553b574627ebc383d35cf8212ee241b191b26518a0dJason Monk * notifyAllListeners. 554b574627ebc383d35cf8212ee241b191b26518a0dJason Monk */ 555b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private void notifyListeners() { 556d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int length = mSignalClusters.size(); 557d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < length; i++) { 558d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSignalClusters.get(i).setIsAirplaneMode(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON, 559d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk R.string.accessibility_airplane_mode); 560b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSignalClusters.get(i).setNoSims(mHasNoSims); 561d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 562d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int signalsChangedLength = mSignalsChangedCallbacks.size(); 563d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < signalsChangedLength; i++) { 564d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSignalsChangedCallbacks.get(i).onAirplaneModeChanged(mAirplaneMode); 565b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSignalsChangedCallbacks.get(i).onNoSimVisibleChanged(mHasNoSims); 566d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 567c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi } 568c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi 569d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 570d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Update the Inet conditions and what network we are connected to. 571d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 572403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti private void updateConnectivity() { 573403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mConnectedTransports.clear(); 574403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mValidatedTransports.clear(); 575403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti for (NetworkCapabilities nc : 576403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) { 577403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti for (int transportType : nc.getTransportTypes()) { 578403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mConnectedTransports.set(transportType); 579403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) { 580403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mValidatedTransports.set(transportType); 581403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti } 582403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti } 583af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 584af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 585d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (CHATTY) { 586403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports); 587403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports); 588af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 589d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 590403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mConnected = !mConnectedTransports.isEmpty(); 591403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mInetCondition = !mValidatedTransports.isEmpty(); 592403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mBluetoothTethered = mConnectedTransports.get(TRANSPORT_BLUETOOTH); 593403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mEthernetConnected = mConnectedTransports.get(TRANSPORT_ETHERNET); 594d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 59525d8a48e7348c939a3f829fe87e47857307bdbf9Jason Monk pushConnectivityToSignals(); 59625d8a48e7348c939a3f829fe87e47857307bdbf9Jason Monk } 59725d8a48e7348c939a3f829fe87e47857307bdbf9Jason Monk 59825d8a48e7348c939a3f829fe87e47857307bdbf9Jason Monk /** 59925d8a48e7348c939a3f829fe87e47857307bdbf9Jason Monk * Pushes the current connectivity state to all SignalControllers. 60025d8a48e7348c939a3f829fe87e47857307bdbf9Jason Monk */ 60125d8a48e7348c939a3f829fe87e47857307bdbf9Jason Monk private void pushConnectivityToSignals() { 602d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // We want to update all the icons, all at once, for any condition change 603b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { 604403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mobileSignalController.setInetCondition( 605403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mInetCondition ? 1 : 0, 606403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mValidatedTransports.get(mobileSignalController.getTransportType()) ? 1 : 0); 607b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 608d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiSignalController.setInetCondition( 609403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mValidatedTransports.get(mWifiSignalController.getTransportType()) ? 1 : 0); 610af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 611af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 612d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 613d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Recalculate and update the carrier label. 614d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 615d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk void refreshCarrierLabel() { 616d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Context context = mContext; 617af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 618d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk WifiSignalController.WifiState wifiState = mWifiSignalController.getState(); 619b574627ebc383d35cf8212ee241b191b26518a0dJason Monk String label = ""; 620b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController controller : mMobileSignalControllers.values()) { 621b574627ebc383d35cf8212ee241b191b26518a0dJason Monk label = controller.getLabel(label, mConnected, mHasMobileDataFeature); 622b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 623af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 624d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // TODO Simplify this ugliness, some of the flows below shouldn't be possible anymore 625d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // but stay for the sake of history. 626d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mBluetoothTethered && !mHasMobileDataFeature) { 627d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk label = mContext.getString(R.string.bluetooth_tethered); 628af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 629af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 630403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti if (mEthernetConnected && !mHasMobileDataFeature) { 631d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk label = context.getString(R.string.ethernet_label); 632af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 633af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 634b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (mAirplaneMode && !isEmergencyOnly()) { 635d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // combined values from connected wifi take precedence over airplane mode 636d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (wifiState.connected && mHasMobileDataFeature) { 637d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Suppress "No internet connection." from mobile if wifi connected. 638d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk label = ""; 639d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 640d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (!mHasMobileDataFeature) { 641d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk label = context.getString( 642d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk R.string.status_bar_settings_signal_meter_disconnected); 643d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 644af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 645b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } else if (!isMobileDataConnected() && !wifiState.connected && !mBluetoothTethered && 646403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti !mEthernetConnected && !mHasMobileDataFeature) { 647d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Pretty much no connection. 648d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk label = context.getString(R.string.status_bar_settings_signal_meter_disconnected); 649af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 650af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 651d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // for mobile devices, we always show mobile connection info here (SPN/PLMN) 652d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // for other devices, we show whatever network is connected 653d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // This is determined above by references to mHasMobileDataFeature. 654d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int length = mCarrierListeners.size(); 655d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < length; i++) { 656d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCarrierListeners.get(i).setCarrierLabel(label); 657af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 658d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 659af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 660b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private boolean isMobileDataConnected() { 661b574627ebc383d35cf8212ee241b191b26518a0dJason Monk MobileSignalController controller = getDataController(); 662b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return controller != null ? controller.getState().dataConnected : false; 663b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 664b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 665d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 666d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println("NetworkController state:"); 667403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti 668d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(" - telephony ------"); 669d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.print(" hasVoiceCallingFeature()="); 670d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(hasVoiceCallingFeature()); 671af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 672d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(" - Bluetooth ----"); 673d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.print(" mBtReverseTethered="); 674d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(mBluetoothTethered); 675d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 676d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(" - connectivity ------"); 677403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti pw.print(" mConnectedTransports="); 678403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti pw.println(mConnectedTransports); 679403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti pw.print(" mValidatedTransports="); 680403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti pw.println(mValidatedTransports); 681d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.print(" mInetCondition="); 682d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(mInetCondition); 683d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.print(" mAirplaneMode="); 684d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(mAirplaneMode); 685d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.print(" mLocale="); 686d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(mLocale); 687d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 688b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { 689b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mobileSignalController.dump(pw); 690b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 691d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiSignalController.dump(pw); 692d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 693d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 694d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private boolean mDemoMode; 695d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private int mDemoInetCondition; 696d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private WifiSignalController.WifiState mDemoWifiState; 697d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 698d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 699d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void dispatchDemoCommand(String command, Bundle args) { 700d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (!mDemoMode && command.equals(COMMAND_ENTER)) { 701d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (DEBUG) Log.d(TAG, "Entering demo mode"); 702d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk unregisterListeners(); 703d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDemoMode = true; 704d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDemoInetCondition = mInetCondition ? 1 : 0; 705d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDemoWifiState = mWifiSignalController.getState(); 706d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else if (mDemoMode && command.equals(COMMAND_EXIT)) { 707d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (DEBUG) Log.d(TAG, "Exiting demo mode"); 708d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDemoMode = false; 709b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Update what MobileSignalControllers, because they may change 710b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // to set the number of sim slots. 711b574627ebc383d35cf8212ee241b191b26518a0dJason Monk updateMobileControllers(); 712b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController controller : mMobileSignalControllers.values()) { 713b574627ebc383d35cf8212ee241b191b26518a0dJason Monk controller.resetLastState(); 714b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 715d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiSignalController.resetLastState(); 716d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk registerListeners(); 717d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk notifyAllListeners(); 718d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk refreshCarrierLabel(); 719d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else if (mDemoMode && command.equals(COMMAND_NETWORK)) { 720d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String airplane = args.getString("airplane"); 721d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (airplane != null) { 722d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean show = airplane.equals("show"); 723d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int length = mSignalClusters.size(); 724d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < length; i++) { 725d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSignalClusters.get(i).setIsAirplaneMode(show, TelephonyIcons.FLIGHT_MODE_ICON, 726d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk R.string.accessibility_airplane_mode); 727d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 728af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 729d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String fully = args.getString("fully"); 730d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (fully != null) { 731d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDemoInetCondition = Boolean.parseBoolean(fully) ? 1 : 0; 732d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiSignalController.setInetCondition(mDemoInetCondition); 733b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (MobileSignalController controller : mMobileSignalControllers.values()) { 734b574627ebc383d35cf8212ee241b191b26518a0dJason Monk controller.setInetCondition(mDemoInetCondition, mDemoInetCondition); 735b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 736d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 737d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String wifi = args.getString("wifi"); 738d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (wifi != null) { 739d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean show = wifi.equals("show"); 740d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String level = args.getString("level"); 741d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (level != null) { 742d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDemoWifiState.level = level.equals("null") ? -1 743d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1); 744d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDemoWifiState.connected = mDemoWifiState.level >= 0; 745d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 746d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDemoWifiState.enabled = show; 747d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiSignalController.notifyListeners(); 748af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 749b574627ebc383d35cf8212ee241b191b26518a0dJason Monk String sims = args.getString("sims"); 750b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (sims != null) { 751b574627ebc383d35cf8212ee241b191b26518a0dJason Monk int num = Integer.parseInt(sims); 752b574627ebc383d35cf8212ee241b191b26518a0dJason Monk List<SubscriptionInfo> subs = new ArrayList<SubscriptionInfo>(); 753b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (num != mMobileSignalControllers.size()) { 754b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mMobileSignalControllers.clear(); 755b574627ebc383d35cf8212ee241b191b26518a0dJason Monk int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax(); 756b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (int i = start /* get out of normal index range */; i < start + num; i++) { 757b574627ebc383d35cf8212ee241b191b26518a0dJason Monk SubscriptionInfo info = new SubscriptionInfo(i, "", i, "", "", 0, 0, "", 0, 758b574627ebc383d35cf8212ee241b191b26518a0dJason Monk null, 0, 0, ""); 759b574627ebc383d35cf8212ee241b191b26518a0dJason Monk subs.add(info); 760b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mMobileSignalControllers.put(i, new MobileSignalController(mContext, 761b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mConfig, mHasMobileDataFeature, mPhone, mSignalsChangedCallbacks, 762b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSignalClusters, this, info)); 763b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 764b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 765b574627ebc383d35cf8212ee241b191b26518a0dJason Monk final int n = mSignalClusters.size(); 766b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (int i = 0; i < n; i++) { 767b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSignalClusters.get(i).setSubs(subs); 768b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 769b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 770b574627ebc383d35cf8212ee241b191b26518a0dJason Monk String nosim = args.getString("nosim"); 771b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (nosim != null) { 772b574627ebc383d35cf8212ee241b191b26518a0dJason Monk boolean show = nosim.equals("show"); 773b574627ebc383d35cf8212ee241b191b26518a0dJason Monk final int n = mSignalClusters.size(); 774b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (int i = 0; i < n; i++) { 775b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSignalClusters.get(i).setNoSims(show); 776b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 777b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 778d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String mobile = args.getString("mobile"); 779d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mobile != null) { 780d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean show = mobile.equals("show"); 781d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String datatype = args.getString("datatype"); 782b574627ebc383d35cf8212ee241b191b26518a0dJason Monk String slotString = args.getString("slot"); 783b574627ebc383d35cf8212ee241b191b26518a0dJason Monk int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString); 784b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Hack to index linearly for easy use. 785b574627ebc383d35cf8212ee241b191b26518a0dJason Monk MobileSignalController controller = mMobileSignalControllers 786b574627ebc383d35cf8212ee241b191b26518a0dJason Monk .values().toArray(new MobileSignalController[0])[slot]; 787b574627ebc383d35cf8212ee241b191b26518a0dJason Monk controller.getState().dataSim = datatype != null; 788d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (datatype != null) { 789b574627ebc383d35cf8212ee241b191b26518a0dJason Monk controller.getState().iconGroup = 790d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk datatype.equals("1x") ? TelephonyIcons.ONE_X : 791d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk datatype.equals("3g") ? TelephonyIcons.THREE_G : 792d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk datatype.equals("4g") ? TelephonyIcons.FOUR_G : 793d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk datatype.equals("e") ? TelephonyIcons.E : 794d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk datatype.equals("g") ? TelephonyIcons.G : 795d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk datatype.equals("h") ? TelephonyIcons.H : 796d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk datatype.equals("lte") ? TelephonyIcons.LTE : 797d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk datatype.equals("roam") ? TelephonyIcons.ROAMING : 798d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk TelephonyIcons.UNKNOWN; 799d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 800d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int[][] icons = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH; 801d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String level = args.getString("level"); 802d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (level != null) { 803b574627ebc383d35cf8212ee241b191b26518a0dJason Monk controller.getState().level = level.equals("null") ? -1 804d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk : Math.min(Integer.parseInt(level), icons[0].length - 1); 805b574627ebc383d35cf8212ee241b191b26518a0dJason Monk controller.getState().connected = controller.getState().level >= 0; 806d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 807b574627ebc383d35cf8212ee241b191b26518a0dJason Monk controller.getState().enabled = show; 808b574627ebc383d35cf8212ee241b191b26518a0dJason Monk controller.notifyListeners(); 809af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 810d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk refreshCarrierLabel(); 811af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 812af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 813af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 814b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private final OnSubscriptionsChangedListener mSubscriptionListener = 815b574627ebc383d35cf8212ee241b191b26518a0dJason Monk new OnSubscriptionsChangedListener() { 816c9f0571302a59b171ff16fa049e9727503ca2986Jason Monk @Override 817c9f0571302a59b171ff16fa049e9727503ca2986Jason Monk public void onSubscriptionsChanged() { 818b574627ebc383d35cf8212ee241b191b26518a0dJason Monk updateMobileControllers(); 819b574627ebc383d35cf8212ee241b191b26518a0dJason Monk }; 820b574627ebc383d35cf8212ee241b191b26518a0dJason Monk }; 821b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 822b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // TODO: Move to its own file. 823d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static class WifiSignalController extends 824d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk SignalController<WifiSignalController.WifiState, SignalController.IconGroup> { 825d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final WifiManager mWifiManager; 826d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final AsyncChannel mWifiChannel; 827d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final boolean mHasMobileData; 828d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 829d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public WifiSignalController(Context context, boolean hasMobileData, 830d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk List<NetworkSignalChangedCallback> signalCallbacks, 831d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk List<SignalCluster> signalClusters, NetworkControllerImpl networkController) { 832403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI, 833403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti signalCallbacks, signalClusters, networkController); 834d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 835d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mHasMobileData = hasMobileData; 836d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Handler handler = new WifiHandler(); 837d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiChannel = new AsyncChannel(); 838d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger(); 839d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (wifiMessenger != null) { 840d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiChannel.connect(context, handler, wifiMessenger); 841af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 842d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // WiFi only has one state. 843d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup( 844d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk "Wi-Fi Icons", 845d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk WifiIcons.WIFI_SIGNAL_STRENGTH, 846d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk WifiIcons.QS_WIFI_SIGNAL_STRENGTH, 847d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH, 848d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk WifiIcons.WIFI_NO_NETWORK, 849d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk WifiIcons.QS_WIFI_NO_NETWORK, 850d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk WifiIcons.WIFI_NO_NETWORK, 851d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk WifiIcons.QS_WIFI_NO_NETWORK, 852d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk AccessibilityContentDescriptions.WIFI_NO_CONNECTION 853d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk ); 854af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 855af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 856d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 857b574627ebc383d35cf8212ee241b191b26518a0dJason Monk protected WifiState cleanState() { 858d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return new WifiState(); 859d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 860af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 861d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 862d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void notifyListeners() { 863d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // only show wifi in the cluster if connected or if wifi-only 864b574627ebc383d35cf8212ee241b191b26518a0dJason Monk boolean wifiVisible = mCurrentState.enabled 865d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && (mCurrentState.connected || !mHasMobileData); 866b574627ebc383d35cf8212ee241b191b26518a0dJason Monk String wifiDesc = wifiVisible ? mCurrentState.ssid : null; 867b574627ebc383d35cf8212ee241b191b26518a0dJason Monk boolean ssidPresent = wifiVisible && mCurrentState.ssid != null; 868d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String contentDescription = getStringIfExists(getContentDescription()); 869d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int length = mSignalsChangedCallbacks.size(); 870d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < length; i++) { 871d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSignalsChangedCallbacks.get(i).onWifiSignalChanged(mCurrentState.enabled, 872d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.connected, getQsCurrentIconId(), 873d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk ssidPresent && mCurrentState.activityIn, 874d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk ssidPresent && mCurrentState.activityOut, contentDescription, wifiDesc); 875d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 876af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 877d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int signalClustersLength = mSignalClusters.size(); 878d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < signalClustersLength; i++) { 879b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSignalClusters.get(i).setWifiIndicators(wifiVisible, getCurrentIconId(), 880b574627ebc383d35cf8212ee241b191b26518a0dJason Monk contentDescription); 881af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 882af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 88323dd176915fc118563e510647f048589c12e78e5Lorenzo Colitti 884d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 885d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Extract wifi state directly from broadcasts about changes in wifi state. 886d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 887d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void handleBroadcast(Intent intent) { 888d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String action = intent.getAction(); 889d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 890d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 891d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; 892d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 893d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final NetworkInfo networkInfo = (NetworkInfo) 894d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 895d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.connected = networkInfo != null && networkInfo.isConnected(); 896d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // If Connected grab the signal strength and ssid. 897d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mCurrentState.connected) { 898d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // try getting it out of the intent first 899d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk WifiInfo info = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) != null 900d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk ? (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) 901d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk : mWifiManager.getConnectionInfo(); 902d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (info != null) { 903b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mCurrentState.ssid = getSsid(info); 904af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } else { 905d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.ssid = null; 906af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 907d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else if (!mCurrentState.connected) { 908d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.ssid = null; 909d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 910d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { 911b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Default to -200 as its below WifiManager.MIN_RSSI. 912d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.rssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200); 913d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.level = WifiManager.calculateSignalLevel( 914d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.rssi, WifiIcons.WIFI_LEVEL_COUNT); 915af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 916af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 917d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk notifyListenersIfNecessary(); 918af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 919af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 920b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private String getSsid(WifiInfo info) { 921d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String ssid = info.getSSID(); 922d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (ssid != null) { 923d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return ssid; 924d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 925d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // OK, it's not in the connectionInfo; we have to go hunting for it 926d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks(); 927d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int length = networks.size(); 928d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < length; i++) { 929d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (networks.get(i).networkId == info.getNetworkId()) { 930d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return networks.get(i).SSID; 931af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 932af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 933d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return null; 934af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 935af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 936d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @VisibleForTesting 937d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk void setActivity(int wifiActivity) { 938d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT 939d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk || wifiActivity == WifiManager.DATA_ACTIVITY_IN; 940d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.activityOut = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT 941d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk || wifiActivity == WifiManager.DATA_ACTIVITY_OUT; 942d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk notifyListenersIfNecessary(); 9431cd44e3ab4c413df05a0281fc80dc35fdc932746Jason Monk } 9441cd44e3ab4c413df05a0281fc80dc35fdc932746Jason Monk 945d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 946d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Handler to receive the data activity on wifi. 947d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 948d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk class WifiHandler extends Handler { 949d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 950d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void handleMessage(Message msg) { 951d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk switch (msg.what) { 952d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 953d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 954d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mWifiChannel.sendMessage(Message.obtain(this, 955d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk AsyncChannel.CMD_CHANNEL_FULL_CONNECTION)); 956d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 957d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Log.e(mTag, "Failed to connect to wifi"); 958d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 959af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock break; 960d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk case WifiManager.DATA_ACTIVITY_NOTIFICATION: 961d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk setActivity(msg.arg1); 962af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock break; 963af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock default: 964d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Ignore 965af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock break; 966af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 967af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 968af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 969af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 970d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static class WifiState extends SignalController.State { 971d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String ssid; 972af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 973d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 974d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void copyFrom(State s) { 975b574627ebc383d35cf8212ee241b191b26518a0dJason Monk super.copyFrom(s); 976d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk WifiState state = (WifiState) s; 977d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk ssid = state.ssid; 978af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 979af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 980d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 981d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected void toString(StringBuilder builder) { 982d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk super.toString(builder); 983b574627ebc383d35cf8212ee241b191b26518a0dJason Monk builder.append(',').append("ssid=").append(ssid); 984d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 985af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 986d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 987d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public boolean equals(Object o) { 988d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return super.equals(o) 989d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && Objects.equals(((WifiState) o).ssid, ssid); 990af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 991af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 992af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 993af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 994b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // TODO: Move to its own file. 995d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static class MobileSignalController extends SignalController<MobileSignalController.MobileState, 996d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk MobileSignalController.MobileIconGroup> { 997d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final TelephonyManager mPhone; 998d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final String mNetworkNameDefault; 999d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final String mNetworkNameSeparator; 1000b574627ebc383d35cf8212ee241b191b26518a0dJason Monk @VisibleForTesting 1001b574627ebc383d35cf8212ee241b191b26518a0dJason Monk final PhoneStateListener mPhoneStateListener; 1002b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Save entire info for logging, we only use the id. 1003b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private final SubscriptionInfo mSubscriptionInfo; 1004d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1005d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // @VisibleForDemoMode 10063aaabd71242bf8aedb8edb87565943460a79226dJason Monk final SparseArray<MobileIconGroup> mNetworkToIconLookup; 1007d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1008d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Since some pieces of the phone state are interdependent we store it locally, 1009d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // this could potentially become part of MobileState for simplification/complication 1010d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // of code. 1011d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private IccCardConstants.State mSimState = IccCardConstants.State.READY; 1012d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 1013d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private int mDataState = TelephonyManager.DATA_DISCONNECTED; 1014d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private ServiceState mServiceState; 1015d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private SignalStrength mSignalStrength; 1016d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private MobileIconGroup mDefaultIcons; 10173aaabd71242bf8aedb8edb87565943460a79226dJason Monk private Config mConfig; 1018d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1019d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't 1020d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // need listener lists anymore. 1021d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public MobileSignalController(Context context, Config config, boolean hasMobileData, 1022d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk TelephonyManager phone, List<NetworkSignalChangedCallback> signalCallbacks, 1023b574627ebc383d35cf8212ee241b191b26518a0dJason Monk List<SignalCluster> signalClusters, NetworkControllerImpl networkController, 1024b574627ebc383d35cf8212ee241b191b26518a0dJason Monk SubscriptionInfo info) { 1025b574627ebc383d35cf8212ee241b191b26518a0dJason Monk super("MobileSignalController(" + info.getSubscriptionId() + ")", context, 1026403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti NetworkCapabilities.TRANSPORT_CELLULAR, signalCallbacks, signalClusters, 1027b574627ebc383d35cf8212ee241b191b26518a0dJason Monk networkController); 10283aaabd71242bf8aedb8edb87565943460a79226dJason Monk mNetworkToIconLookup = new SparseArray<>(); 1029d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mConfig = config; 1030d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mPhone = phone; 1031b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSubscriptionInfo = info; 1032b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId()); 1033d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator); 1034d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkNameDefault = getStringIfExists( 1035d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk com.android.internal.R.string.lockscreen_carrier_default); 1036d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1037d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mapIconSets(); 1038d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1039d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mLastState.networkName = mCurrentState.networkName = mNetworkNameDefault; 1040d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mLastState.enabled = mCurrentState.enabled = hasMobileData; 1041d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons; 1042b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Get initial data sim state. 1043b574627ebc383d35cf8212ee241b191b26518a0dJason Monk updateDataSim(); 1044d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1045d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 10463aaabd71242bf8aedb8edb87565943460a79226dJason Monk public void setConfiguration(Config config) { 10473aaabd71242bf8aedb8edb87565943460a79226dJason Monk mConfig = config; 10483aaabd71242bf8aedb8edb87565943460a79226dJason Monk mapIconSets(); 10493aaabd71242bf8aedb8edb87565943460a79226dJason Monk updateTelephony(); 10503aaabd71242bf8aedb8edb87565943460a79226dJason Monk } 10513aaabd71242bf8aedb8edb87565943460a79226dJason Monk 1052d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1053d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Get (the mobile parts of) the carrier string. 1054d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * 1055d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * @param currentLabel can be used for concatenation, currently just empty 1056d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * @param connected whether the device has connection to the internet at all 1057d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * @param isMobileLabel whether to always return the network or just when data is connected 1058d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1059d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public String getLabel(String currentLabel, boolean connected, boolean isMobileLabel) { 1060d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (!mCurrentState.enabled) { 1061d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return ""; 1062d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 1063d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String mobileLabel = ""; 1064d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // We want to show the carrier name if in service and either: 1065d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // - We are connected to mobile data, or 1066d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // - We are not connected to mobile data, as long as the *reason* packets are not 1067d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // being routed over that link is that we have better connectivity via wifi. 1068d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // If data is disconnected for some other reason but wifi (or ethernet/bluetooth) 1069d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // is connected, we show nothing. 1070d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Otherwise (nothing connected) we show "No internet connection". 1071d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mCurrentState.dataConnected) { 1072d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mobileLabel = mCurrentState.networkName; 1073d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else if (connected || mCurrentState.isEmergency) { 1074d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mCurrentState.connected || mCurrentState.isEmergency) { 1075d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // The isEmergencyOnly test covers the case of a phone with no SIM 1076d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mobileLabel = mCurrentState.networkName; 1077d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1078d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 1079b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mobileLabel = mContext.getString( 1080b574627ebc383d35cf8212ee241b191b26518a0dJason Monk R.string.status_bar_settings_signal_meter_disconnected); 1081af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1082d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1083b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (currentLabel.length() != 0) { 1084b574627ebc383d35cf8212ee241b191b26518a0dJason Monk currentLabel = currentLabel + mNetworkNameSeparator; 1085b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 1086d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Now for things that should only be shown when actually using mobile data. 1087d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (isMobileLabel) { 1088b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return currentLabel + mobileLabel; 1089af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } else { 1090b574627ebc383d35cf8212ee241b191b26518a0dJason Monk return currentLabel 1091b574627ebc383d35cf8212ee241b191b26518a0dJason Monk + (mCurrentState.dataConnected ? mobileLabel : currentLabel); 1092af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1093af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1094af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1095af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1096d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public int getDataContentDescription() { 1097d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return getIcons().mDataContentDescription; 1098d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1099af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1100d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void setAirplaneMode(boolean airplaneMode) { 1101d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.airplaneMode = airplaneMode; 1102d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk notifyListenersIfNecessary(); 1103af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1104af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1105d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void setInetCondition(int inetCondition, int inetConditionForNetwork) { 1106d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // For mobile data, use general inet condition for phone signal indexing, 1107d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // and network specific for data indexing (I think this might be a bug, but 1108d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // keeping for now). 1109d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // TODO: Update with explanation of why. 1110d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.inetForNetwork = inetConditionForNetwork; 1111d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk setInetCondition(inetCondition); 1112af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1113d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1114d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1115d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Start listening for phone state changes. 1116d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1117d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void registerListener() { 1118d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mPhone.listen(mPhoneStateListener, 1119d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk PhoneStateListener.LISTEN_SERVICE_STATE 1120d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS 1121d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk | PhoneStateListener.LISTEN_CALL_STATE 1122d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE 1123d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk | PhoneStateListener.LISTEN_DATA_ACTIVITY); 1124af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1125af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1126d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1127d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Stop listening for phone state changes. 1128d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1129d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void unregisterListener() { 1130d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mPhone.listen(mPhoneStateListener, 0); 1131d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1132af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1133d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1134d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Produce a mapping of data network types to icon groups for simple and quick use in 1135d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * updateTelephony. 1136d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1137d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private void mapIconSets() { 11383aaabd71242bf8aedb8edb87565943460a79226dJason Monk mNetworkToIconLookup.clear(); 1139d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1140d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G); 1141d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G); 1142d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G); 1143d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G); 1144d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G); 1145af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1146b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (!mConfig.showAtLeast3G) { 1147d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN, 1148d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk TelephonyIcons.UNKNOWN); 1149d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E); 1150d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X); 1151d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X); 1152d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1153d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDefaultIcons = TelephonyIcons.G; 1154af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } else { 1155d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN, 1156d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk TelephonyIcons.THREE_G); 1157d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, 1158d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk TelephonyIcons.THREE_G); 1159d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, 1160d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk TelephonyIcons.THREE_G); 1161d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, 1162d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk TelephonyIcons.THREE_G); 1163d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDefaultIcons = TelephonyIcons.THREE_G; 1164af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1165af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1166d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk MobileIconGroup hGroup = TelephonyIcons.THREE_G; 1167d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mConfig.hspaDataDistinguishable) { 1168d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk hGroup = TelephonyIcons.H; 1169d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1170d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup); 1171d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup); 1172d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup); 1173d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup); 1174af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1175d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mConfig.show4gForLte) { 1176d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G); 1177d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 1178d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE); 1179d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1180af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1181af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1182d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1183d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void notifyListeners() { 1184d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk MobileIconGroup icons = getIcons(); 1185d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1186d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String contentDescription = getStringIfExists(getContentDescription()); 1187d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String dataContentDescription = getStringIfExists(icons.mDataContentDescription); 1188b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Only send data sim callbacks to QS. 1189b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (mCurrentState.dataSim) { 1190b574627ebc383d35cf8212ee241b191b26518a0dJason Monk int qsTypeIcon = mCurrentState.dataConnected ? 1191b574627ebc383d35cf8212ee241b191b26518a0dJason Monk icons.mQsDataType[mCurrentState.inetForNetwork] : 0; 1192b574627ebc383d35cf8212ee241b191b26518a0dJason Monk int length = mSignalsChangedCallbacks.size(); 1193b574627ebc383d35cf8212ee241b191b26518a0dJason Monk for (int i = 0; i < length; i++) { 1194b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSignalsChangedCallbacks.get(i).onMobileDataSignalChanged(mCurrentState.enabled 1195b36becff0831e48e208495a2c4ccf1a7330aeb58Jason Monk && !mCurrentState.isEmergency, 1196b574627ebc383d35cf8212ee241b191b26518a0dJason Monk getQsCurrentIconId(), contentDescription, 1197b574627ebc383d35cf8212ee241b191b26518a0dJason Monk qsTypeIcon, 1198b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mCurrentState.dataConnected && mCurrentState.activityIn, 1199b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mCurrentState.dataConnected && mCurrentState.activityOut, 1200b574627ebc383d35cf8212ee241b191b26518a0dJason Monk dataContentDescription, 1201b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mCurrentState.isEmergency ? null : mCurrentState.networkName, 1202b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Only wide if actually showing something. 1203b574627ebc383d35cf8212ee241b191b26518a0dJason Monk icons.mIsWide && qsTypeIcon != 0); 1204b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 1205d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1206b574627ebc383d35cf8212ee241b191b26518a0dJason Monk boolean showDataIcon = mCurrentState.dataConnected && mCurrentState.inetForNetwork != 0 1207d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk || mCurrentState.iconGroup == TelephonyIcons.ROAMING; 1208d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int typeIcon = showDataIcon ? icons.mDataType : 0; 1209d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int signalClustersLength = mSignalClusters.size(); 1210d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < signalClustersLength; i++) { 1211d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSignalClusters.get(i).setMobileDataIndicators( 1212d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.enabled && !mCurrentState.airplaneMode, 1213d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk getCurrentIconId(), 1214d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk typeIcon, 1215d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk contentDescription, 1216d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk dataContentDescription, 1217d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Only wide if actually showing something. 1218b574627ebc383d35cf8212ee241b191b26518a0dJason Monk icons.mIsWide && typeIcon != 0, 1219b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSubscriptionInfo.getSubscriptionId()); 1220d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1221af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1222af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1223d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1224b574627ebc383d35cf8212ee241b191b26518a0dJason Monk protected MobileState cleanState() { 1225d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return new MobileState(); 1226d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1227d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1228d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private boolean hasService() { 1229d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mServiceState != null) { 1230d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Consider the device to be in service if either voice or data 1231d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // service is available. Some SIM cards are marketed as data-only 1232d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // and do not support voice service, and on these SIM cards, we 1233d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // want to show signal bars for data service as well as the "no 1234d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // service" or "emergency calls only" text that indicates that voice 1235d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // is not available. 1236d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk switch (mServiceState.getVoiceRegState()) { 1237d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk case ServiceState.STATE_POWER_OFF: 1238d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return false; 1239d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk case ServiceState.STATE_OUT_OF_SERVICE: 1240d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk case ServiceState.STATE_EMERGENCY_ONLY: 1241d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE; 1242d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk default: 1243d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return true; 1244d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1245d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 1246d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return false; 1247d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1248af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1249af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1250d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private boolean isCdma() { 1251d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return (mSignalStrength != null) && !mSignalStrength.isGsm(); 1252af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1253af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1254d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public boolean isEmergencyOnly() { 1255d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return (mServiceState != null && mServiceState.isEmergencyOnly()); 1256d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1257af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1258d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private boolean isRoaming() { 1259d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (isCdma()) { 1260d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int iconMode = mServiceState.getCdmaEriIconMode(); 1261d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF 1262d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL 1263d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH); 1264d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 1265d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return mServiceState != null && mServiceState.getRoaming(); 1266d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1267d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1268af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1269d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void handleBroadcast(Intent intent) { 1270d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String action = intent.getAction(); 1271b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) { 1272d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false), 1273d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk intent.getStringExtra(TelephonyIntents.EXTRA_SPN), 1274d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false), 1275d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk intent.getStringExtra(TelephonyIntents.EXTRA_PLMN)); 1276d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk notifyListenersIfNecessary(); 1277b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { 1278b574627ebc383d35cf8212ee241b191b26518a0dJason Monk updateDataSim(); 1279d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1280d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1281af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1282b574627ebc383d35cf8212ee241b191b26518a0dJason Monk private void updateDataSim() { 1283b574627ebc383d35cf8212ee241b191b26518a0dJason Monk int defaultDataSub = SubscriptionManager.getDefaultDataSubId(); 1284a54bf6583380cf328b9858d942b4c387c6163f0fWink Saville if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) { 1285b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId(); 1286af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } else { 1287b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // There doesn't seem to be a data sim selected, however if 1288b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // there isn't a MobileSignalController with dataSim set, then 1289b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // QS won't get any callbacks and will be blank. Instead 1290b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // lets just assume we are the data sim (which will basically 1291b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // show one at random) in QS until one is selected. The user 1292b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // should pick one soon after, so we shouldn't be in this state 1293b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // for long. 1294b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mCurrentState.dataSim = true; 1295af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1296b574627ebc383d35cf8212ee241b191b26518a0dJason Monk notifyListenersIfNecessary(); 1297d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1298af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1299d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1300d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Updates the network's name based on incoming spn and plmn. 1301d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1302d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) { 1303d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (CHATTY) { 1304d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn 1305d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk + " showPlmn=" + showPlmn + " plmn=" + plmn); 1306d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1307d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk StringBuilder str = new StringBuilder(); 1308d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (showPlmn && plmn != null) { 1309d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk str.append(plmn); 1310d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1311d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (showSpn && spn != null) { 1312d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (str.length() != 0) { 1313d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk str.append(mNetworkNameSeparator); 1314d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1315d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk str.append(spn); 1316d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1317d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (str.length() != 0) { 1318d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.networkName = str.toString(); 1319d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 1320d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.networkName = mNetworkNameDefault; 1321af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1322af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1323af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1324d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1325d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Updates the current state based on mServiceState, mSignalStrength, mDataNetType, 1326d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * mDataState, and mSimState. It should be called any time one of these is updated. 1327d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * This will call listeners if necessary. 1328d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1329d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final void updateTelephony() { 1330d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (DEBUG) { 1331d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Log.d(TAG, "updateTelephonySignalStrength: hasService=" + hasService() 1332d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk + " ss=" + mSignalStrength); 1333d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1334d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.connected = hasService() && mSignalStrength != null; 1335d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mCurrentState.connected) { 1336d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) { 1337d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.level = mSignalStrength.getCdmaLevel(); 1338d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 1339d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.level = mSignalStrength.getLevel(); 1340d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1341d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 13423aaabd71242bf8aedb8edb87565943460a79226dJason Monk if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) { 1343d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType); 1344af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } else { 1345d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.iconGroup = mDefaultIcons; 1346d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1347d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.dataConnected = mCurrentState.connected 1348d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && mDataState == TelephonyManager.DATA_CONNECTED; 1349af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1350d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (isRoaming()) { 1351d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.iconGroup = TelephonyIcons.ROAMING; 1352d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1353d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (isEmergencyOnly() != mCurrentState.isEmergency) { 1354d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.isEmergency = isEmergencyOnly(); 1355d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkController.recalculateEmergency(); 1356af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1357b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // Fill in the network name if we think we have it. 1358b574627ebc383d35cf8212ee241b191b26518a0dJason Monk if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null 1359b574627ebc383d35cf8212ee241b191b26518a0dJason Monk && mServiceState.getOperatorAlphaShort() != null) { 1360b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mCurrentState.networkName = mServiceState.getOperatorAlphaShort(); 1361b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 1362d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk notifyListenersIfNecessary(); 1363af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1364af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1365d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @VisibleForTesting 1366d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk void setActivity(int activity) { 1367d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT 1368d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk || activity == TelephonyManager.DATA_ACTIVITY_IN; 1369d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT 1370d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk || activity == TelephonyManager.DATA_ACTIVITY_OUT; 1371d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk notifyListenersIfNecessary(); 1372af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1373af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1374d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1375d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void dump(PrintWriter pw) { 1376d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk super.dump(pw); 1377b574627ebc383d35cf8212ee241b191b26518a0dJason Monk pw.println(" mSubscription=" + mSubscriptionInfo + ","); 1378d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(" mServiceState=" + mServiceState + ","); 1379d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(" mSignalStrength=" + mSignalStrength + ","); 1380d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(" mDataState=" + mDataState + ","); 1381d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(" mDataNetType=" + mDataNetType + ","); 1382af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1383af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1384b574627ebc383d35cf8212ee241b191b26518a0dJason Monk class MobilePhoneStateListener extends PhoneStateListener { 1385b574627ebc383d35cf8212ee241b191b26518a0dJason Monk public MobilePhoneStateListener(int subId) { 1386b574627ebc383d35cf8212ee241b191b26518a0dJason Monk super(subId); 1387b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 1388b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 1389d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1390d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void onSignalStrengthsChanged(SignalStrength signalStrength) { 1391d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (DEBUG) { 1392b574627ebc383d35cf8212ee241b191b26518a0dJason Monk Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength + 1393d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel()))); 1394af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1395d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSignalStrength = signalStrength; 1396d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk updateTelephony(); 1397af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1398af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1399d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1400d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void onServiceStateChanged(ServiceState state) { 1401d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (DEBUG) { 1402b574627ebc383d35cf8212ee241b191b26518a0dJason Monk Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState() 1403d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk + " dataState=" + state.getDataRegState()); 1404d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1405d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mServiceState = state; 1406d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk updateTelephony(); 1407d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1408af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1409d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1410d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void onDataConnectionStateChanged(int state, int networkType) { 1411d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (DEBUG) { 1412b574627ebc383d35cf8212ee241b191b26518a0dJason Monk Log.d(mTag, "onDataConnectionStateChanged: state=" + state 1413d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk + " type=" + networkType); 1414d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1415d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDataState = state; 1416d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDataNetType = networkType; 1417d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk updateTelephony(); 1418d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 141923dd176915fc118563e510647f048589c12e78e5Lorenzo Colitti 1420d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1421d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void onDataActivity(int direction) { 1422d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (DEBUG) { 1423b574627ebc383d35cf8212ee241b191b26518a0dJason Monk Log.d(mTag, "onDataActivity: direction=" + direction); 1424d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1425d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk setActivity(direction); 1426d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1427d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk }; 1428d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1429d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static class MobileIconGroup extends SignalController.IconGroup { 1430d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int mDataContentDescription; // mContentDescriptionDataType 1431d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int mDataType; 1432d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final boolean mIsWide; 1433d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int[] mQsDataType; 1434d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1435d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, 1436d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, 1437d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int discContentDesc, int dataContentDesc, int dataType, boolean isWide, 1438d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int[] qsDataType) { 1439d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState, 1440d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk qsDiscState, discContentDesc); 1441d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDataContentDescription = dataContentDesc; 1442d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDataType = dataType; 1443d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mIsWide = isWide; 1444d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mQsDataType = qsDataType; 1445af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1446af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1447af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1448d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static class MobileState extends SignalController.State { 1449d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk String networkName; 1450b574627ebc383d35cf8212ee241b191b26518a0dJason Monk boolean dataSim; 1451d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean dataConnected; 1452d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean isEmergency; 1453d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean airplaneMode; 1454d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int inetForNetwork; 1455af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1456d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1457d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void copyFrom(State s) { 1458b574627ebc383d35cf8212ee241b191b26518a0dJason Monk super.copyFrom(s); 1459d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk MobileState state = (MobileState) s; 1460b574627ebc383d35cf8212ee241b191b26518a0dJason Monk dataSim = state.dataSim; 1461d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk networkName = state.networkName; 1462d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk dataConnected = state.dataConnected; 1463d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk inetForNetwork = state.inetForNetwork; 1464d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk isEmergency = state.isEmergency; 1465d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk airplaneMode = state.airplaneMode; 1466af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1467af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1468d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1469d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected void toString(StringBuilder builder) { 1470b574627ebc383d35cf8212ee241b191b26518a0dJason Monk super.toString(builder); 1471b574627ebc383d35cf8212ee241b191b26518a0dJason Monk builder.append(','); 1472b574627ebc383d35cf8212ee241b191b26518a0dJason Monk builder.append("dataSim=").append(dataSim).append(','); 1473d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk builder.append("networkName=").append(networkName).append(','); 1474d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk builder.append("dataConnected=").append(dataConnected).append(','); 1475d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk builder.append("inetForNetwork=").append(inetForNetwork).append(','); 1476d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk builder.append("isEmergency=").append(isEmergency).append(','); 1477b574627ebc383d35cf8212ee241b191b26518a0dJason Monk builder.append("airplaneMode=").append(airplaneMode); 1478d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1479af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1480d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1481d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public boolean equals(Object o) { 1482d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return super.equals(o) 1483d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && Objects.equals(((MobileState) o).networkName, networkName) 1484b574627ebc383d35cf8212ee241b191b26518a0dJason Monk && ((MobileState) o).dataSim == dataSim 1485d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && ((MobileState) o).dataConnected == dataConnected 1486d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && ((MobileState) o).isEmergency == isEmergency 1487d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && ((MobileState) o).airplaneMode == airplaneMode 1488d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && ((MobileState) o).inetForNetwork == inetForNetwork; 1489d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1490af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1491d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1492af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1493d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1494d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Common base class for handling signal for both wifi and mobile data. 1495d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1496d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static abstract class SignalController<T extends SignalController.State, 1497d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk I extends SignalController.IconGroup> { 1498d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected final String mTag; 1499d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected final T mCurrentState; 1500d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected final T mLastState; 1501403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti protected final int mTransportType; 1502d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected final Context mContext; 1503d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // The owner of the SignalController (i.e. NetworkController will maintain the following 1504d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // lists and call notifyListeners whenever the list has changed to ensure everyone 1505d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // is aware of current state. 1506d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected final List<NetworkSignalChangedCallback> mSignalsChangedCallbacks; 1507d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected final List<SignalCluster> mSignalClusters; 1508d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected final NetworkControllerImpl mNetworkController; 1509d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1510d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Save the previous HISTORY_SIZE states for logging. 1511d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private final State[] mHistory; 1512d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Where to copy the next state into. 1513d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk private int mHistoryIndex; 1514d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1515d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public SignalController(String tag, Context context, int type, 1516d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk List<NetworkSignalChangedCallback> signalCallbacks, 1517d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk List<SignalCluster> signalClusters, NetworkControllerImpl networkController) { 1518b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mTag = TAG + "." + tag; 1519d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkController = networkController; 1520403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti mTransportType = type; 1521d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mContext = context; 1522d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSignalsChangedCallbacks = signalCallbacks; 1523d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSignalClusters = signalClusters; 1524d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState = cleanState(); 1525d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mLastState = cleanState(); 1526d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (RECORD_HISTORY) { 1527d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mHistory = new State[HISTORY_SIZE]; 1528d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < HISTORY_SIZE; i++) { 1529d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mHistory[i] = cleanState(); 1530d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1531d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1532af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1533af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1534d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public T getState() { 1535d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return mCurrentState; 1536af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1537af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1538403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti public int getTransportType() { 1539403aa2684e0e93b4792aabc0bbe1f32ac5e417afLorenzo Colitti return mTransportType; 1540af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1541af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1542d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void setInetCondition(int inetCondition) { 1543d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.inetCondition = inetCondition; 1544d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk notifyListenersIfNecessary(); 1545af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1546af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1547d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1548d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Used at the end of demo mode to clear out any ugly state that it has created. 1549d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Since we haven't had any callbacks, then isDirty will not have been triggered, 1550d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * so we can just take the last good state directly from there. 1551b574627ebc383d35cf8212ee241b191b26518a0dJason Monk * 1552b574627ebc383d35cf8212ee241b191b26518a0dJason Monk * Used for demo mode. 1553d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1554d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk void resetLastState() { 1555d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.copyFrom(mLastState); 155623dd176915fc118563e510647f048589c12e78e5Lorenzo Colitti } 155723dd176915fc118563e510647f048589c12e78e5Lorenzo Colitti 1558d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1559d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Determines if the state of this signal controller has changed and 1560d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * needs to trigger callbacks related to it. 1561d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1562d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public boolean isDirty() { 1563d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (!mLastState.equals(mCurrentState)) { 1564d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (DEBUG) { 1565d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Log.d(mTag, "Change in state from: " + mLastState + "\n" 1566d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk + "\tto: " + mCurrentState); 1567d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1568d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return true; 1569d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1570d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return false; 1571af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1572af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1573d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void saveLastState() { 1574d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (RECORD_HISTORY) { 1575b574627ebc383d35cf8212ee241b191b26518a0dJason Monk recordLastState(); 1576d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1577d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Updates the current time. 1578d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mCurrentState.time = System.currentTimeMillis(); 1579d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mLastState.copyFrom(mCurrentState); 1580d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1581d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1582d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1583d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Gets the signal icon for QS based on current state of connected, enabled, and level. 1584d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1585d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public int getQsCurrentIconId() { 1586d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mCurrentState.connected) { 1587d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return getIcons().mQsIcons[mCurrentState.inetCondition][mCurrentState.level]; 1588d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else if (mCurrentState.enabled) { 1589d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return getIcons().mQsDiscState; 1590d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 1591d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return getIcons().mQsNullState; 1592d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1593af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1594af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1595d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1596d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Gets the signal icon for SB based on current state of connected, enabled, and level. 1597d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1598d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public int getCurrentIconId() { 1599d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mCurrentState.connected) { 1600d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level]; 1601d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else if (mCurrentState.enabled) { 1602d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return getIcons().mSbDiscState; 1603d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 1604d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return getIcons().mSbNullState; 1605af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1606af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1607af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1608d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1609b574627ebc383d35cf8212ee241b191b26518a0dJason Monk * Gets the content description id for the signal based on current state of connected and 1610d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * level. 1611d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1612d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public int getContentDescription() { 1613d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mCurrentState.connected) { 1614d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return getIcons().mContentDesc[mCurrentState.level]; 1615af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } else { 1616d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return getIcons().mDiscContentDesc; 1617af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1618af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1619af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1620b574627ebc383d35cf8212ee241b191b26518a0dJason Monk public void notifyListenersIfNecessary() { 1621d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (isDirty()) { 1622d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk saveLastState(); 1623d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk notifyListeners(); 1624d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mNetworkController.refreshCarrierLabel(); 1625af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1626af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1627af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1628d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1629d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Returns the resource if resId is not 0, and an empty string otherwise. 1630d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1631d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected String getStringIfExists(int resId) { 1632d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return resId != 0 ? mContext.getString(resId) : ""; 1633af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1634af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1635d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected I getIcons() { 1636d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return (I) mCurrentState.iconGroup; 1637af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1638af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1639d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1640d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Saves the last state of any changes, so we can log the current 1641d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * and last value of any state data. 1642d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1643b574627ebc383d35cf8212ee241b191b26518a0dJason Monk protected void recordLastState() { 1644d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mHistory[mHistoryIndex++ & (HISTORY_SIZE - 1)].copyFrom(mLastState); 1645d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1646af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1647d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void dump(PrintWriter pw) { 1648d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(" - " + mTag + " -----"); 1649d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(" Current State: " + mCurrentState); 1650d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (RECORD_HISTORY) { 1651d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Count up the states that actually contain time stamps, and only display those. 1652d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int size = 0; 1653d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = 0; i < HISTORY_SIZE; i++) { 1654d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (mHistory[i].time != 0) size++; 1655d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1656d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Print out the previous states in ordered number. 1657d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk for (int i = mHistoryIndex + HISTORY_SIZE - 1; 1658d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk i >= mHistoryIndex + HISTORY_SIZE - size; i--) { 1659d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk pw.println(" Previous State(" + (mHistoryIndex + HISTORY_SIZE - i) + ": " 1660d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk + mHistory[i & (HISTORY_SIZE - 1)]); 1661d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1662d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1663d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1664af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1665d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1666d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Trigger callbacks based on current state. The callbacks should be completely 1667d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * based on current state, and only need to be called in the scenario where 1668d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * mCurrentState != mLastState. 1669d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1670d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public abstract void notifyListeners(); 1671d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1672d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /** 1673d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Generate a blank T. 1674d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1675b574627ebc383d35cf8212ee241b191b26518a0dJason Monk protected abstract T cleanState(); 1676d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1677d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk /* 1678d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * Holds icons for a given state. Arrays are generally indexed as inet 1679d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * state (full connectivity or not) first, and second dimension as 1680d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk * signal strength. 1681d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk */ 1682d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static class IconGroup { 1683d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int[][] mSbIcons; 1684d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int[][] mQsIcons; 1685d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int[] mContentDesc; 1686d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int mSbNullState; 1687d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int mQsNullState; 1688d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int mSbDiscState; 1689d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int mQsDiscState; 1690d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final int mDiscContentDesc; 1691d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // For logging. 1692d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk final String mName; 1693d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1694d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, 1695d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, 1696d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int discContentDesc) { 1697d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mName = name; 1698d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSbIcons = sbIcons; 1699d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mQsIcons = qsIcons; 1700d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mContentDesc = contentDesc; 1701d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSbNullState = sbNullState; 1702d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mQsNullState = qsNullState; 1703d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mSbDiscState = sbDiscState; 1704d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mQsDiscState = qsDiscState; 1705d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk mDiscContentDesc = discContentDesc; 1706d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1707af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1708d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1709d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public String toString() { 1710d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return "IconGroup(" + mName + ")"; 1711af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1712af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1713af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 1714d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static class State { 1715d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean connected; 1716d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean enabled; 1717d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean activityIn; 1718d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean activityOut; 1719d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int level; 1720d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk IconGroup iconGroup; 1721d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int inetCondition; 1722d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk int rssi; // Only for logging. 1723d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1724d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk // Not used for comparison, just used for logging. 1725d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk long time; 1726d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1727d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public void copyFrom(State state) { 1728d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk connected = state.connected; 1729d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk enabled = state.enabled; 1730d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk level = state.level; 1731d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk iconGroup = state.iconGroup; 1732d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk inetCondition = state.inetCondition; 1733d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk activityIn = state.activityIn; 1734d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk activityOut = state.activityOut; 1735d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk rssi = state.rssi; 1736d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk time = state.time; 1737af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1738d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1739d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1740d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public String toString() { 1741d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (time != 0) { 1742d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk StringBuilder builder = new StringBuilder(); 1743d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk toString(builder); 1744d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return builder.toString(); 1745d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } else { 1746d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return "Empty " + getClass().getSimpleName(); 1747af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1748af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1749d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1750d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk protected void toString(StringBuilder builder) { 1751d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk builder.append("connected=").append(connected).append(',') 1752d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk .append("enabled=").append(enabled).append(',') 1753d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk .append("level=").append(level).append(',') 1754d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk .append("inetCondition=").append(inetCondition).append(',') 1755d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk .append("iconGroup=").append(iconGroup).append(',') 1756d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk .append("activityIn=").append(activityIn).append(',') 1757d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk .append("activityOut=").append(activityOut).append(',') 1758d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk .append("rssi=").append(rssi).append(',') 1759d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk .append("lastModified=").append(DateFormat.format("MM-dd hh:mm:ss", time)); 1760af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1761d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1762d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @Override 1763d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public boolean equals(Object o) { 1764d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk if (!o.getClass().equals(getClass())) { 1765d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return false; 1766af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1767d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk State other = (State) o; 1768d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return other.connected == connected 1769d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && other.enabled == enabled 1770d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && other.level == level 1771d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && other.inetCondition == inetCondition 1772d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && other.iconGroup == iconGroup 1773d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && other.activityIn == activityIn 1774d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && other.activityOut == activityOut 1775d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk && other.rssi == rssi; 1776af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1777af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1778af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1779d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1780d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public interface SignalCluster { 1781d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription); 1782d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1783d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon, 1784b574627ebc383d35cf8212ee241b191b26518a0dJason Monk String contentDescription, String typeContentDescription, boolean isTypeIconWide, 1785b574627ebc383d35cf8212ee241b191b26518a0dJason Monk int subId); 1786b574627ebc383d35cf8212ee241b191b26518a0dJason Monk void setSubs(List<SubscriptionInfo> subs); 1787b574627ebc383d35cf8212ee241b191b26518a0dJason Monk void setNoSims(boolean show); 1788d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1789d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk void setIsAirplaneMode(boolean is, int airplaneIcon, int contentDescription); 1790d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1791d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1792d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public interface EmergencyListener { 1793d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk void setEmergencyCallsOnly(boolean emergencyOnly); 1794d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1795d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1796d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk public interface CarrierLabelListener { 1797d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk void setCarrierLabel(String label); 1798d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1799d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1800d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk @VisibleForTesting 1801d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static class Config { 1802b574627ebc383d35cf8212ee241b191b26518a0dJason Monk boolean showAtLeast3G = false; 1803d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean alwaysShowCdmaRssi = false; 1804d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean show4gForLte = false; 1805d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk boolean hspaDataDistinguishable; 1806d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1807d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk static Config readConfig(Context context) { 1808d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Config config = new Config(); 1809d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk Resources res = context.getResources(); 1810d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 1811b574627ebc383d35cf8212ee241b191b26518a0dJason Monk config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G); 1812d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk config.alwaysShowCdmaRssi = 1813d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi); 1814d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk config.show4gForLte = res.getBoolean(R.bool.config_show4GForLTE); 1815d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk config.hspaDataDistinguishable = 1816d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk res.getBoolean(R.bool.config_hspa_data_distinguishable); 1817d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk return config; 1818d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1819d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk } 1820af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock} 1821