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