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