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