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