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