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