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