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