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