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