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