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