• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 
17 package com.android.systemui.statusbar.policy;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.content.res.Resources;
24 import android.net.ConnectivityManager;
25 import android.net.NetworkInfo;
26 import android.net.wifi.WifiConfiguration;
27 import android.net.wifi.WifiInfo;
28 import android.net.wifi.WifiManager;
29 import android.net.wimax.WimaxManagerConstants;
30 import android.os.Binder;
31 import android.os.Handler;
32 import android.os.Message;
33 import android.os.Messenger;
34 import android.os.RemoteException;
35 import android.provider.Settings;
36 import android.telephony.PhoneStateListener;
37 import android.telephony.ServiceState;
38 import android.telephony.SignalStrength;
39 import android.telephony.TelephonyManager;
40 import android.util.Slog;
41 import android.view.View;
42 import android.widget.ImageView;
43 import android.widget.TextView;
44 
45 import com.android.internal.app.IBatteryStats;
46 import com.android.internal.telephony.IccCardConstants;
47 import com.android.internal.telephony.TelephonyIntents;
48 import com.android.internal.telephony.cdma.EriInfo;
49 import com.android.internal.util.AsyncChannel;
50 import com.android.server.am.BatteryStatsService;
51 import com.android.systemui.R;
52 
53 import java.io.FileDescriptor;
54 import java.io.PrintWriter;
55 import java.util.ArrayList;
56 import java.util.List;
57 
58 public class NetworkController extends BroadcastReceiver {
59     // debug
60     static final String TAG = "StatusBar.NetworkController";
61     static final boolean DEBUG = false;
62     static final boolean CHATTY = false; // additional diagnostics, but not logspew
63 
64     // telephony
65     boolean mHspaDataDistinguishable;
66     final TelephonyManager mPhone;
67     boolean mDataConnected;
68     IccCardConstants.State mSimState = IccCardConstants.State.READY;
69     int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
70     int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
71     int mDataState = TelephonyManager.DATA_DISCONNECTED;
72     int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
73     ServiceState mServiceState;
74     SignalStrength mSignalStrength;
75     int[] mDataIconList = TelephonyIcons.DATA_G[0];
76     String mNetworkName;
77     String mNetworkNameDefault;
78     String mNetworkNameSeparator;
79     int mPhoneSignalIconId;
80     int mQSPhoneSignalIconId;
81     int mDataDirectionIconId; // data + data direction on phones
82     int mDataSignalIconId;
83     int mDataTypeIconId;
84     int mQSDataTypeIconId;
85     int mAirplaneIconId;
86     boolean mDataActive;
87     int mMobileActivityIconId; // overlay arrows for data direction
88     int mLastSignalLevel;
89     boolean mShowPhoneRSSIForData = false;
90     boolean mShowAtLeastThreeGees = false;
91     boolean mAlwaysShowCdmaRssi = false;
92 
93     String mContentDescriptionPhoneSignal;
94     String mContentDescriptionWifi;
95     String mContentDescriptionWimax;
96     String mContentDescriptionCombinedSignal;
97     String mContentDescriptionDataType;
98 
99     // wifi
100     final WifiManager mWifiManager;
101     AsyncChannel mWifiChannel;
102     boolean mWifiEnabled, mWifiConnected;
103     int mWifiRssi, mWifiLevel;
104     String mWifiSsid;
105     int mWifiIconId = 0;
106     int mQSWifiIconId = 0;
107     int mWifiActivityIconId = 0; // overlay arrows for wifi direction
108     int mWifiActivity = WifiManager.DATA_ACTIVITY_NONE;
109 
110     // bluetooth
111     private boolean mBluetoothTethered = false;
112     private int mBluetoothTetherIconId =
113         com.android.internal.R.drawable.stat_sys_tether_bluetooth;
114 
115     //wimax
116     private boolean mWimaxSupported = false;
117     private boolean mIsWimaxEnabled = false;
118     private boolean mWimaxConnected = false;
119     private boolean mWimaxIdle = false;
120     private int mWimaxIconId = 0;
121     private int mWimaxSignal = 0;
122     private int mWimaxState = 0;
123     private int mWimaxExtraState = 0;
124 
125     // data connectivity (regardless of state, can we access the internet?)
126     // state of inet connection - 0 not connected, 100 connected
127     private boolean mConnected = false;
128     private int mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
129     private String mConnectedNetworkTypeName;
130     private int mInetCondition = 0;
131     private static final int INET_CONDITION_THRESHOLD = 50;
132 
133     private boolean mAirplaneMode = false;
134     private boolean mLastAirplaneMode = true;
135 
136     // our ui
137     Context mContext;
138     ArrayList<ImageView> mPhoneSignalIconViews = new ArrayList<ImageView>();
139     ArrayList<ImageView> mDataDirectionIconViews = new ArrayList<ImageView>();
140     ArrayList<ImageView> mDataDirectionOverlayIconViews = new ArrayList<ImageView>();
141     ArrayList<ImageView> mWifiIconViews = new ArrayList<ImageView>();
142     ArrayList<ImageView> mWimaxIconViews = new ArrayList<ImageView>();
143     ArrayList<ImageView> mCombinedSignalIconViews = new ArrayList<ImageView>();
144     ArrayList<ImageView> mDataTypeIconViews = new ArrayList<ImageView>();
145     ArrayList<TextView> mCombinedLabelViews = new ArrayList<TextView>();
146     ArrayList<TextView> mMobileLabelViews = new ArrayList<TextView>();
147     ArrayList<TextView> mWifiLabelViews = new ArrayList<TextView>();
148     ArrayList<TextView> mEmergencyLabelViews = new ArrayList<TextView>();
149     ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>();
150     ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks =
151             new ArrayList<NetworkSignalChangedCallback>();
152     int mLastPhoneSignalIconId = -1;
153     int mLastDataDirectionIconId = -1;
154     int mLastDataDirectionOverlayIconId = -1;
155     int mLastWifiIconId = -1;
156     int mLastWimaxIconId = -1;
157     int mLastCombinedSignalIconId = -1;
158     int mLastDataTypeIconId = -1;
159     String mLastCombinedLabel = "";
160 
161     private boolean mHasMobileDataFeature;
162 
163     boolean mDataAndWifiStacked = false;
164 
165     // yuck -- stop doing this here and put it in the framework
166     IBatteryStats mBatteryStats;
167 
168     public interface SignalCluster {
setWifiIndicators(boolean visible, int strengthIcon, int activityIcon, String contentDescription)169         void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon,
170                 String contentDescription);
setMobileDataIndicators(boolean visible, int strengthIcon, int activityIcon, int typeIcon, String contentDescription, String typeContentDescription)171         void setMobileDataIndicators(boolean visible, int strengthIcon, int activityIcon,
172                 int typeIcon, String contentDescription, String typeContentDescription);
setIsAirplaneMode(boolean is, int airplaneIcon)173         void setIsAirplaneMode(boolean is, int airplaneIcon);
174     }
175 
176     public interface NetworkSignalChangedCallback {
onWifiSignalChanged(boolean enabled, int wifiSignalIconId, String wifitSignalContentDescriptionId, String description)177         void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
178                 String wifitSignalContentDescriptionId, String description);
onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId, String mobileSignalContentDescriptionId, int dataTypeIconId, String dataTypeContentDescriptionId, String description)179         void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId,
180                 String mobileSignalContentDescriptionId, int dataTypeIconId,
181                 String dataTypeContentDescriptionId, String description);
onAirplaneModeChanged(boolean enabled)182         void onAirplaneModeChanged(boolean enabled);
183     }
184 
185     /**
186      * Construct this controller object and register for updates.
187      */
NetworkController(Context context)188     public NetworkController(Context context) {
189         mContext = context;
190         final Resources res = context.getResources();
191 
192         ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
193                 Context.CONNECTIVITY_SERVICE);
194         mHasMobileDataFeature = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
195 
196         mShowPhoneRSSIForData = res.getBoolean(R.bool.config_showPhoneRSSIForData);
197         mShowAtLeastThreeGees = res.getBoolean(R.bool.config_showMin3G);
198         mAlwaysShowCdmaRssi = res.getBoolean(
199                 com.android.internal.R.bool.config_alwaysUseCdmaRssi);
200 
201         // set up the default wifi icon, used when no radios have ever appeared
202         updateWifiIcons();
203         updateWimaxIcons();
204 
205         // telephony
206         mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
207         mPhone.listen(mPhoneStateListener,
208                           PhoneStateListener.LISTEN_SERVICE_STATE
209                         | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
210                         | PhoneStateListener.LISTEN_CALL_STATE
211                         | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
212                         | PhoneStateListener.LISTEN_DATA_ACTIVITY);
213         mHspaDataDistinguishable = mContext.getResources().getBoolean(
214                 R.bool.config_hspa_data_distinguishable);
215         mNetworkNameSeparator = mContext.getString(R.string.status_bar_network_name_separator);
216         mNetworkNameDefault = mContext.getString(
217                 com.android.internal.R.string.lockscreen_carrier_default);
218         mNetworkName = mNetworkNameDefault;
219 
220         // wifi
221         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
222         Handler handler = new WifiHandler();
223         mWifiChannel = new AsyncChannel();
224         Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger();
225         if (wifiMessenger != null) {
226             mWifiChannel.connect(mContext, handler, wifiMessenger);
227         }
228 
229         // broadcasts
230         IntentFilter filter = new IntentFilter();
231         filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
232         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
233         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
234         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
235         filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
236         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
237         filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
238         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
239         filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
240         mWimaxSupported = mContext.getResources().getBoolean(
241                 com.android.internal.R.bool.config_wimaxEnabled);
242         if(mWimaxSupported) {
243             filter.addAction(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION);
244             filter.addAction(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION);
245             filter.addAction(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION);
246         }
247         context.registerReceiver(this, filter);
248 
249         // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
250         updateAirplaneMode();
251 
252         // yuck
253         mBatteryStats = BatteryStatsService.getService();
254     }
255 
hasMobileDataFeature()256     public boolean hasMobileDataFeature() {
257         return mHasMobileDataFeature;
258     }
259 
isEmergencyOnly()260     public boolean isEmergencyOnly() {
261         return (mServiceState != null && mServiceState.isEmergencyOnly());
262     }
263 
addPhoneSignalIconView(ImageView v)264     public void addPhoneSignalIconView(ImageView v) {
265         mPhoneSignalIconViews.add(v);
266     }
267 
addDataDirectionIconView(ImageView v)268     public void addDataDirectionIconView(ImageView v) {
269         mDataDirectionIconViews.add(v);
270     }
271 
addDataDirectionOverlayIconView(ImageView v)272     public void addDataDirectionOverlayIconView(ImageView v) {
273         mDataDirectionOverlayIconViews.add(v);
274     }
275 
addWifiIconView(ImageView v)276     public void addWifiIconView(ImageView v) {
277         mWifiIconViews.add(v);
278     }
addWimaxIconView(ImageView v)279     public void addWimaxIconView(ImageView v) {
280         mWimaxIconViews.add(v);
281     }
282 
addCombinedSignalIconView(ImageView v)283     public void addCombinedSignalIconView(ImageView v) {
284         mCombinedSignalIconViews.add(v);
285     }
286 
addDataTypeIconView(ImageView v)287     public void addDataTypeIconView(ImageView v) {
288         mDataTypeIconViews.add(v);
289     }
290 
addCombinedLabelView(TextView v)291     public void addCombinedLabelView(TextView v) {
292         mCombinedLabelViews.add(v);
293     }
294 
addMobileLabelView(TextView v)295     public void addMobileLabelView(TextView v) {
296         mMobileLabelViews.add(v);
297     }
298 
addWifiLabelView(TextView v)299     public void addWifiLabelView(TextView v) {
300         mWifiLabelViews.add(v);
301     }
302 
addEmergencyLabelView(TextView v)303     public void addEmergencyLabelView(TextView v) {
304         mEmergencyLabelViews.add(v);
305     }
306 
addSignalCluster(SignalCluster cluster)307     public void addSignalCluster(SignalCluster cluster) {
308         mSignalClusters.add(cluster);
309         refreshSignalCluster(cluster);
310     }
311 
addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb)312     public void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) {
313         mSignalsChangedCallbacks.add(cb);
314         notifySignalsChangedCallbacks(cb);
315     }
316 
refreshSignalCluster(SignalCluster cluster)317     public void refreshSignalCluster(SignalCluster cluster) {
318         cluster.setWifiIndicators(
319                 // only show wifi in the cluster if connected or if wifi-only
320                 mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature),
321                 mWifiIconId,
322                 mWifiActivityIconId,
323                 mContentDescriptionWifi);
324 
325         if (mIsWimaxEnabled && mWimaxConnected) {
326             // wimax is special
327             cluster.setMobileDataIndicators(
328                     true,
329                     mAlwaysShowCdmaRssi ? mPhoneSignalIconId : mWimaxIconId,
330                     mMobileActivityIconId,
331                     mDataTypeIconId,
332                     mContentDescriptionWimax,
333                     mContentDescriptionDataType);
334         } else {
335             // normal mobile data
336             cluster.setMobileDataIndicators(
337                     mHasMobileDataFeature,
338                     mShowPhoneRSSIForData ? mPhoneSignalIconId : mDataSignalIconId,
339                     mMobileActivityIconId,
340                     mDataTypeIconId,
341                     mContentDescriptionPhoneSignal,
342                     mContentDescriptionDataType);
343         }
344         cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId);
345     }
346 
notifySignalsChangedCallbacks(NetworkSignalChangedCallback cb)347     void notifySignalsChangedCallbacks(NetworkSignalChangedCallback cb) {
348         // only show wifi in the cluster if connected or if wifi-only
349         boolean wifiEnabled = mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature);
350         String wifiDesc = wifiEnabled ?
351                 mWifiSsid : null;
352         cb.onWifiSignalChanged(wifiEnabled, mQSWifiIconId, mContentDescriptionWifi, wifiDesc);
353 
354         if (isEmergencyOnly()) {
355             cb.onMobileDataSignalChanged(false, mQSPhoneSignalIconId,
356                     mContentDescriptionPhoneSignal, mQSDataTypeIconId, mContentDescriptionDataType,
357                     null);
358         } else {
359             if (mIsWimaxEnabled && mWimaxConnected) {
360                 // Wimax is special
361                 cb.onMobileDataSignalChanged(true, mQSPhoneSignalIconId,
362                         mContentDescriptionPhoneSignal, mQSDataTypeIconId,
363                         mContentDescriptionDataType, mNetworkName);
364             } else {
365                 // Normal mobile data
366                 cb.onMobileDataSignalChanged(mHasMobileDataFeature, mQSPhoneSignalIconId,
367                         mContentDescriptionPhoneSignal, mQSDataTypeIconId,
368                         mContentDescriptionDataType, mNetworkName);
369             }
370         }
371         cb.onAirplaneModeChanged(mAirplaneMode);
372     }
373 
setStackedMode(boolean stacked)374     public void setStackedMode(boolean stacked) {
375         mDataAndWifiStacked = true;
376     }
377 
378     @Override
onReceive(Context context, Intent intent)379     public void onReceive(Context context, Intent intent) {
380         final String action = intent.getAction();
381         if (action.equals(WifiManager.RSSI_CHANGED_ACTION)
382                 || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)
383                 || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
384             updateWifiState(intent);
385             refreshViews();
386         } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
387             updateSimState(intent);
388             updateDataIcon();
389             refreshViews();
390         } else if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
391             updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
392                         intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
393                         intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
394                         intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
395             refreshViews();
396         } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
397                  action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
398             updateConnectivity(intent);
399             refreshViews();
400         } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
401             refreshViews();
402         } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
403             updateAirplaneMode();
404             refreshViews();
405         } else if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION) ||
406                 action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION) ||
407                 action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) {
408             updateWimaxState(intent);
409             refreshViews();
410         }
411     }
412 
413 
414     // ===== Telephony ==============================================================
415 
416     PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
417         @Override
418         public void onSignalStrengthsChanged(SignalStrength signalStrength) {
419             if (DEBUG) {
420                 Slog.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength +
421                     ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
422             }
423             mSignalStrength = signalStrength;
424             updateTelephonySignalStrength();
425             refreshViews();
426         }
427 
428         @Override
429         public void onServiceStateChanged(ServiceState state) {
430             if (DEBUG) {
431                 Slog.d(TAG, "onServiceStateChanged state=" + state.getState());
432             }
433             mServiceState = state;
434             updateTelephonySignalStrength();
435             updateDataNetType();
436             updateDataIcon();
437             refreshViews();
438         }
439 
440         @Override
441         public void onCallStateChanged(int state, String incomingNumber) {
442             if (DEBUG) {
443                 Slog.d(TAG, "onCallStateChanged state=" + state);
444             }
445             // In cdma, if a voice call is made, RSSI should switch to 1x.
446             if (isCdma()) {
447                 updateTelephonySignalStrength();
448                 refreshViews();
449             }
450         }
451 
452         @Override
453         public void onDataConnectionStateChanged(int state, int networkType) {
454             if (DEBUG) {
455                 Slog.d(TAG, "onDataConnectionStateChanged: state=" + state
456                         + " type=" + networkType);
457             }
458             mDataState = state;
459             mDataNetType = networkType;
460             updateDataNetType();
461             updateDataIcon();
462             refreshViews();
463         }
464 
465         @Override
466         public void onDataActivity(int direction) {
467             if (DEBUG) {
468                 Slog.d(TAG, "onDataActivity: direction=" + direction);
469             }
470             mDataActivity = direction;
471             updateDataIcon();
472             refreshViews();
473         }
474     };
475 
updateSimState(Intent intent)476     private final void updateSimState(Intent intent) {
477         String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
478         if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
479             mSimState = IccCardConstants.State.ABSENT;
480         }
481         else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
482             mSimState = IccCardConstants.State.READY;
483         }
484         else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
485             final String lockedReason =
486                     intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
487             if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
488                 mSimState = IccCardConstants.State.PIN_REQUIRED;
489             }
490             else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
491                 mSimState = IccCardConstants.State.PUK_REQUIRED;
492             }
493             else {
494                 mSimState = IccCardConstants.State.NETWORK_LOCKED;
495             }
496         } else {
497             mSimState = IccCardConstants.State.UNKNOWN;
498         }
499     }
500 
isCdma()501     private boolean isCdma() {
502         return (mSignalStrength != null) && !mSignalStrength.isGsm();
503     }
504 
hasService()505     private boolean hasService() {
506         if (mServiceState != null) {
507             switch (mServiceState.getState()) {
508                 case ServiceState.STATE_OUT_OF_SERVICE:
509                 case ServiceState.STATE_POWER_OFF:
510                     return false;
511                 default:
512                     return true;
513             }
514         } else {
515             return false;
516         }
517     }
518 
updateAirplaneMode()519     private void updateAirplaneMode() {
520         mAirplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
521             Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
522     }
523 
updateTelephonySignalStrength()524     private final void updateTelephonySignalStrength() {
525         if (!hasService()) {
526             if (CHATTY) Slog.d(TAG, "updateTelephonySignalStrength: !hasService()");
527             mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
528             mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
529             mDataSignalIconId = R.drawable.stat_sys_signal_null;
530         } else {
531             if (mSignalStrength == null) {
532                 if (CHATTY) Slog.d(TAG, "updateTelephonySignalStrength: mSignalStrength == null");
533                 mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
534                 mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
535                 mDataSignalIconId = R.drawable.stat_sys_signal_null;
536                 mContentDescriptionPhoneSignal = mContext.getString(
537                         AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]);
538             } else {
539                 int iconLevel;
540                 int[] iconList;
541                 if (isCdma() && mAlwaysShowCdmaRssi) {
542                     mLastSignalLevel = iconLevel = mSignalStrength.getCdmaLevel();
543                     if(DEBUG) Slog.d(TAG, "mAlwaysShowCdmaRssi=" + mAlwaysShowCdmaRssi
544                             + " set to cdmaLevel=" + mSignalStrength.getCdmaLevel()
545                             + " instead of level=" + mSignalStrength.getLevel());
546                 } else {
547                     mLastSignalLevel = iconLevel = mSignalStrength.getLevel();
548                 }
549 
550                 if (isCdma()) {
551                     if (isCdmaEri()) {
552                         iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition];
553                     } else {
554                         iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition];
555                     }
556                 } else {
557                     // Though mPhone is a Manager, this call is not an IPC
558                     if (mPhone.isNetworkRoaming()) {
559                         iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition];
560                     } else {
561                         iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition];
562                     }
563                 }
564                 mPhoneSignalIconId = iconList[iconLevel];
565                 mQSPhoneSignalIconId =
566                         TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[mInetCondition][iconLevel];
567                 mContentDescriptionPhoneSignal = mContext.getString(
568                         AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[iconLevel]);
569                 mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel];
570             }
571         }
572     }
573 
updateDataNetType()574     private final void updateDataNetType() {
575         if (mIsWimaxEnabled && mWimaxConnected) {
576             // wimax is a special 4g network not handled by telephony
577             mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
578             mDataTypeIconId = R.drawable.stat_sys_data_connected_4g;
579             mQSDataTypeIconId = R.drawable.ic_qs_signal_4g;
580             mContentDescriptionDataType = mContext.getString(
581                     R.string.accessibility_data_connection_4g);
582         } else {
583             switch (mDataNetType) {
584                 case TelephonyManager.NETWORK_TYPE_UNKNOWN:
585                     if (!mShowAtLeastThreeGees) {
586                         mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
587                         mDataTypeIconId = 0;
588                         mQSDataTypeIconId = 0;
589                         mContentDescriptionDataType = mContext.getString(
590                                 R.string.accessibility_data_connection_gprs);
591                         break;
592                     } else {
593                         // fall through
594                     }
595                 case TelephonyManager.NETWORK_TYPE_EDGE:
596                     if (!mShowAtLeastThreeGees) {
597                         mDataIconList = TelephonyIcons.DATA_E[mInetCondition];
598                         mDataTypeIconId = R.drawable.stat_sys_data_connected_e;
599                         mQSDataTypeIconId = R.drawable.ic_qs_signal_e;
600                         mContentDescriptionDataType = mContext.getString(
601                                 R.string.accessibility_data_connection_edge);
602                         break;
603                     } else {
604                         // fall through
605                     }
606                 case TelephonyManager.NETWORK_TYPE_UMTS:
607                     mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
608                     mDataTypeIconId = R.drawable.stat_sys_data_connected_3g;
609                     mQSDataTypeIconId = R.drawable.ic_qs_signal_3g;
610                     mContentDescriptionDataType = mContext.getString(
611                             R.string.accessibility_data_connection_3g);
612                     break;
613                 case TelephonyManager.NETWORK_TYPE_HSDPA:
614                 case TelephonyManager.NETWORK_TYPE_HSUPA:
615                 case TelephonyManager.NETWORK_TYPE_HSPA:
616                 case TelephonyManager.NETWORK_TYPE_HSPAP:
617                     if (mHspaDataDistinguishable) {
618                         mDataIconList = TelephonyIcons.DATA_H[mInetCondition];
619                         mDataTypeIconId = R.drawable.stat_sys_data_connected_h;
620                         mQSDataTypeIconId = R.drawable.ic_qs_signal_h;
621                         mContentDescriptionDataType = mContext.getString(
622                                 R.string.accessibility_data_connection_3_5g);
623                     } else {
624                         mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
625                         mDataTypeIconId = R.drawable.stat_sys_data_connected_3g;
626                         mQSDataTypeIconId = R.drawable.ic_qs_signal_3g;
627                         mContentDescriptionDataType = mContext.getString(
628                                 R.string.accessibility_data_connection_3g);
629                     }
630                     break;
631                 case TelephonyManager.NETWORK_TYPE_CDMA:
632                     if (!mShowAtLeastThreeGees) {
633                         // display 1xRTT for IS95A/B
634                         mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
635                         mDataTypeIconId = R.drawable.stat_sys_data_connected_1x;
636                         mQSDataTypeIconId = R.drawable.ic_qs_signal_1x;
637                         mContentDescriptionDataType = mContext.getString(
638                                 R.string.accessibility_data_connection_cdma);
639                         break;
640                     } else {
641                         // fall through
642                     }
643                 case TelephonyManager.NETWORK_TYPE_1xRTT:
644                     if (!mShowAtLeastThreeGees) {
645                         mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
646                         mDataTypeIconId = R.drawable.stat_sys_data_connected_1x;
647                         mQSDataTypeIconId = R.drawable.ic_qs_signal_1x;
648                         mContentDescriptionDataType = mContext.getString(
649                                 R.string.accessibility_data_connection_cdma);
650                         break;
651                     } else {
652                         // fall through
653                     }
654                 case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
655                 case TelephonyManager.NETWORK_TYPE_EVDO_A:
656                 case TelephonyManager.NETWORK_TYPE_EVDO_B:
657                 case TelephonyManager.NETWORK_TYPE_EHRPD:
658                     mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
659                     mDataTypeIconId = R.drawable.stat_sys_data_connected_3g;
660                     mQSDataTypeIconId = R.drawable.ic_qs_signal_3g;
661                     mContentDescriptionDataType = mContext.getString(
662                             R.string.accessibility_data_connection_3g);
663                     break;
664                 case TelephonyManager.NETWORK_TYPE_LTE:
665                     mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
666                     mDataTypeIconId = R.drawable.stat_sys_data_connected_4g;
667                     mQSDataTypeIconId = R.drawable.ic_qs_signal_4g;
668                     mContentDescriptionDataType = mContext.getString(
669                             R.string.accessibility_data_connection_4g);
670                     break;
671                 default:
672                     if (!mShowAtLeastThreeGees) {
673                         mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
674                         mDataTypeIconId = R.drawable.stat_sys_data_connected_g;
675                         mQSDataTypeIconId = R.drawable.ic_qs_signal_g;
676                         mContentDescriptionDataType = mContext.getString(
677                                 R.string.accessibility_data_connection_gprs);
678                     } else {
679                         mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
680                         mDataTypeIconId = R.drawable.stat_sys_data_connected_3g;
681                         mQSDataTypeIconId = R.drawable.ic_qs_signal_3g;
682                         mContentDescriptionDataType = mContext.getString(
683                                 R.string.accessibility_data_connection_3g);
684                     }
685                     break;
686             }
687         }
688 
689         if (isCdma()) {
690             if (isCdmaEri()) {
691                 mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
692                 mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
693             }
694         } else if (mPhone.isNetworkRoaming()) {
695                 mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
696                 mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
697         }
698     }
699 
isCdmaEri()700     boolean isCdmaEri() {
701         if (mServiceState != null) {
702             final int iconIndex = mServiceState.getCdmaEriIconIndex();
703             if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) {
704                 final int iconMode = mServiceState.getCdmaEriIconMode();
705                 if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
706                         || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) {
707                     return true;
708                 }
709             }
710         }
711         return false;
712     }
713 
updateDataIcon()714     private final void updateDataIcon() {
715         int iconId;
716         boolean visible = true;
717 
718         if (!isCdma()) {
719             // GSM case, we have to check also the sim state
720             if (mSimState == IccCardConstants.State.READY ||
721                     mSimState == IccCardConstants.State.UNKNOWN) {
722                 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
723                     switch (mDataActivity) {
724                         case TelephonyManager.DATA_ACTIVITY_IN:
725                             iconId = mDataIconList[1];
726                             break;
727                         case TelephonyManager.DATA_ACTIVITY_OUT:
728                             iconId = mDataIconList[2];
729                             break;
730                         case TelephonyManager.DATA_ACTIVITY_INOUT:
731                             iconId = mDataIconList[3];
732                             break;
733                         default:
734                             iconId = mDataIconList[0];
735                             break;
736                     }
737                     mDataDirectionIconId = iconId;
738                 } else {
739                     iconId = 0;
740                     visible = false;
741                 }
742             } else {
743                 iconId = R.drawable.stat_sys_no_sim;
744                 visible = false; // no SIM? no data
745             }
746         } else {
747             // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
748             if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
749                 switch (mDataActivity) {
750                     case TelephonyManager.DATA_ACTIVITY_IN:
751                         iconId = mDataIconList[1];
752                         break;
753                     case TelephonyManager.DATA_ACTIVITY_OUT:
754                         iconId = mDataIconList[2];
755                         break;
756                     case TelephonyManager.DATA_ACTIVITY_INOUT:
757                         iconId = mDataIconList[3];
758                         break;
759                     case TelephonyManager.DATA_ACTIVITY_DORMANT:
760                     default:
761                         iconId = mDataIconList[0];
762                         break;
763                 }
764             } else {
765                 iconId = 0;
766                 visible = false;
767             }
768         }
769 
770         // yuck - this should NOT be done by the status bar
771         long ident = Binder.clearCallingIdentity();
772         try {
773             mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
774         } catch (RemoteException e) {
775         } finally {
776             Binder.restoreCallingIdentity(ident);
777         }
778 
779         mDataDirectionIconId = iconId;
780         mDataConnected = visible;
781     }
782 
updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn)783     void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) {
784         if (false) {
785             Slog.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
786                     + " showPlmn=" + showPlmn + " plmn=" + plmn);
787         }
788         StringBuilder str = new StringBuilder();
789         boolean something = false;
790         if (showPlmn && plmn != null) {
791             str.append(plmn);
792             something = true;
793         }
794         if (showSpn && spn != null) {
795             if (something) {
796                 str.append(mNetworkNameSeparator);
797             }
798             str.append(spn);
799             something = true;
800         }
801         if (something) {
802             mNetworkName = str.toString();
803         } else {
804             mNetworkName = mNetworkNameDefault;
805         }
806     }
807 
808     // ===== Wifi ===================================================================
809 
810     class WifiHandler extends Handler {
811         @Override
handleMessage(Message msg)812         public void handleMessage(Message msg) {
813             switch (msg.what) {
814                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
815                     if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
816                         mWifiChannel.sendMessage(Message.obtain(this,
817                                 AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
818                     } else {
819                         Slog.e(TAG, "Failed to connect to wifi");
820                     }
821                     break;
822                 case WifiManager.DATA_ACTIVITY_NOTIFICATION:
823                     if (msg.arg1 != mWifiActivity) {
824                         mWifiActivity = msg.arg1;
825                         refreshViews();
826                     }
827                     break;
828                 default:
829                     //Ignore
830                     break;
831             }
832         }
833     }
834 
updateWifiState(Intent intent)835     private void updateWifiState(Intent intent) {
836         final String action = intent.getAction();
837         if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
838             mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
839                     WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
840 
841         } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
842             final NetworkInfo networkInfo = (NetworkInfo)
843                     intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
844             boolean wasConnected = mWifiConnected;
845             mWifiConnected = networkInfo != null && networkInfo.isConnected();
846             // If we just connected, grab the inintial signal strength and ssid
847             if (mWifiConnected && !wasConnected) {
848                 // try getting it out of the intent first
849                 WifiInfo info = (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
850                 if (info == null) {
851                     info = mWifiManager.getConnectionInfo();
852                 }
853                 if (info != null) {
854                     mWifiSsid = huntForSsid(info);
855                 } else {
856                     mWifiSsid = null;
857                 }
858             } else if (!mWifiConnected) {
859                 mWifiSsid = null;
860             }
861         } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
862             mWifiRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
863             mWifiLevel = WifiManager.calculateSignalLevel(
864                     mWifiRssi, WifiIcons.WIFI_LEVEL_COUNT);
865         }
866 
867         updateWifiIcons();
868     }
869 
updateWifiIcons()870     private void updateWifiIcons() {
871         if (mWifiConnected) {
872             mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
873             mQSWifiIconId = WifiIcons.QS_WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
874             mContentDescriptionWifi = mContext.getString(
875                     AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]);
876         } else {
877             if (mDataAndWifiStacked) {
878                 mWifiIconId = 0;
879                 mQSWifiIconId = 0;
880             } else {
881                 mWifiIconId = mWifiEnabled ? R.drawable.stat_sys_wifi_signal_null : 0;
882                 mQSWifiIconId = mWifiEnabled ? R.drawable.ic_qs_wifi_no_network : 0;
883             }
884             mContentDescriptionWifi = mContext.getString(R.string.accessibility_no_wifi);
885         }
886     }
887 
huntForSsid(WifiInfo info)888     private String huntForSsid(WifiInfo info) {
889         String ssid = info.getSSID();
890         if (ssid != null) {
891             return ssid;
892         }
893         // OK, it's not in the connectionInfo; we have to go hunting for it
894         List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
895         for (WifiConfiguration net : networks) {
896             if (net.networkId == info.getNetworkId()) {
897                 return net.SSID;
898             }
899         }
900         return null;
901     }
902 
903 
904     // ===== Wimax ===================================================================
updateWimaxState(Intent intent)905     private final void updateWimaxState(Intent intent) {
906         final String action = intent.getAction();
907         boolean wasConnected = mWimaxConnected;
908         if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION)) {
909             int wimaxStatus = intent.getIntExtra(WimaxManagerConstants.EXTRA_4G_STATE,
910                     WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
911             mIsWimaxEnabled = (wimaxStatus ==
912                     WimaxManagerConstants.NET_4G_STATE_ENABLED);
913         } else if (action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION)) {
914             mWimaxSignal = intent.getIntExtra(WimaxManagerConstants.EXTRA_NEW_SIGNAL_LEVEL, 0);
915         } else if (action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) {
916             mWimaxState = intent.getIntExtra(WimaxManagerConstants.EXTRA_WIMAX_STATE,
917                     WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
918             mWimaxExtraState = intent.getIntExtra(
919                     WimaxManagerConstants.EXTRA_WIMAX_STATE_DETAIL,
920                     WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
921             mWimaxConnected = (mWimaxState ==
922                     WimaxManagerConstants.WIMAX_STATE_CONNECTED);
923             mWimaxIdle = (mWimaxExtraState == WimaxManagerConstants.WIMAX_IDLE);
924         }
925         updateDataNetType();
926         updateWimaxIcons();
927     }
928 
updateWimaxIcons()929     private void updateWimaxIcons() {
930         if (mIsWimaxEnabled) {
931             if (mWimaxConnected) {
932                 if (mWimaxIdle)
933                     mWimaxIconId = WimaxIcons.WIMAX_IDLE;
934                 else
935                     mWimaxIconId = WimaxIcons.WIMAX_SIGNAL_STRENGTH[mInetCondition][mWimaxSignal];
936                 mContentDescriptionWimax = mContext.getString(
937                         AccessibilityContentDescriptions.WIMAX_CONNECTION_STRENGTH[mWimaxSignal]);
938             } else {
939                 mWimaxIconId = WimaxIcons.WIMAX_DISCONNECTED;
940                 mContentDescriptionWimax = mContext.getString(R.string.accessibility_no_wimax);
941             }
942         } else {
943             mWimaxIconId = 0;
944         }
945     }
946 
947     // ===== Full or limited Internet connectivity ==================================
948 
updateConnectivity(Intent intent)949     private void updateConnectivity(Intent intent) {
950         if (CHATTY) {
951             Slog.d(TAG, "updateConnectivity: intent=" + intent);
952         }
953 
954         final ConnectivityManager connManager = (ConnectivityManager) mContext
955                 .getSystemService(Context.CONNECTIVITY_SERVICE);
956         final NetworkInfo info = connManager.getActiveNetworkInfo();
957 
958         // Are we connected at all, by any interface?
959         mConnected = info != null && info.isConnected();
960         if (mConnected) {
961             mConnectedNetworkType = info.getType();
962             mConnectedNetworkTypeName = info.getTypeName();
963         } else {
964             mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
965             mConnectedNetworkTypeName = null;
966         }
967 
968         int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
969 
970         if (CHATTY) {
971             Slog.d(TAG, "updateConnectivity: networkInfo=" + info);
972             Slog.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus);
973         }
974 
975         mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
976 
977         if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) {
978             mBluetoothTethered = info.isConnected();
979         } else {
980             mBluetoothTethered = false;
981         }
982 
983         // We want to update all the icons, all at once, for any condition change
984         updateDataNetType();
985         updateWimaxIcons();
986         updateDataIcon();
987         updateTelephonySignalStrength();
988         updateWifiIcons();
989     }
990 
991 
992     // ===== Update the views =======================================================
993 
refreshViews()994     void refreshViews() {
995         Context context = mContext;
996 
997         int combinedSignalIconId = 0;
998         int combinedActivityIconId = 0;
999         String combinedLabel = "";
1000         String wifiLabel = "";
1001         String mobileLabel = "";
1002         int N;
1003         final boolean emergencyOnly = isEmergencyOnly();
1004 
1005         if (!mHasMobileDataFeature) {
1006             mDataSignalIconId = mPhoneSignalIconId = 0;
1007             mQSPhoneSignalIconId = 0;
1008             mobileLabel = "";
1009         } else {
1010             // We want to show the carrier name if in service and either:
1011             //   - We are connected to mobile data, or
1012             //   - We are not connected to mobile data, as long as the *reason* packets are not
1013             //     being routed over that link is that we have better connectivity via wifi.
1014             // If data is disconnected for some other reason but wifi (or ethernet/bluetooth)
1015             // is connected, we show nothing.
1016             // Otherwise (nothing connected) we show "No internet connection".
1017 
1018             if (mDataConnected) {
1019                 mobileLabel = mNetworkName;
1020             } else if (mConnected || emergencyOnly) {
1021                 if (hasService() || emergencyOnly) {
1022                     // The isEmergencyOnly test covers the case of a phone with no SIM
1023                     mobileLabel = mNetworkName;
1024                 } else {
1025                     // Tablets, basically
1026                     mobileLabel = "";
1027                 }
1028             } else {
1029                 mobileLabel
1030                     = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
1031             }
1032 
1033             // Now for things that should only be shown when actually using mobile data.
1034             if (mDataConnected) {
1035                 combinedSignalIconId = mDataSignalIconId;
1036                 switch (mDataActivity) {
1037                     case TelephonyManager.DATA_ACTIVITY_IN:
1038                         mMobileActivityIconId = R.drawable.stat_sys_signal_in;
1039                         break;
1040                     case TelephonyManager.DATA_ACTIVITY_OUT:
1041                         mMobileActivityIconId = R.drawable.stat_sys_signal_out;
1042                         break;
1043                     case TelephonyManager.DATA_ACTIVITY_INOUT:
1044                         mMobileActivityIconId = R.drawable.stat_sys_signal_inout;
1045                         break;
1046                     default:
1047                         mMobileActivityIconId = 0;
1048                         break;
1049                 }
1050 
1051                 combinedLabel = mobileLabel;
1052                 combinedActivityIconId = mMobileActivityIconId;
1053                 combinedSignalIconId = mDataSignalIconId; // set by updateDataIcon()
1054                 mContentDescriptionCombinedSignal = mContentDescriptionDataType;
1055             } else {
1056                 mMobileActivityIconId = 0;
1057             }
1058         }
1059 
1060         if (mWifiConnected) {
1061             if (mWifiSsid == null) {
1062                 wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid);
1063                 mWifiActivityIconId = 0; // no wifis, no bits
1064             } else {
1065                 wifiLabel = mWifiSsid;
1066                 if (DEBUG) {
1067                     wifiLabel += "xxxxXXXXxxxxXXXX";
1068                 }
1069                 switch (mWifiActivity) {
1070                     case WifiManager.DATA_ACTIVITY_IN:
1071                         mWifiActivityIconId = R.drawable.stat_sys_wifi_in;
1072                         break;
1073                     case WifiManager.DATA_ACTIVITY_OUT:
1074                         mWifiActivityIconId = R.drawable.stat_sys_wifi_out;
1075                         break;
1076                     case WifiManager.DATA_ACTIVITY_INOUT:
1077                         mWifiActivityIconId = R.drawable.stat_sys_wifi_inout;
1078                         break;
1079                     case WifiManager.DATA_ACTIVITY_NONE:
1080                         mWifiActivityIconId = 0;
1081                         break;
1082                 }
1083             }
1084 
1085             combinedActivityIconId = mWifiActivityIconId;
1086             combinedLabel = wifiLabel;
1087             combinedSignalIconId = mWifiIconId; // set by updateWifiIcons()
1088             mContentDescriptionCombinedSignal = mContentDescriptionWifi;
1089         } else {
1090             if (mHasMobileDataFeature) {
1091                 wifiLabel = "";
1092             } else {
1093                 wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
1094             }
1095         }
1096 
1097         if (mBluetoothTethered) {
1098             combinedLabel = mContext.getString(R.string.bluetooth_tethered);
1099             combinedSignalIconId = mBluetoothTetherIconId;
1100             mContentDescriptionCombinedSignal = mContext.getString(
1101                     R.string.accessibility_bluetooth_tether);
1102         }
1103 
1104         final boolean ethernetConnected = (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET);
1105         if (ethernetConnected) {
1106             combinedLabel = context.getString(R.string.ethernet_label);
1107         }
1108 
1109         if (mAirplaneMode &&
1110                 (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) {
1111             // Only display the flight-mode icon if not in "emergency calls only" mode.
1112 
1113             // look again; your radios are now airplanes
1114             mContentDescriptionPhoneSignal = mContext.getString(
1115                     R.string.accessibility_airplane_mode);
1116             mAirplaneIconId = R.drawable.stat_sys_signal_flightmode;
1117             mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = mQSDataTypeIconId = 0;
1118             mQSPhoneSignalIconId = 0;
1119 
1120             // combined values from connected wifi take precedence over airplane mode
1121             if (mWifiConnected) {
1122                 // Suppress "No internet connection." from mobile if wifi connected.
1123                 mobileLabel = "";
1124             } else {
1125                 if (mHasMobileDataFeature) {
1126                     // let the mobile icon show "No internet connection."
1127                     wifiLabel = "";
1128                 } else {
1129                     wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
1130                     combinedLabel = wifiLabel;
1131                 }
1132                 mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal;
1133                 combinedSignalIconId = mDataSignalIconId;
1134             }
1135         }
1136         else if (!mDataConnected && !mWifiConnected && !mBluetoothTethered && !mWimaxConnected && !ethernetConnected) {
1137             // pretty much totally disconnected
1138 
1139             combinedLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
1140             // On devices without mobile radios, we want to show the wifi icon
1141             combinedSignalIconId =
1142                 mHasMobileDataFeature ? mDataSignalIconId : mWifiIconId;
1143             mContentDescriptionCombinedSignal = mHasMobileDataFeature
1144                 ? mContentDescriptionDataType : mContentDescriptionWifi;
1145 
1146             mDataTypeIconId = 0;
1147             mQSDataTypeIconId = 0;
1148             if (isCdma()) {
1149                 if (isCdmaEri()) {
1150                     mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
1151                     mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
1152                 }
1153             } else if (mPhone.isNetworkRoaming()) {
1154                 mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
1155                 mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
1156             }
1157         }
1158 
1159         if (DEBUG) {
1160             Slog.d(TAG, "refreshViews connected={"
1161                     + (mWifiConnected?" wifi":"")
1162                     + (mDataConnected?" data":"")
1163                     + " } level="
1164                     + ((mSignalStrength == null)?"??":Integer.toString(mSignalStrength.getLevel()))
1165                     + " combinedSignalIconId=0x"
1166                     + Integer.toHexString(combinedSignalIconId)
1167                     + "/" + getResourceName(combinedSignalIconId)
1168                     + " combinedActivityIconId=0x" + Integer.toHexString(combinedActivityIconId)
1169                     + " mobileLabel=" + mobileLabel
1170                     + " wifiLabel=" + wifiLabel
1171                     + " emergencyOnly=" + emergencyOnly
1172                     + " combinedLabel=" + combinedLabel
1173                     + " mAirplaneMode=" + mAirplaneMode
1174                     + " mDataActivity=" + mDataActivity
1175                     + " mPhoneSignalIconId=0x" + Integer.toHexString(mPhoneSignalIconId)
1176                     + " mQSPhoneSignalIconId=0x" + Integer.toHexString(mQSPhoneSignalIconId)
1177                     + " mDataDirectionIconId=0x" + Integer.toHexString(mDataDirectionIconId)
1178                     + " mDataSignalIconId=0x" + Integer.toHexString(mDataSignalIconId)
1179                     + " mDataTypeIconId=0x" + Integer.toHexString(mDataTypeIconId)
1180                     + " mQSDataTypeIconId=0x" + Integer.toHexString(mQSDataTypeIconId)
1181                     + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId)
1182                     + " mQSWifiIconId=0x" + Integer.toHexString(mQSWifiIconId)
1183                     + " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId));
1184         }
1185 
1186         if (mLastPhoneSignalIconId          != mPhoneSignalIconId
1187          || mLastDataDirectionOverlayIconId != combinedActivityIconId
1188          || mLastWifiIconId                 != mWifiIconId
1189          || mLastWimaxIconId                != mWimaxIconId
1190          || mLastDataTypeIconId             != mDataTypeIconId
1191          || mLastAirplaneMode               != mAirplaneMode)
1192         {
1193             // NB: the mLast*s will be updated later
1194             for (SignalCluster cluster : mSignalClusters) {
1195                 refreshSignalCluster(cluster);
1196             }
1197             for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
1198                 notifySignalsChangedCallbacks(cb);
1199             }
1200         }
1201 
1202         if (mLastAirplaneMode != mAirplaneMode) {
1203             mLastAirplaneMode = mAirplaneMode;
1204         }
1205 
1206         // the phone icon on phones
1207         if (mLastPhoneSignalIconId != mPhoneSignalIconId) {
1208             mLastPhoneSignalIconId = mPhoneSignalIconId;
1209             N = mPhoneSignalIconViews.size();
1210             for (int i=0; i<N; i++) {
1211                 final ImageView v = mPhoneSignalIconViews.get(i);
1212                 if (mPhoneSignalIconId == 0) {
1213                     v.setVisibility(View.GONE);
1214                 } else {
1215                     v.setVisibility(View.VISIBLE);
1216                     v.setImageResource(mPhoneSignalIconId);
1217                     v.setContentDescription(mContentDescriptionPhoneSignal);
1218                 }
1219             }
1220         }
1221 
1222         // the data icon on phones
1223         if (mLastDataDirectionIconId != mDataDirectionIconId) {
1224             mLastDataDirectionIconId = mDataDirectionIconId;
1225             N = mDataDirectionIconViews.size();
1226             for (int i=0; i<N; i++) {
1227                 final ImageView v = mDataDirectionIconViews.get(i);
1228                 v.setImageResource(mDataDirectionIconId);
1229                 v.setContentDescription(mContentDescriptionDataType);
1230             }
1231         }
1232 
1233         // the wifi icon on phones
1234         if (mLastWifiIconId != mWifiIconId) {
1235             mLastWifiIconId = mWifiIconId;
1236             N = mWifiIconViews.size();
1237             for (int i=0; i<N; i++) {
1238                 final ImageView v = mWifiIconViews.get(i);
1239                 if (mWifiIconId == 0) {
1240                     v.setVisibility(View.GONE);
1241                 } else {
1242                     v.setVisibility(View.VISIBLE);
1243                     v.setImageResource(mWifiIconId);
1244                     v.setContentDescription(mContentDescriptionWifi);
1245                 }
1246             }
1247         }
1248 
1249         // the wimax icon on phones
1250         if (mLastWimaxIconId != mWimaxIconId) {
1251             mLastWimaxIconId = mWimaxIconId;
1252             N = mWimaxIconViews.size();
1253             for (int i=0; i<N; i++) {
1254                 final ImageView v = mWimaxIconViews.get(i);
1255                 if (mWimaxIconId == 0) {
1256                     v.setVisibility(View.GONE);
1257                 } else {
1258                     v.setVisibility(View.VISIBLE);
1259                     v.setImageResource(mWimaxIconId);
1260                     v.setContentDescription(mContentDescriptionWimax);
1261                 }
1262            }
1263         }
1264         // the combined data signal icon
1265         if (mLastCombinedSignalIconId != combinedSignalIconId) {
1266             mLastCombinedSignalIconId = combinedSignalIconId;
1267             N = mCombinedSignalIconViews.size();
1268             for (int i=0; i<N; i++) {
1269                 final ImageView v = mCombinedSignalIconViews.get(i);
1270                 v.setImageResource(combinedSignalIconId);
1271                 v.setContentDescription(mContentDescriptionCombinedSignal);
1272             }
1273         }
1274 
1275         // the data network type overlay
1276         if (mLastDataTypeIconId != mDataTypeIconId) {
1277             mLastDataTypeIconId = mDataTypeIconId;
1278             N = mDataTypeIconViews.size();
1279             for (int i=0; i<N; i++) {
1280                 final ImageView v = mDataTypeIconViews.get(i);
1281                 if (mDataTypeIconId == 0) {
1282                     v.setVisibility(View.GONE);
1283                 } else {
1284                     v.setVisibility(View.VISIBLE);
1285                     v.setImageResource(mDataTypeIconId);
1286                     v.setContentDescription(mContentDescriptionDataType);
1287                 }
1288             }
1289         }
1290 
1291         // the data direction overlay
1292         if (mLastDataDirectionOverlayIconId != combinedActivityIconId) {
1293             if (DEBUG) {
1294                 Slog.d(TAG, "changing data overlay icon id to " + combinedActivityIconId);
1295             }
1296             mLastDataDirectionOverlayIconId = combinedActivityIconId;
1297             N = mDataDirectionOverlayIconViews.size();
1298             for (int i=0; i<N; i++) {
1299                 final ImageView v = mDataDirectionOverlayIconViews.get(i);
1300                 if (combinedActivityIconId == 0) {
1301                     v.setVisibility(View.GONE);
1302                 } else {
1303                     v.setVisibility(View.VISIBLE);
1304                     v.setImageResource(combinedActivityIconId);
1305                     v.setContentDescription(mContentDescriptionDataType);
1306                 }
1307             }
1308         }
1309 
1310         // the combinedLabel in the notification panel
1311         if (!mLastCombinedLabel.equals(combinedLabel)) {
1312             mLastCombinedLabel = combinedLabel;
1313             N = mCombinedLabelViews.size();
1314             for (int i=0; i<N; i++) {
1315                 TextView v = mCombinedLabelViews.get(i);
1316                 v.setText(combinedLabel);
1317             }
1318         }
1319 
1320         // wifi label
1321         N = mWifiLabelViews.size();
1322         for (int i=0; i<N; i++) {
1323             TextView v = mWifiLabelViews.get(i);
1324             v.setText(wifiLabel);
1325             if ("".equals(wifiLabel)) {
1326                 v.setVisibility(View.GONE);
1327             } else {
1328                 v.setVisibility(View.VISIBLE);
1329             }
1330         }
1331 
1332         // mobile label
1333         N = mMobileLabelViews.size();
1334         for (int i=0; i<N; i++) {
1335             TextView v = mMobileLabelViews.get(i);
1336             v.setText(mobileLabel);
1337             if ("".equals(mobileLabel)) {
1338                 v.setVisibility(View.GONE);
1339             } else {
1340                 v.setVisibility(View.VISIBLE);
1341             }
1342         }
1343 
1344         // e-call label
1345         N = mEmergencyLabelViews.size();
1346         for (int i=0; i<N; i++) {
1347             TextView v = mEmergencyLabelViews.get(i);
1348             if (!emergencyOnly) {
1349                 v.setVisibility(View.GONE);
1350             } else {
1351                 v.setText(mobileLabel); // comes from the telephony stack
1352                 v.setVisibility(View.VISIBLE);
1353             }
1354         }
1355     }
1356 
dump(FileDescriptor fd, PrintWriter pw, String[] args)1357     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1358         pw.println("NetworkController state:");
1359         pw.println(String.format("  %s network type %d (%s)",
1360                 mConnected?"CONNECTED":"DISCONNECTED",
1361                 mConnectedNetworkType, mConnectedNetworkTypeName));
1362         pw.println("  - telephony ------");
1363         pw.print("  hasService()=");
1364         pw.println(hasService());
1365         pw.print("  mHspaDataDistinguishable=");
1366         pw.println(mHspaDataDistinguishable);
1367         pw.print("  mDataConnected=");
1368         pw.println(mDataConnected);
1369         pw.print("  mSimState=");
1370         pw.println(mSimState);
1371         pw.print("  mPhoneState=");
1372         pw.println(mPhoneState);
1373         pw.print("  mDataState=");
1374         pw.println(mDataState);
1375         pw.print("  mDataActivity=");
1376         pw.println(mDataActivity);
1377         pw.print("  mDataNetType=");
1378         pw.print(mDataNetType);
1379         pw.print("/");
1380         pw.println(TelephonyManager.getNetworkTypeName(mDataNetType));
1381         pw.print("  mServiceState=");
1382         pw.println(mServiceState);
1383         pw.print("  mSignalStrength=");
1384         pw.println(mSignalStrength);
1385         pw.print("  mLastSignalLevel=");
1386         pw.println(mLastSignalLevel);
1387         pw.print("  mNetworkName=");
1388         pw.println(mNetworkName);
1389         pw.print("  mNetworkNameDefault=");
1390         pw.println(mNetworkNameDefault);
1391         pw.print("  mNetworkNameSeparator=");
1392         pw.println(mNetworkNameSeparator.replace("\n","\\n"));
1393         pw.print("  mPhoneSignalIconId=0x");
1394         pw.print(Integer.toHexString(mPhoneSignalIconId));
1395         pw.print("/");
1396         pw.print("  mQSPhoneSignalIconId=0x");
1397         pw.print(Integer.toHexString(mQSPhoneSignalIconId));
1398         pw.print("/");
1399         pw.println(getResourceName(mPhoneSignalIconId));
1400         pw.print("  mDataDirectionIconId=");
1401         pw.print(Integer.toHexString(mDataDirectionIconId));
1402         pw.print("/");
1403         pw.println(getResourceName(mDataDirectionIconId));
1404         pw.print("  mDataSignalIconId=");
1405         pw.print(Integer.toHexString(mDataSignalIconId));
1406         pw.print("/");
1407         pw.println(getResourceName(mDataSignalIconId));
1408         pw.print("  mDataTypeIconId=");
1409         pw.print(Integer.toHexString(mDataTypeIconId));
1410         pw.print("/");
1411         pw.println(getResourceName(mDataTypeIconId));
1412         pw.print("  mQSDataTypeIconId=");
1413         pw.print(Integer.toHexString(mQSDataTypeIconId));
1414         pw.print("/");
1415         pw.println(getResourceName(mQSDataTypeIconId));
1416 
1417         pw.println("  - wifi ------");
1418         pw.print("  mWifiEnabled=");
1419         pw.println(mWifiEnabled);
1420         pw.print("  mWifiConnected=");
1421         pw.println(mWifiConnected);
1422         pw.print("  mWifiRssi=");
1423         pw.println(mWifiRssi);
1424         pw.print("  mWifiLevel=");
1425         pw.println(mWifiLevel);
1426         pw.print("  mWifiSsid=");
1427         pw.println(mWifiSsid);
1428         pw.println(String.format("  mWifiIconId=0x%08x/%s",
1429                     mWifiIconId, getResourceName(mWifiIconId)));
1430         pw.println(String.format("  mQSWifiIconId=0x%08x/%s",
1431                     mQSWifiIconId, getResourceName(mQSWifiIconId)));
1432         pw.print("  mWifiActivity=");
1433         pw.println(mWifiActivity);
1434 
1435         if (mWimaxSupported) {
1436             pw.println("  - wimax ------");
1437             pw.print("  mIsWimaxEnabled="); pw.println(mIsWimaxEnabled);
1438             pw.print("  mWimaxConnected="); pw.println(mWimaxConnected);
1439             pw.print("  mWimaxIdle="); pw.println(mWimaxIdle);
1440             pw.println(String.format("  mWimaxIconId=0x%08x/%s",
1441                         mWimaxIconId, getResourceName(mWimaxIconId)));
1442             pw.println(String.format("  mWimaxSignal=%d", mWimaxSignal));
1443             pw.println(String.format("  mWimaxState=%d", mWimaxState));
1444             pw.println(String.format("  mWimaxExtraState=%d", mWimaxExtraState));
1445         }
1446 
1447         pw.println("  - Bluetooth ----");
1448         pw.print("  mBtReverseTethered=");
1449         pw.println(mBluetoothTethered);
1450 
1451         pw.println("  - connectivity ------");
1452         pw.print("  mInetCondition=");
1453         pw.println(mInetCondition);
1454 
1455         pw.println("  - icons ------");
1456         pw.print("  mLastPhoneSignalIconId=0x");
1457         pw.print(Integer.toHexString(mLastPhoneSignalIconId));
1458         pw.print("/");
1459         pw.println(getResourceName(mLastPhoneSignalIconId));
1460         pw.print("  mLastDataDirectionIconId=0x");
1461         pw.print(Integer.toHexString(mLastDataDirectionIconId));
1462         pw.print("/");
1463         pw.println(getResourceName(mLastDataDirectionIconId));
1464         pw.print("  mLastDataDirectionOverlayIconId=0x");
1465         pw.print(Integer.toHexString(mLastDataDirectionOverlayIconId));
1466         pw.print("/");
1467         pw.println(getResourceName(mLastDataDirectionOverlayIconId));
1468         pw.print("  mLastWifiIconId=0x");
1469         pw.print(Integer.toHexString(mLastWifiIconId));
1470         pw.print("/");
1471         pw.println(getResourceName(mLastWifiIconId));
1472         pw.print("  mLastCombinedSignalIconId=0x");
1473         pw.print(Integer.toHexString(mLastCombinedSignalIconId));
1474         pw.print("/");
1475         pw.println(getResourceName(mLastCombinedSignalIconId));
1476         pw.print("  mLastDataTypeIconId=0x");
1477         pw.print(Integer.toHexString(mLastDataTypeIconId));
1478         pw.print("/");
1479         pw.println(getResourceName(mLastDataTypeIconId));
1480         pw.print("  mLastCombinedLabel=");
1481         pw.print(mLastCombinedLabel);
1482         pw.println("");
1483     }
1484 
getResourceName(int resId)1485     private String getResourceName(int resId) {
1486         if (resId != 0) {
1487             final Resources res = mContext.getResources();
1488             try {
1489                 return res.getResourceName(resId);
1490             } catch (android.content.res.Resources.NotFoundException ex) {
1491                 return "(unknown)";
1492             }
1493         } else {
1494             return "(null)";
1495         }
1496     }
1497 
1498 }
1499