• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.systemui.statusbar.connectivity;
17 
18 import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
19 
20 import android.content.Context;
21 import android.content.Intent;
22 import android.database.ContentObserver;
23 import android.net.NetworkCapabilities;
24 import android.os.Handler;
25 import android.os.Looper;
26 import android.provider.Settings.Global;
27 import android.telephony.CellSignalStrength;
28 import android.telephony.CellSignalStrengthCdma;
29 import android.telephony.SignalStrength;
30 import android.telephony.SubscriptionInfo;
31 import android.telephony.SubscriptionManager;
32 import android.telephony.TelephonyManager;
33 import android.text.Html;
34 import android.text.TextUtils;
35 import android.util.Log;
36 
37 import com.android.internal.annotations.VisibleForTesting;
38 import com.android.settingslib.SignalIcon.MobileIconGroup;
39 import com.android.settingslib.graph.SignalDrawable;
40 import com.android.settingslib.mobile.MobileMappings.Config;
41 import com.android.settingslib.mobile.MobileStatusTracker;
42 import com.android.settingslib.mobile.MobileStatusTracker.MobileStatus;
43 import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults;
44 import com.android.settingslib.mobile.TelephonyIcons;
45 import com.android.settingslib.net.SignalStrengthUtil;
46 import com.android.systemui.res.R;
47 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor;
48 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy;
49 import com.android.systemui.util.CarrierConfigTracker;
50 
51 import java.io.PrintWriter;
52 import java.text.SimpleDateFormat;
53 import java.util.BitSet;
54 import java.util.List;
55 import java.util.Map;
56 
57 /**
58  * Monitors the mobile signal changes and update the SysUI icons.
59  *
60  * @deprecated Use {@link MobileIconsInteractor} instead.
61  */
62 @Deprecated
63 public class MobileSignalController extends SignalController<MobileState, MobileIconGroup> {
64     private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
65     private static final int STATUS_HISTORY_SIZE = 64;
66     private final TelephonyManager mPhone;
67     private final CarrierConfigTracker mCarrierConfigTracker;
68     private final SubscriptionDefaults mDefaults;
69     private final MobileMappingsProxy mMobileMappingsProxy;
70     private final String mNetworkNameDefault;
71     private final String mNetworkNameSeparator;
72     private final ContentObserver mObserver;
73     // Save entire info for logging, we only use the id.
74     final SubscriptionInfo mSubscriptionInfo;
75     private Map<String, MobileIconGroup> mNetworkToIconLookup;
76 
77     private MobileIconGroup mDefaultIcons;
78     private Config mConfig;
79     @VisibleForTesting
80     boolean mInflateSignalStrengths = false;
81     @VisibleForTesting
82     final MobileStatusTracker mMobileStatusTracker;
83 
84     // Save the previous STATUS_HISTORY_SIZE states for logging.
85     private final String[] mMobileStatusHistory = new String[STATUS_HISTORY_SIZE];
86     // Where to copy the next state into.
87     private int mMobileStatusHistoryIndex;
88 
89     private final MobileStatusTracker.Callback mMobileCallback =
90             new MobileStatusTracker.Callback() {
91                 private String mLastStatus;
92 
93                 @Override
94                 public void onMobileStatusChanged(boolean updateTelephony,
95                         MobileStatus mobileStatus) {
96                     if (DEBUG) {
97                         Log.d(mTag, "onMobileStatusChanged="
98                                 + " updateTelephony=" + updateTelephony
99                                 + " mobileStatus=" + mobileStatus.toString());
100                     }
101                     String currentStatus = mobileStatus.toString();
102                     if (!currentStatus.equals(mLastStatus)) {
103                         mLastStatus = currentStatus;
104                         String status = new StringBuilder()
105                                 .append(SSDF.format(System.currentTimeMillis())).append(",")
106                                 .append(currentStatus)
107                                 .toString();
108                         recordLastMobileStatus(status);
109                     }
110                     updateMobileStatus(mobileStatus);
111                     if (updateTelephony) {
112                         updateTelephony();
113                     } else {
114                         notifyListenersIfNecessary();
115                     }
116                 }
117             };
118 
119     // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
120     // need listener lists anymore.
MobileSignalController( Context context, Config config, boolean hasMobileData, TelephonyManager phone, CallbackHandler callbackHandler, NetworkControllerImpl networkController, MobileMappingsProxy mobileMappingsProxy, SubscriptionInfo info, SubscriptionDefaults defaults, Looper receiverLooper, CarrierConfigTracker carrierConfigTracker, MobileStatusTrackerFactory mobileStatusTrackerFactory )121     public MobileSignalController(
122             Context context,
123             Config config,
124             boolean hasMobileData,
125             TelephonyManager phone,
126             CallbackHandler callbackHandler,
127             NetworkControllerImpl networkController,
128             MobileMappingsProxy mobileMappingsProxy,
129             SubscriptionInfo info,
130             SubscriptionDefaults defaults,
131             Looper receiverLooper,
132             CarrierConfigTracker carrierConfigTracker,
133             MobileStatusTrackerFactory mobileStatusTrackerFactory
134     ) {
135         super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
136                 NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
137                 networkController);
138         mCarrierConfigTracker = carrierConfigTracker;
139         mConfig = config;
140         mPhone = phone;
141         mDefaults = defaults;
142         mSubscriptionInfo = info;
143         mMobileMappingsProxy = mobileMappingsProxy;
144         mNetworkNameSeparator = getTextIfExists(
145                 R.string.status_bar_network_name_separator).toString();
146         mNetworkNameDefault = getTextIfExists(
147                 com.android.internal.R.string.lockscreen_carrier_default).toString();
148 
149         mNetworkToIconLookup = mMobileMappingsProxy.mapIconSets(mConfig);
150         mDefaultIcons = mMobileMappingsProxy.getDefaultIcons(mConfig);
151 
152         String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
153                 : mNetworkNameDefault;
154         mLastState.networkName = mCurrentState.networkName = networkName;
155         mLastState.networkNameData = mCurrentState.networkNameData = networkName;
156         mLastState.enabled = mCurrentState.enabled = hasMobileData;
157         mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
158         mObserver = new ContentObserver(new Handler(receiverLooper)) {
159             @Override
160             public void onChange(boolean selfChange) {
161                 updateTelephony();
162             }
163         };
164         mMobileStatusTracker = mobileStatusTrackerFactory.createTracker(mMobileCallback);
165     }
166 
setConfiguration(Config config)167     void setConfiguration(Config config) {
168         mConfig = config;
169         updateInflateSignalStrength();
170         mNetworkToIconLookup = mMobileMappingsProxy.mapIconSets(mConfig);
171         mDefaultIcons = mMobileMappingsProxy.getDefaultIcons(mConfig);
172         updateTelephony();
173     }
174 
setAirplaneMode(boolean airplaneMode)175     void setAirplaneMode(boolean airplaneMode) {
176         mCurrentState.airplaneMode = airplaneMode;
177         notifyListenersIfNecessary();
178     }
179 
setUserSetupComplete(boolean userSetup)180     void setUserSetupComplete(boolean userSetup) {
181         mCurrentState.userSetup = userSetup;
182         notifyListenersIfNecessary();
183     }
184 
185     @Override
updateConnectivity(BitSet connectedTransports, BitSet validatedTransports)186     public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
187         boolean isValidated = validatedTransports.get(mTransportType);
188         mCurrentState.isDefault = connectedTransports.get(mTransportType);
189         // Only show this as not having connectivity if we are default.
190         mCurrentState.inetCondition = (isValidated || !mCurrentState.isDefault) ? 1 : 0;
191         notifyListenersIfNecessary();
192     }
193 
setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode)194     void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) {
195         mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode;
196         updateTelephony();
197     }
198 
199     /**
200      * Start listening for phone state changes.
201      */
registerListener()202     public void registerListener() {
203         mMobileStatusTracker.setListening(true);
204         mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA),
205                 true, mObserver);
206         mContext.getContentResolver().registerContentObserver(Global.getUriFor(
207                 Global.MOBILE_DATA + mSubscriptionInfo.getSubscriptionId()),
208                 true, mObserver);
209     }
210 
211     /**
212      * Stop listening for phone state changes.
213      */
unregisterListener()214     public void unregisterListener() {
215         mMobileStatusTracker.setListening(false);
216         mContext.getContentResolver().unregisterContentObserver(mObserver);
217     }
218 
updateInflateSignalStrength()219     private void updateInflateSignalStrength() {
220         mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext,
221                 mSubscriptionInfo.getSubscriptionId());
222     }
223 
getNumLevels()224     private int getNumLevels() {
225         if (mInflateSignalStrengths) {
226             return CellSignalStrength.getNumSignalStrengthLevels() + 1;
227         }
228         return CellSignalStrength.getNumSignalStrengthLevels();
229     }
230 
231     @Override
getCurrentIconId()232     public int getCurrentIconId() {
233         if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) {
234             return SignalDrawable.getCarrierChangeState(getNumLevels());
235         } else if (mCurrentState.connected) {
236             int level = mCurrentState.level;
237             if (mInflateSignalStrengths) {
238                 level++;
239             }
240             boolean dataDisabled = mCurrentState.userSetup
241                     && (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
242                     || (mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA
243                             && mCurrentState.defaultDataOff));
244             boolean noInternet = mCurrentState.inetCondition == 0;
245             boolean cutOut = dataDisabled || noInternet;
246             return SignalDrawable.getState(level, getNumLevels(), cutOut);
247         } else if (mCurrentState.enabled) {
248             return SignalDrawable.getEmptyState(getNumLevels());
249         } else {
250             return 0;
251         }
252     }
253 
254     @Override
getQsCurrentIconId()255     public int getQsCurrentIconId() {
256         return getCurrentIconId();
257     }
258 
259     @Override
notifyListeners(SignalCallback callback)260     public void notifyListeners(SignalCallback callback) {
261         // If the device is on carrier merged WiFi, we should let WifiSignalController to control
262         // the SysUI states.
263         if (mNetworkController.isCarrierMergedWifi(mSubscriptionInfo.getSubscriptionId())) {
264             return;
265         }
266         MobileIconGroup icons = getIcons();
267 
268         String contentDescription = getTextIfExists(getContentDescription()).toString();
269         CharSequence dataContentDescriptionHtml = getTextIfExists(icons.dataContentDescription);
270 
271         //TODO: Hacky
272         // The data content description can sometimes be shown in a text view and might come to us
273         // as HTML. Strip any styling here so that listeners don't have to care
274         CharSequence dataContentDescription = Html.fromHtml(
275                 dataContentDescriptionHtml.toString(), 0).toString();
276         if (mCurrentState.inetCondition == 0) {
277             dataContentDescription = mContext.getString(R.string.data_connection_no_internet);
278         }
279 
280         int iconId = mCurrentState.getNetworkTypeIcon(mContext);
281         final QsInfo qsInfo = getQsInfo(contentDescription, iconId);
282         final SbInfo sbInfo = getSbInfo(contentDescription, iconId);
283 
284         MobileDataIndicators mobileDataIndicators = new MobileDataIndicators(
285                 sbInfo.icon,
286                 qsInfo.icon,
287                 sbInfo.ratTypeIcon,
288                 qsInfo.ratTypeIcon,
289                 mCurrentState.hasActivityIn(),
290                 mCurrentState.hasActivityOut(),
291                 dataContentDescription,
292                 dataContentDescriptionHtml,
293                 qsInfo.description,
294                 mSubscriptionInfo.getSubscriptionId(),
295                 mCurrentState.roaming,
296                 sbInfo.showTriangle);
297         callback.setMobileDataIndicators(mobileDataIndicators);
298     }
299 
getQsInfo(String contentDescription, int dataTypeIcon)300     private QsInfo getQsInfo(String contentDescription, int dataTypeIcon) {
301         int qsTypeIcon = 0;
302         IconState qsIcon = null;
303         CharSequence qsDescription = null;
304 
305         if (mCurrentState.dataSim) {
306             // only show QS icons if the state is also default
307             if (!mCurrentState.isDefault) {
308                 return new QsInfo(qsTypeIcon, qsIcon, qsDescription);
309             }
310 
311             if (mCurrentState.showQuickSettingsRatIcon() || mConfig.alwaysShowDataRatIcon) {
312                 qsTypeIcon = dataTypeIcon;
313             }
314 
315             boolean qsIconVisible = mCurrentState.enabled && !mCurrentState.isEmergency;
316             qsIcon = new IconState(qsIconVisible, getQsCurrentIconId(), contentDescription);
317 
318             if (!mCurrentState.isEmergency) {
319                 qsDescription = mCurrentState.networkName;
320             }
321         }
322 
323         return new QsInfo(qsTypeIcon, qsIcon, qsDescription);
324     }
325 
getSbInfo(String contentDescription, int dataTypeIcon)326     private SbInfo getSbInfo(String contentDescription, int dataTypeIcon) {
327         final boolean dataDisabled = mCurrentState.isDataDisabledOrNotDefault();
328         IconState statusIcon = new IconState(
329                 mCurrentState.enabled && !mCurrentState.airplaneMode,
330                 getCurrentIconId(), contentDescription);
331 
332         boolean showDataIconInStatusBar =
333                 (mCurrentState.dataConnected && mCurrentState.isDefault) || dataDisabled;
334         int typeIcon =
335                 (showDataIconInStatusBar || mConfig.alwaysShowDataRatIcon) ? dataTypeIcon : 0;
336         boolean showTriangle = mCurrentState.enabled && !mCurrentState.airplaneMode;
337 
338         return new SbInfo(showTriangle, typeIcon, statusIcon);
339     }
340 
341     @Override
cleanState()342     protected MobileState cleanState() {
343         return new MobileState();
344     }
345 
isInService()346     public boolean isInService() {
347         return mCurrentState.isInService();
348     }
349 
getNetworkNameForCarrierWiFi()350     String getNetworkNameForCarrierWiFi() {
351         return mPhone.getSimOperatorName();
352     }
353 
isRoaming()354     private boolean isRoaming() {
355         // During a carrier change, roaming indications need to be suppressed.
356         if (isCarrierNetworkChangeActive()) {
357             return false;
358         }
359         if (mCurrentState.isCdma()) {
360             return mPhone.getCdmaEnhancedRoamingIndicatorDisplayNumber()
361                     != TelephonyManager.ERI_OFF;
362         } else {
363             return mCurrentState.isRoaming();
364         }
365     }
366 
isCarrierNetworkChangeActive()367     private boolean isCarrierNetworkChangeActive() {
368         return mCurrentState.carrierNetworkChangeMode;
369     }
370 
handleBroadcast(Intent intent)371     void handleBroadcast(Intent intent) {
372         String action = intent.getAction();
373         if (action.equals(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED)) {
374             updateNetworkName(intent.getBooleanExtra(TelephonyManager.EXTRA_SHOW_SPN, false),
375                     intent.getStringExtra(TelephonyManager.EXTRA_SPN),
376                     intent.getStringExtra(TelephonyManager.EXTRA_DATA_SPN),
377                     intent.getBooleanExtra(TelephonyManager.EXTRA_SHOW_PLMN, false),
378                     intent.getStringExtra(TelephonyManager.EXTRA_PLMN));
379             notifyListenersIfNecessary();
380         } else if (action.equals(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
381             updateDataSim();
382             notifyListenersIfNecessary();
383         } else if (action.equals(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED)) {
384             int carrierId = intent.getIntExtra(
385                     TelephonyManager.EXTRA_CARRIER_ID, UNKNOWN_CARRIER_ID);
386             mCurrentState.setCarrierId(carrierId);
387         }
388     }
389 
updateDataSim()390     private void updateDataSim() {
391         int activeDataSubId = mDefaults.getActiveDataSubId();
392         if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) {
393             mCurrentState.dataSim = activeDataSubId == mSubscriptionInfo.getSubscriptionId();
394         } else {
395             // There doesn't seem to be a data sim selected, however if
396             // there isn't a MobileSignalController with dataSim set, then
397             // QS won't get any callbacks and will be blank.  Instead
398             // lets just assume we are the data sim (which will basically
399             // show one at random) in QS until one is selected.  The user
400             // should pick one soon after, so we shouldn't be in this state
401             // for long.
402             mCurrentState.dataSim = true;
403         }
404     }
405 
406     /**
407      * Updates the network's name based on incoming spn and plmn.
408      */
updateNetworkName(boolean showSpn, String spn, String dataSpn, boolean showPlmn, String plmn)409     void updateNetworkName(boolean showSpn, String spn, String dataSpn,
410             boolean showPlmn, String plmn) {
411         if (CHATTY) {
412             Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn
413                     + " spn=" + spn + " dataSpn=" + dataSpn
414                     + " showPlmn=" + showPlmn + " plmn=" + plmn);
415         }
416         StringBuilder str = new StringBuilder();
417         StringBuilder strData = new StringBuilder();
418         if (showPlmn && plmn != null) {
419             str.append(plmn);
420             strData.append(plmn);
421         }
422         if (showSpn && spn != null) {
423             if (str.length() != 0) {
424                 str.append(mNetworkNameSeparator);
425             }
426             str.append(spn);
427         }
428         if (str.length() != 0) {
429             mCurrentState.networkName = str.toString();
430         } else {
431             mCurrentState.networkName = mNetworkNameDefault;
432         }
433         if (showSpn && dataSpn != null) {
434             if (strData.length() != 0) {
435                 strData.append(mNetworkNameSeparator);
436             }
437             strData.append(dataSpn);
438         }
439         if (strData.length() != 0) {
440             mCurrentState.networkNameData = strData.toString();
441         } else {
442             mCurrentState.networkNameData = mNetworkNameDefault;
443         }
444     }
445 
446     /**
447      * Extracts the CellSignalStrengthCdma from SignalStrength then returns the level
448      */
getCdmaLevel(SignalStrength signalStrength)449     private int getCdmaLevel(SignalStrength signalStrength) {
450         List<CellSignalStrengthCdma> signalStrengthCdma =
451                 signalStrength.getCellSignalStrengths(CellSignalStrengthCdma.class);
452         if (!signalStrengthCdma.isEmpty()) {
453             return signalStrengthCdma.get(0).getLevel();
454         }
455         return CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
456     }
457 
updateMobileStatus(MobileStatus mobileStatus)458     private void updateMobileStatus(MobileStatus mobileStatus) {
459         mCurrentState.setFromMobileStatus(mobileStatus);
460     }
461 
getSignalLevel(SignalStrength signalStrength)462     int getSignalLevel(SignalStrength signalStrength) {
463         if (signalStrength == null) {
464             return 0;
465         }
466         if (!signalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
467             return getCdmaLevel(signalStrength);
468         } else {
469             return signalStrength.getLevel();
470         }
471     }
472 
473     /**
474      * Updates the current state based on ServiceState, SignalStrength, DataState,
475      * TelephonyDisplayInfo, and sim state.  It should be called any time one of these is updated.
476      * This will call listeners if necessary.
477      */
updateTelephony()478     private void updateTelephony() {
479         if (DEBUG) {
480             Log.d(mTag, "updateTelephonySignalStrength: hasService="
481                     + mCurrentState.isInService()
482                     + " ss=" + mCurrentState.signalStrength
483                     + " displayInfo=" + mCurrentState.telephonyDisplayInfo);
484         }
485         checkDefaultData();
486         mCurrentState.connected = mCurrentState.isInService();
487         if (mCurrentState.connected) {
488             mCurrentState.level = getSignalLevel(mCurrentState.signalStrength);
489         }
490 
491         mCurrentState.setCarrierId(mPhone.getSimCarrierId());
492         String iconKey = mMobileMappingsProxy.getIconKey(mCurrentState.telephonyDisplayInfo);
493         if (mNetworkToIconLookup.get(iconKey) != null) {
494             mCurrentState.iconGroup = mNetworkToIconLookup.get(iconKey);
495         } else {
496             mCurrentState.iconGroup = mDefaultIcons;
497         }
498         mCurrentState.dataConnected = mCurrentState.isDataConnected();
499 
500         mCurrentState.roaming = isRoaming();
501         if (isCarrierNetworkChangeActive()) {
502             mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
503         } else if (isDataDisabled() && !mConfig.alwaysShowDataRatIcon) {
504             if (mSubscriptionInfo.getSubscriptionId() != mDefaults.getDefaultDataSubId()) {
505                 mCurrentState.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA;
506             } else {
507                 mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
508             }
509         }
510         if (mCurrentState.isEmergencyOnly() != mCurrentState.isEmergency) {
511             mCurrentState.isEmergency = mCurrentState.isEmergencyOnly();
512             mNetworkController.recalculateEmergency();
513         }
514         // Fill in the network name if we think we have it.
515         if (mCurrentState.networkName.equals(mNetworkNameDefault)
516                 && !TextUtils.isEmpty(mCurrentState.getOperatorAlphaShort())) {
517             mCurrentState.networkName = mCurrentState.getOperatorAlphaShort();
518         }
519         // If this is the data subscription, update the currentState data name
520         if (mCurrentState.networkNameData.equals(mNetworkNameDefault)
521                 && mCurrentState.dataSim
522                 && !TextUtils.isEmpty(mCurrentState.getOperatorAlphaShort())) {
523             mCurrentState.networkNameData = mCurrentState.getOperatorAlphaShort();
524         }
525 
526         notifyListenersIfNecessary();
527     }
528 
529     /**
530      * If we are controlling the NOT_DEFAULT_DATA icon, check the status of the other one
531      */
checkDefaultData()532     private void checkDefaultData() {
533         if (mCurrentState.iconGroup != TelephonyIcons.NOT_DEFAULT_DATA) {
534             mCurrentState.defaultDataOff = false;
535             return;
536         }
537 
538         mCurrentState.defaultDataOff = mNetworkController.isDataControllerDisabled();
539     }
540 
onMobileDataChanged()541     void onMobileDataChanged() {
542         checkDefaultData();
543         notifyListenersIfNecessary();
544     }
545 
isDataDisabled()546     boolean isDataDisabled() {
547         return !mPhone.isDataConnectionAllowed();
548     }
549 
550     @VisibleForTesting
setActivity(int activity)551     void setActivity(int activity) {
552         mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
553                 || activity == TelephonyManager.DATA_ACTIVITY_IN;
554         mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
555                 || activity == TelephonyManager.DATA_ACTIVITY_OUT;
556         notifyListenersIfNecessary();
557     }
558 
recordLastMobileStatus(String mobileStatus)559     private void recordLastMobileStatus(String mobileStatus) {
560         mMobileStatusHistory[mMobileStatusHistoryIndex] = mobileStatus;
561         mMobileStatusHistoryIndex = (mMobileStatusHistoryIndex + 1) % STATUS_HISTORY_SIZE;
562     }
563 
564     @Override
dump(PrintWriter pw)565     public void dump(PrintWriter pw) {
566         super.dump(pw);
567         pw.println("  mSubscription=" + mSubscriptionInfo + ",");
568         pw.println("  mInflateSignalStrengths=" + mInflateSignalStrengths + ",");
569         pw.println("  isDataDisabled=" + isDataDisabled() + ",");
570         pw.println("  mNetworkToIconLookup=" + mNetworkToIconLookup + ",");
571         pw.println("  mMobileStatusTracker.isListening=" + mMobileStatusTracker.isListening());
572         pw.println("  MobileStatusHistory");
573         int size = 0;
574         for (int i = 0; i < STATUS_HISTORY_SIZE; i++) {
575             if (mMobileStatusHistory[i] != null) {
576                 size++;
577             }
578         }
579         // Print out the previous states in ordered number.
580         for (int i = mMobileStatusHistoryIndex + STATUS_HISTORY_SIZE - 1;
581                 i >= mMobileStatusHistoryIndex + STATUS_HISTORY_SIZE - size; i--) {
582             pw.println("  Previous MobileStatus("
583                     + (mMobileStatusHistoryIndex + STATUS_HISTORY_SIZE - i) + "): "
584                     + mMobileStatusHistory[i & (STATUS_HISTORY_SIZE - 1)]);
585         }
586 
587         dumpTableData(pw);
588     }
589 
590     /** Box for QS icon info */
591     private static final class QsInfo {
592         final int ratTypeIcon;
593         final IconState icon;
594         final CharSequence description;
595 
QsInfo(int typeIcon, IconState iconState, CharSequence desc)596         QsInfo(int typeIcon, IconState iconState, CharSequence desc) {
597             ratTypeIcon = typeIcon;
598             icon = iconState;
599             description = desc;
600         }
601 
602         @Override
toString()603         public String toString() {
604             return "QsInfo: ratTypeIcon=" + ratTypeIcon + " icon=" + icon;
605         }
606     }
607 
608     /** Box for status bar icon info */
609     private static final class SbInfo {
610         final boolean showTriangle;
611         final int ratTypeIcon;
612         final IconState icon;
613 
SbInfo(boolean show, int typeIcon, IconState iconState)614         SbInfo(boolean show, int typeIcon, IconState iconState) {
615             showTriangle = show;
616             ratTypeIcon = typeIcon;
617             icon = iconState;
618         }
619 
620         @Override
toString()621         public String toString() {
622             return "SbInfo: showTriangle=" + showTriangle + " ratTypeIcon=" + ratTypeIcon
623                     + " icon=" + icon;
624         }
625     }
626 }
627