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