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