NetworkController.java revision fab337648df339b1a1fea4fa97d8217760435d56
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.Handler; 37import android.os.HandlerThread; 38import android.os.Looper; 39import android.os.Message; 40import android.os.Messenger; 41import android.os.RemoteException; 42import android.os.SystemProperties; 43import android.provider.Settings; 44import android.provider.Telephony; 45import android.telephony.PhoneStateListener; 46import android.telephony.ServiceState; 47import android.telephony.SignalStrength; 48import android.telephony.TelephonyManager; 49import android.util.Slog; 50import android.view.View; 51import android.widget.ImageView; 52import android.widget.TextView; 53 54import com.android.internal.app.IBatteryStats; 55import com.android.internal.telephony.IccCard; 56import com.android.internal.telephony.TelephonyIntents; 57import com.android.internal.telephony.cdma.EriInfo; 58import com.android.server.am.BatteryStatsService; 59import com.android.internal.util.AsyncChannel; 60 61import com.android.systemui.R; 62 63public class NetworkController extends BroadcastReceiver { 64 // debug 65 static final String TAG = "StatusBar.NetworkController"; 66 static final boolean DEBUG = false; 67 68 // telephony 69 boolean mHspaDataDistinguishable; 70 final TelephonyManager mPhone; 71 boolean mDataConnected; 72 IccCard.State mSimState = IccCard.State.READY; 73 int mPhoneState = TelephonyManager.CALL_STATE_IDLE; 74 int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 75 int mDataState = TelephonyManager.DATA_DISCONNECTED; 76 int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; 77 ServiceState mServiceState; 78 SignalStrength mSignalStrength; 79 int[] mDataIconList = TelephonyIcons.DATA_G[0]; 80 String mNetworkName; 81 String mNetworkNameDefault; 82 String mNetworkNameSeparator; 83 int mPhoneSignalIconId; 84 int mDataDirectionIconId; 85 int mDataDirectionOverlayIconId; 86 int mDataSignalIconId; 87 int mDataTypeIconId; 88 boolean mDataActive; 89 90 // wifi 91 final WifiManager mWifiManager; 92 AsyncChannel mWifiChannel; 93 boolean mWifiEnabled, mWifiConnected; 94 int mWifiLevel; 95 String mWifiSsid; 96 int mWifiIconId = 0; 97 98 // bluetooth 99 private boolean mBluetoothTethered = false; 100 private int mBluetoothTetherIconId = 101 com.android.internal.R.drawable.stat_sys_tether_bluetooth; 102 103 // data connectivity (regardless of state, can we access the internet?) 104 // state of inet connection - 0 not connected, 100 connected 105 private int mInetCondition = 0; 106 private static final int INET_CONDITION_THRESHOLD = 50; 107 108 // our ui 109 Context mContext; 110 ArrayList<ImageView> mPhoneSignalIconViews = new ArrayList<ImageView>(); 111 ArrayList<ImageView> mDataDirectionIconViews = new ArrayList<ImageView>(); 112 ArrayList<ImageView> mDataDirectionOverlayIconViews = new ArrayList<ImageView>(); 113 ArrayList<ImageView> mWifiIconViews = new ArrayList<ImageView>(); 114 ArrayList<ImageView> mCombinedSignalIconViews = new ArrayList<ImageView>(); 115 ArrayList<ImageView> mDataTypeIconViews = new ArrayList<ImageView>(); 116 ArrayList<TextView> mLabelViews = new ArrayList<TextView>(); 117 int mLastPhoneSignalIconId = -1; 118 int mLastDataDirectionIconId = -1; 119 int mLastDataDirectionOverlayIconId = -1; 120 int mLastWifiIconId = -1; 121 int mLastCombinedSignalIconId = -1; 122 int mLastDataTypeIconId = -1; 123 String mLastLabel = ""; 124 125 // yuck -- stop doing this here and put it in the framework 126 IBatteryStats mBatteryStats; 127 128 /** 129 * Construct this controller object and register for updates. 130 */ 131 public NetworkController(Context context) { 132 mContext = context; 133 134 // set up the default wifi icon, used when no radios have ever appeared 135 updateWifiIcons(); 136 137 // telephony 138 mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 139 mPhone.listen(mPhoneStateListener, 140 PhoneStateListener.LISTEN_SERVICE_STATE 141 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS 142 | PhoneStateListener.LISTEN_CALL_STATE 143 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE 144 | PhoneStateListener.LISTEN_DATA_ACTIVITY); 145 mHspaDataDistinguishable = mContext.getResources().getBoolean( 146 R.bool.config_hspa_data_distinguishable); 147 mNetworkNameSeparator = mContext.getString(R.string.status_bar_network_name_separator); 148 mNetworkNameDefault = mContext.getString( 149 com.android.internal.R.string.lockscreen_carrier_default); 150 mNetworkName = mNetworkNameDefault; 151 152 // wifi 153 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 154 HandlerThread handlerThread = new HandlerThread("WifiServiceThread"); 155 handlerThread.start(); 156 Handler handler = new WifiHandler(handlerThread.getLooper()); 157 mWifiChannel = new AsyncChannel(); 158 Messenger wifiMessenger = mWifiManager.getMessenger(); 159 if (wifiMessenger != null) { 160 mWifiChannel.connect(mContext, handler, wifiMessenger); 161 } 162 163 // broadcasts 164 IntentFilter filter = new IntentFilter(); 165 filter.addAction(WifiManager.RSSI_CHANGED_ACTION); 166 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 167 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 168 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 169 filter.addAction(Telephony.Intents.SPN_STRINGS_UPDATED_ACTION); 170 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 171 filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); 172 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 173 context.registerReceiver(this, filter); 174 175 // yuck 176 mBatteryStats = BatteryStatsService.getService(); 177 } 178 179 public void addPhoneSignalIconView(ImageView v) { 180 mPhoneSignalIconViews.add(v); 181 } 182 183 public void addDataDirectionIconView(ImageView v) { 184 mDataDirectionIconViews.add(v); 185 } 186 187 public void addDataDirectionOverlayIconView(ImageView v) { 188 mDataDirectionOverlayIconViews.add(v); 189 } 190 191 public void addWifiIconView(ImageView v) { 192 mWifiIconViews.add(v); 193 } 194 195 public void addCombinedSignalIconView(ImageView v) { 196 mCombinedSignalIconViews.add(v); 197 } 198 199 public void addDataTypeIconView(ImageView v) { 200 mDataTypeIconViews.add(v); 201 } 202 203 public void addLabelView(TextView v) { 204 mLabelViews.add(v); 205 } 206 207 @Override 208 public void onReceive(Context context, Intent intent) { 209 final String action = intent.getAction(); 210 if (action.equals(WifiManager.RSSI_CHANGED_ACTION) 211 || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) 212 || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 213 updateWifiState(intent); 214 refreshViews(); 215 } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { 216 updateSimState(intent); 217 updateDataIcon(); 218 refreshViews(); 219 } else if (action.equals(Telephony.Intents.SPN_STRINGS_UPDATED_ACTION)) { 220 updateNetworkName(intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_SPN, false), 221 intent.getStringExtra(Telephony.Intents.EXTRA_SPN), 222 intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_PLMN, false), 223 intent.getStringExtra(Telephony.Intents.EXTRA_PLMN)); 224 refreshViews(); 225 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) || 226 action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { 227 updateConnectivity(intent); 228 refreshViews(); 229 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 230 refreshViews(); 231 } 232 } 233 234 235 // ===== Telephony ============================================================== 236 237 PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 238 @Override 239 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 240 if (DEBUG) { 241 Slog.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength); 242 } 243 mSignalStrength = signalStrength; 244 updateTelephonySignalStrength(); 245 refreshViews(); 246 } 247 248 @Override 249 public void onServiceStateChanged(ServiceState state) { 250 if (DEBUG) { 251 Slog.d(TAG, "onServiceStateChanged state=" + state.getState()); 252 } 253 mServiceState = state; 254 updateTelephonySignalStrength(); 255 updateDataIcon(); 256 refreshViews(); 257 } 258 259 @Override 260 public void onCallStateChanged(int state, String incomingNumber) { 261 if (DEBUG) { 262 Slog.d(TAG, "onCallStateChanged state=" + state); 263 } 264 // In cdma, if a voice call is made, RSSI should switch to 1x. 265 if (isCdma()) { 266 updateTelephonySignalStrength(); 267 refreshViews(); 268 } 269 } 270 271 @Override 272 public void onDataConnectionStateChanged(int state, int networkType) { 273 if (DEBUG) { 274 Slog.d(TAG, "onDataConnectionStateChanged: state=" + state 275 + " type=" + networkType); 276 } 277 mDataState = state; 278 mDataNetType = networkType; 279 if (state < 0) { 280 // device without a data connection 281 mSignalStrength = null; 282 } 283 updateDataNetType(); 284 updateDataIcon(); 285 refreshViews(); 286 } 287 288 @Override 289 public void onDataActivity(int direction) { 290 if (DEBUG) { 291 Slog.d(TAG, "onDataActivity: direction=" + direction); 292 } 293 mDataActivity = direction; 294 updateDataIcon(); 295 refreshViews(); 296 } 297 }; 298 299 private final void updateSimState(Intent intent) { 300 String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE); 301 if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { 302 mSimState = IccCard.State.ABSENT; 303 } 304 else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) { 305 mSimState = IccCard.State.READY; 306 } 307 else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { 308 final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON); 309 if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { 310 mSimState = IccCard.State.PIN_REQUIRED; 311 } 312 else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { 313 mSimState = IccCard.State.PUK_REQUIRED; 314 } 315 else { 316 mSimState = IccCard.State.NETWORK_LOCKED; 317 } 318 } else { 319 mSimState = IccCard.State.UNKNOWN; 320 } 321 } 322 323 private boolean isCdma() { 324 return (mSignalStrength != null) && !mSignalStrength.isGsm(); 325 } 326 327 private boolean hasService() { 328 if (mServiceState != null) { 329 switch (mServiceState.getState()) { 330 case ServiceState.STATE_OUT_OF_SERVICE: 331 case ServiceState.STATE_POWER_OFF: 332 return false; 333 default: 334 return true; 335 } 336 } else { 337 return false; 338 } 339 } 340 341 private boolean hasMobileDataFeature() { 342 // XXX: HAX: replace when a more reliable method is available 343 return (! "wifi-only".equals(SystemProperties.get("ro.carrier"))); 344 } 345 346 private final void updateTelephonySignalStrength() { 347 // Display signal strength while in "emergency calls only" mode 348 if (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly())) { 349 //Slog.d(TAG, "updateTelephonySignalStrength: no service"); 350 if (Settings.System.getInt(mContext.getContentResolver(), 351 Settings.System.AIRPLANE_MODE_ON, 0) == 1) { 352 mPhoneSignalIconId = R.drawable.stat_sys_signal_flightmode; 353 mDataSignalIconId = R.drawable.stat_sys_signal_flightmode; 354 } else { 355 mPhoneSignalIconId = R.drawable.stat_sys_signal_null; 356 mDataSignalIconId = R.drawable.stat_sys_signal_0; // note we use 0 instead of null 357 } 358 } else { 359 if (mSignalStrength == null) { 360 mPhoneSignalIconId = R.drawable.stat_sys_signal_null; 361 mDataSignalIconId = R.drawable.stat_sys_signal_0; // note we use 0 instead of null 362 } else { 363 int iconLevel; 364 int[] iconList; 365 iconLevel = mSignalStrength.getLevel(); 366 if (isCdma()) { 367 if (isCdmaEri()) { 368 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition]; 369 } else { 370 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition]; 371 } 372 } else { 373 // Though mPhone is a Manager, this call is not an IPC 374 if (mPhone.isNetworkRoaming()) { 375 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition]; 376 } else { 377 iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition]; 378 } 379 } 380 mPhoneSignalIconId = iconList[iconLevel]; 381 mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel]; 382 } 383 } 384 } 385 386 private final void updateDataNetType() { 387 switch (mDataNetType) { 388 case TelephonyManager.NETWORK_TYPE_UNKNOWN: 389 mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; 390 mDataTypeIconId = 0; 391 break; 392 case TelephonyManager.NETWORK_TYPE_EDGE: 393 mDataIconList = TelephonyIcons.DATA_E[mInetCondition]; 394 mDataTypeIconId = R.drawable.stat_sys_signal_edge; 395 break; 396 case TelephonyManager.NETWORK_TYPE_UMTS: 397 mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; 398 mDataTypeIconId = R.drawable.stat_sys_signal_3g; 399 break; 400 case TelephonyManager.NETWORK_TYPE_HSDPA: 401 case TelephonyManager.NETWORK_TYPE_HSUPA: 402 case TelephonyManager.NETWORK_TYPE_HSPA: 403 if (mHspaDataDistinguishable) { 404 mDataIconList = TelephonyIcons.DATA_H[mInetCondition]; 405 mDataTypeIconId = R.drawable.stat_sys_signal_hsdpa; 406 } else { 407 mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; 408 mDataTypeIconId = R.drawable.stat_sys_signal_3g; 409 } 410 break; 411 case TelephonyManager.NETWORK_TYPE_CDMA: 412 // display 1xRTT for IS95A/B 413 mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; 414 mDataTypeIconId = R.drawable.stat_sys_signal_1x; 415 break; 416 case TelephonyManager.NETWORK_TYPE_1xRTT: 417 mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; 418 mDataTypeIconId = R.drawable.stat_sys_signal_1x; 419 break; 420 case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through 421 case TelephonyManager.NETWORK_TYPE_EVDO_A: 422 case TelephonyManager.NETWORK_TYPE_EVDO_B: 423 case TelephonyManager.NETWORK_TYPE_EHRPD: 424 mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; 425 mDataTypeIconId = R.drawable.stat_sys_signal_3g; 426 break; 427 case TelephonyManager.NETWORK_TYPE_LTE: 428 mDataIconList = TelephonyIcons.DATA_4G[mInetCondition]; 429 mDataTypeIconId = R.drawable.stat_sys_signal_4g; 430 break; 431 default: 432 mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; 433 mDataTypeIconId = R.drawable.stat_sys_signal_gprs; 434 break; 435 } 436 if ((isCdma() && isCdmaEri()) || mPhone.isNetworkRoaming()) { 437 mDataTypeIconId = R.drawable.stat_sys_signal_roam; 438 } 439 } 440 441 boolean isCdmaEri() { 442 final int iconIndex = mServiceState.getCdmaEriIconIndex(); 443 if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) { 444 final int iconMode = mServiceState.getCdmaEriIconMode(); 445 if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL 446 || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) { 447 return true; 448 } 449 } 450 return false; 451 } 452 453 private final void updateDataIcon() { 454 int iconId; 455 boolean visible = true; 456 457 if (!isCdma()) { 458 // GSM case, we have to check also the sim state 459 if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) { 460 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) { 461 switch (mDataActivity) { 462 case TelephonyManager.DATA_ACTIVITY_IN: 463 iconId = mDataIconList[1]; 464 break; 465 case TelephonyManager.DATA_ACTIVITY_OUT: 466 iconId = mDataIconList[2]; 467 break; 468 case TelephonyManager.DATA_ACTIVITY_INOUT: 469 iconId = mDataIconList[3]; 470 break; 471 default: 472 iconId = mDataIconList[0]; 473 break; 474 } 475 mDataDirectionIconId = iconId; 476 } else { 477 iconId = 0; 478 visible = false; 479 } 480 } else { 481 iconId = R.drawable.stat_sys_no_sim; 482 } 483 } else { 484 // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT 485 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) { 486 switch (mDataActivity) { 487 case TelephonyManager.DATA_ACTIVITY_IN: 488 iconId = mDataIconList[1]; 489 break; 490 case TelephonyManager.DATA_ACTIVITY_OUT: 491 iconId = mDataIconList[2]; 492 break; 493 case TelephonyManager.DATA_ACTIVITY_INOUT: 494 iconId = mDataIconList[3]; 495 break; 496 case TelephonyManager.DATA_ACTIVITY_DORMANT: 497 default: 498 iconId = mDataIconList[0]; 499 break; 500 } 501 } else { 502 iconId = 0; 503 visible = false; 504 } 505 } 506 507 // yuck - this should NOT be done by the status bar 508 long ident = Binder.clearCallingIdentity(); 509 try { 510 mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible); 511 } catch (RemoteException e) { 512 } finally { 513 Binder.restoreCallingIdentity(ident); 514 } 515 516 mDataDirectionIconId = iconId; 517 mDataConnected = visible; 518 } 519 520 void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) { 521 if (false) { 522 Slog.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn 523 + " showPlmn=" + showPlmn + " plmn=" + plmn); 524 } 525 StringBuilder str = new StringBuilder(); 526 boolean something = false; 527 if (showPlmn && plmn != null) { 528 str.append(plmn); 529 something = true; 530 } 531 if (showSpn && spn != null) { 532 if (something) { 533 str.append(mNetworkNameSeparator); 534 } 535 str.append(spn); 536 something = true; 537 } 538 if (something) { 539 mNetworkName = str.toString(); 540 } else { 541 mNetworkName = mNetworkNameDefault; 542 } 543 } 544 545 // ===== Wifi =================================================================== 546 547 class WifiHandler extends Handler { 548 549 WifiHandler(Looper looper) { 550 super(looper); 551 } 552 553 @Override 554 public void handleMessage(Message msg) { 555 switch (msg.what) { 556 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 557 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 558 mWifiChannel.sendMessage(Message.obtain(this, 559 AsyncChannel.CMD_CHANNEL_FULL_CONNECTION)); 560 } else { 561 Slog.e(TAG, "Failed to connect to wifi"); 562 } 563 break; 564 case WifiManager.DATA_ACTIVITY_NOTIFICATION: 565 int dataActivity = msg.arg1; 566 /* TODO: update icons based on data activity */ 567 switch (dataActivity) { 568 case WifiManager.DATA_ACTIVITY_IN: 569 break; 570 case WifiManager.DATA_ACTIVITY_OUT: 571 break; 572 case WifiManager.DATA_ACTIVITY_INOUT: 573 break; 574 case WifiManager.DATA_ACTIVITY_NONE: 575 break; 576 } 577 break; 578 default: 579 //Ignore 580 break; 581 } 582 } 583 } 584 585 private void updateWifiState(Intent intent) { 586 final String action = intent.getAction(); 587 if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 588 mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 589 WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; 590 591 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 592 final NetworkInfo networkInfo = (NetworkInfo) 593 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 594 boolean wasConnected = mWifiConnected; 595 mWifiConnected = networkInfo != null && networkInfo.isConnected(); 596 // If we just connected, grab the inintial signal strength and ssid 597 if (mWifiConnected && !wasConnected) { 598 WifiInfo info = mWifiManager.getConnectionInfo(); 599 if (info != null) { 600 mWifiLevel = WifiManager.calculateSignalLevel(info.getRssi(), 601 WifiIcons.WIFI_LEVEL_COUNT); 602 mWifiSsid = huntForSsid(info); 603 } else { 604 mWifiLevel = 0; 605 mWifiSsid = null; 606 } 607 } else if (!mWifiConnected) { 608 mWifiLevel = 0; 609 mWifiSsid = null; 610 } 611 612 } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { 613 if (mWifiConnected) { 614 final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200); 615 mWifiLevel = WifiManager.calculateSignalLevel(newRssi, WifiIcons.WIFI_LEVEL_COUNT); 616 } 617 } 618 619 updateWifiIcons(); 620 } 621 622 private void updateWifiIcons() { 623 if (mWifiConnected) { 624 mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel]; 625 } else { 626 mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]; 627 } 628 } 629 630 private String huntForSsid(WifiInfo info) { 631 String ssid = info.getSSID(); 632 if (ssid != null) { 633 return ssid; 634 } 635 // OK, it's not in the connectionInfo; we have to go hunting for it 636 List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks(); 637 for (WifiConfiguration net : networks) { 638 if (net.networkId == info.getNetworkId()) { 639 return net.SSID; 640 } 641 } 642 return null; 643 } 644 645 646 // ===== Full or limited Internet connectivity ================================== 647 648 private void updateConnectivity(Intent intent) { 649 NetworkInfo info = (NetworkInfo)(intent.getParcelableExtra( 650 ConnectivityManager.EXTRA_NETWORK_INFO)); 651 int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0); 652 653 int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0); 654 655 switch (info.getType()) { 656 case ConnectivityManager.TYPE_MOBILE: 657 mInetCondition = inetCondition; 658 updateDataNetType(); 659 updateDataIcon(); 660 updateTelephonySignalStrength(); // apply any change in connectionStatus 661 break; 662 case ConnectivityManager.TYPE_WIFI: 663 mInetCondition = inetCondition; 664 updateWifiIcons(); 665 break; 666 case ConnectivityManager.TYPE_BLUETOOTH: 667 mInetCondition = inetCondition; 668 if (info != null) { 669 mBluetoothTethered = info.isConnected() ? true: false; 670 } else { 671 mBluetoothTethered = false; 672 } 673 break; 674 } 675 } 676 677 678 // ===== Update the views ======================================================= 679 680 // figure out what to show- there should be one connected network or nothing 681 // General order of preference is: wifi, 3G than bluetooth. This might vary by product. 682 void refreshViews() { 683 Context context = mContext; 684 685 int combinedSignalIconId; 686 int dataDirectionOverlayIconId = 0; 687 int dataTypeIconId; 688 String label; 689 int N; 690 691 if (mWifiConnected) { 692 if (mWifiSsid == null) { 693 label = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid); 694 } else { 695 label = mWifiSsid; 696 } 697 combinedSignalIconId = mWifiIconId; 698 dataTypeIconId = 0; 699 } else if (mDataConnected) { 700 label = mNetworkName; 701 combinedSignalIconId = mDataSignalIconId; 702 switch (mDataActivity) { 703 case TelephonyManager.DATA_ACTIVITY_IN: 704 dataDirectionOverlayIconId = R.drawable.stat_sys_signal_in; 705 break; 706 case TelephonyManager.DATA_ACTIVITY_OUT: 707 dataDirectionOverlayIconId = R.drawable.stat_sys_signal_out; 708 break; 709 case TelephonyManager.DATA_ACTIVITY_INOUT: 710 dataDirectionOverlayIconId = R.drawable.stat_sys_signal_inout; 711 break; 712 default: 713 dataDirectionOverlayIconId = 0; 714 break; 715 } 716 combinedSignalIconId = mDataSignalIconId; 717 dataTypeIconId = mDataTypeIconId; 718 } else if (mBluetoothTethered) { 719 label = mContext.getString(R.string.bluetooth_tethered); 720 combinedSignalIconId = mBluetoothTetherIconId; 721 dataTypeIconId = 0; 722 } else { 723 label = context.getString(R.string.status_bar_settings_signal_meter_disconnected); 724 // On devices without mobile radios, we want to show the wifi icon 725 combinedSignalIconId = 726 hasMobileDataFeature() ? mDataSignalIconId : mWifiIconId; 727 dataTypeIconId = 0; 728 } 729 730 if (DEBUG) { 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