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