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