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