NetworkController.java revision c198bb1db8c16789a815b5fa2b393e113047bd47
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 mDataActiveSignalIconId; 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> mWifiIconViews = new ArrayList<ImageView>(); 105 ArrayList<ImageView> mCombinedSignalIconViews = new ArrayList<ImageView>(); 106 ArrayList<ImageView> mDataTypeIconViews = new ArrayList<ImageView>(); 107 ArrayList<TextView> mLabelViews = new ArrayList<TextView>(); 108 int mLastPhoneSignalIconId = -1; 109 int mLastDataDirectionIconId = -1; 110 int mLastWifiIconId = -1; 111 int mLastCombinedSignalIconId = -1; 112 int mLastDataTypeIconId = -1; 113 String mLastLabel = ""; 114 115 // yuck -- stop doing this here and put it in the framework 116 IBatteryStats mBatteryStats; 117 118 /** 119 * Construct this controller object and register for updates. 120 */ 121 public NetworkController(Context context) { 122 mContext = context; 123 124 // telephony 125 mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 126 mPhone.listen(mPhoneStateListener, 127 PhoneStateListener.LISTEN_SERVICE_STATE 128 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS 129 | PhoneStateListener.LISTEN_CALL_STATE 130 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE 131 | PhoneStateListener.LISTEN_DATA_ACTIVITY); 132 mHspaDataDistinguishable = mContext.getResources().getBoolean( 133 R.bool.config_hspa_data_distinguishable); 134 mNetworkNameSeparator = mContext.getString(R.string.status_bar_network_name_separator); 135 mNetworkNameDefault = mContext.getString( 136 com.android.internal.R.string.lockscreen_carrier_default); 137 mNetworkName = mNetworkNameDefault; 138 139 // wifi 140 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 141 142 // broadcasts 143 IntentFilter filter = new IntentFilter(); 144 filter.addAction(WifiManager.RSSI_CHANGED_ACTION); 145 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 146 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 147 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 148 filter.addAction(Telephony.Intents.SPN_STRINGS_UPDATED_ACTION); 149 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 150 filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); 151 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 152 context.registerReceiver(this, filter); 153 154 // yuck 155 mBatteryStats = BatteryStatsService.getService(); 156 } 157 158 public void addPhoneSignalIconView(ImageView v) { 159 mPhoneSignalIconViews.add(v); 160 } 161 162 public void addDataDirectionIconView(ImageView v) { 163 mDataDirectionIconViews.add(v); 164 } 165 166 public void addWifiIconView(ImageView v) { 167 mWifiIconViews.add(v); 168 } 169 170 public void addCombinedSignalIconView(ImageView v) { 171 mCombinedSignalIconViews.add(v); 172 } 173 174 public void addDataTypeIconView(ImageView v) { 175 mDataTypeIconViews.add(v); 176 } 177 178 public void addLabelView(TextView v) { 179 mLabelViews.add(v); 180 } 181 182 public void onReceive(Context context, Intent intent) { 183 final String action = intent.getAction(); 184 if (action.equals(WifiManager.RSSI_CHANGED_ACTION) 185 || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) 186 || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 187 updateWifiState(intent); 188 refreshViews(); 189 } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { 190 updateSimState(intent); 191 updateDataIcon(); 192 refreshViews(); 193 } else if (action.equals(Telephony.Intents.SPN_STRINGS_UPDATED_ACTION)) { 194 updateNetworkName(intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_SPN, false), 195 intent.getStringExtra(Telephony.Intents.EXTRA_SPN), 196 intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_PLMN, false), 197 intent.getStringExtra(Telephony.Intents.EXTRA_PLMN)); 198 refreshViews(); 199 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) || 200 action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { 201 updateConnectivity(intent); 202 refreshViews(); 203 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 204 refreshViews(); 205 } 206 } 207 208 209 // ===== Telephony ============================================================== 210 211 PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 212 @Override 213 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 214 if (DEBUG) { 215 Slog.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength); 216 } 217 mSignalStrength = signalStrength; 218 updateTelephonySignalStrength(); 219 refreshViews(); 220 } 221 222 @Override 223 public void onServiceStateChanged(ServiceState state) { 224 if (DEBUG) { 225 Slog.d(TAG, "onServiceStateChanged state=" + state.getState()); 226 } 227 mServiceState = state; 228 updateTelephonySignalStrength(); 229 updateDataIcon(); 230 refreshViews(); 231 } 232 233 @Override 234 public void onCallStateChanged(int state, String incomingNumber) { 235 if (DEBUG) { 236 Slog.d(TAG, "onCallStateChanged state=" + state); 237 } 238 // In cdma, if a voice call is made, RSSI should switch to 1x. 239 if (isCdma()) { 240 updateTelephonySignalStrength(); 241 refreshViews(); 242 } 243 } 244 245 @Override 246 public void onDataConnectionStateChanged(int state, int networkType) { 247 if (DEBUG) { 248 Slog.d(TAG, "onDataConnectionStateChanged: state=" + state 249 + " type=" + networkType); 250 } 251 mDataState = state; 252 mDataNetType = networkType; 253 updateDataNetType(); 254 updateDataIcon(); 255 refreshViews(); 256 } 257 258 @Override 259 public void onDataActivity(int direction) { 260 if (DEBUG) { 261 Slog.d(TAG, "onDataActivity: direction=" + direction); 262 } 263 mDataActivity = direction; 264 updateDataIcon(); 265 refreshViews(); 266 } 267 }; 268 269 private final void updateSimState(Intent intent) { 270 String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE); 271 if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { 272 mSimState = IccCard.State.ABSENT; 273 } 274 else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) { 275 mSimState = IccCard.State.READY; 276 } 277 else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { 278 final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON); 279 if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { 280 mSimState = IccCard.State.PIN_REQUIRED; 281 } 282 else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { 283 mSimState = IccCard.State.PUK_REQUIRED; 284 } 285 else { 286 mSimState = IccCard.State.NETWORK_LOCKED; 287 } 288 } else { 289 mSimState = IccCard.State.UNKNOWN; 290 } 291 } 292 293 private boolean isCdma() { 294 return (mSignalStrength != null) && !mSignalStrength.isGsm(); 295 } 296 297 private boolean isEvdo() { 298 return ((mServiceState != null) 299 && ((mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_0) 300 || (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_A) 301 || (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_B))); 302 } 303 304 private boolean hasService() { 305 if (mServiceState != null) { 306 switch (mServiceState.getState()) { 307 case ServiceState.STATE_OUT_OF_SERVICE: 308 case ServiceState.STATE_POWER_OFF: 309 return false; 310 default: 311 return true; 312 } 313 } else { 314 return false; 315 } 316 } 317 318 private int getCdmaLevel() { 319 if (mSignalStrength == null) return 0; 320 final int cdmaDbm = mSignalStrength.getCdmaDbm(); 321 final int cdmaEcio = mSignalStrength.getCdmaEcio(); 322 int levelDbm = 0; 323 int levelEcio = 0; 324 325 if (cdmaDbm >= -75) levelDbm = 4; 326 else if (cdmaDbm >= -85) levelDbm = 3; 327 else if (cdmaDbm >= -95) levelDbm = 2; 328 else if (cdmaDbm >= -100) levelDbm = 1; 329 else levelDbm = 0; 330 331 // Ec/Io are in dB*10 332 if (cdmaEcio >= -90) levelEcio = 4; 333 else if (cdmaEcio >= -110) levelEcio = 3; 334 else if (cdmaEcio >= -130) levelEcio = 2; 335 else if (cdmaEcio >= -150) levelEcio = 1; 336 else levelEcio = 0; 337 338 return (levelDbm < levelEcio) ? levelDbm : levelEcio; 339 } 340 341 private int getEvdoLevel() { 342 if (mSignalStrength == null) return 0; 343 int evdoDbm = mSignalStrength.getEvdoDbm(); 344 int evdoSnr = mSignalStrength.getEvdoSnr(); 345 int levelEvdoDbm = 0; 346 int levelEvdoSnr = 0; 347 348 if (evdoDbm >= -65) levelEvdoDbm = 4; 349 else if (evdoDbm >= -75) levelEvdoDbm = 3; 350 else if (evdoDbm >= -90) levelEvdoDbm = 2; 351 else if (evdoDbm >= -105) levelEvdoDbm = 1; 352 else levelEvdoDbm = 0; 353 354 if (evdoSnr >= 7) levelEvdoSnr = 4; 355 else if (evdoSnr >= 5) levelEvdoSnr = 3; 356 else if (evdoSnr >= 3) levelEvdoSnr = 2; 357 else if (evdoSnr >= 1) levelEvdoSnr = 1; 358 else levelEvdoSnr = 0; 359 360 return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr; 361 } 362 363 private final void updateTelephonySignalStrength() { 364 // Display signal strength while in "emergency calls only" mode 365 if (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly())) { 366 //Slog.d(TAG, "updateTelephonySignalStrength: no service"); 367 if (Settings.System.getInt(mContext.getContentResolver(), 368 Settings.System.AIRPLANE_MODE_ON, 0) == 1) { 369 mPhoneSignalIconId = R.drawable.stat_sys_signal_flightmode; 370 mDataActiveSignalIconId = mDataSignalIconId = R.drawable.stat_sys_signal_flightmode; 371 } else { 372 mPhoneSignalIconId = R.drawable.stat_sys_signal_null; 373 // note we use 0 instead of null 374 mDataActiveSignalIconId = mDataSignalIconId = R.drawable.stat_sys_signal_0; 375 } 376 } else { 377 if (mSignalStrength == null) { 378 mPhoneSignalIconId = R.drawable.stat_sys_signal_null; 379 // note we use 0 instead of null 380 mDataActiveSignalIconId = mDataSignalIconId = R.drawable.stat_sys_signal_0; 381 } else if (isCdma()) { 382 // If 3G(EV) and 1x network are available than 3G should be 383 // displayed, displayed RSSI should be from the EV side. 384 // If a voice call is made then RSSI should switch to 1x. 385 int iconLevel; 386 if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){ 387 iconLevel = getEvdoLevel(); 388 } else { 389 iconLevel = getCdmaLevel(); 390 } 391 int[] iconList; 392 if (isCdmaEri()) { 393 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition]; 394 } else { 395 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition]; 396 } 397 mPhoneSignalIconId = iconList[iconLevel]; 398 mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel]; 399 mDataActiveSignalIconId 400 = TelephonyIcons.DATA_SIGNAL_STRENGTH_ACTIVE[mInetCondition][iconLevel]; 401 } else { 402 int asu = mSignalStrength.getGsmSignalStrength(); 403 404 // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5 405 // asu = 0 (-113dB or less) is very weak 406 // signal, its better to show 0 bars to the user in such cases. 407 // asu = 99 is a special case, where the signal strength is unknown. 408 int iconLevel; 409 if (asu <= 2 || asu == 99) iconLevel = 0; 410 else if (asu >= 12) iconLevel = 4; 411 else if (asu >= 8) iconLevel = 3; 412 else if (asu >= 5) iconLevel = 2; 413 else iconLevel = 1; 414 415 // Though mPhone is a Manager, this call is not an IPC 416 int[] iconList; 417 if (mPhone.isNetworkRoaming()) { 418 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition]; 419 } else { 420 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition]; 421 } 422 mPhoneSignalIconId = iconList[iconLevel]; 423 mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel]; 424 mDataActiveSignalIconId 425 = TelephonyIcons.DATA_SIGNAL_STRENGTH_ACTIVE[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 dataTypeIconId; 689 String label; 690 int N; 691 692 if (mWifiConnected) { 693 if (mWifiSsid == null) { 694 label = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid); 695 } else { 696 label = mWifiSsid; 697 } 698 combinedSignalIconId = mWifiIconId; 699 dataTypeIconId = 0; 700 } else if (mDataConnected) { 701 label = mNetworkName; 702 switch (mDataActivity) { 703 case TelephonyManager.DATA_ACTIVITY_IN: 704 case TelephonyManager.DATA_ACTIVITY_OUT: 705 case TelephonyManager.DATA_ACTIVITY_INOUT: 706 combinedSignalIconId = mDataActiveSignalIconId; 707 break; 708 default: 709 combinedSignalIconId = mDataSignalIconId; 710 break; 711 } 712 dataTypeIconId = mDataTypeIconId; 713 } else if (mBluetoothTethered) { 714 label = mContext.getString(R.string.bluetooth_tethered); 715 combinedSignalIconId = mBluetoothTetherIconId; 716 dataTypeIconId = 0; 717 } else { 718 label = context.getString(R.string.status_bar_settings_signal_meter_disconnected); 719 combinedSignalIconId = mDataSignalIconId; 720 dataTypeIconId = 0; 721 } 722 723 if (false) { 724 Slog.d(TAG, "refreshViews combinedSignalIconId=0x" 725 + Integer.toHexString(combinedSignalIconId) 726 + "/" + getResourceName(combinedSignalIconId) 727 + " mDataActivity=" + mDataActivity 728 + " mPhoneSignalIconId=0x" + Integer.toHexString(mPhoneSignalIconId) 729 + " mDataDirectionIconId=0x" + Integer.toHexString(mDataDirectionIconId) 730 + " mDataSignalIconId=0x" + Integer.toHexString(mDataSignalIconId) 731 + " mDataActiveSignalIconId=0x" + Integer.toHexString(mDataActiveSignalIconId) 732 + " mDataTypeIconId=0x" + Integer.toHexString(mDataTypeIconId) 733 + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId) 734 + " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId)); 735 } 736 737 // the phone icon on phones 738 if (mLastPhoneSignalIconId != mPhoneSignalIconId) { 739 mLastPhoneSignalIconId = mPhoneSignalIconId; 740 N = mPhoneSignalIconViews.size(); 741 for (int i=0; i<N; i++) { 742 final ImageView v = mPhoneSignalIconViews.get(i); 743 v.setImageResource(mPhoneSignalIconId); 744 } 745 } 746 747 // the data icon on phones 748 if (mLastDataDirectionIconId != mDataDirectionIconId) { 749 mLastDataDirectionIconId = mDataDirectionIconId; 750 N = mDataDirectionIconViews.size(); 751 for (int i=0; i<N; i++) { 752 final ImageView v = mDataDirectionIconViews.get(i); 753 v.setImageResource(mDataDirectionIconId); 754 } 755 } 756 757 // the wifi icon on phones 758 if (mLastWifiIconId != mWifiIconId) { 759 mLastWifiIconId = mWifiIconId; 760 N = mWifiIconViews.size(); 761 for (int i=0; i<N; i++) { 762 final ImageView v = mWifiIconViews.get(i); 763 v.setImageResource(mWifiIconId); 764 } 765 } 766 767 // the combined data signal icon 768 if (mLastCombinedSignalIconId != combinedSignalIconId) { 769 mLastCombinedSignalIconId = combinedSignalIconId; 770 N = mCombinedSignalIconViews.size(); 771 for (int i=0; i<N; i++) { 772 final ImageView v = mCombinedSignalIconViews.get(i); 773 v.setImageResource(combinedSignalIconId); 774 } 775 } 776 777 // the data network type overlay 778 if (mLastDataTypeIconId != dataTypeIconId) { 779 mLastDataTypeIconId = dataTypeIconId; 780 N = mDataTypeIconViews.size(); 781 for (int i=0; i<N; i++) { 782 final ImageView v = mDataTypeIconViews.get(i); 783 if (dataTypeIconId == 0) { 784 v.setVisibility(View.INVISIBLE); 785 } else { 786 v.setVisibility(View.VISIBLE); 787 v.setImageResource(dataTypeIconId); 788 } 789 } 790 } 791 792 // the label in the notification panel 793 if (!mLastLabel.equals(label)) { 794 mLastLabel = label; 795 N = mLabelViews.size(); 796 for (int i=0; i<N; i++) { 797 TextView v = mLabelViews.get(i); 798 v.setText(label); 799 } 800 } 801 } 802 803 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 804 pw.println(" - telephony ------"); 805 pw.print(" mHspaDataDistinguishable="); 806 pw.println(mHspaDataDistinguishable); 807 pw.print(" mDataConnected="); 808 pw.println(mDataConnected); 809 pw.print(" mSimState="); 810 pw.println(mSimState); 811 pw.print(" mPhoneState="); 812 pw.println(mPhoneState); 813 pw.print(" mDataState="); 814 pw.println(mDataState); 815 pw.print(" mDataActivity="); 816 pw.println(mDataActivity); 817 pw.print(" mServiceState="); 818 pw.println(mServiceState.toString()); 819 pw.print(" mNetworkName="); 820 pw.println(mNetworkName); 821 pw.print(" mNetworkNameDefault="); 822 pw.println(mNetworkNameDefault); 823 pw.print(" mNetworkNameSeparator="); 824 pw.println(mNetworkNameSeparator); 825 pw.print(" mPhoneSignalIconId=0x"); 826 pw.print(Integer.toHexString(mPhoneSignalIconId)); 827 pw.print("/"); 828 pw.println(getResourceName(mPhoneSignalIconId)); 829 pw.print(" mDataDirectionIconId="); 830 pw.print(Integer.toHexString(mDataDirectionIconId)); 831 pw.print("/"); 832 pw.println(getResourceName(mDataDirectionIconId)); 833 pw.print(" mDataSignalIconId="); 834 pw.print(Integer.toHexString(mDataSignalIconId)); 835 pw.print("/"); 836 pw.println(getResourceName(mDataSignalIconId)); 837 pw.print(" mDataActiveSignalIconId="); 838 pw.print(Integer.toHexString(mDataActiveSignalIconId)); 839 pw.print("/"); 840 pw.println(getResourceName(mDataActiveSignalIconId)); 841 pw.print(" mDataTypeIconId="); 842 pw.print(Integer.toHexString(mDataTypeIconId)); 843 pw.print("/"); 844 pw.println(getResourceName(mDataTypeIconId)); 845 846 pw.println(" - wifi ------"); 847 pw.print(" mWifiEnabled="); 848 pw.println(mWifiEnabled); 849 pw.print(" mWifiConnected="); 850 pw.println(mWifiConnected); 851 pw.print(" mWifiLevel="); 852 pw.println(mWifiLevel); 853 pw.print(" mWifiSsid="); 854 pw.println(mWifiSsid); 855 pw.print(" mWifiIconId="); 856 pw.println(mWifiIconId); 857 858 pw.println(" - Bluetooth ----"); 859 pw.print(" mBtReverseTethered="); 860 pw.println(mBluetoothTethered); 861 862 pw.println(" - connectivity ------"); 863 pw.print(" mInetCondition="); 864 pw.println(mInetCondition); 865 866 pw.println(" - icons ------"); 867 pw.print(" mLastPhoneSignalIconId=0x"); 868 pw.print(Integer.toHexString(mLastPhoneSignalIconId)); 869 pw.print("/"); 870 pw.println(getResourceName(mLastPhoneSignalIconId)); 871 pw.print(" mLastDataDirectionIconId=0x"); 872 pw.print(Integer.toHexString(mLastDataDirectionIconId)); 873 pw.print("/"); 874 pw.println(getResourceName(mLastDataDirectionIconId)); 875 pw.print(" mLastWifiIconId=0x"); 876 pw.print(Integer.toHexString(mLastWifiIconId)); 877 pw.print("/"); 878 pw.println(getResourceName(mLastWifiIconId)); 879 pw.print(" mLastCombinedSignalIconId=0x"); 880 pw.print(Integer.toHexString(mLastCombinedSignalIconId)); 881 pw.print("/"); 882 pw.println(getResourceName(mLastCombinedSignalIconId)); 883 pw.print(" mLastDataTypeIconId=0x"); 884 pw.print(Integer.toHexString(mLastDataTypeIconId)); 885 pw.print("/"); 886 pw.println(getResourceName(mLastCombinedSignalIconId)); 887 pw.print(" mLastLabel="); 888 pw.print(mLastLabel); 889 } 890 891 private String getResourceName(int resId) { 892 if (resId == 0) { 893 final Resources res = mContext.getResources(); 894 try { 895 return res.getResourceName(resId); 896 } catch (android.content.res.Resources.NotFoundException ex) { 897 return "(unknown)"; 898 } 899 } else { 900 return "(null)"; 901 } 902 } 903 904} 905