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