WifiStateMachine.java revision 06636d2de935ad5d2e8fb6483c406fe922c75ff2
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.server.wifi; 18 19import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; 20import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; 21import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; 22import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING; 23import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; 24import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; 25import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING; 26import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; 27import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING; 28import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN; 29 30import android.Manifest; 31import android.app.ActivityManager; 32import android.app.AlarmManager; 33import android.app.PendingIntent; 34import android.bluetooth.BluetoothAdapter; 35import android.content.BroadcastReceiver; 36import android.content.Context; 37import android.content.Intent; 38import android.content.IntentFilter; 39import android.content.pm.ApplicationInfo; 40import android.content.pm.IPackageManager; 41import android.content.pm.PackageManager; 42import android.database.ContentObserver; 43import android.net.ConnectivityManager; 44import android.net.DhcpResults; 45import android.net.LinkProperties; 46import android.net.Network; 47import android.net.NetworkAgent; 48import android.net.NetworkCapabilities; 49import android.net.NetworkFactory; 50import android.net.NetworkInfo; 51import android.net.NetworkInfo.DetailedState; 52import android.net.NetworkMisc; 53import android.net.NetworkRequest; 54import android.net.NetworkUtils; 55import android.net.RouteInfo; 56import android.net.StaticIpConfiguration; 57import android.net.dhcp.DhcpClient; 58import android.net.ip.IpManager; 59import android.net.wifi.PasspointManagementObjectDefinition; 60import android.net.wifi.RssiPacketCountInfo; 61import android.net.wifi.ScanResult; 62import android.net.wifi.ScanSettings; 63import android.net.wifi.SupplicantState; 64import android.net.wifi.WifiChannel; 65import android.net.wifi.WifiConfiguration; 66import android.net.wifi.WifiConnectionStatistics; 67import android.net.wifi.WifiEnterpriseConfig; 68import android.net.wifi.WifiInfo; 69import android.net.wifi.WifiLinkLayerStats; 70import android.net.wifi.WifiManager; 71import android.net.wifi.WifiScanner; 72import android.net.wifi.WifiSsid; 73import android.net.wifi.WpsInfo; 74import android.net.wifi.WpsResult; 75import android.net.wifi.WpsResult.Status; 76import android.net.wifi.p2p.IWifiP2pManager; 77import android.os.BatteryStats; 78import android.os.Binder; 79import android.os.Bundle; 80import android.os.IBinder; 81import android.os.INetworkManagementService; 82import android.os.Looper; 83import android.os.Message; 84import android.os.Messenger; 85import android.os.PowerManager; 86import android.os.Process; 87import android.os.RemoteException; 88import android.os.SystemClock; 89import android.os.SystemProperties; 90import android.os.UserHandle; 91import android.os.UserManager; 92import android.os.WorkSource; 93import android.provider.Settings; 94import android.security.KeyStore; 95import android.telephony.TelephonyManager; 96import android.text.TextUtils; 97import android.util.Log; 98import android.util.SparseArray; 99 100import com.android.internal.R; 101import com.android.internal.app.IBatteryStats; 102import com.android.internal.util.AsyncChannel; 103import com.android.internal.util.MessageUtils; 104import com.android.internal.util.Protocol; 105import com.android.internal.util.State; 106import com.android.internal.util.StateMachine; 107import com.android.server.connectivity.KeepalivePacketData; 108import com.android.server.wifi.hotspot2.IconEvent; 109import com.android.server.wifi.hotspot2.NetworkDetail; 110import com.android.server.wifi.hotspot2.Utils; 111import com.android.server.wifi.p2p.WifiP2pServiceImpl; 112 113import java.io.BufferedReader; 114import java.io.FileDescriptor; 115import java.io.FileNotFoundException; 116import java.io.FileReader; 117import java.io.IOException; 118import java.io.PrintWriter; 119import java.net.Inet4Address; 120import java.net.InetAddress; 121import java.util.ArrayList; 122import java.util.Arrays; 123import java.util.Calendar; 124import java.util.HashSet; 125import java.util.LinkedList; 126import java.util.List; 127import java.util.Queue; 128import java.util.Random; 129import java.util.Set; 130import java.util.concurrent.atomic.AtomicBoolean; 131import java.util.concurrent.atomic.AtomicInteger; 132 133/** 134 * TODO: 135 * Deprecate WIFI_STATE_UNKNOWN 136 */ 137 138/** 139 * Track the state of Wifi connectivity. All event handling is done here, 140 * and all changes in connectivity state are initiated here. 141 * 142 * Wi-Fi now supports three modes of operation: Client, SoftAp and p2p 143 * In the current implementation, we support concurrent wifi p2p and wifi operation. 144 * The WifiStateMachine handles SoftAp and Client operations while WifiP2pService 145 * handles p2p operation. 146 * 147 * @hide 148 */ 149public class WifiStateMachine extends StateMachine implements WifiNative.WifiRssiEventHandler { 150 151 private static final String NETWORKTYPE = "WIFI"; 152 private static final String NETWORKTYPE_UNTRUSTED = "WIFI_UT"; 153 private static boolean DBG = false; 154 private static boolean USE_PAUSE_SCANS = false; 155 private static final String TAG = "WifiStateMachine"; 156 157 private static final int ONE_HOUR_MILLI = 1000 * 60 * 60; 158 159 private static final String GOOGLE_OUI = "DA-A1-19"; 160 161 private int mVerboseLoggingLevel = 0; 162 /* debug flag, indicating if handling of ASSOCIATION_REJECT ended up blacklisting 163 * the corresponding BSSID. 164 */ 165 private boolean didBlackListBSSID = false; 166 167 /** 168 * Log with error attribute 169 * 170 * @param s is string log 171 */ 172 protected void loge(String s) { 173 Log.e(getName(), s); 174 } 175 protected void logd(String s) { 176 Log.d(getName(), s); 177 } 178 protected void log(String s) {; 179 Log.d(getName(), s); 180 } 181 182 private WifiMetrics mWifiMetrics; 183 private WifiMonitor mWifiMonitor; 184 private WifiNative mWifiNative; 185 private WifiConfigManager mWifiConfigManager; 186 private WifiConnectivityManager mWifiConnectivityManager; 187 private WifiQualifiedNetworkSelector mWifiQualifiedNetworkSelector; 188 private INetworkManagementService mNwService; 189 private ConnectivityManager mCm; 190 private BaseWifiLogger mWifiLogger; 191 private WifiApConfigStore mWifiApConfigStore; 192 private final boolean mP2pSupported; 193 private final AtomicBoolean mP2pConnected = new AtomicBoolean(false); 194 private boolean mTemporarilyDisconnectWifi = false; 195 private final String mPrimaryDeviceType; 196 private final Clock mClock = new Clock(); 197 private final WifiCountryCode mCountryCode; 198 199 /* Scan results handling */ 200 private List<ScanDetail> mScanResults = new ArrayList<>(); 201 private final Object mScanResultsLock = new Object(); 202 203 // For debug, number of known scan results that were found as part of last scan result event, 204 // as well the number of scans results returned by the supplicant with that message 205 private int mNumScanResultsKnown; 206 private int mNumScanResultsReturned; 207 208 private boolean mScreenOn = false; 209 210 /* Chipset supports background scan */ 211 private final boolean mBackgroundScanSupported; 212 213 private final String mInterfaceName; 214 /* Tethering interface could be separate from wlan interface */ 215 private String mTetherInterfaceName; 216 217 private int mLastSignalLevel = -1; 218 private String mLastBssid; 219 private int mLastNetworkId; // The network Id we successfully joined 220 private ScanDetail mActiveScanDetail; // ScanDetail associated with active network 221 private boolean linkDebouncing = false; 222 223 @Override 224 public void onRssiThresholdBreached(byte curRssi) { 225 if (DBG) { 226 Log.e(TAG, "onRssiThresholdBreach event. Cur Rssi = " + curRssi); 227 } 228 sendMessage(CMD_RSSI_THRESHOLD_BREACH, curRssi); 229 } 230 231 public void processRssiThreshold(byte curRssi, int reason) { 232 if (curRssi == Byte.MAX_VALUE || curRssi == Byte.MIN_VALUE) { 233 Log.wtf(TAG, "processRssiThreshold: Invalid rssi " + curRssi); 234 return; 235 } 236 for (int i = 0; i < mRssiRanges.length; i++) { 237 if (curRssi < mRssiRanges[i]) { 238 // Assume sorted values(ascending order) for rssi, 239 // bounded by high(127) and low(-128) at extremeties 240 byte maxRssi = mRssiRanges[i]; 241 byte minRssi = mRssiRanges[i-1]; 242 // This value of hw has to be believed as this value is averaged and has breached 243 // the rssi thresholds and raised event to host. This would be eggregious if this 244 // value is invalid 245 mWifiInfo.setRssi((int) curRssi); 246 updateCapabilities(getCurrentWifiConfiguration()); 247 int ret = startRssiMonitoringOffload(maxRssi, minRssi); 248 Log.d(TAG, "Re-program RSSI thresholds for " + smToString(reason) + 249 ": [" + minRssi + ", " + maxRssi + "], curRssi=" + curRssi + " ret=" + ret); 250 break; 251 } 252 } 253 } 254 public void registerNetworkDisabled(int netId) { 255 // Initiate a connectivity scan 256 if (mWifiConnectivityManager != null) { 257 mWifiConnectivityManager.forceConnectivityScan(); 258 } 259 } 260 261 // Testing various network disconnect cases by sending lots of spurious 262 // disconnect to supplicant 263 private boolean testNetworkDisconnect = false; 264 265 private boolean mEnableRssiPolling = false; 266 private int mRssiPollToken = 0; 267 /* 3 operational states for STA operation: CONNECT_MODE, SCAN_ONLY_MODE, SCAN_ONLY_WIFI_OFF_MODE 268 * In CONNECT_MODE, the STA can scan and connect to an access point 269 * In SCAN_ONLY_MODE, the STA can only scan for access points 270 * In SCAN_ONLY_WIFI_OFF_MODE, the STA can only scan for access points with wifi toggle being off 271 */ 272 private int mOperationalMode = CONNECT_MODE; 273 private boolean mIsScanOngoing = false; 274 private boolean mIsFullScanOngoing = false; 275 private boolean mSendScanResultsBroadcast = false; 276 277 private final Queue<Message> mBufferedScanMsg = new LinkedList<Message>(); 278 private WorkSource mScanWorkSource = null; 279 private static final int UNKNOWN_SCAN_SOURCE = -1; 280 private static final int SCAN_ALARM_SOURCE = -2; 281 private static final int ADD_OR_UPDATE_SOURCE = -3; 282 private static final int SET_ALLOW_UNTRUSTED_SOURCE = -4; 283 private static final int ENABLE_WIFI = -5; 284 public static final int DFS_RESTRICTED_SCAN_REQUEST = -6; 285 286 private static final int SCAN_REQUEST_BUFFER_MAX_SIZE = 10; 287 private static final String CUSTOMIZED_SCAN_SETTING = "customized_scan_settings"; 288 private static final String CUSTOMIZED_SCAN_WORKSOURCE = "customized_scan_worksource"; 289 private static final String SCAN_REQUEST_TIME = "scan_request_time"; 290 291 /* Tracks if state machine has received any screen state change broadcast yet. 292 * We can miss one of these at boot. 293 */ 294 private AtomicBoolean mScreenBroadcastReceived = new AtomicBoolean(false); 295 296 private boolean mBluetoothConnectionActive = false; 297 298 private PowerManager.WakeLock mSuspendWakeLock; 299 300 /** 301 * Interval in milliseconds between polling for RSSI 302 * and linkspeed information 303 */ 304 private static final int POLL_RSSI_INTERVAL_MSECS = 3000; 305 306 /** 307 * Interval in milliseconds between receiving a disconnect event 308 * while connected to a good AP, and handling the disconnect proper 309 */ 310 private static final int LINK_FLAPPING_DEBOUNCE_MSEC = 4000; 311 312 /** 313 * Delay between supplicant restarts upon failure to establish connection 314 */ 315 private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000; 316 317 /** 318 * Number of times we attempt to restart supplicant 319 */ 320 private static final int SUPPLICANT_RESTART_TRIES = 5; 321 322 private int mSupplicantRestartCount = 0; 323 /* Tracks sequence number on stop failure message */ 324 private int mSupplicantStopFailureToken = 0; 325 326 /** 327 * Tether state change notification time out 328 */ 329 private static final int TETHER_NOTIFICATION_TIME_OUT_MSECS = 5000; 330 331 /* Tracks sequence number on a tether notification time out */ 332 private int mTetherToken = 0; 333 334 /** 335 * Driver start time out. 336 */ 337 private static final int DRIVER_START_TIME_OUT_MSECS = 10000; 338 339 /* Tracks sequence number on a driver time out */ 340 private int mDriverStartToken = 0; 341 342 /** 343 * Don't select new network when previous network selection is 344 * pending connection for this much time 345 */ 346 private static final int CONNECT_TIMEOUT_MSEC = 3000; 347 348 /** 349 * The link properties of the wifi interface. 350 * Do not modify this directly; use updateLinkProperties instead. 351 */ 352 private LinkProperties mLinkProperties; 353 354 /* Tracks sequence number on a periodic scan message */ 355 private int mPeriodicScanToken = 0; 356 357 // Wakelock held during wifi start/stop and driver load/unload 358 private PowerManager.WakeLock mWakeLock; 359 360 private Context mContext; 361 362 private final Object mDhcpResultsLock = new Object(); 363 private DhcpResults mDhcpResults; 364 365 // NOTE: Do not return to clients - use #getWiFiInfoForUid(int) 366 private final WifiInfo mWifiInfo; 367 private NetworkInfo mNetworkInfo; 368 private final NetworkCapabilities mDfltNetworkCapabilities; 369 private SupplicantStateTracker mSupplicantStateTracker; 370 371 private int mWifiLinkLayerStatsSupported = 4; // Temporary disable 372 373 // Whether the state machine goes thru the Disconnecting->Disconnected->ObtainingIpAddress 374 private boolean mAutoRoaming = false; 375 376 // Roaming failure count 377 private int mRoamFailCount = 0; 378 379 // This is the BSSID we are trying to associate to, it can be set to "any" 380 // if we havent selected a BSSID for joining. 381 // if we havent selected a BSSID for joining. 382 // The BSSID we are associated to is found in mWifiInfo 383 private String mTargetRoamBSSID = "any"; 384 //This one is used to track whta is the current target network ID. This is used for error 385 // handling during connection setup since many error message from supplicant does not report 386 // SSID Once connected, it will be set to invalid 387 private int mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 388 389 private long mLastDriverRoamAttempt = 0; 390 391 private WifiConfiguration targetWificonfiguration = null; 392 393 // Used as debug to indicate which configuration last was saved 394 private WifiConfiguration lastSavedConfigurationAttempt = null; 395 396 // Used as debug to indicate which configuration last was removed 397 private WifiConfiguration lastForgetConfigurationAttempt = null; 398 399 //Random used by softAP channel Selection 400 private static Random mRandom = new Random(Calendar.getInstance().getTimeInMillis()); 401 402 boolean isRoaming() { 403 return mAutoRoaming; 404 } 405 406 public void autoRoamSetBSSID(int netId, String bssid) { 407 autoRoamSetBSSID(mWifiConfigManager.getWifiConfiguration(netId), bssid); 408 } 409 410 public boolean autoRoamSetBSSID(WifiConfiguration config, String bssid) { 411 boolean ret = true; 412 if (mTargetRoamBSSID == null) mTargetRoamBSSID = "any"; 413 if (bssid == null) bssid = "any"; 414 if (config == null) return false; // Nothing to do 415 416 if (mTargetRoamBSSID != null && bssid == mTargetRoamBSSID && bssid == config.BSSID) { 417 return false; // We didnt change anything 418 } 419 if (!mTargetRoamBSSID.equals("any") && bssid.equals("any")) { 420 // Changing to ANY 421 if (!mWifiConfigManager.ROAM_ON_ANY) { 422 ret = false; // Nothing to do 423 } 424 } 425 if (config.BSSID != null) { 426 bssid = config.BSSID; 427 if (DBG) { 428 Log.d(TAG, "force BSSID to " + bssid + "due to config"); 429 } 430 } 431 432 if (DBG) { 433 logd("autoRoamSetBSSID " + bssid + " key=" + config.configKey()); 434 } 435 mTargetRoamBSSID = bssid; 436 mWifiConfigManager.saveWifiConfigBSSID(config, bssid); 437 return ret; 438 } 439 440 /** 441 * set Config's default BSSID (for association purpose) 442 * @param config config need set BSSID 443 * @param bssid default BSSID to assocaite with when connect to this network 444 * @return false -- does not change the current default BSSID of the configure 445 * true -- change the current default BSSID of the configur 446 */ 447 private boolean setTargetBssid(WifiConfiguration config, String bssid) { 448 if (config == null) { 449 return false; 450 } 451 452 if (config.BSSID != null) { 453 bssid = config.BSSID; 454 if (DBG) { 455 Log.d(TAG, "force BSSID to " + bssid + "due to config"); 456 } 457 } 458 459 if (bssid == null) { 460 bssid = "any"; 461 } 462 463 String networkSelectionBSSID = config.getNetworkSelectionStatus() 464 .getNetworkSelectionBSSID(); 465 if (networkSelectionBSSID != null && networkSelectionBSSID.equals(bssid)) { 466 if (DBG) { 467 Log.d(TAG, "Current prefered BSSID is same as target"); 468 return false; 469 } 470 } 471 472 if (DBG) { 473 Log.d(TAG, "target set to " + config.SSID + ":" + bssid); 474 } 475 mTargetRoamBSSID = bssid; 476 mWifiConfigManager.saveWifiConfigBSSID(config, bssid); 477 return true; 478 } 479 /** 480 * Save the UID correctly depending on if this is a new or existing network. 481 * @return true if operation is authorized, false otherwise 482 */ 483 boolean recordUidIfAuthorized(WifiConfiguration config, int uid, boolean onlyAnnotate) { 484 if (!mWifiConfigManager.isNetworkConfigured(config)) { 485 config.creatorUid = uid; 486 config.creatorName = mContext.getPackageManager().getNameForUid(uid); 487 } else if (!mWifiConfigManager.canModifyNetwork(uid, config, onlyAnnotate)) { 488 return false; 489 } 490 491 config.lastUpdateUid = uid; 492 config.lastUpdateName = mContext.getPackageManager().getNameForUid(uid); 493 494 return true; 495 496 } 497 498 /** 499 * Checks to see if user has specified if the apps configuration is connectable. 500 * If the user hasn't specified we query the user and return true. 501 * 502 * @param message The message to be deferred 503 * @param netId Network id of the configuration to check against 504 * @param allowOverride If true we won't defer to the user if the uid of the message holds the 505 * CONFIG_OVERRIDE_PERMISSION 506 * @return True if we are waiting for user feedback or netId is invalid. False otherwise. 507 */ 508 boolean deferForUserInput(Message message, int netId, boolean allowOverride){ 509 final WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(netId); 510 511 // We can only evaluate saved configurations. 512 if (config == null) { 513 logd("deferForUserInput: configuration for netId=" + netId + " not stored"); 514 return true; 515 } 516 517 switch (config.userApproved) { 518 case WifiConfiguration.USER_APPROVED: 519 case WifiConfiguration.USER_BANNED: 520 return false; 521 case WifiConfiguration.USER_PENDING: 522 default: // USER_UNSPECIFIED 523 /* the intention was to ask user here; but a dialog box is * 524 * too invasive; so we are going to allow connection for now */ 525 config.userApproved = WifiConfiguration.USER_APPROVED; 526 return false; 527 } 528 } 529 530 private final IpManager mIpManager; 531 532 private AlarmManager mAlarmManager; 533 private PendingIntent mScanIntent; 534 535 /* Tracks current frequency mode */ 536 private AtomicInteger mFrequencyBand = new AtomicInteger(WifiManager.WIFI_FREQUENCY_BAND_AUTO); 537 538 // Channel for sending replies. 539 private AsyncChannel mReplyChannel = new AsyncChannel(); 540 541 private WifiP2pServiceImpl mWifiP2pServiceImpl; 542 543 // Used to initiate a connection with WifiP2pService 544 private AsyncChannel mWifiP2pChannel; 545 546 private WifiScanner mWifiScanner; 547 548 private int mConnectionRequests = 0; 549 private WifiNetworkFactory mNetworkFactory; 550 private UntrustedWifiNetworkFactory mUntrustedNetworkFactory; 551 private WifiNetworkAgent mNetworkAgent; 552 553 private String[] mWhiteListedSsids = null; 554 555 private byte[] mRssiRanges; 556 557 // Keep track of various statistics, for retrieval by System Apps, i.e. under @SystemApi 558 // We should really persist that into the networkHistory.txt file, and read it back when 559 // WifiStateMachine starts up 560 private WifiConnectionStatistics mWifiConnectionStatistics = new WifiConnectionStatistics(); 561 562 // Used to filter out requests we couldn't possibly satisfy. 563 private final NetworkCapabilities mNetworkCapabilitiesFilter = new NetworkCapabilities(); 564 565 // Provide packet filter capabilities to ConnectivityService. 566 private final NetworkMisc mNetworkMisc = new NetworkMisc(); 567 568 /* The base for wifi message types */ 569 static final int BASE = Protocol.BASE_WIFI; 570 /* Start the supplicant */ 571 static final int CMD_START_SUPPLICANT = BASE + 11; 572 /* Stop the supplicant */ 573 static final int CMD_STOP_SUPPLICANT = BASE + 12; 574 /* Start the driver */ 575 static final int CMD_START_DRIVER = BASE + 13; 576 /* Stop the driver */ 577 static final int CMD_STOP_DRIVER = BASE + 14; 578 /* Indicates Static IP succeeded */ 579 static final int CMD_STATIC_IP_SUCCESS = BASE + 15; 580 /* Indicates Static IP failed */ 581 static final int CMD_STATIC_IP_FAILURE = BASE + 16; 582 /* Indicates supplicant stop failed */ 583 static final int CMD_STOP_SUPPLICANT_FAILED = BASE + 17; 584 /* A delayed message sent to start driver when it fail to come up */ 585 static final int CMD_DRIVER_START_TIMED_OUT = BASE + 19; 586 587 /* Start the soft access point */ 588 static final int CMD_START_AP = BASE + 21; 589 /* Indicates soft ap start failed */ 590 static final int CMD_START_AP_FAILURE = BASE + 22; 591 /* Stop the soft access point */ 592 static final int CMD_STOP_AP = BASE + 23; 593 /* Soft access point teardown is completed. */ 594 static final int CMD_AP_STOPPED = BASE + 24; 595 596 static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 31; 597 598 /* Supplicant commands */ 599 /* Is supplicant alive ? */ 600 static final int CMD_PING_SUPPLICANT = BASE + 51; 601 /* Add/update a network configuration */ 602 static final int CMD_ADD_OR_UPDATE_NETWORK = BASE + 52; 603 /* Delete a network */ 604 static final int CMD_REMOVE_NETWORK = BASE + 53; 605 /* Enable a network. The device will attempt a connection to the given network. */ 606 static final int CMD_ENABLE_NETWORK = BASE + 54; 607 /* Enable all networks */ 608 static final int CMD_ENABLE_ALL_NETWORKS = BASE + 55; 609 /* Blacklist network. De-prioritizes the given BSSID for connection. */ 610 static final int CMD_BLACKLIST_NETWORK = BASE + 56; 611 /* Clear the blacklist network list */ 612 static final int CMD_CLEAR_BLACKLIST = BASE + 57; 613 /* Save configuration */ 614 static final int CMD_SAVE_CONFIG = BASE + 58; 615 /* Get configured networks */ 616 static final int CMD_GET_CONFIGURED_NETWORKS = BASE + 59; 617 /* Get available frequencies */ 618 static final int CMD_GET_CAPABILITY_FREQ = BASE + 60; 619 /* Get adaptors */ 620 static final int CMD_GET_SUPPORTED_FEATURES = BASE + 61; 621 /* Get configured networks with real preSharedKey */ 622 static final int CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS = BASE + 62; 623 /* Get Link Layer Stats thru HAL */ 624 static final int CMD_GET_LINK_LAYER_STATS = BASE + 63; 625 /* Supplicant commands after driver start*/ 626 /* Initiate a scan */ 627 static final int CMD_START_SCAN = BASE + 71; 628 /* Set operational mode. CONNECT, SCAN ONLY, SCAN_ONLY with Wi-Fi off mode */ 629 static final int CMD_SET_OPERATIONAL_MODE = BASE + 72; 630 /* Disconnect from a network */ 631 static final int CMD_DISCONNECT = BASE + 73; 632 /* Reconnect to a network */ 633 static final int CMD_RECONNECT = BASE + 74; 634 /* Reassociate to a network */ 635 static final int CMD_REASSOCIATE = BASE + 75; 636 /* Get Connection Statistis */ 637 static final int CMD_GET_CONNECTION_STATISTICS = BASE + 76; 638 639 /* Controls suspend mode optimizations 640 * 641 * When high perf mode is enabled, suspend mode optimizations are disabled 642 * 643 * When high perf mode is disabled, suspend mode optimizations are enabled 644 * 645 * Suspend mode optimizations include: 646 * - packet filtering 647 * - turn off roaming 648 * - DTIM wake up settings 649 */ 650 static final int CMD_SET_HIGH_PERF_MODE = BASE + 77; 651 /* Enables RSSI poll */ 652 static final int CMD_ENABLE_RSSI_POLL = BASE + 82; 653 /* RSSI poll */ 654 static final int CMD_RSSI_POLL = BASE + 83; 655 /* Enable suspend mode optimizations in the driver */ 656 static final int CMD_SET_SUSPEND_OPT_ENABLED = BASE + 86; 657 /* Delayed NETWORK_DISCONNECT */ 658 static final int CMD_DELAYED_NETWORK_DISCONNECT = BASE + 87; 659 /* When there are no saved networks, we do a periodic scan to notify user of 660 * an open network */ 661 static final int CMD_NO_NETWORKS_PERIODIC_SCAN = BASE + 88; 662 /* Test network Disconnection NETWORK_DISCONNECT */ 663 static final int CMD_TEST_NETWORK_DISCONNECT = BASE + 89; 664 665 private int testNetworkDisconnectCounter = 0; 666 667 /* Set the frequency band */ 668 static final int CMD_SET_FREQUENCY_BAND = BASE + 90; 669 /* Enable TDLS on a specific MAC address */ 670 static final int CMD_ENABLE_TDLS = BASE + 92; 671 /* DHCP/IP configuration watchdog */ 672 static final int CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER = BASE + 93; 673 674 /** 675 * Watchdog for protecting against b/16823537 676 * Leave time for 4-way handshake to succeed 677 */ 678 static final int ROAM_GUARD_TIMER_MSEC = 15000; 679 680 int roamWatchdogCount = 0; 681 /* Roam state watchdog */ 682 static final int CMD_ROAM_WATCHDOG_TIMER = BASE + 94; 683 /* Screen change intent handling */ 684 static final int CMD_SCREEN_STATE_CHANGED = BASE + 95; 685 686 /* Disconnecting state watchdog */ 687 static final int CMD_DISCONNECTING_WATCHDOG_TIMER = BASE + 96; 688 689 /* Remove a packages associated configrations */ 690 static final int CMD_REMOVE_APP_CONFIGURATIONS = BASE + 97; 691 692 /* Disable an ephemeral network */ 693 static final int CMD_DISABLE_EPHEMERAL_NETWORK = BASE + 98; 694 695 /* Get matching network */ 696 static final int CMD_GET_MATCHING_CONFIG = BASE + 99; 697 698 /* alert from firmware */ 699 static final int CMD_FIRMWARE_ALERT = BASE + 100; 700 701 /* SIM is removed; reset any cached data for it */ 702 static final int CMD_RESET_SIM_NETWORKS = BASE + 101; 703 704 /* OSU APIs */ 705 static final int CMD_ADD_PASSPOINT_MO = BASE + 102; 706 static final int CMD_MODIFY_PASSPOINT_MO = BASE + 103; 707 static final int CMD_QUERY_OSU_ICON = BASE + 104; 708 709 /* try to match a provider with current network */ 710 static final int CMD_MATCH_PROVIDER_NETWORK = BASE + 105; 711 712 /** 713 * Make this timer 40 seconds, which is about the normal DHCP timeout. 714 * In no valid case, the WiFiStateMachine should remain stuck in ObtainingIpAddress 715 * for more than 30 seconds. 716 */ 717 static final int OBTAINING_IP_ADDRESS_GUARD_TIMER_MSEC = 40000; 718 719 int obtainingIpWatchdogCount = 0; 720 721 /* Commands from/to the SupplicantStateTracker */ 722 /* Reset the supplicant state tracker */ 723 static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111; 724 725 int disconnectingWatchdogCount = 0; 726 static final int DISCONNECTING_GUARD_TIMER_MSEC = 5000; 727 728 /* P2p commands */ 729 /* We are ok with no response here since we wont do much with it anyway */ 730 public static final int CMD_ENABLE_P2P = BASE + 131; 731 /* In order to shut down supplicant cleanly, we wait till p2p has 732 * been disabled */ 733 public static final int CMD_DISABLE_P2P_REQ = BASE + 132; 734 public static final int CMD_DISABLE_P2P_RSP = BASE + 133; 735 736 public static final int CMD_BOOT_COMPLETED = BASE + 134; 737 738 /* We now have a valid IP configuration. */ 739 static final int CMD_IP_CONFIGURATION_SUCCESSFUL = BASE + 138; 740 /* We no longer have a valid IP configuration. */ 741 static final int CMD_IP_CONFIGURATION_LOST = BASE + 139; 742 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 743 static final int CMD_UPDATE_LINKPROPERTIES = BASE + 140; 744 745 /* Supplicant is trying to associate to a given BSSID */ 746 static final int CMD_TARGET_BSSID = BASE + 141; 747 748 /* Reload all networks and reconnect */ 749 static final int CMD_RELOAD_TLS_AND_RECONNECT = BASE + 142; 750 751 static final int CMD_AUTO_CONNECT = BASE + 143; 752 753 private static final int NETWORK_STATUS_UNWANTED_DISCONNECT = 0; 754 private static final int NETWORK_STATUS_UNWANTED_VALIDATION_FAILED = 1; 755 private static final int NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN = 2; 756 757 static final int CMD_UNWANTED_NETWORK = BASE + 144; 758 759 static final int CMD_AUTO_ROAM = BASE + 145; 760 761 static final int CMD_AUTO_SAVE_NETWORK = BASE + 146; 762 763 static final int CMD_ASSOCIATED_BSSID = BASE + 147; 764 765 static final int CMD_NETWORK_STATUS = BASE + 148; 766 767 /* A layer 3 neighbor on the Wi-Fi link became unreachable. */ 768 static final int CMD_IP_REACHABILITY_LOST = BASE + 149; 769 770 /* Remove a packages associated configrations */ 771 static final int CMD_REMOVE_USER_CONFIGURATIONS = BASE + 152; 772 773 static final int CMD_ACCEPT_UNVALIDATED = BASE + 153; 774 775 /* used to log if PNO was started */ 776 static final int CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION = BASE + 158; 777 778 /* used to offload sending IP packet */ 779 static final int CMD_START_IP_PACKET_OFFLOAD = BASE + 160; 780 781 /* used to stop offload sending IP packet */ 782 static final int CMD_STOP_IP_PACKET_OFFLOAD = BASE + 161; 783 784 /* used to start rssi monitoring in hw */ 785 static final int CMD_START_RSSI_MONITORING_OFFLOAD = BASE + 162; 786 787 /* used to stop rssi moniroting in hw */ 788 static final int CMD_STOP_RSSI_MONITORING_OFFLOAD = BASE + 163; 789 790 /* used to indicated RSSI threshold breach in hw */ 791 static final int CMD_RSSI_THRESHOLD_BREACH = BASE + 164; 792 793 /* used to indicate that the foreground user was switched */ 794 static final int CMD_USER_SWITCH = BASE + 165; 795 796 /* Enable/Disable WifiConnectivityManager */ 797 static final int CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER = BASE + 166; 798 799 /** 800 * Used to handle messages bounced between WifiStateMachine and IpManager. 801 */ 802 static final int CMD_IPV4_PROVISIONING_SUCCESS = BASE + 200; 803 static final int CMD_IPV4_PROVISIONING_FAILURE = BASE + 201; 804 805 /* Push a new APF program to the HAL */ 806 static final int CMD_INSTALL_PACKET_FILTER = BASE + 202; 807 808 /* Enable/disable fallback packet filtering */ 809 static final int CMD_SET_FALLBACK_PACKET_FILTERING = BASE + 203; 810 811 /* Enable/disable Neighbor Discovery offload functionality. */ 812 static final int CMD_CONFIG_ND_OFFLOAD = BASE + 204; 813 814 // For message logging. 815 private static final Class[] sMessageClasses = { 816 AsyncChannel.class, WifiStateMachine.class, DhcpClient.class }; 817 private static final SparseArray<String> sSmToString = 818 MessageUtils.findMessageNames(sMessageClasses); 819 820 821 /* Wifi state machine modes of operation */ 822 /* CONNECT_MODE - connect to any 'known' AP when it becomes available */ 823 public static final int CONNECT_MODE = 1; 824 /* SCAN_ONLY_MODE - don't connect to any APs; scan, but only while apps hold lock */ 825 public static final int SCAN_ONLY_MODE = 2; 826 /* SCAN_ONLY_WITH_WIFI_OFF - scan, but don't connect to any APs */ 827 public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3; 828 829 private static final int SUCCESS = 1; 830 private static final int FAILURE = -1; 831 832 /* Tracks if suspend optimizations need to be disabled by DHCP, 833 * screen or due to high perf mode. 834 * When any of them needs to disable it, we keep the suspend optimizations 835 * disabled 836 */ 837 private int mSuspendOptNeedsDisabled = 0; 838 839 private static final int SUSPEND_DUE_TO_DHCP = 1; 840 private static final int SUSPEND_DUE_TO_HIGH_PERF = 1 << 1; 841 private static final int SUSPEND_DUE_TO_SCREEN = 1 << 2; 842 843 /* Tracks if user has enabled suspend optimizations through settings */ 844 private AtomicBoolean mUserWantsSuspendOpt = new AtomicBoolean(true); 845 846 /** 847 * Default framework scan interval in milliseconds. This is used in the scenario in which 848 * wifi chipset does not support background scanning to set up a 849 * periodic wake up scan so that the device can connect to a new access 850 * point on the move. {@link Settings.Global#WIFI_FRAMEWORK_SCAN_INTERVAL_MS} can 851 * override this. 852 */ 853 private final int mDefaultFrameworkScanIntervalMs; 854 855 856 /** 857 * Scan period for the NO_NETWORKS_PERIIDOC_SCAN_FEATURE 858 */ 859 private final int mNoNetworksPeriodicScan; 860 861 /** 862 * Supplicant scan interval in milliseconds. 863 * Comes from {@link Settings.Global#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} or 864 * from the default config if the setting is not set 865 */ 866 private long mSupplicantScanIntervalMs; 867 868 /** 869 * timeStamp of last full band scan we perfoemed for autojoin while connected with screen lit 870 */ 871 private long lastFullBandConnectedTimeMilli; 872 873 /** 874 * time interval to the next full band scan we will perform for 875 * autojoin while connected with screen lit 876 */ 877 private long fullBandConnectedTimeIntervalMilli; 878 879 /** 880 * max time interval to the next full band scan we will perform for 881 * autojoin while connected with screen lit 882 * Max time is 5 minutes 883 */ 884 private static final long maxFullBandConnectedTimeIntervalMilli = 1000 * 60 * 5; 885 886 /** 887 * Minimum time interval between enabling all networks. 888 * A device can end up repeatedly connecting to a bad network on screen on/off toggle 889 * due to enabling every time. We add a threshold to avoid this. 890 */ 891 private static final int MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS = 10 * 60 * 1000; /* 10 minutes */ 892 private long mLastEnableAllNetworksTime; 893 894 int mRunningBeaconCount = 0; 895 896 /* Default parent state */ 897 private State mDefaultState = new DefaultState(); 898 /* Temporary initial state */ 899 private State mInitialState = new InitialState(); 900 /* Driver loaded, waiting for supplicant to start */ 901 private State mSupplicantStartingState = new SupplicantStartingState(); 902 /* Driver loaded and supplicant ready */ 903 private State mSupplicantStartedState = new SupplicantStartedState(); 904 /* Waiting for supplicant to stop and monitor to exit */ 905 private State mSupplicantStoppingState = new SupplicantStoppingState(); 906 /* Driver start issued, waiting for completed event */ 907 private State mDriverStartingState = new DriverStartingState(); 908 /* Driver started */ 909 private State mDriverStartedState = new DriverStartedState(); 910 /* Wait until p2p is disabled 911 * This is a special state which is entered right after we exit out of DriverStartedState 912 * before transitioning to another state. 913 */ 914 private State mWaitForP2pDisableState = new WaitForP2pDisableState(); 915 /* Driver stopping */ 916 private State mDriverStoppingState = new DriverStoppingState(); 917 /* Driver stopped */ 918 private State mDriverStoppedState = new DriverStoppedState(); 919 /* Scan for networks, no connection will be established */ 920 private State mScanModeState = new ScanModeState(); 921 /* Connecting to an access point */ 922 private State mConnectModeState = new ConnectModeState(); 923 /* Connected at 802.11 (L2) level */ 924 private State mL2ConnectedState = new L2ConnectedState(); 925 /* fetching IP after connection to access point (assoc+auth complete) */ 926 private State mObtainingIpState = new ObtainingIpState(); 927 /* Connected with IP addr */ 928 private State mConnectedState = new ConnectedState(); 929 /* Roaming */ 930 private State mRoamingState = new RoamingState(); 931 /* disconnect issued, waiting for network disconnect confirmation */ 932 private State mDisconnectingState = new DisconnectingState(); 933 /* Network is not connected, supplicant assoc+auth is not complete */ 934 private State mDisconnectedState = new DisconnectedState(); 935 /* Waiting for WPS to be completed*/ 936 private State mWpsRunningState = new WpsRunningState(); 937 /* Soft ap state */ 938 private State mSoftApState = new SoftApState(); 939 940 public static class SimAuthRequestData { 941 int networkId; 942 int protocol; 943 String ssid; 944 // EAP-SIM: data[] contains the 3 rand, one for each of the 3 challenges 945 // EAP-AKA/AKA': data[] contains rand & authn couple for the single challenge 946 String[] data; 947 } 948 949 /** 950 * One of {@link WifiManager#WIFI_STATE_DISABLED}, 951 * {@link WifiManager#WIFI_STATE_DISABLING}, 952 * {@link WifiManager#WIFI_STATE_ENABLED}, 953 * {@link WifiManager#WIFI_STATE_ENABLING}, 954 * {@link WifiManager#WIFI_STATE_UNKNOWN} 955 */ 956 private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED); 957 958 /** 959 * One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 960 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 961 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 962 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 963 * {@link WifiManager#WIFI_AP_STATE_FAILED} 964 */ 965 private final AtomicInteger mWifiApState = new AtomicInteger(WIFI_AP_STATE_DISABLED); 966 967 private static final int SCAN_REQUEST = 0; 968 private static final String ACTION_START_SCAN = 969 "com.android.server.WifiManager.action.START_SCAN"; 970 971 /** 972 * Keep track of whether WIFI is running. 973 */ 974 private boolean mIsRunning = false; 975 976 /** 977 * Keep track of whether we last told the battery stats we had started. 978 */ 979 private boolean mReportedRunning = false; 980 981 /** 982 * Most recently set source of starting WIFI. 983 */ 984 private final WorkSource mRunningWifiUids = new WorkSource(); 985 986 /** 987 * The last reported UIDs that were responsible for starting WIFI. 988 */ 989 private final WorkSource mLastRunningWifiUids = new WorkSource(); 990 991 private final IBatteryStats mBatteryStats; 992 993 private final String mTcpBufferSizes; 994 995 // Used for debug and stats gathering 996 private static int sScanAlarmIntentCount = 0; 997 998 private static final int sFrameworkMinScanIntervalSaneValue = 10000; 999 1000 private long mGScanStartTimeMilli; 1001 private long mGScanPeriodMilli; 1002 1003 private FrameworkFacade mFacade; 1004 1005 private final BackupManagerProxy mBackupManagerProxy; 1006 1007 public WifiStateMachine(Context context, FrameworkFacade facade, Looper looper, 1008 UserManager userManager, WifiInjector wifiInjector, 1009 BackupManagerProxy backupManagerProxy, 1010 WifiCountryCode countryCode) { 1011 super("WifiStateMachine", looper); 1012 1013 mWifiMetrics = wifiInjector.getWifiMetrics(); 1014 mContext = context; 1015 mFacade = facade; 1016 mWifiNative = WifiNative.getWlanNativeInterface(); 1017 mBackupManagerProxy = backupManagerProxy; 1018 1019 // TODO refactor WifiNative use of context out into it's own class 1020 mWifiNative.initContext(mContext); 1021 mInterfaceName = mWifiNative.getInterfaceName(); 1022 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, ""); 1023 mBatteryStats = IBatteryStats.Stub.asInterface(mFacade.getService( 1024 BatteryStats.SERVICE_NAME)); 1025 1026 IBinder b = mFacade.getService(Context.NETWORKMANAGEMENT_SERVICE); 1027 mNwService = INetworkManagementService.Stub.asInterface(b); 1028 1029 mP2pSupported = mContext.getPackageManager().hasSystemFeature( 1030 PackageManager.FEATURE_WIFI_DIRECT); 1031 1032 mWifiConfigManager = mFacade.makeWifiConfigManager(context, this, mWifiNative, facade, 1033 mClock, userManager, KeyStore.getInstance()); 1034 1035 mWifiMonitor = WifiMonitor.getInstance(); 1036 1037 boolean enableFirmwareLogs = mContext.getResources().getBoolean( 1038 R.bool.config_wifi_enable_wifi_firmware_debugging); 1039 1040 if (enableFirmwareLogs) { 1041 int maxRingBufferSizeBytes = mContext.getResources().getInteger( 1042 R.integer.config_wifi_logger_ring_buffer_size_limit_kb) * 1024; 1043 mWifiLogger = facade.makeRealLogger(this, mWifiNative, maxRingBufferSizeBytes); 1044 } else { 1045 mWifiLogger = facade.makeBaseLogger(); 1046 } 1047 1048 mWifiInfo = new WifiInfo(); 1049 mWifiQualifiedNetworkSelector = new WifiQualifiedNetworkSelector(mWifiConfigManager, 1050 mContext, mWifiInfo, mClock); 1051 mSupplicantStateTracker = mFacade.makeSupplicantStateTracker( 1052 context, mWifiConfigManager, getHandler()); 1053 1054 mLinkProperties = new LinkProperties(); 1055 1056 IBinder s1 = mFacade.getService(Context.WIFI_P2P_SERVICE); 1057 mWifiP2pServiceImpl = (WifiP2pServiceImpl) IWifiP2pManager.Stub.asInterface(s1); 1058 1059 mNetworkInfo.setIsAvailable(false); 1060 mLastBssid = null; 1061 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 1062 mLastSignalLevel = -1; 1063 1064 mIpManager = mFacade.makeIpManager(mContext, mInterfaceName, new IpManagerCallback()); 1065 mIpManager.setMulticastFilter(true); 1066 1067 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 1068 mScanIntent = getPrivateBroadcast(ACTION_START_SCAN, SCAN_REQUEST); 1069 1070 // Make sure the interval is not configured less than 10 seconds 1071 int period = mContext.getResources().getInteger( 1072 R.integer.config_wifi_framework_scan_interval); 1073 if (period < sFrameworkMinScanIntervalSaneValue) { 1074 period = sFrameworkMinScanIntervalSaneValue; 1075 } 1076 mDefaultFrameworkScanIntervalMs = period; 1077 1078 mNoNetworksPeriodicScan = mContext.getResources().getInteger( 1079 R.integer.config_wifi_no_network_periodic_scan_interval); 1080 1081 mBackgroundScanSupported = mContext.getResources().getBoolean( 1082 R.bool.config_wifi_background_scan_support); 1083 1084 mPrimaryDeviceType = mContext.getResources().getString( 1085 R.string.config_wifi_p2p_device_type); 1086 1087 mCountryCode = countryCode; 1088 1089 mUserWantsSuspendOpt.set(mFacade.getIntegerSetting(mContext, 1090 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1); 1091 1092 mNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); 1093 mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 1094 mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 1095 mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); 1096 mNetworkCapabilitiesFilter.setLinkUpstreamBandwidthKbps(1024 * 1024); 1097 mNetworkCapabilitiesFilter.setLinkDownstreamBandwidthKbps(1024 * 1024); 1098 // TODO - needs to be a bit more dynamic 1099 mDfltNetworkCapabilities = new NetworkCapabilities(mNetworkCapabilitiesFilter); 1100 1101 mContext.registerReceiver( 1102 new BroadcastReceiver() { 1103 @Override 1104 public void onReceive(Context context, Intent intent) { 1105 sScanAlarmIntentCount++; // Used for debug only 1106 startScan(SCAN_ALARM_SOURCE, mDelayedScanCounter.incrementAndGet(), null, null); 1107 if (DBG) 1108 logd("SCAN ALARM -> " + mDelayedScanCounter.get()); 1109 } 1110 }, 1111 new IntentFilter(ACTION_START_SCAN)); 1112 1113 1114 IntentFilter filter = new IntentFilter(); 1115 filter.addAction(Intent.ACTION_SCREEN_ON); 1116 filter.addAction(Intent.ACTION_SCREEN_OFF); 1117 mContext.registerReceiver( 1118 new BroadcastReceiver() { 1119 @Override 1120 public void onReceive(Context context, Intent intent) { 1121 String action = intent.getAction(); 1122 1123 if (action.equals(Intent.ACTION_SCREEN_ON)) { 1124 sendMessage(CMD_SCREEN_STATE_CHANGED, 1); 1125 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1126 sendMessage(CMD_SCREEN_STATE_CHANGED, 0); 1127 } 1128 } 1129 }, filter); 1130 1131 mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor( 1132 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED), false, 1133 new ContentObserver(getHandler()) { 1134 @Override 1135 public void onChange(boolean selfChange) { 1136 mUserWantsSuspendOpt.set(mFacade.getIntegerSetting(mContext, 1137 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1); 1138 } 1139 }); 1140 1141 mContext.registerReceiver( 1142 new BroadcastReceiver() { 1143 @Override 1144 public void onReceive(Context context, Intent intent) { 1145 sendMessage(CMD_BOOT_COMPLETED); 1146 } 1147 }, 1148 new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); 1149 1150 PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 1151 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getName()); 1152 1153 mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend"); 1154 mSuspendWakeLock.setReferenceCounted(false); 1155 1156 mTcpBufferSizes = mContext.getResources().getString( 1157 com.android.internal.R.string.config_wifi_tcp_buffers); 1158 1159 // CHECKSTYLE:OFF IndentationCheck 1160 addState(mDefaultState); 1161 addState(mInitialState, mDefaultState); 1162 addState(mSupplicantStartingState, mDefaultState); 1163 addState(mSupplicantStartedState, mDefaultState); 1164 addState(mDriverStartingState, mSupplicantStartedState); 1165 addState(mDriverStartedState, mSupplicantStartedState); 1166 addState(mScanModeState, mDriverStartedState); 1167 addState(mConnectModeState, mDriverStartedState); 1168 addState(mL2ConnectedState, mConnectModeState); 1169 addState(mObtainingIpState, mL2ConnectedState); 1170 addState(mConnectedState, mL2ConnectedState); 1171 addState(mRoamingState, mL2ConnectedState); 1172 addState(mDisconnectingState, mConnectModeState); 1173 addState(mDisconnectedState, mConnectModeState); 1174 addState(mWpsRunningState, mConnectModeState); 1175 addState(mWaitForP2pDisableState, mSupplicantStartedState); 1176 addState(mDriverStoppingState, mSupplicantStartedState); 1177 addState(mDriverStoppedState, mSupplicantStartedState); 1178 addState(mSupplicantStoppingState, mDefaultState); 1179 addState(mSoftApState, mDefaultState); 1180 // CHECKSTYLE:ON IndentationCheck 1181 1182 setInitialState(mInitialState); 1183 1184 setLogRecSize(ActivityManager.isLowRamDeviceStatic() ? 100 : 3000); 1185 setLogOnlyTransitions(false); 1186 1187 //start the state machine 1188 start(); 1189 1190 mWifiMonitor.registerHandler(mInterfaceName, CMD_TARGET_BSSID, getHandler()); 1191 mWifiMonitor.registerHandler(mInterfaceName, CMD_ASSOCIATED_BSSID, getHandler()); 1192 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ANQP_DONE_EVENT, getHandler()); 1193 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT, 1194 getHandler()); 1195 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 1196 getHandler()); 1197 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.DRIVER_HUNG_EVENT, getHandler()); 1198 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_DONE_EVENT, getHandler()); 1199 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_START_EVENT, 1200 getHandler()); 1201 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.HS20_REMEDIATION_EVENT, 1202 getHandler()); 1203 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT, 1204 getHandler()); 1205 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT, 1206 getHandler()); 1207 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.RX_HS20_ANQP_ICON_EVENT, 1208 getHandler()); 1209 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SCAN_FAILED_EVENT, getHandler()); 1210 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SCAN_RESULTS_EVENT, getHandler()); 1211 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SSID_REENABLED, getHandler()); 1212 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SSID_TEMP_DISABLED, getHandler()); 1213 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_CONNECTION_EVENT, getHandler()); 1214 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_DISCONNECTION_EVENT, 1215 getHandler()); 1216 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 1217 getHandler()); 1218 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_IDENTITY, getHandler()); 1219 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_SIM_AUTH, getHandler()); 1220 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_FAIL_EVENT, getHandler()); 1221 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_OVERLAP_EVENT, getHandler()); 1222 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_SUCCESS_EVENT, getHandler()); 1223 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_TIMEOUT_EVENT, getHandler()); 1224 1225 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 1226 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1227 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); 1228 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 1229 1230 mVerboseLoggingLevel = mFacade.getIntegerSetting( 1231 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0); 1232 updateLoggingLevel(); 1233 } 1234 1235 class IpManagerCallback extends IpManager.Callback { 1236 @Override 1237 public void onPreDhcpAction() { 1238 sendMessage(DhcpClient.CMD_PRE_DHCP_ACTION); 1239 } 1240 1241 @Override 1242 public void onPostDhcpAction() { 1243 sendMessage(DhcpClient.CMD_POST_DHCP_ACTION); 1244 } 1245 1246 @Override 1247 public void onNewDhcpResults(DhcpResults dhcpResults) { 1248 if (dhcpResults != null) { 1249 sendMessage(CMD_IPV4_PROVISIONING_SUCCESS, dhcpResults); 1250 } else { 1251 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 1252 } 1253 } 1254 1255 @Override 1256 public void onProvisioningSuccess(LinkProperties newLp) { 1257 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); 1258 sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL); 1259 } 1260 1261 @Override 1262 public void onProvisioningFailure(LinkProperties newLp) { 1263 sendMessage(CMD_IP_CONFIGURATION_LOST); 1264 } 1265 1266 @Override 1267 public void onLinkPropertiesChange(LinkProperties newLp) { 1268 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); 1269 } 1270 1271 @Override 1272 public void onReachabilityLost(String logMsg) { 1273 sendMessage(CMD_IP_REACHABILITY_LOST, logMsg); 1274 } 1275 1276 @Override 1277 public void installPacketFilter(byte[] filter) { 1278 sendMessage(CMD_INSTALL_PACKET_FILTER, filter); 1279 } 1280 1281 @Override 1282 public void setFallbackMulticastFilter(boolean enabled) { 1283 sendMessage(CMD_SET_FALLBACK_PACKET_FILTERING, enabled); 1284 } 1285 1286 @Override 1287 public void setNeighborDiscoveryOffload(boolean enabled) { 1288 sendMessage(CMD_CONFIG_ND_OFFLOAD, (enabled ? 1 : 0)); 1289 } 1290 } 1291 1292 private void stopIpManager() { 1293 /* Restore power save and suspend optimizations */ 1294 handlePostDhcpSetup(); 1295 mIpManager.stop(); 1296 } 1297 1298 PendingIntent getPrivateBroadcast(String action, int requestCode) { 1299 Intent intent = new Intent(action, null); 1300 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1301 intent.setPackage("android"); 1302 return mFacade.getBroadcast(mContext, requestCode, intent, 0); 1303 } 1304 1305 int getVerboseLoggingLevel() { 1306 return mVerboseLoggingLevel; 1307 } 1308 1309 void enableVerboseLogging(int verbose) { 1310 mVerboseLoggingLevel = verbose; 1311 mFacade.setIntegerSetting( 1312 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, verbose); 1313 updateLoggingLevel(); 1314 } 1315 1316 void updateLoggingLevel() { 1317 if (mVerboseLoggingLevel > 0) { 1318 DBG = true; 1319 mWifiNative.setSupplicantLogLevel("DEBUG"); 1320 } else { 1321 DBG = false; 1322 mWifiNative.setSupplicantLogLevel("INFO"); 1323 } 1324 mCountryCode.enableVerboseLogging(mVerboseLoggingLevel); 1325 mWifiLogger.startLogging(DBG); 1326 mWifiMonitor.enableVerboseLogging(mVerboseLoggingLevel); 1327 mWifiNative.enableVerboseLogging(mVerboseLoggingLevel); 1328 mWifiConfigManager.enableVerboseLogging(mVerboseLoggingLevel); 1329 mSupplicantStateTracker.enableVerboseLogging(mVerboseLoggingLevel); 1330 mWifiQualifiedNetworkSelector.enableVerboseLogging(mVerboseLoggingLevel); 1331 if (mWifiConnectivityManager != null) { 1332 mWifiConnectivityManager.enableVerboseLogging(mVerboseLoggingLevel); 1333 } 1334 } 1335 1336 boolean allowFullBandScanAndAssociated() { 1337 1338 if (!mWifiConfigManager.getEnableAutoJoinWhenAssociated()) { 1339 if (DBG) { 1340 Log.e(TAG, "allowFullBandScanAndAssociated: " 1341 + " enableAutoJoinWhenAssociated : disallow"); 1342 } 1343 return false; 1344 } 1345 1346 if (mWifiInfo.txSuccessRate > mWifiConfigManager.MAX_TX_PACKET_FOR_FULL_SCANS 1347 || mWifiInfo.rxSuccessRate > mWifiConfigManager.MAX_RX_PACKET_FOR_FULL_SCANS) { 1348 if (DBG) { 1349 Log.e(TAG, "allowFullBandScanAndAssociated: packet rate tx" 1350 + mWifiInfo.txSuccessRate + " rx " 1351 + mWifiInfo.rxSuccessRate 1352 + " allow scan with traffic " + getAllowScansWithTraffic()); 1353 } 1354 // Too much traffic at the interface, hence no full band scan 1355 if (getAllowScansWithTraffic() == 0) { 1356 return false; 1357 } 1358 } 1359 1360 if (getCurrentState() != mConnectedState) { 1361 if (DBG) { 1362 Log.e(TAG, "allowFullBandScanAndAssociated: getCurrentState() : disallow"); 1363 } 1364 return false; 1365 } 1366 1367 return true; 1368 } 1369 1370 long mLastScanPermissionUpdate = 0; 1371 boolean mConnectedModeGScanOffloadStarted = false; 1372 // Don't do a G-scan enable/re-enable cycle more than once within 20seconds 1373 // The function updateAssociatedScanPermission() can be called quite frequently, hence 1374 // we want to throttle the GScan Stop->Start transition 1375 static final long SCAN_PERMISSION_UPDATE_THROTTLE_MILLI = 20000; 1376 void updateAssociatedScanPermission() { 1377 } 1378 1379 private int mAggressiveHandover = 0; 1380 1381 int getAggressiveHandover() { 1382 return mAggressiveHandover; 1383 } 1384 1385 void enableAggressiveHandover(int enabled) { 1386 mAggressiveHandover = enabled; 1387 } 1388 1389 public void clearANQPCache() { 1390 mWifiConfigManager.trimANQPCache(true); 1391 } 1392 1393 public void setAllowScansWithTraffic(int enabled) { 1394 mWifiConfigManager.mAlwaysEnableScansWhileAssociated.set(enabled); 1395 } 1396 1397 public int getAllowScansWithTraffic() { 1398 return mWifiConfigManager.mAlwaysEnableScansWhileAssociated.get(); 1399 } 1400 1401 public boolean enableAutoJoinWhenAssociated(boolean enabled) { 1402 boolean old_state = mWifiConfigManager.getEnableAutoJoinWhenAssociated(); 1403 mWifiConfigManager.enableAutoJoinWhenAssociated(enabled); 1404 if (!old_state && enabled && mScreenOn && getCurrentState() == mConnectedState) { 1405 startDelayedScan(mWifiConfigManager.mWifiAssociatedShortScanIntervalMs.get(), null, 1406 null); 1407 } 1408 return true; 1409 } 1410 1411 public boolean getEnableAutoJoinWhenAssociated() { 1412 return mWifiConfigManager.getEnableAutoJoinWhenAssociated(); 1413 } 1414 1415 /* 1416 * 1417 * Framework scan control 1418 */ 1419 1420 private boolean mAlarmEnabled = false; 1421 1422 private AtomicInteger mDelayedScanCounter = new AtomicInteger(); 1423 1424 private void setScanAlarm(boolean enabled) { 1425 if (DBG) { 1426 String state; 1427 if (enabled) state = "enabled"; else state = "disabled"; 1428 logd("setScanAlarm " + state 1429 + " defaultperiod " + mDefaultFrameworkScanIntervalMs 1430 + " mBackgroundScanSupported " + mBackgroundScanSupported); 1431 } 1432 if (mBackgroundScanSupported == false) { 1433 // Scan alarm is only used for background scans if they are not 1434 // offloaded to the wifi chipset, hence enable the scan alarm 1435 // gicing us RTC_WAKEUP of backgroundScan is NOT supported 1436 enabled = true; 1437 } 1438 1439 if (enabled == mAlarmEnabled) return; 1440 if (enabled) { 1441 /* Set RTC_WAKEUP alarms if PNO is not supported - because no one is */ 1442 /* going to wake up the host processor to look for access points */ 1443 mAlarmManager.set(AlarmManager.RTC_WAKEUP, 1444 System.currentTimeMillis() + mDefaultFrameworkScanIntervalMs, 1445 mScanIntent); 1446 mAlarmEnabled = true; 1447 } else { 1448 mAlarmManager.cancel(mScanIntent); 1449 mAlarmEnabled = false; 1450 } 1451 } 1452 1453 private void cancelDelayedScan() { 1454 mDelayedScanCounter.incrementAndGet(); 1455 } 1456 1457 private boolean checkAndRestartDelayedScan(int counter, boolean restart, int milli, 1458 ScanSettings settings, WorkSource workSource) { 1459 1460 if (counter != mDelayedScanCounter.get()) { 1461 return false; 1462 } 1463 if (restart) 1464 startDelayedScan(milli, settings, workSource); 1465 return true; 1466 } 1467 1468 private void startDelayedScan(int milli, ScanSettings settings, WorkSource workSource) { 1469 if (milli <= 0) return; 1470 /** 1471 * The cases where the scan alarm should be run are : 1472 * - DisconnectedState && screenOn => used delayed timer 1473 * - DisconnectedState && !screenOn && mBackgroundScanSupported => PNO 1474 * - DisconnectedState && !screenOn && !mBackgroundScanSupported => used RTC_WAKEUP Alarm 1475 * - ConnectedState && screenOn => used delayed timer 1476 */ 1477 1478 mDelayedScanCounter.incrementAndGet(); 1479 if (mScreenOn && 1480 (getCurrentState() == mDisconnectedState 1481 || getCurrentState() == mConnectedState)) { 1482 Bundle bundle = new Bundle(); 1483 bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, settings); 1484 bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource); 1485 bundle.putLong(SCAN_REQUEST_TIME, System.currentTimeMillis()); 1486 sendMessageDelayed(CMD_START_SCAN, SCAN_ALARM_SOURCE, 1487 mDelayedScanCounter.get(), bundle, milli); 1488 if (DBG) logd("startDelayedScan send -> " + mDelayedScanCounter + " milli " + milli); 1489 } else if (mBackgroundScanSupported == false 1490 && !mScreenOn && getCurrentState() == mDisconnectedState) { 1491 setScanAlarm(true); 1492 if (DBG) logd("startDelayedScan start scan alarm -> " 1493 + mDelayedScanCounter + " milli " + milli); 1494 } else { 1495 if (DBG) logd("startDelayedScan unhandled -> " 1496 + mDelayedScanCounter + " milli " + milli); 1497 } 1498 } 1499 1500 private boolean setRandomMacOui() { 1501 String oui = mContext.getResources().getString(R.string.config_wifi_random_mac_oui); 1502 if (TextUtils.isEmpty(oui)) { 1503 oui = GOOGLE_OUI; 1504 } 1505 String[] ouiParts = oui.split("-"); 1506 byte[] ouiBytes = new byte[3]; 1507 ouiBytes[0] = (byte) (Integer.parseInt(ouiParts[0], 16) & 0xFF); 1508 ouiBytes[1] = (byte) (Integer.parseInt(ouiParts[1], 16) & 0xFF); 1509 ouiBytes[2] = (byte) (Integer.parseInt(ouiParts[2], 16) & 0xFF); 1510 1511 logd("Setting OUI to " + oui); 1512 return mWifiNative.setScanningMacOui(ouiBytes); 1513 } 1514 1515 /** 1516 * ****************************************************** 1517 * Methods exposed for public use 1518 * ****************************************************** 1519 */ 1520 1521 public Messenger getMessenger() { 1522 return new Messenger(getHandler()); 1523 } 1524 1525 /** 1526 * TODO: doc 1527 */ 1528 public boolean syncPingSupplicant(AsyncChannel channel) { 1529 Message resultMsg = channel.sendMessageSynchronously(CMD_PING_SUPPLICANT); 1530 boolean result = (resultMsg.arg1 != FAILURE); 1531 resultMsg.recycle(); 1532 return result; 1533 } 1534 1535 /** 1536 * When settings allowing making use of untrusted networks change, trigger a scan 1537 * so as to kick of autojoin. 1538 */ 1539 public void startScanForUntrustedSettingChange() { 1540 startScan(SET_ALLOW_UNTRUSTED_SOURCE, 0, null, null); 1541 } 1542 1543 /** 1544 * Initiate a wifi scan. If workSource is not null, blame is given to it, otherwise blame is 1545 * given to callingUid. 1546 * 1547 * @param callingUid The uid initiating the wifi scan. Blame will be given here unless 1548 * workSource is specified. 1549 * @param workSource If not null, blame is given to workSource. 1550 * @param settings Scan settings, see {@link ScanSettings}. 1551 */ 1552 public void startScan(int callingUid, int scanCounter, 1553 ScanSettings settings, WorkSource workSource) { 1554 Bundle bundle = new Bundle(); 1555 bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, settings); 1556 bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource); 1557 bundle.putLong(SCAN_REQUEST_TIME, System.currentTimeMillis()); 1558 sendMessage(CMD_START_SCAN, callingUid, scanCounter, bundle); 1559 } 1560 1561 // called from BroadcastListener 1562 1563 /** 1564 * Start reading new scan data 1565 * Data comes in as: 1566 * "scancount=5\n" 1567 * "nextcount=5\n" 1568 * "apcount=3\n" 1569 * "trunc\n" (optional) 1570 * "bssid=...\n" 1571 * "ssid=...\n" 1572 * "freq=...\n" (in Mhz) 1573 * "level=...\n" 1574 * "dist=...\n" (in cm) 1575 * "distsd=...\n" (standard deviation, in cm) 1576 * "====" 1577 * "bssid=...\n" 1578 * etc 1579 * "====" 1580 * "bssid=...\n" 1581 * etc 1582 * "%%%%" 1583 * "apcount=2\n" 1584 * "bssid=...\n" 1585 * etc 1586 * "%%%% 1587 * etc 1588 * "----" 1589 */ 1590 private final static boolean DEBUG_PARSE = false; 1591 1592 private long mDisconnectedTimeStamp = 0; 1593 1594 public long getDisconnectedTimeMilli() { 1595 if (getCurrentState() == mDisconnectedState 1596 && mDisconnectedTimeStamp != 0) { 1597 long now_ms = System.currentTimeMillis(); 1598 return now_ms - mDisconnectedTimeStamp; 1599 } 1600 return 0; 1601 } 1602 1603 // Keeping track of scan requests 1604 private long lastStartScanTimeStamp = 0; 1605 private long lastScanDuration = 0; 1606 // Last connect attempt is used to prevent scan requests: 1607 // - for a period of 10 seconds after attempting to connect 1608 private long lastConnectAttemptTimestamp = 0; 1609 private Set<Integer> lastScanFreqs = null; 1610 1611 // For debugging, keep track of last message status handling 1612 // TODO, find an equivalent mechanism as part of parent class 1613 private static int MESSAGE_HANDLING_STATUS_PROCESSED = 2; 1614 private static int MESSAGE_HANDLING_STATUS_OK = 1; 1615 private static int MESSAGE_HANDLING_STATUS_UNKNOWN = 0; 1616 private static int MESSAGE_HANDLING_STATUS_REFUSED = -1; 1617 private static int MESSAGE_HANDLING_STATUS_FAIL = -2; 1618 private static int MESSAGE_HANDLING_STATUS_OBSOLETE = -3; 1619 private static int MESSAGE_HANDLING_STATUS_DEFERRED = -4; 1620 private static int MESSAGE_HANDLING_STATUS_DISCARD = -5; 1621 private static int MESSAGE_HANDLING_STATUS_LOOPED = -6; 1622 private static int MESSAGE_HANDLING_STATUS_HANDLING_ERROR = -7; 1623 1624 private int messageHandlingStatus = 0; 1625 1626 //TODO: this is used only to track connection attempts, however the link state and packet per 1627 //TODO: second logic should be folded into that 1628 private boolean checkOrDeferScanAllowed(Message msg) { 1629 long now = System.currentTimeMillis(); 1630 if (lastConnectAttemptTimestamp != 0 && (now - lastConnectAttemptTimestamp) < 10000) { 1631 Message dmsg = Message.obtain(msg); 1632 sendMessageDelayed(dmsg, 11000 - (now - lastConnectAttemptTimestamp)); 1633 return false; 1634 } 1635 return true; 1636 } 1637 1638 private int mOnTime = 0; 1639 private int mTxTime = 0; 1640 private int mRxTime = 0; 1641 private int mOnTimeStartScan = 0; 1642 private int mTxTimeStartScan = 0; 1643 private int mRxTimeStartScan = 0; 1644 private int mOnTimeScan = 0; 1645 private int mTxTimeScan = 0; 1646 private int mRxTimeScan = 0; 1647 private int mOnTimeThisScan = 0; 1648 private int mTxTimeThisScan = 0; 1649 private int mRxTimeThisScan = 0; 1650 1651 private int mOnTimeScreenStateChange = 0; 1652 private long lastOntimeReportTimeStamp = 0; 1653 private long lastScreenStateChangeTimeStamp = 0; 1654 private int mOnTimeLastReport = 0; 1655 private int mTxTimeLastReport = 0; 1656 private int mRxTimeLastReport = 0; 1657 1658 private long lastLinkLayerStatsUpdate = 0; 1659 1660 String reportOnTime() { 1661 long now = System.currentTimeMillis(); 1662 StringBuilder sb = new StringBuilder(); 1663 // Report stats since last report 1664 int on = mOnTime - mOnTimeLastReport; 1665 mOnTimeLastReport = mOnTime; 1666 int tx = mTxTime - mTxTimeLastReport; 1667 mTxTimeLastReport = mTxTime; 1668 int rx = mRxTime - mRxTimeLastReport; 1669 mRxTimeLastReport = mRxTime; 1670 int period = (int) (now - lastOntimeReportTimeStamp); 1671 lastOntimeReportTimeStamp = now; 1672 sb.append(String.format("[on:%d tx:%d rx:%d period:%d]", on, tx, rx, period)); 1673 // Report stats since Screen State Changed 1674 on = mOnTime - mOnTimeScreenStateChange; 1675 period = (int) (now - lastScreenStateChangeTimeStamp); 1676 sb.append(String.format(" from screen [on:%d period:%d]", on, period)); 1677 return sb.toString(); 1678 } 1679 1680 WifiLinkLayerStats getWifiLinkLayerStats(boolean dbg) { 1681 WifiLinkLayerStats stats = null; 1682 if (mWifiLinkLayerStatsSupported > 0) { 1683 String name = "wlan0"; 1684 stats = mWifiNative.getWifiLinkLayerStats(name); 1685 if (name != null && stats == null && mWifiLinkLayerStatsSupported > 0) { 1686 mWifiLinkLayerStatsSupported -= 1; 1687 } else if (stats != null) { 1688 lastLinkLayerStatsUpdate = System.currentTimeMillis(); 1689 mOnTime = stats.on_time; 1690 mTxTime = stats.tx_time; 1691 mRxTime = stats.rx_time; 1692 mRunningBeaconCount = stats.beacon_rx; 1693 } 1694 } 1695 if (stats == null || mWifiLinkLayerStatsSupported <= 0) { 1696 long mTxPkts = mFacade.getTxPackets(mInterfaceName); 1697 long mRxPkts = mFacade.getRxPackets(mInterfaceName); 1698 mWifiInfo.updatePacketRates(mTxPkts, mRxPkts); 1699 } else { 1700 mWifiInfo.updatePacketRates(stats); 1701 } 1702 return stats; 1703 } 1704 1705 void startRadioScanStats() { 1706 WifiLinkLayerStats stats = getWifiLinkLayerStats(false); 1707 if (stats != null) { 1708 mOnTimeStartScan = stats.on_time; 1709 mTxTimeStartScan = stats.tx_time; 1710 mRxTimeStartScan = stats.rx_time; 1711 mOnTime = stats.on_time; 1712 mTxTime = stats.tx_time; 1713 mRxTime = stats.rx_time; 1714 } 1715 } 1716 1717 void closeRadioScanStats() { 1718 WifiLinkLayerStats stats = getWifiLinkLayerStats(false); 1719 if (stats != null) { 1720 mOnTimeThisScan = stats.on_time - mOnTimeStartScan; 1721 mTxTimeThisScan = stats.tx_time - mTxTimeStartScan; 1722 mRxTimeThisScan = stats.rx_time - mRxTimeStartScan; 1723 mOnTimeScan += mOnTimeThisScan; 1724 mTxTimeScan += mTxTimeThisScan; 1725 mRxTimeScan += mRxTimeThisScan; 1726 } 1727 } 1728 1729 int startWifiIPPacketOffload(int slot, KeepalivePacketData packetData, int intervalSeconds) { 1730 int ret = mWifiNative.startSendingOffloadedPacket(slot, packetData, intervalSeconds * 1000); 1731 if (ret != 0) { 1732 loge("startWifiIPPacketOffload(" + slot + ", " + intervalSeconds + 1733 "): hardware error " + ret); 1734 return ConnectivityManager.PacketKeepalive.ERROR_HARDWARE_ERROR; 1735 } else { 1736 return ConnectivityManager.PacketKeepalive.SUCCESS; 1737 } 1738 } 1739 1740 int stopWifiIPPacketOffload(int slot) { 1741 int ret = mWifiNative.stopSendingOffloadedPacket(slot); 1742 if (ret != 0) { 1743 loge("stopWifiIPPacketOffload(" + slot + "): hardware error " + ret); 1744 return ConnectivityManager.PacketKeepalive.ERROR_HARDWARE_ERROR; 1745 } else { 1746 return ConnectivityManager.PacketKeepalive.SUCCESS; 1747 } 1748 } 1749 1750 int startRssiMonitoringOffload(byte maxRssi, byte minRssi) { 1751 return mWifiNative.startRssiMonitoring(maxRssi, minRssi, WifiStateMachine.this); 1752 } 1753 1754 int stopRssiMonitoringOffload() { 1755 return mWifiNative.stopRssiMonitoring(); 1756 } 1757 1758 // If workSource is not null, blame is given to it, otherwise blame is given to callingUid. 1759 private void noteScanStart(int callingUid, WorkSource workSource) { 1760 if (lastStartScanTimeStamp != 0) { 1761 noteScanEnd(); 1762 } 1763 long now = System.currentTimeMillis(); 1764 lastStartScanTimeStamp = now; 1765 lastScanDuration = 0; 1766 if (DBG) { 1767 String ts = String.format("[%,d ms]", now); 1768 if (workSource != null) { 1769 if (DBG) logd(ts + " noteScanStart" + workSource.toString() 1770 + " uid " + Integer.toString(callingUid)); 1771 } else { 1772 if (DBG) logd(ts + " noteScanstart no scan source" 1773 + " uid " + Integer.toString(callingUid)); 1774 } 1775 } 1776 startRadioScanStats(); 1777 if (mScanWorkSource == null && ((callingUid != UNKNOWN_SCAN_SOURCE 1778 && callingUid != SCAN_ALARM_SOURCE) 1779 || workSource != null)) { 1780 mScanWorkSource = workSource != null ? workSource : new WorkSource(callingUid); 1781 1782 if (mScanWorkSource.size() == 1 && mScanWorkSource.get(0) < 0) { 1783 // WiFi uses negative UIDs to mean special things. BatteryStats don't care! 1784 mScanWorkSource = new WorkSource(Process.WIFI_UID); 1785 } 1786 1787 try { 1788 mBatteryStats.noteWifiScanStartedFromSource(mScanWorkSource); 1789 } catch (RemoteException e) { 1790 log(e.toString()); 1791 } 1792 } 1793 } 1794 1795 private void noteScanEnd() { 1796 closeRadioScanStats(); 1797 long now = System.currentTimeMillis(); 1798 if (lastStartScanTimeStamp != 0) { 1799 lastScanDuration = now - lastStartScanTimeStamp; 1800 } 1801 lastStartScanTimeStamp = 0; 1802 if (DBG) { 1803 String ts = String.format("[%,d ms]", now); 1804 if (mScanWorkSource != null) 1805 logd(ts + " noteScanEnd " + mScanWorkSource.toString() 1806 + " onTime=" + mOnTimeThisScan); 1807 else 1808 logd(ts + " noteScanEnd no scan source" 1809 + " onTime=" + mOnTimeThisScan); 1810 } 1811 if (mScanWorkSource != null) { 1812 try { 1813 mBatteryStats.noteWifiScanStoppedFromSource(mScanWorkSource); 1814 } catch (RemoteException e) { 1815 log(e.toString()); 1816 } finally { 1817 mScanWorkSource = null; 1818 } 1819 } 1820 } 1821 1822 private void handleScanRequest(Message message) { 1823 ScanSettings settings = null; 1824 WorkSource workSource = null; 1825 1826 // unbundle parameters 1827 Bundle bundle = (Bundle) message.obj; 1828 1829 if (bundle != null) { 1830 settings = bundle.getParcelable(CUSTOMIZED_SCAN_SETTING); 1831 workSource = bundle.getParcelable(CUSTOMIZED_SCAN_WORKSOURCE); 1832 } 1833 1834 Set<Integer> freqs = null; 1835 if (settings != null && settings.channelSet != null) { 1836 freqs = new HashSet<Integer>(); 1837 for (WifiChannel channel : settings.channelSet) { 1838 freqs.add(channel.freqMHz); 1839 } 1840 } 1841 1842 // Retrieve the list of hidden networkId's to scan for. 1843 Set<Integer> hiddenNetworkIds = mWifiConfigManager.getHiddenConfiguredNetworkIds(); 1844 1845 // call wifi native to start the scan 1846 if (startScanNative(freqs, hiddenNetworkIds, workSource)) { 1847 // only count battery consumption if scan request is accepted 1848 noteScanStart(message.arg1, workSource); 1849 // a full scan covers everything, clearing scan request buffer 1850 if (freqs == null) 1851 mBufferedScanMsg.clear(); 1852 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; 1853 if (workSource != null) { 1854 // External worksource was passed along the scan request, 1855 // hence always send a broadcast 1856 mSendScanResultsBroadcast = true; 1857 } 1858 return; 1859 } 1860 1861 // if reach here, scan request is rejected 1862 1863 if (!mIsScanOngoing) { 1864 // if rejection is NOT due to ongoing scan (e.g. bad scan parameters), 1865 1866 // discard this request and pop up the next one 1867 if (mBufferedScanMsg.size() > 0) { 1868 sendMessage(mBufferedScanMsg.remove()); 1869 } 1870 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 1871 } else if (!mIsFullScanOngoing) { 1872 // if rejection is due to an ongoing scan, and the ongoing one is NOT a full scan, 1873 // buffer the scan request to make sure specified channels will be scanned eventually 1874 if (freqs == null) 1875 mBufferedScanMsg.clear(); 1876 if (mBufferedScanMsg.size() < SCAN_REQUEST_BUFFER_MAX_SIZE) { 1877 Message msg = obtainMessage(CMD_START_SCAN, 1878 message.arg1, message.arg2, bundle); 1879 mBufferedScanMsg.add(msg); 1880 } else { 1881 // if too many requests in buffer, combine them into a single full scan 1882 bundle = new Bundle(); 1883 bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, null); 1884 bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource); 1885 Message msg = obtainMessage(CMD_START_SCAN, message.arg1, message.arg2, bundle); 1886 mBufferedScanMsg.clear(); 1887 mBufferedScanMsg.add(msg); 1888 } 1889 messageHandlingStatus = MESSAGE_HANDLING_STATUS_LOOPED; 1890 } else { 1891 // mIsScanOngoing and mIsFullScanOngoing 1892 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 1893 } 1894 } 1895 1896 1897 // TODO this is a temporary measure to bridge between WifiScanner and WifiStateMachine until 1898 // scan functionality is refactored out of WifiStateMachine. 1899 /** 1900 * return true iff scan request is accepted 1901 */ 1902 private boolean startScanNative(final Set<Integer> freqs, Set<Integer> hiddenNetworkIds, 1903 WorkSource workSource) { 1904 WifiScanner.ScanSettings settings = new WifiScanner.ScanSettings(); 1905 if (freqs == null) { 1906 settings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS; 1907 } else { 1908 settings.band = WifiScanner.WIFI_BAND_UNSPECIFIED; 1909 int index = 0; 1910 settings.channels = new WifiScanner.ChannelSpec[freqs.size()]; 1911 for (Integer freq : freqs) { 1912 settings.channels[index++] = new WifiScanner.ChannelSpec(freq); 1913 } 1914 } 1915 settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 1916 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT; 1917 if (hiddenNetworkIds != null && hiddenNetworkIds.size() > 0) { 1918 int i = 0; 1919 settings.hiddenNetworkIds = new int[hiddenNetworkIds.size()]; 1920 for (Integer netId : hiddenNetworkIds) { 1921 settings.hiddenNetworkIds[i++] = netId; 1922 } 1923 } 1924 WifiScanner.ScanListener nativeScanListener = new WifiScanner.ScanListener() { 1925 // ignore all events since WifiStateMachine is registered for the supplicant events 1926 public void onSuccess() { 1927 } 1928 public void onFailure(int reason, String description) { 1929 mIsScanOngoing = false; 1930 mIsFullScanOngoing = false; 1931 } 1932 public void onResults(WifiScanner.ScanData[] results) { 1933 } 1934 public void onFullResult(ScanResult fullScanResult) { 1935 } 1936 public void onPeriodChanged(int periodInMs) { 1937 } 1938 }; 1939 mWifiScanner.startScan(settings, nativeScanListener, workSource); 1940 mIsScanOngoing = true; 1941 mIsFullScanOngoing = (freqs == null); 1942 lastScanFreqs = freqs; 1943 return true; 1944 } 1945 1946 /** 1947 * TODO: doc 1948 */ 1949 public void setSupplicantRunning(boolean enable) { 1950 if (enable) { 1951 sendMessage(CMD_START_SUPPLICANT); 1952 } else { 1953 sendMessage(CMD_STOP_SUPPLICANT); 1954 } 1955 } 1956 1957 /** 1958 * TODO: doc 1959 */ 1960 public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) { 1961 if (enable) { 1962 sendMessage(CMD_START_AP, wifiConfig); 1963 } else { 1964 sendMessage(CMD_STOP_AP); 1965 } 1966 } 1967 1968 public void setWifiApConfiguration(WifiConfiguration config) { 1969 mWifiApConfigStore.setApConfiguration(config); 1970 } 1971 1972 public WifiConfiguration syncGetWifiApConfiguration() { 1973 return mWifiApConfigStore.getApConfiguration(); 1974 } 1975 1976 /** 1977 * TODO: doc 1978 */ 1979 public int syncGetWifiState() { 1980 return mWifiState.get(); 1981 } 1982 1983 /** 1984 * TODO: doc 1985 */ 1986 public String syncGetWifiStateByName() { 1987 switch (mWifiState.get()) { 1988 case WIFI_STATE_DISABLING: 1989 return "disabling"; 1990 case WIFI_STATE_DISABLED: 1991 return "disabled"; 1992 case WIFI_STATE_ENABLING: 1993 return "enabling"; 1994 case WIFI_STATE_ENABLED: 1995 return "enabled"; 1996 case WIFI_STATE_UNKNOWN: 1997 return "unknown state"; 1998 default: 1999 return "[invalid state]"; 2000 } 2001 } 2002 2003 /** 2004 * TODO: doc 2005 */ 2006 public int syncGetWifiApState() { 2007 return mWifiApState.get(); 2008 } 2009 2010 /** 2011 * TODO: doc 2012 */ 2013 public String syncGetWifiApStateByName() { 2014 switch (mWifiApState.get()) { 2015 case WIFI_AP_STATE_DISABLING: 2016 return "disabling"; 2017 case WIFI_AP_STATE_DISABLED: 2018 return "disabled"; 2019 case WIFI_AP_STATE_ENABLING: 2020 return "enabling"; 2021 case WIFI_AP_STATE_ENABLED: 2022 return "enabled"; 2023 case WIFI_AP_STATE_FAILED: 2024 return "failed"; 2025 default: 2026 return "[invalid state]"; 2027 } 2028 } 2029 2030 public boolean isConnected() { 2031 return getCurrentState() == mConnectedState; 2032 } 2033 2034 public boolean isDisconnected() { 2035 return getCurrentState() == mDisconnectedState; 2036 } 2037 2038 public boolean isSupplicantTransientState() { 2039 SupplicantState SupplicantState = mWifiInfo.getSupplicantState(); 2040 if (SupplicantState == SupplicantState.ASSOCIATING 2041 || SupplicantState == SupplicantState.AUTHENTICATING 2042 || SupplicantState == SupplicantState.FOUR_WAY_HANDSHAKE 2043 || SupplicantState == SupplicantState.GROUP_HANDSHAKE) { 2044 2045 if (DBG) { 2046 Log.d(TAG, "Supplicant is under transient state: " + SupplicantState); 2047 } 2048 return true; 2049 } else { 2050 if (DBG) { 2051 Log.d(TAG, "Supplicant is under steady state: " + SupplicantState); 2052 } 2053 } 2054 2055 return false; 2056 } 2057 2058 public boolean isLinkDebouncing() { 2059 return linkDebouncing; 2060 } 2061 2062 /** 2063 * Get status information for the current connection, if any. 2064 * 2065 * @return a {@link WifiInfo} object containing information about the current connection 2066 */ 2067 public WifiInfo syncRequestConnectionInfo() { 2068 return getWiFiInfoForUid(Binder.getCallingUid()); 2069 } 2070 2071 public WifiInfo getWifiInfo() { 2072 return mWifiInfo; 2073 } 2074 2075 public DhcpResults syncGetDhcpResults() { 2076 synchronized (mDhcpResultsLock) { 2077 return new DhcpResults(mDhcpResults); 2078 } 2079 } 2080 2081 /** 2082 * TODO: doc 2083 */ 2084 public void setDriverStart(boolean enable) { 2085 if (enable) { 2086 sendMessage(CMD_START_DRIVER); 2087 } else { 2088 sendMessage(CMD_STOP_DRIVER); 2089 } 2090 } 2091 2092 /** 2093 * TODO: doc 2094 */ 2095 public void setOperationalMode(int mode) { 2096 if (DBG) log("setting operational mode to " + String.valueOf(mode)); 2097 sendMessage(CMD_SET_OPERATIONAL_MODE, mode, 0); 2098 } 2099 2100 /** 2101 * TODO: doc 2102 */ 2103 public List<ScanResult> syncGetScanResultsList() { 2104 synchronized (mScanResultsLock) { 2105 List<ScanResult> scanList = new ArrayList<ScanResult>(); 2106 for (ScanDetail result : mScanResults) { 2107 scanList.add(new ScanResult(result.getScanResult())); 2108 } 2109 return scanList; 2110 } 2111 } 2112 2113 public int syncAddPasspointManagementObject(AsyncChannel channel, String managementObject) { 2114 Message resultMsg = 2115 channel.sendMessageSynchronously(CMD_ADD_PASSPOINT_MO, managementObject); 2116 int result = resultMsg.arg1; 2117 resultMsg.recycle(); 2118 return result; 2119 } 2120 2121 public int syncModifyPasspointManagementObject(AsyncChannel channel, String fqdn, 2122 List<PasspointManagementObjectDefinition> 2123 managementObjectDefinitions) { 2124 Bundle bundle = new Bundle(); 2125 bundle.putString("FQDN", fqdn); 2126 bundle.putParcelableList("MOS", managementObjectDefinitions); 2127 Message resultMsg = channel.sendMessageSynchronously(CMD_MODIFY_PASSPOINT_MO, bundle); 2128 int result = resultMsg.arg1; 2129 resultMsg.recycle(); 2130 return result; 2131 } 2132 2133 public boolean syncQueryPasspointIcon(AsyncChannel channel, long bssid, String fileName) { 2134 Bundle bundle = new Bundle(); 2135 bundle.putLong("BSSID", bssid); 2136 bundle.putString("FILENAME", fileName); 2137 Message resultMsg = channel.sendMessageSynchronously(CMD_QUERY_OSU_ICON, bundle); 2138 int result = resultMsg.arg1; 2139 resultMsg.recycle(); 2140 return result == 1; 2141 } 2142 2143 public int matchProviderWithCurrentNetwork(AsyncChannel channel, String fqdn) { 2144 Message resultMsg = channel.sendMessageSynchronously(CMD_MATCH_PROVIDER_NETWORK, fqdn); 2145 int result = resultMsg.arg1; 2146 resultMsg.recycle(); 2147 return result; 2148 } 2149 2150 /** 2151 * Deauthenticate and set the re-authentication hold off time for the current network 2152 * @param holdoff hold off time in milliseconds 2153 * @param ess set if the hold off pertains to an ESS rather than a BSS 2154 */ 2155 public void deauthenticateNetwork(AsyncChannel channel, long holdoff, boolean ess) { 2156 // TODO: This needs an implementation 2157 } 2158 2159 public void disableEphemeralNetwork(String SSID) { 2160 if (SSID != null) { 2161 sendMessage(CMD_DISABLE_EPHEMERAL_NETWORK, SSID); 2162 } 2163 } 2164 2165 /** 2166 * Get unsynchronized pointer to scan result list 2167 * Can be called only from AutoJoinController which runs in the WifiStateMachine context 2168 */ 2169 public List<ScanDetail> getScanResultsListNoCopyUnsync() { 2170 return mScanResults; 2171 } 2172 2173 /** 2174 * Disconnect from Access Point 2175 */ 2176 public void disconnectCommand() { 2177 sendMessage(CMD_DISCONNECT); 2178 } 2179 2180 public void disconnectCommand(int uid, int reason) { 2181 sendMessage(CMD_DISCONNECT, uid, reason); 2182 } 2183 2184 /** 2185 * Initiate a reconnection to AP 2186 */ 2187 public void reconnectCommand() { 2188 sendMessage(CMD_RECONNECT); 2189 } 2190 2191 /** 2192 * Initiate a re-association to AP 2193 */ 2194 public void reassociateCommand() { 2195 sendMessage(CMD_REASSOCIATE); 2196 } 2197 2198 /** 2199 * Reload networks and then reconnect; helps load correct data for TLS networks 2200 */ 2201 2202 public void reloadTlsNetworksAndReconnect() { 2203 sendMessage(CMD_RELOAD_TLS_AND_RECONNECT); 2204 } 2205 2206 /** 2207 * Add a network synchronously 2208 * 2209 * @return network id of the new network 2210 */ 2211 public int syncAddOrUpdateNetwork(AsyncChannel channel, WifiConfiguration config) { 2212 Message resultMsg = channel.sendMessageSynchronously(CMD_ADD_OR_UPDATE_NETWORK, config); 2213 int result = resultMsg.arg1; 2214 resultMsg.recycle(); 2215 return result; 2216 } 2217 2218 /** 2219 * Get configured networks synchronously 2220 * 2221 * @param channel 2222 * @return 2223 */ 2224 2225 public List<WifiConfiguration> syncGetConfiguredNetworks(int uuid, AsyncChannel channel) { 2226 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONFIGURED_NETWORKS, uuid); 2227 List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj; 2228 resultMsg.recycle(); 2229 return result; 2230 } 2231 2232 public List<WifiConfiguration> syncGetPrivilegedConfiguredNetwork(AsyncChannel channel) { 2233 Message resultMsg = channel.sendMessageSynchronously( 2234 CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS); 2235 List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj; 2236 resultMsg.recycle(); 2237 return result; 2238 } 2239 2240 public WifiConfiguration syncGetMatchingWifiConfig(ScanResult scanResult, AsyncChannel channel) { 2241 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_MATCHING_CONFIG, scanResult); 2242 return (WifiConfiguration) resultMsg.obj; 2243 } 2244 2245 /** 2246 * Get connection statistics synchronously 2247 * 2248 * @param channel 2249 * @return 2250 */ 2251 2252 public WifiConnectionStatistics syncGetConnectionStatistics(AsyncChannel channel) { 2253 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONNECTION_STATISTICS); 2254 WifiConnectionStatistics result = (WifiConnectionStatistics) resultMsg.obj; 2255 resultMsg.recycle(); 2256 return result; 2257 } 2258 2259 /** 2260 * Get adaptors synchronously 2261 */ 2262 2263 public int syncGetSupportedFeatures(AsyncChannel channel) { 2264 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_SUPPORTED_FEATURES); 2265 int supportedFeatureSet = resultMsg.arg1; 2266 resultMsg.recycle(); 2267 return supportedFeatureSet; 2268 } 2269 2270 /** 2271 * Get link layers stats for adapter synchronously 2272 */ 2273 public WifiLinkLayerStats syncGetLinkLayerStats(AsyncChannel channel) { 2274 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_LINK_LAYER_STATS); 2275 WifiLinkLayerStats result = (WifiLinkLayerStats) resultMsg.obj; 2276 resultMsg.recycle(); 2277 return result; 2278 } 2279 2280 /** 2281 * Delete a network 2282 * 2283 * @param networkId id of the network to be removed 2284 */ 2285 public boolean syncRemoveNetwork(AsyncChannel channel, int networkId) { 2286 Message resultMsg = channel.sendMessageSynchronously(CMD_REMOVE_NETWORK, networkId); 2287 boolean result = (resultMsg.arg1 != FAILURE); 2288 resultMsg.recycle(); 2289 return result; 2290 } 2291 2292 /** 2293 * Enable a network 2294 * 2295 * @param netId network id of the network 2296 * @param disableOthers true, if all other networks have to be disabled 2297 * @return {@code true} if the operation succeeds, {@code false} otherwise 2298 */ 2299 public boolean syncEnableNetwork(AsyncChannel channel, int netId, boolean disableOthers) { 2300 Message resultMsg = channel.sendMessageSynchronously(CMD_ENABLE_NETWORK, netId, 2301 disableOthers ? 1 : 0); 2302 boolean result = (resultMsg.arg1 != FAILURE); 2303 resultMsg.recycle(); 2304 return result; 2305 } 2306 2307 /** 2308 * Disable a network 2309 * 2310 * @param netId network id of the network 2311 * @return {@code true} if the operation succeeds, {@code false} otherwise 2312 */ 2313 public boolean syncDisableNetwork(AsyncChannel channel, int netId) { 2314 Message resultMsg = channel.sendMessageSynchronously(WifiManager.DISABLE_NETWORK, netId); 2315 boolean result = (resultMsg.arg1 != WifiManager.DISABLE_NETWORK_FAILED); 2316 resultMsg.recycle(); 2317 return result; 2318 } 2319 2320 /** 2321 * Retrieves a WPS-NFC configuration token for the specified network 2322 * 2323 * @return a hex string representation of the WPS-NFC configuration token 2324 */ 2325 public String syncGetWpsNfcConfigurationToken(int netId) { 2326 return mWifiNative.getNfcWpsConfigurationToken(netId); 2327 } 2328 2329 /** 2330 * Blacklist a BSSID. This will avoid the AP if there are 2331 * alternate APs to connect 2332 * 2333 * @param bssid BSSID of the network 2334 */ 2335 public void addToBlacklist(String bssid) { 2336 sendMessage(CMD_BLACKLIST_NETWORK, bssid); 2337 } 2338 2339 /** 2340 * Clear the blacklist list 2341 */ 2342 public void clearBlacklist() { 2343 sendMessage(CMD_CLEAR_BLACKLIST); 2344 } 2345 2346 public void enableRssiPolling(boolean enabled) { 2347 sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0); 2348 } 2349 2350 public void enableAllNetworks() { 2351 sendMessage(CMD_ENABLE_ALL_NETWORKS); 2352 } 2353 2354 /** 2355 * Start filtering Multicast v4 packets 2356 */ 2357 public void startFilteringMulticastPackets() { 2358 mIpManager.setMulticastFilter(true); 2359 } 2360 2361 /** 2362 * Stop filtering Multicast v4 packets 2363 */ 2364 public void stopFilteringMulticastPackets() { 2365 mIpManager.setMulticastFilter(false); 2366 } 2367 2368 /** 2369 * Set high performance mode of operation. 2370 * Enabling would set active power mode and disable suspend optimizations; 2371 * disabling would set auto power mode and enable suspend optimizations 2372 * 2373 * @param enable true if enable, false otherwise 2374 */ 2375 public void setHighPerfModeEnabled(boolean enable) { 2376 sendMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0); 2377 } 2378 2379 2380 /** 2381 * reset cached SIM credential data 2382 */ 2383 public synchronized void resetSimAuthNetworks() { 2384 sendMessage(CMD_RESET_SIM_NETWORKS); 2385 } 2386 2387 /** 2388 * Get Network object of current wifi network 2389 * @return Network object of current wifi network 2390 */ 2391 public Network getCurrentNetwork() { 2392 if (mNetworkAgent != null) { 2393 return new Network(mNetworkAgent.netId); 2394 } else { 2395 return null; 2396 } 2397 } 2398 2399 2400 /** 2401 * Set the operational frequency band 2402 * 2403 * @param band 2404 * @param persist {@code true} if the setting should be remembered. 2405 */ 2406 public void setFrequencyBand(int band, boolean persist) { 2407 if (persist) { 2408 Settings.Global.putInt(mContext.getContentResolver(), 2409 Settings.Global.WIFI_FREQUENCY_BAND, 2410 band); 2411 } 2412 sendMessage(CMD_SET_FREQUENCY_BAND, band, 0); 2413 } 2414 2415 /** 2416 * Enable TDLS for a specific MAC address 2417 */ 2418 public void enableTdls(String remoteMacAddress, boolean enable) { 2419 int enabler = enable ? 1 : 0; 2420 sendMessage(CMD_ENABLE_TDLS, enabler, 0, remoteMacAddress); 2421 } 2422 2423 /** 2424 * Returns the operational frequency band 2425 */ 2426 public int getFrequencyBand() { 2427 return mFrequencyBand.get(); 2428 } 2429 2430 /** 2431 * Returns the wifi configuration file 2432 */ 2433 public String getConfigFile() { 2434 return mWifiConfigManager.getConfigFile(); 2435 } 2436 2437 /** 2438 * Send a message indicating bluetooth adapter connection state changed 2439 */ 2440 public void sendBluetoothAdapterStateChange(int state) { 2441 sendMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0); 2442 } 2443 2444 /** 2445 * Send a message indicating a package has been uninstalled. 2446 */ 2447 public void removeAppConfigs(String packageName, int uid) { 2448 // Build partial AppInfo manually - package may not exist in database any more 2449 ApplicationInfo ai = new ApplicationInfo(); 2450 ai.packageName = packageName; 2451 ai.uid = uid; 2452 sendMessage(CMD_REMOVE_APP_CONFIGURATIONS, ai); 2453 } 2454 2455 /** 2456 * Send a message indicating a user has been removed. 2457 */ 2458 public void removeUserConfigs(int userId) { 2459 sendMessage(CMD_REMOVE_USER_CONFIGURATIONS, userId); 2460 } 2461 2462 /** 2463 * Save configuration on supplicant 2464 * 2465 * @return {@code true} if the operation succeeds, {@code false} otherwise 2466 * <p/> 2467 * TODO: deprecate this 2468 */ 2469 public boolean syncSaveConfig(AsyncChannel channel) { 2470 Message resultMsg = channel.sendMessageSynchronously(CMD_SAVE_CONFIG); 2471 boolean result = (resultMsg.arg1 != FAILURE); 2472 resultMsg.recycle(); 2473 return result; 2474 } 2475 2476 public void updateBatteryWorkSource(WorkSource newSource) { 2477 synchronized (mRunningWifiUids) { 2478 try { 2479 if (newSource != null) { 2480 mRunningWifiUids.set(newSource); 2481 } 2482 if (mIsRunning) { 2483 if (mReportedRunning) { 2484 // If the work source has changed since last time, need 2485 // to remove old work from battery stats. 2486 if (mLastRunningWifiUids.diff(mRunningWifiUids)) { 2487 mBatteryStats.noteWifiRunningChanged(mLastRunningWifiUids, 2488 mRunningWifiUids); 2489 mLastRunningWifiUids.set(mRunningWifiUids); 2490 } 2491 } else { 2492 // Now being started, report it. 2493 mBatteryStats.noteWifiRunning(mRunningWifiUids); 2494 mLastRunningWifiUids.set(mRunningWifiUids); 2495 mReportedRunning = true; 2496 } 2497 } else { 2498 if (mReportedRunning) { 2499 // Last reported we were running, time to stop. 2500 mBatteryStats.noteWifiStopped(mLastRunningWifiUids); 2501 mLastRunningWifiUids.clear(); 2502 mReportedRunning = false; 2503 } 2504 } 2505 mWakeLock.setWorkSource(newSource); 2506 } catch (RemoteException ignore) { 2507 } 2508 } 2509 } 2510 2511 public void dumpIpManager(FileDescriptor fd, PrintWriter pw, String[] args) { 2512 mIpManager.dump(fd, pw, args); 2513 } 2514 2515 @Override 2516 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2517 super.dump(fd, pw, args); 2518 mSupplicantStateTracker.dump(fd, pw, args); 2519 pw.println("mLinkProperties " + mLinkProperties); 2520 pw.println("mWifiInfo " + mWifiInfo); 2521 pw.println("mDhcpResults " + mDhcpResults); 2522 pw.println("mNetworkInfo " + mNetworkInfo); 2523 pw.println("mLastSignalLevel " + mLastSignalLevel); 2524 pw.println("mLastBssid " + mLastBssid); 2525 pw.println("mLastNetworkId " + mLastNetworkId); 2526 pw.println("mOperationalMode " + mOperationalMode); 2527 pw.println("mUserWantsSuspendOpt " + mUserWantsSuspendOpt); 2528 pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 2529 pw.println("Supplicant status " + mWifiNative.status(true)); 2530 if (mCountryCode.getCurrentCountryCode() != null) { 2531 pw.println("CurrentCountryCode " + mCountryCode.getCurrentCountryCode()); 2532 } else { 2533 pw.println("CurrentCountryCode is not initialized"); 2534 } 2535 pw.println("mConnectedModeGScanOffloadStarted " + mConnectedModeGScanOffloadStarted); 2536 pw.println("mGScanPeriodMilli " + mGScanPeriodMilli); 2537 if (mWhiteListedSsids != null && mWhiteListedSsids.length > 0) { 2538 pw.println("SSID whitelist :" ); 2539 for (int i=0; i < mWhiteListedSsids.length; i++) { 2540 pw.println(" " + mWhiteListedSsids[i]); 2541 } 2542 } 2543 if (mNetworkFactory != null) { 2544 mNetworkFactory.dump(fd, pw, args); 2545 } else { 2546 pw.println("mNetworkFactory is not initialized"); 2547 } 2548 2549 if (mUntrustedNetworkFactory != null) { 2550 mUntrustedNetworkFactory.dump(fd, pw, args); 2551 } else { 2552 pw.println("mUntrustedNetworkFactory is not initialized"); 2553 } 2554 pw.println("Wlan Wake Reasons:" + mWifiNative.getWlanWakeReasonCount()); 2555 pw.println(); 2556 updateWifiMetrics(); 2557 mWifiMetrics.dump(fd, pw, args); 2558 pw.println(); 2559 mNetworkFactory.dump(fd, pw, args); 2560 mUntrustedNetworkFactory.dump(fd, pw, args); 2561 pw.println(); 2562 2563 mWifiConfigManager.dump(fd, pw, args); 2564 pw.println(); 2565 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_USER_ACTION); 2566 mWifiLogger.dump(fd, pw, args); 2567 mWifiQualifiedNetworkSelector.dump(fd, pw, args); 2568 dumpIpManager(fd, pw, args); 2569 if (mWifiConnectivityManager != null) { 2570 mWifiConnectivityManager.dump(fd, pw, args); 2571 } 2572 } 2573 2574 public void handleUserSwitch(int userId) { 2575 sendMessage(CMD_USER_SWITCH, userId); 2576 } 2577 2578 /** 2579 * ****************************************************** 2580 * Internal private functions 2581 * ****************************************************** 2582 */ 2583 2584 private void logStateAndMessage(Message message, State state) { 2585 messageHandlingStatus = 0; 2586 if (DBG) { 2587 logd(" " + state.getClass().getSimpleName() + " " + getLogRecString(message)); 2588 } 2589 } 2590 2591 /** 2592 * helper, prints the milli time since boot wi and w/o suspended time 2593 */ 2594 String printTime() { 2595 StringBuilder sb = new StringBuilder(); 2596 sb.append(" rt=").append(SystemClock.uptimeMillis()); 2597 sb.append("/").append(SystemClock.elapsedRealtime()); 2598 return sb.toString(); 2599 } 2600 2601 /** 2602 * Return the additional string to be logged by LogRec, default 2603 * 2604 * @param msg that was processed 2605 * @return information to be logged as a String 2606 */ 2607 protected String getLogRecString(Message msg) { 2608 WifiConfiguration config; 2609 Long now; 2610 String report; 2611 String key; 2612 StringBuilder sb = new StringBuilder(); 2613 if (mScreenOn) { 2614 sb.append("!"); 2615 } 2616 if (messageHandlingStatus != MESSAGE_HANDLING_STATUS_UNKNOWN) { 2617 sb.append("(").append(messageHandlingStatus).append(")"); 2618 } 2619 sb.append(smToString(msg)); 2620 if (msg.sendingUid > 0 && msg.sendingUid != Process.WIFI_UID) { 2621 sb.append(" uid=" + msg.sendingUid); 2622 } 2623 sb.append(" ").append(printTime()); 2624 switch (msg.what) { 2625 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 2626 sb.append(" "); 2627 sb.append(Integer.toString(msg.arg1)); 2628 sb.append(" "); 2629 sb.append(Integer.toString(msg.arg2)); 2630 sb.append(" scanAllowed=").append(allowFullBandScanAndAssociated()); 2631 sb.append(" autojoinAllowed="); 2632 sb.append(mWifiConfigManager.getEnableAutoJoinWhenAssociated()); 2633 sb.append(" withTraffic=").append(getAllowScansWithTraffic()); 2634 sb.append(" tx=").append(mWifiInfo.txSuccessRate); 2635 sb.append("/").append(mWifiConfigManager.MAX_TX_PACKET_FOR_FULL_SCANS); 2636 sb.append(" rx=").append(mWifiInfo.rxSuccessRate); 2637 sb.append("/").append(mWifiConfigManager.MAX_RX_PACKET_FOR_FULL_SCANS); 2638 sb.append(" -> ").append(mConnectedModeGScanOffloadStarted); 2639 break; 2640 case CMD_START_SCAN: 2641 now = System.currentTimeMillis(); 2642 sb.append(" "); 2643 sb.append(Integer.toString(msg.arg1)); 2644 sb.append(" "); 2645 sb.append(Integer.toString(msg.arg2)); 2646 sb.append(" ic="); 2647 sb.append(Integer.toString(sScanAlarmIntentCount)); 2648 if (msg.obj != null) { 2649 Bundle bundle = (Bundle) msg.obj; 2650 Long request = bundle.getLong(SCAN_REQUEST_TIME, 0); 2651 if (request != 0) { 2652 sb.append(" proc(ms):").append(now - request); 2653 } 2654 } 2655 if (mIsScanOngoing) sb.append(" onGoing"); 2656 if (mIsFullScanOngoing) sb.append(" full"); 2657 if (lastStartScanTimeStamp != 0) { 2658 sb.append(" started:").append(lastStartScanTimeStamp); 2659 sb.append(",").append(now - lastStartScanTimeStamp); 2660 } 2661 if (lastScanDuration != 0) { 2662 sb.append(" dur:").append(lastScanDuration); 2663 } 2664 sb.append(" cnt=").append(mDelayedScanCounter); 2665 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2666 sb.append(" f=").append(mWifiInfo.getFrequency()); 2667 sb.append(" sc=").append(mWifiInfo.score); 2668 sb.append(" link=").append(mWifiInfo.getLinkSpeed()); 2669 sb.append(String.format(" tx=%.1f,", mWifiInfo.txSuccessRate)); 2670 sb.append(String.format(" %.1f,", mWifiInfo.txRetriesRate)); 2671 sb.append(String.format(" %.1f ", mWifiInfo.txBadRate)); 2672 sb.append(String.format(" rx=%.1f", mWifiInfo.rxSuccessRate)); 2673 if (lastScanFreqs != null) { 2674 sb.append(" list="); 2675 for(int freq : lastScanFreqs) { 2676 sb.append(freq).append(","); 2677 } 2678 } else { 2679 sb.append(" fiv=").append(fullBandConnectedTimeIntervalMilli); 2680 } 2681 report = reportOnTime(); 2682 if (report != null) { 2683 sb.append(" ").append(report); 2684 } 2685 break; 2686 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 2687 sb.append(" "); 2688 sb.append(Integer.toString(msg.arg1)); 2689 sb.append(" "); 2690 sb.append(Integer.toString(msg.arg2)); 2691 StateChangeResult stateChangeResult = (StateChangeResult) msg.obj; 2692 if (stateChangeResult != null) { 2693 sb.append(stateChangeResult.toString()); 2694 } 2695 break; 2696 case WifiManager.SAVE_NETWORK: 2697 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 2698 sb.append(" "); 2699 sb.append(Integer.toString(msg.arg1)); 2700 sb.append(" "); 2701 sb.append(Integer.toString(msg.arg2)); 2702 if (lastSavedConfigurationAttempt != null) { 2703 sb.append(" ").append(lastSavedConfigurationAttempt.configKey()); 2704 sb.append(" nid=").append(lastSavedConfigurationAttempt.networkId); 2705 if (lastSavedConfigurationAttempt.hiddenSSID) { 2706 sb.append(" hidden"); 2707 } 2708 if (lastSavedConfigurationAttempt.preSharedKey != null 2709 && !lastSavedConfigurationAttempt.preSharedKey.equals("*")) { 2710 sb.append(" hasPSK"); 2711 } 2712 if (lastSavedConfigurationAttempt.ephemeral) { 2713 sb.append(" ephemeral"); 2714 } 2715 if (lastSavedConfigurationAttempt.selfAdded) { 2716 sb.append(" selfAdded"); 2717 } 2718 sb.append(" cuid=").append(lastSavedConfigurationAttempt.creatorUid); 2719 sb.append(" suid=").append(lastSavedConfigurationAttempt.lastUpdateUid); 2720 } 2721 break; 2722 case WifiManager.FORGET_NETWORK: 2723 sb.append(" "); 2724 sb.append(Integer.toString(msg.arg1)); 2725 sb.append(" "); 2726 sb.append(Integer.toString(msg.arg2)); 2727 if (lastForgetConfigurationAttempt != null) { 2728 sb.append(" ").append(lastForgetConfigurationAttempt.configKey()); 2729 sb.append(" nid=").append(lastForgetConfigurationAttempt.networkId); 2730 if (lastForgetConfigurationAttempt.hiddenSSID) { 2731 sb.append(" hidden"); 2732 } 2733 if (lastForgetConfigurationAttempt.preSharedKey != null) { 2734 sb.append(" hasPSK"); 2735 } 2736 if (lastForgetConfigurationAttempt.ephemeral) { 2737 sb.append(" ephemeral"); 2738 } 2739 if (lastForgetConfigurationAttempt.selfAdded) { 2740 sb.append(" selfAdded"); 2741 } 2742 sb.append(" cuid=").append(lastForgetConfigurationAttempt.creatorUid); 2743 sb.append(" suid=").append(lastForgetConfigurationAttempt.lastUpdateUid); 2744 WifiConfiguration.NetworkSelectionStatus netWorkSelectionStatus = 2745 lastForgetConfigurationAttempt.getNetworkSelectionStatus(); 2746 sb.append(" ajst=").append( 2747 netWorkSelectionStatus.getNetworkStatusString()); 2748 } 2749 break; 2750 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 2751 sb.append(" "); 2752 sb.append(Integer.toString(msg.arg1)); 2753 sb.append(" "); 2754 sb.append(Integer.toString(msg.arg2)); 2755 String bssid = (String) msg.obj; 2756 if (bssid != null && bssid.length() > 0) { 2757 sb.append(" "); 2758 sb.append(bssid); 2759 } 2760 sb.append(" blacklist=" + Boolean.toString(didBlackListBSSID)); 2761 break; 2762 case WifiMonitor.SCAN_RESULTS_EVENT: 2763 sb.append(" "); 2764 sb.append(Integer.toString(msg.arg1)); 2765 sb.append(" "); 2766 sb.append(Integer.toString(msg.arg2)); 2767 if (mScanResults != null) { 2768 sb.append(" found="); 2769 sb.append(mScanResults.size()); 2770 } 2771 sb.append(" known=").append(mNumScanResultsKnown); 2772 sb.append(" got=").append(mNumScanResultsReturned); 2773 if (lastScanDuration != 0) { 2774 sb.append(" dur:").append(lastScanDuration); 2775 } 2776 if (mOnTime != 0) { 2777 sb.append(" on:").append(mOnTimeThisScan).append(",").append(mOnTimeScan); 2778 sb.append(",").append(mOnTime); 2779 } 2780 if (mTxTime != 0) { 2781 sb.append(" tx:").append(mTxTimeThisScan).append(",").append(mTxTimeScan); 2782 sb.append(",").append(mTxTime); 2783 } 2784 if (mRxTime != 0) { 2785 sb.append(" rx:").append(mRxTimeThisScan).append(",").append(mRxTimeScan); 2786 sb.append(",").append(mRxTime); 2787 } 2788 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 2789 sb.append(String.format(" con=%d", mConnectionRequests)); 2790 key = mWifiConfigManager.getLastSelectedConfiguration(); 2791 if (key != null) { 2792 sb.append(" last=").append(key); 2793 } 2794 break; 2795 case WifiMonitor.SCAN_FAILED_EVENT: 2796 break; 2797 case WifiMonitor.NETWORK_CONNECTION_EVENT: 2798 sb.append(" "); 2799 sb.append(Integer.toString(msg.arg1)); 2800 sb.append(" "); 2801 sb.append(Integer.toString(msg.arg2)); 2802 sb.append(" ").append(mLastBssid); 2803 sb.append(" nid=").append(mLastNetworkId); 2804 config = getCurrentWifiConfiguration(); 2805 if (config != null) { 2806 sb.append(" ").append(config.configKey()); 2807 } 2808 key = mWifiConfigManager.getLastSelectedConfiguration(); 2809 if (key != null) { 2810 sb.append(" last=").append(key); 2811 } 2812 break; 2813 case CMD_TARGET_BSSID: 2814 case CMD_ASSOCIATED_BSSID: 2815 sb.append(" "); 2816 sb.append(Integer.toString(msg.arg1)); 2817 sb.append(" "); 2818 sb.append(Integer.toString(msg.arg2)); 2819 if (msg.obj != null) { 2820 sb.append(" BSSID=").append((String) msg.obj); 2821 } 2822 if (mTargetRoamBSSID != null) { 2823 sb.append(" Target=").append(mTargetRoamBSSID); 2824 } 2825 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 2826 break; 2827 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 2828 if (msg.obj != null) { 2829 sb.append(" ").append((String) msg.obj); 2830 } 2831 sb.append(" nid=").append(msg.arg1); 2832 sb.append(" reason=").append(msg.arg2); 2833 if (mLastBssid != null) { 2834 sb.append(" lastbssid=").append(mLastBssid); 2835 } 2836 if (mWifiInfo.getFrequency() != -1) { 2837 sb.append(" freq=").append(mWifiInfo.getFrequency()); 2838 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2839 } 2840 if (linkDebouncing) { 2841 sb.append(" debounce"); 2842 } 2843 break; 2844 case WifiMonitor.SSID_TEMP_DISABLED: 2845 case WifiMonitor.SSID_REENABLED: 2846 sb.append(" nid=").append(msg.arg1); 2847 if (msg.obj != null) { 2848 sb.append(" ").append((String) msg.obj); 2849 } 2850 config = getCurrentWifiConfiguration(); 2851 if (config != null) { 2852 WifiConfiguration.NetworkSelectionStatus netWorkSelectionStatus = 2853 config.getNetworkSelectionStatus(); 2854 sb.append(" cur=").append(config.configKey()); 2855 sb.append(" ajst=").append(netWorkSelectionStatus.getNetworkStatusString()); 2856 if (config.selfAdded) { 2857 sb.append(" selfAdded"); 2858 } 2859 if (config.status != 0) { 2860 sb.append(" st=").append(config.status); 2861 sb.append(" rs=").append( 2862 netWorkSelectionStatus.getNetworkDisableReasonString()); 2863 } 2864 if (config.lastConnected != 0) { 2865 now = System.currentTimeMillis(); 2866 sb.append(" lastconn=").append(now - config.lastConnected).append("(ms)"); 2867 } 2868 if (mLastBssid != null) { 2869 sb.append(" lastbssid=").append(mLastBssid); 2870 } 2871 if (mWifiInfo.getFrequency() != -1) { 2872 sb.append(" freq=").append(mWifiInfo.getFrequency()); 2873 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2874 sb.append(" bssid=").append(mWifiInfo.getBSSID()); 2875 } 2876 } 2877 break; 2878 case CMD_RSSI_POLL: 2879 case CMD_UNWANTED_NETWORK: 2880 case WifiManager.RSSI_PKTCNT_FETCH: 2881 sb.append(" "); 2882 sb.append(Integer.toString(msg.arg1)); 2883 sb.append(" "); 2884 sb.append(Integer.toString(msg.arg2)); 2885 if (mWifiInfo.getSSID() != null) 2886 if (mWifiInfo.getSSID() != null) 2887 sb.append(" ").append(mWifiInfo.getSSID()); 2888 if (mWifiInfo.getBSSID() != null) 2889 sb.append(" ").append(mWifiInfo.getBSSID()); 2890 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2891 sb.append(" f=").append(mWifiInfo.getFrequency()); 2892 sb.append(" sc=").append(mWifiInfo.score); 2893 sb.append(" link=").append(mWifiInfo.getLinkSpeed()); 2894 sb.append(String.format(" tx=%.1f,", mWifiInfo.txSuccessRate)); 2895 sb.append(String.format(" %.1f,", mWifiInfo.txRetriesRate)); 2896 sb.append(String.format(" %.1f ", mWifiInfo.txBadRate)); 2897 sb.append(String.format(" rx=%.1f", mWifiInfo.rxSuccessRate)); 2898 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 2899 report = reportOnTime(); 2900 if (report != null) { 2901 sb.append(" ").append(report); 2902 } 2903 if (mWifiScoreReport != null) { 2904 sb.append(mWifiScoreReport.getReport()); 2905 } 2906 if (mConnectedModeGScanOffloadStarted) { 2907 sb.append(" offload-started periodMilli " + mGScanPeriodMilli); 2908 } else { 2909 sb.append(" offload-stopped"); 2910 } 2911 break; 2912 case CMD_AUTO_CONNECT: 2913 case WifiManager.CONNECT_NETWORK: 2914 sb.append(" "); 2915 sb.append(Integer.toString(msg.arg1)); 2916 sb.append(" "); 2917 sb.append(Integer.toString(msg.arg2)); 2918 config = mWifiConfigManager.getWifiConfiguration(msg.arg1); 2919 if (config != null) { 2920 sb.append(" ").append(config.configKey()); 2921 if (config.visibility != null) { 2922 sb.append(" ").append(config.visibility.toString()); 2923 } 2924 } 2925 if (mTargetRoamBSSID != null) { 2926 sb.append(" ").append(mTargetRoamBSSID); 2927 } 2928 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 2929 config = getCurrentWifiConfiguration(); 2930 if (config != null) { 2931 sb.append(config.configKey()); 2932 if (config.visibility != null) { 2933 sb.append(" ").append(config.visibility.toString()); 2934 } 2935 } 2936 break; 2937 case CMD_AUTO_ROAM: 2938 sb.append(" "); 2939 sb.append(Integer.toString(msg.arg1)); 2940 sb.append(" "); 2941 sb.append(Integer.toString(msg.arg2)); 2942 ScanResult result = (ScanResult) msg.obj; 2943 if (result != null) { 2944 now = System.currentTimeMillis(); 2945 sb.append(" bssid=").append(result.BSSID); 2946 sb.append(" rssi=").append(result.level); 2947 sb.append(" freq=").append(result.frequency); 2948 if (result.seen > 0 && result.seen < now) { 2949 sb.append(" seen=").append(now - result.seen); 2950 } else { 2951 // Somehow the timestamp for this scan result is inconsistent 2952 sb.append(" !seen=").append(result.seen); 2953 } 2954 } 2955 if (mTargetRoamBSSID != null) { 2956 sb.append(" ").append(mTargetRoamBSSID); 2957 } 2958 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 2959 sb.append(" fail count=").append(Integer.toString(mRoamFailCount)); 2960 break; 2961 case CMD_ADD_OR_UPDATE_NETWORK: 2962 sb.append(" "); 2963 sb.append(Integer.toString(msg.arg1)); 2964 sb.append(" "); 2965 sb.append(Integer.toString(msg.arg2)); 2966 if (msg.obj != null) { 2967 config = (WifiConfiguration) msg.obj; 2968 sb.append(" ").append(config.configKey()); 2969 sb.append(" prio=").append(config.priority); 2970 sb.append(" status=").append(config.status); 2971 if (config.BSSID != null) { 2972 sb.append(" ").append(config.BSSID); 2973 } 2974 WifiConfiguration curConfig = getCurrentWifiConfiguration(); 2975 if (curConfig != null) { 2976 if (curConfig.configKey().equals(config.configKey())) { 2977 sb.append(" is current"); 2978 } else { 2979 sb.append(" current=").append(curConfig.configKey()); 2980 sb.append(" prio=").append(curConfig.priority); 2981 sb.append(" status=").append(curConfig.status); 2982 } 2983 } 2984 } 2985 break; 2986 case WifiManager.DISABLE_NETWORK: 2987 case CMD_ENABLE_NETWORK: 2988 sb.append(" "); 2989 sb.append(Integer.toString(msg.arg1)); 2990 sb.append(" "); 2991 sb.append(Integer.toString(msg.arg2)); 2992 key = mWifiConfigManager.getLastSelectedConfiguration(); 2993 if (key != null) { 2994 sb.append(" last=").append(key); 2995 } 2996 config = mWifiConfigManager.getWifiConfiguration(msg.arg1); 2997 if (config != null && (key == null || !config.configKey().equals(key))) { 2998 sb.append(" target=").append(key); 2999 } 3000 break; 3001 case CMD_GET_CONFIGURED_NETWORKS: 3002 sb.append(" "); 3003 sb.append(Integer.toString(msg.arg1)); 3004 sb.append(" "); 3005 sb.append(Integer.toString(msg.arg2)); 3006 sb.append(" num=").append(mWifiConfigManager.getConfiguredNetworksSize()); 3007 break; 3008 case DhcpClient.CMD_PRE_DHCP_ACTION: 3009 sb.append(" "); 3010 sb.append(Integer.toString(msg.arg1)); 3011 sb.append(" "); 3012 sb.append(Integer.toString(msg.arg2)); 3013 sb.append(" txpkts=").append(mWifiInfo.txSuccess); 3014 sb.append(",").append(mWifiInfo.txBad); 3015 sb.append(",").append(mWifiInfo.txRetries); 3016 break; 3017 case DhcpClient.CMD_POST_DHCP_ACTION: 3018 sb.append(" "); 3019 sb.append(Integer.toString(msg.arg1)); 3020 sb.append(" "); 3021 sb.append(Integer.toString(msg.arg2)); 3022 if (msg.arg1 == DhcpClient.DHCP_SUCCESS) { 3023 sb.append(" OK "); 3024 } else if (msg.arg1 == DhcpClient.DHCP_FAILURE) { 3025 sb.append(" FAIL "); 3026 } 3027 if (mLinkProperties != null) { 3028 sb.append(" "); 3029 sb.append(getLinkPropertiesSummary(mLinkProperties)); 3030 } 3031 break; 3032 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 3033 sb.append(" "); 3034 sb.append(Integer.toString(msg.arg1)); 3035 sb.append(" "); 3036 sb.append(Integer.toString(msg.arg2)); 3037 if (msg.obj != null) { 3038 NetworkInfo info = (NetworkInfo) msg.obj; 3039 NetworkInfo.State state = info.getState(); 3040 NetworkInfo.DetailedState detailedState = info.getDetailedState(); 3041 if (state != null) { 3042 sb.append(" st=").append(state); 3043 } 3044 if (detailedState != null) { 3045 sb.append("/").append(detailedState); 3046 } 3047 } 3048 break; 3049 case CMD_IP_CONFIGURATION_LOST: 3050 int count = -1; 3051 WifiConfiguration c = getCurrentWifiConfiguration(); 3052 if (c != null) { 3053 count = c.getNetworkSelectionStatus().getDisableReasonCounter( 3054 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3055 } 3056 sb.append(" "); 3057 sb.append(Integer.toString(msg.arg1)); 3058 sb.append(" "); 3059 sb.append(Integer.toString(msg.arg2)); 3060 sb.append(" failures: "); 3061 sb.append(Integer.toString(count)); 3062 sb.append("/"); 3063 sb.append(Integer.toString(mWifiConfigManager.getMaxDhcpRetries())); 3064 if (mWifiInfo.getBSSID() != null) { 3065 sb.append(" ").append(mWifiInfo.getBSSID()); 3066 } 3067 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 3068 break; 3069 case CMD_UPDATE_LINKPROPERTIES: 3070 sb.append(" "); 3071 sb.append(Integer.toString(msg.arg1)); 3072 sb.append(" "); 3073 sb.append(Integer.toString(msg.arg2)); 3074 if (mLinkProperties != null) { 3075 sb.append(" "); 3076 sb.append(getLinkPropertiesSummary(mLinkProperties)); 3077 } 3078 break; 3079 case CMD_IP_REACHABILITY_LOST: 3080 if (msg.obj != null) { 3081 sb.append(" ").append((String) msg.obj); 3082 } 3083 break; 3084 case CMD_INSTALL_PACKET_FILTER: 3085 sb.append(" len=" + ((byte[])msg.obj).length); 3086 break; 3087 case CMD_SET_FALLBACK_PACKET_FILTERING: 3088 sb.append(" enabled=" + (boolean)msg.obj); 3089 break; 3090 case CMD_ROAM_WATCHDOG_TIMER: 3091 sb.append(" "); 3092 sb.append(Integer.toString(msg.arg1)); 3093 sb.append(" "); 3094 sb.append(Integer.toString(msg.arg2)); 3095 sb.append(" cur=").append(roamWatchdogCount); 3096 break; 3097 case CMD_DISCONNECTING_WATCHDOG_TIMER: 3098 sb.append(" "); 3099 sb.append(Integer.toString(msg.arg1)); 3100 sb.append(" "); 3101 sb.append(Integer.toString(msg.arg2)); 3102 sb.append(" cur=").append(disconnectingWatchdogCount); 3103 break; 3104 case CMD_START_RSSI_MONITORING_OFFLOAD: 3105 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 3106 case CMD_RSSI_THRESHOLD_BREACH: 3107 sb.append(" rssi="); 3108 sb.append(Integer.toString(msg.arg1)); 3109 sb.append(" thresholds="); 3110 sb.append(Arrays.toString(mRssiRanges)); 3111 break; 3112 case CMD_USER_SWITCH: 3113 sb.append(" userId="); 3114 sb.append(Integer.toString(msg.arg1)); 3115 break; 3116 case CMD_IPV4_PROVISIONING_SUCCESS: 3117 sb.append(" "); 3118 if (msg.arg1 == DhcpClient.DHCP_SUCCESS) { 3119 sb.append("DHCP_OK"); 3120 } else if (msg.arg1 == CMD_STATIC_IP_SUCCESS) { 3121 sb.append("STATIC_OK"); 3122 } else { 3123 sb.append(Integer.toString(msg.arg1)); 3124 } 3125 break; 3126 case CMD_IPV4_PROVISIONING_FAILURE: 3127 sb.append(" "); 3128 if (msg.arg1 == DhcpClient.DHCP_FAILURE) { 3129 sb.append("DHCP_FAIL"); 3130 } else if (msg.arg1 == CMD_STATIC_IP_FAILURE) { 3131 sb.append("STATIC_FAIL"); 3132 } else { 3133 sb.append(Integer.toString(msg.arg1)); 3134 } 3135 break; 3136 default: 3137 sb.append(" "); 3138 sb.append(Integer.toString(msg.arg1)); 3139 sb.append(" "); 3140 sb.append(Integer.toString(msg.arg2)); 3141 break; 3142 } 3143 3144 return sb.toString(); 3145 } 3146 3147 private void handleScreenStateChanged(boolean screenOn) { 3148 mScreenOn = screenOn; 3149 if (DBG) { 3150 logd(" handleScreenStateChanged Enter: screenOn=" + screenOn 3151 + " mUserWantsSuspendOpt=" + mUserWantsSuspendOpt 3152 + " state " + getCurrentState().getName() 3153 + " suppState:" + mSupplicantStateTracker.getSupplicantStateName()); 3154 } 3155 enableRssiPolling(screenOn); 3156 if (mUserWantsSuspendOpt.get()) { 3157 if (screenOn) { 3158 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, 0); 3159 } else { 3160 // Allow 2s for suspend optimizations to be set 3161 mSuspendWakeLock.acquire(2000); 3162 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, 0); 3163 } 3164 } 3165 mScreenBroadcastReceived.set(true); 3166 3167 getWifiLinkLayerStats(false); 3168 mOnTimeScreenStateChange = mOnTime; 3169 lastScreenStateChangeTimeStamp = lastLinkLayerStatsUpdate; 3170 3171 mWifiMetrics.setScreenState(screenOn); 3172 3173 if (mWifiConnectivityManager != null) { 3174 mWifiConnectivityManager.handleScreenStateChanged(screenOn); 3175 } 3176 3177 if (DBG) log("handleScreenStateChanged Exit: " + screenOn); 3178 } 3179 3180 private void checkAndSetConnectivityInstance() { 3181 if (mCm == null) { 3182 mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 3183 } 3184 } 3185 3186 3187 /** 3188 * Set the frequency band from the system setting value, if any. 3189 */ 3190 private void setFrequencyBand() { 3191 int band = mFacade.getIntegerSetting(mContext, 3192 Settings.Global.WIFI_FREQUENCY_BAND, WifiManager.WIFI_FREQUENCY_BAND_AUTO); 3193 3194 if (mWifiNative.setBand(band)) { 3195 mFrequencyBand.set(band); 3196 if (mWifiConnectivityManager != null) { 3197 mWifiConnectivityManager.setUserPreferredBand(band); 3198 } 3199 if (DBG) { 3200 logd("done set frequency band " + band); 3201 } 3202 } else { 3203 loge("Failed to set frequency band " + band); 3204 } 3205 } 3206 3207 private void setSuspendOptimizationsNative(int reason, boolean enabled) { 3208 if (DBG) { 3209 log("setSuspendOptimizationsNative: " + reason + " " + enabled 3210 + " -want " + mUserWantsSuspendOpt.get() 3211 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 3212 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 3213 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 3214 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 3215 } 3216 //mWifiNative.setSuspendOptimizations(enabled); 3217 3218 if (enabled) { 3219 mSuspendOptNeedsDisabled &= ~reason; 3220 /* None of dhcp, screen or highperf need it disabled and user wants it enabled */ 3221 if (mSuspendOptNeedsDisabled == 0 && mUserWantsSuspendOpt.get()) { 3222 if (DBG) { 3223 log("setSuspendOptimizationsNative do it " + reason + " " + enabled 3224 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 3225 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 3226 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 3227 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 3228 } 3229 mWifiNative.setSuspendOptimizations(true); 3230 } 3231 } else { 3232 mSuspendOptNeedsDisabled |= reason; 3233 mWifiNative.setSuspendOptimizations(false); 3234 } 3235 } 3236 3237 private void setSuspendOptimizations(int reason, boolean enabled) { 3238 if (DBG) log("setSuspendOptimizations: " + reason + " " + enabled); 3239 if (enabled) { 3240 mSuspendOptNeedsDisabled &= ~reason; 3241 } else { 3242 mSuspendOptNeedsDisabled |= reason; 3243 } 3244 if (DBG) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 3245 } 3246 3247 private void setWifiState(int wifiState) { 3248 final int previousWifiState = mWifiState.get(); 3249 3250 try { 3251 if (wifiState == WIFI_STATE_ENABLED) { 3252 mBatteryStats.noteWifiOn(); 3253 } else if (wifiState == WIFI_STATE_DISABLED) { 3254 mBatteryStats.noteWifiOff(); 3255 } 3256 } catch (RemoteException e) { 3257 loge("Failed to note battery stats in wifi"); 3258 } 3259 3260 mWifiState.set(wifiState); 3261 3262 if (DBG) log("setWifiState: " + syncGetWifiStateByName()); 3263 3264 final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); 3265 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3266 intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState); 3267 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState); 3268 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3269 } 3270 3271 private void setWifiApState(int wifiApState, int reason) { 3272 final int previousWifiApState = mWifiApState.get(); 3273 3274 try { 3275 if (wifiApState == WIFI_AP_STATE_ENABLED) { 3276 mBatteryStats.noteWifiOn(); 3277 } else if (wifiApState == WIFI_AP_STATE_DISABLED) { 3278 mBatteryStats.noteWifiOff(); 3279 } 3280 } catch (RemoteException e) { 3281 loge("Failed to note battery stats in wifi"); 3282 } 3283 3284 // Update state 3285 mWifiApState.set(wifiApState); 3286 3287 if (DBG) log("setWifiApState: " + syncGetWifiApStateByName()); 3288 3289 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 3290 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3291 intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState); 3292 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState); 3293 if (wifiApState == WifiManager.WIFI_AP_STATE_FAILED) { 3294 //only set reason number when softAP start failed 3295 intent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, reason); 3296 } 3297 3298 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3299 } 3300 3301 private void setScanResults() { 3302 mNumScanResultsKnown = 0; 3303 mNumScanResultsReturned = 0; 3304 3305 ArrayList<ScanDetail> scanResults = mWifiNative.getScanResults(); 3306 3307 if (scanResults.isEmpty()) { 3308 mScanResults = new ArrayList<>(); 3309 return; 3310 } 3311 3312 mWifiConfigManager.trimANQPCache(false); 3313 3314 boolean connected = mLastBssid != null; 3315 long activeBssid = 0L; 3316 if (connected) { 3317 try { 3318 activeBssid = Utils.parseMac(mLastBssid); 3319 } catch (IllegalArgumentException iae) { 3320 connected = false; 3321 } 3322 } 3323 3324 synchronized (mScanResultsLock) { 3325 ScanDetail activeScanDetail = null; 3326 mScanResults = scanResults; 3327 mNumScanResultsReturned = mScanResults.size(); 3328 for (ScanDetail resultDetail : mScanResults) { 3329 if (connected && resultDetail.getNetworkDetail().getBSSID() == activeBssid) { 3330 if (activeScanDetail == null 3331 || activeScanDetail.getNetworkDetail().getBSSID() != activeBssid 3332 || activeScanDetail.getNetworkDetail().getANQPElements() == null) { 3333 activeScanDetail = resultDetail; 3334 } 3335 } 3336 // Cache DTIM values parsed from the beacon frame Traffic Indication Map (TIM) 3337 // Information Element (IE), into the associated WifiConfigurations. Most of the 3338 // time there is no TIM IE in the scan result (Probe Response instead of Beacon 3339 // Frame), these scanResult DTIM's are negative and ignored. 3340 // <TODO> Cache these per BSSID, since dtim can change vary 3341 NetworkDetail networkDetail = resultDetail.getNetworkDetail(); 3342 if (networkDetail != null && networkDetail.getDtimInterval() > 0) { 3343 List<WifiConfiguration> associatedWifiConfigurations = 3344 mWifiConfigManager.updateSavedNetworkWithNewScanDetail(resultDetail); 3345 if (associatedWifiConfigurations != null) { 3346 for (WifiConfiguration associatedConf : associatedWifiConfigurations) { 3347 if (associatedConf != null) { 3348 associatedConf.dtimInterval = networkDetail.getDtimInterval(); 3349 } 3350 } 3351 } 3352 } 3353 } 3354 mActiveScanDetail = activeScanDetail; 3355 } 3356 3357 if (linkDebouncing) { 3358 // If debouncing, we dont re-select a SSID or BSSID hence 3359 // there is no need to call the network selection code 3360 // in WifiAutoJoinController, instead, 3361 // just try to reconnect to the same SSID by triggering a roam 3362 // The third parameter 1 means roam not from network selection but debouncing 3363 sendMessage(CMD_AUTO_ROAM, mLastNetworkId, 1, null); 3364 } 3365 } 3366 3367 public ScanDetail getActiveScanDetail() { 3368 synchronized (mScanResultsLock) { 3369 return mActiveScanDetail; 3370 } 3371 } 3372 3373 /* 3374 * Fetch RSSI, linkspeed, and frequency on current connection 3375 */ 3376 private void fetchRssiLinkSpeedAndFrequencyNative() { 3377 Integer newRssi = null; 3378 Integer newLinkSpeed = null; 3379 Integer newFrequency = null; 3380 3381 String signalPoll = mWifiNative.signalPoll(); 3382 3383 if (signalPoll != null) { 3384 String[] lines = signalPoll.split("\n"); 3385 for (String line : lines) { 3386 String[] prop = line.split("="); 3387 if (prop.length < 2) continue; 3388 try { 3389 if (prop[0].equals("RSSI")) { 3390 newRssi = Integer.parseInt(prop[1]); 3391 } else if (prop[0].equals("LINKSPEED")) { 3392 newLinkSpeed = Integer.parseInt(prop[1]); 3393 } else if (prop[0].equals("FREQUENCY")) { 3394 newFrequency = Integer.parseInt(prop[1]); 3395 } 3396 } catch (NumberFormatException e) { 3397 //Ignore, defaults on rssi and linkspeed are assigned 3398 } 3399 } 3400 } 3401 3402 if (DBG) { 3403 logd("fetchRssiLinkSpeedAndFrequencyNative rssi=" + newRssi + 3404 " linkspeed=" + newLinkSpeed + " freq=" + newFrequency); 3405 } 3406 3407 if (newRssi != null && newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) { 3408 // screen out invalid values 3409 /* some implementations avoid negative values by adding 256 3410 * so we need to adjust for that here. 3411 */ 3412 if (newRssi > 0) newRssi -= 256; 3413 mWifiInfo.setRssi(newRssi); 3414 /* 3415 * Rather then sending the raw RSSI out every time it 3416 * changes, we precalculate the signal level that would 3417 * be displayed in the status bar, and only send the 3418 * broadcast if that much more coarse-grained number 3419 * changes. This cuts down greatly on the number of 3420 * broadcasts, at the cost of not informing others 3421 * interested in RSSI of all the changes in signal 3422 * level. 3423 */ 3424 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, WifiManager.RSSI_LEVELS); 3425 if (newSignalLevel != mLastSignalLevel) { 3426 updateCapabilities(getCurrentWifiConfiguration()); 3427 sendRssiChangeBroadcast(newRssi); 3428 } 3429 mLastSignalLevel = newSignalLevel; 3430 } else { 3431 mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); 3432 updateCapabilities(getCurrentWifiConfiguration()); 3433 } 3434 3435 if (newLinkSpeed != null) { 3436 mWifiInfo.setLinkSpeed(newLinkSpeed); 3437 } 3438 if (newFrequency != null && newFrequency > 0) { 3439 if (ScanResult.is5GHz(newFrequency)) { 3440 mWifiConnectionStatistics.num5GhzConnected++; 3441 } 3442 if (ScanResult.is24GHz(newFrequency)) { 3443 mWifiConnectionStatistics.num24GhzConnected++; 3444 } 3445 mWifiInfo.setFrequency(newFrequency); 3446 } 3447 mWifiConfigManager.updateConfiguration(mWifiInfo); 3448 } 3449 3450 /** 3451 * Determine if we need to switch network: 3452 * - the delta determine the urgency to switch and/or or the expected evilness of the disruption 3453 * - match the uregncy of the switch versus the packet usage at the interface 3454 */ 3455 boolean shouldSwitchNetwork(int networkDelta) { 3456 int delta; 3457 if (networkDelta <= 0) { 3458 return false; 3459 } 3460 delta = networkDelta; 3461 if (!mWifiConfigManager.getEnableAutoJoinWhenAssociated() 3462 && mWifiInfo.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) { 3463 // If AutoJoin while associated is not enabled, 3464 // we should never switch network when already associated 3465 delta = -1000; 3466 } else { 3467 // TODO: Look at per AC packet count, do not switch if VO/VI traffic is present 3468 // TODO: at the interface. We should also discriminate between ucast and mcast, 3469 // TODO: since the rxSuccessRate include all the bonjour and Ipv6 3470 // TODO: broadcasts 3471 if ((mWifiInfo.txSuccessRate > 20) || (mWifiInfo.rxSuccessRate > 80)) { 3472 delta -= 999; 3473 } else if ((mWifiInfo.txSuccessRate > 5) || (mWifiInfo.rxSuccessRate > 30)) { 3474 delta -= 6; 3475 } 3476 logd("shouldSwitchNetwork " 3477 + " txSuccessRate=" + String.format("%.2f", mWifiInfo.txSuccessRate) 3478 + " rxSuccessRate=" + String.format("%.2f", mWifiInfo.rxSuccessRate) 3479 + " delta " + networkDelta + " -> " + delta); 3480 } 3481 if (delta > 0) { 3482 return true; 3483 } 3484 return false; 3485 } 3486 3487 // Polling has completed, hence we wont have a score anymore 3488 private void cleanWifiScore() { 3489 mWifiInfo.txBadRate = 0; 3490 mWifiInfo.txSuccessRate = 0; 3491 mWifiInfo.txRetriesRate = 0; 3492 mWifiInfo.rxSuccessRate = 0; 3493 mWifiScoreReport = null; 3494 } 3495 3496 // Object holding most recent wifi score report and bad Linkspeed count 3497 WifiScoreReport mWifiScoreReport = null; 3498 3499 public double getTxPacketRate() { 3500 return mWifiInfo.txSuccessRate; 3501 } 3502 3503 public double getRxPacketRate() { 3504 return mWifiInfo.rxSuccessRate; 3505 } 3506 3507 /** 3508 * Fetch TX packet counters on current connection 3509 */ 3510 private void fetchPktcntNative(RssiPacketCountInfo info) { 3511 String pktcntPoll = mWifiNative.pktcntPoll(); 3512 3513 if (pktcntPoll != null) { 3514 String[] lines = pktcntPoll.split("\n"); 3515 for (String line : lines) { 3516 String[] prop = line.split("="); 3517 if (prop.length < 2) continue; 3518 try { 3519 if (prop[0].equals("TXGOOD")) { 3520 info.txgood = Integer.parseInt(prop[1]); 3521 } else if (prop[0].equals("TXBAD")) { 3522 info.txbad = Integer.parseInt(prop[1]); 3523 } 3524 } catch (NumberFormatException e) { 3525 // Ignore 3526 } 3527 } 3528 } 3529 } 3530 3531 private void updateLinkProperties(LinkProperties newLp) { 3532 if (DBG) { 3533 log("Link configuration changed for netId: " + mLastNetworkId 3534 + " old: " + mLinkProperties + " new: " + newLp); 3535 } 3536 // We own this instance of LinkProperties because IpManager passes us a copy. 3537 mLinkProperties = newLp; 3538 if (mNetworkAgent != null) { 3539 mNetworkAgent.sendLinkProperties(mLinkProperties); 3540 } 3541 3542 if (getNetworkDetailedState() == DetailedState.CONNECTED) { 3543 // If anything has changed and we're already connected, send out a notification. 3544 // TODO: Update all callers to use NetworkCallbacks and delete this. 3545 sendLinkConfigurationChangedBroadcast(); 3546 } 3547 3548 if (DBG) { 3549 StringBuilder sb = new StringBuilder(); 3550 sb.append("updateLinkProperties nid: " + mLastNetworkId); 3551 sb.append(" state: " + getNetworkDetailedState()); 3552 3553 if (mLinkProperties != null) { 3554 sb.append(" "); 3555 sb.append(getLinkPropertiesSummary(mLinkProperties)); 3556 } 3557 logd(sb.toString()); 3558 } 3559 } 3560 3561 /** 3562 * Clears all our link properties. 3563 */ 3564 private void clearLinkProperties() { 3565 // Clear the link properties obtained from DHCP. The only caller of this 3566 // function has already called IpManager#stop(), which clears its state. 3567 synchronized (mDhcpResultsLock) { 3568 if (mDhcpResults != null) { 3569 mDhcpResults.clear(); 3570 } 3571 } 3572 3573 // Now clear the merged link properties. 3574 mLinkProperties.clear(); 3575 if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties); 3576 } 3577 3578 /** 3579 * try to update default route MAC address. 3580 */ 3581 private String updateDefaultRouteMacAddress(int timeout) { 3582 String address = null; 3583 for (RouteInfo route : mLinkProperties.getRoutes()) { 3584 if (route.isDefaultRoute() && route.hasGateway()) { 3585 InetAddress gateway = route.getGateway(); 3586 if (gateway instanceof Inet4Address) { 3587 if (DBG) { 3588 logd("updateDefaultRouteMacAddress found Ipv4 default :" 3589 + gateway.getHostAddress()); 3590 } 3591 address = macAddressFromRoute(gateway.getHostAddress()); 3592 /* The gateway's MAC address is known */ 3593 if ((address == null) && (timeout > 0)) { 3594 boolean reachable = false; 3595 try { 3596 reachable = gateway.isReachable(timeout); 3597 } catch (Exception e) { 3598 loge("updateDefaultRouteMacAddress exception reaching :" 3599 + gateway.getHostAddress()); 3600 3601 } finally { 3602 if (reachable == true) { 3603 3604 address = macAddressFromRoute(gateway.getHostAddress()); 3605 if (DBG) { 3606 logd("updateDefaultRouteMacAddress reachable (tried again) :" 3607 + gateway.getHostAddress() + " found " + address); 3608 } 3609 } 3610 } 3611 } 3612 if (address != null) { 3613 mWifiConfigManager.setDefaultGwMacAddress(mLastNetworkId, address); 3614 } 3615 } 3616 } 3617 } 3618 return address; 3619 } 3620 3621 void sendScanResultsAvailableBroadcast(boolean scanSucceeded) { 3622 Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 3623 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3624 intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, scanSucceeded); 3625 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 3626 } 3627 3628 private void sendRssiChangeBroadcast(final int newRssi) { 3629 try { 3630 mBatteryStats.noteWifiRssiChanged(newRssi); 3631 } catch (RemoteException e) { 3632 // Won't happen. 3633 } 3634 Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION); 3635 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3636 intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi); 3637 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3638 } 3639 3640 private void sendNetworkStateChangeBroadcast(String bssid) { 3641 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); 3642 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3643 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo)); 3644 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties)); 3645 if (bssid != null) 3646 intent.putExtra(WifiManager.EXTRA_BSSID, bssid); 3647 if (mNetworkInfo.getDetailedState() == DetailedState.VERIFYING_POOR_LINK || 3648 mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) { 3649 // We no longer report MAC address to third-parties and our code does 3650 // not rely on this broadcast, so just send the default MAC address. 3651 fetchRssiLinkSpeedAndFrequencyNative(); 3652 WifiInfo sentWifiInfo = new WifiInfo(mWifiInfo); 3653 sentWifiInfo.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS); 3654 intent.putExtra(WifiManager.EXTRA_WIFI_INFO, sentWifiInfo); 3655 } 3656 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3657 } 3658 3659 private WifiInfo getWiFiInfoForUid(int uid) { 3660 if (Binder.getCallingUid() == Process.myUid()) { 3661 return mWifiInfo; 3662 } 3663 3664 WifiInfo result = new WifiInfo(mWifiInfo); 3665 result.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS); 3666 3667 IBinder binder = mFacade.getService("package"); 3668 IPackageManager packageManager = IPackageManager.Stub.asInterface(binder); 3669 3670 try { 3671 if (packageManager.checkUidPermission(Manifest.permission.LOCAL_MAC_ADDRESS, 3672 uid) == PackageManager.PERMISSION_GRANTED) { 3673 result.setMacAddress(mWifiInfo.getMacAddress()); 3674 } 3675 } catch (RemoteException e) { 3676 Log.e(TAG, "Error checking receiver permission", e); 3677 } 3678 3679 return result; 3680 } 3681 3682 private void sendLinkConfigurationChangedBroadcast() { 3683 Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); 3684 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3685 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties)); 3686 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 3687 } 3688 3689 private void sendSupplicantConnectionChangedBroadcast(boolean connected) { 3690 Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 3691 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3692 intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected); 3693 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 3694 } 3695 3696 /** 3697 * Record the detailed state of a network. 3698 * 3699 * @param state the new {@code DetailedState} 3700 */ 3701 private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) { 3702 boolean hidden = false; 3703 3704 if (linkDebouncing || isRoaming()) { 3705 // There is generally a confusion in the system about colluding 3706 // WiFi Layer 2 state (as reported by supplicant) and the Network state 3707 // which leads to multiple confusion. 3708 // 3709 // If link is de-bouncing or roaming, we already have an IP address 3710 // as well we were connected and are doing L2 cycles of 3711 // reconnecting or renewing IP address to check that we still have it 3712 // This L2 link flapping should ne be reflected into the Network state 3713 // which is the state of the WiFi Network visible to Layer 3 and applications 3714 // Note that once debouncing and roaming are completed, we will 3715 // set the Network state to where it should be, or leave it as unchanged 3716 // 3717 hidden = true; 3718 } 3719 if (DBG) { 3720 log("setDetailed state, old =" 3721 + mNetworkInfo.getDetailedState() + " and new state=" + state 3722 + " hidden=" + hidden); 3723 } 3724 if (mNetworkInfo.getExtraInfo() != null && mWifiInfo.getSSID() != null 3725 && !mWifiInfo.getSSID().equals(WifiSsid.NONE)) { 3726 // Always indicate that SSID has changed 3727 if (!mNetworkInfo.getExtraInfo().equals(mWifiInfo.getSSID())) { 3728 if (DBG) { 3729 log("setDetailed state send new extra info" + mWifiInfo.getSSID()); 3730 } 3731 mNetworkInfo.setExtraInfo(mWifiInfo.getSSID()); 3732 sendNetworkStateChangeBroadcast(null); 3733 } 3734 } 3735 if (hidden == true) { 3736 return false; 3737 } 3738 3739 if (state != mNetworkInfo.getDetailedState()) { 3740 mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID()); 3741 if (mNetworkAgent != null) { 3742 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 3743 } 3744 sendNetworkStateChangeBroadcast(null); 3745 return true; 3746 } 3747 return false; 3748 } 3749 3750 private DetailedState getNetworkDetailedState() { 3751 return mNetworkInfo.getDetailedState(); 3752 } 3753 3754 private SupplicantState handleSupplicantStateChange(Message message) { 3755 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 3756 SupplicantState state = stateChangeResult.state; 3757 // Supplicant state change 3758 // [31-13] Reserved for future use 3759 // [8 - 0] Supplicant state (as defined in SupplicantState.java) 3760 // 50023 supplicant_state_changed (custom|1|5) 3761 mWifiInfo.setSupplicantState(state); 3762 // If we receive a supplicant state change with an empty SSID, 3763 // this implies that wpa_supplicant is already disconnected. 3764 // We should pretend we are still connected when linkDebouncing is on. 3765 if ((stateChangeResult.wifiSsid == null 3766 || stateChangeResult.wifiSsid.toString().isEmpty()) && linkDebouncing) { 3767 return state; 3768 } 3769 // Network id is only valid when we start connecting 3770 if (SupplicantState.isConnecting(state)) { 3771 mWifiInfo.setNetworkId(stateChangeResult.networkId); 3772 } else { 3773 mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); 3774 } 3775 3776 mWifiInfo.setBSSID(stateChangeResult.BSSID); 3777 3778 if (mWhiteListedSsids != null 3779 && mWhiteListedSsids.length > 0 3780 && stateChangeResult.wifiSsid != null) { 3781 String SSID = stateChangeResult.wifiSsid.toString(); 3782 String currentSSID = mWifiInfo.getSSID(); 3783 if (SSID != null && currentSSID != null && !SSID.equals(WifiSsid.NONE)) { 3784 // Remove quote before comparing 3785 if (SSID.length() >= 2 && SSID.charAt(0) == '"' 3786 && SSID.charAt(SSID.length() - 1) == '"') { 3787 SSID = SSID.substring(1, SSID.length() - 1); 3788 } 3789 if (currentSSID.length() >= 2 && currentSSID.charAt(0) == '"' 3790 && currentSSID.charAt(currentSSID.length() - 1) == '"') { 3791 currentSSID = currentSSID.substring(1, currentSSID.length() - 1); 3792 } 3793 if ((!SSID.equals(currentSSID)) && (getCurrentState() == mConnectedState)) { 3794 lastConnectAttemptTimestamp = System.currentTimeMillis(); 3795 targetWificonfiguration = 3796 mWifiConfigManager.getWifiConfiguration(mWifiInfo.getNetworkId()); 3797 transitionTo(mRoamingState); 3798 } 3799 } 3800 } 3801 3802 mWifiInfo.setSSID(stateChangeResult.wifiSsid); 3803 mWifiInfo.setEphemeral(mWifiConfigManager.isEphemeral(mWifiInfo.getNetworkId())); 3804 if (!mWifiInfo.getMeteredHint()) { // don't override the value if already set. 3805 mWifiInfo.setMeteredHint(mWifiConfigManager.getMeteredHint(mWifiInfo.getNetworkId())); 3806 } 3807 3808 mSupplicantStateTracker.sendMessage(Message.obtain(message)); 3809 3810 return state; 3811 } 3812 3813 /** 3814 * Resets the Wi-Fi Connections by clearing any state, resetting any sockets 3815 * using the interface, stopping DHCP & disabling interface 3816 */ 3817 private void handleNetworkDisconnect() { 3818 if (DBG) log("handleNetworkDisconnect: Stopping DHCP and clearing IP" 3819 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 3820 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 3821 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 3822 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 3823 3824 stopRssiMonitoringOffload(); 3825 3826 clearCurrentConfigBSSID("handleNetworkDisconnect"); 3827 3828 stopIpManager(); 3829 3830 /* Reset data structures */ 3831 mWifiScoreReport = null; 3832 mWifiInfo.reset(); 3833 linkDebouncing = false; 3834 /* Reset roaming parameters */ 3835 mAutoRoaming = false; 3836 3837 /** 3838 * fullBandConnectedTimeIntervalMilli: 3839 * - start scans at mWifiConfigManager.mWifiAssociatedShortScanIntervalMs seconds 3840 * interval 3841 * - exponentially increase to mWifiConfigManager.mAssociatedFullScanMaxIntervalMs 3842 * Initialize to sane value = 20 seconds 3843 */ 3844 fullBandConnectedTimeIntervalMilli = 20 * 1000; 3845 3846 setNetworkDetailedState(DetailedState.DISCONNECTED); 3847 if (mNetworkAgent != null) { 3848 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 3849 mNetworkAgent = null; 3850 } 3851 mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED); 3852 3853 /* Clear network properties */ 3854 clearLinkProperties(); 3855 3856 /* Cend event to CM & network change broadcast */ 3857 sendNetworkStateChangeBroadcast(mLastBssid); 3858 3859 /* Cancel auto roam requests */ 3860 autoRoamSetBSSID(mLastNetworkId, "any"); 3861 mLastBssid = null; 3862 registerDisconnected(); 3863 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 3864 } 3865 3866 private void handleSupplicantConnectionLoss(boolean killSupplicant) { 3867 /* Socket connection can be lost when we do a graceful shutdown 3868 * or when the driver is hung. Ensure supplicant is stopped here. 3869 */ 3870 if (killSupplicant) { 3871 mWifiMonitor.killSupplicant(mP2pSupported); 3872 } 3873 mWifiNative.closeSupplicantConnection(); 3874 sendSupplicantConnectionChangedBroadcast(false); 3875 setWifiState(WIFI_STATE_DISABLED); 3876 } 3877 3878 void handlePreDhcpSetup() { 3879 if (!mBluetoothConnectionActive) { 3880 /* 3881 * There are problems setting the Wi-Fi driver's power 3882 * mode to active when bluetooth coexistence mode is 3883 * enabled or sense. 3884 * <p> 3885 * We set Wi-Fi to active mode when 3886 * obtaining an IP address because we've found 3887 * compatibility issues with some routers with low power 3888 * mode. 3889 * <p> 3890 * In order for this active power mode to properly be set, 3891 * we disable coexistence mode until we're done with 3892 * obtaining an IP address. One exception is if we 3893 * are currently connected to a headset, since disabling 3894 * coexistence would interrupt that connection. 3895 */ 3896 // Disable the coexistence mode 3897 mWifiNative.setBluetoothCoexistenceMode( 3898 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); 3899 } 3900 3901 // Disable power save and suspend optimizations during DHCP 3902 // Note: The order here is important for now. Brcm driver changes 3903 // power settings when we control suspend mode optimizations. 3904 // TODO: Remove this comment when the driver is fixed. 3905 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false); 3906 mWifiNative.setPowerSave(false); 3907 3908 // Update link layer stats 3909 getWifiLinkLayerStats(false); 3910 3911 /* P2p discovery breaks dhcp, shut it down in order to get through this */ 3912 Message msg = new Message(); 3913 msg.what = WifiP2pServiceImpl.BLOCK_DISCOVERY; 3914 msg.arg1 = WifiP2pServiceImpl.ENABLED; 3915 msg.arg2 = DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE; 3916 msg.obj = WifiStateMachine.this; 3917 mWifiP2pChannel.sendMessage(msg); 3918 } 3919 3920 void handlePostDhcpSetup() { 3921 /* Restore power save and suspend optimizations */ 3922 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true); 3923 mWifiNative.setPowerSave(true); 3924 3925 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.BLOCK_DISCOVERY, 3926 WifiP2pServiceImpl.DISABLED); 3927 3928 // Set the coexistence mode back to its default value 3929 mWifiNative.setBluetoothCoexistenceMode( 3930 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); 3931 } 3932 3933 /** 3934 * Inform other components (WifiMetrics, WifiLogger, etc.) that the current connection attempt 3935 * has concluded. 3936 */ 3937 private void reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode) { 3938 mWifiMetrics.endConnectionEvent(level2FailureCode, connectivityFailureCode); 3939 switch (level2FailureCode) { 3940 case WifiMetrics.ConnectionEvent.FAILURE_NONE: 3941 case WifiMetrics.ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT: 3942 // WifiLogger doesn't care about success, or pre-empted connections. 3943 break; 3944 default: 3945 mWifiLogger.reportConnectionFailure(); 3946 } 3947 } 3948 3949 private void handleIPv4Success(DhcpResults dhcpResults) { 3950 if (DBG) { 3951 logd("handleIPv4Success <" + dhcpResults.toString() + ">"); 3952 logd("link address " + dhcpResults.ipAddress); 3953 } 3954 3955 Inet4Address addr; 3956 synchronized (mDhcpResultsLock) { 3957 mDhcpResults = dhcpResults; 3958 addr = (Inet4Address) dhcpResults.ipAddress.getAddress(); 3959 } 3960 3961 if (isRoaming()) { 3962 int previousAddress = mWifiInfo.getIpAddress(); 3963 int newAddress = NetworkUtils.inetAddressToInt(addr); 3964 if (previousAddress != newAddress) { 3965 logd("handleIPv4Success, roaming and address changed" + 3966 mWifiInfo + " got: " + addr); 3967 } 3968 } 3969 mWifiInfo.setInetAddress(addr); 3970 if (!mWifiInfo.getMeteredHint()) { // don't override the value if already set. 3971 mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint()); 3972 updateCapabilities(getCurrentWifiConfiguration()); 3973 } 3974 } 3975 3976 private void handleSuccessfulIpConfiguration() { 3977 mLastSignalLevel = -1; // Force update of signal strength 3978 WifiConfiguration c = getCurrentWifiConfiguration(); 3979 if (c != null) { 3980 // Reset IP failure tracking 3981 c.getNetworkSelectionStatus().clearDisableReasonCounter( 3982 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3983 3984 // Tell the framework whether the newly connected network is trusted or untrusted. 3985 updateCapabilities(c); 3986 } 3987 if (c != null) { 3988 ScanResult result = getCurrentScanResult(); 3989 if (result == null) { 3990 logd("WifiStateMachine: handleSuccessfulIpConfiguration and no scan results" + 3991 c.configKey()); 3992 } else { 3993 // Clear the per BSSID failure count 3994 result.numIpConfigFailures = 0; 3995 // Clear the WHOLE BSSID blacklist, which means supplicant is free to retry 3996 // any BSSID, even though it may already have a non zero ip failure count, 3997 // this will typically happen if the user walks away and come back to his arrea 3998 // TODO: implement blacklisting based on a timer, i.e. keep BSSID blacklisted 3999 // in supplicant for a couple of hours or a day 4000 mWifiConfigManager.clearBssidBlacklist(); 4001 } 4002 } 4003 } 4004 4005 private void handleIPv4Failure() { 4006 // TODO: Move this to provisioning failure, not DHCP failure. 4007 // DHCPv4 failure is expected on an IPv6-only network. 4008 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_DHCP_FAILURE); 4009 if (DBG) { 4010 int count = -1; 4011 WifiConfiguration config = getCurrentWifiConfiguration(); 4012 if (config != null) { 4013 count = config.getNetworkSelectionStatus().getDisableReasonCounter( 4014 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 4015 } 4016 log("DHCP failure count=" + count); 4017 } 4018 reportConnectionAttemptEnd( 4019 WifiMetrics.ConnectionEvent.FAILURE_DHCP, 4020 WifiMetricsProto.ConnectionEvent.HLF_DHCP); 4021 synchronized(mDhcpResultsLock) { 4022 if (mDhcpResults != null) { 4023 mDhcpResults.clear(); 4024 } 4025 } 4026 if (DBG) { 4027 logd("handleIPv4Failure"); 4028 } 4029 } 4030 4031 private void handleIpConfigurationLost() { 4032 mWifiInfo.setInetAddress(null); 4033 mWifiInfo.setMeteredHint(false); 4034 4035 mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId, 4036 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 4037 4038 /* DHCP times out after about 30 seconds, we do a 4039 * disconnect thru supplicant, we will let autojoin retry connecting to the network 4040 */ 4041 mWifiNative.disconnect(); 4042 } 4043 4044 // TODO: De-duplicated this and handleIpConfigurationLost(). 4045 private void handleIpReachabilityLost() { 4046 mWifiInfo.setInetAddress(null); 4047 mWifiInfo.setMeteredHint(false); 4048 4049 // TODO: Determine whether to call some form of mWifiConfigManager.handleSSIDStateChange(). 4050 4051 // Disconnect via supplicant, and let autojoin retry connecting to the network. 4052 mWifiNative.disconnect(); 4053 } 4054 4055 private int convertFrequencyToChannelNumber(int frequency) { 4056 if (frequency >= 2412 && frequency <= 2484) { 4057 return (frequency -2412) / 5 + 1; 4058 } else if (frequency >= 5170 && frequency <=5825) { 4059 //DFS is included 4060 return (frequency -5170) / 5 + 34; 4061 } else { 4062 return 0; 4063 } 4064 } 4065 4066 private int chooseApChannel(int apBand) { 4067 int apChannel; 4068 int[] channel; 4069 4070 if (apBand == 0) { 4071 ArrayList<Integer> allowed2GChannel = 4072 mWifiApConfigStore.getAllowed2GChannel(); 4073 if (allowed2GChannel == null || allowed2GChannel.size() == 0) { 4074 //most safe channel to use 4075 if (DBG) { 4076 Log.d(TAG, "No specified 2G allowed channel list"); 4077 } 4078 apChannel = 6; 4079 } else { 4080 int index = mRandom.nextInt(allowed2GChannel.size()); 4081 apChannel = allowed2GChannel.get(index).intValue(); 4082 } 4083 } else { 4084 //5G without DFS 4085 channel = mWifiNative.getChannelsForBand(2); 4086 if (channel != null && channel.length > 0) { 4087 apChannel = channel[mRandom.nextInt(channel.length)]; 4088 apChannel = convertFrequencyToChannelNumber(apChannel); 4089 } else { 4090 Log.e(TAG, "SoftAp do not get available channel list"); 4091 apChannel = 0; 4092 } 4093 } 4094 4095 if (DBG) { 4096 Log.d(TAG, "SoftAp set on channel " + apChannel); 4097 } 4098 4099 return apChannel; 4100 } 4101 4102 /* Driver/firmware setup for soft AP. */ 4103 private boolean setupDriverForSoftAp() { 4104 if (!mWifiNative.loadDriver()) { 4105 Log.e(TAG, "Failed to load driver for softap"); 4106 return false; 4107 } 4108 4109 int index = mWifiNative.queryInterfaceIndex(mInterfaceName); 4110 if (index != -1) { 4111 if (!mWifiNative.setInterfaceUp(false)) { 4112 Log.e(TAG, "toggleInterface failed"); 4113 return false; 4114 } 4115 } else { 4116 if (DBG) Log.d(TAG, "No interfaces to bring down"); 4117 } 4118 4119 try { 4120 mNwService.wifiFirmwareReload(mInterfaceName, "AP"); 4121 if (DBG) Log.d(TAG, "Firmware reloaded in AP mode"); 4122 } catch (Exception e) { 4123 Log.e(TAG, "Failed to reload AP firmware " + e); 4124 } 4125 4126 if (!mWifiNative.startHal()) { 4127 /* starting HAL is optional */ 4128 Log.e(TAG, "Failed to start HAL"); 4129 } 4130 return true; 4131 } 4132 4133 private byte[] macAddressFromString(String macString) { 4134 String[] macBytes = macString.split(":"); 4135 if (macBytes.length != 6) { 4136 throw new IllegalArgumentException("MAC address should be 6 bytes long!"); 4137 } 4138 byte[] mac = new byte[6]; 4139 for (int i = 0; i < macBytes.length; i++) { 4140 Integer hexVal = Integer.parseInt(macBytes[i], 16); 4141 mac[i] = hexVal.byteValue(); 4142 } 4143 return mac; 4144 } 4145 4146 /* 4147 * Read a MAC address in /proc/arp/table, used by WifistateMachine 4148 * so as to record MAC address of default gateway. 4149 **/ 4150 private String macAddressFromRoute(String ipAddress) { 4151 String macAddress = null; 4152 BufferedReader reader = null; 4153 try { 4154 reader = new BufferedReader(new FileReader("/proc/net/arp")); 4155 4156 // Skip over the line bearing colum titles 4157 String line = reader.readLine(); 4158 4159 while ((line = reader.readLine()) != null) { 4160 String[] tokens = line.split("[ ]+"); 4161 if (tokens.length < 6) { 4162 continue; 4163 } 4164 4165 // ARP column format is 4166 // Address HWType HWAddress Flags Mask IFace 4167 String ip = tokens[0]; 4168 String mac = tokens[3]; 4169 4170 if (ipAddress.equals(ip)) { 4171 macAddress = mac; 4172 break; 4173 } 4174 } 4175 4176 if (macAddress == null) { 4177 loge("Did not find remoteAddress {" + ipAddress + "} in " + 4178 "/proc/net/arp"); 4179 } 4180 4181 } catch (FileNotFoundException e) { 4182 loge("Could not open /proc/net/arp to lookup mac address"); 4183 } catch (IOException e) { 4184 loge("Could not read /proc/net/arp to lookup mac address"); 4185 } finally { 4186 try { 4187 if (reader != null) { 4188 reader.close(); 4189 } 4190 } catch (IOException e) { 4191 // Do nothing 4192 } 4193 } 4194 return macAddress; 4195 4196 } 4197 4198 private class WifiNetworkFactory extends NetworkFactory { 4199 public WifiNetworkFactory(Looper l, Context c, String TAG, NetworkCapabilities f) { 4200 super(l, c, TAG, f); 4201 } 4202 4203 @Override 4204 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 4205 ++mConnectionRequests; 4206 } 4207 4208 @Override 4209 protected void releaseNetworkFor(NetworkRequest networkRequest) { 4210 --mConnectionRequests; 4211 } 4212 4213 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4214 pw.println("mConnectionRequests " + mConnectionRequests); 4215 } 4216 4217 } 4218 4219 private class UntrustedWifiNetworkFactory extends NetworkFactory { 4220 private int mUntrustedReqCount; 4221 4222 public UntrustedWifiNetworkFactory(Looper l, Context c, String tag, NetworkCapabilities f) { 4223 super(l, c, tag, f); 4224 } 4225 4226 @Override 4227 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 4228 if (!networkRequest.networkCapabilities.hasCapability( 4229 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 4230 if (++mUntrustedReqCount == 1) { 4231 if (mWifiConnectivityManager != null) { 4232 mWifiConnectivityManager.setUntrustedConnectionAllowed(true); 4233 } 4234 } 4235 } 4236 } 4237 4238 @Override 4239 protected void releaseNetworkFor(NetworkRequest networkRequest) { 4240 if (!networkRequest.networkCapabilities.hasCapability( 4241 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 4242 if (--mUntrustedReqCount == 0) { 4243 if (mWifiConnectivityManager != null) { 4244 mWifiConnectivityManager.setUntrustedConnectionAllowed(false); 4245 } 4246 } 4247 } 4248 } 4249 4250 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4251 pw.println("mUntrustedReqCount " + mUntrustedReqCount); 4252 } 4253 } 4254 4255 void maybeRegisterNetworkFactory() { 4256 if (mNetworkFactory == null) { 4257 checkAndSetConnectivityInstance(); 4258 if (mCm != null) { 4259 mNetworkFactory = new WifiNetworkFactory(getHandler().getLooper(), mContext, 4260 NETWORKTYPE, mNetworkCapabilitiesFilter); 4261 mNetworkFactory.setScoreFilter(60); 4262 mNetworkFactory.register(); 4263 4264 // We can't filter untrusted network in the capabilities filter because a trusted 4265 // network would still satisfy a request that accepts untrusted ones. 4266 mUntrustedNetworkFactory = new UntrustedWifiNetworkFactory(getHandler().getLooper(), 4267 mContext, NETWORKTYPE_UNTRUSTED, mNetworkCapabilitiesFilter); 4268 mUntrustedNetworkFactory.setScoreFilter(Integer.MAX_VALUE); 4269 mUntrustedNetworkFactory.register(); 4270 } 4271 } 4272 } 4273 4274 /******************************************************** 4275 * HSM states 4276 *******************************************************/ 4277 4278 class DefaultState extends State { 4279 @Override 4280 public boolean processMessage(Message message) { 4281 logStateAndMessage(message, this); 4282 4283 switch (message.what) { 4284 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 4285 AsyncChannel ac = (AsyncChannel) message.obj; 4286 if (ac == mWifiP2pChannel) { 4287 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 4288 mWifiP2pChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 4289 } else { 4290 loge("WifiP2pService connection failure, error=" + message.arg1); 4291 } 4292 } else { 4293 loge("got HALF_CONNECTED for unknown channel"); 4294 } 4295 break; 4296 } 4297 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 4298 AsyncChannel ac = (AsyncChannel) message.obj; 4299 if (ac == mWifiP2pChannel) { 4300 loge("WifiP2pService channel lost, message.arg1 =" + message.arg1); 4301 //TODO: Re-establish connection to state machine after a delay 4302 // mWifiP2pChannel.connect(mContext, getHandler(), 4303 // mWifiP2pManager.getMessenger()); 4304 } 4305 break; 4306 } 4307 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 4308 mBluetoothConnectionActive = (message.arg1 != 4309 BluetoothAdapter.STATE_DISCONNECTED); 4310 break; 4311 /* Synchronous call returns */ 4312 case CMD_PING_SUPPLICANT: 4313 case CMD_ENABLE_NETWORK: 4314 case CMD_ADD_OR_UPDATE_NETWORK: 4315 case CMD_REMOVE_NETWORK: 4316 case CMD_SAVE_CONFIG: 4317 replyToMessage(message, message.what, FAILURE); 4318 break; 4319 case CMD_GET_CAPABILITY_FREQ: 4320 replyToMessage(message, message.what, null); 4321 break; 4322 case CMD_GET_CONFIGURED_NETWORKS: 4323 replyToMessage(message, message.what, (List<WifiConfiguration>) null); 4324 break; 4325 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 4326 replyToMessage(message, message.what, (List<WifiConfiguration>) null); 4327 break; 4328 case CMD_ENABLE_RSSI_POLL: 4329 mEnableRssiPolling = (message.arg1 == 1); 4330 break; 4331 case CMD_SET_HIGH_PERF_MODE: 4332 if (message.arg1 == 1) { 4333 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false); 4334 } else { 4335 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true); 4336 } 4337 break; 4338 case CMD_BOOT_COMPLETED: 4339 maybeRegisterNetworkFactory(); 4340 break; 4341 case CMD_SCREEN_STATE_CHANGED: 4342 handleScreenStateChanged(message.arg1 != 0); 4343 break; 4344 /* Discard */ 4345 case CMD_START_SCAN: 4346 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4347 break; 4348 case CMD_START_SUPPLICANT: 4349 case CMD_STOP_SUPPLICANT: 4350 case CMD_STOP_SUPPLICANT_FAILED: 4351 case CMD_START_DRIVER: 4352 case CMD_STOP_DRIVER: 4353 case CMD_DRIVER_START_TIMED_OUT: 4354 case CMD_START_AP: 4355 case CMD_START_AP_FAILURE: 4356 case CMD_STOP_AP: 4357 case CMD_AP_STOPPED: 4358 case CMD_DISCONNECT: 4359 case CMD_RECONNECT: 4360 case CMD_REASSOCIATE: 4361 case CMD_RELOAD_TLS_AND_RECONNECT: 4362 case WifiMonitor.SUP_CONNECTION_EVENT: 4363 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4364 case WifiMonitor.NETWORK_CONNECTION_EVENT: 4365 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 4366 case WifiMonitor.SCAN_RESULTS_EVENT: 4367 case WifiMonitor.SCAN_FAILED_EVENT: 4368 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4369 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 4370 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 4371 case WifiMonitor.WPS_OVERLAP_EVENT: 4372 case CMD_BLACKLIST_NETWORK: 4373 case CMD_CLEAR_BLACKLIST: 4374 case CMD_SET_OPERATIONAL_MODE: 4375 case CMD_SET_FREQUENCY_BAND: 4376 case CMD_RSSI_POLL: 4377 case CMD_ENABLE_ALL_NETWORKS: 4378 case DhcpClient.CMD_PRE_DHCP_ACTION: 4379 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 4380 case DhcpClient.CMD_POST_DHCP_ACTION: 4381 case CMD_NO_NETWORKS_PERIODIC_SCAN: 4382 case CMD_DISABLE_P2P_RSP: 4383 case WifiMonitor.SUP_REQUEST_IDENTITY: 4384 case CMD_TEST_NETWORK_DISCONNECT: 4385 case CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER: 4386 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 4387 case CMD_TARGET_BSSID: 4388 case CMD_AUTO_CONNECT: 4389 case CMD_AUTO_ROAM: 4390 case CMD_AUTO_SAVE_NETWORK: 4391 case CMD_ASSOCIATED_BSSID: 4392 case CMD_UNWANTED_NETWORK: 4393 case CMD_DISCONNECTING_WATCHDOG_TIMER: 4394 case CMD_ROAM_WATCHDOG_TIMER: 4395 case CMD_DISABLE_EPHEMERAL_NETWORK: 4396 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 4397 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4398 break; 4399 case CMD_SET_SUSPEND_OPT_ENABLED: 4400 if (message.arg1 == 1) { 4401 mSuspendWakeLock.release(); 4402 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true); 4403 } else { 4404 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false); 4405 } 4406 break; 4407 case WifiMonitor.DRIVER_HUNG_EVENT: 4408 setSupplicantRunning(false); 4409 setSupplicantRunning(true); 4410 break; 4411 case WifiManager.CONNECT_NETWORK: 4412 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 4413 WifiManager.BUSY); 4414 break; 4415 case WifiManager.FORGET_NETWORK: 4416 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 4417 WifiManager.BUSY); 4418 break; 4419 case WifiManager.SAVE_NETWORK: 4420 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 4421 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 4422 WifiManager.BUSY); 4423 break; 4424 case WifiManager.START_WPS: 4425 replyToMessage(message, WifiManager.WPS_FAILED, 4426 WifiManager.BUSY); 4427 break; 4428 case WifiManager.CANCEL_WPS: 4429 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, 4430 WifiManager.BUSY); 4431 break; 4432 case WifiManager.DISABLE_NETWORK: 4433 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 4434 WifiManager.BUSY); 4435 break; 4436 case WifiManager.RSSI_PKTCNT_FETCH: 4437 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED, 4438 WifiManager.BUSY); 4439 break; 4440 case CMD_GET_SUPPORTED_FEATURES: 4441 int featureSet = mWifiNative.getSupportedFeatureSet(); 4442 replyToMessage(message, message.what, featureSet); 4443 break; 4444 case CMD_FIRMWARE_ALERT: 4445 if (mWifiLogger != null) { 4446 byte[] buffer = (byte[])message.obj; 4447 mWifiLogger.captureAlertData(message.arg1, buffer); 4448 } 4449 break; 4450 case CMD_GET_LINK_LAYER_STATS: 4451 // Not supported hence reply with error message 4452 replyToMessage(message, message.what, null); 4453 break; 4454 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 4455 NetworkInfo info = (NetworkInfo) message.obj; 4456 mP2pConnected.set(info.isConnected()); 4457 break; 4458 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 4459 mTemporarilyDisconnectWifi = (message.arg1 == 1); 4460 replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 4461 break; 4462 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 4463 case CMD_UPDATE_LINKPROPERTIES: 4464 updateLinkProperties((LinkProperties) message.obj); 4465 break; 4466 case CMD_GET_MATCHING_CONFIG: 4467 replyToMessage(message, message.what); 4468 break; 4469 case CMD_IP_CONFIGURATION_SUCCESSFUL: 4470 case CMD_IP_CONFIGURATION_LOST: 4471 case CMD_IP_REACHABILITY_LOST: 4472 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4473 break; 4474 case CMD_GET_CONNECTION_STATISTICS: 4475 replyToMessage(message, message.what, mWifiConnectionStatistics); 4476 break; 4477 case CMD_REMOVE_APP_CONFIGURATIONS: 4478 deferMessage(message); 4479 break; 4480 case CMD_REMOVE_USER_CONFIGURATIONS: 4481 deferMessage(message); 4482 break; 4483 case CMD_START_IP_PACKET_OFFLOAD: 4484 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 4485 message.arg1, 4486 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 4487 break; 4488 case CMD_STOP_IP_PACKET_OFFLOAD: 4489 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 4490 message.arg1, 4491 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 4492 break; 4493 case CMD_START_RSSI_MONITORING_OFFLOAD: 4494 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4495 break; 4496 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 4497 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4498 break; 4499 case CMD_USER_SWITCH: 4500 mWifiConfigManager.handleUserSwitch(message.arg1); 4501 break; 4502 case CMD_ADD_PASSPOINT_MO: 4503 case CMD_MODIFY_PASSPOINT_MO: 4504 case CMD_QUERY_OSU_ICON: 4505 case CMD_MATCH_PROVIDER_NETWORK: 4506 /* reply with arg1 = 0 - it returns API failure to the calling app 4507 * (message.what is not looked at) 4508 */ 4509 replyToMessage(message, message.what); 4510 break; 4511 case CMD_RESET_SIM_NETWORKS: 4512 /* Defer this message until supplicant is started. */ 4513 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 4514 deferMessage(message); 4515 break; 4516 case CMD_INSTALL_PACKET_FILTER: 4517 mWifiNative.installPacketFilter((byte[]) message.obj); 4518 break; 4519 case CMD_SET_FALLBACK_PACKET_FILTERING: 4520 if ((boolean) message.obj) { 4521 mWifiNative.startFilteringMulticastV4Packets(); 4522 } else { 4523 mWifiNative.stopFilteringMulticastV4Packets(); 4524 } 4525 break; 4526 default: 4527 loge("Error! unhandled message" + message); 4528 break; 4529 } 4530 return HANDLED; 4531 } 4532 } 4533 4534 class InitialState extends State { 4535 @Override 4536 public void enter() { 4537 mWifiNative.stopHal(); 4538 mWifiNative.unloadDriver(); 4539 if (mWifiP2pChannel == null) { 4540 mWifiP2pChannel = new AsyncChannel(); 4541 mWifiP2pChannel.connect(mContext, getHandler(), 4542 mWifiP2pServiceImpl.getP2pStateMachineMessenger()); 4543 } 4544 4545 if (mWifiApConfigStore == null) { 4546 mWifiApConfigStore = 4547 mFacade.makeApConfigStore(mContext, mBackupManagerProxy); 4548 } 4549 } 4550 @Override 4551 public boolean processMessage(Message message) { 4552 logStateAndMessage(message, this); 4553 switch (message.what) { 4554 case CMD_START_SUPPLICANT: 4555 if (mWifiNative.loadDriver()) { 4556 try { 4557 mNwService.wifiFirmwareReload(mInterfaceName, "STA"); 4558 } catch (Exception e) { 4559 loge("Failed to reload STA firmware " + e); 4560 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 4561 return HANDLED; 4562 } 4563 4564 try { 4565 // A runtime crash can leave the interface up and 4566 // IP addresses configured, and this affects 4567 // connectivity when supplicant starts up. 4568 // Ensure interface is down and we have no IP 4569 // addresses before a supplicant start. 4570 mNwService.setInterfaceDown(mInterfaceName); 4571 mNwService.clearInterfaceAddresses(mInterfaceName); 4572 4573 // Set privacy extensions 4574 mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true); 4575 4576 // IPv6 is enabled only as long as access point is connected since: 4577 // - IPv6 addresses and routes stick around after disconnection 4578 // - kernel is unaware when connected and fails to start IPv6 negotiation 4579 // - kernel can start autoconfiguration when 802.1x is not complete 4580 mNwService.disableIpv6(mInterfaceName); 4581 } catch (RemoteException re) { 4582 loge("Unable to change interface settings: " + re); 4583 } catch (IllegalStateException ie) { 4584 loge("Unable to change interface settings: " + ie); 4585 } 4586 4587 /* Stop a running supplicant after a runtime restart 4588 * Avoids issues with drivers that do not handle interface down 4589 * on a running supplicant properly. 4590 */ 4591 mWifiMonitor.killSupplicant(mP2pSupported); 4592 4593 if (mWifiNative.startHal() == false) { 4594 /* starting HAL is optional */ 4595 loge("Failed to start HAL"); 4596 } 4597 4598 if (mWifiNative.startSupplicant(mP2pSupported)) { 4599 setWifiState(WIFI_STATE_ENABLING); 4600 if (DBG) log("Supplicant start successful"); 4601 mWifiMonitor.startMonitoring(mInterfaceName); 4602 transitionTo(mSupplicantStartingState); 4603 } else { 4604 loge("Failed to start supplicant!"); 4605 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 4606 } 4607 } else { 4608 loge("Failed to load driver"); 4609 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 4610 } 4611 break; 4612 case CMD_START_AP: 4613 if (setupDriverForSoftAp()) { 4614 transitionTo(mSoftApState); 4615 } else { 4616 setWifiApState(WIFI_AP_STATE_FAILED, 4617 WifiManager.SAP_START_FAILURE_GENERAL); 4618 /** 4619 * Transition to InitialState (current state) to reset the 4620 * driver/HAL back to the initial state. 4621 */ 4622 transitionTo(mInitialState); 4623 } 4624 break; 4625 default: 4626 return NOT_HANDLED; 4627 } 4628 return HANDLED; 4629 } 4630 } 4631 4632 class SupplicantStartingState extends State { 4633 private void initializeWpsDetails() { 4634 String detail; 4635 detail = SystemProperties.get("ro.product.name", ""); 4636 if (!mWifiNative.setDeviceName(detail)) { 4637 loge("Failed to set device name " + detail); 4638 } 4639 detail = SystemProperties.get("ro.product.manufacturer", ""); 4640 if (!mWifiNative.setManufacturer(detail)) { 4641 loge("Failed to set manufacturer " + detail); 4642 } 4643 detail = SystemProperties.get("ro.product.model", ""); 4644 if (!mWifiNative.setModelName(detail)) { 4645 loge("Failed to set model name " + detail); 4646 } 4647 detail = SystemProperties.get("ro.product.model", ""); 4648 if (!mWifiNative.setModelNumber(detail)) { 4649 loge("Failed to set model number " + detail); 4650 } 4651 detail = SystemProperties.get("ro.serialno", ""); 4652 if (!mWifiNative.setSerialNumber(detail)) { 4653 loge("Failed to set serial number " + detail); 4654 } 4655 if (!mWifiNative.setConfigMethods("physical_display virtual_push_button")) { 4656 loge("Failed to set WPS config methods"); 4657 } 4658 if (!mWifiNative.setDeviceType(mPrimaryDeviceType)) { 4659 loge("Failed to set primary device type " + mPrimaryDeviceType); 4660 } 4661 } 4662 4663 @Override 4664 public boolean processMessage(Message message) { 4665 logStateAndMessage(message, this); 4666 4667 switch(message.what) { 4668 case WifiMonitor.SUP_CONNECTION_EVENT: 4669 if (DBG) log("Supplicant connection established"); 4670 setWifiState(WIFI_STATE_ENABLED); 4671 mSupplicantRestartCount = 0; 4672 /* Reset the supplicant state to indicate the supplicant 4673 * state is not known at this time */ 4674 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4675 /* Initialize data structures */ 4676 mLastBssid = null; 4677 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 4678 mLastSignalLevel = -1; 4679 4680 mWifiInfo.setMacAddress(mWifiNative.getMacAddress()); 4681 /* set frequency band of operation */ 4682 setFrequencyBand(); 4683 mWifiNative.enableSaveConfig(); 4684 mWifiConfigManager.loadAndEnableAllNetworks(); 4685 if (mWifiConfigManager.mEnableVerboseLogging.get() > 0) { 4686 enableVerboseLogging(mWifiConfigManager.mEnableVerboseLogging.get()); 4687 } 4688 initializeWpsDetails(); 4689 4690 sendSupplicantConnectionChangedBroadcast(true); 4691 transitionTo(mDriverStartedState); 4692 break; 4693 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4694 if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { 4695 loge("Failed to setup control channel, restart supplicant"); 4696 mWifiMonitor.killSupplicant(mP2pSupported); 4697 transitionTo(mInitialState); 4698 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 4699 } else { 4700 loge("Failed " + mSupplicantRestartCount + 4701 " times to start supplicant, unload driver"); 4702 mSupplicantRestartCount = 0; 4703 setWifiState(WIFI_STATE_UNKNOWN); 4704 transitionTo(mInitialState); 4705 } 4706 break; 4707 case CMD_START_SUPPLICANT: 4708 case CMD_STOP_SUPPLICANT: 4709 case CMD_START_AP: 4710 case CMD_STOP_AP: 4711 case CMD_START_DRIVER: 4712 case CMD_STOP_DRIVER: 4713 case CMD_SET_OPERATIONAL_MODE: 4714 case CMD_SET_FREQUENCY_BAND: 4715 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 4716 deferMessage(message); 4717 break; 4718 default: 4719 return NOT_HANDLED; 4720 } 4721 return HANDLED; 4722 } 4723 } 4724 4725 class SupplicantStartedState extends State { 4726 @Override 4727 public void enter() { 4728 /* Wifi is available as long as we have a connection to supplicant */ 4729 mNetworkInfo.setIsAvailable(true); 4730 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4731 4732 int defaultInterval = mContext.getResources().getInteger( 4733 R.integer.config_wifi_supplicant_scan_interval); 4734 4735 mSupplicantScanIntervalMs = mFacade.getLongSetting(mContext, 4736 Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS, 4737 defaultInterval); 4738 4739 mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000); 4740 mWifiNative.setExternalSim(true); 4741 4742 /* turn on use of DFS channels */ 4743 mWifiNative.setDfsFlag(true); 4744 4745 setRandomMacOui(); 4746 mWifiNative.enableAutoConnect(false); 4747 mCountryCode.setReadyForChange(true); 4748 } 4749 4750 @Override 4751 public boolean processMessage(Message message) { 4752 logStateAndMessage(message, this); 4753 4754 switch(message.what) { 4755 case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */ 4756 if (mP2pSupported) { 4757 transitionTo(mWaitForP2pDisableState); 4758 } else { 4759 transitionTo(mSupplicantStoppingState); 4760 } 4761 break; 4762 case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ 4763 loge("Connection lost, restart supplicant"); 4764 handleSupplicantConnectionLoss(true); 4765 handleNetworkDisconnect(); 4766 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4767 if (mP2pSupported) { 4768 transitionTo(mWaitForP2pDisableState); 4769 } else { 4770 transitionTo(mInitialState); 4771 } 4772 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 4773 break; 4774 case WifiMonitor.SCAN_RESULTS_EVENT: 4775 case WifiMonitor.SCAN_FAILED_EVENT: 4776 maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered 4777 noteScanEnd(); 4778 setScanResults(); 4779 if (mIsFullScanOngoing || mSendScanResultsBroadcast) { 4780 /* Just updated results from full scan, let apps know about this */ 4781 boolean scanSucceeded = message.what == WifiMonitor.SCAN_RESULTS_EVENT; 4782 sendScanResultsAvailableBroadcast(scanSucceeded); 4783 } 4784 mSendScanResultsBroadcast = false; 4785 mIsScanOngoing = false; 4786 mIsFullScanOngoing = false; 4787 if (mBufferedScanMsg.size() > 0) 4788 sendMessage(mBufferedScanMsg.remove()); 4789 break; 4790 case CMD_PING_SUPPLICANT: 4791 boolean ok = mWifiNative.ping(); 4792 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 4793 break; 4794 case CMD_GET_CAPABILITY_FREQ: 4795 String freqs = mWifiNative.getFreqCapability(); 4796 replyToMessage(message, message.what, freqs); 4797 break; 4798 case CMD_START_AP: 4799 /* Cannot start soft AP while in client mode */ 4800 loge("Failed to start soft AP with a running supplicant"); 4801 setWifiApState(WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL); 4802 break; 4803 case CMD_SET_OPERATIONAL_MODE: 4804 mOperationalMode = message.arg1; 4805 mWifiConfigManager. 4806 setAndEnableLastSelectedConfiguration( 4807 WifiConfiguration.INVALID_NETWORK_ID); 4808 break; 4809 case CMD_TARGET_BSSID: 4810 // Trying to associate to this BSSID 4811 if (message.obj != null) { 4812 mTargetRoamBSSID = (String) message.obj; 4813 } 4814 break; 4815 case CMD_GET_LINK_LAYER_STATS: 4816 WifiLinkLayerStats stats = getWifiLinkLayerStats(DBG); 4817 if (stats == null) { 4818 // When firmware doesnt support link layer stats, return an empty object 4819 stats = new WifiLinkLayerStats(); 4820 } 4821 replyToMessage(message, message.what, stats); 4822 break; 4823 case CMD_RESET_SIM_NETWORKS: 4824 log("resetting EAP-SIM/AKA/AKA' networks since SIM was removed"); 4825 mWifiConfigManager.resetSimNetworks(); 4826 break; 4827 default: 4828 return NOT_HANDLED; 4829 } 4830 return HANDLED; 4831 } 4832 4833 @Override 4834 public void exit() { 4835 mNetworkInfo.setIsAvailable(false); 4836 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4837 mCountryCode.setReadyForChange(false); 4838 } 4839 } 4840 4841 class SupplicantStoppingState extends State { 4842 @Override 4843 public void enter() { 4844 /* Send any reset commands to supplicant before shutting it down */ 4845 handleNetworkDisconnect(); 4846 4847 String suppState = System.getProperty("init.svc.wpa_supplicant"); 4848 if (suppState == null) suppState = "unknown"; 4849 String p2pSuppState = System.getProperty("init.svc.p2p_supplicant"); 4850 if (p2pSuppState == null) p2pSuppState = "unknown"; 4851 4852 logd("SupplicantStoppingState: stopSupplicant " 4853 + " init.svc.wpa_supplicant=" + suppState 4854 + " init.svc.p2p_supplicant=" + p2pSuppState); 4855 mWifiMonitor.stopSupplicant(); 4856 4857 /* Send ourselves a delayed message to indicate failure after a wait time */ 4858 sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED, 4859 ++mSupplicantStopFailureToken, 0), SUPPLICANT_RESTART_INTERVAL_MSECS); 4860 setWifiState(WIFI_STATE_DISABLING); 4861 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4862 } 4863 @Override 4864 public boolean processMessage(Message message) { 4865 logStateAndMessage(message, this); 4866 4867 switch(message.what) { 4868 case WifiMonitor.SUP_CONNECTION_EVENT: 4869 loge("Supplicant connection received while stopping"); 4870 break; 4871 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4872 if (DBG) log("Supplicant connection lost"); 4873 handleSupplicantConnectionLoss(false); 4874 transitionTo(mInitialState); 4875 break; 4876 case CMD_STOP_SUPPLICANT_FAILED: 4877 if (message.arg1 == mSupplicantStopFailureToken) { 4878 loge("Timed out on a supplicant stop, kill and proceed"); 4879 handleSupplicantConnectionLoss(true); 4880 transitionTo(mInitialState); 4881 } 4882 break; 4883 case CMD_START_SUPPLICANT: 4884 case CMD_STOP_SUPPLICANT: 4885 case CMD_START_AP: 4886 case CMD_STOP_AP: 4887 case CMD_START_DRIVER: 4888 case CMD_STOP_DRIVER: 4889 case CMD_SET_OPERATIONAL_MODE: 4890 case CMD_SET_FREQUENCY_BAND: 4891 deferMessage(message); 4892 break; 4893 default: 4894 return NOT_HANDLED; 4895 } 4896 return HANDLED; 4897 } 4898 } 4899 4900 class DriverStartingState extends State { 4901 private int mTries; 4902 @Override 4903 public void enter() { 4904 mTries = 1; 4905 /* Send ourselves a delayed message to start driver a second time */ 4906 sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT, 4907 ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS); 4908 } 4909 @Override 4910 public boolean processMessage(Message message) { 4911 logStateAndMessage(message, this); 4912 4913 switch(message.what) { 4914 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4915 SupplicantState state = handleSupplicantStateChange(message); 4916 /* If suplicant is exiting out of INTERFACE_DISABLED state into 4917 * a state that indicates driver has started, it is ready to 4918 * receive driver commands 4919 */ 4920 if (SupplicantState.isDriverActive(state)) { 4921 transitionTo(mDriverStartedState); 4922 } 4923 break; 4924 case CMD_DRIVER_START_TIMED_OUT: 4925 if (message.arg1 == mDriverStartToken) { 4926 if (mTries >= 2) { 4927 loge("Failed to start driver after " + mTries); 4928 setSupplicantRunning(false); 4929 setSupplicantRunning(true); 4930 } else { 4931 loge("Driver start failed, retrying"); 4932 mWakeLock.acquire(); 4933 mWifiNative.startDriver(); 4934 mWakeLock.release(); 4935 4936 ++mTries; 4937 /* Send ourselves a delayed message to start driver again */ 4938 sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT, 4939 ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS); 4940 } 4941 } 4942 break; 4943 /* Queue driver commands & connection events */ 4944 case CMD_START_DRIVER: 4945 case CMD_STOP_DRIVER: 4946 case WifiMonitor.NETWORK_CONNECTION_EVENT: 4947 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 4948 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 4949 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 4950 case WifiMonitor.WPS_OVERLAP_EVENT: 4951 case CMD_SET_FREQUENCY_BAND: 4952 case CMD_START_SCAN: 4953 case CMD_DISCONNECT: 4954 case CMD_REASSOCIATE: 4955 case CMD_RECONNECT: 4956 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 4957 deferMessage(message); 4958 break; 4959 case WifiMonitor.SCAN_RESULTS_EVENT: 4960 case WifiMonitor.SCAN_FAILED_EVENT: 4961 // Loose scan results obtained in Driver Starting state, they can only confuse 4962 // the state machine 4963 break; 4964 default: 4965 return NOT_HANDLED; 4966 } 4967 return HANDLED; 4968 } 4969 } 4970 4971 class DriverStartedState extends State { 4972 @Override 4973 public void enter() { 4974 if (DBG) { 4975 logd("DriverStartedState enter"); 4976 } 4977 4978 // We can't do this in the constructor because WifiStateMachine is created before the 4979 // wifi scanning service is initialized 4980 if (mWifiScanner == null) { 4981 mWifiScanner = 4982 (WifiScanner) mContext.getSystemService(Context.WIFI_SCANNING_SERVICE); 4983 mWifiConnectivityManager = new WifiConnectivityManager(mContext, 4984 WifiStateMachine.this, mWifiScanner, mWifiConfigManager, mWifiInfo, 4985 mWifiQualifiedNetworkSelector); 4986 } 4987 4988 mWifiLogger.startLogging(DBG); 4989 mIsRunning = true; 4990 updateBatteryWorkSource(null); 4991 /** 4992 * Enable bluetooth coexistence scan mode when bluetooth connection is active. 4993 * When this mode is on, some of the low-level scan parameters used by the 4994 * driver are changed to reduce interference with bluetooth 4995 */ 4996 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 4997 /* initialize network state */ 4998 setNetworkDetailedState(DetailedState.DISCONNECTED); 4999 5000 // Disable legacy multicast filtering, which on some chipsets defaults to enabled. 5001 // Legacy IPv6 multicast filtering blocks ICMPv6 router advertisements which breaks IPv6 5002 // provisioning. Legacy IPv4 multicast filtering may be re-enabled later via 5003 // IpManager.Callback.setFallbackMulticastFilter() 5004 mWifiNative.stopFilteringMulticastV4Packets(); 5005 mWifiNative.stopFilteringMulticastV6Packets(); 5006 5007 if (mOperationalMode != CONNECT_MODE) { 5008 mWifiNative.disconnect(); 5009 mWifiConfigManager.disableAllNetworksNative(); 5010 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 5011 setWifiState(WIFI_STATE_DISABLED); 5012 } 5013 transitionTo(mScanModeState); 5014 } else { 5015 5016 // Status pulls in the current supplicant state and network connection state 5017 // events over the monitor connection. This helps framework sync up with 5018 // current supplicant state 5019 // TODO: actually check th supplicant status string and make sure the supplicant 5020 // is in disconnecte4d state. 5021 mWifiNative.status(); 5022 // Transitioning to Disconnected state will trigger a scan and subsequently AutoJoin 5023 transitionTo(mDisconnectedState); 5024 transitionTo(mDisconnectedState); 5025 } 5026 5027 // We may have missed screen update at boot 5028 if (mScreenBroadcastReceived.get() == false) { 5029 PowerManager powerManager = (PowerManager)mContext.getSystemService( 5030 Context.POWER_SERVICE); 5031 handleScreenStateChanged(powerManager.isScreenOn()); 5032 } else { 5033 // Set the right suspend mode settings 5034 mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0 5035 && mUserWantsSuspendOpt.get()); 5036 } 5037 mWifiNative.setPowerSave(true); 5038 5039 if (mP2pSupported) { 5040 if (mOperationalMode == CONNECT_MODE) { 5041 mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P); 5042 } else { 5043 // P2P statemachine starts in disabled state, and is not enabled until 5044 // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to 5045 // keep it disabled. 5046 } 5047 } 5048 5049 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 5050 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5051 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED); 5052 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5053 5054 // Enable link layer stats gathering 5055 mWifiNative.setWifiLinkLayerStats("wlan0", 1); 5056 } 5057 5058 @Override 5059 public boolean processMessage(Message message) { 5060 logStateAndMessage(message, this); 5061 5062 switch(message.what) { 5063 case CMD_START_SCAN: 5064 handleScanRequest(message); 5065 break; 5066 case CMD_SET_FREQUENCY_BAND: 5067 int band = message.arg1; 5068 if (DBG) log("set frequency band " + band); 5069 if (mWifiNative.setBand(band)) { 5070 5071 if (DBG) logd("did set frequency band " + band); 5072 5073 mFrequencyBand.set(band); 5074 // Flush old data - like scan results 5075 mWifiNative.bssFlush(); 5076 5077 if (DBG) logd("done set frequency band " + band); 5078 5079 } else { 5080 loge("Failed to set frequency band " + band); 5081 } 5082 break; 5083 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 5084 mBluetoothConnectionActive = (message.arg1 != 5085 BluetoothAdapter.STATE_DISCONNECTED); 5086 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 5087 break; 5088 case CMD_STOP_DRIVER: 5089 int mode = message.arg1; 5090 5091 log("stop driver"); 5092 mWifiConfigManager.disableAllNetworksNative(); 5093 5094 if (getCurrentState() != mDisconnectedState) { 5095 mWifiNative.disconnect(); 5096 handleNetworkDisconnect(); 5097 } 5098 mWakeLock.acquire(); 5099 mWifiNative.stopDriver(); 5100 mWakeLock.release(); 5101 if (mP2pSupported) { 5102 transitionTo(mWaitForP2pDisableState); 5103 } else { 5104 transitionTo(mDriverStoppingState); 5105 } 5106 break; 5107 case CMD_START_DRIVER: 5108 if (mOperationalMode == CONNECT_MODE) { 5109 mWifiConfigManager.enableAllNetworks(); 5110 } 5111 break; 5112 case CMD_SET_SUSPEND_OPT_ENABLED: 5113 if (message.arg1 == 1) { 5114 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); 5115 mSuspendWakeLock.release(); 5116 } else { 5117 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); 5118 } 5119 break; 5120 case CMD_SET_HIGH_PERF_MODE: 5121 if (message.arg1 == 1) { 5122 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); 5123 } else { 5124 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); 5125 } 5126 break; 5127 case CMD_ENABLE_TDLS: 5128 if (message.obj != null) { 5129 String remoteAddress = (String) message.obj; 5130 boolean enable = (message.arg1 == 1); 5131 mWifiNative.startTdls(remoteAddress, enable); 5132 } 5133 break; 5134 case WifiMonitor.ANQP_DONE_EVENT: 5135 mWifiConfigManager.notifyANQPDone((Long) message.obj, message.arg1 != 0); 5136 break; 5137 case CMD_STOP_IP_PACKET_OFFLOAD: { 5138 int slot = message.arg1; 5139 int ret = stopWifiIPPacketOffload(slot); 5140 if (mNetworkAgent != null) { 5141 mNetworkAgent.onPacketKeepaliveEvent(slot, ret); 5142 } 5143 break; 5144 } 5145 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 5146 mWifiConfigManager.notifyIconReceived((IconEvent) message.obj); 5147 break; 5148 case WifiMonitor.HS20_REMEDIATION_EVENT: 5149 mWifiConfigManager.wnmFrameReceived((WnmData) message.obj); 5150 break; 5151 case CMD_CONFIG_ND_OFFLOAD: 5152 final boolean enabled = (message.arg1 > 0); 5153 mWifiNative.configureNeighborDiscoveryOffload(enabled); 5154 break; 5155 case CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER: 5156 if (mWifiConnectivityManager != null) { 5157 mWifiConnectivityManager.enable(message.arg1 == 1 ? true : false); 5158 } 5159 break; 5160 default: 5161 return NOT_HANDLED; 5162 } 5163 return HANDLED; 5164 } 5165 @Override 5166 public void exit() { 5167 5168 mWifiLogger.stopLogging(); 5169 5170 mIsRunning = false; 5171 updateBatteryWorkSource(null); 5172 mScanResults = new ArrayList<>(); 5173 5174 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 5175 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5176 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); 5177 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5178 noteScanEnd(); // wrap up any pending request. 5179 mBufferedScanMsg.clear(); 5180 } 5181 } 5182 5183 class WaitForP2pDisableState extends State { 5184 private State mTransitionToState; 5185 @Override 5186 public void enter() { 5187 switch (getCurrentMessage().what) { 5188 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5189 mTransitionToState = mInitialState; 5190 break; 5191 case CMD_STOP_DRIVER: 5192 mTransitionToState = mDriverStoppingState; 5193 break; 5194 case CMD_STOP_SUPPLICANT: 5195 mTransitionToState = mSupplicantStoppingState; 5196 break; 5197 default: 5198 mTransitionToState = mDriverStoppingState; 5199 break; 5200 } 5201 mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ); 5202 } 5203 @Override 5204 public boolean processMessage(Message message) { 5205 logStateAndMessage(message, this); 5206 5207 switch(message.what) { 5208 case WifiStateMachine.CMD_DISABLE_P2P_RSP: 5209 transitionTo(mTransitionToState); 5210 break; 5211 /* Defer wifi start/shut and driver commands */ 5212 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5213 case CMD_START_SUPPLICANT: 5214 case CMD_STOP_SUPPLICANT: 5215 case CMD_START_AP: 5216 case CMD_STOP_AP: 5217 case CMD_START_DRIVER: 5218 case CMD_STOP_DRIVER: 5219 case CMD_SET_OPERATIONAL_MODE: 5220 case CMD_SET_FREQUENCY_BAND: 5221 case CMD_START_SCAN: 5222 case CMD_DISCONNECT: 5223 case CMD_REASSOCIATE: 5224 case CMD_RECONNECT: 5225 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5226 deferMessage(message); 5227 break; 5228 default: 5229 return NOT_HANDLED; 5230 } 5231 return HANDLED; 5232 } 5233 } 5234 5235 class DriverStoppingState extends State { 5236 @Override 5237 public boolean processMessage(Message message) { 5238 logStateAndMessage(message, this); 5239 5240 switch(message.what) { 5241 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5242 SupplicantState state = handleSupplicantStateChange(message); 5243 if (state == SupplicantState.INTERFACE_DISABLED) { 5244 transitionTo(mDriverStoppedState); 5245 } 5246 break; 5247 /* Queue driver commands */ 5248 case CMD_START_DRIVER: 5249 case CMD_STOP_DRIVER: 5250 case CMD_SET_FREQUENCY_BAND: 5251 case CMD_START_SCAN: 5252 case CMD_DISCONNECT: 5253 case CMD_REASSOCIATE: 5254 case CMD_RECONNECT: 5255 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5256 deferMessage(message); 5257 break; 5258 default: 5259 return NOT_HANDLED; 5260 } 5261 return HANDLED; 5262 } 5263 } 5264 5265 class DriverStoppedState extends State { 5266 @Override 5267 public boolean processMessage(Message message) { 5268 logStateAndMessage(message, this); 5269 switch (message.what) { 5270 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5271 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 5272 SupplicantState state = stateChangeResult.state; 5273 // A WEXT bug means that we can be back to driver started state 5274 // unexpectedly 5275 if (SupplicantState.isDriverActive(state)) { 5276 transitionTo(mDriverStartedState); 5277 } 5278 break; 5279 case CMD_START_DRIVER: 5280 mWakeLock.acquire(); 5281 mWifiNative.startDriver(); 5282 mWakeLock.release(); 5283 transitionTo(mDriverStartingState); 5284 break; 5285 default: 5286 return NOT_HANDLED; 5287 } 5288 return HANDLED; 5289 } 5290 } 5291 5292 class ScanModeState extends State { 5293 private int mLastOperationMode; 5294 @Override 5295 public void enter() { 5296 mLastOperationMode = mOperationalMode; 5297 } 5298 @Override 5299 public boolean processMessage(Message message) { 5300 logStateAndMessage(message, this); 5301 5302 switch(message.what) { 5303 case CMD_SET_OPERATIONAL_MODE: 5304 if (message.arg1 == CONNECT_MODE) { 5305 5306 if (mLastOperationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 5307 setWifiState(WIFI_STATE_ENABLED); 5308 // Load and re-enable networks when going back to enabled state 5309 // This is essential for networks to show up after restore 5310 mWifiConfigManager.loadAndEnableAllNetworks(); 5311 mWifiP2pChannel.sendMessage(CMD_ENABLE_P2P); 5312 } else { 5313 mWifiConfigManager.enableAllNetworks(); 5314 } 5315 5316 // Loose last selection choice since user toggled WiFi 5317 mWifiConfigManager. 5318 setAndEnableLastSelectedConfiguration( 5319 WifiConfiguration.INVALID_NETWORK_ID); 5320 5321 mOperationalMode = CONNECT_MODE; 5322 transitionTo(mDisconnectedState); 5323 } else { 5324 // Nothing to do 5325 return HANDLED; 5326 } 5327 break; 5328 // Handle scan. All the connection related commands are 5329 // handled only in ConnectModeState 5330 case CMD_START_SCAN: 5331 handleScanRequest(message); 5332 break; 5333 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5334 SupplicantState state = handleSupplicantStateChange(message); 5335 if (DBG) log("SupplicantState= " + state); 5336 break; 5337 default: 5338 return NOT_HANDLED; 5339 } 5340 return HANDLED; 5341 } 5342 } 5343 5344 5345 String smToString(Message message) { 5346 return smToString(message.what); 5347 } 5348 5349 String smToString(int what) { 5350 String s = sSmToString.get(what); 5351 if (s != null) { 5352 return s; 5353 } 5354 switch (what) { 5355 case WifiMonitor.DRIVER_HUNG_EVENT: 5356 s = "DRIVER_HUNG_EVENT"; 5357 break; 5358 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 5359 s = "AsyncChannel.CMD_CHANNEL_HALF_CONNECTED"; 5360 break; 5361 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 5362 s = "AsyncChannel.CMD_CHANNEL_DISCONNECTED"; 5363 break; 5364 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 5365 s = "WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST"; 5366 break; 5367 case WifiManager.DISABLE_NETWORK: 5368 s = "WifiManager.DISABLE_NETWORK"; 5369 break; 5370 case WifiManager.CONNECT_NETWORK: 5371 s = "CONNECT_NETWORK"; 5372 break; 5373 case WifiManager.SAVE_NETWORK: 5374 s = "SAVE_NETWORK"; 5375 break; 5376 case WifiManager.FORGET_NETWORK: 5377 s = "FORGET_NETWORK"; 5378 break; 5379 case WifiMonitor.SUP_CONNECTION_EVENT: 5380 s = "SUP_CONNECTION_EVENT"; 5381 break; 5382 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5383 s = "SUP_DISCONNECTION_EVENT"; 5384 break; 5385 case WifiMonitor.SCAN_RESULTS_EVENT: 5386 s = "SCAN_RESULTS_EVENT"; 5387 break; 5388 case WifiMonitor.SCAN_FAILED_EVENT: 5389 s = "SCAN_FAILED_EVENT"; 5390 break; 5391 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5392 s = "SUPPLICANT_STATE_CHANGE_EVENT"; 5393 break; 5394 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 5395 s = "AUTHENTICATION_FAILURE_EVENT"; 5396 break; 5397 case WifiMonitor.SSID_TEMP_DISABLED: 5398 s = "SSID_TEMP_DISABLED"; 5399 break; 5400 case WifiMonitor.SSID_REENABLED: 5401 s = "SSID_REENABLED"; 5402 break; 5403 case WifiMonitor.WPS_SUCCESS_EVENT: 5404 s = "WPS_SUCCESS_EVENT"; 5405 break; 5406 case WifiMonitor.WPS_FAIL_EVENT: 5407 s = "WPS_FAIL_EVENT"; 5408 break; 5409 case WifiMonitor.SUP_REQUEST_IDENTITY: 5410 s = "SUP_REQUEST_IDENTITY"; 5411 break; 5412 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5413 s = "NETWORK_CONNECTION_EVENT"; 5414 break; 5415 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5416 s = "NETWORK_DISCONNECTION_EVENT"; 5417 break; 5418 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 5419 s = "ASSOCIATION_REJECTION_EVENT"; 5420 break; 5421 case WifiMonitor.ANQP_DONE_EVENT: 5422 s = "WifiMonitor.ANQP_DONE_EVENT"; 5423 break; 5424 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 5425 s = "WifiMonitor.RX_HS20_ANQP_ICON_EVENT"; 5426 break; 5427 case WifiMonitor.GAS_QUERY_DONE_EVENT: 5428 s = "WifiMonitor.GAS_QUERY_DONE_EVENT"; 5429 break; 5430 case WifiMonitor.HS20_REMEDIATION_EVENT: 5431 s = "WifiMonitor.HS20_REMEDIATION_EVENT"; 5432 break; 5433 case WifiMonitor.GAS_QUERY_START_EVENT: 5434 s = "WifiMonitor.GAS_QUERY_START_EVENT"; 5435 break; 5436 case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT: 5437 s = "GROUP_CREATING_TIMED_OUT"; 5438 break; 5439 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 5440 s = "P2P_CONNECTION_CHANGED"; 5441 break; 5442 case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE: 5443 s = "P2P.DISCONNECT_WIFI_RESPONSE"; 5444 break; 5445 case WifiP2pServiceImpl.SET_MIRACAST_MODE: 5446 s = "P2P.SET_MIRACAST_MODE"; 5447 break; 5448 case WifiP2pServiceImpl.BLOCK_DISCOVERY: 5449 s = "P2P.BLOCK_DISCOVERY"; 5450 break; 5451 case WifiManager.CANCEL_WPS: 5452 s = "CANCEL_WPS"; 5453 break; 5454 case WifiManager.CANCEL_WPS_FAILED: 5455 s = "CANCEL_WPS_FAILED"; 5456 break; 5457 case WifiManager.CANCEL_WPS_SUCCEDED: 5458 s = "CANCEL_WPS_SUCCEDED"; 5459 break; 5460 case WifiManager.START_WPS: 5461 s = "START_WPS"; 5462 break; 5463 case WifiManager.START_WPS_SUCCEEDED: 5464 s = "START_WPS_SUCCEEDED"; 5465 break; 5466 case WifiManager.WPS_FAILED: 5467 s = "WPS_FAILED"; 5468 break; 5469 case WifiManager.WPS_COMPLETED: 5470 s = "WPS_COMPLETED"; 5471 break; 5472 case WifiManager.RSSI_PKTCNT_FETCH: 5473 s = "RSSI_PKTCNT_FETCH"; 5474 break; 5475 default: 5476 s = "what:" + Integer.toString(what); 5477 break; 5478 } 5479 return s; 5480 } 5481 5482 void registerConnected() { 5483 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 5484 WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 5485 if (config != null) { 5486 //Here we will clear all disable counters once a network is connected 5487 //records how long this network is connected in future 5488 config.lastConnected = System.currentTimeMillis(); 5489 config.getNetworkSelectionStatus().clearDisableReasonCounter(); 5490 config.numAssociation++; 5491 } 5492 // On connect, reset wifiScoreReport 5493 mWifiScoreReport = null; 5494 } 5495 } 5496 5497 void registerDisconnected() { 5498 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 5499 // We are switching away from this configuration, 5500 // hence record the time we were connected last 5501 WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 5502 if (config != null) { 5503 config.lastDisconnected = System.currentTimeMillis(); 5504 if (config.ephemeral) { 5505 // Remove ephemeral WifiConfigurations from file 5506 mWifiConfigManager.forgetNetwork(mLastNetworkId); 5507 } 5508 } 5509 } 5510 } 5511 5512 void noteWifiDisabledWhileAssociated() { 5513 // We got disabled by user while we were associated, make note of it 5514 int rssi = mWifiInfo.getRssi(); 5515 WifiConfiguration config = getCurrentWifiConfiguration(); 5516 if (getCurrentState() == mConnectedState 5517 && rssi != WifiInfo.INVALID_RSSI 5518 && config != null) { 5519 boolean is24GHz = mWifiInfo.is24GHz(); 5520 boolean isBadRSSI = (is24GHz && rssi < mWifiConfigManager.mThresholdMinimumRssi24.get()) 5521 || (!is24GHz && rssi < mWifiConfigManager.mThresholdMinimumRssi5.get()); 5522 boolean isLowRSSI = 5523 (is24GHz && rssi < mWifiConfigManager.mThresholdQualifiedRssi24.get()) 5524 || (!is24GHz && mWifiInfo.getRssi() < 5525 mWifiConfigManager.mThresholdQualifiedRssi5.get()); 5526 boolean isHighRSSI = (is24GHz && rssi 5527 >= mWifiConfigManager.mThresholdSaturatedRssi24.get()) 5528 || (!is24GHz && mWifiInfo.getRssi() 5529 >= mWifiConfigManager.mThresholdSaturatedRssi5.get()); 5530 if (isBadRSSI) { 5531 // Take note that we got disabled while RSSI was Bad 5532 config.numUserTriggeredWifiDisableLowRSSI++; 5533 } else if (isLowRSSI) { 5534 // Take note that we got disabled while RSSI was Low 5535 config.numUserTriggeredWifiDisableBadRSSI++; 5536 } else if (!isHighRSSI) { 5537 // Take note that we got disabled while RSSI was Not high 5538 config.numUserTriggeredWifiDisableNotHighRSSI++; 5539 } 5540 } 5541 } 5542 5543 WifiConfiguration getCurrentWifiConfiguration() { 5544 if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 5545 return null; 5546 } 5547 return mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 5548 } 5549 5550 ScanResult getCurrentScanResult() { 5551 WifiConfiguration config = getCurrentWifiConfiguration(); 5552 if (config == null) { 5553 return null; 5554 } 5555 String BSSID = mWifiInfo.getBSSID(); 5556 if (BSSID == null) { 5557 BSSID = mTargetRoamBSSID; 5558 } 5559 ScanDetailCache scanDetailCache = 5560 mWifiConfigManager.getScanDetailCache(config); 5561 5562 if (scanDetailCache == null) { 5563 return null; 5564 } 5565 5566 return scanDetailCache.get(BSSID); 5567 } 5568 5569 String getCurrentBSSID() { 5570 if (linkDebouncing) { 5571 return null; 5572 } 5573 return mLastBssid; 5574 } 5575 5576 class ConnectModeState extends State { 5577 5578 @Override 5579 public void enter() { 5580 // Inform WifiConnectivityManager that Wifi is enabled 5581 if (mWifiConnectivityManager != null) { 5582 mWifiConnectivityManager.setWifiEnabled(true); 5583 } 5584 // Inform metrics that Wifi is Enabled (but not yet connected) 5585 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 5586 5587 5588 } 5589 5590 @Override 5591 public void exit() { 5592 // Inform WifiConnectivityManager that Wifi is disabled 5593 if (mWifiConnectivityManager != null) { 5594 mWifiConnectivityManager.setWifiEnabled(false); 5595 } 5596 // Inform metrics that Wifi is being disabled (Toggled, airplane enabled, etc) 5597 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISABLED); 5598 } 5599 5600 @Override 5601 public boolean processMessage(Message message) { 5602 WifiConfiguration config; 5603 int netId; 5604 boolean ok; 5605 boolean didDisconnect; 5606 String bssid; 5607 String ssid; 5608 NetworkUpdateResult result; 5609 logStateAndMessage(message, this); 5610 5611 switch (message.what) { 5612 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 5613 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_ASSOC_FAILURE); 5614 didBlackListBSSID = false; 5615 bssid = (String) message.obj; 5616 if (bssid == null || TextUtils.isEmpty(bssid)) { 5617 // If BSSID is null, use the target roam BSSID 5618 bssid = mTargetRoamBSSID; 5619 } 5620 if (bssid != null) { 5621 // If we have a BSSID, tell configStore to black list it 5622 if (mWifiConnectivityManager != null) { 5623 didBlackListBSSID = mWifiConnectivityManager.trackBssid(bssid, 5624 false); 5625 } 5626 } 5627 5628 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 5629 WifiConfiguration.NetworkSelectionStatus 5630 .DISABLED_ASSOCIATION_REJECTION); 5631 5632 mSupplicantStateTracker.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT); 5633 //If rejection occurred while Metrics is tracking a ConnnectionEvent, end it. 5634 reportConnectionAttemptEnd( 5635 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, 5636 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5637 break; 5638 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 5639 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_AUTH_FAILURE); 5640 mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); 5641 if (mTargetNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 5642 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 5643 WifiConfiguration.NetworkSelectionStatus 5644 .DISABLED_AUTHENTICATION_FAILURE); 5645 } 5646 //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. 5647 reportConnectionAttemptEnd( 5648 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, 5649 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5650 break; 5651 case WifiMonitor.SSID_TEMP_DISABLED: 5652 Log.e(TAG, "Supplicant SSID temporary disabled:" 5653 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 5654 mWifiConfigManager.updateNetworkSelectionStatus( 5655 message.arg1, 5656 WifiConfiguration.NetworkSelectionStatus 5657 .DISABLED_AUTHENTICATION_FAILURE); 5658 reportConnectionAttemptEnd( 5659 WifiMetrics.ConnectionEvent.FAILURE_SSID_TEMP_DISABLED, 5660 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5661 break; 5662 case WifiMonitor.SSID_REENABLED: 5663 Log.d(TAG, "Supplicant SSID reenable:" 5664 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 5665 // Do not re-enable it in Quality Network Selection since framework has its own 5666 // Algorithm of disable/enable 5667 break; 5668 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5669 SupplicantState state = handleSupplicantStateChange(message); 5670 // A driver/firmware hang can now put the interface in a down state. 5671 // We detect the interface going down and recover from it 5672 if (!SupplicantState.isDriverActive(state)) { 5673 if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 5674 handleNetworkDisconnect(); 5675 } 5676 log("Detected an interface down, restart driver"); 5677 transitionTo(mDriverStoppedState); 5678 sendMessage(CMD_START_DRIVER); 5679 break; 5680 } 5681 5682 // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT 5683 // when authentication times out after a successful connection, 5684 // we can figure this from the supplicant state. If supplicant 5685 // state is DISCONNECTED, but the mNetworkInfo says we are not 5686 // disconnected, we need to handle a disconnection 5687 if (!linkDebouncing && state == SupplicantState.DISCONNECTED && 5688 mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 5689 if (DBG) log("Missed CTRL-EVENT-DISCONNECTED, disconnect"); 5690 handleNetworkDisconnect(); 5691 transitionTo(mDisconnectedState); 5692 } 5693 5694 // If we have COMPLETED a connection to a BSSID, start doing 5695 // DNAv4/DNAv6 -style probing for on-link neighbors of 5696 // interest (e.g. routers); harmless if none are configured. 5697 if (state == SupplicantState.COMPLETED) { 5698 mIpManager.confirmConfiguration(); 5699 } 5700 break; 5701 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 5702 if (message.arg1 == 1) { 5703 mWifiNative.disconnect(); 5704 mTemporarilyDisconnectWifi = true; 5705 } else { 5706 mWifiNative.reconnect(); 5707 mTemporarilyDisconnectWifi = false; 5708 } 5709 break; 5710 case CMD_ADD_OR_UPDATE_NETWORK: 5711 // Only the current foreground user can modify networks. 5712 if (!mWifiConfigManager.isCurrentUserProfile( 5713 UserHandle.getUserId(message.sendingUid))) { 5714 loge("Only the current foreground user can modify networks " 5715 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5716 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5717 replyToMessage(message, message.what, FAILURE); 5718 break; 5719 } 5720 5721 config = (WifiConfiguration) message.obj; 5722 5723 if (!recordUidIfAuthorized(config, message.sendingUid, 5724 /* onlyAnnotate */ false)) { 5725 logw("Not authorized to update network " 5726 + " config=" + config.SSID 5727 + " cnid=" + config.networkId 5728 + " uid=" + message.sendingUid); 5729 replyToMessage(message, message.what, FAILURE); 5730 break; 5731 } 5732 5733 int res = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 5734 if (res < 0) { 5735 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5736 } else { 5737 WifiConfiguration curConfig = getCurrentWifiConfiguration(); 5738 if (curConfig != null && config != null) { 5739 WifiConfiguration.NetworkSelectionStatus networkStatus = 5740 config.getNetworkSelectionStatus(); 5741 if (curConfig.priority < config.priority && networkStatus != null 5742 && !networkStatus.isNetworkPermanentlyDisabled()) { 5743 // Interpret this as a connect attempt 5744 // Set the last selected configuration so as to allow the system to 5745 // stick the last user choice without persisting the choice 5746 mWifiConfigManager.setAndEnableLastSelectedConfiguration(res); 5747 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 5748 boolean persist = mWifiConfigManager 5749 .checkConfigOverridePermission(message.sendingUid); 5750 if (mWifiConnectivityManager != null) { 5751 mWifiConnectivityManager.connectToUserSelectNetwork(res, 5752 persist); 5753 } 5754 5755 // Remember time of last connection attempt 5756 lastConnectAttemptTimestamp = System.currentTimeMillis(); 5757 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5758 5759 // As a courtesy to the caller, trigger a scan now 5760 startScan(ADD_OR_UPDATE_SOURCE, 0, null, null); 5761 } 5762 } 5763 } 5764 replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK, res); 5765 break; 5766 case CMD_REMOVE_NETWORK: 5767 // Only the current foreground user can modify networks. 5768 if (!mWifiConfigManager.isCurrentUserProfile( 5769 UserHandle.getUserId(message.sendingUid))) { 5770 loge("Only the current foreground user can modify networks " 5771 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5772 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5773 replyToMessage(message, message.what, FAILURE); 5774 break; 5775 } 5776 netId = message.arg1; 5777 5778 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 5779 /* onlyAnnotate */ false)) { 5780 logw("Not authorized to remove network " 5781 + " cnid=" + netId 5782 + " uid=" + message.sendingUid); 5783 replyToMessage(message, message.what, FAILURE); 5784 break; 5785 } 5786 5787 ok = mWifiConfigManager.removeNetwork(message.arg1); 5788 if (!ok) { 5789 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5790 } 5791 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 5792 break; 5793 case CMD_ENABLE_NETWORK: 5794 // Only the current foreground user can modify networks. 5795 if (!mWifiConfigManager.isCurrentUserProfile( 5796 UserHandle.getUserId(message.sendingUid))) { 5797 loge("Only the current foreground user can modify networks " 5798 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5799 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5800 replyToMessage(message, message.what, FAILURE); 5801 break; 5802 } 5803 5804 boolean disableOthers = message.arg2 == 1; 5805 netId = message.arg1; 5806 config = mWifiConfigManager.getWifiConfiguration(netId); 5807 if (config == null) { 5808 loge("No network with id = " + netId); 5809 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5810 replyToMessage(message, message.what, FAILURE); 5811 break; 5812 } 5813 5814 // disable other only means select this network, does not mean all other 5815 // networks need to be disabled 5816 if (disableOthers) { 5817 // Remember time of last connection attempt 5818 lastConnectAttemptTimestamp = System.currentTimeMillis(); 5819 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5820 } 5821 // Cancel auto roam requests 5822 autoRoamSetBSSID(netId, "any"); 5823 5824 int uid = message.sendingUid; 5825 mWifiConfigManager.updateNetworkSelectionStatus(config, 5826 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE); 5827 mWifiConfigManager.setLatestUserSelectedConfiguration(config); 5828 ok = mWifiConfigManager.enableNetwork(netId, disableOthers, uid); 5829 if (!ok) { 5830 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5831 } else if (disableOthers) { 5832 mTargetNetworkId = netId; 5833 } 5834 5835 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 5836 break; 5837 case CMD_ENABLE_ALL_NETWORKS: 5838 long time = android.os.SystemClock.elapsedRealtime(); 5839 if (time - mLastEnableAllNetworksTime > MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS) { 5840 mWifiConfigManager.enableAllNetworks(); 5841 mLastEnableAllNetworksTime = time; 5842 } 5843 break; 5844 case WifiManager.DISABLE_NETWORK: 5845 if (mWifiConfigManager.updateNetworkSelectionStatus(message.arg1, 5846 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER)) { 5847 replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED); 5848 } else { 5849 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5850 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 5851 WifiManager.ERROR); 5852 } 5853 break; 5854 case CMD_DISABLE_EPHEMERAL_NETWORK: 5855 config = mWifiConfigManager.disableEphemeralNetwork((String)message.obj); 5856 if (config != null) { 5857 if (config.networkId == mLastNetworkId) { 5858 // Disconnect and let autojoin reselect a new network 5859 sendMessage(CMD_DISCONNECT); 5860 } 5861 } 5862 break; 5863 case CMD_BLACKLIST_NETWORK: 5864 mWifiConfigManager.blackListBssid((String) message.obj); 5865 break; 5866 case CMD_CLEAR_BLACKLIST: 5867 mWifiConfigManager.clearBssidBlacklist(); 5868 break; 5869 case CMD_SAVE_CONFIG: 5870 ok = mWifiConfigManager.saveConfig(); 5871 5872 if (DBG) logd("did save config " + ok); 5873 replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); 5874 5875 // Inform the backup manager about a data change 5876 mBackupManagerProxy.notifyDataChanged(); 5877 break; 5878 case CMD_GET_CONFIGURED_NETWORKS: 5879 replyToMessage(message, message.what, 5880 mWifiConfigManager.getConfiguredNetworks()); 5881 break; 5882 case WifiMonitor.SUP_REQUEST_IDENTITY: 5883 int networkId = message.arg2; 5884 boolean identitySent = false; 5885 int eapMethod = WifiEnterpriseConfig.Eap.NONE; 5886 5887 if (targetWificonfiguration != null 5888 && targetWificonfiguration.enterpriseConfig != null) { 5889 eapMethod = targetWificonfiguration.enterpriseConfig.getEapMethod(); 5890 } 5891 5892 // For SIM & AKA/AKA' EAP method Only, get identity from ICC 5893 if (targetWificonfiguration != null 5894 && targetWificonfiguration.networkId == networkId 5895 && targetWificonfiguration.allowedKeyManagement 5896 .get(WifiConfiguration.KeyMgmt.IEEE8021X) 5897 && (eapMethod == WifiEnterpriseConfig.Eap.SIM 5898 || eapMethod == WifiEnterpriseConfig.Eap.AKA 5899 || eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME)) { 5900 TelephonyManager tm = (TelephonyManager) 5901 mContext.getSystemService(Context.TELEPHONY_SERVICE); 5902 if (tm != null) { 5903 String imsi = tm.getSubscriberId(); 5904 String mccMnc = ""; 5905 5906 if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) 5907 mccMnc = tm.getSimOperator(); 5908 5909 String identity = buildIdentity(eapMethod, imsi, mccMnc); 5910 5911 if (!identity.isEmpty()) { 5912 mWifiNative.simIdentityResponse(networkId, identity); 5913 identitySent = true; 5914 } 5915 } 5916 } 5917 if (!identitySent) { 5918 // Supplicant lacks credentials to connect to that network, hence black list 5919 ssid = (String) message.obj; 5920 if (targetWificonfiguration != null && ssid != null 5921 && targetWificonfiguration.SSID != null 5922 && targetWificonfiguration.SSID.equals("\"" + ssid + "\"")) { 5923 mWifiConfigManager.updateNetworkSelectionStatus(targetWificonfiguration, 5924 WifiConfiguration.NetworkSelectionStatus 5925 .DISABLED_AUTHENTICATION_NO_CREDENTIALS); 5926 } 5927 // Disconnect now, as we don't have any way to fullfill 5928 // the supplicant request. 5929 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 5930 WifiConfiguration.INVALID_NETWORK_ID); 5931 mWifiNative.disconnect(); 5932 } 5933 break; 5934 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 5935 logd("Received SUP_REQUEST_SIM_AUTH"); 5936 SimAuthRequestData requestData = (SimAuthRequestData) message.obj; 5937 if (requestData != null) { 5938 if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) { 5939 handleGsmAuthRequest(requestData); 5940 } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA 5941 || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) { 5942 handle3GAuthRequest(requestData); 5943 } 5944 } else { 5945 loge("Invalid sim auth request"); 5946 } 5947 break; 5948 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 5949 replyToMessage(message, message.what, 5950 mWifiConfigManager.getPrivilegedConfiguredNetworks()); 5951 break; 5952 case CMD_GET_MATCHING_CONFIG: 5953 replyToMessage(message, message.what, 5954 mWifiConfigManager.getMatchingConfig((ScanResult)message.obj)); 5955 break; 5956 /* Do a redundant disconnect without transition */ 5957 case CMD_DISCONNECT: 5958 mWifiConfigManager.setAndEnableLastSelectedConfiguration 5959 (WifiConfiguration.INVALID_NETWORK_ID); 5960 mWifiNative.disconnect(); 5961 break; 5962 case CMD_RECONNECT: 5963 if (mWifiConnectivityManager != null) { 5964 mWifiConnectivityManager.forceConnectivityScan(); 5965 } 5966 break; 5967 case CMD_REASSOCIATE: 5968 lastConnectAttemptTimestamp = System.currentTimeMillis(); 5969 mWifiNative.reassociate(); 5970 break; 5971 case CMD_RELOAD_TLS_AND_RECONNECT: 5972 if (mWifiConfigManager.needsUnlockedKeyStore()) { 5973 logd("Reconnecting to give a chance to un-connected TLS networks"); 5974 mWifiNative.disconnect(); 5975 lastConnectAttemptTimestamp = System.currentTimeMillis(); 5976 mWifiNative.reconnect(); 5977 } 5978 break; 5979 case CMD_AUTO_ROAM: 5980 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5981 return HANDLED; 5982 case CMD_AUTO_CONNECT: 5983 /* Work Around: wpa_supplicant can get in a bad state where it returns a non 5984 * associated status to the STATUS command but somehow-someplace still thinks 5985 * it is associated and thus will ignore select/reconnect command with 5986 * following message: 5987 * "Already associated with the selected network - do nothing" 5988 * 5989 * Hence, sends a disconnect to supplicant first. 5990 */ 5991 didDisconnect = false; 5992 if (getCurrentState() != mDisconnectedState) { 5993 /** Supplicant will ignore the reconnect if we are currently associated, 5994 * hence trigger a disconnect 5995 */ 5996 didDisconnect = true; 5997 mWifiNative.disconnect(); 5998 } 5999 6000 /* connect command coming from auto-join */ 6001 netId = message.arg1; 6002 mTargetNetworkId = netId; 6003 mTargetRoamBSSID = (String) message.obj; 6004 config = mWifiConfigManager.getWifiConfiguration(netId); 6005 logd("CMD_AUTO_CONNECT sup state " 6006 + mSupplicantStateTracker.getSupplicantStateName() 6007 + " my state " + getCurrentState().getName() 6008 + " nid=" + Integer.toString(netId) 6009 + " roam=" + Boolean.toString(mAutoRoaming)); 6010 if (config == null) { 6011 loge("AUTO_CONNECT and no config, bail out..."); 6012 break; 6013 } 6014 6015 /* Make sure we cancel any previous roam request */ 6016 setTargetBssid(config, mTargetRoamBSSID); 6017 6018 /* Save the network config */ 6019 logd("CMD_AUTO_CONNECT will save config -> " + config.SSID 6020 + " nid=" + Integer.toString(netId)); 6021 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 6022 netId = result.getNetworkId(); 6023 logd("CMD_AUTO_CONNECT did save config -> " 6024 + " nid=" + Integer.toString(netId)); 6025 6026 // Since we updated the config,read it back from config store: 6027 config = mWifiConfigManager.getWifiConfiguration(netId); 6028 if (config == null) { 6029 loge("CMD_AUTO_CONNECT couldn't update the config, got null config"); 6030 break; 6031 } 6032 if (netId != config.networkId) { 6033 loge("CMD_AUTO_CONNECT couldn't update the config, want" 6034 + " nid=" + Integer.toString(netId) + " but got" + config.networkId); 6035 break; 6036 } 6037 6038 if (deferForUserInput(message, netId, false)) { 6039 break; 6040 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 6041 WifiConfiguration.USER_BANNED) { 6042 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6043 WifiManager.NOT_AUTHORIZED); 6044 break; 6045 } 6046 6047 // If we're autojoining a network that the user or an app explicitly selected, 6048 // keep track of the UID that selected it. 6049 // TODO(b/26786318): Keep track of the lastSelectedConfiguration and the 6050 // lastConnectUid on a per-user basis. 6051 int lastConnectUid = WifiConfiguration.UNKNOWN_UID; 6052 6053 //Start a new ConnectionEvent due to auto_connect, assume we are connecting 6054 //between different networks due to QNS, setting ROAM_UNRELATED 6055 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 6056 WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); 6057 if (!didDisconnect) { 6058 //If we were originally disconnected, then this was not any kind of ROAM 6059 mWifiMetrics.setConnectionEventRoamType( 6060 WifiMetricsProto.ConnectionEvent.ROAM_NONE); 6061 } 6062 //Determine if this CONNECTION is for a user selection 6063 if (mWifiConfigManager.isLastSelectedConfiguration(config) 6064 && mWifiConfigManager.isCurrentUserProfile( 6065 UserHandle.getUserId(config.lastConnectUid))) { 6066 lastConnectUid = config.lastConnectUid; 6067 mWifiMetrics.setConnectionEventRoamType( 6068 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED); 6069 } 6070 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 6071 lastConnectUid) && mWifiNative.reconnect()) { 6072 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6073 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 6074 config = mWifiConfigManager.getWifiConfiguration(netId); 6075 if (config != null 6076 && !mWifiConfigManager.isLastSelectedConfiguration(config)) { 6077 // If we autojoined a different config than the user selected one, 6078 // it means we could not see the last user selection, 6079 // or that the last user selection was faulty and ended up blacklisted 6080 // for some reason (in which case the user is notified with an error 6081 // message in the Wifi picker), and thus we managed to auto-join away 6082 // from the selected config. -> in that case we need to forget 6083 // the selection because we don't want to abruptly switch back to it. 6084 // 6085 // Note that the user selection is also forgotten after a period of time 6086 // during which the device has been disconnected. 6087 // The default value is 30 minutes : see the code path at bottom of 6088 // setScanResults() function. 6089 mWifiConfigManager. 6090 setAndEnableLastSelectedConfiguration( 6091 WifiConfiguration.INVALID_NETWORK_ID); 6092 } 6093 mAutoRoaming = false; 6094 if (isRoaming() || linkDebouncing) { 6095 transitionTo(mRoamingState); 6096 } else if (didDisconnect) { 6097 transitionTo(mDisconnectingState); 6098 } 6099 } else { 6100 loge("Failed to connect config: " + config + " netId: " + netId); 6101 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6102 WifiManager.ERROR); 6103 reportConnectionAttemptEnd( 6104 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 6105 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6106 break; 6107 } 6108 break; 6109 case CMD_REMOVE_APP_CONFIGURATIONS: 6110 mWifiConfigManager.removeNetworksForApp((ApplicationInfo) message.obj); 6111 break; 6112 case CMD_REMOVE_USER_CONFIGURATIONS: 6113 mWifiConfigManager.removeNetworksForUser(message.arg1); 6114 break; 6115 case WifiManager.CONNECT_NETWORK: 6116 // Only the current foreground user can modify networks. 6117 if (!mWifiConfigManager.isCurrentUserProfile( 6118 UserHandle.getUserId(message.sendingUid))) { 6119 loge("Only the current foreground user can modify networks " 6120 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 6121 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6122 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6123 WifiManager.NOT_AUTHORIZED); 6124 break; 6125 } 6126 6127 /** 6128 * The connect message can contain a network id passed as arg1 on message or 6129 * or a config passed as obj on message. 6130 * For a new network, a config is passed to create and connect. 6131 * For an existing network, a network id is passed 6132 */ 6133 netId = message.arg1; 6134 config = (WifiConfiguration) message.obj; 6135 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6136 boolean updatedExisting = false; 6137 6138 /* Save the network config */ 6139 if (config != null) { 6140 // When connecting to an access point, WifiStateMachine wants to update the 6141 // relevant config with administrative data. This update should not be 6142 // considered a 'real' update, therefore lockdown by Device Owner must be 6143 // disregarded. 6144 if (!recordUidIfAuthorized(config, message.sendingUid, 6145 /* onlyAnnotate */ true)) { 6146 logw("Not authorized to update network " 6147 + " config=" + config.SSID 6148 + " cnid=" + config.networkId 6149 + " uid=" + message.sendingUid); 6150 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6151 WifiManager.NOT_AUTHORIZED); 6152 break; 6153 } 6154 String configKey = config.configKey(true /* allowCached */); 6155 WifiConfiguration savedConfig = 6156 mWifiConfigManager.getWifiConfiguration(configKey); 6157 if (savedConfig != null) { 6158 // There is an existing config with this netId, but it wasn't exposed 6159 // (either AUTO_JOIN_DELETED or ephemeral; see WifiConfigManager# 6160 // getConfiguredNetworks). Remove those bits and update the config. 6161 config = savedConfig; 6162 logd("CONNECT_NETWORK updating existing config with id=" + 6163 config.networkId + " configKey=" + configKey); 6164 config.ephemeral = false; 6165 mWifiConfigManager.updateNetworkSelectionStatus(config, 6166 WifiConfiguration.NetworkSelectionStatus 6167 .NETWORK_SELECTION_ENABLE); 6168 updatedExisting = true; 6169 } 6170 6171 result = mWifiConfigManager.saveNetwork(config, message.sendingUid); 6172 netId = result.getNetworkId(); 6173 } 6174 config = mWifiConfigManager.getWifiConfiguration(netId); 6175 if (config == null) { 6176 logd("CONNECT_NETWORK no config for id=" + Integer.toString(netId) + " " 6177 + mSupplicantStateTracker.getSupplicantStateName() + " my state " 6178 + getCurrentState().getName()); 6179 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6180 WifiManager.ERROR); 6181 break; 6182 } 6183 mTargetNetworkId = netId; 6184 autoRoamSetBSSID(netId, "any"); 6185 if (message.sendingUid == Process.WIFI_UID 6186 || message.sendingUid == Process.SYSTEM_UID) { 6187 // As a sanity measure, clear the BSSID in the supplicant network block. 6188 // If system or Wifi Settings want to connect, they will not 6189 // specify the BSSID. 6190 // If an app however had added a BSSID to this configuration, and the BSSID 6191 // was wrong, Then we would forever fail to connect until that BSSID 6192 // is cleaned up. 6193 clearConfigBSSID(config, "CONNECT_NETWORK"); 6194 } 6195 6196 if (deferForUserInput(message, netId, true)) { 6197 break; 6198 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 6199 WifiConfiguration.USER_BANNED) { 6200 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6201 WifiManager.NOT_AUTHORIZED); 6202 break; 6203 } 6204 6205 mAutoRoaming = false; 6206 6207 /* Tell network selection the user did try to connect to that network if from 6208 settings */ 6209 boolean persist = 6210 mWifiConfigManager.checkConfigOverridePermission(message.sendingUid); 6211 6212 6213 mWifiConfigManager.setAndEnableLastSelectedConfiguration(netId); 6214 if (mWifiConnectivityManager != null) { 6215 mWifiConnectivityManager.connectToUserSelectNetwork(netId, persist); 6216 } 6217 didDisconnect = false; 6218 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 6219 && mLastNetworkId != netId) { 6220 /** Supplicant will ignore the reconnect if we are currently associated, 6221 * hence trigger a disconnect 6222 */ 6223 didDisconnect = true; 6224 mWifiNative.disconnect(); 6225 } 6226 6227 //Start a new ConnectionEvent due to connect_network, this is always user 6228 //selected 6229 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 6230 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED); 6231 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ true, 6232 message.sendingUid) && mWifiNative.reconnect()) { 6233 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6234 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 6235 6236 /* The state tracker handles enabling networks upon completion/failure */ 6237 mSupplicantStateTracker.sendMessage(WifiManager.CONNECT_NETWORK); 6238 replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 6239 if (didDisconnect) { 6240 /* Expect a disconnection from the old connection */ 6241 transitionTo(mDisconnectingState); 6242 } else if (updatedExisting && getCurrentState() == mConnectedState && 6243 getCurrentWifiConfiguration().networkId == netId) { 6244 // Update the current set of network capabilities, but stay in the 6245 // current state. 6246 updateCapabilities(config); 6247 } else { 6248 /** 6249 * Directly go to disconnected state where we 6250 * process the connection events from supplicant 6251 */ 6252 transitionTo(mDisconnectedState); 6253 } 6254 } else { 6255 loge("Failed to connect config: " + config + " netId: " + netId); 6256 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6257 WifiManager.ERROR); 6258 reportConnectionAttemptEnd( 6259 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 6260 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6261 break; 6262 } 6263 break; 6264 case WifiManager.SAVE_NETWORK: 6265 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6266 // Fall thru 6267 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 6268 // Only the current foreground user can modify networks. 6269 if (!mWifiConfigManager.isCurrentUserProfile( 6270 UserHandle.getUserId(message.sendingUid))) { 6271 loge("Only the current foreground user can modify networks " 6272 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 6273 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6274 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6275 WifiManager.NOT_AUTHORIZED); 6276 break; 6277 } 6278 6279 lastSavedConfigurationAttempt = null; // Used for debug 6280 config = (WifiConfiguration) message.obj; 6281 if (config == null) { 6282 loge("ERROR: SAVE_NETWORK with null configuration" 6283 + mSupplicantStateTracker.getSupplicantStateName() 6284 + " my state " + getCurrentState().getName()); 6285 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6286 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6287 WifiManager.ERROR); 6288 break; 6289 } 6290 lastSavedConfigurationAttempt = new WifiConfiguration(config); 6291 int nid = config.networkId; 6292 logd("SAVE_NETWORK id=" + Integer.toString(nid) 6293 + " config=" + config.SSID 6294 + " nid=" + config.networkId 6295 + " supstate=" + mSupplicantStateTracker.getSupplicantStateName() 6296 + " my state " + getCurrentState().getName()); 6297 6298 // Only record the uid if this is user initiated 6299 boolean checkUid = (message.what == WifiManager.SAVE_NETWORK); 6300 if (checkUid && !recordUidIfAuthorized(config, message.sendingUid, 6301 /* onlyAnnotate */ false)) { 6302 logw("Not authorized to update network " 6303 + " config=" + config.SSID 6304 + " cnid=" + config.networkId 6305 + " uid=" + message.sendingUid); 6306 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6307 WifiManager.NOT_AUTHORIZED); 6308 break; 6309 } 6310 6311 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 6312 if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) { 6313 if (mWifiInfo.getNetworkId() == result.getNetworkId()) { 6314 if (result.hasIpChanged()) { 6315 // The currently connection configuration was changed 6316 // We switched from DHCP to static or from static to DHCP, or the 6317 // static IP address has changed. 6318 log("Reconfiguring IP on connection"); 6319 // TODO: clear addresses and disable IPv6 6320 // to simplify obtainingIpState. 6321 transitionTo(mObtainingIpState); 6322 } 6323 if (result.hasProxyChanged()) { 6324 log("Reconfiguring proxy on connection"); 6325 mIpManager.setHttpProxy( 6326 mWifiConfigManager.getProxyProperties(mLastNetworkId)); 6327 } 6328 } 6329 replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED); 6330 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 6331 6332 if (DBG) { 6333 logd("Success save network nid=" 6334 + Integer.toString(result.getNetworkId())); 6335 } 6336 6337 /** 6338 * If the command comes from WifiManager, then 6339 * tell autojoin the user did try to modify and save that network, 6340 * and interpret the SAVE_NETWORK as a request to connect 6341 */ 6342 boolean user = message.what == WifiManager.SAVE_NETWORK; 6343 6344 // Did this connect come from settings 6345 boolean persistConnect = 6346 mWifiConfigManager.checkConfigOverridePermission( 6347 message.sendingUid); 6348 6349 if (user) { 6350 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 6351 mWifiConfigManager.writeKnownNetworkHistory(); 6352 } 6353 6354 if (mWifiConnectivityManager != null) { 6355 mWifiConnectivityManager.connectToUserSelectNetwork( 6356 result.getNetworkId(), persistConnect); 6357 } 6358 } else { 6359 loge("Failed to save network"); 6360 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6361 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6362 WifiManager.ERROR); 6363 } 6364 break; 6365 case WifiManager.FORGET_NETWORK: 6366 // Only the current foreground user can modify networks. 6367 if (!mWifiConfigManager.isCurrentUserProfile( 6368 UserHandle.getUserId(message.sendingUid))) { 6369 loge("Only the current foreground user can modify networks " 6370 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 6371 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6372 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 6373 WifiManager.NOT_AUTHORIZED); 6374 break; 6375 } 6376 6377 // Debug only, remember last configuration that was forgotten 6378 WifiConfiguration toRemove 6379 = mWifiConfigManager.getWifiConfiguration(message.arg1); 6380 if (toRemove == null) { 6381 lastForgetConfigurationAttempt = null; 6382 } else { 6383 lastForgetConfigurationAttempt = new WifiConfiguration(toRemove); 6384 } 6385 // check that the caller owns this network 6386 netId = message.arg1; 6387 6388 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 6389 /* onlyAnnotate */ false)) { 6390 logw("Not authorized to forget network " 6391 + " cnid=" + netId 6392 + " uid=" + message.sendingUid); 6393 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 6394 WifiManager.NOT_AUTHORIZED); 6395 break; 6396 } 6397 6398 if (mWifiConfigManager.forgetNetwork(message.arg1)) { 6399 replyToMessage(message, WifiManager.FORGET_NETWORK_SUCCEEDED); 6400 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, 6401 (WifiConfiguration) message.obj); 6402 } else { 6403 loge("Failed to forget network"); 6404 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 6405 WifiManager.ERROR); 6406 } 6407 break; 6408 case WifiManager.START_WPS: 6409 WpsInfo wpsInfo = (WpsInfo) message.obj; 6410 WpsResult wpsResult; 6411 switch (wpsInfo.setup) { 6412 case WpsInfo.PBC: 6413 wpsResult = mWifiConfigManager.startWpsPbc(wpsInfo); 6414 break; 6415 case WpsInfo.KEYPAD: 6416 wpsResult = mWifiConfigManager.startWpsWithPinFromAccessPoint(wpsInfo); 6417 break; 6418 case WpsInfo.DISPLAY: 6419 wpsResult = mWifiConfigManager.startWpsWithPinFromDevice(wpsInfo); 6420 break; 6421 default: 6422 wpsResult = new WpsResult(Status.FAILURE); 6423 loge("Invalid setup for WPS"); 6424 break; 6425 } 6426 mWifiConfigManager.setAndEnableLastSelectedConfiguration 6427 (WifiConfiguration.INVALID_NETWORK_ID); 6428 if (wpsResult.status == Status.SUCCESS) { 6429 replyToMessage(message, WifiManager.START_WPS_SUCCEEDED, wpsResult); 6430 transitionTo(mWpsRunningState); 6431 } else { 6432 loge("Failed to start WPS with config " + wpsInfo.toString()); 6433 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR); 6434 } 6435 break; 6436 case CMD_ASSOCIATED_BSSID: 6437 // This is where we can confirm the connection BSSID. Use it to find the 6438 // right ScanDetail to populate metrics. 6439 String someBssid = (String) message.obj; 6440 if (someBssid != null) { 6441 //Get the config associated with this connection attempt 6442 WifiConfiguration someConf = 6443 mWifiConfigManager.getWifiConfiguration(mTargetNetworkId); 6444 // Get the ScanDetail associated with this BSSID 6445 ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCache( 6446 someConf); 6447 if (scanDetailCache != null) { 6448 mWifiMetrics.setConnectionScanDetail(scanDetailCache.getScanDetail( 6449 someBssid)); 6450 } 6451 } 6452 return NOT_HANDLED; 6453 case WifiMonitor.NETWORK_CONNECTION_EVENT: 6454 if (DBG) log("Network connection established"); 6455 mLastNetworkId = message.arg1; 6456 mLastBssid = (String) message.obj; 6457 6458 mWifiInfo.setBSSID(mLastBssid); 6459 mWifiInfo.setNetworkId(mLastNetworkId); 6460 mWifiQualifiedNetworkSelector 6461 .enableBssidForQualityNetworkSelection(mLastBssid, true); 6462 sendNetworkStateChangeBroadcast(mLastBssid); 6463 transitionTo(mObtainingIpState); 6464 break; 6465 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6466 // Calling handleNetworkDisconnect here is redundant because we might already 6467 // have called it when leaving L2ConnectedState to go to disconnecting state 6468 // or thru other path 6469 // We should normally check the mWifiInfo or mLastNetworkId so as to check 6470 // if they are valid, and only in this case call handleNEtworkDisconnect, 6471 // TODO: this should be fixed for a L MR release 6472 // The side effect of calling handleNetworkDisconnect twice is that a bunch of 6473 // idempotent commands are executed twice (stopping Dhcp, enabling the SPS mode 6474 // at the chip etc... 6475 if (DBG) log("ConnectModeState: Network connection lost "); 6476 handleNetworkDisconnect(); 6477 transitionTo(mDisconnectedState); 6478 break; 6479 case CMD_ADD_PASSPOINT_MO: 6480 res = mWifiConfigManager.addPasspointManagementObject((String) message.obj); 6481 replyToMessage(message, message.what, res); 6482 break; 6483 case CMD_MODIFY_PASSPOINT_MO: 6484 if (message.obj != null) { 6485 Bundle bundle = (Bundle) message.obj; 6486 ArrayList<PasspointManagementObjectDefinition> mos = 6487 bundle.getParcelableArrayList("MOS"); 6488 res = mWifiConfigManager.modifyPasspointMo(bundle.getString("FQDN"), mos); 6489 } else { 6490 res = 0; 6491 } 6492 replyToMessage(message, message.what, res); 6493 6494 break; 6495 case CMD_QUERY_OSU_ICON: 6496 if (mWifiConfigManager.queryPasspointIcon( 6497 ((Bundle) message.obj).getLong("BSSID"), 6498 ((Bundle) message.obj).getString("FILENAME"))) { 6499 res = 1; 6500 } else { 6501 res = 0; 6502 } 6503 replyToMessage(message, message.what, res); 6504 break; 6505 case CMD_MATCH_PROVIDER_NETWORK: 6506 res = mWifiConfigManager.matchProviderWithCurrentNetwork((String) message.obj); 6507 replyToMessage(message, message.what, res); 6508 break; 6509 default: 6510 return NOT_HANDLED; 6511 } 6512 return HANDLED; 6513 } 6514 } 6515 6516 private void updateCapabilities(WifiConfiguration config) { 6517 NetworkCapabilities networkCapabilities = new NetworkCapabilities(mDfltNetworkCapabilities); 6518 if (config != null) { 6519 if (config.ephemeral) { 6520 networkCapabilities.removeCapability( 6521 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 6522 } else { 6523 networkCapabilities.addCapability( 6524 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 6525 } 6526 6527 networkCapabilities.setSignalStrength( 6528 (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI) 6529 ? mWifiInfo.getRssi() 6530 : NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED); 6531 } 6532 6533 if (mWifiInfo.getMeteredHint()) { 6534 networkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 6535 } 6536 6537 mNetworkAgent.sendNetworkCapabilities(networkCapabilities); 6538 } 6539 6540 private class WifiNetworkAgent extends NetworkAgent { 6541 public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, 6542 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { 6543 super(l, c, TAG, ni, nc, lp, score, misc); 6544 } 6545 protected void unwanted() { 6546 // Ignore if we're not the current networkAgent. 6547 if (this != mNetworkAgent) return; 6548 if (DBG) log("WifiNetworkAgent -> Wifi unwanted score " 6549 + Integer.toString(mWifiInfo.score)); 6550 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT); 6551 } 6552 6553 @Override 6554 protected void networkStatus(int status) { 6555 if (this != mNetworkAgent) return; 6556 if (status == NetworkAgent.INVALID_NETWORK) { 6557 if (DBG) log("WifiNetworkAgent -> Wifi networkStatus invalid, score=" 6558 + Integer.toString(mWifiInfo.score)); 6559 unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED); 6560 } else if (status == NetworkAgent.VALID_NETWORK) { 6561 if (DBG) { 6562 log("WifiNetworkAgent -> Wifi networkStatus valid, score= " 6563 + Integer.toString(mWifiInfo.score)); 6564 } 6565 doNetworkStatus(status); 6566 } 6567 } 6568 6569 @Override 6570 protected void saveAcceptUnvalidated(boolean accept) { 6571 if (this != mNetworkAgent) return; 6572 WifiStateMachine.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0); 6573 } 6574 6575 @Override 6576 protected void startPacketKeepalive(Message msg) { 6577 WifiStateMachine.this.sendMessage( 6578 CMD_START_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 6579 } 6580 6581 @Override 6582 protected void stopPacketKeepalive(Message msg) { 6583 WifiStateMachine.this.sendMessage( 6584 CMD_STOP_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 6585 } 6586 6587 @Override 6588 protected void setSignalStrengthThresholds(int[] thresholds) { 6589 // 0. If there are no thresholds, or if the thresholds are invalid, stop RSSI monitoring. 6590 // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and 6591 // MAX_VALUE at the start/end of the thresholds array if necessary. 6592 // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware 6593 // event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then 6594 // re-arm the hardware event. This needs to be done on the state machine thread to 6595 // avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one 6596 // sent in the NetworkCapabilities) must be the one received from the hardware event 6597 // received, or we might skip callbacks. 6598 // 3. Ensure that when we disconnect, RSSI monitoring is stopped. 6599 log("Received signal strength thresholds: " + Arrays.toString(thresholds)); 6600 if (thresholds.length == 0) { 6601 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 6602 mWifiInfo.getRssi()); 6603 return; 6604 } 6605 int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2); 6606 rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE; 6607 rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE; 6608 Arrays.sort(rssiVals); 6609 byte[] rssiRange = new byte[rssiVals.length]; 6610 for (int i = 0; i < rssiVals.length; i++) { 6611 int val = rssiVals[i]; 6612 if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) { 6613 rssiRange[i] = (byte) val; 6614 } else { 6615 Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: " 6616 + Arrays.toString(rssiVals)); 6617 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 6618 mWifiInfo.getRssi()); 6619 return; 6620 } 6621 } 6622 // TODO: Do we quash rssi values in this sorted array which are very close? 6623 mRssiRanges = rssiRange; 6624 WifiStateMachine.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD, 6625 mWifiInfo.getRssi()); 6626 } 6627 6628 @Override 6629 protected void preventAutomaticReconnect() { 6630 if (this != mNetworkAgent) return; 6631 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN); 6632 } 6633 } 6634 6635 void unwantedNetwork(int reason) { 6636 sendMessage(CMD_UNWANTED_NETWORK, reason); 6637 } 6638 6639 void doNetworkStatus(int status) { 6640 sendMessage(CMD_NETWORK_STATUS, status); 6641 } 6642 6643 // rfc4186 & rfc4187: 6644 // create Permanent Identity base on IMSI, 6645 // identity = usernam@realm 6646 // with username = prefix | IMSI 6647 // and realm is derived MMC/MNC tuple according 3GGP spec(TS23.003) 6648 private String buildIdentity(int eapMethod, String imsi, String mccMnc) { 6649 String mcc; 6650 String mnc; 6651 String prefix; 6652 6653 if (imsi == null || imsi.isEmpty()) 6654 return ""; 6655 6656 if (eapMethod == WifiEnterpriseConfig.Eap.SIM) 6657 prefix = "1"; 6658 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA) 6659 prefix = "0"; 6660 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME) 6661 prefix = "6"; 6662 else // not a valide EapMethod 6663 return ""; 6664 6665 /* extract mcc & mnc from mccMnc */ 6666 if (mccMnc != null && !mccMnc.isEmpty()) { 6667 mcc = mccMnc.substring(0, 3); 6668 mnc = mccMnc.substring(3); 6669 if (mnc.length() == 2) 6670 mnc = "0" + mnc; 6671 } else { 6672 // extract mcc & mnc from IMSI, assume mnc size is 3 6673 mcc = imsi.substring(0, 3); 6674 mnc = imsi.substring(3, 6); 6675 } 6676 6677 return prefix + imsi + "@wlan.mnc" + mnc + ".mcc" + mcc + ".3gppnetwork.org"; 6678 } 6679 6680 boolean startScanForConfiguration(WifiConfiguration config, boolean restrictChannelList) { 6681 if (config == null) 6682 return false; 6683 6684 // We are still seeing a fairly high power consumption triggered by autojoin scans 6685 // Hence do partial scans only for PSK configuration that are roamable since the 6686 // primary purpose of the partial scans is roaming. 6687 // Full badn scans with exponential backoff for the purpose or extended roaming and 6688 // network switching are performed unconditionally. 6689 ScanDetailCache scanDetailCache = 6690 mWifiConfigManager.getScanDetailCache(config); 6691 if (scanDetailCache == null 6692 || !config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) 6693 || scanDetailCache.size() > 6) { 6694 //return true but to not trigger the scan 6695 return true; 6696 } 6697 HashSet<Integer> freqs = mWifiConfigManager.makeChannelList(config, 6698 ONE_HOUR_MILLI, restrictChannelList); 6699 if (freqs != null && freqs.size() != 0) { 6700 //if (DBG) { 6701 logd("starting scan for " + config.configKey() + " with " + freqs); 6702 //} 6703 Set<Integer> hiddenNetworkIds = new HashSet<>(); 6704 if (config.hiddenSSID) { 6705 hiddenNetworkIds.add(config.networkId); 6706 } 6707 // Call wifi native to start the scan 6708 if (startScanNative(freqs, hiddenNetworkIds, null)) { 6709 // Only count battery consumption if scan request is accepted 6710 noteScanStart(SCAN_ALARM_SOURCE, null); 6711 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; 6712 } else { 6713 // used for debug only, mark scan as failed 6714 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 6715 } 6716 return true; 6717 } else { 6718 if (DBG) logd("no channels for " + config.configKey()); 6719 return false; 6720 } 6721 } 6722 6723 void clearCurrentConfigBSSID(String dbg) { 6724 // Clear the bssid in the current config's network block 6725 WifiConfiguration config = getCurrentWifiConfiguration(); 6726 if (config == null) 6727 return; 6728 clearConfigBSSID(config, dbg); 6729 } 6730 void clearConfigBSSID(WifiConfiguration config, String dbg) { 6731 if (config == null) 6732 return; 6733 if (DBG) { 6734 logd(dbg + " " + mTargetRoamBSSID + " config " + config.configKey() 6735 + " config.NetworkSelectionStatus.mNetworkSelectionBSSID " 6736 + config.getNetworkSelectionStatus().getNetworkSelectionBSSID()); 6737 } 6738 if (DBG) { 6739 logd(dbg + " " + config.SSID 6740 + " nid=" + Integer.toString(config.networkId)); 6741 } 6742 mWifiConfigManager.saveWifiConfigBSSID(config, "any"); 6743 } 6744 6745 class L2ConnectedState extends State { 6746 @Override 6747 public void enter() { 6748 mRssiPollToken++; 6749 if (mEnableRssiPolling) { 6750 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0); 6751 } 6752 if (mNetworkAgent != null) { 6753 loge("Have NetworkAgent when entering L2Connected"); 6754 setNetworkDetailedState(DetailedState.DISCONNECTED); 6755 } 6756 setNetworkDetailedState(DetailedState.CONNECTING); 6757 6758 mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, 6759 "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter, 6760 mLinkProperties, 60, mNetworkMisc); 6761 6762 // We must clear the config BSSID, as the wifi chipset may decide to roam 6763 // from this point on and having the BSSID specified in the network block would 6764 // cause the roam to faile and the device to disconnect 6765 clearCurrentConfigBSSID("L2ConnectedState"); 6766 mCountryCode.setReadyForChange(false); 6767 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); 6768 } 6769 6770 @Override 6771 public void exit() { 6772 mIpManager.stop(); 6773 6774 // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState 6775 // Bug: 15347363 6776 // For paranoia's sake, call handleNetworkDisconnect 6777 // only if BSSID is null or last networkId 6778 // is not invalid. 6779 if (DBG) { 6780 StringBuilder sb = new StringBuilder(); 6781 sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId)); 6782 if (mLastBssid !=null) { 6783 sb.append(" ").append(mLastBssid); 6784 } 6785 } 6786 if (mLastBssid != null || mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6787 handleNetworkDisconnect(); 6788 } 6789 mCountryCode.setReadyForChange(true); 6790 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 6791 } 6792 6793 @Override 6794 public boolean processMessage(Message message) { 6795 logStateAndMessage(message, this); 6796 6797 switch (message.what) { 6798 case DhcpClient.CMD_PRE_DHCP_ACTION: 6799 handlePreDhcpSetup(); 6800 break; 6801 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 6802 mIpManager.completedPreDhcpAction(); 6803 break; 6804 case DhcpClient.CMD_POST_DHCP_ACTION: 6805 handlePostDhcpSetup(); 6806 // We advance to mConnectedState because IpManager will also send a 6807 // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(), 6808 // which calls updateLinkProperties, which then sends 6809 // CMD_IP_CONFIGURATION_SUCCESSFUL. 6810 // 6811 // In the event of failure, we transition to mDisconnectingState 6812 // similarly--via messages sent back from IpManager. 6813 break; 6814 case CMD_IPV4_PROVISIONING_SUCCESS: { 6815 handleIPv4Success((DhcpResults) message.obj); 6816 sendNetworkStateChangeBroadcast(mLastBssid); 6817 break; 6818 } 6819 case CMD_IPV4_PROVISIONING_FAILURE: { 6820 handleIPv4Failure(); 6821 break; 6822 } 6823 case CMD_IP_CONFIGURATION_SUCCESSFUL: 6824 handleSuccessfulIpConfiguration(); 6825 reportConnectionAttemptEnd( 6826 WifiMetrics.ConnectionEvent.FAILURE_NONE, 6827 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6828 sendConnectedState(); 6829 transitionTo(mConnectedState); 6830 break; 6831 case CMD_IP_CONFIGURATION_LOST: 6832 // Get Link layer stats so that we get fresh tx packet counters. 6833 getWifiLinkLayerStats(true); 6834 handleIpConfigurationLost(); 6835 transitionTo(mDisconnectingState); 6836 break; 6837 case CMD_IP_REACHABILITY_LOST: 6838 if (DBG && message.obj != null) log((String) message.obj); 6839 handleIpReachabilityLost(); 6840 transitionTo(mDisconnectingState); 6841 break; 6842 case CMD_DISCONNECT: 6843 mWifiNative.disconnect(); 6844 transitionTo(mDisconnectingState); 6845 break; 6846 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 6847 if (message.arg1 == 1) { 6848 mWifiNative.disconnect(); 6849 mTemporarilyDisconnectWifi = true; 6850 transitionTo(mDisconnectingState); 6851 } 6852 break; 6853 case CMD_SET_OPERATIONAL_MODE: 6854 if (message.arg1 != CONNECT_MODE) { 6855 sendMessage(CMD_DISCONNECT); 6856 deferMessage(message); 6857 if (message.arg1 == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 6858 noteWifiDisabledWhileAssociated(); 6859 } 6860 } 6861 mWifiConfigManager. 6862 setAndEnableLastSelectedConfiguration( 6863 WifiConfiguration.INVALID_NETWORK_ID); 6864 break; 6865 case CMD_START_SCAN: 6866 if (DBG) { 6867 logd("CMD_START_SCAN source " + message.arg1 6868 + " txSuccessRate="+String.format( "%.2f", mWifiInfo.txSuccessRate) 6869 + " rxSuccessRate="+String.format( "%.2f", mWifiInfo.rxSuccessRate) 6870 + " targetRoamBSSID=" + mTargetRoamBSSID 6871 + " RSSI=" + mWifiInfo.getRssi()); 6872 } 6873 if (message.arg1 == SCAN_ALARM_SOURCE) { 6874 // Check if the CMD_START_SCAN message is obsolete (and thus if it should 6875 // not be processed) and restart the scan if neede 6876 if (!mWifiConfigManager.getEnableAutoJoinWhenAssociated()) { 6877 return HANDLED; 6878 } 6879 boolean shouldScan = mScreenOn; 6880 6881 if (!checkAndRestartDelayedScan(message.arg2, 6882 shouldScan, 6883 mWifiConfigManager.mWifiAssociatedShortScanIntervalMs.get(), 6884 null, null)) { 6885 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 6886 logd("L2Connected CMD_START_SCAN source " 6887 + message.arg1 6888 + " " + message.arg2 + ", " + mDelayedScanCounter 6889 + " -> obsolete"); 6890 return HANDLED; 6891 } 6892 if (mP2pConnected.get()) { 6893 logd("L2Connected CMD_START_SCAN source " 6894 + message.arg1 6895 + " " + message.arg2 + ", " + mDelayedScanCounter 6896 + " ignore because P2P is connected"); 6897 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6898 return HANDLED; 6899 } 6900 boolean tryFullBandScan = false; 6901 boolean restrictChannelList = false; 6902 long now_ms = System.currentTimeMillis(); 6903 if (DBG) { 6904 logd("CMD_START_SCAN with age=" 6905 + Long.toString(now_ms - lastFullBandConnectedTimeMilli) 6906 + " interval=" + fullBandConnectedTimeIntervalMilli 6907 + " maxinterval=" + maxFullBandConnectedTimeIntervalMilli); 6908 } 6909 6910 if (mWifiConfigManager.mEnableFullBandScanWhenAssociated.get() 6911 && (now_ms - lastFullBandConnectedTimeMilli) 6912 > fullBandConnectedTimeIntervalMilli) { 6913 if (DBG) { 6914 logd("CMD_START_SCAN try full band scan age=" 6915 + Long.toString(now_ms - lastFullBandConnectedTimeMilli) 6916 + " interval=" + fullBandConnectedTimeIntervalMilli 6917 + " maxinterval=" + maxFullBandConnectedTimeIntervalMilli); 6918 } 6919 tryFullBandScan = true; 6920 } 6921 6922 if (mWifiInfo.txSuccessRate 6923 > mWifiConfigManager.MAX_TX_PACKET_FOR_FULL_SCANS 6924 || mWifiInfo.rxSuccessRate 6925 > mWifiConfigManager.MAX_RX_PACKET_FOR_FULL_SCANS) { 6926 // Too much traffic at the interface, hence no full band scan 6927 if (DBG) { 6928 logd("CMD_START_SCAN prevent full band scan due to pkt rate"); 6929 } 6930 tryFullBandScan = false; 6931 } 6932 6933 if (mWifiInfo.txSuccessRate 6934 > mWifiConfigManager.MAX_TX_PACKET_FOR_PARTIAL_SCANS 6935 || mWifiInfo.rxSuccessRate 6936 > mWifiConfigManager.MAX_RX_PACKET_FOR_PARTIAL_SCANS) { 6937 // Don't scan if lots of packets are being sent 6938 restrictChannelList = true; 6939 if (mWifiConfigManager.mAlwaysEnableScansWhileAssociated.get() == 0) { 6940 if (DBG) { 6941 logd("CMD_START_SCAN source " + message.arg1 6942 + " ...and ignore scans" 6943 + " tx=" 6944 + String.format("%.2f", mWifiInfo.txSuccessRate) 6945 + " rx=" 6946 + String.format("%.2f", mWifiInfo.rxSuccessRate)); 6947 } 6948 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 6949 return HANDLED; 6950 } 6951 } 6952 6953 WifiConfiguration currentConfiguration = getCurrentWifiConfiguration(); 6954 if (DBG) { 6955 logd("CMD_START_SCAN full=" + 6956 tryFullBandScan); 6957 } 6958 if (currentConfiguration != null) { 6959 if (fullBandConnectedTimeIntervalMilli < 6960 mWifiConfigManager.mWifiAssociatedShortScanIntervalMs.get()) { 6961 // Sanity 6962 fullBandConnectedTimeIntervalMilli = 6963 mWifiConfigManager 6964 .mWifiAssociatedShortScanIntervalMs.get(); 6965 } 6966 if (tryFullBandScan) { 6967 lastFullBandConnectedTimeMilli = now_ms; 6968 if (fullBandConnectedTimeIntervalMilli 6969 < mWifiConfigManager.mAssociatedFullScanMaxIntervalMs) { 6970 // Increase the interval 6971 fullBandConnectedTimeIntervalMilli = 6972 fullBandConnectedTimeIntervalMilli * 6973 mWifiConfigManager 6974 .mAssociatedFullScanBackoff.get() / 8; 6975 6976 if (DBG) { 6977 logd("CMD_START_SCAN bump interval =" 6978 + fullBandConnectedTimeIntervalMilli); 6979 } 6980 } 6981 handleScanRequest(message); 6982 } else { 6983 if (!startScanForConfiguration( 6984 currentConfiguration, restrictChannelList)) { 6985 if (DBG) { 6986 logd("starting scan, " + 6987 " did not find channels -> full"); 6988 } 6989 lastFullBandConnectedTimeMilli = now_ms; 6990 if (fullBandConnectedTimeIntervalMilli 6991 < mWifiConfigManager 6992 .mAssociatedFullScanMaxIntervalMs) { 6993 // Increase the interval 6994 fullBandConnectedTimeIntervalMilli = 6995 fullBandConnectedTimeIntervalMilli 6996 * mWifiConfigManager 6997 .mAssociatedFullScanBackoff.get() 6998 / 8; 6999 7000 if (DBG) { 7001 logd("CMD_START_SCAN bump interval =" 7002 + fullBandConnectedTimeIntervalMilli); 7003 } 7004 } 7005 handleScanRequest(message); 7006 } 7007 } 7008 7009 } else { 7010 logd("CMD_START_SCAN : connected mode and no configuration"); 7011 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 7012 } 7013 } else { 7014 // Not scan alarm source 7015 return NOT_HANDLED; 7016 } 7017 break; 7018 /* Ignore connection to same network */ 7019 case WifiManager.CONNECT_NETWORK: 7020 int netId = message.arg1; 7021 if (mWifiInfo.getNetworkId() == netId) { 7022 break; 7023 } 7024 return NOT_HANDLED; 7025 case WifiMonitor.NETWORK_CONNECTION_EVENT: 7026 mWifiInfo.setBSSID((String) message.obj); 7027 mLastNetworkId = message.arg1; 7028 mWifiInfo.setNetworkId(mLastNetworkId); 7029 if(!mLastBssid.equals((String) message.obj)) { 7030 mLastBssid = (String) message.obj; 7031 sendNetworkStateChangeBroadcast(mLastBssid); 7032 } 7033 break; 7034 case CMD_RSSI_POLL: 7035 if (message.arg1 == mRssiPollToken) { 7036 if (mWifiConfigManager.mEnableChipWakeUpWhenAssociated.get()) { 7037 if (DBG) log(" get link layer stats " + mWifiLinkLayerStatsSupported); 7038 WifiLinkLayerStats stats = getWifiLinkLayerStats(DBG); 7039 if (stats != null) { 7040 // Sanity check the results provided by driver 7041 if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI 7042 && (stats.rssi_mgmt == 0 7043 || stats.beacon_rx == 0)) { 7044 stats = null; 7045 } 7046 } 7047 // Get Info and continue polling 7048 fetchRssiLinkSpeedAndFrequencyNative(); 7049 mWifiScoreReport = 7050 WifiScoreReport.calculateScore(mWifiInfo, 7051 getCurrentWifiConfiguration(), 7052 mWifiConfigManager, 7053 mNetworkAgent, 7054 mWifiScoreReport, 7055 mAggressiveHandover); 7056 } 7057 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 7058 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 7059 if (DBG) sendRssiChangeBroadcast(mWifiInfo.getRssi()); 7060 } else { 7061 // Polling has completed 7062 } 7063 break; 7064 case CMD_ENABLE_RSSI_POLL: 7065 cleanWifiScore(); 7066 if (mWifiConfigManager.mEnableRssiPollWhenAssociated.get()) { 7067 mEnableRssiPolling = (message.arg1 == 1); 7068 } else { 7069 mEnableRssiPolling = false; 7070 } 7071 mRssiPollToken++; 7072 if (mEnableRssiPolling) { 7073 // First poll 7074 fetchRssiLinkSpeedAndFrequencyNative(); 7075 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 7076 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 7077 } 7078 break; 7079 case WifiManager.RSSI_PKTCNT_FETCH: 7080 RssiPacketCountInfo info = new RssiPacketCountInfo(); 7081 fetchRssiLinkSpeedAndFrequencyNative(); 7082 info.rssi = mWifiInfo.getRssi(); 7083 fetchPktcntNative(info); 7084 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED, info); 7085 break; 7086 case CMD_DELAYED_NETWORK_DISCONNECT: 7087 if (!linkDebouncing && mWifiConfigManager.mEnableLinkDebouncing) { 7088 7089 // Ignore if we are not debouncing 7090 logd("CMD_DELAYED_NETWORK_DISCONNECT and not debouncing - ignore " 7091 + message.arg1); 7092 return HANDLED; 7093 } else { 7094 logd("CMD_DELAYED_NETWORK_DISCONNECT and debouncing - disconnect " 7095 + message.arg1); 7096 7097 linkDebouncing = false; 7098 // If we are still debouncing while this message comes, 7099 // it means we were not able to reconnect within the alloted time 7100 // = LINK_FLAPPING_DEBOUNCE_MSEC 7101 // and thus, trigger a real disconnect 7102 handleNetworkDisconnect(); 7103 transitionTo(mDisconnectedState); 7104 } 7105 break; 7106 case CMD_ASSOCIATED_BSSID: 7107 if ((String) message.obj == null) { 7108 logw("Associated command w/o BSSID"); 7109 break; 7110 } 7111 mLastBssid = (String) message.obj; 7112 if (mLastBssid != null && (mWifiInfo.getBSSID() == null 7113 || !mLastBssid.equals(mWifiInfo.getBSSID()))) { 7114 mWifiInfo.setBSSID((String) message.obj); 7115 sendNetworkStateChangeBroadcast(mLastBssid); 7116 } 7117 break; 7118 case CMD_START_RSSI_MONITORING_OFFLOAD: 7119 case CMD_RSSI_THRESHOLD_BREACH: 7120 byte currRssi = (byte) message.arg1; 7121 processRssiThreshold(currRssi, message.what); 7122 break; 7123 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 7124 stopRssiMonitoringOffload(); 7125 break; 7126 case CMD_RESET_SIM_NETWORKS: 7127 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 7128 WifiConfiguration config = 7129 mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 7130 if (mWifiConfigManager.isSimConfig(config)) { 7131 mWifiNative.disconnect(); 7132 transitionTo(mDisconnectingState); 7133 } 7134 } 7135 /* allow parent state to reset data for other networks */ 7136 return NOT_HANDLED; 7137 default: 7138 return NOT_HANDLED; 7139 } 7140 7141 return HANDLED; 7142 } 7143 } 7144 7145 class ObtainingIpState extends State { 7146 @Override 7147 public void enter() { 7148 if (DBG) { 7149 String key = ""; 7150 if (getCurrentWifiConfiguration() != null) { 7151 key = getCurrentWifiConfiguration().configKey(); 7152 } 7153 log("enter ObtainingIpState netId=" + Integer.toString(mLastNetworkId) 7154 + " " + key + " " 7155 + " roam=" + mAutoRoaming 7156 + " static=" + mWifiConfigManager.isUsingStaticIp(mLastNetworkId) 7157 + " watchdog= " + obtainingIpWatchdogCount); 7158 } 7159 7160 // Reset link Debouncing, indicating we have successfully re-connected to the AP 7161 // We might still be roaming 7162 linkDebouncing = false; 7163 7164 // Send event to CM & network change broadcast 7165 setNetworkDetailedState(DetailedState.OBTAINING_IPADDR); 7166 7167 // We must clear the config BSSID, as the wifi chipset may decide to roam 7168 // from this point on and having the BSSID specified in the network block would 7169 // cause the roam to fail and the device to disconnect. 7170 clearCurrentConfigBSSID("ObtainingIpAddress"); 7171 7172 // Stop IpManager in case we're switching from DHCP to static 7173 // configuration or vice versa. 7174 // 7175 // TODO: Only ever enter this state the first time we connect to a 7176 // network, never on switching between static configuration and 7177 // DHCP. When we transition from static configuration to DHCP in 7178 // particular, we must tell ConnectivityService that we're 7179 // disconnected, because DHCP might take a long time during which 7180 // connectivity APIs such as getActiveNetworkInfo should not return 7181 // CONNECTED. 7182 stopIpManager(); 7183 7184 mIpManager.setHttpProxy(mWifiConfigManager.getProxyProperties(mLastNetworkId)); 7185 if (!TextUtils.isEmpty(mTcpBufferSizes)) { 7186 mIpManager.setTcpBufferSizes(mTcpBufferSizes); 7187 } 7188 7189 if (!mWifiConfigManager.isUsingStaticIp(mLastNetworkId)) { 7190 final IpManager.ProvisioningConfiguration prov = 7191 mIpManager.buildProvisioningConfiguration() 7192 .withPreDhcpAction() 7193 .withApfCapabilities(mWifiNative.getApfCapabilities()) 7194 .build(); 7195 mIpManager.startProvisioning(prov); 7196 obtainingIpWatchdogCount++; 7197 logd("Start Dhcp Watchdog " + obtainingIpWatchdogCount); 7198 // Get Link layer stats so as we get fresh tx packet counters 7199 getWifiLinkLayerStats(true); 7200 sendMessageDelayed(obtainMessage(CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER, 7201 obtainingIpWatchdogCount, 0), OBTAINING_IP_ADDRESS_GUARD_TIMER_MSEC); 7202 } else { 7203 StaticIpConfiguration config = mWifiConfigManager.getStaticIpConfiguration( 7204 mLastNetworkId); 7205 if (config.ipAddress == null) { 7206 logd("Static IP lacks address"); 7207 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 7208 } else { 7209 final IpManager.ProvisioningConfiguration prov = 7210 mIpManager.buildProvisioningConfiguration() 7211 .withStaticConfiguration(config) 7212 .withApfCapabilities(mWifiNative.getApfCapabilities()) 7213 .build(); 7214 mIpManager.startProvisioning(prov); 7215 } 7216 } 7217 } 7218 7219 @Override 7220 public boolean processMessage(Message message) { 7221 logStateAndMessage(message, this); 7222 7223 switch(message.what) { 7224 case CMD_AUTO_CONNECT: 7225 case CMD_AUTO_ROAM: 7226 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7227 break; 7228 case WifiManager.SAVE_NETWORK: 7229 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 7230 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 7231 deferMessage(message); 7232 break; 7233 /* Defer any power mode changes since we must keep active power mode at DHCP */ 7234 7235 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7236 reportConnectionAttemptEnd( 7237 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 7238 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7239 return NOT_HANDLED; 7240 case CMD_SET_HIGH_PERF_MODE: 7241 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 7242 deferMessage(message); 7243 break; 7244 /* Defer scan request since we should not switch to other channels at DHCP */ 7245 case CMD_START_SCAN: 7246 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 7247 deferMessage(message); 7248 break; 7249 case CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER: 7250 if (message.arg1 == obtainingIpWatchdogCount) { 7251 logd("ObtainingIpAddress: Watchdog Triggered, count=" 7252 + obtainingIpWatchdogCount); 7253 handleIpConfigurationLost(); 7254 transitionTo(mDisconnectingState); 7255 break; 7256 } 7257 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7258 break; 7259 default: 7260 return NOT_HANDLED; 7261 } 7262 return HANDLED; 7263 } 7264 } 7265 7266 private void sendConnectedState() { 7267 // If this network was explicitly selected by the user, evaluate whether to call 7268 // explicitlySelected() so the system can treat it appropriately. 7269 WifiConfiguration config = getCurrentWifiConfiguration(); 7270 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 7271 boolean prompt = 7272 mWifiConfigManager.checkConfigOverridePermission(config.lastConnectUid); 7273 if (DBG) { 7274 log("Network selected by UID " + config.lastConnectUid + " prompt=" + prompt); 7275 } 7276 if (prompt) { 7277 // Selected by the user via Settings or QuickSettings. If this network has Internet 7278 // access, switch to it. Otherwise, switch to it only if the user confirms that they 7279 // really want to switch, or has already confirmed and selected "Don't ask again". 7280 if (DBG) { 7281 log("explictlySelected acceptUnvalidated=" + config.noInternetAccessExpected); 7282 } 7283 mNetworkAgent.explicitlySelected(config.noInternetAccessExpected); 7284 } 7285 } 7286 7287 setNetworkDetailedState(DetailedState.CONNECTED); 7288 mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.CONNECTED); 7289 sendNetworkStateChangeBroadcast(mLastBssid); 7290 } 7291 7292 class RoamingState extends State { 7293 boolean mAssociated; 7294 @Override 7295 public void enter() { 7296 if (DBG) { 7297 log("RoamingState Enter" 7298 + " mScreenOn=" + mScreenOn ); 7299 } 7300 setScanAlarm(false); 7301 7302 // Make sure we disconnect if roaming fails 7303 roamWatchdogCount++; 7304 logd("Start Roam Watchdog " + roamWatchdogCount); 7305 sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER, 7306 roamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); 7307 mAssociated = false; 7308 } 7309 @Override 7310 public boolean processMessage(Message message) { 7311 logStateAndMessage(message, this); 7312 WifiConfiguration config; 7313 switch (message.what) { 7314 case CMD_IP_CONFIGURATION_LOST: 7315 config = getCurrentWifiConfiguration(); 7316 if (config != null) { 7317 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_AUTOROAM_FAILURE); 7318 mWifiConfigManager.noteRoamingFailure(config, 7319 WifiConfiguration.ROAMING_FAILURE_IP_CONFIG); 7320 } 7321 return NOT_HANDLED; 7322 case CMD_UNWANTED_NETWORK: 7323 if (DBG) log("Roaming and CS doesnt want the network -> ignore"); 7324 return HANDLED; 7325 case CMD_SET_OPERATIONAL_MODE: 7326 if (message.arg1 != CONNECT_MODE) { 7327 deferMessage(message); 7328 } 7329 break; 7330 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 7331 /** 7332 * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT 7333 * before NETWORK_DISCONNECTION_EVENT 7334 * And there is an associated BSSID corresponding to our target BSSID, then 7335 * we have missed the network disconnection, transition to mDisconnectedState 7336 * and handle the rest of the events there. 7337 */ 7338 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 7339 if (stateChangeResult.state == SupplicantState.DISCONNECTED 7340 || stateChangeResult.state == SupplicantState.INACTIVE 7341 || stateChangeResult.state == SupplicantState.INTERFACE_DISABLED) { 7342 if (DBG) { 7343 log("STATE_CHANGE_EVENT in roaming state " 7344 + stateChangeResult.toString() ); 7345 } 7346 if (stateChangeResult.BSSID != null 7347 && stateChangeResult.BSSID.equals(mTargetRoamBSSID)) { 7348 handleNetworkDisconnect(); 7349 transitionTo(mDisconnectedState); 7350 } 7351 } 7352 if (stateChangeResult.state == SupplicantState.ASSOCIATED) { 7353 // We completed the layer2 roaming part 7354 mAssociated = true; 7355 if (stateChangeResult.BSSID != null) { 7356 mTargetRoamBSSID = (String) stateChangeResult.BSSID; 7357 } 7358 } 7359 break; 7360 case CMD_ROAM_WATCHDOG_TIMER: 7361 if (roamWatchdogCount == message.arg1) { 7362 if (DBG) log("roaming watchdog! -> disconnect"); 7363 mWifiMetrics.endConnectionEvent( 7364 WifiMetrics.ConnectionEvent.FAILURE_ROAM_TIMEOUT, 7365 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7366 mRoamFailCount++; 7367 handleNetworkDisconnect(); 7368 mWifiNative.disconnect(); 7369 transitionTo(mDisconnectedState); 7370 } 7371 break; 7372 case WifiMonitor.NETWORK_CONNECTION_EVENT: 7373 if (mAssociated) { 7374 if (DBG) log("roaming and Network connection established"); 7375 mLastNetworkId = message.arg1; 7376 mLastBssid = (String) message.obj; 7377 mWifiInfo.setBSSID(mLastBssid); 7378 mWifiInfo.setNetworkId(mLastNetworkId); 7379 if (mWifiConnectivityManager != null) { 7380 mWifiConnectivityManager.trackBssid(mLastBssid, true); 7381 } 7382 sendNetworkStateChangeBroadcast(mLastBssid); 7383 7384 // Successful framework roam! (probably) 7385 reportConnectionAttemptEnd( 7386 WifiMetrics.ConnectionEvent.FAILURE_NONE, 7387 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7388 // We used to transition to ObtainingIpState in an 7389 // attempt to do DHCPv4 RENEWs on framework roams. 7390 // DHCP can take too long to time out, and we now rely 7391 // upon IpManager's use of IpReachabilityMonitor to 7392 // confirm our current network configuration. 7393 // 7394 // mIpManager.confirmConfiguration() is called within 7395 // the handling of SupplicantState.COMPLETED. 7396 transitionTo(mConnectedState); 7397 } else { 7398 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7399 } 7400 break; 7401 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7402 // Throw away but only if it corresponds to the network we're roaming to 7403 String bssid = (String) message.obj; 7404 if (true) { 7405 String target = ""; 7406 if (mTargetRoamBSSID != null) target = mTargetRoamBSSID; 7407 log("NETWORK_DISCONNECTION_EVENT in roaming state" 7408 + " BSSID=" + bssid 7409 + " target=" + target); 7410 } 7411 if (bssid != null && bssid.equals(mTargetRoamBSSID)) { 7412 handleNetworkDisconnect(); 7413 transitionTo(mDisconnectedState); 7414 } 7415 break; 7416 case WifiMonitor.SSID_TEMP_DISABLED: 7417 // Auth error while roaming 7418 logd("SSID_TEMP_DISABLED nid=" + Integer.toString(mLastNetworkId) 7419 + " id=" + Integer.toString(message.arg1) 7420 + " isRoaming=" + isRoaming() 7421 + " roam=" + mAutoRoaming); 7422 if (message.arg1 == mLastNetworkId) { 7423 config = getCurrentWifiConfiguration(); 7424 if (config != null) { 7425 mWifiLogger.captureBugReportData( 7426 WifiLogger.REPORT_REASON_AUTOROAM_FAILURE); 7427 mWifiConfigManager.noteRoamingFailure(config, 7428 WifiConfiguration.ROAMING_FAILURE_AUTH_FAILURE); 7429 } 7430 handleNetworkDisconnect(); 7431 transitionTo(mDisconnectingState); 7432 } 7433 return NOT_HANDLED; 7434 case CMD_START_SCAN: 7435 deferMessage(message); 7436 break; 7437 default: 7438 return NOT_HANDLED; 7439 } 7440 return HANDLED; 7441 } 7442 7443 @Override 7444 public void exit() { 7445 logd("WifiStateMachine: Leaving Roaming state"); 7446 } 7447 } 7448 7449 class ConnectedState extends State { 7450 @Override 7451 public void enter() { 7452 String address; 7453 updateDefaultRouteMacAddress(1000); 7454 if (DBG) { 7455 log("Enter ConnectedState " 7456 + " mScreenOn=" + mScreenOn 7457 + " scanperiod=" 7458 + Integer.toString( 7459 mWifiConfigManager.mWifiAssociatedShortScanIntervalMs.get())); 7460 } 7461 7462 if (mWifiConnectivityManager != null) { 7463 mWifiConnectivityManager.handleConnectionStateChanged( 7464 WifiConnectivityManager.WIFI_STATE_CONNECTED); 7465 } 7466 registerConnected(); 7467 lastConnectAttemptTimestamp = 0; 7468 targetWificonfiguration = null; 7469 // Paranoia 7470 linkDebouncing = false; 7471 7472 // Not roaming anymore 7473 mAutoRoaming = false; 7474 7475 if (testNetworkDisconnect) { 7476 testNetworkDisconnectCounter++; 7477 logd("ConnectedState Enter start disconnect test " + 7478 testNetworkDisconnectCounter); 7479 sendMessageDelayed(obtainMessage(CMD_TEST_NETWORK_DISCONNECT, 7480 testNetworkDisconnectCounter, 0), 15000); 7481 } 7482 7483 // Reenable all networks, allow for hidden networks to be scanned 7484 mWifiConfigManager.enableAllNetworks(); 7485 7486 mLastDriverRoamAttempt = 0; 7487 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 7488 } 7489 @Override 7490 public boolean processMessage(Message message) { 7491 WifiConfiguration config = null; 7492 logStateAndMessage(message, this); 7493 7494 switch (message.what) { 7495 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 7496 updateAssociatedScanPermission(); 7497 break; 7498 case CMD_UNWANTED_NETWORK: 7499 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { 7500 mWifiConfigManager.handleBadNetworkDisconnectReport( 7501 mLastNetworkId, mWifiInfo); 7502 mWifiNative.disconnect(); 7503 transitionTo(mDisconnectingState); 7504 } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN || 7505 message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { 7506 Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 7507 ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN" 7508 : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED")); 7509 config = getCurrentWifiConfiguration(); 7510 if (config != null) { 7511 // Disable autojoin 7512 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) { 7513 config.validatedInternetAccess = false; 7514 // Clear last-selected status, as being last-selected also avoids 7515 // disabling auto-join. 7516 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 7517 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 7518 WifiConfiguration.INVALID_NETWORK_ID); 7519 } 7520 mWifiConfigManager.updateNetworkSelectionStatus(config, 7521 WifiConfiguration.NetworkSelectionStatus 7522 .DISABLED_NO_INTERNET); 7523 } 7524 config.numNoInternetAccessReports += 1; 7525 mWifiConfigManager.writeKnownNetworkHistory(); 7526 } 7527 } 7528 return HANDLED; 7529 case CMD_NETWORK_STATUS: 7530 if (message.arg1 == NetworkAgent.VALID_NETWORK) { 7531 config = getCurrentWifiConfiguration(); 7532 if (config != null) { 7533 // re-enable autojoin 7534 config.numNoInternetAccessReports = 0; 7535 config.validatedInternetAccess = true; 7536 mWifiConfigManager.writeKnownNetworkHistory(); 7537 } 7538 } 7539 return HANDLED; 7540 case CMD_ACCEPT_UNVALIDATED: 7541 boolean accept = (message.arg1 != 0); 7542 config = getCurrentWifiConfiguration(); 7543 if (config != null) { 7544 config.noInternetAccessExpected = accept; 7545 } 7546 return HANDLED; 7547 case CMD_TEST_NETWORK_DISCONNECT: 7548 // Force a disconnect 7549 if (message.arg1 == testNetworkDisconnectCounter) { 7550 mWifiNative.disconnect(); 7551 } 7552 break; 7553 case CMD_ASSOCIATED_BSSID: 7554 // ASSOCIATING to a new BSSID while already connected, indicates 7555 // that driver is roaming 7556 mLastDriverRoamAttempt = System.currentTimeMillis(); 7557 return NOT_HANDLED; 7558 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7559 long lastRoam = 0; 7560 reportConnectionAttemptEnd( 7561 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 7562 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7563 if (mLastDriverRoamAttempt != 0) { 7564 // Calculate time since last driver roam attempt 7565 lastRoam = System.currentTimeMillis() - mLastDriverRoamAttempt; 7566 mLastDriverRoamAttempt = 0; 7567 } 7568 if (unexpectedDisconnectedReason(message.arg2)) { 7569 mWifiLogger.captureBugReportData( 7570 WifiLogger.REPORT_REASON_UNEXPECTED_DISCONNECT); 7571 } 7572 config = getCurrentWifiConfiguration(); 7573 if (mScreenOn 7574 && !linkDebouncing 7575 && config != null 7576 && config.getNetworkSelectionStatus().isNetworkEnabled() 7577 && !mWifiConfigManager.isLastSelectedConfiguration(config) 7578 && (message.arg2 != 3 /* reason cannot be 3, i.e. locally generated */ 7579 || (lastRoam > 0 && lastRoam < 2000) /* unless driver is roaming */) 7580 && ((ScanResult.is24GHz(mWifiInfo.getFrequency()) 7581 && mWifiInfo.getRssi() > 7582 WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND) 7583 || (ScanResult.is5GHz(mWifiInfo.getFrequency()) 7584 && mWifiInfo.getRssi() > 7585 mWifiConfigManager.mThresholdQualifiedRssi5.get()))) { 7586 // Start de-bouncing the L2 disconnection: 7587 // this L2 disconnection might be spurious. 7588 // Hence we allow 4 seconds for the state machine to try 7589 // to reconnect, go thru the 7590 // roaming cycle and enter Obtaining IP address 7591 // before signalling the disconnect to ConnectivityService and L3 7592 startScanForConfiguration(getCurrentWifiConfiguration(), false); 7593 linkDebouncing = true; 7594 7595 sendMessageDelayed(obtainMessage(CMD_DELAYED_NETWORK_DISCONNECT, 7596 0, mLastNetworkId), LINK_FLAPPING_DEBOUNCE_MSEC); 7597 if (DBG) { 7598 log("NETWORK_DISCONNECTION_EVENT in connected state" 7599 + " BSSID=" + mWifiInfo.getBSSID() 7600 + " RSSI=" + mWifiInfo.getRssi() 7601 + " freq=" + mWifiInfo.getFrequency() 7602 + " reason=" + message.arg2 7603 + " -> debounce"); 7604 } 7605 return HANDLED; 7606 } else { 7607 if (DBG) { 7608 log("NETWORK_DISCONNECTION_EVENT in connected state" 7609 + " BSSID=" + mWifiInfo.getBSSID() 7610 + " RSSI=" + mWifiInfo.getRssi() 7611 + " freq=" + mWifiInfo.getFrequency() 7612 + " was debouncing=" + linkDebouncing 7613 + " reason=" + message.arg2 7614 + " Network Selection Status=" + (config == null ? "Unavailable" 7615 : config.getNetworkSelectionStatus().getNetworkStatusString())); 7616 } 7617 } 7618 break; 7619 case CMD_AUTO_ROAM: 7620 // Clear the driver roam indication since we are attempting a framework roam 7621 mLastDriverRoamAttempt = 0; 7622 7623 /*<TODO> 2016-02-24 7624 Fix CMD_AUTO_ROAM to use the candidate (message.arg1) networkID, rather than 7625 the old networkID. 7626 The current code only handles roaming between BSSIDs on the same networkID, 7627 and will break for roams between different (but linked) networkIDs. This 7628 case occurs for DBDC roaming, and the CMD_AUTO_ROAM sent due to it will 7629 fail. 7630 */ 7631 /* Connect command coming from auto-join */ 7632 ScanResult candidate = (ScanResult)message.obj; 7633 String bssid = "any"; 7634 if (candidate != null) { 7635 bssid = candidate.BSSID; 7636 } 7637 int netId = message.arg1; 7638 if (netId == WifiConfiguration.INVALID_NETWORK_ID) { 7639 loge("AUTO_ROAM and no config, bail out..."); 7640 break; 7641 } else { 7642 config = mWifiConfigManager.getWifiConfiguration(netId); 7643 } 7644 7645 logd("CMD_AUTO_ROAM sup state " 7646 + mSupplicantStateTracker.getSupplicantStateName() 7647 + " my state " + getCurrentState().getName() 7648 + " nid=" + Integer.toString(netId) 7649 + " config " + config.configKey() 7650 + " roam=" + Integer.toString(message.arg2) 7651 + " to " + bssid 7652 + " targetRoamBSSID " + mTargetRoamBSSID); 7653 7654 setTargetBssid(config, bssid); 7655 mTargetNetworkId = netId; 7656 7657 /* Determine if this is a regular roam (between BSSIDs sharing the same SSID), 7658 or a DBDC roam (between 2.4 & 5GHz networks on different SSID's, but with 7659 matching 16 byte BSSID prefixes): 7660 */ 7661 WifiConfiguration currentConfig = getCurrentWifiConfiguration(); 7662 if (currentConfig != null && currentConfig.isLinked(config)) { 7663 // This is dual band roaming 7664 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 7665 WifiMetricsProto.ConnectionEvent.ROAM_DBDC); 7666 } else { 7667 // This is regular roaming 7668 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 7669 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 7670 } 7671 7672 if (deferForUserInput(message, netId, false)) { 7673 reportConnectionAttemptEnd( 7674 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 7675 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7676 break; 7677 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 7678 WifiConfiguration.USER_BANNED) { 7679 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 7680 WifiManager.NOT_AUTHORIZED); 7681 reportConnectionAttemptEnd( 7682 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 7683 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7684 break; 7685 } 7686 7687 boolean ret = false; 7688 if (mLastNetworkId != netId) { 7689 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 7690 WifiConfiguration.UNKNOWN_UID) && mWifiNative.reconnect()) { 7691 ret = true; 7692 } 7693 } else { 7694 ret = mWifiNative.reassociate(); 7695 } 7696 if (ret) { 7697 lastConnectAttemptTimestamp = System.currentTimeMillis(); 7698 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 7699 7700 // replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 7701 mAutoRoaming = true; 7702 transitionTo(mRoamingState); 7703 7704 } else { 7705 loge("Failed to connect config: " + config + " netId: " + netId); 7706 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 7707 WifiManager.ERROR); 7708 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 7709 reportConnectionAttemptEnd( 7710 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 7711 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7712 break; 7713 } 7714 break; 7715 case CMD_START_IP_PACKET_OFFLOAD: { 7716 int slot = message.arg1; 7717 int intervalSeconds = message.arg2; 7718 KeepalivePacketData pkt = (KeepalivePacketData) message.obj; 7719 byte[] dstMac; 7720 try { 7721 InetAddress gateway = RouteInfo.selectBestRoute( 7722 mLinkProperties.getRoutes(), pkt.dstAddress).getGateway(); 7723 String dstMacStr = macAddressFromRoute(gateway.getHostAddress()); 7724 dstMac = macAddressFromString(dstMacStr); 7725 } catch (NullPointerException|IllegalArgumentException e) { 7726 loge("Can't find MAC address for next hop to " + pkt.dstAddress); 7727 mNetworkAgent.onPacketKeepaliveEvent(slot, 7728 ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 7729 break; 7730 } 7731 pkt.dstMac = dstMac; 7732 int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds); 7733 mNetworkAgent.onPacketKeepaliveEvent(slot, result); 7734 break; 7735 } 7736 default: 7737 return NOT_HANDLED; 7738 } 7739 return HANDLED; 7740 } 7741 7742 @Override 7743 public void exit() { 7744 logd("WifiStateMachine: Leaving Connected state"); 7745 if (mWifiConnectivityManager != null) { 7746 mWifiConnectivityManager.handleConnectionStateChanged( 7747 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 7748 } 7749 7750 mLastDriverRoamAttempt = 0; 7751 mWhiteListedSsids = null; 7752 } 7753 } 7754 7755 class DisconnectingState extends State { 7756 7757 @Override 7758 public void enter() { 7759 7760 if (DBG) { 7761 logd(" Enter DisconnectingState State scan interval " 7762 + mWifiConfigManager.mWifiDisconnectedShortScanIntervalMs.get() 7763 + " screenOn=" + mScreenOn); 7764 } 7765 7766 // Make sure we disconnect: we enter this state prior to connecting to a new 7767 // network, waiting for either a DISCONNECT event or a SUPPLICANT_STATE_CHANGE 7768 // event which in this case will be indicating that supplicant started to associate. 7769 // In some cases supplicant doesn't ignore the connect requests (it might not 7770 // find the target SSID in its cache), 7771 // Therefore we end up stuck that state, hence the need for the watchdog. 7772 disconnectingWatchdogCount++; 7773 logd("Start Disconnecting Watchdog " + disconnectingWatchdogCount); 7774 sendMessageDelayed(obtainMessage(CMD_DISCONNECTING_WATCHDOG_TIMER, 7775 disconnectingWatchdogCount, 0), DISCONNECTING_GUARD_TIMER_MSEC); 7776 } 7777 7778 @Override 7779 public boolean processMessage(Message message) { 7780 logStateAndMessage(message, this); 7781 switch (message.what) { 7782 case CMD_SET_OPERATIONAL_MODE: 7783 if (message.arg1 != CONNECT_MODE) { 7784 deferMessage(message); 7785 } 7786 break; 7787 case CMD_START_SCAN: 7788 deferMessage(message); 7789 return HANDLED; 7790 case CMD_DISCONNECTING_WATCHDOG_TIMER: 7791 if (disconnectingWatchdogCount == message.arg1) { 7792 if (DBG) log("disconnecting watchdog! -> disconnect"); 7793 handleNetworkDisconnect(); 7794 transitionTo(mDisconnectedState); 7795 } 7796 break; 7797 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 7798 /** 7799 * If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT 7800 * we have missed the network disconnection, transition to mDisconnectedState 7801 * and handle the rest of the events there 7802 */ 7803 deferMessage(message); 7804 handleNetworkDisconnect(); 7805 transitionTo(mDisconnectedState); 7806 break; 7807 default: 7808 return NOT_HANDLED; 7809 } 7810 return HANDLED; 7811 } 7812 } 7813 7814 class DisconnectedState extends State { 7815 @Override 7816 public void enter() { 7817 // We dont scan frequently if this is a temporary disconnect 7818 // due to p2p 7819 if (mTemporarilyDisconnectWifi) { 7820 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 7821 return; 7822 } 7823 7824 if (DBG) { 7825 logd(" Enter DisconnectedState scan interval " 7826 + mWifiConfigManager.mWifiDisconnectedShortScanIntervalMs.get() 7827 + " screenOn=" + mScreenOn); 7828 } 7829 7830 /** clear the roaming state, if we were roaming, we failed */ 7831 mAutoRoaming = false; 7832 7833 if (mWifiConnectivityManager != null) { 7834 mWifiConnectivityManager.handleConnectionStateChanged( 7835 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 7836 } 7837 7838 /** 7839 * If we have no networks saved, the supplicant stops doing the periodic scan. 7840 * The scans are useful to notify the user of the presence of an open network. 7841 * Note that these are not wake up scans. 7842 */ 7843 if (mNoNetworksPeriodicScan != 0 && !mP2pConnected.get() 7844 && mWifiConfigManager.getConfiguredNetworks().size() == 0) { 7845 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7846 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7847 } 7848 7849 mDisconnectedTimeStamp = System.currentTimeMillis(); 7850 } 7851 @Override 7852 public boolean processMessage(Message message) { 7853 boolean ret = HANDLED; 7854 7855 logStateAndMessage(message, this); 7856 7857 switch (message.what) { 7858 case CMD_NO_NETWORKS_PERIODIC_SCAN: 7859 if (mP2pConnected.get()) break; 7860 if (mNoNetworksPeriodicScan != 0 && message.arg1 == mPeriodicScanToken && 7861 mWifiConfigManager.getConfiguredNetworks().size() == 0) { 7862 startScan(UNKNOWN_SCAN_SOURCE, -1, null, null); 7863 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7864 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7865 } 7866 break; 7867 case WifiManager.FORGET_NETWORK: 7868 case CMD_REMOVE_NETWORK: 7869 case CMD_REMOVE_APP_CONFIGURATIONS: 7870 case CMD_REMOVE_USER_CONFIGURATIONS: 7871 // Set up a delayed message here. After the forget/remove is handled 7872 // the handled delayed message will determine if there is a need to 7873 // scan and continue 7874 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7875 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7876 ret = NOT_HANDLED; 7877 break; 7878 case CMD_SET_OPERATIONAL_MODE: 7879 if (message.arg1 != CONNECT_MODE) { 7880 mOperationalMode = message.arg1; 7881 mWifiConfigManager.disableAllNetworksNative(); 7882 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 7883 mWifiP2pChannel.sendMessage(CMD_DISABLE_P2P_REQ); 7884 setWifiState(WIFI_STATE_DISABLED); 7885 } 7886 transitionTo(mScanModeState); 7887 } 7888 mWifiConfigManager. 7889 setAndEnableLastSelectedConfiguration( 7890 WifiConfiguration.INVALID_NETWORK_ID); 7891 break; 7892 /* Ignore network disconnect */ 7893 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7894 // Interpret this as an L2 connection failure 7895 break; 7896 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 7897 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 7898 if (DBG) { 7899 logd("SUPPLICANT_STATE_CHANGE_EVENT state=" + stateChangeResult.state + 7900 " -> state= " + WifiInfo.getDetailedStateOf(stateChangeResult.state) 7901 + " debouncing=" + linkDebouncing); 7902 } 7903 setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state)); 7904 /* ConnectModeState does the rest of the handling */ 7905 ret = NOT_HANDLED; 7906 break; 7907 case CMD_START_SCAN: 7908 if (!checkOrDeferScanAllowed(message)) { 7909 // The scan request was rescheduled 7910 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 7911 return HANDLED; 7912 } 7913 if (message.arg1 == SCAN_ALARM_SOURCE) { 7914 // Check if the CMD_START_SCAN message is obsolete (and thus if it should 7915 // not be processed) and restart the scan 7916 int period = 7917 mWifiConfigManager.mWifiDisconnectedShortScanIntervalMs.get(); 7918 if (mP2pConnected.get()) { 7919 period = (int) mFacade.getLongSetting(mContext, 7920 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, 7921 period); 7922 } 7923 if (!checkAndRestartDelayedScan(message.arg2, 7924 true, period, null, null)) { 7925 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 7926 logd("Disconnected CMD_START_SCAN source " 7927 + message.arg1 7928 + " " + message.arg2 + ", " + mDelayedScanCounter 7929 + " -> obsolete"); 7930 return HANDLED; 7931 } 7932 7933 handleScanRequest(message); 7934 ret = HANDLED; 7935 } else { 7936 ret = NOT_HANDLED; 7937 } 7938 break; 7939 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 7940 NetworkInfo info = (NetworkInfo) message.obj; 7941 mP2pConnected.set(info.isConnected()); 7942 if (mP2pConnected.get()) { 7943 int defaultInterval = mContext.getResources().getInteger( 7944 R.integer.config_wifi_scan_interval_p2p_connected); 7945 long scanIntervalMs = mFacade.getLongSetting(mContext, 7946 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, 7947 defaultInterval); 7948 mWifiNative.setScanInterval((int) scanIntervalMs/1000); 7949 } else if (mWifiConfigManager.getConfiguredNetworks().size() == 0) { 7950 if (DBG) log("Turn on scanning after p2p disconnected"); 7951 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7952 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7953 } else { 7954 // If P2P is not connected and there are saved networks, then restart 7955 // scanning at the normal period. This is necessary because scanning might 7956 // have been disabled altogether if WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS 7957 // was set to zero. 7958 startDelayedScan( 7959 mWifiConfigManager.mWifiDisconnectedShortScanIntervalMs.get(), 7960 null, null); 7961 } 7962 break; 7963 case CMD_RECONNECT: 7964 case CMD_REASSOCIATE: 7965 if (mTemporarilyDisconnectWifi) { 7966 // Drop a third party reconnect/reassociate if STA is 7967 // temporarily disconnected for p2p 7968 break; 7969 } else { 7970 // ConnectModeState handles it 7971 ret = NOT_HANDLED; 7972 } 7973 break; 7974 case CMD_SCREEN_STATE_CHANGED: 7975 handleScreenStateChanged(message.arg1 != 0); 7976 break; 7977 default: 7978 ret = NOT_HANDLED; 7979 } 7980 return ret; 7981 } 7982 7983 @Override 7984 public void exit() { 7985 if (mWifiConnectivityManager != null) { 7986 mWifiConnectivityManager.handleConnectionStateChanged( 7987 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 7988 } 7989 } 7990 } 7991 7992 class WpsRunningState extends State { 7993 // Tracks the source to provide a reply 7994 private Message mSourceMessage; 7995 @Override 7996 public void enter() { 7997 mSourceMessage = Message.obtain(getCurrentMessage()); 7998 } 7999 @Override 8000 public boolean processMessage(Message message) { 8001 logStateAndMessage(message, this); 8002 8003 switch (message.what) { 8004 case WifiMonitor.WPS_SUCCESS_EVENT: 8005 // Ignore intermediate success, wait for full connection 8006 break; 8007 case WifiMonitor.NETWORK_CONNECTION_EVENT: 8008 replyToMessage(mSourceMessage, WifiManager.WPS_COMPLETED); 8009 mSourceMessage.recycle(); 8010 mSourceMessage = null; 8011 deferMessage(message); 8012 transitionTo(mDisconnectedState); 8013 break; 8014 case WifiMonitor.WPS_OVERLAP_EVENT: 8015 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 8016 WifiManager.WPS_OVERLAP_ERROR); 8017 mSourceMessage.recycle(); 8018 mSourceMessage = null; 8019 transitionTo(mDisconnectedState); 8020 break; 8021 case WifiMonitor.WPS_FAIL_EVENT: 8022 // Arg1 has the reason for the failure 8023 if ((message.arg1 != WifiManager.ERROR) || (message.arg2 != 0)) { 8024 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1); 8025 mSourceMessage.recycle(); 8026 mSourceMessage = null; 8027 transitionTo(mDisconnectedState); 8028 } else { 8029 if (DBG) log("Ignore unspecified fail event during WPS connection"); 8030 } 8031 break; 8032 case WifiMonitor.WPS_TIMEOUT_EVENT: 8033 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 8034 WifiManager.WPS_TIMED_OUT); 8035 mSourceMessage.recycle(); 8036 mSourceMessage = null; 8037 transitionTo(mDisconnectedState); 8038 break; 8039 case WifiManager.START_WPS: 8040 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS); 8041 break; 8042 case WifiManager.CANCEL_WPS: 8043 if (mWifiNative.cancelWps()) { 8044 replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED); 8045 } else { 8046 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR); 8047 } 8048 transitionTo(mDisconnectedState); 8049 break; 8050 /** 8051 * Defer all commands that can cause connections to a different network 8052 * or put the state machine out of connect mode 8053 */ 8054 case CMD_STOP_DRIVER: 8055 case CMD_SET_OPERATIONAL_MODE: 8056 case WifiManager.CONNECT_NETWORK: 8057 case CMD_ENABLE_NETWORK: 8058 case CMD_RECONNECT: 8059 case CMD_REASSOCIATE: 8060 case CMD_ENABLE_ALL_NETWORKS: 8061 deferMessage(message); 8062 break; 8063 case CMD_AUTO_CONNECT: 8064 case CMD_AUTO_ROAM: 8065 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 8066 return HANDLED; 8067 case CMD_START_SCAN: 8068 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 8069 return HANDLED; 8070 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8071 if (DBG) log("Network connection lost"); 8072 handleNetworkDisconnect(); 8073 break; 8074 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 8075 if (DBG) log("Ignore Assoc reject event during WPS Connection"); 8076 break; 8077 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 8078 // Disregard auth failure events during WPS connection. The 8079 // EAP sequence is retried several times, and there might be 8080 // failures (especially for wps pin). We will get a WPS_XXX 8081 // event at the end of the sequence anyway. 8082 if (DBG) log("Ignore auth failure during WPS connection"); 8083 break; 8084 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 8085 // Throw away supplicant state changes when WPS is running. 8086 // We will start getting supplicant state changes once we get 8087 // a WPS success or failure 8088 break; 8089 default: 8090 return NOT_HANDLED; 8091 } 8092 return HANDLED; 8093 } 8094 8095 @Override 8096 public void exit() { 8097 mWifiConfigManager.enableAllNetworks(); 8098 mWifiConfigManager.loadConfiguredNetworks(); 8099 } 8100 } 8101 8102 class SoftApState extends State { 8103 private SoftApManager mSoftApManager; 8104 8105 private class SoftApListener implements SoftApManager.Listener { 8106 @Override 8107 public void onStateChanged(int state, int reason) { 8108 if (state == WIFI_AP_STATE_DISABLED) { 8109 sendMessage(CMD_AP_STOPPED); 8110 } else if (state == WIFI_AP_STATE_FAILED) { 8111 sendMessage(CMD_START_AP_FAILURE); 8112 } 8113 8114 setWifiApState(state, reason); 8115 } 8116 } 8117 8118 @Override 8119 public void enter() { 8120 final Message message = getCurrentMessage(); 8121 if (message.what == CMD_START_AP) { 8122 WifiConfiguration config = (WifiConfiguration) message.obj; 8123 8124 if (config == null) { 8125 /** 8126 * Configuration not provided in the command, fallback to use the current 8127 * configuration. 8128 */ 8129 config = mWifiApConfigStore.getApConfiguration(); 8130 } else { 8131 /* Update AP configuration. */ 8132 mWifiApConfigStore.setApConfiguration(config); 8133 } 8134 8135 checkAndSetConnectivityInstance(); 8136 mSoftApManager = mFacade.makeSoftApManager( 8137 mContext, getHandler().getLooper(), mWifiNative, mNwService, 8138 mCm, mCountryCode.getCurrentCountryCode(), 8139 mWifiApConfigStore.getAllowed2GChannel(), 8140 new SoftApListener()); 8141 mSoftApManager.start(config); 8142 } else { 8143 throw new RuntimeException("Illegal transition to SoftApState: " + message); 8144 } 8145 } 8146 8147 @Override 8148 public void exit() { 8149 mSoftApManager = null; 8150 } 8151 8152 @Override 8153 public boolean processMessage(Message message) { 8154 logStateAndMessage(message, this); 8155 8156 switch(message.what) { 8157 case CMD_START_AP: 8158 /* Ignore start command when it is starting/started. */ 8159 break; 8160 case CMD_STOP_AP: 8161 mSoftApManager.stop(); 8162 break; 8163 case CMD_START_AP_FAILURE: 8164 transitionTo(mInitialState); 8165 break; 8166 case CMD_AP_STOPPED: 8167 transitionTo(mInitialState); 8168 break; 8169 default: 8170 return NOT_HANDLED; 8171 } 8172 return HANDLED; 8173 } 8174 } 8175 8176 /** 8177 * State machine initiated requests can have replyTo set to null indicating 8178 * there are no recepients, we ignore those reply actions. 8179 */ 8180 private void replyToMessage(Message msg, int what) { 8181 if (msg.replyTo == null) return; 8182 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 8183 mReplyChannel.replyToMessage(msg, dstMsg); 8184 } 8185 8186 private void replyToMessage(Message msg, int what, int arg1) { 8187 if (msg.replyTo == null) return; 8188 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 8189 dstMsg.arg1 = arg1; 8190 mReplyChannel.replyToMessage(msg, dstMsg); 8191 } 8192 8193 private void replyToMessage(Message msg, int what, Object obj) { 8194 if (msg.replyTo == null) return; 8195 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 8196 dstMsg.obj = obj; 8197 mReplyChannel.replyToMessage(msg, dstMsg); 8198 } 8199 8200 /** 8201 * arg2 on the source message has a unique id that needs to be retained in replies 8202 * to match the request 8203 * <p>see WifiManager for details 8204 */ 8205 private Message obtainMessageWithWhatAndArg2(Message srcMsg, int what) { 8206 Message msg = Message.obtain(); 8207 msg.what = what; 8208 msg.arg2 = srcMsg.arg2; 8209 return msg; 8210 } 8211 8212 /** 8213 * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT 8214 * @param msg Must have a WifiConfiguration obj to succeed 8215 */ 8216 private void broadcastWifiCredentialChanged(int wifiCredentialEventType, 8217 WifiConfiguration config) { 8218 if (config != null && config.preSharedKey != null) { 8219 Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); 8220 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); 8221 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, 8222 wifiCredentialEventType); 8223 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT, 8224 android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE); 8225 } 8226 } 8227 8228 private static int parseHex(char ch) { 8229 if ('0' <= ch && ch <= '9') { 8230 return ch - '0'; 8231 } else if ('a' <= ch && ch <= 'f') { 8232 return ch - 'a' + 10; 8233 } else if ('A' <= ch && ch <= 'F') { 8234 return ch - 'A' + 10; 8235 } else { 8236 throw new NumberFormatException("" + ch + " is not a valid hex digit"); 8237 } 8238 } 8239 8240 private byte[] parseHex(String hex) { 8241 /* This only works for good input; don't throw bad data at it */ 8242 if (hex == null) { 8243 return new byte[0]; 8244 } 8245 8246 if (hex.length() % 2 != 0) { 8247 throw new NumberFormatException(hex + " is not a valid hex string"); 8248 } 8249 8250 byte[] result = new byte[(hex.length())/2 + 1]; 8251 result[0] = (byte) ((hex.length())/2); 8252 for (int i = 0, j = 1; i < hex.length(); i += 2, j++) { 8253 int val = parseHex(hex.charAt(i)) * 16 + parseHex(hex.charAt(i+1)); 8254 byte b = (byte) (val & 0xFF); 8255 result[j] = b; 8256 } 8257 8258 return result; 8259 } 8260 8261 private static String makeHex(byte[] bytes) { 8262 StringBuilder sb = new StringBuilder(); 8263 for (byte b : bytes) { 8264 sb.append(String.format("%02x", b)); 8265 } 8266 return sb.toString(); 8267 } 8268 8269 private static String makeHex(byte[] bytes, int from, int len) { 8270 StringBuilder sb = new StringBuilder(); 8271 for (int i = 0; i < len; i++) { 8272 sb.append(String.format("%02x", bytes[from+i])); 8273 } 8274 return sb.toString(); 8275 } 8276 8277 private static byte[] concat(byte[] array1, byte[] array2, byte[] array3) { 8278 8279 int len = array1.length + array2.length + array3.length; 8280 8281 if (array1.length != 0) { 8282 len++; /* add another byte for size */ 8283 } 8284 8285 if (array2.length != 0) { 8286 len++; /* add another byte for size */ 8287 } 8288 8289 if (array3.length != 0) { 8290 len++; /* add another byte for size */ 8291 } 8292 8293 byte[] result = new byte[len]; 8294 8295 int index = 0; 8296 if (array1.length != 0) { 8297 result[index] = (byte) (array1.length & 0xFF); 8298 index++; 8299 for (byte b : array1) { 8300 result[index] = b; 8301 index++; 8302 } 8303 } 8304 8305 if (array2.length != 0) { 8306 result[index] = (byte) (array2.length & 0xFF); 8307 index++; 8308 for (byte b : array2) { 8309 result[index] = b; 8310 index++; 8311 } 8312 } 8313 8314 if (array3.length != 0) { 8315 result[index] = (byte) (array3.length & 0xFF); 8316 index++; 8317 for (byte b : array3) { 8318 result[index] = b; 8319 index++; 8320 } 8321 } 8322 return result; 8323 } 8324 8325 private static byte[] concatHex(byte[] array1, byte[] array2) { 8326 8327 int len = array1.length + array2.length; 8328 8329 byte[] result = new byte[len]; 8330 8331 int index = 0; 8332 if (array1.length != 0) { 8333 for (byte b : array1) { 8334 result[index] = b; 8335 index++; 8336 } 8337 } 8338 8339 if (array2.length != 0) { 8340 for (byte b : array2) { 8341 result[index] = b; 8342 index++; 8343 } 8344 } 8345 8346 return result; 8347 } 8348 8349 String getGsmSimAuthResponse(String[] requestData, TelephonyManager tm) { 8350 StringBuilder sb = new StringBuilder(); 8351 for (String challenge : requestData) { 8352 if (challenge == null || challenge.isEmpty()) { 8353 continue; 8354 } 8355 logd("RAND = " + challenge); 8356 8357 byte[] rand = null; 8358 try { 8359 rand = parseHex(challenge); 8360 } catch (NumberFormatException e) { 8361 loge("malformed challenge"); 8362 continue; 8363 } 8364 8365 String base64Challenge = android.util.Base64.encodeToString( 8366 rand, android.util.Base64.NO_WRAP); 8367 8368 // Try USIM first for authentication. 8369 String tmResponse = tm.getIccAuthentication(tm.APPTYPE_USIM, 8370 tm.AUTHTYPE_EAP_SIM, base64Challenge); 8371 if (tmResponse == null) { 8372 /* Then, in case of failure, issue may be due to sim type, retry as a simple sim 8373 */ 8374 tmResponse = tm.getIccAuthentication(tm.APPTYPE_SIM, 8375 tm.AUTHTYPE_EAP_SIM, base64Challenge); 8376 } 8377 logv("Raw Response - " + tmResponse); 8378 8379 if (tmResponse == null || tmResponse.length() <= 4) { 8380 loge("bad response - " + tmResponse); 8381 return null; 8382 } 8383 8384 byte[] result = android.util.Base64.decode(tmResponse, android.util.Base64.DEFAULT); 8385 logv("Hex Response -" + makeHex(result)); 8386 int sres_len = result[0]; 8387 if (sres_len >= result.length) { 8388 loge("malfomed response - " + tmResponse); 8389 return null; 8390 } 8391 String sres = makeHex(result, 1, sres_len); 8392 int kc_offset = 1 + sres_len; 8393 if (kc_offset >= result.length) { 8394 loge("malfomed response - " + tmResponse); 8395 return null; 8396 } 8397 int kc_len = result[kc_offset]; 8398 if (kc_offset + kc_len > result.length) { 8399 loge("malfomed response - " + tmResponse); 8400 return null; 8401 } 8402 String kc = makeHex(result, 1 + kc_offset, kc_len); 8403 sb.append(":" + kc + ":" + sres); 8404 logv("kc:" + kc + " sres:" + sres); 8405 } 8406 8407 return sb.toString(); 8408 } 8409 8410 void handleGsmAuthRequest(SimAuthRequestData requestData) { 8411 if (targetWificonfiguration == null 8412 || targetWificonfiguration.networkId == requestData.networkId) { 8413 logd("id matches targetWifiConfiguration"); 8414 } else { 8415 logd("id does not match targetWifiConfiguration"); 8416 return; 8417 } 8418 8419 TelephonyManager tm = (TelephonyManager) 8420 mContext.getSystemService(Context.TELEPHONY_SERVICE); 8421 8422 if (tm == null) { 8423 loge("could not get telephony manager"); 8424 mWifiNative.simAuthFailedResponse(requestData.networkId); 8425 return; 8426 } 8427 8428 String response = getGsmSimAuthResponse(requestData.data, tm); 8429 if (response == null) { 8430 mWifiNative.simAuthFailedResponse(requestData.networkId); 8431 } else { 8432 logv("Supplicant Response -" + response); 8433 mWifiNative.simAuthResponse(requestData.networkId, "GSM-AUTH", response); 8434 } 8435 } 8436 8437 void handle3GAuthRequest(SimAuthRequestData requestData) { 8438 StringBuilder sb = new StringBuilder(); 8439 byte[] rand = null; 8440 byte[] authn = null; 8441 String res_type = "UMTS-AUTH"; 8442 8443 if (targetWificonfiguration == null 8444 || targetWificonfiguration.networkId == requestData.networkId) { 8445 logd("id matches targetWifiConfiguration"); 8446 } else { 8447 logd("id does not match targetWifiConfiguration"); 8448 return; 8449 } 8450 if (requestData.data.length == 2) { 8451 try { 8452 rand = parseHex(requestData.data[0]); 8453 authn = parseHex(requestData.data[1]); 8454 } catch (NumberFormatException e) { 8455 loge("malformed challenge"); 8456 } 8457 } else { 8458 loge("malformed challenge"); 8459 } 8460 8461 String tmResponse = ""; 8462 if (rand != null && authn != null) { 8463 String base64Challenge = android.util.Base64.encodeToString( 8464 concatHex(rand,authn), android.util.Base64.NO_WRAP); 8465 8466 TelephonyManager tm = (TelephonyManager) 8467 mContext.getSystemService(Context.TELEPHONY_SERVICE); 8468 if (tm != null) { 8469 tmResponse = tm.getIccAuthentication(tm.APPTYPE_USIM, 8470 tm.AUTHTYPE_EAP_AKA, base64Challenge); 8471 logv("Raw Response - " + tmResponse); 8472 } else { 8473 loge("could not get telephony manager"); 8474 } 8475 } 8476 8477 boolean good_response = false; 8478 if (tmResponse != null && tmResponse.length() > 4) { 8479 byte[] result = android.util.Base64.decode(tmResponse, 8480 android.util.Base64.DEFAULT); 8481 loge("Hex Response - " + makeHex(result)); 8482 byte tag = result[0]; 8483 if (tag == (byte) 0xdb) { 8484 logv("successful 3G authentication "); 8485 int res_len = result[1]; 8486 String res = makeHex(result, 2, res_len); 8487 int ck_len = result[res_len + 2]; 8488 String ck = makeHex(result, res_len + 3, ck_len); 8489 int ik_len = result[res_len + ck_len + 3]; 8490 String ik = makeHex(result, res_len + ck_len + 4, ik_len); 8491 sb.append(":" + ik + ":" + ck + ":" + res); 8492 logv("ik:" + ik + "ck:" + ck + " res:" + res); 8493 good_response = true; 8494 } else if (tag == (byte) 0xdc) { 8495 loge("synchronisation failure"); 8496 int auts_len = result[1]; 8497 String auts = makeHex(result, 2, auts_len); 8498 res_type = "UMTS-AUTS"; 8499 sb.append(":" + auts); 8500 logv("auts:" + auts); 8501 good_response = true; 8502 } else { 8503 loge("bad response - unknown tag = " + tag); 8504 } 8505 } else { 8506 loge("bad response - " + tmResponse); 8507 } 8508 8509 if (good_response) { 8510 String response = sb.toString(); 8511 logv("Supplicant Response -" + response); 8512 mWifiNative.simAuthResponse(requestData.networkId, res_type, response); 8513 } else { 8514 mWifiNative.umtsAuthFailedResponse(requestData.networkId); 8515 } 8516 } 8517 8518 /** 8519 * Automatically connect to the network specified 8520 * 8521 * @param networkId ID of the network to connect to 8522 * @param bssid BSSID of the network 8523 */ 8524 public void autoConnectToNetwork(int networkId, String bssid) { 8525 sendMessage(CMD_AUTO_CONNECT, networkId, 0, bssid); 8526 } 8527 8528 /** 8529 * Automatically roam to the network specified 8530 * 8531 * @param networkId ID of the network to roam to 8532 * @param scanResult scan result which identifies the network to roam to 8533 */ 8534 public void autoRoamToNetwork(int networkId, ScanResult scanResult) { 8535 sendMessage(CMD_AUTO_ROAM, networkId, 0, scanResult); 8536 } 8537 8538 /** 8539 * Dynamically turn on/off WifiConnectivityManager 8540 * 8541 * @param enabled true-enable; false-disable 8542 */ 8543 public void enableWifiConnectivityManager(boolean enabled) { 8544 sendMessage(CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER, enabled ? 1 : 0); 8545 } 8546 8547 /** 8548 * @param reason reason code from supplicant on network disconnected event 8549 * @return true if this is a suspicious disconnect 8550 */ 8551 static boolean unexpectedDisconnectedReason(int reason) { 8552 return reason == 2 // PREV_AUTH_NOT_VALID 8553 || reason == 6 // CLASS2_FRAME_FROM_NONAUTH_STA 8554 || reason == 7 // FRAME_FROM_NONASSOC_STA 8555 || reason == 8 // STA_HAS_LEFT 8556 || reason == 9 // STA_REQ_ASSOC_WITHOUT_AUTH 8557 || reason == 14 // MICHAEL_MIC_FAILURE 8558 || reason == 15 // 4WAY_HANDSHAKE_TIMEOUT 8559 || reason == 16 // GROUP_KEY_UPDATE_TIMEOUT 8560 || reason == 18 // GROUP_CIPHER_NOT_VALID 8561 || reason == 19 // PAIRWISE_CIPHER_NOT_VALID 8562 || reason == 23 // IEEE_802_1X_AUTH_FAILED 8563 || reason == 34; // DISASSOC_LOW_ACK 8564 } 8565 8566 /** 8567 * Update WifiMetrics before dumping 8568 */ 8569 void updateWifiMetrics() { 8570 int numSavedNetworks = mWifiConfigManager.getConfiguredNetworksSize(); 8571 int numOpenNetworks = 0; 8572 int numPersonalNetworks = 0; 8573 int numEnterpriseNetworks = 0; 8574 int numNetworksAddedByUser = 0; 8575 int numNetworksAddedByApps = 0; 8576 for (WifiConfiguration config : mWifiConfigManager.getConfiguredNetworks()) { 8577 if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { 8578 numOpenNetworks++; 8579 } else if (config.isEnterprise()) { 8580 numEnterpriseNetworks++; 8581 } else { 8582 numPersonalNetworks++; 8583 } 8584 if (config.selfAdded) { 8585 numNetworksAddedByUser++; 8586 } else { 8587 numNetworksAddedByApps++; 8588 } 8589 } 8590 mWifiMetrics.setNumSavedNetworks(numSavedNetworks); 8591 mWifiMetrics.setNumOpenNetworks(numOpenNetworks); 8592 mWifiMetrics.setNumPersonalNetworks(numPersonalNetworks); 8593 mWifiMetrics.setNumEnterpriseNetworks(numEnterpriseNetworks); 8594 mWifiMetrics.setNumNetworksAddedByUser(numNetworksAddedByUser); 8595 mWifiMetrics.setNumNetworksAddedByApps(numNetworksAddedByApps); 8596 8597 /* <TODO> decide how to access WifiServiecImpl.isLocationEnabled() or if to do it manually 8598 mWifiMetrics.setIsLocationEnabled(Settings.Secure.getInt( 8599 mContext.getContentResolver(), 8600 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) 8601 != Settings.Secure.LOCATION_MODE_OFF); 8602 */ 8603 8604 /* <TODO> decide how statemachine will access WifiSettingsStore 8605 mWifiMetrics.setIsScanningAlwaysEnabled(mSettingsStore.isScanningAlwaysAvailable()); 8606 */ 8607 } 8608 8609 private static String getLinkPropertiesSummary(LinkProperties lp) { 8610 List<String> attributes = new ArrayList(6); 8611 if (lp.hasIPv4Address()) { 8612 attributes.add("v4"); 8613 } 8614 if (lp.hasIPv4DefaultRoute()) { 8615 attributes.add("v4r"); 8616 } 8617 if (lp.hasIPv4DnsServer()) { 8618 attributes.add("v4dns"); 8619 } 8620 if (lp.hasGlobalIPv6Address()) { 8621 attributes.add("v6"); 8622 } 8623 if (lp.hasIPv6DefaultRoute()) { 8624 attributes.add("v6r"); 8625 } 8626 if (lp.hasIPv6DnsServer()) { 8627 attributes.add("v6dns"); 8628 } 8629 8630 return TextUtils.join(" ", attributes); 8631 } 8632} 8633