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