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