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