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