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