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