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