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