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