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