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