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