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