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