NetworkController.java revision ddbba42b812ab397a75db78aba6b48fecf0e31f6
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.util.ArrayList;
20import java.util.List;
21
22import android.content.BroadcastReceiver;
23import android.content.Context;
24import android.content.Intent;
25import android.content.IntentFilter;
26import android.net.ConnectivityManager;
27import android.net.NetworkInfo;
28import android.net.wifi.SupplicantState;
29import android.net.wifi.WifiConfiguration;
30import android.net.wifi.WifiInfo;
31import android.net.wifi.WifiManager;
32import android.os.Binder;
33import android.os.RemoteException;
34import android.provider.Settings;
35import android.telephony.PhoneStateListener;
36import android.telephony.ServiceState;
37import android.telephony.SignalStrength;
38import android.telephony.TelephonyManager;
39import android.util.Slog;
40import android.view.View;
41import android.widget.ImageView;
42import android.widget.TextView;
43
44import com.android.internal.app.IBatteryStats;
45import com.android.internal.telephony.IccCard;
46import com.android.internal.telephony.TelephonyIntents;
47import com.android.internal.telephony.cdma.EriInfo;
48import com.android.server.am.BatteryStatsService;
49
50import com.android.systemui.R;
51
52public class NetworkController extends BroadcastReceiver {
53    // debug
54    static final String TAG = "StatusBar.NetworkController";
55    static final boolean DEBUG = false;
56
57    // telephony
58    boolean mHspaDataDistinguishable;
59    final TelephonyManager mPhone;
60    boolean mDataConnected;
61    IccCard.State mSimState = IccCard.State.READY;
62    int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
63    int mDataState = TelephonyManager.DATA_DISCONNECTED;
64    int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
65    ServiceState mServiceState;
66    SignalStrength mSignalStrength;
67    int[] mDataIconList = TelephonyIcons.DATA_G[0];
68    int mPhoneSignalIconId;
69    int mDataDirectionIconId;
70    int mDataSignalIconId;
71    int mDataTypeIconId;
72
73    // wifi
74    final WifiManager mWifiManager;
75    boolean mWifiEnabled, mWifiConnected;
76    int mWifiLevel;
77    String mWifiSsid;
78    int mWifiIconId;
79
80    // data connectivity (regardless of state, can we access the internet?)
81    // state of inet connection - 0 not connected, 100 connected
82    private int mInetCondition = 0;
83    private static final int INET_CONDITION_THRESHOLD = 50;
84
85    // our ui
86    Context mContext;
87    ArrayList<ImageView> mPhoneSignalIconViews = new ArrayList<ImageView>();
88    ArrayList<ImageView> mDataDirectionIconViews = new ArrayList<ImageView>();
89    ArrayList<ImageView> mWifiIconViews = new ArrayList<ImageView>();
90    ArrayList<ImageView> mCombinedSignalIconViews = new ArrayList<ImageView>();
91    ArrayList<ImageView> mDataTypeIconViews = new ArrayList<ImageView>();
92    ArrayList<TextView> mLabelViews = new ArrayList<TextView>();
93    int mLastPhoneSignalIconId = -1;
94    int mLastDataDirectionIconId = -1;
95    int mLastWifiIconId = -1;
96    int mLastCombinedSignalIconId = -1;
97    int mLastDataTypeIconId = -1;
98    String mLastLabel = "";
99
100    // yuck -- stop doing this here and put it in the framework
101    IBatteryStats mBatteryStats;
102
103    /**
104     * Construct this controller object and register for updates.
105     */
106    public NetworkController(Context context) {
107        mContext = context;
108
109        // telephony
110        mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
111        mPhone.listen(mPhoneStateListener,
112                          PhoneStateListener.LISTEN_SERVICE_STATE
113                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
114                        | PhoneStateListener.LISTEN_CALL_STATE
115                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
116                        | PhoneStateListener.LISTEN_DATA_ACTIVITY);
117        mHspaDataDistinguishable = mContext.getResources().getBoolean(
118                R.bool.config_hspa_data_distinguishable);
119
120
121        // wifi
122        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
123
124        // broadcasts
125        IntentFilter filter = new IntentFilter();
126        filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
127        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
128        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
129        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
130        context.registerReceiver(this, filter);
131
132        // yuck
133        mBatteryStats = BatteryStatsService.getService();
134    }
135
136    public void addPhoneSignalIconView(ImageView v) {
137        mPhoneSignalIconViews.add(v);
138    }
139
140    public void addDataDirectionIconView(ImageView v) {
141        mDataDirectionIconViews.add(v);
142    }
143
144    public void addWifiIconView(ImageView v) {
145        mWifiIconViews.add(v);
146    }
147
148    public void addCombinedSignalIconView(ImageView v) {
149        mCombinedSignalIconViews.add(v);
150    }
151
152    public void addDataTypeIconView(ImageView v) {
153        mDataTypeIconViews.add(v);
154    }
155
156    public void addLabelView(TextView v) {
157        mLabelViews.add(v);
158    }
159
160    public void onReceive(Context context, Intent intent) {
161        final String action = intent.getAction();
162        if (action.equals(WifiManager.RSSI_CHANGED_ACTION)
163                || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)
164                || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
165            updateWifiState(intent);
166            refreshViews();
167        } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
168            updateSimState(intent);
169            updateDataIcon();
170            refreshViews();
171        } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
172                 action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
173            updateConnectivity(intent);
174            refreshViews();
175        }
176    }
177
178
179    // ===== Telephony ==============================================================
180
181    PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
182        @Override
183        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
184            if (DEBUG) {
185                Slog.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength);
186            }
187            mSignalStrength = signalStrength;
188            updateTelephonySignalStrength();
189            refreshViews();
190        }
191
192        @Override
193        public void onServiceStateChanged(ServiceState state) {
194            if (DEBUG) {
195                Slog.d(TAG, "onServiceStateChanged state=" + state.getState());
196            }
197            mServiceState = state;
198            updateTelephonySignalStrength();
199            updateDataIcon();
200            refreshViews();
201        }
202
203        @Override
204        public void onCallStateChanged(int state, String incomingNumber) {
205            if (DEBUG) {
206                Slog.d(TAG, "onCallStateChanged state=" + state);
207            }
208            // In cdma, if a voice call is made, RSSI should switch to 1x.
209            if (isCdma()) {
210                updateTelephonySignalStrength();
211                refreshViews();
212            }
213        }
214
215        @Override
216        public void onDataConnectionStateChanged(int state, int networkType) {
217            if (DEBUG) {
218                Slog.d(TAG, "onDataConnectionStateChanged: state=" + state
219                        + " type=" + networkType);
220            }
221            mDataState = state;
222            updateDataNetType(networkType);
223            updateDataIcon();
224            refreshViews();
225        }
226
227        @Override
228        public void onDataActivity(int direction) {
229            if (DEBUG) {
230                Slog.d(TAG, "onDataActivity: direction=" + direction);
231            }
232            mDataActivity = direction;
233            updateDataIcon();
234            refreshViews();
235        }
236    };
237
238    private final void updateSimState(Intent intent) {
239        String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
240        if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
241            mSimState = IccCard.State.ABSENT;
242        }
243        else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
244            mSimState = IccCard.State.READY;
245        }
246        else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
247            final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
248            if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
249                mSimState = IccCard.State.PIN_REQUIRED;
250            }
251            else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
252                mSimState = IccCard.State.PUK_REQUIRED;
253            }
254            else {
255                mSimState = IccCard.State.NETWORK_LOCKED;
256            }
257        } else {
258            mSimState = IccCard.State.UNKNOWN;
259        }
260    }
261
262    private boolean isCdma() {
263        return (mSignalStrength != null) && !mSignalStrength.isGsm();
264    }
265
266    private boolean isEvdo() {
267        return ((mServiceState != null)
268             && ((mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
269                 || (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_A)
270                 || (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_B)));
271    }
272
273    private boolean hasService() {
274        if (mServiceState != null) {
275            switch (mServiceState.getState()) {
276                case ServiceState.STATE_OUT_OF_SERVICE:
277                case ServiceState.STATE_POWER_OFF:
278                    return false;
279                default:
280                    return true;
281            }
282        } else {
283            return false;
284        }
285    }
286
287    private int getCdmaLevel() {
288        if (mSignalStrength == null) return 0;
289        final int cdmaDbm = mSignalStrength.getCdmaDbm();
290        final int cdmaEcio = mSignalStrength.getCdmaEcio();
291        int levelDbm = 0;
292        int levelEcio = 0;
293
294        if (cdmaDbm >= -75) levelDbm = 4;
295        else if (cdmaDbm >= -85) levelDbm = 3;
296        else if (cdmaDbm >= -95) levelDbm = 2;
297        else if (cdmaDbm >= -100) levelDbm = 1;
298        else levelDbm = 0;
299
300        // Ec/Io are in dB*10
301        if (cdmaEcio >= -90) levelEcio = 4;
302        else if (cdmaEcio >= -110) levelEcio = 3;
303        else if (cdmaEcio >= -130) levelEcio = 2;
304        else if (cdmaEcio >= -150) levelEcio = 1;
305        else levelEcio = 0;
306
307        return (levelDbm < levelEcio) ? levelDbm : levelEcio;
308    }
309
310    private int getEvdoLevel() {
311        if (mSignalStrength == null) return 0;
312        int evdoDbm = mSignalStrength.getEvdoDbm();
313        int evdoSnr = mSignalStrength.getEvdoSnr();
314        int levelEvdoDbm = 0;
315        int levelEvdoSnr = 0;
316
317        if (evdoDbm >= -65) levelEvdoDbm = 4;
318        else if (evdoDbm >= -75) levelEvdoDbm = 3;
319        else if (evdoDbm >= -90) levelEvdoDbm = 2;
320        else if (evdoDbm >= -105) levelEvdoDbm = 1;
321        else levelEvdoDbm = 0;
322
323        if (evdoSnr >= 7) levelEvdoSnr = 4;
324        else if (evdoSnr >= 5) levelEvdoSnr = 3;
325        else if (evdoSnr >= 3) levelEvdoSnr = 2;
326        else if (evdoSnr >= 1) levelEvdoSnr = 1;
327        else levelEvdoSnr = 0;
328
329        return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
330    }
331
332    private final void updateTelephonySignalStrength() {
333        // Display signal strength while in "emergency calls only" mode
334        if (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly())) {
335            //Slog.d(TAG, "updateTelephonySignalStrength: no service");
336            if (Settings.System.getInt(mContext.getContentResolver(),
337                    Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
338                mPhoneSignalIconId = R.drawable.stat_sys_signal_flightmode;
339                mDataSignalIconId = R.drawable.stat_sys_signal_flightmode;
340            } else {
341                mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
342                mDataSignalIconId = R.drawable.stat_sys_signal_0; // note we use 0 instead of null
343            }
344        } else {
345            if (mSignalStrength == null) {
346                mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
347                mDataSignalIconId = R.drawable.stat_sys_signal_0; // note we use 0 instead of null
348            } else if (isCdma()) {
349                // If 3G(EV) and 1x network are available than 3G should be
350                // displayed, displayed RSSI should be from the EV side.
351                // If a voice call is made then RSSI should switch to 1x.
352                int iconLevel;
353                if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){
354                    iconLevel = getEvdoLevel();
355                } else {
356                    iconLevel = getCdmaLevel();
357                }
358                int[] iconList;
359                if (isCdmaEri()) {
360                    iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition];
361                } else {
362                    iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition];
363                }
364                mPhoneSignalIconId = iconList[iconLevel];
365                mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel];
366            } else {
367                int asu = mSignalStrength.getGsmSignalStrength();
368
369                // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
370                // asu = 0 (-113dB or less) is very weak
371                // signal, its better to show 0 bars to the user in such cases.
372                // asu = 99 is a special case, where the signal strength is unknown.
373                int iconLevel;
374                if (asu <= 2 || asu == 99) iconLevel = 0;
375                else if (asu >= 12) iconLevel = 4;
376                else if (asu >= 8)  iconLevel = 3;
377                else if (asu >= 5)  iconLevel = 2;
378                else iconLevel = 1;
379
380                // Though mPhone is a Manager, this call is not an IPC
381                int[] iconList;
382                if (mPhone.isNetworkRoaming()) {
383                    iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition];
384                } else {
385                    iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition];
386                }
387                mPhoneSignalIconId = iconList[iconLevel];
388                mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel];
389            }
390        }
391    }
392
393    private final void updateDataNetType(int net) {
394        switch (net) {
395            case TelephonyManager.NETWORK_TYPE_EDGE:
396                mDataIconList = TelephonyIcons.DATA_E[mInetCondition];
397                mDataTypeIconId = R.drawable.stat_sys_signal_edge;
398                break;
399            case TelephonyManager.NETWORK_TYPE_UMTS:
400                mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
401                mDataTypeIconId = R.drawable.stat_sys_signal_3g;
402                break;
403            case TelephonyManager.NETWORK_TYPE_HSDPA:
404            case TelephonyManager.NETWORK_TYPE_HSUPA:
405            case TelephonyManager.NETWORK_TYPE_HSPA:
406                if (mHspaDataDistinguishable) {
407                    mDataIconList = TelephonyIcons.DATA_H[mInetCondition];
408                    mDataTypeIconId = R.drawable.stat_sys_signal_hsdpa;
409                } else {
410                    mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
411                    mDataTypeIconId = R.drawable.stat_sys_signal_3g;
412                }
413                break;
414            case TelephonyManager.NETWORK_TYPE_CDMA:
415                // display 1xRTT for IS95A/B
416                mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
417                mDataTypeIconId = R.drawable.stat_sys_signal_1x;
418                break;
419            case TelephonyManager.NETWORK_TYPE_1xRTT:
420                mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
421                mDataTypeIconId = R.drawable.stat_sys_signal_1x;
422                break;
423            case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
424            case TelephonyManager.NETWORK_TYPE_EVDO_A:
425            case TelephonyManager.NETWORK_TYPE_EVDO_B:
426                mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
427                mDataTypeIconId = R.drawable.stat_sys_signal_3g;
428                break;
429            // TODO - add support for NETWORK_TYPE_LTE and NETWORK_TYPE_EHRPD
430            default:
431                mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
432                mDataTypeIconId = R.drawable.stat_sys_signal_gprs;
433            break;
434        }
435        if ((isCdma() && isCdmaEri()) || mPhone.isNetworkRoaming()) {
436            mDataTypeIconId = R.drawable.stat_sys_signal_roam;
437        }
438    }
439
440    boolean isCdmaEri() {
441        final int iconIndex = mServiceState.getCdmaEriIconIndex();
442        if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) {
443            final int iconMode = mServiceState.getCdmaEriIconMode();
444            if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
445                    || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) {
446                return true;
447            }
448        }
449        return false;
450    }
451
452    private final void updateDataIcon() {
453        int iconId;
454        boolean visible = true;
455
456        if (!isCdma()) {
457            // GSM case, we have to check also the sim state
458            if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
459                if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
460                    switch (mDataActivity) {
461                        case TelephonyManager.DATA_ACTIVITY_IN:
462                            iconId = mDataIconList[1];
463                            break;
464                        case TelephonyManager.DATA_ACTIVITY_OUT:
465                            iconId = mDataIconList[2];
466                            break;
467                        case TelephonyManager.DATA_ACTIVITY_INOUT:
468                            iconId = mDataIconList[3];
469                            break;
470                        default:
471                            iconId = mDataIconList[0];
472                            break;
473                    }
474                    mDataDirectionIconId = iconId;
475                } else {
476                    iconId = 0;
477                    visible = false;
478                }
479            } else {
480                iconId = R.drawable.stat_sys_no_sim;
481            }
482        } else {
483            // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
484            if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
485                switch (mDataActivity) {
486                    case TelephonyManager.DATA_ACTIVITY_IN:
487                        iconId = mDataIconList[1];
488                        break;
489                    case TelephonyManager.DATA_ACTIVITY_OUT:
490                        iconId = mDataIconList[2];
491                        break;
492                    case TelephonyManager.DATA_ACTIVITY_INOUT:
493                        iconId = mDataIconList[3];
494                        break;
495                    case TelephonyManager.DATA_ACTIVITY_DORMANT:
496                    default:
497                        iconId = mDataIconList[0];
498                        break;
499                }
500            } else {
501                iconId = 0;
502                visible = false;
503            }
504        }
505
506        // yuck - this should NOT be done by the status bar
507        long ident = Binder.clearCallingIdentity();
508        try {
509            mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
510        } catch (RemoteException e) {
511        } finally {
512            Binder.restoreCallingIdentity(ident);
513        }
514
515        mDataDirectionIconId = iconId;
516        mDataConnected = visible;
517    }
518
519    // ===== Wifi ===================================================================
520
521    private void updateWifiState(Intent intent) {
522        final String action = intent.getAction();
523        if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
524            mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
525                    WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
526
527        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
528            final NetworkInfo networkInfo = (NetworkInfo)
529                    intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
530            boolean wasConnected = mWifiConnected;
531            mWifiConnected = networkInfo != null && networkInfo.isConnected();
532            // If we just connected, grab the inintial signal strength and ssid
533            if (mWifiConnected && !wasConnected) {
534                WifiInfo info = mWifiManager.getConnectionInfo();
535                if (info != null) {
536                    mWifiLevel = WifiManager.calculateSignalLevel(info.getRssi(),
537                            WifiIcons.WIFI_LEVEL_COUNT);
538                    mWifiSsid = huntForSsid(info);
539                } else {
540                    mWifiLevel = 0;
541                    mWifiSsid = null;
542                }
543            } else if (!mWifiConnected) {
544                mWifiLevel = 0;
545                mWifiSsid = null;
546            }
547
548        } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
549            if (mWifiConnected) {
550                final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
551                mWifiLevel = WifiManager.calculateSignalLevel(newRssi, WifiIcons.WIFI_LEVEL_COUNT);
552            }
553        }
554
555        updateWifiIcons();
556    }
557
558    private void updateWifiIcons() {
559        if (mWifiConnected) {
560            mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
561        } else {
562            mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[0][0];
563        }
564    }
565
566    private String huntForSsid(WifiInfo info) {
567        String ssid = info.getSSID();
568        if (ssid != null) {
569            return ssid;
570        }
571        // OK, it's not in the connectionInfo; we have to go hunting for it
572        List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
573        for (WifiConfiguration net : networks) {
574            if (net.networkId == info.getNetworkId()) {
575                return net.SSID;
576            }
577        }
578        return null;
579    }
580
581
582    // ===== Full or limited Internet connectivity ==================================
583
584    private void updateConnectivity(Intent intent) {
585        NetworkInfo info = (NetworkInfo)(intent.getParcelableExtra(
586                ConnectivityManager.EXTRA_NETWORK_INFO));
587        int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
588
589        int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
590
591        switch (info.getType()) {
592            case ConnectivityManager.TYPE_MOBILE:
593                mInetCondition = inetCondition;
594                updateDataNetType(info.getSubtype());
595                updateDataIcon();
596                updateTelephonySignalStrength(); // apply any change in connectionStatus
597                break;
598            case ConnectivityManager.TYPE_WIFI:
599                mInetCondition = inetCondition;
600                updateWifiIcons();
601                break;
602        }
603    }
604
605
606    // ===== Update the views =======================================================
607
608    // figure out what to show: first wifi, then 3G, then nothing
609    void refreshViews() {
610        Context context = mContext;
611
612        int combinedSignalIconId;
613        int dataTypeIconId;
614        String label;
615        int N;
616
617        if (mWifiConnected) {
618            if (mWifiSsid == null) {
619                label = context.getString(R.string.system_panel_signal_meter_wifi_nossid);
620            } else {
621                label = context.getString(R.string.system_panel_signal_meter_wifi_ssid_format,
622                                      mWifiSsid);
623            }
624            combinedSignalIconId = mWifiIconId;
625            dataTypeIconId = 0;
626        } else {
627            if (mDataConnected) {
628                label = context.getString(R.string.system_panel_signal_meter_data_connected);
629            } else {
630                label = context.getString(R.string.system_panel_signal_meter_disconnected);
631            }
632            combinedSignalIconId = mDataSignalIconId;
633            dataTypeIconId = mDataTypeIconId;
634        }
635
636        if (false) {
637            Slog.d(TAG, "refreshViews combinedSignalIconId=0x"
638                    + Integer.toHexString(mPhoneSignalIconId)
639                    + " mPhoneSignalIconId=0x" + Integer.toHexString(mPhoneSignalIconId)
640                    + " mDataDirectionIconId=0x" + Integer.toHexString(mDataDirectionIconId)
641                    + " mDataSignalIconId=0x" + Integer.toHexString(mDataSignalIconId)
642                    + " mDataTypeIconId=0x" + Integer.toHexString(mDataTypeIconId)
643                    + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId));
644        }
645
646        // the phone icon on phones
647        if (mLastPhoneSignalIconId != mPhoneSignalIconId) {
648            mLastPhoneSignalIconId = mPhoneSignalIconId;
649            N = mPhoneSignalIconViews.size();
650            for (int i=0; i<N; i++) {
651                final ImageView v = mPhoneSignalIconViews.get(i);
652                v.setImageResource(mPhoneSignalIconId);
653            }
654        }
655
656        // the data icon on phones
657        if (mLastDataDirectionIconId != mDataDirectionIconId) {
658            mLastDataDirectionIconId = mDataDirectionIconId;
659            N = mDataDirectionIconViews.size();
660            for (int i=0; i<N; i++) {
661                final ImageView v = mDataDirectionIconViews.get(i);
662                v.setImageResource(mDataDirectionIconId);
663            }
664        }
665
666        // the wifi icon on phones
667        if (mLastWifiIconId != mWifiIconId) {
668            mLastWifiIconId = mWifiIconId;
669            N = mWifiIconViews.size();
670            for (int i=0; i<N; i++) {
671                final ImageView v = mWifiIconViews.get(i);
672                v.setImageResource(mWifiIconId);
673            }
674        }
675
676        // the combined data signal icon
677        if (mLastCombinedSignalIconId != combinedSignalIconId) {
678            mLastCombinedSignalIconId = combinedSignalIconId;
679            N = mCombinedSignalIconViews.size();
680            for (int i=0; i<N; i++) {
681                final ImageView v = mCombinedSignalIconViews.get(i);
682                v.setImageResource(combinedSignalIconId);
683            }
684        }
685
686        // the data network type overlay
687        if (mLastDataTypeIconId != dataTypeIconId) {
688            mLastDataTypeIconId = dataTypeIconId;
689            N = mDataTypeIconViews.size();
690            for (int i=0; i<N; i++) {
691                final ImageView v = mDataTypeIconViews.get(i);
692                if (dataTypeIconId == 0) {
693                    v.setVisibility(View.INVISIBLE);
694                } else {
695                    v.setVisibility(View.VISIBLE);
696                    v.setImageResource(dataTypeIconId);
697                }
698            }
699        }
700
701        // the label in the notification panel
702        if (!mLastLabel.equals(label)) {
703            mLastLabel = label;
704            N = mLabelViews.size();
705            for (int i=0; i<N; i++) {
706                TextView v = mLabelViews.get(i);
707                v.setText(label);
708            }
709        }
710    }
711}
712