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