NetworkController.java revision 9a7c7129760ac89ffebf3dd3b508ff755ecff844
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 java.io.FileDescriptor; 20import java.io.PrintWriter; 21import java.util.ArrayList; 22import java.util.List; 23 24import android.content.BroadcastReceiver; 25import android.content.Context; 26import android.content.Intent; 27import android.content.IntentFilter; 28import android.content.res.Resources; 29import android.net.ConnectivityManager; 30import android.net.NetworkInfo; 31import android.net.wifi.SupplicantState; 32import android.net.wifi.WifiConfiguration; 33import android.net.wifi.WifiInfo; 34import android.net.wifi.WifiManager; 35import android.os.Binder; 36import android.os.RemoteException; 37import android.os.SystemProperties; 38import android.provider.Settings; 39import android.provider.Telephony; 40import android.telephony.PhoneStateListener; 41import android.telephony.ServiceState; 42import android.telephony.SignalStrength; 43import android.telephony.TelephonyManager; 44import android.util.Slog; 45import android.view.View; 46import android.widget.ImageView; 47import android.widget.TextView; 48 49import com.android.internal.app.IBatteryStats; 50import com.android.internal.telephony.IccCard; 51import com.android.internal.telephony.TelephonyIntents; 52import com.android.internal.telephony.cdma.EriInfo; 53import com.android.server.am.BatteryStatsService; 54 55import com.android.systemui.R; 56 57public class NetworkController extends BroadcastReceiver { 58 // debug 59 static final String TAG = "StatusBar.NetworkController"; 60 static final boolean DEBUG = false; 61 62 // telephony 63 boolean mHspaDataDistinguishable; 64 final TelephonyManager mPhone; 65 boolean mDataConnected; 66 IccCard.State mSimState = IccCard.State.READY; 67 int mPhoneState = TelephonyManager.CALL_STATE_IDLE; 68 int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 69 int mDataState = TelephonyManager.DATA_DISCONNECTED; 70 int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; 71 ServiceState mServiceState; 72 SignalStrength mSignalStrength; 73 int[] mDataIconList = TelephonyIcons.DATA_G[0]; 74 String mNetworkName; 75 String mNetworkNameDefault; 76 String mNetworkNameSeparator; 77 int mPhoneSignalIconId; 78 int mDataDirectionIconId; 79 int mDataDirectionOverlayIconId; 80 int mDataSignalIconId; 81 int mDataTypeIconId; 82 boolean mDataActive; 83 84 // wifi 85 final WifiManager mWifiManager; 86 boolean mWifiEnabled, mWifiConnected; 87 int mWifiLevel; 88 String mWifiSsid; 89 int mWifiIconId = 0; 90 91 // bluetooth 92 private boolean mBluetoothTethered = false; 93 private int mBluetoothTetherIconId = 94 com.android.internal.R.drawable.stat_sys_tether_bluetooth; 95 96 // data connectivity (regardless of state, can we access the internet?) 97 // state of inet connection - 0 not connected, 100 connected 98 private int mInetCondition = 0; 99 private static final int INET_CONDITION_THRESHOLD = 50; 100 101 // our ui 102 Context mContext; 103 ArrayList<ImageView> mPhoneSignalIconViews = new ArrayList<ImageView>(); 104 ArrayList<ImageView> mDataDirectionIconViews = new ArrayList<ImageView>(); 105 ArrayList<ImageView> mDataDirectionOverlayIconViews = new ArrayList<ImageView>(); 106 ArrayList<ImageView> mWifiIconViews = new ArrayList<ImageView>(); 107 ArrayList<ImageView> mCombinedSignalIconViews = new ArrayList<ImageView>(); 108 ArrayList<ImageView> mDataTypeIconViews = new ArrayList<ImageView>(); 109 ArrayList<TextView> mLabelViews = new ArrayList<TextView>(); 110 int mLastPhoneSignalIconId = -1; 111 int mLastDataDirectionIconId = -1; 112 int mLastDataDirectionOverlayIconId = -1; 113 int mLastWifiIconId = -1; 114 int mLastCombinedSignalIconId = -1; 115 int mLastDataTypeIconId = -1; 116 String mLastLabel = ""; 117 118 // yuck -- stop doing this here and put it in the framework 119 IBatteryStats mBatteryStats; 120 121 /** 122 * Construct this controller object and register for updates. 123 */ 124 public NetworkController(Context context) { 125 mContext = context; 126 127 // set up the default wifi icon, used when no radios have ever appeared 128 updateWifiIcons(); 129 130 // telephony 131 mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 132 mPhone.listen(mPhoneStateListener, 133 PhoneStateListener.LISTEN_SERVICE_STATE 134 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS 135 | PhoneStateListener.LISTEN_CALL_STATE 136 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE 137 | PhoneStateListener.LISTEN_DATA_ACTIVITY); 138 mHspaDataDistinguishable = mContext.getResources().getBoolean( 139 R.bool.config_hspa_data_distinguishable); 140 mNetworkNameSeparator = mContext.getString(R.string.status_bar_network_name_separator); 141 mNetworkNameDefault = mContext.getString( 142 com.android.internal.R.string.lockscreen_carrier_default); 143 mNetworkName = mNetworkNameDefault; 144 145 // wifi 146 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 147 148 // broadcasts 149 IntentFilter filter = new IntentFilter(); 150 filter.addAction(WifiManager.RSSI_CHANGED_ACTION); 151 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 152 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 153 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 154 filter.addAction(Telephony.Intents.SPN_STRINGS_UPDATED_ACTION); 155 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 156 filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); 157 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 158 context.registerReceiver(this, filter); 159 160 // yuck 161 mBatteryStats = BatteryStatsService.getService(); 162 } 163 164 public void addPhoneSignalIconView(ImageView v) { 165 mPhoneSignalIconViews.add(v); 166 } 167 168 public void addDataDirectionIconView(ImageView v) { 169 mDataDirectionIconViews.add(v); 170 } 171 172 public void addDataDirectionOverlayIconView(ImageView v) { 173 mDataDirectionOverlayIconViews.add(v); 174 } 175 176 public void addWifiIconView(ImageView v) { 177 mWifiIconViews.add(v); 178 } 179 180 public void addCombinedSignalIconView(ImageView v) { 181 mCombinedSignalIconViews.add(v); 182 } 183 184 public void addDataTypeIconView(ImageView v) { 185 mDataTypeIconViews.add(v); 186 } 187 188 public void addLabelView(TextView v) { 189 mLabelViews.add(v); 190 } 191 192 public void onReceive(Context context, Intent intent) { 193 final String action = intent.getAction(); 194 if (action.equals(WifiManager.RSSI_CHANGED_ACTION) 195 || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) 196 || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 197 updateWifiState(intent); 198 refreshViews(); 199 } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { 200 updateSimState(intent); 201 updateDataIcon(); 202 refreshViews(); 203 } else if (action.equals(Telephony.Intents.SPN_STRINGS_UPDATED_ACTION)) { 204 updateNetworkName(intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_SPN, false), 205 intent.getStringExtra(Telephony.Intents.EXTRA_SPN), 206 intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_PLMN, false), 207 intent.getStringExtra(Telephony.Intents.EXTRA_PLMN)); 208 refreshViews(); 209 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) || 210 action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { 211 updateConnectivity(intent); 212 refreshViews(); 213 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 214 refreshViews(); 215 } 216 } 217 218 219 // ===== Telephony ============================================================== 220 221 PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 222 @Override 223 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 224 if (DEBUG) { 225 Slog.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength); 226 } 227 mSignalStrength = signalStrength; 228 updateTelephonySignalStrength(); 229 refreshViews(); 230 } 231 232 @Override 233 public void onServiceStateChanged(ServiceState state) { 234 if (DEBUG) { 235 Slog.d(TAG, "onServiceStateChanged state=" + state.getState()); 236 } 237 mServiceState = state; 238 updateTelephonySignalStrength(); 239 updateDataIcon(); 240 refreshViews(); 241 } 242 243 @Override 244 public void onCallStateChanged(int state, String incomingNumber) { 245 if (DEBUG) { 246 Slog.d(TAG, "onCallStateChanged state=" + state); 247 } 248 // In cdma, if a voice call is made, RSSI should switch to 1x. 249 if (isCdma()) { 250 updateTelephonySignalStrength(); 251 refreshViews(); 252 } 253 } 254 255 @Override 256 public void onDataConnectionStateChanged(int state, int networkType) { 257 if (DEBUG) { 258 Slog.d(TAG, "onDataConnectionStateChanged: state=" + state 259 + " type=" + networkType); 260 } 261 mDataState = state; 262 mDataNetType = networkType; 263 if (state < 0) { 264 // device without a data connection 265 mSignalStrength = null; 266 } 267 updateDataNetType(); 268 updateDataIcon(); 269 refreshViews(); 270 } 271 272 @Override 273 public void onDataActivity(int direction) { 274 if (DEBUG) { 275 Slog.d(TAG, "onDataActivity: direction=" + direction); 276 } 277 mDataActivity = direction; 278 updateDataIcon(); 279 refreshViews(); 280 } 281 }; 282 283 private final void updateSimState(Intent intent) { 284 String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE); 285 if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { 286 mSimState = IccCard.State.ABSENT; 287 } 288 else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) { 289 mSimState = IccCard.State.READY; 290 } 291 else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { 292 final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON); 293 if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { 294 mSimState = IccCard.State.PIN_REQUIRED; 295 } 296 else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { 297 mSimState = IccCard.State.PUK_REQUIRED; 298 } 299 else { 300 mSimState = IccCard.State.NETWORK_LOCKED; 301 } 302 } else { 303 mSimState = IccCard.State.UNKNOWN; 304 } 305 } 306 307 private boolean isCdma() { 308 return (mSignalStrength != null) && !mSignalStrength.isGsm(); 309 } 310 311 private boolean isEvdo() { 312 return ((mServiceState != null) 313 && ((mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_0) 314 || (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_A) 315 || (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_B))); 316 } 317 318 private boolean hasService() { 319 if (mServiceState != null) { 320 switch (mServiceState.getState()) { 321 case ServiceState.STATE_OUT_OF_SERVICE: 322 case ServiceState.STATE_POWER_OFF: 323 return false; 324 default: 325 return true; 326 } 327 } else { 328 return false; 329 } 330 } 331 332 private boolean hasMobileDataFeature() { 333 // XXX: HAX: replace when a more reliable method is available 334 return (! "wifi-only".equals(SystemProperties.get("ro.carrier"))); 335 } 336 337 private int getCdmaLevel() { 338 if (mSignalStrength == null) return 0; 339 final int cdmaDbm = mSignalStrength.getCdmaDbm(); 340 final int cdmaEcio = mSignalStrength.getCdmaEcio(); 341 int levelDbm = 0; 342 int levelEcio = 0; 343 344 if (cdmaDbm >= -75) levelDbm = 4; 345 else if (cdmaDbm >= -85) levelDbm = 3; 346 else if (cdmaDbm >= -95) levelDbm = 2; 347 else if (cdmaDbm >= -100) levelDbm = 1; 348 else levelDbm = 0; 349 350 // Ec/Io are in dB*10 351 if (cdmaEcio >= -90) levelEcio = 4; 352 else if (cdmaEcio >= -110) levelEcio = 3; 353 else if (cdmaEcio >= -130) levelEcio = 2; 354 else if (cdmaEcio >= -150) levelEcio = 1; 355 else levelEcio = 0; 356 357 return (levelDbm < levelEcio) ? levelDbm : levelEcio; 358 } 359 360 private int getEvdoLevel() { 361 if (mSignalStrength == null) return 0; 362 int evdoDbm = mSignalStrength.getEvdoDbm(); 363 int evdoSnr = mSignalStrength.getEvdoSnr(); 364 int levelEvdoDbm = 0; 365 int levelEvdoSnr = 0; 366 367 if (evdoDbm >= -65) levelEvdoDbm = 4; 368 else if (evdoDbm >= -75) levelEvdoDbm = 3; 369 else if (evdoDbm >= -90) levelEvdoDbm = 2; 370 else if (evdoDbm >= -105) levelEvdoDbm = 1; 371 else levelEvdoDbm = 0; 372 373 if (evdoSnr >= 7) levelEvdoSnr = 4; 374 else if (evdoSnr >= 5) levelEvdoSnr = 3; 375 else if (evdoSnr >= 3) levelEvdoSnr = 2; 376 else if (evdoSnr >= 1) levelEvdoSnr = 1; 377 else levelEvdoSnr = 0; 378 379 return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr; 380 } 381 382 private final void updateTelephonySignalStrength() { 383 // Display signal strength while in "emergency calls only" mode 384 if (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly())) { 385 //Slog.d(TAG, "updateTelephonySignalStrength: no service"); 386 if (Settings.System.getInt(mContext.getContentResolver(), 387 Settings.System.AIRPLANE_MODE_ON, 0) == 1) { 388 mPhoneSignalIconId = R.drawable.stat_sys_signal_flightmode; 389 mDataSignalIconId = R.drawable.stat_sys_signal_flightmode; 390 } else { 391 mPhoneSignalIconId = R.drawable.stat_sys_signal_null; 392 mDataSignalIconId = R.drawable.stat_sys_signal_0; // note we use 0 instead of null 393 } 394 } else { 395 if (mSignalStrength == null) { 396 mPhoneSignalIconId = R.drawable.stat_sys_signal_null; 397 mDataSignalIconId = R.drawable.stat_sys_signal_0; // note we use 0 instead of null 398 } else if (isCdma()) { 399 // If 3G(EV) and 1x network are available than 3G should be 400 // displayed, displayed RSSI should be from the EV side. 401 // If a voice call is made then RSSI should switch to 1x. 402 int iconLevel; 403 if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){ 404 iconLevel = getEvdoLevel(); 405 } else { 406 iconLevel = getCdmaLevel(); 407 } 408 int[] iconList; 409 if (isCdmaEri()) { 410 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition]; 411 } else { 412 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition]; 413 } 414 mPhoneSignalIconId = iconList[iconLevel]; 415 mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel]; 416 } else { 417 int asu = mSignalStrength.getGsmSignalStrength(); 418 419 // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5 420 // asu = 0 (-113dB or less) is very weak 421 // signal, its better to show 0 bars to the user in such cases. 422 // asu = 99 is a special case, where the signal strength is unknown. 423 int iconLevel; 424 if (asu <= 2 || asu == 99) iconLevel = 0; 425 else if (asu >= 12) iconLevel = 4; 426 else if (asu >= 8) iconLevel = 3; 427 else if (asu >= 5) iconLevel = 2; 428 else iconLevel = 1; 429 430 // Though mPhone is a Manager, this call is not an IPC 431 int[] iconList; 432 if (mPhone.isNetworkRoaming()) { 433 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition]; 434 } else { 435 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition]; 436 } 437 mPhoneSignalIconId = iconList[iconLevel]; 438 mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel]; 439 } 440 } 441 } 442 443 private final void updateDataNetType() { 444 switch (mDataNetType) { 445 case TelephonyManager.NETWORK_TYPE_UNKNOWN: 446 mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; 447 mDataTypeIconId = 0; 448 break; 449 case TelephonyManager.NETWORK_TYPE_EDGE: 450 mDataIconList = TelephonyIcons.DATA_E[mInetCondition]; 451 mDataTypeIconId = R.drawable.stat_sys_signal_edge; 452 break; 453 case TelephonyManager.NETWORK_TYPE_UMTS: 454 mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; 455 mDataTypeIconId = R.drawable.stat_sys_signal_3g; 456 break; 457 case TelephonyManager.NETWORK_TYPE_HSDPA: 458 case TelephonyManager.NETWORK_TYPE_HSUPA: 459 case TelephonyManager.NETWORK_TYPE_HSPA: 460 if (mHspaDataDistinguishable) { 461 mDataIconList = TelephonyIcons.DATA_H[mInetCondition]; 462 mDataTypeIconId = R.drawable.stat_sys_signal_hsdpa; 463 } else { 464 mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; 465 mDataTypeIconId = R.drawable.stat_sys_signal_3g; 466 } 467 break; 468 case TelephonyManager.NETWORK_TYPE_CDMA: 469 // display 1xRTT for IS95A/B 470 mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; 471 mDataTypeIconId = R.drawable.stat_sys_signal_1x; 472 break; 473 case TelephonyManager.NETWORK_TYPE_1xRTT: 474 mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; 475 mDataTypeIconId = R.drawable.stat_sys_signal_1x; 476 break; 477 case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through 478 case TelephonyManager.NETWORK_TYPE_EVDO_A: 479 case TelephonyManager.NETWORK_TYPE_EVDO_B: 480 mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; 481 mDataTypeIconId = R.drawable.stat_sys_signal_3g; 482 break; 483 // TODO - add support for NETWORK_TYPE_LTE and NETWORK_TYPE_EHRPD 484 default: 485 mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; 486 mDataTypeIconId = R.drawable.stat_sys_signal_gprs; 487 break; 488 } 489 if ((isCdma() && isCdmaEri()) || mPhone.isNetworkRoaming()) { 490 mDataTypeIconId = R.drawable.stat_sys_signal_roam; 491 } 492 } 493 494 boolean isCdmaEri() { 495 final int iconIndex = mServiceState.getCdmaEriIconIndex(); 496 if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) { 497 final int iconMode = mServiceState.getCdmaEriIconMode(); 498 if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL 499 || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) { 500 return true; 501 } 502 } 503 return false; 504 } 505 506 private final void updateDataIcon() { 507 int iconId; 508 boolean visible = true; 509 510 if (!isCdma()) { 511 // GSM case, we have to check also the sim state 512 if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) { 513 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) { 514 switch (mDataActivity) { 515 case TelephonyManager.DATA_ACTIVITY_IN: 516 iconId = mDataIconList[1]; 517 break; 518 case TelephonyManager.DATA_ACTIVITY_OUT: 519 iconId = mDataIconList[2]; 520 break; 521 case TelephonyManager.DATA_ACTIVITY_INOUT: 522 iconId = mDataIconList[3]; 523 break; 524 default: 525 iconId = mDataIconList[0]; 526 break; 527 } 528 mDataDirectionIconId = iconId; 529 } else { 530 iconId = 0; 531 visible = false; 532 } 533 } else { 534 iconId = R.drawable.stat_sys_no_sim; 535 } 536 } else { 537 // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT 538 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) { 539 switch (mDataActivity) { 540 case TelephonyManager.DATA_ACTIVITY_IN: 541 iconId = mDataIconList[1]; 542 break; 543 case TelephonyManager.DATA_ACTIVITY_OUT: 544 iconId = mDataIconList[2]; 545 break; 546 case TelephonyManager.DATA_ACTIVITY_INOUT: 547 iconId = mDataIconList[3]; 548 break; 549 case TelephonyManager.DATA_ACTIVITY_DORMANT: 550 default: 551 iconId = mDataIconList[0]; 552 break; 553 } 554 } else { 555 iconId = 0; 556 visible = false; 557 } 558 } 559 560 // yuck - this should NOT be done by the status bar 561 long ident = Binder.clearCallingIdentity(); 562 try { 563 mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible); 564 } catch (RemoteException e) { 565 } finally { 566 Binder.restoreCallingIdentity(ident); 567 } 568 569 mDataDirectionIconId = iconId; 570 mDataConnected = visible; 571 } 572 573 void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) { 574 if (false) { 575 Slog.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn 576 + " showPlmn=" + showPlmn + " plmn=" + plmn); 577 } 578 StringBuilder str = new StringBuilder(); 579 boolean something = false; 580 if (showPlmn && plmn != null) { 581 str.append(plmn); 582 something = true; 583 } 584 if (showSpn && spn != null) { 585 if (something) { 586 str.append(mNetworkNameSeparator); 587 } 588 str.append(spn); 589 something = true; 590 } 591 if (something) { 592 mNetworkName = str.toString(); 593 } else { 594 mNetworkName = mNetworkNameDefault; 595 } 596 } 597 598 // ===== Wifi =================================================================== 599 600 private void updateWifiState(Intent intent) { 601 final String action = intent.getAction(); 602 if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 603 mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 604 WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; 605 606 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 607 final NetworkInfo networkInfo = (NetworkInfo) 608 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 609 boolean wasConnected = mWifiConnected; 610 mWifiConnected = networkInfo != null && networkInfo.isConnected(); 611 // If we just connected, grab the inintial signal strength and ssid 612 if (mWifiConnected && !wasConnected) { 613 WifiInfo info = mWifiManager.getConnectionInfo(); 614 if (info != null) { 615 mWifiLevel = WifiManager.calculateSignalLevel(info.getRssi(), 616 WifiIcons.WIFI_LEVEL_COUNT); 617 mWifiSsid = huntForSsid(info); 618 } else { 619 mWifiLevel = 0; 620 mWifiSsid = null; 621 } 622 } else if (!mWifiConnected) { 623 mWifiLevel = 0; 624 mWifiSsid = null; 625 } 626 627 } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { 628 if (mWifiConnected) { 629 final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200); 630 mWifiLevel = WifiManager.calculateSignalLevel(newRssi, WifiIcons.WIFI_LEVEL_COUNT); 631 } 632 } 633 634 updateWifiIcons(); 635 } 636 637 private void updateWifiIcons() { 638 if (mWifiConnected) { 639 mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel]; 640 } else { 641 mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]; 642 } 643 } 644 645 private String huntForSsid(WifiInfo info) { 646 String ssid = info.getSSID(); 647 if (ssid != null) { 648 return ssid; 649 } 650 // OK, it's not in the connectionInfo; we have to go hunting for it 651 List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks(); 652 for (WifiConfiguration net : networks) { 653 if (net.networkId == info.getNetworkId()) { 654 return net.SSID; 655 } 656 } 657 return null; 658 } 659 660 661 // ===== Full or limited Internet connectivity ================================== 662 663 private void updateConnectivity(Intent intent) { 664 NetworkInfo info = (NetworkInfo)(intent.getParcelableExtra( 665 ConnectivityManager.EXTRA_NETWORK_INFO)); 666 int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0); 667 668 int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0); 669 670 switch (info.getType()) { 671 case ConnectivityManager.TYPE_MOBILE: 672 mInetCondition = inetCondition; 673 updateDataNetType(); 674 updateDataIcon(); 675 updateTelephonySignalStrength(); // apply any change in connectionStatus 676 break; 677 case ConnectivityManager.TYPE_WIFI: 678 mInetCondition = inetCondition; 679 updateWifiIcons(); 680 break; 681 case ConnectivityManager.TYPE_BLUETOOTH: 682 mInetCondition = inetCondition; 683 if (info != null) { 684 mBluetoothTethered = info.isConnected() ? true: false; 685 } else { 686 mBluetoothTethered = false; 687 } 688 break; 689 } 690 } 691 692 693 // ===== Update the views ======================================================= 694 695 // figure out what to show- there should be one connected network or nothing 696 // General order of preference is: wifi, 3G than bluetooth. This might vary by product. 697 void refreshViews() { 698 Context context = mContext; 699 700 int combinedSignalIconId; 701 int dataDirectionOverlayIconId = 0; 702 int dataTypeIconId; 703 String label; 704 int N; 705 706 if (mWifiConnected) { 707 if (mWifiSsid == null) { 708 label = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid); 709 } else { 710 label = mWifiSsid; 711 } 712 combinedSignalIconId = mWifiIconId; 713 dataTypeIconId = 0; 714 } else if (mDataConnected) { 715 label = mNetworkName; 716 combinedSignalIconId = mDataSignalIconId; 717 switch (mDataActivity) { 718 case TelephonyManager.DATA_ACTIVITY_IN: 719 dataDirectionOverlayIconId = R.drawable.stat_sys_signal_in; 720 break; 721 case TelephonyManager.DATA_ACTIVITY_OUT: 722 dataDirectionOverlayIconId = R.drawable.stat_sys_signal_out; 723 break; 724 case TelephonyManager.DATA_ACTIVITY_INOUT: 725 dataDirectionOverlayIconId = R.drawable.stat_sys_signal_inout; 726 break; 727 default: 728 dataDirectionOverlayIconId = 0; 729 break; 730 } 731 combinedSignalIconId = mDataSignalIconId; 732 dataTypeIconId = mDataTypeIconId; 733 } else if (mBluetoothTethered) { 734 label = mContext.getString(R.string.bluetooth_tethered); 735 combinedSignalIconId = mBluetoothTetherIconId; 736 dataTypeIconId = 0; 737 } else { 738 label = context.getString(R.string.status_bar_settings_signal_meter_disconnected); 739 // On devices without mobile radios, we want to show the wifi icon 740 combinedSignalIconId = 741 hasMobileDataFeature() ? mDataSignalIconId : mWifiIconId; 742 dataTypeIconId = 0; 743 } 744 745 if (DEBUG) { 746 Slog.d(TAG, "refreshViews combinedSignalIconId=0x" 747 + Integer.toHexString(combinedSignalIconId) 748 + "/" + getResourceName(combinedSignalIconId) 749 + " dataDirectionOverlayIconId=0x" + Integer.toHexString(dataDirectionOverlayIconId) 750 + " mDataActivity=" + mDataActivity 751 + " mPhoneSignalIconId=0x" + Integer.toHexString(mPhoneSignalIconId) 752 + " mDataDirectionIconId=0x" + Integer.toHexString(mDataDirectionIconId) 753 + " mDataSignalIconId=0x" + Integer.toHexString(mDataSignalIconId) 754 + " mDataTypeIconId=0x" + Integer.toHexString(mDataTypeIconId) 755 + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId) 756 + " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId)); 757 } 758 759 // the phone icon on phones 760 if (mLastPhoneSignalIconId != mPhoneSignalIconId) { 761 mLastPhoneSignalIconId = mPhoneSignalIconId; 762 N = mPhoneSignalIconViews.size(); 763 for (int i=0; i<N; i++) { 764 final ImageView v = mPhoneSignalIconViews.get(i); 765 v.setImageResource(mPhoneSignalIconId); 766 } 767 } 768 769 // the data icon on phones 770 if (mLastDataDirectionIconId != mDataDirectionIconId) { 771 mLastDataDirectionIconId = mDataDirectionIconId; 772 N = mDataDirectionIconViews.size(); 773 for (int i=0; i<N; i++) { 774 final ImageView v = mDataDirectionIconViews.get(i); 775 v.setImageResource(mDataDirectionIconId); 776 } 777 } 778 779 // the wifi icon on phones 780 if (mLastWifiIconId != mWifiIconId) { 781 mLastWifiIconId = mWifiIconId; 782 N = mWifiIconViews.size(); 783 for (int i=0; i<N; i++) { 784 final ImageView v = mWifiIconViews.get(i); 785 v.setImageResource(mWifiIconId); 786 } 787 } 788 789 // the combined data signal icon 790 if (mLastCombinedSignalIconId != combinedSignalIconId) { 791 mLastCombinedSignalIconId = combinedSignalIconId; 792 N = mCombinedSignalIconViews.size(); 793 for (int i=0; i<N; i++) { 794 final ImageView v = mCombinedSignalIconViews.get(i); 795 v.setImageResource(combinedSignalIconId); 796 } 797 } 798 799 // the data network type overlay 800 if (mLastDataTypeIconId != dataTypeIconId) { 801 mLastDataTypeIconId = dataTypeIconId; 802 N = mDataTypeIconViews.size(); 803 for (int i=0; i<N; i++) { 804 final ImageView v = mDataTypeIconViews.get(i); 805 if (dataTypeIconId == 0) { 806 v.setVisibility(View.INVISIBLE); 807 } else { 808 v.setVisibility(View.VISIBLE); 809 v.setImageResource(dataTypeIconId); 810 } 811 } 812 } 813 814 // the data direction overlay 815 if (mLastDataDirectionOverlayIconId != dataDirectionOverlayIconId) { 816 Slog.d(TAG, "changing data overlay icon id to " + dataDirectionOverlayIconId); 817 mLastDataDirectionOverlayIconId = dataDirectionOverlayIconId; 818 N = mDataDirectionOverlayIconViews.size(); 819 for (int i=0; i<N; i++) { 820 final ImageView v = mDataDirectionOverlayIconViews.get(i); 821 if (dataDirectionOverlayIconId == 0) { 822 v.setVisibility(View.INVISIBLE); 823 } else { 824 v.setVisibility(View.VISIBLE); 825 v.setImageResource(dataDirectionOverlayIconId); 826 } 827 } 828 } 829 830 // the label in the notification panel 831 if (!mLastLabel.equals(label)) { 832 mLastLabel = label; 833 N = mLabelViews.size(); 834 for (int i=0; i<N; i++) { 835 TextView v = mLabelViews.get(i); 836 v.setText(label); 837 } 838 } 839 } 840 841 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 842 pw.println(" - telephony ------"); 843 pw.print(" mHspaDataDistinguishable="); 844 pw.println(mHspaDataDistinguishable); 845 pw.print(" mDataConnected="); 846 pw.println(mDataConnected); 847 pw.print(" mSimState="); 848 pw.println(mSimState); 849 pw.print(" mPhoneState="); 850 pw.println(mPhoneState); 851 pw.print(" mDataState="); 852 pw.println(mDataState); 853 pw.print(" mDataActivity="); 854 pw.println(mDataActivity); 855 pw.print(" mServiceState="); 856 pw.println(mServiceState.toString()); 857 pw.print(" mNetworkName="); 858 pw.println(mNetworkName); 859 pw.print(" mNetworkNameDefault="); 860 pw.println(mNetworkNameDefault); 861 pw.print(" mNetworkNameSeparator="); 862 pw.println(mNetworkNameSeparator); 863 pw.print(" mPhoneSignalIconId=0x"); 864 pw.print(Integer.toHexString(mPhoneSignalIconId)); 865 pw.print("/"); 866 pw.println(getResourceName(mPhoneSignalIconId)); 867 pw.print(" mDataDirectionIconId="); 868 pw.print(Integer.toHexString(mDataDirectionIconId)); 869 pw.print("/"); 870 pw.println(getResourceName(mDataDirectionIconId)); 871 pw.print(" mDataSignalIconId="); 872 pw.print(Integer.toHexString(mDataSignalIconId)); 873 pw.print("/"); 874 pw.println(getResourceName(mDataSignalIconId)); 875 pw.print(" mDataTypeIconId="); 876 pw.print(Integer.toHexString(mDataTypeIconId)); 877 pw.print("/"); 878 pw.println(getResourceName(mDataTypeIconId)); 879 880 pw.println(" - wifi ------"); 881 pw.print(" mWifiEnabled="); 882 pw.println(mWifiEnabled); 883 pw.print(" mWifiConnected="); 884 pw.println(mWifiConnected); 885 pw.print(" mWifiLevel="); 886 pw.println(mWifiLevel); 887 pw.print(" mWifiSsid="); 888 pw.println(mWifiSsid); 889 pw.print(" mWifiIconId="); 890 pw.println(mWifiIconId); 891 892 pw.println(" - Bluetooth ----"); 893 pw.print(" mBtReverseTethered="); 894 pw.println(mBluetoothTethered); 895 896 pw.println(" - connectivity ------"); 897 pw.print(" mInetCondition="); 898 pw.println(mInetCondition); 899 900 pw.println(" - icons ------"); 901 pw.print(" mLastPhoneSignalIconId=0x"); 902 pw.print(Integer.toHexString(mLastPhoneSignalIconId)); 903 pw.print("/"); 904 pw.println(getResourceName(mLastPhoneSignalIconId)); 905 pw.print(" mLastDataDirectionIconId=0x"); 906 pw.print(Integer.toHexString(mLastDataDirectionIconId)); 907 pw.print("/"); 908 pw.println(getResourceName(mLastDataDirectionIconId)); 909 pw.print(" mLastDataDirectionOverlayIconId=0x"); 910 pw.print(Integer.toHexString(mLastDataDirectionOverlayIconId)); 911 pw.print("/"); 912 pw.println(getResourceName(mLastDataDirectionOverlayIconId)); 913 pw.print(" mLastWifiIconId=0x"); 914 pw.print(Integer.toHexString(mLastWifiIconId)); 915 pw.print("/"); 916 pw.println(getResourceName(mLastWifiIconId)); 917 pw.print(" mLastCombinedSignalIconId=0x"); 918 pw.print(Integer.toHexString(mLastCombinedSignalIconId)); 919 pw.print("/"); 920 pw.println(getResourceName(mLastCombinedSignalIconId)); 921 pw.print(" mLastDataTypeIconId=0x"); 922 pw.print(Integer.toHexString(mLastDataTypeIconId)); 923 pw.print("/"); 924 pw.println(getResourceName(mLastCombinedSignalIconId)); 925 pw.print(" mLastLabel="); 926 pw.print(mLastLabel); 927 } 928 929 private String getResourceName(int resId) { 930 if (resId == 0) { 931 final Resources res = mContext.getResources(); 932 try { 933 return res.getResourceName(resId); 934 } catch (android.content.res.Resources.NotFoundException ex) { 935 return "(unknown)"; 936 } 937 } else { 938 return "(null)"; 939 } 940 } 941 942} 943