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