WifiStateMachine.java revision f11073c03746f1c79e6a316884bc59574b562a8b
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 int alertReason = message.arg1; 3934 mWifiDiagnostics.captureAlertData(alertReason, buffer); 3935 mWifiMetrics.incrementAlertReasonCount(alertReason); 3936 } 3937 break; 3938 case CMD_GET_LINK_LAYER_STATS: 3939 // Not supported hence reply with error message 3940 replyToMessage(message, message.what, null); 3941 break; 3942 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 3943 NetworkInfo info = (NetworkInfo) message.obj; 3944 mP2pConnected.set(info.isConnected()); 3945 break; 3946 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 3947 mTemporarilyDisconnectWifi = (message.arg1 == 1); 3948 replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 3949 break; 3950 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 3951 case CMD_UPDATE_LINKPROPERTIES: 3952 updateLinkProperties((LinkProperties) message.obj); 3953 break; 3954 case CMD_GET_MATCHING_CONFIG: 3955 replyToMessage(message, message.what); 3956 break; 3957 case CMD_IP_CONFIGURATION_SUCCESSFUL: 3958 case CMD_IP_CONFIGURATION_LOST: 3959 case CMD_IP_REACHABILITY_LOST: 3960 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3961 break; 3962 case CMD_GET_CONNECTION_STATISTICS: 3963 replyToMessage(message, message.what, mWifiConnectionStatistics); 3964 break; 3965 case CMD_REMOVE_APP_CONFIGURATIONS: 3966 deferMessage(message); 3967 break; 3968 case CMD_REMOVE_USER_CONFIGURATIONS: 3969 deferMessage(message); 3970 break; 3971 case CMD_START_IP_PACKET_OFFLOAD: 3972 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 3973 message.arg1, 3974 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 3975 break; 3976 case CMD_STOP_IP_PACKET_OFFLOAD: 3977 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 3978 message.arg1, 3979 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 3980 break; 3981 case CMD_START_RSSI_MONITORING_OFFLOAD: 3982 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3983 break; 3984 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 3985 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3986 break; 3987 case CMD_USER_SWITCH: 3988 mWifiConfigManager.handleUserSwitch(message.arg1); 3989 break; 3990 case CMD_ADD_PASSPOINT_MO: 3991 case CMD_MODIFY_PASSPOINT_MO: 3992 case CMD_QUERY_OSU_ICON: 3993 case CMD_MATCH_PROVIDER_NETWORK: 3994 /* reply with arg1 = 0 - it returns API failure to the calling app 3995 * (message.what is not looked at) 3996 */ 3997 replyToMessage(message, message.what); 3998 break; 3999 case CMD_RESET_SIM_NETWORKS: 4000 /* Defer this message until supplicant is started. */ 4001 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 4002 deferMessage(message); 4003 break; 4004 case CMD_INSTALL_PACKET_FILTER: 4005 mWifiNative.installPacketFilter((byte[]) message.obj); 4006 break; 4007 case CMD_SET_FALLBACK_PACKET_FILTERING: 4008 if ((boolean) message.obj) { 4009 mWifiNative.startFilteringMulticastV4Packets(); 4010 } else { 4011 mWifiNative.stopFilteringMulticastV4Packets(); 4012 } 4013 break; 4014 case CMD_CLIENT_INTERFACE_BINDER_DEATH: 4015 // We have lost contact with a client interface, which means that we cannot 4016 // trust that the driver is up or that the interface is ready. We are fit 4017 // for no WiFi related work. 4018 transitionTo(mInitialState); 4019 break; 4020 default: 4021 loge("Error! unhandled message" + message); 4022 break; 4023 } 4024 return HANDLED; 4025 } 4026 } 4027 4028 class InitialState extends State { 4029 4030 private void cleanup() { 4031 // Tearing down the client interfaces below is going to stop our supplicant. 4032 mWifiMonitor.stopAllMonitoring(); 4033 4034 mDeathRecipient.unlinkToDeath(); 4035 if (mWificond != null) { 4036 try { 4037 mWificond.tearDownInterfaces(); 4038 } catch (RemoteException e) { 4039 // There is very little we can do here 4040 Log.e(TAG, "Failed to tear down interfaces via wificond"); 4041 } 4042 mWificond = null; 4043 } 4044 mWifiNative.stopHal(); 4045 } 4046 4047 @Override 4048 public void enter() { 4049 cleanup(); 4050 if (mWifiP2pChannel == null && mWifiP2pServiceImpl != null) { 4051 mWifiP2pChannel = new AsyncChannel(); 4052 mWifiP2pChannel.connect(mContext, getHandler(), 4053 mWifiP2pServiceImpl.getP2pStateMachineMessenger()); 4054 } 4055 4056 if (mWifiApConfigStore == null) { 4057 mWifiApConfigStore = 4058 mFacade.makeApConfigStore(mContext, mBackupManagerProxy); 4059 } 4060 } 4061 @Override 4062 public boolean processMessage(Message message) { 4063 logStateAndMessage(message, this); 4064 switch (message.what) { 4065 case CMD_START_SUPPLICANT: 4066 // Refresh our reference to wificond. This allows us to tolerate restarts. 4067 mWificond = mWifiInjector.makeWificond(); 4068 mClientInterface = setupDriverForClientMode(mWificond); 4069 if (mClientInterface == null || 4070 !mDeathRecipient.linkToDeath(mClientInterface.asBinder())) { 4071 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 4072 cleanup(); 4073 break; 4074 } 4075 4076 try { 4077 // A runtime crash can leave the interface up and 4078 // IP addresses configured, and this affects 4079 // connectivity when supplicant starts up. 4080 // Ensure interface is down and we have no IP 4081 // addresses before a supplicant start. 4082 mNwService.setInterfaceDown(mInterfaceName); 4083 mNwService.clearInterfaceAddresses(mInterfaceName); 4084 4085 // Set privacy extensions 4086 mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true); 4087 4088 // IPv6 is enabled only as long as access point is connected since: 4089 // - IPv6 addresses and routes stick around after disconnection 4090 // - kernel is unaware when connected and fails to start IPv6 negotiation 4091 // - kernel can start autoconfiguration when 802.1x is not complete 4092 mNwService.disableIpv6(mInterfaceName); 4093 } catch (RemoteException re) { 4094 loge("Unable to change interface settings: " + re); 4095 } catch (IllegalStateException ie) { 4096 loge("Unable to change interface settings: " + ie); 4097 } 4098 4099 if (!mWifiNative.startHal()) { 4100 // starting HAL is optional 4101 Log.e(TAG, "Failed to start HAL for client mode"); 4102 } 4103 4104 try { 4105 if (!mClientInterface.enableSupplicant()) { 4106 loge("Failed to start supplicant!"); 4107 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 4108 cleanup(); 4109 break; 4110 } 4111 } catch (RemoteException e) { 4112 cleanup(); 4113 break; 4114 } 4115 setSupplicantLogLevel(); 4116 setWifiState(WIFI_STATE_ENABLING); 4117 if (mVerboseLoggingEnabled) log("Supplicant start successful"); 4118 mWifiMonitor.startMonitoring(mInterfaceName); 4119 transitionTo(mSupplicantStartingState); 4120 break; 4121 case CMD_START_AP: 4122 // Refresh our reference to wificond. This allows us to tolerate restarts. 4123 mWificond = mWifiInjector.makeWificond(); 4124 transitionTo(mSoftApState); 4125 break; 4126 case CMD_SET_OPERATIONAL_MODE: 4127 mOperationalMode = message.arg1; 4128 if (mOperationalMode != DISABLED_MODE) { 4129 sendMessage(CMD_START_SUPPLICANT); 4130 } 4131 break; 4132 default: 4133 return NOT_HANDLED; 4134 } 4135 return HANDLED; 4136 } 4137 } 4138 4139 class SupplicantStartingState extends State { 4140 private void initializeWpsDetails() { 4141 String detail; 4142 detail = mPropertyService.get("ro.product.name", ""); 4143 if (!mWifiNative.setDeviceName(detail)) { 4144 loge("Failed to set device name " + detail); 4145 } 4146 detail = mPropertyService.get("ro.product.manufacturer", ""); 4147 if (!mWifiNative.setManufacturer(detail)) { 4148 loge("Failed to set manufacturer " + detail); 4149 } 4150 detail = mPropertyService.get("ro.product.model", ""); 4151 if (!mWifiNative.setModelName(detail)) { 4152 loge("Failed to set model name " + detail); 4153 } 4154 detail = mPropertyService.get("ro.product.model", ""); 4155 if (!mWifiNative.setModelNumber(detail)) { 4156 loge("Failed to set model number " + detail); 4157 } 4158 detail = mPropertyService.get("ro.serialno", ""); 4159 if (!mWifiNative.setSerialNumber(detail)) { 4160 loge("Failed to set serial number " + detail); 4161 } 4162 if (!mWifiNative.setConfigMethods("physical_display virtual_push_button")) { 4163 loge("Failed to set WPS config methods"); 4164 } 4165 if (!mWifiNative.setDeviceType(mPrimaryDeviceType)) { 4166 loge("Failed to set primary device type " + mPrimaryDeviceType); 4167 } 4168 } 4169 4170 @Override 4171 public boolean processMessage(Message message) { 4172 logStateAndMessage(message, this); 4173 4174 switch(message.what) { 4175 case WifiMonitor.SUP_CONNECTION_EVENT: 4176 if (mVerboseLoggingEnabled) log("Supplicant connection established"); 4177 setWifiState(WIFI_STATE_ENABLED); 4178 mSupplicantRestartCount = 0; 4179 /* Reset the supplicant state to indicate the supplicant 4180 * state is not known at this time */ 4181 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4182 /* Initialize data structures */ 4183 mLastBssid = null; 4184 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 4185 mLastSignalLevel = -1; 4186 4187 mWifiInfo.setMacAddress(mWifiNative.getMacAddress()); 4188 /* set frequency band of operation */ 4189 setFrequencyBand(); 4190 mWifiNative.enableSaveConfig(); 4191 mWifiConfigManager.loadAndEnableAllNetworks(); 4192 initializeWpsDetails(); 4193 4194 sendSupplicantConnectionChangedBroadcast(true); 4195 transitionTo(mSupplicantStartedState); 4196 break; 4197 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4198 if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { 4199 loge("Failed to setup control channel, restart supplicant"); 4200 mWifiMonitor.stopAllMonitoring(); 4201 try { 4202 mClientInterface.disableSupplicant(); 4203 } catch (RemoteException e) { 4204 // The client interface is dead, there is nothing more we can do. 4205 } 4206 transitionTo(mInitialState); 4207 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 4208 } else { 4209 loge("Failed " + mSupplicantRestartCount + 4210 " times to start supplicant, unload driver"); 4211 mSupplicantRestartCount = 0; 4212 setWifiState(WIFI_STATE_UNKNOWN); 4213 transitionTo(mInitialState); 4214 } 4215 break; 4216 case CMD_START_SUPPLICANT: 4217 case CMD_STOP_SUPPLICANT: 4218 case CMD_START_AP: 4219 case CMD_STOP_AP: 4220 case CMD_SET_OPERATIONAL_MODE: 4221 case CMD_SET_FREQUENCY_BAND: 4222 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 4223 deferMessage(message); 4224 break; 4225 default: 4226 return NOT_HANDLED; 4227 } 4228 return HANDLED; 4229 } 4230 } 4231 4232 class SupplicantStartedState extends State { 4233 @Override 4234 public void enter() { 4235 if (mVerboseLoggingEnabled) { 4236 logd("SupplicantStartedState enter"); 4237 } 4238 4239 /* Wifi is available as long as we have a connection to supplicant */ 4240 mNetworkInfo.setIsAvailable(true); 4241 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4242 4243 int defaultInterval = mContext.getResources().getInteger( 4244 R.integer.config_wifi_supplicant_scan_interval); 4245 4246 mSupplicantScanIntervalMs = mFacade.getLongSetting(mContext, 4247 Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS, 4248 defaultInterval); 4249 4250 mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000); 4251 mWifiNative.setExternalSim(true); 4252 4253 /* turn on use of DFS channels */ 4254 mWifiNative.setDfsFlag(true); 4255 4256 setRandomMacOui(); 4257 mWifiNative.enableAutoConnect(false); 4258 mCountryCode.setReadyForChange(true); 4259 4260 // We can't do this in the constructor because WifiStateMachine is created before the 4261 // wifi scanning service is initialized 4262 if (mWifiScanner == null) { 4263 mWifiScanner = mFacade.makeWifiScanner(mContext, getHandler().getLooper()); 4264 4265 mWifiConnectivityManager = new WifiConnectivityManager(mContext, 4266 WifiStateMachine.this, mWifiScanner, mWifiConfigManager, mWifiInfo, 4267 mWifiQualifiedNetworkSelector, mWifiInjector, 4268 getHandler().getLooper()); 4269 } 4270 4271 mWifiDiagnostics.startLogging(mVerboseLoggingEnabled); 4272 mIsRunning = true; 4273 updateBatteryWorkSource(null); 4274 /** 4275 * Enable bluetooth coexistence scan mode when bluetooth connection is active. 4276 * When this mode is on, some of the low-level scan parameters used by the 4277 * driver are changed to reduce interference with bluetooth 4278 */ 4279 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 4280 /* initialize network state */ 4281 setNetworkDetailedState(DetailedState.DISCONNECTED); 4282 4283 // Disable legacy multicast filtering, which on some chipsets defaults to enabled. 4284 // Legacy IPv6 multicast filtering blocks ICMPv6 router advertisements which breaks IPv6 4285 // provisioning. Legacy IPv4 multicast filtering may be re-enabled later via 4286 // IpManager.Callback.setFallbackMulticastFilter() 4287 mWifiNative.stopFilteringMulticastV4Packets(); 4288 mWifiNative.stopFilteringMulticastV6Packets(); 4289 4290 if (mOperationalMode == SCAN_ONLY_MODE || 4291 mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 4292 mWifiNative.disconnect(); 4293 mWifiConfigManager.disableAllNetworksNative(); 4294 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 4295 setWifiState(WIFI_STATE_DISABLED); 4296 } 4297 transitionTo(mScanModeState); 4298 } else if (mOperationalMode == CONNECT_MODE){ 4299 4300 // Status pulls in the current supplicant state and network connection state 4301 // events over the monitor connection. This helps framework sync up with 4302 // current supplicant state 4303 // TODO: actually check the supplicant status string and make sure the supplicant 4304 // is in disconnecte4d state. 4305 mWifiNative.status(); 4306 // Transitioning to Disconnected state will trigger a scan and subsequently AutoJoin 4307 transitionTo(mDisconnectedState); 4308 } else if (mOperationalMode == DISABLED_MODE) { 4309 transitionTo(mSupplicantStoppingState); 4310 } 4311 4312 // We may have missed screen update at boot 4313 if (mScreenBroadcastReceived.get() == false) { 4314 PowerManager powerManager = (PowerManager)mContext.getSystemService( 4315 Context.POWER_SERVICE); 4316 handleScreenStateChanged(powerManager.isInteractive()); 4317 } else { 4318 // Set the right suspend mode settings 4319 mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0 4320 && mUserWantsSuspendOpt.get()); 4321 4322 // Inform WifiConnectivtyManager the screen state in case 4323 // WifiConnectivityManager missed the last screen update because 4324 // it was not started yet. 4325 mWifiConnectivityManager.handleScreenStateChanged(mScreenOn); 4326 } 4327 mWifiNative.setPowerSave(true); 4328 4329 if (mP2pSupported) { 4330 if (mOperationalMode == CONNECT_MODE) { 4331 p2pSendMessage(WifiStateMachine.CMD_ENABLE_P2P); 4332 } else { 4333 // P2P state machine starts in disabled state, and is not enabled until 4334 // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to 4335 // keep it disabled. 4336 } 4337 } 4338 4339 if (mNanSupported && mWifiNanManager != null) { 4340 if (mOperationalMode == CONNECT_MODE) { 4341 mWifiNanManager.enableUsage(); 4342 } else { 4343 /* 4344 * NAN state machine starts in disabled state. Nothing 4345 * needed to keep it disabled. 4346 */ 4347 } 4348 } 4349 4350 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 4351 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4352 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED); 4353 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4354 4355 // Enable link layer stats gathering 4356 mWifiNative.setWifiLinkLayerStats("wlan0", 1); 4357 } 4358 4359 @Override 4360 public boolean processMessage(Message message) { 4361 logStateAndMessage(message, this); 4362 4363 switch(message.what) { 4364 case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */ 4365 if (mP2pSupported) { 4366 transitionTo(mWaitForP2pDisableState); 4367 } else { 4368 transitionTo(mSupplicantStoppingState); 4369 } 4370 break; 4371 case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ 4372 loge("Connection lost, restart supplicant"); 4373 handleSupplicantConnectionLoss(true); 4374 handleNetworkDisconnect(); 4375 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4376 if (mP2pSupported) { 4377 transitionTo(mWaitForP2pDisableState); 4378 } else { 4379 transitionTo(mInitialState); 4380 } 4381 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 4382 break; 4383 case CMD_START_SCAN: 4384 handleScanRequest(message); 4385 break; 4386 case WifiMonitor.SCAN_RESULTS_EVENT: 4387 case WifiMonitor.SCAN_FAILED_EVENT: 4388 maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered 4389 setScanResults(); 4390 if (mIsFullScanOngoing || mSendScanResultsBroadcast) { 4391 /* Just updated results from full scan, let apps know about this */ 4392 boolean scanSucceeded = message.what == WifiMonitor.SCAN_RESULTS_EVENT; 4393 sendScanResultsAvailableBroadcast(scanSucceeded); 4394 } 4395 mSendScanResultsBroadcast = false; 4396 mIsScanOngoing = false; 4397 mIsFullScanOngoing = false; 4398 if (mBufferedScanMsg.size() > 0) 4399 sendMessage(mBufferedScanMsg.remove()); 4400 break; 4401 case CMD_PING_SUPPLICANT: 4402 boolean ok = mWifiNative.ping(); 4403 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 4404 break; 4405 case CMD_SET_FREQUENCY_BAND: 4406 int band = message.arg1; 4407 if (mVerboseLoggingEnabled) log("set frequency band " + band); 4408 if (mWifiNative.setBand(band)) { 4409 4410 if (mVerboseLoggingEnabled) logd("did set frequency band " + band); 4411 4412 mFrequencyBand.set(band); 4413 // Flush old data - like scan results 4414 mWifiNative.bssFlush(); 4415 4416 if (mVerboseLoggingEnabled) logd("done set frequency band " + band); 4417 4418 } else { 4419 loge("Failed to set frequency band " + band); 4420 } 4421 break; 4422 case CMD_GET_CAPABILITY_FREQ: 4423 String freqs = mWifiNative.getFreqCapability(); 4424 replyToMessage(message, message.what, freqs); 4425 break; 4426 case CMD_START_AP: 4427 /* Cannot start soft AP while in client mode */ 4428 loge("Failed to start soft AP with a running supplicant"); 4429 setWifiApState(WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL); 4430 break; 4431 case CMD_SET_OPERATIONAL_MODE: 4432 mOperationalMode = message.arg1; 4433 mWifiConfigManager. 4434 setAndEnableLastSelectedConfiguration( 4435 WifiConfiguration.INVALID_NETWORK_ID); 4436 if (mOperationalMode == DISABLED_MODE) { 4437 transitionTo(mSupplicantStoppingState); 4438 } 4439 break; 4440 case CMD_TARGET_BSSID: 4441 // Trying to associate to this BSSID 4442 if (message.obj != null) { 4443 mTargetRoamBSSID = (String) message.obj; 4444 } 4445 break; 4446 case CMD_GET_LINK_LAYER_STATS: 4447 WifiLinkLayerStats stats = getWifiLinkLayerStats(); 4448 replyToMessage(message, message.what, stats); 4449 break; 4450 case CMD_RESET_SIM_NETWORKS: 4451 log("resetting EAP-SIM/AKA/AKA' networks since SIM was changed"); 4452 mWifiConfigManager.resetSimNetworks(); 4453 break; 4454 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 4455 mBluetoothConnectionActive = (message.arg1 != 4456 BluetoothAdapter.STATE_DISCONNECTED); 4457 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 4458 break; 4459 case CMD_SET_SUSPEND_OPT_ENABLED: 4460 if (message.arg1 == 1) { 4461 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); 4462 if (message.arg2 == 1) { 4463 mSuspendWakeLock.release(); 4464 } 4465 } else { 4466 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); 4467 } 4468 break; 4469 case CMD_SET_HIGH_PERF_MODE: 4470 if (message.arg1 == 1) { 4471 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); 4472 } else { 4473 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); 4474 } 4475 break; 4476 case CMD_ENABLE_TDLS: 4477 if (message.obj != null) { 4478 String remoteAddress = (String) message.obj; 4479 boolean enable = (message.arg1 == 1); 4480 mWifiNative.startTdls(remoteAddress, enable); 4481 } 4482 break; 4483 case WifiMonitor.ANQP_DONE_EVENT: 4484 mWifiConfigManager.notifyANQPDone((Long) message.obj, message.arg1 != 0); 4485 break; 4486 case CMD_STOP_IP_PACKET_OFFLOAD: { 4487 int slot = message.arg1; 4488 int ret = stopWifiIPPacketOffload(slot); 4489 if (mNetworkAgent != null) { 4490 mNetworkAgent.onPacketKeepaliveEvent(slot, ret); 4491 } 4492 break; 4493 } 4494 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 4495 mWifiConfigManager.notifyIconReceived((IconEvent) message.obj); 4496 break; 4497 case WifiMonitor.HS20_REMEDIATION_EVENT: 4498 wnmFrameReceived((WnmData) message.obj); 4499 break; 4500 case CMD_CONFIG_ND_OFFLOAD: 4501 final boolean enabled = (message.arg1 > 0); 4502 mWifiNative.configureNeighborDiscoveryOffload(enabled); 4503 break; 4504 case CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER: 4505 if (mWifiConnectivityManager != null) { 4506 mWifiConnectivityManager.enable(message.arg1 == 1 ? true : false); 4507 } 4508 break; 4509 case CMD_ENABLE_AUTOJOIN_WHEN_ASSOCIATED: 4510 final boolean allowed = (message.arg1 > 0); 4511 boolean old_state = mWifiConfigManager.getEnableAutoJoinWhenAssociated(); 4512 mWifiConfigManager.setEnableAutoJoinWhenAssociated(allowed); 4513 if (!old_state && allowed && mScreenOn 4514 && getCurrentState() == mConnectedState) { 4515 if (mWifiConnectivityManager != null) { 4516 mWifiConnectivityManager.forceConnectivityScan(); 4517 } 4518 } 4519 break; 4520 default: 4521 return NOT_HANDLED; 4522 } 4523 return HANDLED; 4524 } 4525 4526 @Override 4527 public void exit() { 4528 mWifiDiagnostics.stopLogging(); 4529 4530 mIsRunning = false; 4531 updateBatteryWorkSource(null); 4532 mScanResults = new ArrayList<>(); 4533 4534 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 4535 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4536 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); 4537 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4538 mBufferedScanMsg.clear(); 4539 4540 if (mNanSupported && mWifiNanManager != null) { 4541 mWifiNanManager.disableUsage(); 4542 } 4543 4544 mNetworkInfo.setIsAvailable(false); 4545 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4546 mCountryCode.setReadyForChange(false); 4547 } 4548 } 4549 4550 class SupplicantStoppingState extends State { 4551 @Override 4552 public void enter() { 4553 /* Send any reset commands to supplicant before shutting it down */ 4554 handleNetworkDisconnect(); 4555 4556 String suppState = System.getProperty("init.svc.wpa_supplicant"); 4557 if (suppState == null) suppState = "unknown"; 4558 4559 logd("SupplicantStoppingState: stopSupplicant " 4560 + " init.svc.wpa_supplicant=" + suppState); 4561 mWifiMonitor.stopSupplicant(); 4562 4563 /* Send ourselves a delayed message to indicate failure after a wait time */ 4564 sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED, 4565 ++mSupplicantStopFailureToken, 0), SUPPLICANT_RESTART_INTERVAL_MSECS); 4566 setWifiState(WIFI_STATE_DISABLING); 4567 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4568 } 4569 @Override 4570 public boolean processMessage(Message message) { 4571 logStateAndMessage(message, this); 4572 4573 switch(message.what) { 4574 case WifiMonitor.SUP_CONNECTION_EVENT: 4575 loge("Supplicant connection received while stopping"); 4576 break; 4577 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4578 if (mVerboseLoggingEnabled) log("Supplicant connection lost"); 4579 handleSupplicantConnectionLoss(false); 4580 transitionTo(mInitialState); 4581 break; 4582 case CMD_STOP_SUPPLICANT_FAILED: 4583 if (message.arg1 == mSupplicantStopFailureToken) { 4584 loge("Timed out on a supplicant stop, kill and proceed"); 4585 handleSupplicantConnectionLoss(true); 4586 transitionTo(mInitialState); 4587 } 4588 break; 4589 case CMD_START_SUPPLICANT: 4590 case CMD_STOP_SUPPLICANT: 4591 case CMD_START_AP: 4592 case CMD_STOP_AP: 4593 case CMD_SET_OPERATIONAL_MODE: 4594 case CMD_SET_FREQUENCY_BAND: 4595 deferMessage(message); 4596 break; 4597 default: 4598 return NOT_HANDLED; 4599 } 4600 return HANDLED; 4601 } 4602 } 4603 4604 class WaitForP2pDisableState extends State { 4605 private State mTransitionToState; 4606 @Override 4607 public void enter() { 4608 switch (getCurrentMessage().what) { 4609 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4610 mTransitionToState = mInitialState; 4611 break; 4612 case CMD_STOP_SUPPLICANT: 4613 default: 4614 mTransitionToState = mSupplicantStoppingState; 4615 break; 4616 } 4617 p2pSendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ); 4618 } 4619 @Override 4620 public boolean processMessage(Message message) { 4621 logStateAndMessage(message, this); 4622 4623 switch(message.what) { 4624 case WifiStateMachine.CMD_DISABLE_P2P_RSP: 4625 transitionTo(mTransitionToState); 4626 break; 4627 /* Defer wifi start/shut and driver commands */ 4628 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4629 case CMD_START_SUPPLICANT: 4630 case CMD_STOP_SUPPLICANT: 4631 case CMD_START_AP: 4632 case CMD_STOP_AP: 4633 case CMD_SET_OPERATIONAL_MODE: 4634 case CMD_SET_FREQUENCY_BAND: 4635 case CMD_START_SCAN: 4636 case CMD_DISCONNECT: 4637 case CMD_REASSOCIATE: 4638 case CMD_RECONNECT: 4639 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 4640 deferMessage(message); 4641 break; 4642 default: 4643 return NOT_HANDLED; 4644 } 4645 return HANDLED; 4646 } 4647 } 4648 4649 class ScanModeState extends State { 4650 private int mLastOperationMode; 4651 @Override 4652 public void enter() { 4653 mLastOperationMode = mOperationalMode; 4654 } 4655 @Override 4656 public boolean processMessage(Message message) { 4657 logStateAndMessage(message, this); 4658 4659 switch(message.what) { 4660 case CMD_SET_OPERATIONAL_MODE: 4661 if (message.arg1 == CONNECT_MODE) { 4662 4663 if (mLastOperationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 4664 setWifiState(WIFI_STATE_ENABLED); 4665 // Load and re-enable networks when going back to enabled state 4666 // This is essential for networks to show up after restore 4667 mWifiConfigManager.loadAndEnableAllNetworks(); 4668 p2pSendMessage(CMD_ENABLE_P2P); 4669 } else { 4670 mWifiConfigManager.enableAllNetworks(); 4671 } 4672 4673 // Lose last selection choice since user toggled WiFi 4674 mWifiConfigManager. 4675 setAndEnableLastSelectedConfiguration( 4676 WifiConfiguration.INVALID_NETWORK_ID); 4677 4678 mOperationalMode = CONNECT_MODE; 4679 transitionTo(mDisconnectedState); 4680 } else if (message.arg1 == DISABLED_MODE) { 4681 transitionTo(mSupplicantStoppingState); 4682 } 4683 // Nothing to do 4684 break; 4685 // Handle scan. All the connection related commands are 4686 // handled only in ConnectModeState 4687 case CMD_START_SCAN: 4688 handleScanRequest(message); 4689 break; 4690 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4691 SupplicantState state = handleSupplicantStateChange(message); 4692 if (mVerboseLoggingEnabled) log("SupplicantState= " + state); 4693 break; 4694 default: 4695 return NOT_HANDLED; 4696 } 4697 return HANDLED; 4698 } 4699 } 4700 4701 4702 String smToString(Message message) { 4703 return smToString(message.what); 4704 } 4705 4706 String smToString(int what) { 4707 String s = sSmToString.get(what); 4708 if (s != null) { 4709 return s; 4710 } 4711 switch (what) { 4712 case WifiMonitor.DRIVER_HUNG_EVENT: 4713 s = "DRIVER_HUNG_EVENT"; 4714 break; 4715 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 4716 s = "AsyncChannel.CMD_CHANNEL_HALF_CONNECTED"; 4717 break; 4718 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 4719 s = "AsyncChannel.CMD_CHANNEL_DISCONNECTED"; 4720 break; 4721 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 4722 s = "WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST"; 4723 break; 4724 case WifiManager.DISABLE_NETWORK: 4725 s = "WifiManager.DISABLE_NETWORK"; 4726 break; 4727 case WifiManager.CONNECT_NETWORK: 4728 s = "CONNECT_NETWORK"; 4729 break; 4730 case WifiManager.SAVE_NETWORK: 4731 s = "SAVE_NETWORK"; 4732 break; 4733 case WifiManager.FORGET_NETWORK: 4734 s = "FORGET_NETWORK"; 4735 break; 4736 case WifiMonitor.SUP_CONNECTION_EVENT: 4737 s = "SUP_CONNECTION_EVENT"; 4738 break; 4739 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4740 s = "SUP_DISCONNECTION_EVENT"; 4741 break; 4742 case WifiMonitor.SCAN_RESULTS_EVENT: 4743 s = "SCAN_RESULTS_EVENT"; 4744 break; 4745 case WifiMonitor.SCAN_FAILED_EVENT: 4746 s = "SCAN_FAILED_EVENT"; 4747 break; 4748 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4749 s = "SUPPLICANT_STATE_CHANGE_EVENT"; 4750 break; 4751 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 4752 s = "AUTHENTICATION_FAILURE_EVENT"; 4753 break; 4754 case WifiMonitor.SSID_TEMP_DISABLED: 4755 s = "SSID_TEMP_DISABLED"; 4756 break; 4757 case WifiMonitor.SSID_REENABLED: 4758 s = "SSID_REENABLED"; 4759 break; 4760 case WifiMonitor.WPS_SUCCESS_EVENT: 4761 s = "WPS_SUCCESS_EVENT"; 4762 break; 4763 case WifiMonitor.WPS_FAIL_EVENT: 4764 s = "WPS_FAIL_EVENT"; 4765 break; 4766 case WifiMonitor.SUP_REQUEST_IDENTITY: 4767 s = "SUP_REQUEST_IDENTITY"; 4768 break; 4769 case WifiMonitor.NETWORK_CONNECTION_EVENT: 4770 s = "NETWORK_CONNECTION_EVENT"; 4771 break; 4772 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 4773 s = "NETWORK_DISCONNECTION_EVENT"; 4774 break; 4775 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 4776 s = "ASSOCIATION_REJECTION_EVENT"; 4777 break; 4778 case WifiMonitor.ANQP_DONE_EVENT: 4779 s = "WifiMonitor.ANQP_DONE_EVENT"; 4780 break; 4781 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 4782 s = "WifiMonitor.RX_HS20_ANQP_ICON_EVENT"; 4783 break; 4784 case WifiMonitor.GAS_QUERY_DONE_EVENT: 4785 s = "WifiMonitor.GAS_QUERY_DONE_EVENT"; 4786 break; 4787 case WifiMonitor.HS20_REMEDIATION_EVENT: 4788 s = "WifiMonitor.HS20_REMEDIATION_EVENT"; 4789 break; 4790 case WifiMonitor.GAS_QUERY_START_EVENT: 4791 s = "WifiMonitor.GAS_QUERY_START_EVENT"; 4792 break; 4793 case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT: 4794 s = "GROUP_CREATING_TIMED_OUT"; 4795 break; 4796 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 4797 s = "P2P_CONNECTION_CHANGED"; 4798 break; 4799 case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE: 4800 s = "P2P.DISCONNECT_WIFI_RESPONSE"; 4801 break; 4802 case WifiP2pServiceImpl.SET_MIRACAST_MODE: 4803 s = "P2P.SET_MIRACAST_MODE"; 4804 break; 4805 case WifiP2pServiceImpl.BLOCK_DISCOVERY: 4806 s = "P2P.BLOCK_DISCOVERY"; 4807 break; 4808 case WifiManager.CANCEL_WPS: 4809 s = "CANCEL_WPS"; 4810 break; 4811 case WifiManager.CANCEL_WPS_FAILED: 4812 s = "CANCEL_WPS_FAILED"; 4813 break; 4814 case WifiManager.CANCEL_WPS_SUCCEDED: 4815 s = "CANCEL_WPS_SUCCEDED"; 4816 break; 4817 case WifiManager.START_WPS: 4818 s = "START_WPS"; 4819 break; 4820 case WifiManager.START_WPS_SUCCEEDED: 4821 s = "START_WPS_SUCCEEDED"; 4822 break; 4823 case WifiManager.WPS_FAILED: 4824 s = "WPS_FAILED"; 4825 break; 4826 case WifiManager.WPS_COMPLETED: 4827 s = "WPS_COMPLETED"; 4828 break; 4829 case WifiManager.RSSI_PKTCNT_FETCH: 4830 s = "RSSI_PKTCNT_FETCH"; 4831 break; 4832 default: 4833 s = "what:" + Integer.toString(what); 4834 break; 4835 } 4836 return s; 4837 } 4838 4839 void registerConnected() { 4840 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 4841 WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 4842 if (config != null) { 4843 //Here we will clear all disable counters once a network is connected 4844 //records how long this network is connected in future 4845 config.lastConnected = mClock.getWallClockMillis(); 4846 config.numAssociation++; 4847 WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = 4848 config.getNetworkSelectionStatus(); 4849 networkSelectionStatus.clearDisableReasonCounter(); 4850 networkSelectionStatus.setHasEverConnected(true); 4851 } 4852 // On connect, reset wifiScoreReport 4853 mWifiScoreReport = null; 4854 } 4855 } 4856 4857 void registerDisconnected() { 4858 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 4859 // We are switching away from this configuration, 4860 // hence record the time we were connected last 4861 WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 4862 if (config != null) { 4863 config.lastDisconnected = mClock.getWallClockMillis(); 4864 if (config.ephemeral) { 4865 // Remove ephemeral WifiConfigurations from file 4866 mWifiConfigManager.forgetNetwork(mLastNetworkId); 4867 } 4868 } 4869 } 4870 } 4871 4872 void noteWifiDisabledWhileAssociated() { 4873 // We got disabled by user while we were associated, make note of it 4874 int rssi = mWifiInfo.getRssi(); 4875 WifiConfiguration config = getCurrentWifiConfiguration(); 4876 if (getCurrentState() == mConnectedState 4877 && rssi != WifiInfo.INVALID_RSSI 4878 && config != null) { 4879 boolean is24GHz = mWifiInfo.is24GHz(); 4880 boolean isBadRSSI = (is24GHz && rssi < mWifiConfigManager.mThresholdMinimumRssi24.get()) 4881 || (!is24GHz && rssi < mWifiConfigManager.mThresholdMinimumRssi5.get()); 4882 boolean isLowRSSI = 4883 (is24GHz && rssi < mWifiConfigManager.mThresholdQualifiedRssi24.get()) 4884 || (!is24GHz && mWifiInfo.getRssi() < 4885 mWifiConfigManager.mThresholdQualifiedRssi5.get()); 4886 boolean isHighRSSI = (is24GHz && rssi 4887 >= mWifiConfigManager.mThresholdSaturatedRssi24.get()) 4888 || (!is24GHz && mWifiInfo.getRssi() 4889 >= mWifiConfigManager.mThresholdSaturatedRssi5.get()); 4890 if (isBadRSSI) { 4891 // Take note that we got disabled while RSSI was Bad 4892 config.numUserTriggeredWifiDisableLowRSSI++; 4893 } else if (isLowRSSI) { 4894 // Take note that we got disabled while RSSI was Low 4895 config.numUserTriggeredWifiDisableBadRSSI++; 4896 } else if (!isHighRSSI) { 4897 // Take note that we got disabled while RSSI was Not high 4898 config.numUserTriggeredWifiDisableNotHighRSSI++; 4899 } 4900 } 4901 } 4902 4903 /** 4904 * Returns Wificonfiguration object correponding to the currently connected network, null if 4905 * not connected. 4906 */ 4907 public WifiConfiguration getCurrentWifiConfiguration() { 4908 if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 4909 return null; 4910 } 4911 return mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 4912 } 4913 4914 ScanResult getCurrentScanResult() { 4915 WifiConfiguration config = getCurrentWifiConfiguration(); 4916 if (config == null) { 4917 return null; 4918 } 4919 String BSSID = mWifiInfo.getBSSID(); 4920 if (BSSID == null) { 4921 BSSID = mTargetRoamBSSID; 4922 } 4923 ScanDetailCache scanDetailCache = 4924 mWifiConfigManager.getScanDetailCache(config); 4925 4926 if (scanDetailCache == null) { 4927 return null; 4928 } 4929 4930 return scanDetailCache.get(BSSID); 4931 } 4932 4933 String getCurrentBSSID() { 4934 if (isLinkDebouncing()) { 4935 return null; 4936 } 4937 return mLastBssid; 4938 } 4939 4940 class ConnectModeState extends State { 4941 4942 @Override 4943 public void enter() { 4944 // Inform WifiConnectivityManager that Wifi is enabled 4945 if (mWifiConnectivityManager != null) { 4946 mWifiConnectivityManager.setWifiEnabled(true); 4947 } 4948 // Inform metrics that Wifi is Enabled (but not yet connected) 4949 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 4950 } 4951 4952 @Override 4953 public void exit() { 4954 // Inform WifiConnectivityManager that Wifi is disabled 4955 if (mWifiConnectivityManager != null) { 4956 mWifiConnectivityManager.setWifiEnabled(false); 4957 } 4958 // Inform metrics that Wifi is being disabled (Toggled, airplane enabled, etc) 4959 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISABLED); 4960 } 4961 4962 @Override 4963 public boolean processMessage(Message message) { 4964 WifiConfiguration config; 4965 int netId; 4966 boolean ok; 4967 boolean didDisconnect; 4968 String bssid; 4969 String ssid; 4970 NetworkUpdateResult result; 4971 logStateAndMessage(message, this); 4972 4973 switch (message.what) { 4974 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 4975 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_ASSOC_FAILURE); 4976 didBlackListBSSID = false; 4977 bssid = (String) message.obj; 4978 if (bssid == null || TextUtils.isEmpty(bssid)) { 4979 // If BSSID is null, use the target roam BSSID 4980 bssid = mTargetRoamBSSID; 4981 } 4982 if (bssid != null) { 4983 // If we have a BSSID, tell configStore to black list it 4984 if (mWifiConnectivityManager != null) { 4985 didBlackListBSSID = mWifiConnectivityManager.trackBssid(bssid, 4986 false); 4987 } 4988 } 4989 4990 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 4991 WifiConfiguration.NetworkSelectionStatus 4992 .DISABLED_ASSOCIATION_REJECTION); 4993 4994 mSupplicantStateTracker.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT); 4995 //If rejection occurred while Metrics is tracking a ConnnectionEvent, end it. 4996 reportConnectionAttemptEnd( 4997 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, 4998 WifiMetricsProto.ConnectionEvent.HLF_NONE); 4999 mWifiInjector.getWifiLastResortWatchdog() 5000 .noteConnectionFailureAndTriggerIfNeeded( 5001 getTargetSsid(), bssid, 5002 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 5003 break; 5004 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 5005 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_AUTH_FAILURE); 5006 mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); 5007 if (mTargetNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 5008 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 5009 WifiConfiguration.NetworkSelectionStatus 5010 .DISABLED_AUTHENTICATION_FAILURE); 5011 } 5012 //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. 5013 reportConnectionAttemptEnd( 5014 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, 5015 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5016 mWifiInjector.getWifiLastResortWatchdog() 5017 .noteConnectionFailureAndTriggerIfNeeded( 5018 getTargetSsid(), mTargetRoamBSSID, 5019 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 5020 break; 5021 case WifiMonitor.SSID_TEMP_DISABLED: 5022 Log.e(TAG, "Supplicant SSID temporary disabled:" 5023 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 5024 mWifiConfigManager.updateNetworkSelectionStatus( 5025 message.arg1, 5026 WifiConfiguration.NetworkSelectionStatus 5027 .DISABLED_AUTHENTICATION_FAILURE); 5028 reportConnectionAttemptEnd( 5029 WifiMetrics.ConnectionEvent.FAILURE_SSID_TEMP_DISABLED, 5030 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5031 mWifiInjector.getWifiLastResortWatchdog() 5032 .noteConnectionFailureAndTriggerIfNeeded( 5033 getTargetSsid(), mTargetRoamBSSID, 5034 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 5035 break; 5036 case WifiMonitor.SSID_REENABLED: 5037 Log.d(TAG, "Supplicant SSID reenable:" 5038 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 5039 // Do not re-enable it in Quality Network Selection since framework has its own 5040 // Algorithm of disable/enable 5041 break; 5042 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5043 SupplicantState state = handleSupplicantStateChange(message); 5044 // A driver/firmware hang can now put the interface in a down state. 5045 // We detect the interface going down and recover from it 5046 if (!SupplicantState.isDriverActive(state)) { 5047 if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 5048 handleNetworkDisconnect(); 5049 } 5050 log("Detected an interface down, restart driver"); 5051 // Rely on the fact that this will force us into killing supplicant and then 5052 // restart supplicant from a clean state. 5053 transitionTo(mSupplicantStoppingState); 5054 sendMessage(CMD_START_SUPPLICANT); 5055 break; 5056 } 5057 5058 // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT 5059 // when authentication times out after a successful connection, 5060 // we can figure this from the supplicant state. If supplicant 5061 // state is DISCONNECTED, but the mNetworkInfo says we are not 5062 // disconnected, we need to handle a disconnection 5063 if (!isLinkDebouncing() && state == SupplicantState.DISCONNECTED && 5064 mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 5065 if (mVerboseLoggingEnabled) { 5066 log("Missed CTRL-EVENT-DISCONNECTED, disconnect"); 5067 } 5068 handleNetworkDisconnect(); 5069 transitionTo(mDisconnectedState); 5070 } 5071 5072 // If we have COMPLETED a connection to a BSSID, start doing 5073 // DNAv4/DNAv6 -style probing for on-link neighbors of 5074 // interest (e.g. routers); harmless if none are configured. 5075 if (state == SupplicantState.COMPLETED) { 5076 mIpManager.confirmConfiguration(); 5077 } 5078 break; 5079 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 5080 if (message.arg1 == 1) { 5081 mWifiNative.disconnect(); 5082 mTemporarilyDisconnectWifi = true; 5083 } else { 5084 mWifiNative.reconnect(); 5085 mTemporarilyDisconnectWifi = false; 5086 } 5087 break; 5088 case CMD_ADD_OR_UPDATE_NETWORK: 5089 // Only the current foreground user can modify networks. 5090 if (!mWifiConfigManager.isCurrentUserProfile( 5091 UserHandle.getUserId(message.sendingUid))) { 5092 loge("Only the current foreground user can modify networks " 5093 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5094 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5095 replyToMessage(message, message.what, FAILURE); 5096 break; 5097 } 5098 5099 config = (WifiConfiguration) message.obj; 5100 5101 if (!recordUidIfAuthorized(config, message.sendingUid, 5102 /* onlyAnnotate */ false)) { 5103 logw("Not authorized to update network " 5104 + " config=" + config.SSID 5105 + " cnid=" + config.networkId 5106 + " uid=" + message.sendingUid); 5107 replyToMessage(message, message.what, FAILURE); 5108 break; 5109 } 5110 5111 int res = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 5112 if (res < 0) { 5113 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5114 } else { 5115 WifiConfiguration curConfig = getCurrentWifiConfiguration(); 5116 if (curConfig != null && config != null) { 5117 WifiConfiguration.NetworkSelectionStatus networkStatus = 5118 config.getNetworkSelectionStatus(); 5119 if (curConfig.priority < config.priority && networkStatus != null 5120 && !networkStatus.isNetworkPermanentlyDisabled()) { 5121 // Interpret this as a connect attempt 5122 // Set the last selected configuration so as to allow the system to 5123 // stick the last user choice without persisting the choice 5124 mWifiConfigManager.setAndEnableLastSelectedConfiguration(res); 5125 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 5126 boolean persist = mWifiConfigManager 5127 .checkConfigOverridePermission(message.sendingUid); 5128 if (mWifiConnectivityManager != null) { 5129 mWifiConnectivityManager.connectToUserSelectNetwork(res, 5130 persist); 5131 } 5132 5133 // Remember time of last connection attempt 5134 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 5135 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5136 5137 // As a courtesy to the caller, trigger a scan now 5138 startScan(ADD_OR_UPDATE_SOURCE, 0, null, WIFI_WORK_SOURCE); 5139 } 5140 } 5141 } 5142 replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK, res); 5143 break; 5144 case CMD_REMOVE_NETWORK: 5145 // Only the current foreground user can modify networks. 5146 if (!mWifiConfigManager.isCurrentUserProfile( 5147 UserHandle.getUserId(message.sendingUid))) { 5148 loge("Only the current foreground user can modify networks " 5149 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5150 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5151 replyToMessage(message, message.what, FAILURE); 5152 break; 5153 } 5154 netId = message.arg1; 5155 5156 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 5157 /* onlyAnnotate */ false)) { 5158 logw("Not authorized to remove network " 5159 + " cnid=" + netId 5160 + " uid=" + message.sendingUid); 5161 replyToMessage(message, message.what, FAILURE); 5162 break; 5163 } 5164 5165 ok = mWifiConfigManager.removeNetwork(message.arg1); 5166 if (!ok) { 5167 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5168 } 5169 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 5170 break; 5171 case CMD_ENABLE_NETWORK: 5172 // Only the current foreground user can modify networks. 5173 if (!mWifiConfigManager.isCurrentUserProfile( 5174 UserHandle.getUserId(message.sendingUid))) { 5175 loge("Only the current foreground user can modify networks " 5176 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5177 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5178 replyToMessage(message, message.what, FAILURE); 5179 break; 5180 } 5181 5182 boolean disableOthers = message.arg2 == 1; 5183 netId = message.arg1; 5184 config = mWifiConfigManager.getWifiConfiguration(netId); 5185 if (config == null) { 5186 loge("No network with id = " + netId); 5187 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5188 replyToMessage(message, message.what, FAILURE); 5189 break; 5190 } 5191 // disable other only means select this network, does not mean all other 5192 // networks need to be disabled 5193 if (disableOthers) { 5194 // Remember time of last connection attempt 5195 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 5196 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5197 } 5198 // Cancel auto roam requests 5199 autoRoamSetBSSID(netId, "any"); 5200 5201 ok = mWifiConfigManager.enableNetwork( 5202 config, disableOthers, message.sendingUid); 5203 if (!ok) { 5204 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5205 } else if (disableOthers) { 5206 mTargetNetworkId = netId; 5207 } 5208 5209 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 5210 break; 5211 case CMD_ENABLE_ALL_NETWORKS: 5212 long time = android.os.SystemClock.elapsedRealtime(); 5213 if (time - mLastEnableAllNetworksTime > MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS) { 5214 mWifiConfigManager.enableAllNetworks(); 5215 mLastEnableAllNetworksTime = time; 5216 } 5217 break; 5218 case WifiManager.DISABLE_NETWORK: 5219 if (mWifiConfigManager.updateNetworkSelectionStatus(message.arg1, 5220 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER)) { 5221 replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED); 5222 } else { 5223 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5224 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 5225 WifiManager.ERROR); 5226 } 5227 break; 5228 case CMD_DISABLE_EPHEMERAL_NETWORK: 5229 config = mWifiConfigManager.disableEphemeralNetwork((String)message.obj); 5230 if (config != null) { 5231 if (config.networkId == mLastNetworkId) { 5232 // Disconnect and let autojoin reselect a new network 5233 sendMessage(CMD_DISCONNECT); 5234 } 5235 } 5236 break; 5237 case CMD_BLACKLIST_NETWORK: 5238 mWifiConfigManager.blackListBssid((String) message.obj); 5239 break; 5240 case CMD_CLEAR_BLACKLIST: 5241 mWifiConfigManager.clearBssidBlacklist(); 5242 break; 5243 case CMD_SAVE_CONFIG: 5244 ok = mWifiConfigManager.saveConfig(); 5245 5246 if (mVerboseLoggingEnabled) logd("did save config " + ok); 5247 replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); 5248 5249 // Inform the backup manager about a data change 5250 mBackupManagerProxy.notifyDataChanged(); 5251 break; 5252 case CMD_GET_CONFIGURED_NETWORKS: 5253 replyToMessage(message, message.what, 5254 mWifiConfigManager.getSavedNetworks()); 5255 break; 5256 case WifiMonitor.SUP_REQUEST_IDENTITY: 5257 int networkId = message.arg2; 5258 boolean identitySent = false; 5259 int eapMethod = WifiEnterpriseConfig.Eap.NONE; 5260 5261 if (targetWificonfiguration != null 5262 && targetWificonfiguration.enterpriseConfig != null) { 5263 eapMethod = targetWificonfiguration.enterpriseConfig.getEapMethod(); 5264 } 5265 5266 // For SIM & AKA/AKA' EAP method Only, get identity from ICC 5267 if (targetWificonfiguration != null 5268 && targetWificonfiguration.networkId == networkId 5269 && (targetWificonfiguration.allowedKeyManagement 5270 .get(WifiConfiguration.KeyMgmt.WPA_EAP) 5271 || targetWificonfiguration.allowedKeyManagement 5272 .get(WifiConfiguration.KeyMgmt.IEEE8021X)) 5273 && TelephonyUtil.isSimEapMethod(eapMethod)) { 5274 String identity = 5275 TelephonyUtil.getSimIdentity(getTelephonyManager(), eapMethod); 5276 if (identity != null) { 5277 mWifiNative.simIdentityResponse(networkId, identity); 5278 identitySent = true; 5279 } 5280 } 5281 if (!identitySent) { 5282 // Supplicant lacks credentials to connect to that network, hence black list 5283 ssid = (String) message.obj; 5284 if (targetWificonfiguration != null && ssid != null 5285 && targetWificonfiguration.SSID != null 5286 && targetWificonfiguration.SSID.equals("\"" + ssid + "\"")) { 5287 mWifiConfigManager.updateNetworkSelectionStatus(targetWificonfiguration, 5288 WifiConfiguration.NetworkSelectionStatus 5289 .DISABLED_AUTHENTICATION_NO_CREDENTIALS); 5290 } 5291 // Disconnect now, as we don't have any way to fullfill 5292 // the supplicant request. 5293 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 5294 WifiConfiguration.INVALID_NETWORK_ID); 5295 mWifiNative.disconnect(); 5296 } 5297 break; 5298 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 5299 logd("Received SUP_REQUEST_SIM_AUTH"); 5300 SimAuthRequestData requestData = (SimAuthRequestData) message.obj; 5301 if (requestData != null) { 5302 if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) { 5303 handleGsmAuthRequest(requestData); 5304 } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA 5305 || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) { 5306 handle3GAuthRequest(requestData); 5307 } 5308 } else { 5309 loge("Invalid sim auth request"); 5310 } 5311 break; 5312 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 5313 replyToMessage(message, message.what, 5314 mWifiConfigManager.getPrivilegedSavedNetworks()); 5315 break; 5316 case CMD_GET_MATCHING_CONFIG: 5317 replyToMessage(message, message.what, 5318 mWifiConfigManager.getMatchingConfig((ScanResult)message.obj)); 5319 break; 5320 case CMD_RECONNECT: 5321 if (mWifiConnectivityManager != null) { 5322 mWifiConnectivityManager.forceConnectivityScan(); 5323 } 5324 break; 5325 case CMD_REASSOCIATE: 5326 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 5327 mWifiNative.reassociate(); 5328 break; 5329 case CMD_RELOAD_TLS_AND_RECONNECT: 5330 if (mWifiConfigManager.needsUnlockedKeyStore()) { 5331 logd("Reconnecting to give a chance to un-connected TLS networks"); 5332 mWifiNative.disconnect(); 5333 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 5334 mWifiNative.reconnect(); 5335 } 5336 break; 5337 case CMD_AUTO_ROAM: 5338 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5339 return HANDLED; 5340 case CMD_AUTO_CONNECT: 5341 /* Work Around: wpa_supplicant can get in a bad state where it returns a non 5342 * associated status to the STATUS command but somehow-someplace still thinks 5343 * it is associated and thus will ignore select/reconnect command with 5344 * following message: 5345 * "Already associated with the selected network - do nothing" 5346 * 5347 * Hence, sends a disconnect to supplicant first. 5348 */ 5349 didDisconnect = false; 5350 if (getCurrentState() != mDisconnectedState) { 5351 /** Supplicant will ignore the reconnect if we are currently associated, 5352 * hence trigger a disconnect 5353 */ 5354 didDisconnect = true; 5355 mWifiNative.disconnect(); 5356 } 5357 5358 /* connect command coming from auto-join */ 5359 netId = message.arg1; 5360 mTargetNetworkId = netId; 5361 mTargetRoamBSSID = (String) message.obj; 5362 config = mWifiConfigManager.getWifiConfiguration(netId); 5363 logd("CMD_AUTO_CONNECT sup state " 5364 + mSupplicantStateTracker.getSupplicantStateName() 5365 + " my state " + getCurrentState().getName() 5366 + " nid=" + Integer.toString(netId) 5367 + " roam=" + Boolean.toString(mAutoRoaming)); 5368 if (config == null) { 5369 loge("AUTO_CONNECT and no config, bail out..."); 5370 break; 5371 } 5372 5373 /* Make sure we cancel any previous roam request */ 5374 setTargetBssid(config, mTargetRoamBSSID); 5375 5376 /* Save the network config */ 5377 logd("CMD_AUTO_CONNECT will save config -> " + config.SSID 5378 + " nid=" + Integer.toString(netId)); 5379 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 5380 netId = result.getNetworkId(); 5381 logd("CMD_AUTO_CONNECT did save config -> " 5382 + " nid=" + Integer.toString(netId)); 5383 5384 // Since we updated the config,read it back from config store: 5385 config = mWifiConfigManager.getWifiConfiguration(netId); 5386 if (config == null) { 5387 loge("CMD_AUTO_CONNECT couldn't update the config, got null config"); 5388 break; 5389 } 5390 if (netId != config.networkId) { 5391 loge("CMD_AUTO_CONNECT couldn't update the config, want" 5392 + " nid=" + Integer.toString(netId) + " but got" + config.networkId); 5393 break; 5394 } 5395 5396 if (deferForUserInput(message, netId, false)) { 5397 break; 5398 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 5399 WifiConfiguration.USER_BANNED) { 5400 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5401 WifiManager.NOT_AUTHORIZED); 5402 break; 5403 } 5404 5405 // If we're autojoining a network that the user or an app explicitly selected, 5406 // keep track of the UID that selected it. 5407 // TODO(b/26786318): Keep track of the lastSelectedConfiguration and the 5408 // lastConnectUid on a per-user basis. 5409 int lastConnectUid = WifiConfiguration.UNKNOWN_UID; 5410 5411 //Start a new ConnectionEvent due to auto_connect, assume we are connecting 5412 //between different networks due to QNS, setting ROAM_UNRELATED 5413 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 5414 WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); 5415 if (!didDisconnect) { 5416 //If we were originally disconnected, then this was not any kind of ROAM 5417 mWifiMetrics.setConnectionEventRoamType( 5418 WifiMetricsProto.ConnectionEvent.ROAM_NONE); 5419 } 5420 //Determine if this CONNECTION is for a user selection 5421 if (mWifiConfigManager.isLastSelectedConfiguration(config) 5422 && mWifiConfigManager.isCurrentUserProfile( 5423 UserHandle.getUserId(config.lastConnectUid))) { 5424 lastConnectUid = config.lastConnectUid; 5425 mWifiMetrics.setConnectionEventRoamType( 5426 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED); 5427 } 5428 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 5429 lastConnectUid) && mWifiNative.reconnect()) { 5430 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 5431 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 5432 config = mWifiConfigManager.getWifiConfiguration(netId); 5433 if (config != null 5434 && !mWifiConfigManager.isLastSelectedConfiguration(config)) { 5435 // If we autojoined a different config than the user selected one, 5436 // it means we could not see the last user selection, 5437 // or that the last user selection was faulty and ended up blacklisted 5438 // for some reason (in which case the user is notified with an error 5439 // message in the Wifi picker), and thus we managed to auto-join away 5440 // from the selected config. -> in that case we need to forget 5441 // the selection because we don't want to abruptly switch back to it. 5442 // 5443 // Note that the user selection is also forgotten after a period of time 5444 // during which the device has been disconnected. 5445 // The default value is 30 minutes : see the code path at bottom of 5446 // setScanResults() function. 5447 mWifiConfigManager. 5448 setAndEnableLastSelectedConfiguration( 5449 WifiConfiguration.INVALID_NETWORK_ID); 5450 } 5451 mAutoRoaming = false; 5452 if (isRoaming() || isLinkDebouncing()) { 5453 transitionTo(mRoamingState); 5454 } else if (didDisconnect) { 5455 transitionTo(mDisconnectingState); 5456 } 5457 } else { 5458 loge("Failed to connect config: " + config + " netId: " + netId); 5459 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5460 WifiManager.ERROR); 5461 reportConnectionAttemptEnd( 5462 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 5463 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5464 break; 5465 } 5466 break; 5467 case CMD_REMOVE_APP_CONFIGURATIONS: 5468 mWifiConfigManager.removeNetworksForApp((ApplicationInfo) message.obj); 5469 break; 5470 case CMD_REMOVE_USER_CONFIGURATIONS: 5471 mWifiConfigManager.removeNetworksForUser(message.arg1); 5472 break; 5473 case WifiManager.CONNECT_NETWORK: 5474 // Only the current foreground user and System UI (which runs as user 0 but acts 5475 // on behalf of the current foreground user) can modify networks. 5476 if (!mWifiConfigManager.isCurrentUserProfile( 5477 UserHandle.getUserId(message.sendingUid)) && 5478 message.sendingUid != mSystemUiUid) { 5479 loge("Only the current foreground user can modify networks " 5480 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5481 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5482 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5483 WifiManager.NOT_AUTHORIZED); 5484 break; 5485 } 5486 5487 /** 5488 * The connect message can contain a network id passed as arg1 on message or 5489 * or a config passed as obj on message. 5490 * For a new network, a config is passed to create and connect. 5491 * For an existing network, a network id is passed 5492 */ 5493 netId = message.arg1; 5494 config = (WifiConfiguration) message.obj; 5495 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5496 boolean updatedExisting = false; 5497 5498 /* Save the network config */ 5499 if (config != null) { 5500 // When connecting to an access point, WifiStateMachine wants to update the 5501 // relevant config with administrative data. This update should not be 5502 // considered a 'real' update, therefore lockdown by Device Owner must be 5503 // disregarded. 5504 if (!recordUidIfAuthorized(config, message.sendingUid, 5505 /* onlyAnnotate */ true)) { 5506 logw("Not authorized to update network " 5507 + " config=" + config.SSID 5508 + " cnid=" + config.networkId 5509 + " uid=" + message.sendingUid); 5510 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5511 WifiManager.NOT_AUTHORIZED); 5512 break; 5513 } 5514 String configKey = config.configKey(true /* allowCached */); 5515 WifiConfiguration savedConfig = 5516 mWifiConfigManager.getWifiConfiguration(configKey); 5517 if (savedConfig != null) { 5518 // There is an existing config with this netId, but it wasn't exposed 5519 // (either AUTO_JOIN_DELETED or ephemeral; see WifiConfigManager# 5520 // getConfiguredNetworks). Remove those bits and update the config. 5521 config = savedConfig; 5522 logd("CONNECT_NETWORK updating existing config with id=" + 5523 config.networkId + " configKey=" + configKey); 5524 config.ephemeral = false; 5525 mWifiConfigManager.updateNetworkSelectionStatus(config, 5526 WifiConfiguration.NetworkSelectionStatus 5527 .NETWORK_SELECTION_ENABLE); 5528 updatedExisting = true; 5529 } 5530 5531 result = mWifiConfigManager.saveNetwork(config, message.sendingUid); 5532 netId = result.getNetworkId(); 5533 } 5534 config = mWifiConfigManager.getWifiConfiguration(netId); 5535 if (config == null) { 5536 logd("CONNECT_NETWORK no config for id=" + Integer.toString(netId) + " " 5537 + mSupplicantStateTracker.getSupplicantStateName() + " my state " 5538 + getCurrentState().getName()); 5539 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5540 WifiManager.ERROR); 5541 break; 5542 } 5543 mTargetNetworkId = netId; 5544 autoRoamSetBSSID(netId, "any"); 5545 if (message.sendingUid == Process.WIFI_UID 5546 || message.sendingUid == Process.SYSTEM_UID) { 5547 // As a sanity measure, clear the BSSID in the supplicant network block. 5548 // If system or Wifi Settings want to connect, they will not 5549 // specify the BSSID. 5550 // If an app however had added a BSSID to this configuration, and the BSSID 5551 // was wrong, Then we would forever fail to connect until that BSSID 5552 // is cleaned up. 5553 clearConfigBSSID(config, "CONNECT_NETWORK"); 5554 } 5555 5556 if (deferForUserInput(message, netId, true)) { 5557 break; 5558 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 5559 WifiConfiguration.USER_BANNED) { 5560 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5561 WifiManager.NOT_AUTHORIZED); 5562 break; 5563 } 5564 5565 mAutoRoaming = false; 5566 5567 /* Tell network selection the user did try to connect to that network if from 5568 settings */ 5569 boolean persist = 5570 mWifiConfigManager.checkConfigOverridePermission(message.sendingUid); 5571 5572 5573 mWifiConfigManager.setAndEnableLastSelectedConfiguration(netId); 5574 if (mWifiConnectivityManager != null) { 5575 mWifiConnectivityManager.connectToUserSelectNetwork(netId, persist); 5576 } 5577 didDisconnect = false; 5578 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 5579 && mLastNetworkId != netId) { 5580 /** Supplicant will ignore the reconnect if we are currently associated, 5581 * hence trigger a disconnect 5582 */ 5583 didDisconnect = true; 5584 mWifiNative.disconnect(); 5585 } 5586 5587 //Start a new ConnectionEvent due to connect_network, this is always user 5588 //selected 5589 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 5590 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED); 5591 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ true, 5592 message.sendingUid) && mWifiNative.reconnect()) { 5593 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 5594 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 5595 5596 /* The state tracker handles enabling networks upon completion/failure */ 5597 mSupplicantStateTracker.sendMessage(WifiManager.CONNECT_NETWORK); 5598 replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 5599 if (didDisconnect) { 5600 /* Expect a disconnection from the old connection */ 5601 transitionTo(mDisconnectingState); 5602 } else if (updatedExisting && getCurrentState() == mConnectedState && 5603 getCurrentWifiConfiguration().networkId == netId) { 5604 // Update the current set of network capabilities, but stay in the 5605 // current state. 5606 updateCapabilities(config); 5607 } else { 5608 /** 5609 * Directly go to disconnected state where we 5610 * process the connection events from supplicant 5611 */ 5612 transitionTo(mDisconnectedState); 5613 } 5614 } else { 5615 loge("Failed to connect config: " + config + " netId: " + netId); 5616 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5617 WifiManager.ERROR); 5618 reportConnectionAttemptEnd( 5619 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 5620 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5621 break; 5622 } 5623 break; 5624 case WifiManager.SAVE_NETWORK: 5625 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5626 // Fall thru 5627 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 5628 // Only the current foreground user can modify networks. 5629 if (!mWifiConfigManager.isCurrentUserProfile( 5630 UserHandle.getUserId(message.sendingUid))) { 5631 loge("Only the current foreground user can modify networks " 5632 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5633 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5634 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5635 WifiManager.NOT_AUTHORIZED); 5636 break; 5637 } 5638 5639 lastSavedConfigurationAttempt = null; // Used for debug 5640 config = (WifiConfiguration) message.obj; 5641 if (config == null) { 5642 loge("ERROR: SAVE_NETWORK with null configuration" 5643 + mSupplicantStateTracker.getSupplicantStateName() 5644 + " my state " + getCurrentState().getName()); 5645 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5646 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5647 WifiManager.ERROR); 5648 break; 5649 } 5650 lastSavedConfigurationAttempt = new WifiConfiguration(config); 5651 int nid = config.networkId; 5652 logd("SAVE_NETWORK id=" + Integer.toString(nid) 5653 + " config=" + config.SSID 5654 + " nid=" + config.networkId 5655 + " supstate=" + mSupplicantStateTracker.getSupplicantStateName() 5656 + " my state " + getCurrentState().getName()); 5657 5658 // Only record the uid if this is user initiated 5659 boolean checkUid = (message.what == WifiManager.SAVE_NETWORK); 5660 if (checkUid && !recordUidIfAuthorized(config, message.sendingUid, 5661 /* onlyAnnotate */ false)) { 5662 logw("Not authorized to update network " 5663 + " config=" + config.SSID 5664 + " cnid=" + config.networkId 5665 + " uid=" + message.sendingUid); 5666 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5667 WifiManager.NOT_AUTHORIZED); 5668 break; 5669 } 5670 5671 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 5672 if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) { 5673 if (mWifiInfo.getNetworkId() == result.getNetworkId()) { 5674 if (result.hasIpChanged()) { 5675 // The currently connection configuration was changed 5676 // We switched from DHCP to static or from static to DHCP, or the 5677 // static IP address has changed. 5678 log("Reconfiguring IP on connection"); 5679 // TODO: clear addresses and disable IPv6 5680 // to simplify obtainingIpState. 5681 transitionTo(mObtainingIpState); 5682 } 5683 if (result.hasProxyChanged()) { 5684 log("Reconfiguring proxy on connection"); 5685 mIpManager.setHttpProxy( 5686 mWifiConfigManager.getProxyProperties(mLastNetworkId)); 5687 } 5688 } 5689 replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED); 5690 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 5691 5692 if (mVerboseLoggingEnabled) { 5693 logd("Success save network nid=" 5694 + Integer.toString(result.getNetworkId())); 5695 } 5696 5697 /** 5698 * If the command comes from WifiManager, then 5699 * tell autojoin the user did try to modify and save that network, 5700 * and interpret the SAVE_NETWORK as a request to connect 5701 */ 5702 boolean user = message.what == WifiManager.SAVE_NETWORK; 5703 5704 // Did this connect come from settings 5705 boolean persistConnect = 5706 mWifiConfigManager.checkConfigOverridePermission( 5707 message.sendingUid); 5708 5709 if (user) { 5710 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 5711 mWifiConfigManager.writeKnownNetworkHistory(); 5712 } 5713 5714 if (mWifiConnectivityManager != null) { 5715 mWifiConnectivityManager.connectToUserSelectNetwork( 5716 result.getNetworkId(), persistConnect); 5717 } 5718 } else { 5719 loge("Failed to save network"); 5720 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5721 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5722 WifiManager.ERROR); 5723 } 5724 break; 5725 case WifiManager.FORGET_NETWORK: 5726 // Only the current foreground user can modify networks. 5727 if (!mWifiConfigManager.isCurrentUserProfile( 5728 UserHandle.getUserId(message.sendingUid))) { 5729 loge("Only the current foreground user can modify networks " 5730 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5731 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5732 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 5733 WifiManager.NOT_AUTHORIZED); 5734 break; 5735 } 5736 5737 // Debug only, remember last configuration that was forgotten 5738 WifiConfiguration toRemove 5739 = mWifiConfigManager.getWifiConfiguration(message.arg1); 5740 if (toRemove == null) { 5741 lastForgetConfigurationAttempt = null; 5742 } else { 5743 lastForgetConfigurationAttempt = new WifiConfiguration(toRemove); 5744 } 5745 // check that the caller owns this network 5746 netId = message.arg1; 5747 5748 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 5749 /* onlyAnnotate */ false)) { 5750 logw("Not authorized to forget network " 5751 + " cnid=" + netId 5752 + " uid=" + message.sendingUid); 5753 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 5754 WifiManager.NOT_AUTHORIZED); 5755 break; 5756 } 5757 5758 if (mWifiConfigManager.forgetNetwork(message.arg1)) { 5759 replyToMessage(message, WifiManager.FORGET_NETWORK_SUCCEEDED); 5760 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, 5761 (WifiConfiguration) message.obj); 5762 } else { 5763 loge("Failed to forget network"); 5764 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 5765 WifiManager.ERROR); 5766 } 5767 break; 5768 case WifiManager.START_WPS: 5769 WpsInfo wpsInfo = (WpsInfo) message.obj; 5770 WpsResult wpsResult; 5771 switch (wpsInfo.setup) { 5772 case WpsInfo.PBC: 5773 wpsResult = mWifiConfigManager.startWpsPbc(wpsInfo); 5774 break; 5775 case WpsInfo.KEYPAD: 5776 wpsResult = mWifiConfigManager.startWpsWithPinFromAccessPoint(wpsInfo); 5777 break; 5778 case WpsInfo.DISPLAY: 5779 wpsResult = mWifiConfigManager.startWpsWithPinFromDevice(wpsInfo); 5780 break; 5781 default: 5782 wpsResult = new WpsResult(Status.FAILURE); 5783 loge("Invalid setup for WPS"); 5784 break; 5785 } 5786 mWifiConfigManager.setAndEnableLastSelectedConfiguration 5787 (WifiConfiguration.INVALID_NETWORK_ID); 5788 if (wpsResult.status == Status.SUCCESS) { 5789 replyToMessage(message, WifiManager.START_WPS_SUCCEEDED, wpsResult); 5790 transitionTo(mWpsRunningState); 5791 } else { 5792 loge("Failed to start WPS with config " + wpsInfo.toString()); 5793 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR); 5794 } 5795 break; 5796 case CMD_ASSOCIATED_BSSID: 5797 // This is where we can confirm the connection BSSID. Use it to find the 5798 // right ScanDetail to populate metrics. 5799 String someBssid = (String) message.obj; 5800 if (someBssid != null) { 5801 //Get the config associated with this connection attempt 5802 WifiConfiguration someConf = 5803 mWifiConfigManager.getWifiConfiguration(mTargetNetworkId); 5804 // Get the ScanDetail associated with this BSSID 5805 ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCache( 5806 someConf); 5807 if (scanDetailCache != null) { 5808 mWifiMetrics.setConnectionScanDetail(scanDetailCache.getScanDetail( 5809 someBssid)); 5810 } 5811 } 5812 return NOT_HANDLED; 5813 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5814 if (mVerboseLoggingEnabled) log("Network connection established"); 5815 mLastNetworkId = message.arg1; 5816 mLastBssid = (String) message.obj; 5817 5818 mWifiInfo.setBSSID(mLastBssid); 5819 mWifiInfo.setNetworkId(mLastNetworkId); 5820 if (mWifiConnectivityManager != null) { 5821 mWifiConnectivityManager.trackBssid(mLastBssid, true); 5822 } 5823 sendNetworkStateChangeBroadcast(mLastBssid); 5824 transitionTo(mObtainingIpState); 5825 break; 5826 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5827 // Calling handleNetworkDisconnect here is redundant because we might already 5828 // have called it when leaving L2ConnectedState to go to disconnecting state 5829 // or thru other path 5830 // We should normally check the mWifiInfo or mLastNetworkId so as to check 5831 // if they are valid, and only in this case call handleNEtworkDisconnect, 5832 // TODO: this should be fixed for a L MR release 5833 // The side effect of calling handleNetworkDisconnect twice is that a bunch of 5834 // idempotent commands are executed twice (stopping Dhcp, enabling the SPS mode 5835 // at the chip etc... 5836 if (mVerboseLoggingEnabled) log("ConnectModeState: Network connection lost "); 5837 handleNetworkDisconnect(); 5838 transitionTo(mDisconnectedState); 5839 break; 5840 case CMD_ADD_PASSPOINT_MO: 5841 res = mWifiConfigManager.addPasspointManagementObject((String) message.obj); 5842 replyToMessage(message, message.what, res); 5843 break; 5844 case CMD_MODIFY_PASSPOINT_MO: 5845 if (message.obj != null) { 5846 Bundle bundle = (Bundle) message.obj; 5847 ArrayList<PasspointManagementObjectDefinition> mos = 5848 bundle.getParcelableArrayList("MOS"); 5849 res = mWifiConfigManager.modifyPasspointMo(bundle.getString("FQDN"), mos); 5850 } else { 5851 res = 0; 5852 } 5853 replyToMessage(message, message.what, res); 5854 5855 break; 5856 case CMD_QUERY_OSU_ICON: 5857 if (mWifiConfigManager.queryPasspointIcon( 5858 ((Bundle) message.obj).getLong("BSSID"), 5859 ((Bundle) message.obj).getString("FILENAME"))) { 5860 res = 1; 5861 } else { 5862 res = 0; 5863 } 5864 replyToMessage(message, message.what, res); 5865 break; 5866 case CMD_MATCH_PROVIDER_NETWORK: 5867 res = mWifiConfigManager.matchProviderWithCurrentNetwork((String) message.obj); 5868 replyToMessage(message, message.what, res); 5869 break; 5870 default: 5871 return NOT_HANDLED; 5872 } 5873 return HANDLED; 5874 } 5875 } 5876 5877 private void updateCapabilities(WifiConfiguration config) { 5878 NetworkCapabilities networkCapabilities = new NetworkCapabilities(mDfltNetworkCapabilities); 5879 if (config != null) { 5880 if (config.ephemeral) { 5881 networkCapabilities.removeCapability( 5882 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 5883 } else { 5884 networkCapabilities.addCapability( 5885 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 5886 } 5887 5888 networkCapabilities.setSignalStrength( 5889 (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI) 5890 ? mWifiInfo.getRssi() 5891 : NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED); 5892 } 5893 5894 if (mWifiInfo.getMeteredHint()) { 5895 networkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 5896 } 5897 5898 mNetworkAgent.sendNetworkCapabilities(networkCapabilities); 5899 } 5900 5901 private class WifiNetworkAgent extends NetworkAgent { 5902 public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, 5903 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { 5904 super(l, c, TAG, ni, nc, lp, score, misc); 5905 } 5906 5907 @Override 5908 protected void unwanted() { 5909 // Ignore if we're not the current networkAgent. 5910 if (this != mNetworkAgent) return; 5911 if (mVerboseLoggingEnabled) { 5912 log("WifiNetworkAgent -> Wifi unwanted score " + Integer.toString(mWifiInfo.score)); 5913 } 5914 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT); 5915 } 5916 5917 @Override 5918 protected void networkStatus(int status, String redirectUrl) { 5919 if (this != mNetworkAgent) return; 5920 if (status == NetworkAgent.INVALID_NETWORK) { 5921 if (mVerboseLoggingEnabled) { 5922 log("WifiNetworkAgent -> Wifi networkStatus invalid, score=" 5923 + Integer.toString(mWifiInfo.score)); 5924 } 5925 unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED); 5926 } else if (status == NetworkAgent.VALID_NETWORK) { 5927 if (mVerboseLoggingEnabled) { 5928 log("WifiNetworkAgent -> Wifi networkStatus valid, score= " 5929 + Integer.toString(mWifiInfo.score)); 5930 } 5931 doNetworkStatus(status); 5932 } 5933 } 5934 5935 @Override 5936 protected void saveAcceptUnvalidated(boolean accept) { 5937 if (this != mNetworkAgent) return; 5938 WifiStateMachine.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0); 5939 } 5940 5941 @Override 5942 protected void startPacketKeepalive(Message msg) { 5943 WifiStateMachine.this.sendMessage( 5944 CMD_START_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 5945 } 5946 5947 @Override 5948 protected void stopPacketKeepalive(Message msg) { 5949 WifiStateMachine.this.sendMessage( 5950 CMD_STOP_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 5951 } 5952 5953 @Override 5954 protected void setSignalStrengthThresholds(int[] thresholds) { 5955 // 0. If there are no thresholds, or if the thresholds are invalid, stop RSSI monitoring. 5956 // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and 5957 // MAX_VALUE at the start/end of the thresholds array if necessary. 5958 // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware 5959 // event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then 5960 // re-arm the hardware event. This needs to be done on the state machine thread to 5961 // avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one 5962 // sent in the NetworkCapabilities) must be the one received from the hardware event 5963 // received, or we might skip callbacks. 5964 // 3. Ensure that when we disconnect, RSSI monitoring is stopped. 5965 log("Received signal strength thresholds: " + Arrays.toString(thresholds)); 5966 if (thresholds.length == 0) { 5967 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 5968 mWifiInfo.getRssi()); 5969 return; 5970 } 5971 int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2); 5972 rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE; 5973 rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE; 5974 Arrays.sort(rssiVals); 5975 byte[] rssiRange = new byte[rssiVals.length]; 5976 for (int i = 0; i < rssiVals.length; i++) { 5977 int val = rssiVals[i]; 5978 if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) { 5979 rssiRange[i] = (byte) val; 5980 } else { 5981 Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: " 5982 + Arrays.toString(rssiVals)); 5983 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 5984 mWifiInfo.getRssi()); 5985 return; 5986 } 5987 } 5988 // TODO: Do we quash rssi values in this sorted array which are very close? 5989 mRssiRanges = rssiRange; 5990 WifiStateMachine.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD, 5991 mWifiInfo.getRssi()); 5992 } 5993 5994 @Override 5995 protected void preventAutomaticReconnect() { 5996 if (this != mNetworkAgent) return; 5997 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN); 5998 } 5999 } 6000 6001 void unwantedNetwork(int reason) { 6002 sendMessage(CMD_UNWANTED_NETWORK, reason); 6003 } 6004 6005 void doNetworkStatus(int status) { 6006 sendMessage(CMD_NETWORK_STATUS, status); 6007 } 6008 6009 // rfc4186 & rfc4187: 6010 // create Permanent Identity base on IMSI, 6011 // identity = usernam@realm 6012 // with username = prefix | IMSI 6013 // and realm is derived MMC/MNC tuple according 3GGP spec(TS23.003) 6014 private String buildIdentity(int eapMethod, String imsi, String mccMnc) { 6015 String mcc; 6016 String mnc; 6017 String prefix; 6018 6019 if (imsi == null || imsi.isEmpty()) 6020 return ""; 6021 6022 if (eapMethod == WifiEnterpriseConfig.Eap.SIM) 6023 prefix = "1"; 6024 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA) 6025 prefix = "0"; 6026 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME) 6027 prefix = "6"; 6028 else // not a valide EapMethod 6029 return ""; 6030 6031 /* extract mcc & mnc from mccMnc */ 6032 if (mccMnc != null && !mccMnc.isEmpty()) { 6033 mcc = mccMnc.substring(0, 3); 6034 mnc = mccMnc.substring(3); 6035 if (mnc.length() == 2) 6036 mnc = "0" + mnc; 6037 } else { 6038 // extract mcc & mnc from IMSI, assume mnc size is 3 6039 mcc = imsi.substring(0, 3); 6040 mnc = imsi.substring(3, 6); 6041 } 6042 6043 return prefix + imsi + "@wlan.mnc" + mnc + ".mcc" + mcc + ".3gppnetwork.org"; 6044 } 6045 6046 boolean startScanForConfiguration(WifiConfiguration config) { 6047 if (config == null) 6048 return false; 6049 6050 // We are still seeing a fairly high power consumption triggered by autojoin scans 6051 // Hence do partial scans only for PSK configuration that are roamable since the 6052 // primary purpose of the partial scans is roaming. 6053 // Full badn scans with exponential backoff for the purpose or extended roaming and 6054 // network switching are performed unconditionally. 6055 ScanDetailCache scanDetailCache = 6056 mWifiConfigManager.getScanDetailCache(config); 6057 if (scanDetailCache == null 6058 || !config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) 6059 || scanDetailCache.size() > 6) { 6060 //return true but to not trigger the scan 6061 return true; 6062 } 6063 HashSet<Integer> freqs = mWifiConfigManager.makeChannelList(config, ONE_HOUR_MILLI); 6064 if (freqs != null && freqs.size() != 0) { 6065 //if (mVerboseLoggingEnabled) { 6066 logd("starting scan for " + config.configKey() + " with " + freqs); 6067 //} 6068 Set<Integer> hiddenNetworkIds = new HashSet<>(); 6069 if (config.hiddenSSID) { 6070 hiddenNetworkIds.add(config.networkId); 6071 } 6072 // Call wifi native to start the scan 6073 if (startScanNative(freqs, hiddenNetworkIds, WIFI_WORK_SOURCE)) { 6074 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; 6075 } else { 6076 // used for debug only, mark scan as failed 6077 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 6078 } 6079 return true; 6080 } else { 6081 if (mVerboseLoggingEnabled) logd("no channels for " + config.configKey()); 6082 return false; 6083 } 6084 } 6085 6086 void clearCurrentConfigBSSID(String dbg) { 6087 // Clear the bssid in the current config's network block 6088 WifiConfiguration config = getCurrentWifiConfiguration(); 6089 if (config == null) 6090 return; 6091 clearConfigBSSID(config, dbg); 6092 } 6093 void clearConfigBSSID(WifiConfiguration config, String dbg) { 6094 if (config == null) 6095 return; 6096 if (mVerboseLoggingEnabled) { 6097 logd(dbg + " " + mTargetRoamBSSID + " config " + config.configKey() 6098 + " config.NetworkSelectionStatus.mNetworkSelectionBSSID " 6099 + config.getNetworkSelectionStatus().getNetworkSelectionBSSID()); 6100 } 6101 if (mVerboseLoggingEnabled) { 6102 logd(dbg + " " + config.SSID 6103 + " nid=" + Integer.toString(config.networkId)); 6104 } 6105 mWifiConfigManager.saveWifiConfigBSSID(config, "any"); 6106 } 6107 6108 class L2ConnectedState extends State { 6109 @Override 6110 public void enter() { 6111 mRssiPollToken++; 6112 if (mEnableRssiPolling) { 6113 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0); 6114 } 6115 if (mNetworkAgent != null) { 6116 loge("Have NetworkAgent when entering L2Connected"); 6117 setNetworkDetailedState(DetailedState.DISCONNECTED); 6118 } 6119 setNetworkDetailedState(DetailedState.CONNECTING); 6120 6121 mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, 6122 "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter, 6123 mLinkProperties, 60, mNetworkMisc); 6124 6125 // We must clear the config BSSID, as the wifi chipset may decide to roam 6126 // from this point on and having the BSSID specified in the network block would 6127 // cause the roam to faile and the device to disconnect 6128 clearCurrentConfigBSSID("L2ConnectedState"); 6129 mCountryCode.setReadyForChange(false); 6130 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); 6131 } 6132 6133 @Override 6134 public void exit() { 6135 mIpManager.stop(); 6136 6137 // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState 6138 // Bug: 15347363 6139 // For paranoia's sake, call handleNetworkDisconnect 6140 // only if BSSID is null or last networkId 6141 // is not invalid. 6142 if (mVerboseLoggingEnabled) { 6143 StringBuilder sb = new StringBuilder(); 6144 sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId)); 6145 if (mLastBssid !=null) { 6146 sb.append(" ").append(mLastBssid); 6147 } 6148 } 6149 if (mLastBssid != null || mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6150 handleNetworkDisconnect(); 6151 } 6152 mCountryCode.setReadyForChange(true); 6153 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 6154 } 6155 6156 @Override 6157 public boolean processMessage(Message message) { 6158 logStateAndMessage(message, this); 6159 6160 switch (message.what) { 6161 case DhcpClient.CMD_PRE_DHCP_ACTION: 6162 handlePreDhcpSetup(); 6163 break; 6164 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 6165 mIpManager.completedPreDhcpAction(); 6166 break; 6167 case DhcpClient.CMD_POST_DHCP_ACTION: 6168 handlePostDhcpSetup(); 6169 // We advance to mConnectedState because IpManager will also send a 6170 // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(), 6171 // which calls updateLinkProperties, which then sends 6172 // CMD_IP_CONFIGURATION_SUCCESSFUL. 6173 // 6174 // In the event of failure, we transition to mDisconnectingState 6175 // similarly--via messages sent back from IpManager. 6176 break; 6177 case CMD_IPV4_PROVISIONING_SUCCESS: { 6178 handleIPv4Success((DhcpResults) message.obj); 6179 sendNetworkStateChangeBroadcast(mLastBssid); 6180 break; 6181 } 6182 case CMD_IPV4_PROVISIONING_FAILURE: { 6183 handleIPv4Failure(); 6184 break; 6185 } 6186 case CMD_IP_CONFIGURATION_SUCCESSFUL: 6187 handleSuccessfulIpConfiguration(); 6188 reportConnectionAttemptEnd( 6189 WifiMetrics.ConnectionEvent.FAILURE_NONE, 6190 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6191 sendConnectedState(); 6192 transitionTo(mConnectedState); 6193 break; 6194 case CMD_IP_CONFIGURATION_LOST: 6195 // Get Link layer stats so that we get fresh tx packet counters. 6196 getWifiLinkLayerStats(); 6197 handleIpConfigurationLost(); 6198 reportConnectionAttemptEnd( 6199 WifiMetrics.ConnectionEvent.FAILURE_DHCP, 6200 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6201 transitionTo(mDisconnectingState); 6202 break; 6203 case CMD_IP_REACHABILITY_LOST: 6204 if (mVerboseLoggingEnabled && message.obj != null) log((String) message.obj); 6205 handleIpReachabilityLost(); 6206 transitionTo(mDisconnectingState); 6207 break; 6208 case CMD_DISCONNECT: 6209 mWifiNative.disconnect(); 6210 transitionTo(mDisconnectingState); 6211 break; 6212 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 6213 if (message.arg1 == 1) { 6214 mWifiNative.disconnect(); 6215 mTemporarilyDisconnectWifi = true; 6216 transitionTo(mDisconnectingState); 6217 } 6218 break; 6219 case CMD_SET_OPERATIONAL_MODE: 6220 if (message.arg1 != CONNECT_MODE) { 6221 sendMessage(CMD_DISCONNECT); 6222 deferMessage(message); 6223 if (message.arg1 == SCAN_ONLY_WITH_WIFI_OFF_MODE || 6224 message.arg1 == DISABLED_MODE) { 6225 noteWifiDisabledWhileAssociated(); 6226 } 6227 } 6228 mWifiConfigManager. 6229 setAndEnableLastSelectedConfiguration( 6230 WifiConfiguration.INVALID_NETWORK_ID); 6231 break; 6232 /* Ignore connection to same network */ 6233 case WifiManager.CONNECT_NETWORK: 6234 int netId = message.arg1; 6235 if (mWifiInfo.getNetworkId() == netId) { 6236 break; 6237 } 6238 return NOT_HANDLED; 6239 case WifiMonitor.NETWORK_CONNECTION_EVENT: 6240 mWifiInfo.setBSSID((String) message.obj); 6241 mLastNetworkId = message.arg1; 6242 mWifiInfo.setNetworkId(mLastNetworkId); 6243 if(!mLastBssid.equals(message.obj)) { 6244 mLastBssid = (String) message.obj; 6245 sendNetworkStateChangeBroadcast(mLastBssid); 6246 } 6247 break; 6248 case CMD_RSSI_POLL: 6249 if (message.arg1 == mRssiPollToken) { 6250 if (mWifiConfigManager.mEnableChipWakeUpWhenAssociated.get()) { 6251 if (mVerboseLoggingEnabled) { 6252 log(" get link layer stats " + mWifiLinkLayerStatsSupported); 6253 } 6254 WifiLinkLayerStats stats = getWifiLinkLayerStats(); 6255 if (stats != null) { 6256 // Sanity check the results provided by driver 6257 if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI 6258 && (stats.rssi_mgmt == 0 6259 || stats.beacon_rx == 0)) { 6260 stats = null; 6261 } 6262 } 6263 // Get Info and continue polling 6264 fetchRssiLinkSpeedAndFrequencyNative(); 6265 mWifiScoreReport = 6266 WifiScoreReport.calculateScore(mWifiInfo, 6267 getCurrentWifiConfiguration(), 6268 mWifiConfigManager, 6269 mNetworkAgent, 6270 mWifiScoreReport, 6271 mAggressiveHandover, 6272 mVerboseLoggingEnabled); 6273 } 6274 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 6275 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 6276 if (mVerboseLoggingEnabled) sendRssiChangeBroadcast(mWifiInfo.getRssi()); 6277 } else { 6278 // Polling has completed 6279 } 6280 break; 6281 case CMD_ENABLE_RSSI_POLL: 6282 cleanWifiScore(); 6283 if (mWifiConfigManager.mEnableRssiPollWhenAssociated.get()) { 6284 mEnableRssiPolling = (message.arg1 == 1); 6285 } else { 6286 mEnableRssiPolling = false; 6287 } 6288 mRssiPollToken++; 6289 if (mEnableRssiPolling) { 6290 // First poll 6291 fetchRssiLinkSpeedAndFrequencyNative(); 6292 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 6293 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 6294 } 6295 break; 6296 case WifiManager.RSSI_PKTCNT_FETCH: 6297 RssiPacketCountInfo info = new RssiPacketCountInfo(); 6298 fetchRssiLinkSpeedAndFrequencyNative(); 6299 info.rssi = mWifiInfo.getRssi(); 6300 fetchPktcntNative(info); 6301 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED, info); 6302 break; 6303 case CMD_DELAYED_NETWORK_DISCONNECT: 6304 if (!isLinkDebouncing()) { 6305 6306 // Ignore if we are not debouncing 6307 logd("CMD_DELAYED_NETWORK_DISCONNECT and not debouncing - ignore " 6308 + message.arg1); 6309 return HANDLED; 6310 } else { 6311 logd("CMD_DELAYED_NETWORK_DISCONNECT and debouncing - disconnect " 6312 + message.arg1); 6313 6314 mIsLinkDebouncing = false; 6315 // If we are still debouncing while this message comes, 6316 // it means we were not able to reconnect within the alloted time 6317 // = LINK_FLAPPING_DEBOUNCE_MSEC 6318 // and thus, trigger a real disconnect 6319 handleNetworkDisconnect(); 6320 transitionTo(mDisconnectedState); 6321 } 6322 break; 6323 case CMD_ASSOCIATED_BSSID: 6324 if ((String) message.obj == null) { 6325 logw("Associated command w/o BSSID"); 6326 break; 6327 } 6328 mLastBssid = (String) message.obj; 6329 if (mLastBssid != null && (mWifiInfo.getBSSID() == null 6330 || !mLastBssid.equals(mWifiInfo.getBSSID()))) { 6331 mWifiInfo.setBSSID((String) message.obj); 6332 sendNetworkStateChangeBroadcast(mLastBssid); 6333 } 6334 break; 6335 case CMD_START_RSSI_MONITORING_OFFLOAD: 6336 case CMD_RSSI_THRESHOLD_BREACH: 6337 byte currRssi = (byte) message.arg1; 6338 processRssiThreshold(currRssi, message.what); 6339 break; 6340 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 6341 stopRssiMonitoringOffload(); 6342 break; 6343 case CMD_RESET_SIM_NETWORKS: 6344 if (message.arg1 == 0 // sim was removed 6345 && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6346 WifiConfiguration config = 6347 mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 6348 if (TelephonyUtil.isSimConfig(config)) { 6349 mWifiNative.disconnect(); 6350 transitionTo(mDisconnectingState); 6351 } 6352 } 6353 /* allow parent state to reset data for other networks */ 6354 return NOT_HANDLED; 6355 default: 6356 return NOT_HANDLED; 6357 } 6358 6359 return HANDLED; 6360 } 6361 } 6362 6363 class ObtainingIpState extends State { 6364 @Override 6365 public void enter() { 6366 if (mVerboseLoggingEnabled) { 6367 String key = ""; 6368 if (getCurrentWifiConfiguration() != null) { 6369 key = getCurrentWifiConfiguration().configKey(); 6370 } 6371 log("enter ObtainingIpState netId=" + Integer.toString(mLastNetworkId) 6372 + " " + key + " " 6373 + " roam=" + mAutoRoaming 6374 + " static=" + mWifiConfigManager.isUsingStaticIp(mLastNetworkId)); 6375 } 6376 6377 // Reset link Debouncing, indicating we have successfully re-connected to the AP 6378 // We might still be roaming 6379 mIsLinkDebouncing = false; 6380 6381 // Send event to CM & network change broadcast 6382 setNetworkDetailedState(DetailedState.OBTAINING_IPADDR); 6383 6384 // We must clear the config BSSID, as the wifi chipset may decide to roam 6385 // from this point on and having the BSSID specified in the network block would 6386 // cause the roam to fail and the device to disconnect. 6387 clearCurrentConfigBSSID("ObtainingIpAddress"); 6388 6389 // Stop IpManager in case we're switching from DHCP to static 6390 // configuration or vice versa. 6391 // 6392 // TODO: Only ever enter this state the first time we connect to a 6393 // network, never on switching between static configuration and 6394 // DHCP. When we transition from static configuration to DHCP in 6395 // particular, we must tell ConnectivityService that we're 6396 // disconnected, because DHCP might take a long time during which 6397 // connectivity APIs such as getActiveNetworkInfo should not return 6398 // CONNECTED. 6399 stopIpManager(); 6400 6401 mIpManager.setHttpProxy(mWifiConfigManager.getProxyProperties(mLastNetworkId)); 6402 if (!TextUtils.isEmpty(mTcpBufferSizes)) { 6403 mIpManager.setTcpBufferSizes(mTcpBufferSizes); 6404 } 6405 6406 if (!mWifiConfigManager.isUsingStaticIp(mLastNetworkId)) { 6407 final IpManager.ProvisioningConfiguration prov = 6408 IpManager.buildProvisioningConfiguration() 6409 .withPreDhcpAction() 6410 .withApfCapabilities(mWifiNative.getApfCapabilities()) 6411 .build(); 6412 mIpManager.startProvisioning(prov); 6413 // Get Link layer stats so as we get fresh tx packet counters 6414 getWifiLinkLayerStats(); 6415 } else { 6416 StaticIpConfiguration config = mWifiConfigManager.getStaticIpConfiguration( 6417 mLastNetworkId); 6418 if (config.ipAddress == null) { 6419 logd("Static IP lacks address"); 6420 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 6421 } else { 6422 final IpManager.ProvisioningConfiguration prov = 6423 IpManager.buildProvisioningConfiguration() 6424 .withStaticConfiguration(config) 6425 .withApfCapabilities(mWifiNative.getApfCapabilities()) 6426 .build(); 6427 mIpManager.startProvisioning(prov); 6428 } 6429 } 6430 } 6431 6432 @Override 6433 public boolean processMessage(Message message) { 6434 logStateAndMessage(message, this); 6435 6436 switch(message.what) { 6437 case CMD_AUTO_CONNECT: 6438 case CMD_AUTO_ROAM: 6439 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6440 break; 6441 case WifiManager.SAVE_NETWORK: 6442 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 6443 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 6444 deferMessage(message); 6445 break; 6446 /* Defer any power mode changes since we must keep active power mode at DHCP */ 6447 6448 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6449 reportConnectionAttemptEnd( 6450 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 6451 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6452 return NOT_HANDLED; 6453 case CMD_SET_HIGH_PERF_MODE: 6454 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 6455 deferMessage(message); 6456 break; 6457 /* Defer scan request since we should not switch to other channels at DHCP */ 6458 case CMD_START_SCAN: 6459 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 6460 deferMessage(message); 6461 break; 6462 default: 6463 return NOT_HANDLED; 6464 } 6465 return HANDLED; 6466 } 6467 } 6468 6469 private void sendConnectedState() { 6470 // If this network was explicitly selected by the user, evaluate whether to call 6471 // explicitlySelected() so the system can treat it appropriately. 6472 WifiConfiguration config = getCurrentWifiConfiguration(); 6473 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 6474 boolean prompt = 6475 mWifiConfigManager.checkConfigOverridePermission(config.lastConnectUid); 6476 if (mVerboseLoggingEnabled) { 6477 log("Network selected by UID " + config.lastConnectUid + " prompt=" + prompt); 6478 } 6479 if (prompt) { 6480 // Selected by the user via Settings or QuickSettings. If this network has Internet 6481 // access, switch to it. Otherwise, switch to it only if the user confirms that they 6482 // really want to switch, or has already confirmed and selected "Don't ask again". 6483 if (mVerboseLoggingEnabled) { 6484 log("explictlySelected acceptUnvalidated=" + config.noInternetAccessExpected); 6485 } 6486 mNetworkAgent.explicitlySelected(config.noInternetAccessExpected); 6487 } 6488 } 6489 6490 setNetworkDetailedState(DetailedState.CONNECTED); 6491 mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.CONNECTED); 6492 sendNetworkStateChangeBroadcast(mLastBssid); 6493 } 6494 6495 class RoamingState extends State { 6496 boolean mAssociated; 6497 @Override 6498 public void enter() { 6499 if (mVerboseLoggingEnabled) { 6500 log("RoamingState Enter" 6501 + " mScreenOn=" + mScreenOn ); 6502 } 6503 6504 // Make sure we disconnect if roaming fails 6505 roamWatchdogCount++; 6506 logd("Start Roam Watchdog " + roamWatchdogCount); 6507 sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER, 6508 roamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); 6509 mAssociated = false; 6510 } 6511 @Override 6512 public boolean processMessage(Message message) { 6513 logStateAndMessage(message, this); 6514 WifiConfiguration config; 6515 switch (message.what) { 6516 case CMD_IP_CONFIGURATION_LOST: 6517 config = getCurrentWifiConfiguration(); 6518 if (config != null) { 6519 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_AUTOROAM_FAILURE); 6520 mWifiConfigManager.noteRoamingFailure(config, 6521 WifiConfiguration.ROAMING_FAILURE_IP_CONFIG); 6522 } 6523 return NOT_HANDLED; 6524 case CMD_UNWANTED_NETWORK: 6525 if (mVerboseLoggingEnabled) { 6526 log("Roaming and CS doesnt want the network -> ignore"); 6527 } 6528 return HANDLED; 6529 case CMD_SET_OPERATIONAL_MODE: 6530 if (message.arg1 != CONNECT_MODE) { 6531 deferMessage(message); 6532 } 6533 break; 6534 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6535 /** 6536 * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT 6537 * before NETWORK_DISCONNECTION_EVENT 6538 * And there is an associated BSSID corresponding to our target BSSID, then 6539 * we have missed the network disconnection, transition to mDisconnectedState 6540 * and handle the rest of the events there. 6541 */ 6542 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 6543 if (stateChangeResult.state == SupplicantState.DISCONNECTED 6544 || stateChangeResult.state == SupplicantState.INACTIVE 6545 || stateChangeResult.state == SupplicantState.INTERFACE_DISABLED) { 6546 if (mVerboseLoggingEnabled) { 6547 log("STATE_CHANGE_EVENT in roaming state " 6548 + stateChangeResult.toString() ); 6549 } 6550 if (stateChangeResult.BSSID != null 6551 && stateChangeResult.BSSID.equals(mTargetRoamBSSID)) { 6552 handleNetworkDisconnect(); 6553 transitionTo(mDisconnectedState); 6554 } 6555 } 6556 if (stateChangeResult.state == SupplicantState.ASSOCIATED) { 6557 // We completed the layer2 roaming part 6558 mAssociated = true; 6559 if (stateChangeResult.BSSID != null) { 6560 mTargetRoamBSSID = stateChangeResult.BSSID; 6561 } 6562 } 6563 break; 6564 case CMD_ROAM_WATCHDOG_TIMER: 6565 if (roamWatchdogCount == message.arg1) { 6566 if (mVerboseLoggingEnabled) log("roaming watchdog! -> disconnect"); 6567 mWifiMetrics.endConnectionEvent( 6568 WifiMetrics.ConnectionEvent.FAILURE_ROAM_TIMEOUT, 6569 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6570 mRoamFailCount++; 6571 handleNetworkDisconnect(); 6572 mWifiNative.disconnect(); 6573 transitionTo(mDisconnectedState); 6574 } 6575 break; 6576 case WifiMonitor.NETWORK_CONNECTION_EVENT: 6577 if (mAssociated) { 6578 if (mVerboseLoggingEnabled) { 6579 log("roaming and Network connection established"); 6580 } 6581 mLastNetworkId = message.arg1; 6582 mLastBssid = (String) message.obj; 6583 mWifiInfo.setBSSID(mLastBssid); 6584 mWifiInfo.setNetworkId(mLastNetworkId); 6585 if (mWifiConnectivityManager != null) { 6586 mWifiConnectivityManager.trackBssid(mLastBssid, true); 6587 } 6588 sendNetworkStateChangeBroadcast(mLastBssid); 6589 6590 // Successful framework roam! (probably) 6591 reportConnectionAttemptEnd( 6592 WifiMetrics.ConnectionEvent.FAILURE_NONE, 6593 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6594 6595 // We must clear the config BSSID, as the wifi chipset may decide to roam 6596 // from this point on and having the BSSID specified by QNS would cause 6597 // the roam to fail and the device to disconnect. 6598 // When transition from RoamingState to DisconnectingState or 6599 // DisconnectedState, the config BSSID is cleared by 6600 // handleNetworkDisconnect(). 6601 clearCurrentConfigBSSID("RoamingCompleted"); 6602 6603 // We used to transition to ObtainingIpState in an 6604 // attempt to do DHCPv4 RENEWs on framework roams. 6605 // DHCP can take too long to time out, and we now rely 6606 // upon IpManager's use of IpReachabilityMonitor to 6607 // confirm our current network configuration. 6608 // 6609 // mIpManager.confirmConfiguration() is called within 6610 // the handling of SupplicantState.COMPLETED. 6611 transitionTo(mConnectedState); 6612 } else { 6613 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6614 } 6615 break; 6616 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6617 // Throw away but only if it corresponds to the network we're roaming to 6618 String bssid = (String) message.obj; 6619 if (true) { 6620 String target = ""; 6621 if (mTargetRoamBSSID != null) target = mTargetRoamBSSID; 6622 log("NETWORK_DISCONNECTION_EVENT in roaming state" 6623 + " BSSID=" + bssid 6624 + " target=" + target); 6625 } 6626 if (bssid != null && bssid.equals(mTargetRoamBSSID)) { 6627 handleNetworkDisconnect(); 6628 transitionTo(mDisconnectedState); 6629 } 6630 break; 6631 case WifiMonitor.SSID_TEMP_DISABLED: 6632 // Auth error while roaming 6633 logd("SSID_TEMP_DISABLED nid=" + Integer.toString(mLastNetworkId) 6634 + " id=" + Integer.toString(message.arg1) 6635 + " isRoaming=" + isRoaming() 6636 + " roam=" + mAutoRoaming); 6637 if (message.arg1 == mLastNetworkId) { 6638 config = getCurrentWifiConfiguration(); 6639 if (config != null) { 6640 mWifiDiagnostics.captureBugReportData( 6641 WifiDiagnostics.REPORT_REASON_AUTOROAM_FAILURE); 6642 mWifiConfigManager.noteRoamingFailure(config, 6643 WifiConfiguration.ROAMING_FAILURE_AUTH_FAILURE); 6644 } 6645 handleNetworkDisconnect(); 6646 transitionTo(mDisconnectingState); 6647 } 6648 return NOT_HANDLED; 6649 case CMD_START_SCAN: 6650 deferMessage(message); 6651 break; 6652 default: 6653 return NOT_HANDLED; 6654 } 6655 return HANDLED; 6656 } 6657 6658 @Override 6659 public void exit() { 6660 logd("WifiStateMachine: Leaving Roaming state"); 6661 } 6662 } 6663 6664 class ConnectedState extends State { 6665 @Override 6666 public void enter() { 6667 updateDefaultRouteMacAddress(1000); 6668 if (mVerboseLoggingEnabled) { 6669 log("Enter ConnectedState " 6670 + " mScreenOn=" + mScreenOn); 6671 } 6672 6673 if (mWifiConnectivityManager != null) { 6674 mWifiConnectivityManager.handleConnectionStateChanged( 6675 WifiConnectivityManager.WIFI_STATE_CONNECTED); 6676 } 6677 registerConnected(); 6678 lastConnectAttemptTimestamp = 0; 6679 targetWificonfiguration = null; 6680 // Paranoia 6681 mIsLinkDebouncing = false; 6682 6683 // Not roaming anymore 6684 mAutoRoaming = false; 6685 6686 if (testNetworkDisconnect) { 6687 testNetworkDisconnectCounter++; 6688 logd("ConnectedState Enter start disconnect test " + 6689 testNetworkDisconnectCounter); 6690 sendMessageDelayed(obtainMessage(CMD_TEST_NETWORK_DISCONNECT, 6691 testNetworkDisconnectCounter, 0), 15000); 6692 } 6693 6694 // Reenable all networks, allow for hidden networks to be scanned 6695 mWifiConfigManager.enableAllNetworks(); 6696 6697 mLastDriverRoamAttempt = 0; 6698 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 6699 mWifiInjector.getWifiLastResortWatchdog().connectedStateTransition(true); 6700 } 6701 @Override 6702 public boolean processMessage(Message message) { 6703 WifiConfiguration config = null; 6704 logStateAndMessage(message, this); 6705 6706 switch (message.what) { 6707 case CMD_UNWANTED_NETWORK: 6708 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { 6709 mWifiConfigManager.handleBadNetworkDisconnectReport( 6710 mLastNetworkId, mWifiInfo); 6711 mWifiNative.disconnect(); 6712 transitionTo(mDisconnectingState); 6713 } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN || 6714 message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { 6715 Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 6716 ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN" 6717 : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED")); 6718 config = getCurrentWifiConfiguration(); 6719 if (config != null) { 6720 // Disable autojoin 6721 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) { 6722 config.validatedInternetAccess = false; 6723 // Clear last-selected status, as being last-selected also avoids 6724 // disabling auto-join. 6725 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 6726 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 6727 WifiConfiguration.INVALID_NETWORK_ID); 6728 } 6729 mWifiConfigManager.updateNetworkSelectionStatus(config, 6730 WifiConfiguration.NetworkSelectionStatus 6731 .DISABLED_NO_INTERNET); 6732 } 6733 config.numNoInternetAccessReports += 1; 6734 mWifiConfigManager.writeKnownNetworkHistory(); 6735 } 6736 } 6737 return HANDLED; 6738 case CMD_NETWORK_STATUS: 6739 if (message.arg1 == NetworkAgent.VALID_NETWORK) { 6740 config = getCurrentWifiConfiguration(); 6741 if (config != null) { 6742 // re-enable autojoin 6743 config.numNoInternetAccessReports = 0; 6744 config.validatedInternetAccess = true; 6745 mWifiConfigManager.writeKnownNetworkHistory(); 6746 } 6747 } 6748 return HANDLED; 6749 case CMD_ACCEPT_UNVALIDATED: 6750 boolean accept = (message.arg1 != 0); 6751 config = getCurrentWifiConfiguration(); 6752 if (config != null) { 6753 config.noInternetAccessExpected = accept; 6754 mWifiConfigManager.writeKnownNetworkHistory(); 6755 } 6756 return HANDLED; 6757 case CMD_TEST_NETWORK_DISCONNECT: 6758 // Force a disconnect 6759 if (message.arg1 == testNetworkDisconnectCounter) { 6760 mWifiNative.disconnect(); 6761 } 6762 break; 6763 case CMD_ASSOCIATED_BSSID: 6764 // ASSOCIATING to a new BSSID while already connected, indicates 6765 // that driver is roaming 6766 mLastDriverRoamAttempt = mClock.getWallClockMillis(); 6767 return NOT_HANDLED; 6768 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6769 long lastRoam = 0; 6770 reportConnectionAttemptEnd( 6771 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 6772 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6773 if (mLastDriverRoamAttempt != 0) { 6774 // Calculate time since last driver roam attempt 6775 lastRoam = mClock.getWallClockMillis() - mLastDriverRoamAttempt; 6776 mLastDriverRoamAttempt = 0; 6777 } 6778 if (unexpectedDisconnectedReason(message.arg2)) { 6779 mWifiDiagnostics.captureBugReportData( 6780 WifiDiagnostics.REPORT_REASON_UNEXPECTED_DISCONNECT); 6781 } 6782 config = getCurrentWifiConfiguration(); 6783 if (mWifiConfigManager.mEnableLinkDebouncing 6784 && mScreenOn 6785 && !isLinkDebouncing() 6786 && config != null 6787 && config.getNetworkSelectionStatus().isNetworkEnabled() 6788 && !mWifiConfigManager.isLastSelectedConfiguration(config) 6789 && (message.arg2 != 3 /* reason cannot be 3, i.e. locally generated */ 6790 || (lastRoam > 0 && lastRoam < 2000) /* unless driver is roaming */) 6791 && ((ScanResult.is24GHz(mWifiInfo.getFrequency()) 6792 && mWifiInfo.getRssi() > 6793 WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND) 6794 || (ScanResult.is5GHz(mWifiInfo.getFrequency()) 6795 && mWifiInfo.getRssi() > 6796 mWifiConfigManager.mThresholdQualifiedRssi5.get()))) { 6797 // Start de-bouncing the L2 disconnection: 6798 // this L2 disconnection might be spurious. 6799 // Hence we allow 4 seconds for the state machine to try 6800 // to reconnect, go thru the 6801 // roaming cycle and enter Obtaining IP address 6802 // before signalling the disconnect to ConnectivityService and L3 6803 startScanForConfiguration(getCurrentWifiConfiguration()); 6804 mIsLinkDebouncing = true; 6805 6806 sendMessageDelayed(obtainMessage(CMD_DELAYED_NETWORK_DISCONNECT, 6807 0, mLastNetworkId), LINK_FLAPPING_DEBOUNCE_MSEC); 6808 if (mVerboseLoggingEnabled) { 6809 log("NETWORK_DISCONNECTION_EVENT in connected state" 6810 + " BSSID=" + mWifiInfo.getBSSID() 6811 + " RSSI=" + mWifiInfo.getRssi() 6812 + " freq=" + mWifiInfo.getFrequency() 6813 + " reason=" + message.arg2 6814 + " -> debounce"); 6815 } 6816 return HANDLED; 6817 } else { 6818 if (mVerboseLoggingEnabled) { 6819 log("NETWORK_DISCONNECTION_EVENT in connected state" 6820 + " BSSID=" + mWifiInfo.getBSSID() 6821 + " RSSI=" + mWifiInfo.getRssi() 6822 + " freq=" + mWifiInfo.getFrequency() 6823 + " was debouncing=" + isLinkDebouncing() 6824 + " reason=" + message.arg2 6825 + " Network Selection Status=" + (config == null ? "Unavailable" 6826 : config.getNetworkSelectionStatus().getNetworkStatusString())); 6827 } 6828 } 6829 break; 6830 case CMD_AUTO_ROAM: 6831 // Clear the driver roam indication since we are attempting a framework roam 6832 mLastDriverRoamAttempt = 0; 6833 6834 /*<TODO> 2016-02-24 6835 Fix CMD_AUTO_ROAM to use the candidate (message.arg1) networkID, rather than 6836 the old networkID. 6837 The current code only handles roaming between BSSIDs on the same networkID, 6838 and will break for roams between different (but linked) networkIDs. This 6839 case occurs for DBDC roaming, and the CMD_AUTO_ROAM sent due to it will 6840 fail. 6841 */ 6842 /* Connect command coming from auto-join */ 6843 ScanResult candidate = (ScanResult)message.obj; 6844 String bssid = "any"; 6845 if (candidate != null) { 6846 bssid = candidate.BSSID; 6847 } 6848 int netId = message.arg1; 6849 if (netId == WifiConfiguration.INVALID_NETWORK_ID) { 6850 loge("AUTO_ROAM and no config, bail out..."); 6851 break; 6852 } else { 6853 config = mWifiConfigManager.getWifiConfiguration(netId); 6854 } 6855 6856 logd("CMD_AUTO_ROAM sup state " 6857 + mSupplicantStateTracker.getSupplicantStateName() 6858 + " my state " + getCurrentState().getName() 6859 + " nid=" + Integer.toString(netId) 6860 + " config " + config.configKey() 6861 + " roam=" + Integer.toString(message.arg2) 6862 + " to " + bssid 6863 + " targetRoamBSSID " + mTargetRoamBSSID); 6864 6865 setTargetBssid(config, bssid); 6866 mTargetNetworkId = netId; 6867 6868 /* Determine if this is a regular roam (between BSSIDs sharing the same SSID), 6869 or a DBDC roam (between 2.4 & 5GHz networks on different SSID's, but with 6870 matching 16 byte BSSID prefixes): 6871 */ 6872 WifiConfiguration currentConfig = getCurrentWifiConfiguration(); 6873 if (currentConfig != null && currentConfig.isLinked(config)) { 6874 // This is dual band roaming 6875 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 6876 WifiMetricsProto.ConnectionEvent.ROAM_DBDC); 6877 } else { 6878 // This is regular roaming 6879 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 6880 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 6881 } 6882 6883 if (deferForUserInput(message, netId, false)) { 6884 reportConnectionAttemptEnd( 6885 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 6886 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6887 break; 6888 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 6889 WifiConfiguration.USER_BANNED) { 6890 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6891 WifiManager.NOT_AUTHORIZED); 6892 reportConnectionAttemptEnd( 6893 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 6894 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6895 break; 6896 } 6897 6898 boolean ret = false; 6899 if (mLastNetworkId != netId) { 6900 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 6901 WifiConfiguration.UNKNOWN_UID) && mWifiNative.reconnect()) { 6902 ret = true; 6903 } 6904 } else { 6905 ret = mWifiNative.reassociate(); 6906 } 6907 if (ret) { 6908 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 6909 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 6910 6911 // replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 6912 mAutoRoaming = true; 6913 transitionTo(mRoamingState); 6914 6915 } else { 6916 loge("Failed to connect config: " + config + " netId: " + netId); 6917 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6918 WifiManager.ERROR); 6919 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6920 reportConnectionAttemptEnd( 6921 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 6922 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6923 break; 6924 } 6925 break; 6926 case CMD_START_IP_PACKET_OFFLOAD: { 6927 int slot = message.arg1; 6928 int intervalSeconds = message.arg2; 6929 KeepalivePacketData pkt = (KeepalivePacketData) message.obj; 6930 byte[] dstMac; 6931 try { 6932 InetAddress gateway = RouteInfo.selectBestRoute( 6933 mLinkProperties.getRoutes(), pkt.dstAddress).getGateway(); 6934 String dstMacStr = macAddressFromRoute(gateway.getHostAddress()); 6935 dstMac = macAddressFromString(dstMacStr); 6936 } catch (NullPointerException|IllegalArgumentException e) { 6937 loge("Can't find MAC address for next hop to " + pkt.dstAddress); 6938 mNetworkAgent.onPacketKeepaliveEvent(slot, 6939 ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 6940 break; 6941 } 6942 pkt.dstMac = dstMac; 6943 int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds); 6944 mNetworkAgent.onPacketKeepaliveEvent(slot, result); 6945 break; 6946 } 6947 default: 6948 return NOT_HANDLED; 6949 } 6950 return HANDLED; 6951 } 6952 6953 @Override 6954 public void exit() { 6955 logd("WifiStateMachine: Leaving Connected state"); 6956 if (mWifiConnectivityManager != null) { 6957 mWifiConnectivityManager.handleConnectionStateChanged( 6958 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 6959 } 6960 6961 mLastDriverRoamAttempt = 0; 6962 mWifiInjector.getWifiLastResortWatchdog().connectedStateTransition(false); 6963 } 6964 } 6965 6966 class DisconnectingState extends State { 6967 6968 @Override 6969 public void enter() { 6970 6971 if (mVerboseLoggingEnabled) { 6972 logd(" Enter DisconnectingState State screenOn=" + mScreenOn); 6973 } 6974 6975 // Make sure we disconnect: we enter this state prior to connecting to a new 6976 // network, waiting for either a DISCONNECT event or a SUPPLICANT_STATE_CHANGE 6977 // event which in this case will be indicating that supplicant started to associate. 6978 // In some cases supplicant doesn't ignore the connect requests (it might not 6979 // find the target SSID in its cache), 6980 // Therefore we end up stuck that state, hence the need for the watchdog. 6981 disconnectingWatchdogCount++; 6982 logd("Start Disconnecting Watchdog " + disconnectingWatchdogCount); 6983 sendMessageDelayed(obtainMessage(CMD_DISCONNECTING_WATCHDOG_TIMER, 6984 disconnectingWatchdogCount, 0), DISCONNECTING_GUARD_TIMER_MSEC); 6985 } 6986 6987 @Override 6988 public boolean processMessage(Message message) { 6989 logStateAndMessage(message, this); 6990 switch (message.what) { 6991 case CMD_SET_OPERATIONAL_MODE: 6992 if (message.arg1 != CONNECT_MODE) { 6993 deferMessage(message); 6994 } 6995 break; 6996 case CMD_START_SCAN: 6997 deferMessage(message); 6998 return HANDLED; 6999 case CMD_DISCONNECT: 7000 if (mVerboseLoggingEnabled) log("Ignore CMD_DISCONNECT when already disconnecting."); 7001 break; 7002 case CMD_DISCONNECTING_WATCHDOG_TIMER: 7003 if (disconnectingWatchdogCount == message.arg1) { 7004 if (mVerboseLoggingEnabled) log("disconnecting watchdog! -> disconnect"); 7005 handleNetworkDisconnect(); 7006 transitionTo(mDisconnectedState); 7007 } 7008 break; 7009 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 7010 /** 7011 * If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT 7012 * we have missed the network disconnection, transition to mDisconnectedState 7013 * and handle the rest of the events there 7014 */ 7015 deferMessage(message); 7016 handleNetworkDisconnect(); 7017 transitionTo(mDisconnectedState); 7018 break; 7019 default: 7020 return NOT_HANDLED; 7021 } 7022 return HANDLED; 7023 } 7024 } 7025 7026 class DisconnectedState extends State { 7027 @Override 7028 public void enter() { 7029 // We dont scan frequently if this is a temporary disconnect 7030 // due to p2p 7031 if (mTemporarilyDisconnectWifi) { 7032 p2pSendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 7033 return; 7034 } 7035 7036 if (mVerboseLoggingEnabled) { 7037 logd(" Enter DisconnectedState screenOn=" + mScreenOn); 7038 } 7039 7040 /** clear the roaming state, if we were roaming, we failed */ 7041 mAutoRoaming = false; 7042 7043 if (mWifiConnectivityManager != null) { 7044 mWifiConnectivityManager.handleConnectionStateChanged( 7045 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 7046 } 7047 7048 /** 7049 * If we have no networks saved, the supplicant stops doing the periodic scan. 7050 * The scans are useful to notify the user of the presence of an open network. 7051 * Note that these are not wake up scans. 7052 */ 7053 if (mNoNetworksPeriodicScan != 0 && !mP2pConnected.get() 7054 && mWifiConfigManager.getSavedNetworks().size() == 0) { 7055 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7056 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7057 } 7058 7059 mDisconnectedTimeStamp = mClock.getWallClockMillis(); 7060 } 7061 @Override 7062 public boolean processMessage(Message message) { 7063 boolean ret = HANDLED; 7064 7065 logStateAndMessage(message, this); 7066 7067 switch (message.what) { 7068 case CMD_NO_NETWORKS_PERIODIC_SCAN: 7069 if (mP2pConnected.get()) break; 7070 if (mNoNetworksPeriodicScan != 0 && message.arg1 == mPeriodicScanToken && 7071 mWifiConfigManager.getSavedNetworks().size() == 0) { 7072 startScan(UNKNOWN_SCAN_SOURCE, -1, null, WIFI_WORK_SOURCE); 7073 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7074 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7075 } 7076 break; 7077 case WifiManager.FORGET_NETWORK: 7078 case CMD_REMOVE_NETWORK: 7079 case CMD_REMOVE_APP_CONFIGURATIONS: 7080 case CMD_REMOVE_USER_CONFIGURATIONS: 7081 // Set up a delayed message here. After the forget/remove is handled 7082 // the handled delayed message will determine if there is a need to 7083 // scan and continue 7084 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7085 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7086 ret = NOT_HANDLED; 7087 break; 7088 case CMD_SET_OPERATIONAL_MODE: 7089 if (message.arg1 != CONNECT_MODE) { 7090 mOperationalMode = message.arg1; 7091 mWifiConfigManager.disableAllNetworksNative(); 7092 if (mOperationalMode == DISABLED_MODE) { 7093 transitionTo(mSupplicantStoppingState); 7094 } else if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 7095 p2pSendMessage(CMD_DISABLE_P2P_REQ); 7096 setWifiState(WIFI_STATE_DISABLED); 7097 transitionTo(mScanModeState); 7098 } else if (mOperationalMode == SCAN_ONLY_MODE) { 7099 transitionTo(mScanModeState); 7100 } 7101 } 7102 mWifiConfigManager. 7103 setAndEnableLastSelectedConfiguration( 7104 WifiConfiguration.INVALID_NETWORK_ID); 7105 break; 7106 case CMD_DISCONNECT: 7107 if (mVerboseLoggingEnabled) log("Ignore CMD_DISCONNECT when already disconnected."); 7108 break; 7109 /* Ignore network disconnect */ 7110 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7111 // Interpret this as an L2 connection failure 7112 break; 7113 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 7114 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 7115 if (mVerboseLoggingEnabled) { 7116 logd("SUPPLICANT_STATE_CHANGE_EVENT state=" + stateChangeResult.state + 7117 " -> state= " + WifiInfo.getDetailedStateOf(stateChangeResult.state) 7118 + " debouncing=" + isLinkDebouncing()); 7119 } 7120 setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state)); 7121 /* ConnectModeState does the rest of the handling */ 7122 ret = NOT_HANDLED; 7123 break; 7124 case CMD_START_SCAN: 7125 if (!checkOrDeferScanAllowed(message)) { 7126 // The scan request was rescheduled 7127 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 7128 return HANDLED; 7129 } 7130 7131 ret = NOT_HANDLED; 7132 break; 7133 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 7134 NetworkInfo info = (NetworkInfo) message.obj; 7135 mP2pConnected.set(info.isConnected()); 7136 if (mP2pConnected.get()) { 7137 int defaultInterval = mContext.getResources().getInteger( 7138 R.integer.config_wifi_scan_interval_p2p_connected); 7139 long scanIntervalMs = mFacade.getLongSetting(mContext, 7140 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, 7141 defaultInterval); 7142 mWifiNative.setScanInterval((int) scanIntervalMs/1000); 7143 } else if (mWifiConfigManager.getSavedNetworks().size() == 0) { 7144 if (mVerboseLoggingEnabled) log("Turn on scanning after p2p disconnected"); 7145 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7146 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7147 } 7148 break; 7149 case CMD_RECONNECT: 7150 case CMD_REASSOCIATE: 7151 if (mTemporarilyDisconnectWifi) { 7152 // Drop a third party reconnect/reassociate if STA is 7153 // temporarily disconnected for p2p 7154 break; 7155 } else { 7156 // ConnectModeState handles it 7157 ret = NOT_HANDLED; 7158 } 7159 break; 7160 case CMD_SCREEN_STATE_CHANGED: 7161 handleScreenStateChanged(message.arg1 != 0); 7162 break; 7163 default: 7164 ret = NOT_HANDLED; 7165 } 7166 return ret; 7167 } 7168 7169 @Override 7170 public void exit() { 7171 if (mWifiConnectivityManager != null) { 7172 mWifiConnectivityManager.handleConnectionStateChanged( 7173 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 7174 } 7175 } 7176 } 7177 7178 class WpsRunningState extends State { 7179 // Tracks the source to provide a reply 7180 private Message mSourceMessage; 7181 @Override 7182 public void enter() { 7183 mSourceMessage = Message.obtain(getCurrentMessage()); 7184 } 7185 @Override 7186 public boolean processMessage(Message message) { 7187 logStateAndMessage(message, this); 7188 7189 switch (message.what) { 7190 case WifiMonitor.WPS_SUCCESS_EVENT: 7191 // Ignore intermediate success, wait for full connection 7192 break; 7193 case WifiMonitor.NETWORK_CONNECTION_EVENT: 7194 replyToMessage(mSourceMessage, WifiManager.WPS_COMPLETED); 7195 mSourceMessage.recycle(); 7196 mSourceMessage = null; 7197 deferMessage(message); 7198 transitionTo(mDisconnectedState); 7199 break; 7200 case WifiMonitor.WPS_OVERLAP_EVENT: 7201 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 7202 WifiManager.WPS_OVERLAP_ERROR); 7203 mSourceMessage.recycle(); 7204 mSourceMessage = null; 7205 transitionTo(mDisconnectedState); 7206 break; 7207 case WifiMonitor.WPS_FAIL_EVENT: 7208 // Arg1 has the reason for the failure 7209 if ((message.arg1 != WifiManager.ERROR) || (message.arg2 != 0)) { 7210 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1); 7211 mSourceMessage.recycle(); 7212 mSourceMessage = null; 7213 transitionTo(mDisconnectedState); 7214 } else { 7215 if (mVerboseLoggingEnabled) { 7216 log("Ignore unspecified fail event during WPS connection"); 7217 } 7218 } 7219 break; 7220 case WifiMonitor.WPS_TIMEOUT_EVENT: 7221 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 7222 WifiManager.WPS_TIMED_OUT); 7223 mSourceMessage.recycle(); 7224 mSourceMessage = null; 7225 transitionTo(mDisconnectedState); 7226 break; 7227 case WifiManager.START_WPS: 7228 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS); 7229 break; 7230 case WifiManager.CANCEL_WPS: 7231 if (mWifiNative.cancelWps()) { 7232 replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED); 7233 } else { 7234 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR); 7235 } 7236 transitionTo(mDisconnectedState); 7237 break; 7238 /** 7239 * Defer all commands that can cause connections to a different network 7240 * or put the state machine out of connect mode 7241 */ 7242 case CMD_SET_OPERATIONAL_MODE: 7243 case WifiManager.CONNECT_NETWORK: 7244 case CMD_ENABLE_NETWORK: 7245 case CMD_RECONNECT: 7246 case CMD_REASSOCIATE: 7247 case CMD_ENABLE_ALL_NETWORKS: 7248 deferMessage(message); 7249 break; 7250 case CMD_AUTO_CONNECT: 7251 case CMD_AUTO_ROAM: 7252 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7253 return HANDLED; 7254 case CMD_START_SCAN: 7255 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7256 return HANDLED; 7257 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7258 if (mVerboseLoggingEnabled) log("Network connection lost"); 7259 handleNetworkDisconnect(); 7260 break; 7261 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 7262 if (mVerboseLoggingEnabled) { 7263 log("Ignore Assoc reject event during WPS Connection"); 7264 } 7265 break; 7266 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 7267 // Disregard auth failure events during WPS connection. The 7268 // EAP sequence is retried several times, and there might be 7269 // failures (especially for wps pin). We will get a WPS_XXX 7270 // event at the end of the sequence anyway. 7271 if (mVerboseLoggingEnabled) log("Ignore auth failure during WPS connection"); 7272 break; 7273 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 7274 // Throw away supplicant state changes when WPS is running. 7275 // We will start getting supplicant state changes once we get 7276 // a WPS success or failure 7277 break; 7278 default: 7279 return NOT_HANDLED; 7280 } 7281 return HANDLED; 7282 } 7283 7284 @Override 7285 public void exit() { 7286 mWifiConfigManager.enableAllNetworks(); 7287 mWifiConfigManager.loadConfiguredNetworks(); 7288 } 7289 } 7290 7291 class SoftApState extends State { 7292 private SoftApManager mSoftApManager; 7293 7294 private class SoftApListener implements SoftApManager.Listener { 7295 @Override 7296 public void onStateChanged(int state, int reason) { 7297 if (state == WIFI_AP_STATE_DISABLED) { 7298 sendMessage(CMD_AP_STOPPED); 7299 } else if (state == WIFI_AP_STATE_FAILED) { 7300 sendMessage(CMD_START_AP_FAILURE); 7301 } 7302 7303 setWifiApState(state, reason); 7304 } 7305 } 7306 7307 @Override 7308 public void enter() { 7309 final Message message = getCurrentMessage(); 7310 if (message.what != CMD_START_AP) { 7311 throw new RuntimeException("Illegal transition to SoftApState: " + message); 7312 } 7313 7314 IApInterface apInterface = setupDriverForSoftAp(); 7315 if (apInterface == null) { 7316 setWifiApState(WIFI_AP_STATE_FAILED, 7317 WifiManager.SAP_START_FAILURE_GENERAL); 7318 /** 7319 * Transition to InitialState to reset the 7320 * driver/HAL back to the initial state. 7321 */ 7322 transitionTo(mInitialState); 7323 return; 7324 } 7325 7326 WifiConfiguration config = (WifiConfiguration) message.obj; 7327 if (config == null) { 7328 /** 7329 * Configuration not provided in the command, fallback to use the current 7330 * configuration. 7331 */ 7332 config = mWifiApConfigStore.getApConfiguration(); 7333 } else { 7334 /* Update AP configuration. */ 7335 mWifiApConfigStore.setApConfiguration(config); 7336 } 7337 7338 checkAndSetConnectivityInstance(); 7339 mSoftApManager = mWifiInjector.makeSoftApManager( 7340 mWifiNative, mNwService, 7341 mCm, mCountryCode.getCountryCode(), 7342 mWifiApConfigStore.getAllowed2GChannel(), 7343 new SoftApListener(), apInterface); 7344 mSoftApManager.start(config); 7345 } 7346 7347 @Override 7348 public void exit() { 7349 mSoftApManager = null; 7350 } 7351 7352 @Override 7353 public boolean processMessage(Message message) { 7354 logStateAndMessage(message, this); 7355 7356 switch(message.what) { 7357 case CMD_START_AP: 7358 /* Ignore start command when it is starting/started. */ 7359 break; 7360 case CMD_STOP_AP: 7361 mSoftApManager.stop(); 7362 break; 7363 case CMD_START_AP_FAILURE: 7364 transitionTo(mInitialState); 7365 break; 7366 case CMD_AP_STOPPED: 7367 transitionTo(mInitialState); 7368 break; 7369 default: 7370 return NOT_HANDLED; 7371 } 7372 return HANDLED; 7373 } 7374 } 7375 7376 /** 7377 * State machine initiated requests can have replyTo set to null indicating 7378 * there are no recepients, we ignore those reply actions. 7379 */ 7380 private void replyToMessage(Message msg, int what) { 7381 if (msg.replyTo == null) return; 7382 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 7383 mReplyChannel.replyToMessage(msg, dstMsg); 7384 } 7385 7386 private void replyToMessage(Message msg, int what, int arg1) { 7387 if (msg.replyTo == null) return; 7388 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 7389 dstMsg.arg1 = arg1; 7390 mReplyChannel.replyToMessage(msg, dstMsg); 7391 } 7392 7393 private void replyToMessage(Message msg, int what, Object obj) { 7394 if (msg.replyTo == null) return; 7395 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 7396 dstMsg.obj = obj; 7397 mReplyChannel.replyToMessage(msg, dstMsg); 7398 } 7399 7400 /** 7401 * arg2 on the source message has a unique id that needs to be retained in replies 7402 * to match the request 7403 * <p>see WifiManager for details 7404 */ 7405 private Message obtainMessageWithWhatAndArg2(Message srcMsg, int what) { 7406 Message msg = Message.obtain(); 7407 msg.what = what; 7408 msg.arg2 = srcMsg.arg2; 7409 return msg; 7410 } 7411 7412 /** 7413 * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT 7414 * @param config Must have a WifiConfiguration object to succeed 7415 */ 7416 private void broadcastWifiCredentialChanged(int wifiCredentialEventType, 7417 WifiConfiguration config) { 7418 if (config != null && config.preSharedKey != null) { 7419 Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); 7420 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); 7421 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, 7422 wifiCredentialEventType); 7423 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT, 7424 android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE); 7425 } 7426 } 7427 7428 void handleGsmAuthRequest(SimAuthRequestData requestData) { 7429 if (targetWificonfiguration == null 7430 || targetWificonfiguration.networkId == requestData.networkId) { 7431 logd("id matches targetWifiConfiguration"); 7432 } else { 7433 logd("id does not match targetWifiConfiguration"); 7434 return; 7435 } 7436 7437 String response = 7438 TelephonyUtil.getGsmSimAuthResponse(requestData.data, getTelephonyManager()); 7439 if (response == null) { 7440 mWifiNative.simAuthFailedResponse(requestData.networkId); 7441 } else { 7442 logv("Supplicant Response -" + response); 7443 mWifiNative.simAuthResponse(requestData.networkId, "GSM-AUTH", response); 7444 } 7445 } 7446 7447 void handle3GAuthRequest(SimAuthRequestData requestData) { 7448 if (targetWificonfiguration == null 7449 || targetWificonfiguration.networkId == requestData.networkId) { 7450 logd("id matches targetWifiConfiguration"); 7451 } else { 7452 logd("id does not match targetWifiConfiguration"); 7453 return; 7454 } 7455 7456 SimAuthResponseData response = 7457 TelephonyUtil.get3GAuthResponse(requestData, getTelephonyManager()); 7458 if (response != null) { 7459 mWifiNative.simAuthResponse(requestData.networkId, response.type, response.response); 7460 } else { 7461 mWifiNative.umtsAuthFailedResponse(requestData.networkId); 7462 } 7463 } 7464 7465 /** 7466 * Automatically connect to the network specified 7467 * 7468 * @param networkId ID of the network to connect to 7469 * @param bssid BSSID of the network 7470 */ 7471 public void autoConnectToNetwork(int networkId, String bssid) { 7472 sendMessage(CMD_AUTO_CONNECT, networkId, 0, bssid); 7473 } 7474 7475 /** 7476 * Automatically roam to the network specified 7477 * 7478 * @param networkId ID of the network to roam to 7479 * @param scanResult scan result which identifies the network to roam to 7480 */ 7481 public void autoRoamToNetwork(int networkId, ScanResult scanResult) { 7482 sendMessage(CMD_AUTO_ROAM, networkId, 0, scanResult); 7483 } 7484 7485 /** 7486 * Dynamically turn on/off WifiConnectivityManager 7487 * 7488 * @param enabled true-enable; false-disable 7489 */ 7490 public void enableWifiConnectivityManager(boolean enabled) { 7491 sendMessage(CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER, enabled ? 1 : 0); 7492 } 7493 7494 /** 7495 * @param reason reason code from supplicant on network disconnected event 7496 * @return true if this is a suspicious disconnect 7497 */ 7498 static boolean unexpectedDisconnectedReason(int reason) { 7499 return reason == 2 // PREV_AUTH_NOT_VALID 7500 || reason == 6 // CLASS2_FRAME_FROM_NONAUTH_STA 7501 || reason == 7 // FRAME_FROM_NONASSOC_STA 7502 || reason == 8 // STA_HAS_LEFT 7503 || reason == 9 // STA_REQ_ASSOC_WITHOUT_AUTH 7504 || reason == 14 // MICHAEL_MIC_FAILURE 7505 || reason == 15 // 4WAY_HANDSHAKE_TIMEOUT 7506 || reason == 16 // GROUP_KEY_UPDATE_TIMEOUT 7507 || reason == 18 // GROUP_CIPHER_NOT_VALID 7508 || reason == 19 // PAIRWISE_CIPHER_NOT_VALID 7509 || reason == 23 // IEEE_802_1X_AUTH_FAILED 7510 || reason == 34; // DISASSOC_LOW_ACK 7511 } 7512 7513 /** 7514 * Update WifiMetrics before dumping 7515 */ 7516 void updateWifiMetrics() { 7517 int numSavedNetworks = mWifiConfigManager.getConfiguredNetworksSize(); 7518 int numOpenNetworks = 0; 7519 int numPersonalNetworks = 0; 7520 int numEnterpriseNetworks = 0; 7521 int numNetworksAddedByUser = 0; 7522 int numNetworksAddedByApps = 0; 7523 for (WifiConfiguration config : mWifiConfigManager.getSavedNetworks()) { 7524 if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { 7525 numOpenNetworks++; 7526 } else if (config.isEnterprise()) { 7527 numEnterpriseNetworks++; 7528 } else { 7529 numPersonalNetworks++; 7530 } 7531 if (config.selfAdded) { 7532 numNetworksAddedByUser++; 7533 } else { 7534 numNetworksAddedByApps++; 7535 } 7536 } 7537 mWifiMetrics.setNumSavedNetworks(numSavedNetworks); 7538 mWifiMetrics.setNumOpenNetworks(numOpenNetworks); 7539 mWifiMetrics.setNumPersonalNetworks(numPersonalNetworks); 7540 mWifiMetrics.setNumEnterpriseNetworks(numEnterpriseNetworks); 7541 mWifiMetrics.setNumNetworksAddedByUser(numNetworksAddedByUser); 7542 mWifiMetrics.setNumNetworksAddedByApps(numNetworksAddedByApps); 7543 7544 /* <TODO> decide how to access WifiServiecImpl.isLocationEnabled() or if to do it manually 7545 mWifiMetrics.setIsLocationEnabled(Settings.Secure.getInt( 7546 mContext.getContentResolver(), 7547 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) 7548 != Settings.Secure.LOCATION_MODE_OFF); 7549 */ 7550 7551 /* <TODO> decide how statemachine will access WifiSettingsStore 7552 mWifiMetrics.setIsScanningAlwaysEnabled(mSettingsStore.isScanningAlwaysAvailable()); 7553 */ 7554 } 7555 7556 private static String getLinkPropertiesSummary(LinkProperties lp) { 7557 List<String> attributes = new ArrayList<>(6); 7558 if (lp.hasIPv4Address()) { 7559 attributes.add("v4"); 7560 } 7561 if (lp.hasIPv4DefaultRoute()) { 7562 attributes.add("v4r"); 7563 } 7564 if (lp.hasIPv4DnsServer()) { 7565 attributes.add("v4dns"); 7566 } 7567 if (lp.hasGlobalIPv6Address()) { 7568 attributes.add("v6"); 7569 } 7570 if (lp.hasIPv6DefaultRoute()) { 7571 attributes.add("v6r"); 7572 } 7573 if (lp.hasIPv6DnsServer()) { 7574 attributes.add("v6dns"); 7575 } 7576 7577 return TextUtils.join(" ", attributes); 7578 } 7579 7580 private void wnmFrameReceived(WnmData event) { 7581 // %012x HS20-SUBSCRIPTION-REMEDIATION "%u %s", osu_method, url 7582 // %012x HS20-DEAUTH-IMMINENT-NOTICE "%u %u %s", code, reauth_delay, url 7583 7584 Intent intent = new Intent(WifiManager.PASSPOINT_WNM_FRAME_RECEIVED_ACTION); 7585 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 7586 7587 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_BSSID, event.getBssid()); 7588 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_URL, event.getUrl()); 7589 7590 if (event.isDeauthEvent()) { 7591 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_ESS, event.isEss()); 7592 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_DELAY, event.getDelay()); 7593 } else { 7594 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_METHOD, event.getMethod()); 7595 WifiConfiguration config = getCurrentWifiConfiguration(); 7596 if (config != null && config.FQDN != null) { 7597 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_PPOINT_MATCH, 7598 mWifiConfigManager.matchProviderWithCurrentNetwork(config.FQDN)); 7599 } 7600 } 7601 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 7602 } 7603 7604 /** 7605 * Gets the SSID from the WifiConfiguration pointed at by 'mTargetNetworkId' 7606 * This should match the network config framework is attempting to connect to. 7607 */ 7608 private String getTargetSsid() { 7609 WifiConfiguration currentConfig = mWifiConfigManager.getWifiConfiguration(mTargetNetworkId); 7610 if (currentConfig != null) { 7611 return currentConfig.SSID; 7612 } 7613 return null; 7614 } 7615 7616 private void p2pSendMessage(int what) { 7617 if (mWifiP2pChannel != null) { 7618 mWifiP2pChannel.sendMessage(what); 7619 } 7620 } 7621 7622 private void p2pSendMessage(int what, int arg1) { 7623 if (mWifiP2pChannel != null) { 7624 mWifiP2pChannel.sendMessage(what, arg1); 7625 } 7626 } 7627} 7628