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