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.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 {
    173         void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon,
    174                 String contentDescription);
    175         void setMobileDataIndicators(boolean visible, int strengthIcon, int activityIcon,
    176                 int typeIcon, String contentDescription, String typeContentDescription);
    177         void setIsAirplaneMode(boolean is, int airplaneIcon);
    178     }
    179 
    180     public interface NetworkSignalChangedCallback {
    181         void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
    182                 String wifitSignalContentDescriptionId, String description);
    183         void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId,
    184                 String mobileSignalContentDescriptionId, int dataTypeIconId,
    185                 String dataTypeContentDescriptionId, String description);
    186         void onAirplaneModeChanged(boolean enabled);
    187     }
    188 
    189     /**
    190      * Construct this controller object and register for updates.
    191      */
    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 
    262     public boolean hasMobileDataFeature() {
    263         return mHasMobileDataFeature;
    264     }
    265 
    266     public boolean hasVoiceCallingFeature() {
    267         return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
    268     }
    269 
    270     public boolean isEmergencyOnly() {
    271         return (mServiceState != null && mServiceState.isEmergencyOnly());
    272     }
    273 
    274     public void addPhoneSignalIconView(ImageView v) {
    275         mPhoneSignalIconViews.add(v);
    276     }
    277 
    278     public void addDataDirectionIconView(ImageView v) {
    279         mDataDirectionIconViews.add(v);
    280     }
    281 
    282     public void addDataDirectionOverlayIconView(ImageView v) {
    283         mDataDirectionOverlayIconViews.add(v);
    284     }
    285 
    286     public void addWifiIconView(ImageView v) {
    287         mWifiIconViews.add(v);
    288     }
    289     public void addWimaxIconView(ImageView v) {
    290         mWimaxIconViews.add(v);
    291     }
    292 
    293     public void addCombinedSignalIconView(ImageView v) {
    294         mCombinedSignalIconViews.add(v);
    295     }
    296 
    297     public void addDataTypeIconView(ImageView v) {
    298         mDataTypeIconViews.add(v);
    299     }
    300 
    301     public void addCombinedLabelView(TextView v) {
    302         mCombinedLabelViews.add(v);
    303     }
    304 
    305     public void addMobileLabelView(TextView v) {
    306         mMobileLabelViews.add(v);
    307     }
    308 
    309     public void addWifiLabelView(TextView v) {
    310         mWifiLabelViews.add(v);
    311     }
    312 
    313     public void addEmergencyLabelView(TextView v) {
    314         mEmergencyLabelViews.add(v);
    315     }
    316 
    317     public void addSignalCluster(SignalCluster cluster) {
    318         mSignalClusters.add(cluster);
    319         refreshSignalCluster(cluster);
    320     }
    321 
    322     public void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) {
    323         mSignalsChangedCallbacks.add(cb);
    324         notifySignalsChangedCallbacks(cb);
    325     }
    326 
    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 
    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 
    384     public void setStackedMode(boolean stacked) {
    385         mDataAndWifiStacked = true;
    386     }
    387 
    388     @Override
    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 
    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 
    513     private boolean isCdma() {
    514         return (mSignalStrength != null) && !mSignalStrength.isGsm();
    515     }
    516 
    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 
    531     private void updateAirplaneMode() {
    532         mAirplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
    533             Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
    534     }
    535 
    536     private void refreshLocale() {
    537         mLocale = mContext.getResources().getConfiguration().locale;
    538     }
    539 
    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 
    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                     boolean show4GforLTE = mContext.getResources().getBoolean(R.bool.config_show4GForLTE);
    682                     if (show4GforLTE) {
    683                         mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
    684                         mDataTypeIconId = R.drawable.stat_sys_data_connected_4g;
    685                         mQSDataTypeIconId = R.drawable.ic_qs_signal_4g;
    686                         mContentDescriptionDataType = mContext.getString(
    687                                 R.string.accessibility_data_connection_4g);
    688                     } else {
    689                         mDataIconList = TelephonyIcons.DATA_LTE[mInetCondition];
    690                         mDataTypeIconId = R.drawable.stat_sys_data_connected_lte;
    691                         mQSDataTypeIconId = R.drawable.ic_qs_signal_lte;
    692                         mContentDescriptionDataType = mContext.getString(
    693                                 R.string.accessibility_data_connection_lte);
    694                     }
    695                     break;
    696                 default:
    697                     if (!mShowAtLeastThreeGees) {
    698                         mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
    699                         mDataTypeIconId = R.drawable.stat_sys_data_connected_g;
    700                         mQSDataTypeIconId = R.drawable.ic_qs_signal_g;
    701                         mContentDescriptionDataType = mContext.getString(
    702                                 R.string.accessibility_data_connection_gprs);
    703                     } else {
    704                         mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
    705                         mDataTypeIconId = R.drawable.stat_sys_data_connected_3g;
    706                         mQSDataTypeIconId = R.drawable.ic_qs_signal_3g;
    707                         mContentDescriptionDataType = mContext.getString(
    708                                 R.string.accessibility_data_connection_3g);
    709                     }
    710                     break;
    711             }
    712         }
    713 
    714         if (isCdma()) {
    715             if (isCdmaEri()) {
    716                 mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
    717                 mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
    718             }
    719         } else if (mPhone.isNetworkRoaming()) {
    720                 mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
    721                 mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
    722         }
    723     }
    724 
    725     boolean isCdmaEri() {
    726         if (mServiceState != null) {
    727             final int iconIndex = mServiceState.getCdmaEriIconIndex();
    728             if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) {
    729                 final int iconMode = mServiceState.getCdmaEriIconMode();
    730                 if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
    731                         || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) {
    732                     return true;
    733                 }
    734             }
    735         }
    736         return false;
    737     }
    738 
    739     private final void updateDataIcon() {
    740         int iconId;
    741         boolean visible = true;
    742 
    743         if (!isCdma()) {
    744             // GSM case, we have to check also the sim state
    745             if (mSimState == IccCardConstants.State.READY ||
    746                     mSimState == IccCardConstants.State.UNKNOWN) {
    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                         default:
    759                             iconId = mDataIconList[0];
    760                             break;
    761                     }
    762                     mDataDirectionIconId = iconId;
    763                 } else {
    764                     iconId = 0;
    765                     visible = false;
    766                 }
    767             } else {
    768                 iconId = R.drawable.stat_sys_no_sim;
    769                 visible = false; // no SIM? no data
    770             }
    771         } else {
    772             // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
    773             if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
    774                 switch (mDataActivity) {
    775                     case TelephonyManager.DATA_ACTIVITY_IN:
    776                         iconId = mDataIconList[1];
    777                         break;
    778                     case TelephonyManager.DATA_ACTIVITY_OUT:
    779                         iconId = mDataIconList[2];
    780                         break;
    781                     case TelephonyManager.DATA_ACTIVITY_INOUT:
    782                         iconId = mDataIconList[3];
    783                         break;
    784                     case TelephonyManager.DATA_ACTIVITY_DORMANT:
    785                     default:
    786                         iconId = mDataIconList[0];
    787                         break;
    788                 }
    789             } else {
    790                 iconId = 0;
    791                 visible = false;
    792             }
    793         }
    794 
    795         // yuck - this should NOT be done by the status bar
    796         long ident = Binder.clearCallingIdentity();
    797         try {
    798             mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
    799         } catch (RemoteException e) {
    800         } finally {
    801             Binder.restoreCallingIdentity(ident);
    802         }
    803 
    804         mDataDirectionIconId = iconId;
    805         mDataConnected = visible;
    806     }
    807 
    808     void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) {
    809         if (false) {
    810             Slog.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
    811                     + " showPlmn=" + showPlmn + " plmn=" + plmn);
    812         }
    813         StringBuilder str = new StringBuilder();
    814         boolean something = false;
    815         if (showPlmn && plmn != null) {
    816             str.append(plmn);
    817             something = true;
    818         }
    819         if (showSpn && spn != null) {
    820             if (something) {
    821                 str.append(mNetworkNameSeparator);
    822             }
    823             str.append(spn);
    824             something = true;
    825         }
    826         if (something) {
    827             mNetworkName = str.toString();
    828         } else {
    829             mNetworkName = mNetworkNameDefault;
    830         }
    831     }
    832 
    833     // ===== Wifi ===================================================================
    834 
    835     class WifiHandler extends Handler {
    836         @Override
    837         public void handleMessage(Message msg) {
    838             switch (msg.what) {
    839                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
    840                     if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
    841                         mWifiChannel.sendMessage(Message.obtain(this,
    842                                 AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
    843                     } else {
    844                         Slog.e(TAG, "Failed to connect to wifi");
    845                     }
    846                     break;
    847                 case WifiManager.DATA_ACTIVITY_NOTIFICATION:
    848                     if (msg.arg1 != mWifiActivity) {
    849                         mWifiActivity = msg.arg1;
    850                         refreshViews();
    851                     }
    852                     break;
    853                 default:
    854                     //Ignore
    855                     break;
    856             }
    857         }
    858     }
    859 
    860     private void updateWifiState(Intent intent) {
    861         final String action = intent.getAction();
    862         if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
    863             mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
    864                     WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
    865 
    866         } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
    867             final NetworkInfo networkInfo = (NetworkInfo)
    868                     intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    869             boolean wasConnected = mWifiConnected;
    870             mWifiConnected = networkInfo != null && networkInfo.isConnected();
    871             // If we just connected, grab the inintial signal strength and ssid
    872             if (mWifiConnected && !wasConnected) {
    873                 // try getting it out of the intent first
    874                 WifiInfo info = (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
    875                 if (info == null) {
    876                     info = mWifiManager.getConnectionInfo();
    877                 }
    878                 if (info != null) {
    879                     mWifiSsid = huntForSsid(info);
    880                 } else {
    881                     mWifiSsid = null;
    882                 }
    883             } else if (!mWifiConnected) {
    884                 mWifiSsid = null;
    885             }
    886         } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
    887             mWifiRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
    888             mWifiLevel = WifiManager.calculateSignalLevel(
    889                     mWifiRssi, WifiIcons.WIFI_LEVEL_COUNT);
    890         }
    891 
    892         updateWifiIcons();
    893     }
    894 
    895     private void updateWifiIcons() {
    896         if (mWifiConnected) {
    897             mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
    898             mQSWifiIconId = WifiIcons.QS_WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
    899             mContentDescriptionWifi = mContext.getString(
    900                     AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]);
    901         } else {
    902             if (mDataAndWifiStacked) {
    903                 mWifiIconId = 0;
    904                 mQSWifiIconId = 0;
    905             } else {
    906                 mWifiIconId = mWifiEnabled ? R.drawable.stat_sys_wifi_signal_null : 0;
    907                 mQSWifiIconId = mWifiEnabled ? R.drawable.ic_qs_wifi_no_network : 0;
    908             }
    909             mContentDescriptionWifi = mContext.getString(R.string.accessibility_no_wifi);
    910         }
    911     }
    912 
    913     private String huntForSsid(WifiInfo info) {
    914         String ssid = info.getSSID();
    915         if (ssid != null) {
    916             return ssid;
    917         }
    918         // OK, it's not in the connectionInfo; we have to go hunting for it
    919         List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
    920         for (WifiConfiguration net : networks) {
    921             if (net.networkId == info.getNetworkId()) {
    922                 return net.SSID;
    923             }
    924         }
    925         return null;
    926     }
    927 
    928 
    929     // ===== Wimax ===================================================================
    930     private final void updateWimaxState(Intent intent) {
    931         final String action = intent.getAction();
    932         boolean wasConnected = mWimaxConnected;
    933         if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION)) {
    934             int wimaxStatus = intent.getIntExtra(WimaxManagerConstants.EXTRA_4G_STATE,
    935                     WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
    936             mIsWimaxEnabled = (wimaxStatus ==
    937                     WimaxManagerConstants.NET_4G_STATE_ENABLED);
    938         } else if (action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION)) {
    939             mWimaxSignal = intent.getIntExtra(WimaxManagerConstants.EXTRA_NEW_SIGNAL_LEVEL, 0);
    940         } else if (action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) {
    941             mWimaxState = intent.getIntExtra(WimaxManagerConstants.EXTRA_WIMAX_STATE,
    942                     WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
    943             mWimaxExtraState = intent.getIntExtra(
    944                     WimaxManagerConstants.EXTRA_WIMAX_STATE_DETAIL,
    945                     WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
    946             mWimaxConnected = (mWimaxState ==
    947                     WimaxManagerConstants.WIMAX_STATE_CONNECTED);
    948             mWimaxIdle = (mWimaxExtraState == WimaxManagerConstants.WIMAX_IDLE);
    949         }
    950         updateDataNetType();
    951         updateWimaxIcons();
    952     }
    953 
    954     private void updateWimaxIcons() {
    955         if (mIsWimaxEnabled) {
    956             if (mWimaxConnected) {
    957                 if (mWimaxIdle)
    958                     mWimaxIconId = WimaxIcons.WIMAX_IDLE;
    959                 else
    960                     mWimaxIconId = WimaxIcons.WIMAX_SIGNAL_STRENGTH[mInetCondition][mWimaxSignal];
    961                 mContentDescriptionWimax = mContext.getString(
    962                         AccessibilityContentDescriptions.WIMAX_CONNECTION_STRENGTH[mWimaxSignal]);
    963             } else {
    964                 mWimaxIconId = WimaxIcons.WIMAX_DISCONNECTED;
    965                 mContentDescriptionWimax = mContext.getString(R.string.accessibility_no_wimax);
    966             }
    967         } else {
    968             mWimaxIconId = 0;
    969         }
    970     }
    971 
    972     // ===== Full or limited Internet connectivity ==================================
    973 
    974     private void updateConnectivity(Intent intent) {
    975         if (CHATTY) {
    976             Slog.d(TAG, "updateConnectivity: intent=" + intent);
    977         }
    978 
    979         final ConnectivityManager connManager = (ConnectivityManager) mContext
    980                 .getSystemService(Context.CONNECTIVITY_SERVICE);
    981         final NetworkInfo info = connManager.getActiveNetworkInfo();
    982 
    983         // Are we connected at all, by any interface?
    984         mConnected = info != null && info.isConnected();
    985         if (mConnected) {
    986             mConnectedNetworkType = info.getType();
    987             mConnectedNetworkTypeName = info.getTypeName();
    988         } else {
    989             mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
    990             mConnectedNetworkTypeName = null;
    991         }
    992 
    993         int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
    994 
    995         if (CHATTY) {
    996             Slog.d(TAG, "updateConnectivity: networkInfo=" + info);
    997             Slog.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus);
    998         }
    999 
   1000         mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
   1001 
   1002         if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) {
   1003             mBluetoothTethered = info.isConnected();
   1004         } else {
   1005             mBluetoothTethered = false;
   1006         }
   1007 
   1008         // We want to update all the icons, all at once, for any condition change
   1009         updateDataNetType();
   1010         updateWimaxIcons();
   1011         updateDataIcon();
   1012         updateTelephonySignalStrength();
   1013         updateWifiIcons();
   1014     }
   1015 
   1016 
   1017     // ===== Update the views =======================================================
   1018 
   1019     void refreshViews() {
   1020         Context context = mContext;
   1021 
   1022         int combinedSignalIconId = 0;
   1023         int combinedActivityIconId = 0;
   1024         String combinedLabel = "";
   1025         String wifiLabel = "";
   1026         String mobileLabel = "";
   1027         int N;
   1028         final boolean emergencyOnly = isEmergencyOnly();
   1029 
   1030         if (!mHasMobileDataFeature) {
   1031             mDataSignalIconId = mPhoneSignalIconId = 0;
   1032             mQSPhoneSignalIconId = 0;
   1033             mobileLabel = "";
   1034         } else {
   1035             // We want to show the carrier name if in service and either:
   1036             //   - We are connected to mobile data, or
   1037             //   - We are not connected to mobile data, as long as the *reason* packets are not
   1038             //     being routed over that link is that we have better connectivity via wifi.
   1039             // If data is disconnected for some other reason but wifi (or ethernet/bluetooth)
   1040             // is connected, we show nothing.
   1041             // Otherwise (nothing connected) we show "No internet connection".
   1042 
   1043             if (mDataConnected) {
   1044                 mobileLabel = mNetworkName;
   1045             } else if (mConnected || emergencyOnly) {
   1046                 if (hasService() || emergencyOnly) {
   1047                     // The isEmergencyOnly test covers the case of a phone with no SIM
   1048                     mobileLabel = mNetworkName;
   1049                 } else {
   1050                     // Tablets, basically
   1051                     mobileLabel = "";
   1052                 }
   1053             } else {
   1054                 mobileLabel
   1055                     = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
   1056             }
   1057 
   1058             // Now for things that should only be shown when actually using mobile data.
   1059             if (mDataConnected) {
   1060                 combinedSignalIconId = mDataSignalIconId;
   1061                 switch (mDataActivity) {
   1062                     case TelephonyManager.DATA_ACTIVITY_IN:
   1063                         mMobileActivityIconId = R.drawable.stat_sys_signal_in;
   1064                         break;
   1065                     case TelephonyManager.DATA_ACTIVITY_OUT:
   1066                         mMobileActivityIconId = R.drawable.stat_sys_signal_out;
   1067                         break;
   1068                     case TelephonyManager.DATA_ACTIVITY_INOUT:
   1069                         mMobileActivityIconId = R.drawable.stat_sys_signal_inout;
   1070                         break;
   1071                     default:
   1072                         mMobileActivityIconId = 0;
   1073                         break;
   1074                 }
   1075 
   1076                 combinedLabel = mobileLabel;
   1077                 combinedActivityIconId = mMobileActivityIconId;
   1078                 combinedSignalIconId = mDataSignalIconId; // set by updateDataIcon()
   1079                 mContentDescriptionCombinedSignal = mContentDescriptionDataType;
   1080             } else {
   1081                 mMobileActivityIconId = 0;
   1082             }
   1083         }
   1084 
   1085         if (mWifiConnected) {
   1086             if (mWifiSsid == null) {
   1087                 wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid);
   1088                 mWifiActivityIconId = 0; // no wifis, no bits
   1089             } else {
   1090                 wifiLabel = mWifiSsid;
   1091                 if (DEBUG) {
   1092                     wifiLabel += "xxxxXXXXxxxxXXXX";
   1093                 }
   1094                 switch (mWifiActivity) {
   1095                     case WifiManager.DATA_ACTIVITY_IN:
   1096                         mWifiActivityIconId = R.drawable.stat_sys_wifi_in;
   1097                         break;
   1098                     case WifiManager.DATA_ACTIVITY_OUT:
   1099                         mWifiActivityIconId = R.drawable.stat_sys_wifi_out;
   1100                         break;
   1101                     case WifiManager.DATA_ACTIVITY_INOUT:
   1102                         mWifiActivityIconId = R.drawable.stat_sys_wifi_inout;
   1103                         break;
   1104                     case WifiManager.DATA_ACTIVITY_NONE:
   1105                         mWifiActivityIconId = 0;
   1106                         break;
   1107                 }
   1108             }
   1109 
   1110             combinedActivityIconId = mWifiActivityIconId;
   1111             combinedLabel = wifiLabel;
   1112             combinedSignalIconId = mWifiIconId; // set by updateWifiIcons()
   1113             mContentDescriptionCombinedSignal = mContentDescriptionWifi;
   1114         } else {
   1115             if (mHasMobileDataFeature) {
   1116                 wifiLabel = "";
   1117             } else {
   1118                 wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
   1119             }
   1120         }
   1121 
   1122         if (mBluetoothTethered) {
   1123             combinedLabel = mContext.getString(R.string.bluetooth_tethered);
   1124             combinedSignalIconId = mBluetoothTetherIconId;
   1125             mContentDescriptionCombinedSignal = mContext.getString(
   1126                     R.string.accessibility_bluetooth_tether);
   1127         }
   1128 
   1129         final boolean ethernetConnected = (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET);
   1130         if (ethernetConnected) {
   1131             combinedLabel = context.getString(R.string.ethernet_label);
   1132         }
   1133 
   1134         if (mAirplaneMode &&
   1135                 (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) {
   1136             // Only display the flight-mode icon if not in "emergency calls only" mode.
   1137 
   1138             // look again; your radios are now airplanes
   1139             mContentDescriptionPhoneSignal = mContext.getString(
   1140                     R.string.accessibility_airplane_mode);
   1141             mAirplaneIconId = R.drawable.stat_sys_signal_flightmode;
   1142             mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = mQSDataTypeIconId = 0;
   1143             mQSPhoneSignalIconId = 0;
   1144 
   1145             // combined values from connected wifi take precedence over airplane mode
   1146             if (mWifiConnected) {
   1147                 // Suppress "No internet connection." from mobile if wifi connected.
   1148                 mobileLabel = "";
   1149             } else {
   1150                 if (mHasMobileDataFeature) {
   1151                     // let the mobile icon show "No internet connection."
   1152                     wifiLabel = "";
   1153                 } else {
   1154                     wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
   1155                     combinedLabel = wifiLabel;
   1156                 }
   1157                 mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal;
   1158                 combinedSignalIconId = mDataSignalIconId;
   1159             }
   1160         }
   1161         else if (!mDataConnected && !mWifiConnected && !mBluetoothTethered && !mWimaxConnected && !ethernetConnected) {
   1162             // pretty much totally disconnected
   1163 
   1164             combinedLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
   1165             // On devices without mobile radios, we want to show the wifi icon
   1166             combinedSignalIconId =
   1167                 mHasMobileDataFeature ? mDataSignalIconId : mWifiIconId;
   1168             mContentDescriptionCombinedSignal = mHasMobileDataFeature
   1169                 ? mContentDescriptionDataType : mContentDescriptionWifi;
   1170 
   1171             mDataTypeIconId = 0;
   1172             mQSDataTypeIconId = 0;
   1173             if (isCdma()) {
   1174                 if (isCdmaEri()) {
   1175                     mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
   1176                     mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
   1177                 }
   1178             } else if (mPhone.isNetworkRoaming()) {
   1179                 mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
   1180                 mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
   1181             }
   1182         }
   1183 
   1184         if (DEBUG) {
   1185             Slog.d(TAG, "refreshViews connected={"
   1186                     + (mWifiConnected?" wifi":"")
   1187                     + (mDataConnected?" data":"")
   1188                     + " } level="
   1189                     + ((mSignalStrength == null)?"??":Integer.toString(mSignalStrength.getLevel()))
   1190                     + " combinedSignalIconId=0x"
   1191                     + Integer.toHexString(combinedSignalIconId)
   1192                     + "/" + getResourceName(combinedSignalIconId)
   1193                     + " combinedActivityIconId=0x" + Integer.toHexString(combinedActivityIconId)
   1194                     + " mobileLabel=" + mobileLabel
   1195                     + " wifiLabel=" + wifiLabel
   1196                     + " emergencyOnly=" + emergencyOnly
   1197                     + " combinedLabel=" + combinedLabel
   1198                     + " mAirplaneMode=" + mAirplaneMode
   1199                     + " mDataActivity=" + mDataActivity
   1200                     + " mPhoneSignalIconId=0x" + Integer.toHexString(mPhoneSignalIconId)
   1201                     + " mQSPhoneSignalIconId=0x" + Integer.toHexString(mQSPhoneSignalIconId)
   1202                     + " mDataDirectionIconId=0x" + Integer.toHexString(mDataDirectionIconId)
   1203                     + " mDataSignalIconId=0x" + Integer.toHexString(mDataSignalIconId)
   1204                     + " mDataTypeIconId=0x" + Integer.toHexString(mDataTypeIconId)
   1205                     + " mQSDataTypeIconId=0x" + Integer.toHexString(mQSDataTypeIconId)
   1206                     + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId)
   1207                     + " mQSWifiIconId=0x" + Integer.toHexString(mQSWifiIconId)
   1208                     + " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId));
   1209         }
   1210 
   1211         if (mLastPhoneSignalIconId          != mPhoneSignalIconId
   1212          || mLastDataDirectionOverlayIconId != combinedActivityIconId
   1213          || mLastWifiIconId                 != mWifiIconId
   1214          || mLastWimaxIconId                != mWimaxIconId
   1215          || mLastDataTypeIconId             != mDataTypeIconId
   1216          || mLastAirplaneMode               != mAirplaneMode
   1217          || mLastLocale                     != mLocale)
   1218         {
   1219             // NB: the mLast*s will be updated later
   1220             for (SignalCluster cluster : mSignalClusters) {
   1221                 refreshSignalCluster(cluster);
   1222             }
   1223             for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
   1224                 notifySignalsChangedCallbacks(cb);
   1225             }
   1226         }
   1227 
   1228         if (mLastAirplaneMode != mAirplaneMode) {
   1229             mLastAirplaneMode = mAirplaneMode;
   1230         }
   1231 
   1232         if (mLastLocale != mLocale) {
   1233             mLastLocale = mLocale;
   1234         }
   1235 
   1236         // the phone icon on phones
   1237         if (mLastPhoneSignalIconId != mPhoneSignalIconId) {
   1238             mLastPhoneSignalIconId = mPhoneSignalIconId;
   1239             N = mPhoneSignalIconViews.size();
   1240             for (int i=0; i<N; i++) {
   1241                 final ImageView v = mPhoneSignalIconViews.get(i);
   1242                 if (mPhoneSignalIconId == 0) {
   1243                     v.setVisibility(View.GONE);
   1244                 } else {
   1245                     v.setVisibility(View.VISIBLE);
   1246                     v.setImageResource(mPhoneSignalIconId);
   1247                     v.setContentDescription(mContentDescriptionPhoneSignal);
   1248                 }
   1249             }
   1250         }
   1251 
   1252         // the data icon on phones
   1253         if (mLastDataDirectionIconId != mDataDirectionIconId) {
   1254             mLastDataDirectionIconId = mDataDirectionIconId;
   1255             N = mDataDirectionIconViews.size();
   1256             for (int i=0; i<N; i++) {
   1257                 final ImageView v = mDataDirectionIconViews.get(i);
   1258                 v.setImageResource(mDataDirectionIconId);
   1259                 v.setContentDescription(mContentDescriptionDataType);
   1260             }
   1261         }
   1262 
   1263         // the wifi icon on phones
   1264         if (mLastWifiIconId != mWifiIconId) {
   1265             mLastWifiIconId = mWifiIconId;
   1266             N = mWifiIconViews.size();
   1267             for (int i=0; i<N; i++) {
   1268                 final ImageView v = mWifiIconViews.get(i);
   1269                 if (mWifiIconId == 0) {
   1270                     v.setVisibility(View.GONE);
   1271                 } else {
   1272                     v.setVisibility(View.VISIBLE);
   1273                     v.setImageResource(mWifiIconId);
   1274                     v.setContentDescription(mContentDescriptionWifi);
   1275                 }
   1276             }
   1277         }
   1278 
   1279         // the wimax icon on phones
   1280         if (mLastWimaxIconId != mWimaxIconId) {
   1281             mLastWimaxIconId = mWimaxIconId;
   1282             N = mWimaxIconViews.size();
   1283             for (int i=0; i<N; i++) {
   1284                 final ImageView v = mWimaxIconViews.get(i);
   1285                 if (mWimaxIconId == 0) {
   1286                     v.setVisibility(View.GONE);
   1287                 } else {
   1288                     v.setVisibility(View.VISIBLE);
   1289                     v.setImageResource(mWimaxIconId);
   1290                     v.setContentDescription(mContentDescriptionWimax);
   1291                 }
   1292            }
   1293         }
   1294         // the combined data signal icon
   1295         if (mLastCombinedSignalIconId != combinedSignalIconId) {
   1296             mLastCombinedSignalIconId = combinedSignalIconId;
   1297             N = mCombinedSignalIconViews.size();
   1298             for (int i=0; i<N; i++) {
   1299                 final ImageView v = mCombinedSignalIconViews.get(i);
   1300                 v.setImageResource(combinedSignalIconId);
   1301                 v.setContentDescription(mContentDescriptionCombinedSignal);
   1302             }
   1303         }
   1304 
   1305         // the data network type overlay
   1306         if (mLastDataTypeIconId != mDataTypeIconId) {
   1307             mLastDataTypeIconId = mDataTypeIconId;
   1308             N = mDataTypeIconViews.size();
   1309             for (int i=0; i<N; i++) {
   1310                 final ImageView v = mDataTypeIconViews.get(i);
   1311                 if (mDataTypeIconId == 0) {
   1312                     v.setVisibility(View.GONE);
   1313                 } else {
   1314                     v.setVisibility(View.VISIBLE);
   1315                     v.setImageResource(mDataTypeIconId);
   1316                     v.setContentDescription(mContentDescriptionDataType);
   1317                 }
   1318             }
   1319         }
   1320 
   1321         // the data direction overlay
   1322         if (mLastDataDirectionOverlayIconId != combinedActivityIconId) {
   1323             if (DEBUG) {
   1324                 Slog.d(TAG, "changing data overlay icon id to " + combinedActivityIconId);
   1325             }
   1326             mLastDataDirectionOverlayIconId = combinedActivityIconId;
   1327             N = mDataDirectionOverlayIconViews.size();
   1328             for (int i=0; i<N; i++) {
   1329                 final ImageView v = mDataDirectionOverlayIconViews.get(i);
   1330                 if (combinedActivityIconId == 0) {
   1331                     v.setVisibility(View.GONE);
   1332                 } else {
   1333                     v.setVisibility(View.VISIBLE);
   1334                     v.setImageResource(combinedActivityIconId);
   1335                     v.setContentDescription(mContentDescriptionDataType);
   1336                 }
   1337             }
   1338         }
   1339 
   1340         // the combinedLabel in the notification panel
   1341         if (!mLastCombinedLabel.equals(combinedLabel)) {
   1342             mLastCombinedLabel = combinedLabel;
   1343             N = mCombinedLabelViews.size();
   1344             for (int i=0; i<N; i++) {
   1345                 TextView v = mCombinedLabelViews.get(i);
   1346                 v.setText(combinedLabel);
   1347             }
   1348         }
   1349 
   1350         // wifi label
   1351         N = mWifiLabelViews.size();
   1352         for (int i=0; i<N; i++) {
   1353             TextView v = mWifiLabelViews.get(i);
   1354             v.setText(wifiLabel);
   1355             if ("".equals(wifiLabel)) {
   1356                 v.setVisibility(View.GONE);
   1357             } else {
   1358                 v.setVisibility(View.VISIBLE);
   1359             }
   1360         }
   1361 
   1362         // mobile label
   1363         N = mMobileLabelViews.size();
   1364         for (int i=0; i<N; i++) {
   1365             TextView v = mMobileLabelViews.get(i);
   1366             v.setText(mobileLabel);
   1367             if ("".equals(mobileLabel)) {
   1368                 v.setVisibility(View.GONE);
   1369             } else {
   1370                 v.setVisibility(View.VISIBLE);
   1371             }
   1372         }
   1373 
   1374         // e-call label
   1375         N = mEmergencyLabelViews.size();
   1376         for (int i=0; i<N; i++) {
   1377             TextView v = mEmergencyLabelViews.get(i);
   1378             if (!emergencyOnly) {
   1379                 v.setVisibility(View.GONE);
   1380             } else {
   1381                 v.setText(mobileLabel); // comes from the telephony stack
   1382                 v.setVisibility(View.VISIBLE);
   1383             }
   1384         }
   1385     }
   1386 
   1387     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1388         pw.println("NetworkController state:");
   1389         pw.println(String.format("  %s network type %d (%s)",
   1390                 mConnected?"CONNECTED":"DISCONNECTED",
   1391                 mConnectedNetworkType, mConnectedNetworkTypeName));
   1392         pw.println("  - telephony ------");
   1393         pw.print("  hasVoiceCallingFeature()=");
   1394         pw.println(hasVoiceCallingFeature());
   1395         pw.print("  hasService()=");
   1396         pw.println(hasService());
   1397         pw.print("  mHspaDataDistinguishable=");
   1398         pw.println(mHspaDataDistinguishable);
   1399         pw.print("  mDataConnected=");
   1400         pw.println(mDataConnected);
   1401         pw.print("  mSimState=");
   1402         pw.println(mSimState);
   1403         pw.print("  mPhoneState=");
   1404         pw.println(mPhoneState);
   1405         pw.print("  mDataState=");
   1406         pw.println(mDataState);
   1407         pw.print("  mDataActivity=");
   1408         pw.println(mDataActivity);
   1409         pw.print("  mDataNetType=");
   1410         pw.print(mDataNetType);
   1411         pw.print("/");
   1412         pw.println(TelephonyManager.getNetworkTypeName(mDataNetType));
   1413         pw.print("  mServiceState=");
   1414         pw.println(mServiceState);
   1415         pw.print("  mSignalStrength=");
   1416         pw.println(mSignalStrength);
   1417         pw.print("  mLastSignalLevel=");
   1418         pw.println(mLastSignalLevel);
   1419         pw.print("  mNetworkName=");
   1420         pw.println(mNetworkName);
   1421         pw.print("  mNetworkNameDefault=");
   1422         pw.println(mNetworkNameDefault);
   1423         pw.print("  mNetworkNameSeparator=");
   1424         pw.println(mNetworkNameSeparator.replace("\n","\\n"));
   1425         pw.print("  mPhoneSignalIconId=0x");
   1426         pw.print(Integer.toHexString(mPhoneSignalIconId));
   1427         pw.print("/");
   1428         pw.print("  mQSPhoneSignalIconId=0x");
   1429         pw.print(Integer.toHexString(mQSPhoneSignalIconId));
   1430         pw.print("/");
   1431         pw.println(getResourceName(mPhoneSignalIconId));
   1432         pw.print("  mDataDirectionIconId=");
   1433         pw.print(Integer.toHexString(mDataDirectionIconId));
   1434         pw.print("/");
   1435         pw.println(getResourceName(mDataDirectionIconId));
   1436         pw.print("  mDataSignalIconId=");
   1437         pw.print(Integer.toHexString(mDataSignalIconId));
   1438         pw.print("/");
   1439         pw.println(getResourceName(mDataSignalIconId));
   1440         pw.print("  mDataTypeIconId=");
   1441         pw.print(Integer.toHexString(mDataTypeIconId));
   1442         pw.print("/");
   1443         pw.println(getResourceName(mDataTypeIconId));
   1444         pw.print("  mQSDataTypeIconId=");
   1445         pw.print(Integer.toHexString(mQSDataTypeIconId));
   1446         pw.print("/");
   1447         pw.println(getResourceName(mQSDataTypeIconId));
   1448 
   1449         pw.println("  - wifi ------");
   1450         pw.print("  mWifiEnabled=");
   1451         pw.println(mWifiEnabled);
   1452         pw.print("  mWifiConnected=");
   1453         pw.println(mWifiConnected);
   1454         pw.print("  mWifiRssi=");
   1455         pw.println(mWifiRssi);
   1456         pw.print("  mWifiLevel=");
   1457         pw.println(mWifiLevel);
   1458         pw.print("  mWifiSsid=");
   1459         pw.println(mWifiSsid);
   1460         pw.println(String.format("  mWifiIconId=0x%08x/%s",
   1461                     mWifiIconId, getResourceName(mWifiIconId)));
   1462         pw.println(String.format("  mQSWifiIconId=0x%08x/%s",
   1463                     mQSWifiIconId, getResourceName(mQSWifiIconId)));
   1464         pw.print("  mWifiActivity=");
   1465         pw.println(mWifiActivity);
   1466 
   1467         if (mWimaxSupported) {
   1468             pw.println("  - wimax ------");
   1469             pw.print("  mIsWimaxEnabled="); pw.println(mIsWimaxEnabled);
   1470             pw.print("  mWimaxConnected="); pw.println(mWimaxConnected);
   1471             pw.print("  mWimaxIdle="); pw.println(mWimaxIdle);
   1472             pw.println(String.format("  mWimaxIconId=0x%08x/%s",
   1473                         mWimaxIconId, getResourceName(mWimaxIconId)));
   1474             pw.println(String.format("  mWimaxSignal=%d", mWimaxSignal));
   1475             pw.println(String.format("  mWimaxState=%d", mWimaxState));
   1476             pw.println(String.format("  mWimaxExtraState=%d", mWimaxExtraState));
   1477         }
   1478 
   1479         pw.println("  - Bluetooth ----");
   1480         pw.print("  mBtReverseTethered=");
   1481         pw.println(mBluetoothTethered);
   1482 
   1483         pw.println("  - connectivity ------");
   1484         pw.print("  mInetCondition=");
   1485         pw.println(mInetCondition);
   1486 
   1487         pw.println("  - icons ------");
   1488         pw.print("  mLastPhoneSignalIconId=0x");
   1489         pw.print(Integer.toHexString(mLastPhoneSignalIconId));
   1490         pw.print("/");
   1491         pw.println(getResourceName(mLastPhoneSignalIconId));
   1492         pw.print("  mLastDataDirectionIconId=0x");
   1493         pw.print(Integer.toHexString(mLastDataDirectionIconId));
   1494         pw.print("/");
   1495         pw.println(getResourceName(mLastDataDirectionIconId));
   1496         pw.print("  mLastDataDirectionOverlayIconId=0x");
   1497         pw.print(Integer.toHexString(mLastDataDirectionOverlayIconId));
   1498         pw.print("/");
   1499         pw.println(getResourceName(mLastDataDirectionOverlayIconId));
   1500         pw.print("  mLastWifiIconId=0x");
   1501         pw.print(Integer.toHexString(mLastWifiIconId));
   1502         pw.print("/");
   1503         pw.println(getResourceName(mLastWifiIconId));
   1504         pw.print("  mLastCombinedSignalIconId=0x");
   1505         pw.print(Integer.toHexString(mLastCombinedSignalIconId));
   1506         pw.print("/");
   1507         pw.println(getResourceName(mLastCombinedSignalIconId));
   1508         pw.print("  mLastDataTypeIconId=0x");
   1509         pw.print(Integer.toHexString(mLastDataTypeIconId));
   1510         pw.print("/");
   1511         pw.println(getResourceName(mLastDataTypeIconId));
   1512         pw.print("  mLastCombinedLabel=");
   1513         pw.print(mLastCombinedLabel);
   1514         pw.println("");
   1515     }
   1516 
   1517     private String getResourceName(int resId) {
   1518         if (resId != 0) {
   1519             final Resources res = mContext.getResources();
   1520             try {
   1521                 return res.getResourceName(resId);
   1522             } catch (android.content.res.Resources.NotFoundException ex) {
   1523                 return "(unknown)";
   1524             }
   1525         } else {
   1526             return "(null)";
   1527         }
   1528     }
   1529 
   1530 }
   1531