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