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