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