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