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