WifiStateMachine.java revision 843ee4e8b0b3332e6f7403fe3d8346cbb991f9b8
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 Set<Integer> removedNetworkIds; 5398 logStateAndMessage(message, this); 5399 5400 switch (message.what) { 5401 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 5402 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_ASSOC_FAILURE); 5403 didBlackListBSSID = false; 5404 bssid = (String) message.obj; 5405 if (bssid == null || TextUtils.isEmpty(bssid)) { 5406 // If BSSID is null, use the target roam BSSID 5407 bssid = mTargetRoamBSSID; 5408 } 5409 if (bssid != null) { 5410 // If we have a BSSID, tell configStore to black list it 5411 if (mWifiConnectivityManager != null) { 5412 didBlackListBSSID = mWifiConnectivityManager.trackBssid(bssid, 5413 false); 5414 } 5415 } 5416 5417 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 5418 WifiConfiguration.NetworkSelectionStatus 5419 .DISABLED_ASSOCIATION_REJECTION); 5420 5421 mSupplicantStateTracker.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT); 5422 //If rejection occurred while Metrics is tracking a ConnnectionEvent, end it. 5423 reportConnectionAttemptEnd( 5424 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, 5425 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5426 mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(getTargetSsid(), 5427 bssid, 5428 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 5429 break; 5430 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 5431 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_AUTH_FAILURE); 5432 mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); 5433 if (mTargetNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 5434 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 5435 WifiConfiguration.NetworkSelectionStatus 5436 .DISABLED_AUTHENTICATION_FAILURE); 5437 } 5438 //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. 5439 reportConnectionAttemptEnd( 5440 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, 5441 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5442 mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(getTargetSsid(), 5443 mTargetRoamBSSID, 5444 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 5445 break; 5446 case WifiMonitor.SSID_TEMP_DISABLED: 5447 Log.e(TAG, "Supplicant SSID temporary disabled:" 5448 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 5449 mWifiConfigManager.updateNetworkSelectionStatus( 5450 message.arg1, 5451 WifiConfiguration.NetworkSelectionStatus 5452 .DISABLED_AUTHENTICATION_FAILURE); 5453 reportConnectionAttemptEnd( 5454 WifiMetrics.ConnectionEvent.FAILURE_SSID_TEMP_DISABLED, 5455 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5456 mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(getTargetSsid(), 5457 mTargetRoamBSSID, 5458 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 5459 break; 5460 case WifiMonitor.SSID_REENABLED: 5461 Log.d(TAG, "Supplicant SSID reenable:" 5462 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 5463 // Do not re-enable it in Quality Network Selection since framework has its own 5464 // Algorithm of disable/enable 5465 break; 5466 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5467 SupplicantState state = handleSupplicantStateChange(message); 5468 // A driver/firmware hang can now put the interface in a down state. 5469 // We detect the interface going down and recover from it 5470 if (!SupplicantState.isDriverActive(state)) { 5471 if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 5472 handleNetworkDisconnect(); 5473 } 5474 log("Detected an interface down, restart driver"); 5475 transitionTo(mDriverStoppedState); 5476 sendMessage(CMD_START_DRIVER); 5477 break; 5478 } 5479 5480 // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT 5481 // when authentication times out after a successful connection, 5482 // we can figure this from the supplicant state. If supplicant 5483 // state is DISCONNECTED, but the mNetworkInfo says we are not 5484 // disconnected, we need to handle a disconnection 5485 if (!linkDebouncing && state == SupplicantState.DISCONNECTED && 5486 mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 5487 if (DBG) log("Missed CTRL-EVENT-DISCONNECTED, disconnect"); 5488 handleNetworkDisconnect(); 5489 transitionTo(mDisconnectedState); 5490 } 5491 5492 // If we have COMPLETED a connection to a BSSID, start doing 5493 // DNAv4/DNAv6 -style probing for on-link neighbors of 5494 // interest (e.g. routers); harmless if none are configured. 5495 if (state == SupplicantState.COMPLETED) { 5496 mIpManager.confirmConfiguration(); 5497 } 5498 break; 5499 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 5500 if (message.arg1 == 1) { 5501 mWifiNative.disconnect(); 5502 mTemporarilyDisconnectWifi = true; 5503 } else { 5504 mWifiNative.reconnect(); 5505 mTemporarilyDisconnectWifi = false; 5506 } 5507 break; 5508 case CMD_ADD_OR_UPDATE_NETWORK: 5509 // Only the current foreground user can modify networks. 5510 if (!mWifiConfigManager.isCurrentUserProfile( 5511 UserHandle.getUserId(message.sendingUid))) { 5512 loge("Only the current foreground user can modify networks " 5513 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5514 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5515 replyToMessage(message, message.what, FAILURE); 5516 break; 5517 } 5518 5519 config = (WifiConfiguration) message.obj; 5520 5521 if (!recordUidIfAuthorized(config, message.sendingUid, 5522 /* onlyAnnotate */ false)) { 5523 logw("Not authorized to update network " 5524 + " config=" + config.SSID 5525 + " cnid=" + config.networkId 5526 + " uid=" + message.sendingUid); 5527 replyToMessage(message, message.what, FAILURE); 5528 break; 5529 } 5530 5531 int res = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 5532 if (res < 0) { 5533 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5534 } else { 5535 WifiConfiguration curConfig = getCurrentWifiConfiguration(); 5536 if (curConfig != null && config != null) { 5537 WifiConfiguration.NetworkSelectionStatus networkStatus = 5538 config.getNetworkSelectionStatus(); 5539 if (curConfig.priority < config.priority && networkStatus != null 5540 && !networkStatus.isNetworkPermanentlyDisabled()) { 5541 // Interpret this as a connect attempt 5542 // Set the last selected configuration so as to allow the system to 5543 // stick the last user choice without persisting the choice 5544 mWifiConfigManager.setAndEnableLastSelectedConfiguration(res); 5545 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 5546 boolean persist = mWifiConfigManager 5547 .checkConfigOverridePermission(message.sendingUid); 5548 if (mWifiConnectivityManager != null) { 5549 mWifiConnectivityManager.connectToUserSelectNetwork(res, 5550 persist); 5551 } 5552 5553 // Remember time of last connection attempt 5554 lastConnectAttemptTimestamp = System.currentTimeMillis(); 5555 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5556 5557 // As a courtesy to the caller, trigger a scan now 5558 startScan(ADD_OR_UPDATE_SOURCE, 0, null, WIFI_WORK_SOURCE); 5559 } 5560 } 5561 } 5562 replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK, res); 5563 break; 5564 case CMD_REMOVE_NETWORK: 5565 // Only the current foreground user can modify networks. 5566 if (!mWifiConfigManager.isCurrentUserProfile( 5567 UserHandle.getUserId(message.sendingUid))) { 5568 loge("Only the current foreground user can modify networks " 5569 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5570 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5571 replyToMessage(message, message.what, FAILURE); 5572 break; 5573 } 5574 netId = message.arg1; 5575 5576 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 5577 /* onlyAnnotate */ false)) { 5578 logw("Not authorized to remove network " 5579 + " cnid=" + netId 5580 + " uid=" + message.sendingUid); 5581 replyToMessage(message, message.what, FAILURE); 5582 break; 5583 } 5584 5585 ok = mWifiConfigManager.removeNetwork(message.arg1); 5586 if (!ok) { 5587 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5588 } 5589 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 5590 break; 5591 case CMD_ENABLE_NETWORK: 5592 // Only the current foreground user can modify networks. 5593 if (!mWifiConfigManager.isCurrentUserProfile( 5594 UserHandle.getUserId(message.sendingUid))) { 5595 loge("Only the current foreground user can modify networks " 5596 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5597 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5598 replyToMessage(message, message.what, FAILURE); 5599 break; 5600 } 5601 5602 boolean disableOthers = message.arg2 == 1; 5603 netId = message.arg1; 5604 config = mWifiConfigManager.getWifiConfiguration(netId); 5605 if (config == null) { 5606 loge("No network with id = " + netId); 5607 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5608 replyToMessage(message, message.what, FAILURE); 5609 break; 5610 } 5611 // disable other only means select this network, does not mean all other 5612 // networks need to be disabled 5613 if (disableOthers) { 5614 // Remember time of last connection attempt 5615 lastConnectAttemptTimestamp = System.currentTimeMillis(); 5616 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5617 } 5618 // Cancel auto roam requests 5619 autoRoamSetBSSID(netId, "any"); 5620 5621 ok = mWifiConfigManager.enableNetwork( 5622 config, disableOthers, message.sendingUid); 5623 if (!ok) { 5624 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5625 } else { 5626 if (disableOthers) { 5627 mTargetNetworkId = netId; 5628 } 5629 mWifiConnectivityManager.forceConnectivityScan(); 5630 } 5631 5632 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 5633 break; 5634 case CMD_ENABLE_ALL_NETWORKS: 5635 long time = android.os.SystemClock.elapsedRealtime(); 5636 if (time - mLastEnableAllNetworksTime > MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS) { 5637 mWifiConfigManager.enableAllNetworks(); 5638 mLastEnableAllNetworksTime = time; 5639 } 5640 break; 5641 case WifiManager.DISABLE_NETWORK: 5642 if (mWifiConfigManager.updateNetworkSelectionStatus(message.arg1, 5643 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER)) { 5644 replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED); 5645 } else { 5646 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5647 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 5648 WifiManager.ERROR); 5649 } 5650 break; 5651 case CMD_DISABLE_EPHEMERAL_NETWORK: 5652 config = mWifiConfigManager.disableEphemeralNetwork((String)message.obj); 5653 if (config != null) { 5654 if (config.networkId == mLastNetworkId) { 5655 // Disconnect and let autojoin reselect a new network 5656 sendMessage(CMD_DISCONNECT); 5657 } 5658 } 5659 break; 5660 case CMD_BLACKLIST_NETWORK: 5661 mWifiConfigManager.blackListBssid((String) message.obj); 5662 break; 5663 case CMD_CLEAR_BLACKLIST: 5664 mWifiConfigManager.clearBssidBlacklist(); 5665 break; 5666 case CMD_SAVE_CONFIG: 5667 ok = mWifiConfigManager.saveConfig(); 5668 5669 if (DBG) logd("did save config " + ok); 5670 replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); 5671 5672 // Inform the backup manager about a data change 5673 mBackupManagerProxy.notifyDataChanged(); 5674 break; 5675 case CMD_GET_CONFIGURED_NETWORKS: 5676 replyToMessage(message, message.what, 5677 mWifiConfigManager.getSavedNetworks()); 5678 break; 5679 case WifiMonitor.SUP_REQUEST_IDENTITY: 5680 int networkId = message.arg2; 5681 boolean identitySent = false; 5682 int eapMethod = WifiEnterpriseConfig.Eap.NONE; 5683 5684 if (targetWificonfiguration != null 5685 && targetWificonfiguration.enterpriseConfig != null) { 5686 eapMethod = targetWificonfiguration.enterpriseConfig.getEapMethod(); 5687 } 5688 5689 // For SIM & AKA/AKA' EAP method Only, get identity from ICC 5690 if (targetWificonfiguration != null 5691 && targetWificonfiguration.networkId == networkId 5692 && (targetWificonfiguration.allowedKeyManagement 5693 .get(WifiConfiguration.KeyMgmt.IEEE8021X) 5694 || targetWificonfiguration.allowedKeyManagement 5695 .get(WifiConfiguration.KeyMgmt.WPA_EAP)) 5696 && TelephonyUtil.isSimEapMethod(eapMethod)) { 5697 String identity = TelephonyUtil.getSimIdentity(mContext, eapMethod); 5698 if (identity != null) { 5699 mWifiNative.simIdentityResponse(networkId, identity); 5700 identitySent = true; 5701 } 5702 } 5703 if (!identitySent) { 5704 // Supplicant lacks credentials to connect to that network, hence black list 5705 ssid = (String) message.obj; 5706 if (targetWificonfiguration != null && ssid != null 5707 && targetWificonfiguration.SSID != null 5708 && targetWificonfiguration.SSID.equals("\"" + ssid + "\"")) { 5709 mWifiConfigManager.updateNetworkSelectionStatus(targetWificonfiguration, 5710 WifiConfiguration.NetworkSelectionStatus 5711 .DISABLED_AUTHENTICATION_NO_CREDENTIALS); 5712 } 5713 // Disconnect now, as we don't have any way to fullfill 5714 // the supplicant request. 5715 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 5716 WifiConfiguration.INVALID_NETWORK_ID); 5717 mWifiNative.disconnect(); 5718 } 5719 break; 5720 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 5721 logd("Received SUP_REQUEST_SIM_AUTH"); 5722 SimAuthRequestData requestData = (SimAuthRequestData) message.obj; 5723 if (requestData != null) { 5724 if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) { 5725 handleGsmAuthRequest(requestData); 5726 } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA 5727 || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) { 5728 handle3GAuthRequest(requestData); 5729 } 5730 } else { 5731 loge("Invalid sim auth request"); 5732 } 5733 break; 5734 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 5735 replyToMessage(message, message.what, 5736 mWifiConfigManager.getPrivilegedSavedNetworks()); 5737 break; 5738 case CMD_GET_MATCHING_CONFIG: 5739 replyToMessage(message, message.what, 5740 mWifiConfigManager.getMatchingConfig((ScanResult)message.obj)); 5741 break; 5742 case CMD_RECONNECT: 5743 if (mWifiConnectivityManager != null) { 5744 mWifiConnectivityManager.forceConnectivityScan(); 5745 } 5746 break; 5747 case CMD_REASSOCIATE: 5748 lastConnectAttemptTimestamp = System.currentTimeMillis(); 5749 mWifiNative.reassociate(); 5750 break; 5751 case CMD_RELOAD_TLS_AND_RECONNECT: 5752 if (mWifiConfigManager.needsUnlockedKeyStore()) { 5753 logd("Reconnecting to give a chance to un-connected TLS networks"); 5754 mWifiNative.disconnect(); 5755 lastConnectAttemptTimestamp = System.currentTimeMillis(); 5756 mWifiNative.reconnect(); 5757 } 5758 break; 5759 case CMD_AUTO_ROAM: 5760 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5761 return HANDLED; 5762 case CMD_AUTO_CONNECT: 5763 /* Work Around: wpa_supplicant can get in a bad state where it returns a non 5764 * associated status to the STATUS command but somehow-someplace still thinks 5765 * it is associated and thus will ignore select/reconnect command with 5766 * following message: 5767 * "Already associated with the selected network - do nothing" 5768 * 5769 * Hence, sends a disconnect to supplicant first. 5770 */ 5771 didDisconnect = false; 5772 if (getCurrentState() != mDisconnectedState) { 5773 /** Supplicant will ignore the reconnect if we are currently associated, 5774 * hence trigger a disconnect 5775 */ 5776 didDisconnect = true; 5777 mWifiNative.disconnect(); 5778 } 5779 5780 /* connect command coming from auto-join */ 5781 netId = message.arg1; 5782 mTargetNetworkId = netId; 5783 mTargetRoamBSSID = (String) message.obj; 5784 config = mWifiConfigManager.getWifiConfiguration(netId); 5785 logd("CMD_AUTO_CONNECT sup state " 5786 + mSupplicantStateTracker.getSupplicantStateName() 5787 + " my state " + getCurrentState().getName() 5788 + " nid=" + Integer.toString(netId) 5789 + " roam=" + Boolean.toString(mAutoRoaming)); 5790 if (config == null) { 5791 loge("AUTO_CONNECT and no config, bail out..."); 5792 break; 5793 } 5794 5795 /* Make sure we cancel any previous roam request */ 5796 setTargetBssid(config, mTargetRoamBSSID); 5797 5798 /* Save the network config */ 5799 logd("CMD_AUTO_CONNECT will save config -> " + config.SSID 5800 + " nid=" + Integer.toString(netId)); 5801 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 5802 netId = result.getNetworkId(); 5803 logd("CMD_AUTO_CONNECT did save config -> " 5804 + " nid=" + Integer.toString(netId)); 5805 5806 // Since we updated the config,read it back from config store: 5807 config = mWifiConfigManager.getWifiConfiguration(netId); 5808 if (config == null) { 5809 loge("CMD_AUTO_CONNECT couldn't update the config, got null config"); 5810 break; 5811 } 5812 if (netId != config.networkId) { 5813 loge("CMD_AUTO_CONNECT couldn't update the config, want" 5814 + " nid=" + Integer.toString(netId) + " but got" + config.networkId); 5815 break; 5816 } 5817 5818 if (deferForUserInput(message, netId, false)) { 5819 break; 5820 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 5821 WifiConfiguration.USER_BANNED) { 5822 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5823 WifiManager.NOT_AUTHORIZED); 5824 break; 5825 } 5826 5827 // If we're autojoining a network that the user or an app explicitly selected, 5828 // keep track of the UID that selected it. 5829 // TODO(b/26786318): Keep track of the lastSelectedConfiguration and the 5830 // lastConnectUid on a per-user basis. 5831 int lastConnectUid = WifiConfiguration.UNKNOWN_UID; 5832 5833 //Start a new ConnectionEvent due to auto_connect, assume we are connecting 5834 //between different networks due to QNS, setting ROAM_UNRELATED 5835 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 5836 WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); 5837 if (!didDisconnect) { 5838 //If we were originally disconnected, then this was not any kind of ROAM 5839 mWifiMetrics.setConnectionEventRoamType( 5840 WifiMetricsProto.ConnectionEvent.ROAM_NONE); 5841 } 5842 //Determine if this CONNECTION is for a user selection 5843 if (mWifiConfigManager.isLastSelectedConfiguration(config) 5844 && mWifiConfigManager.isCurrentUserProfile( 5845 UserHandle.getUserId(config.lastConnectUid))) { 5846 lastConnectUid = config.lastConnectUid; 5847 mWifiMetrics.setConnectionEventRoamType( 5848 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED); 5849 } 5850 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 5851 lastConnectUid) && mWifiNative.reconnect()) { 5852 lastConnectAttemptTimestamp = System.currentTimeMillis(); 5853 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 5854 config = mWifiConfigManager.getWifiConfiguration(netId); 5855 if (config != null 5856 && !mWifiConfigManager.isLastSelectedConfiguration(config)) { 5857 // If we autojoined a different config than the user selected one, 5858 // it means we could not see the last user selection, 5859 // or that the last user selection was faulty and ended up blacklisted 5860 // for some reason (in which case the user is notified with an error 5861 // message in the Wifi picker), and thus we managed to auto-join away 5862 // from the selected config. -> in that case we need to forget 5863 // the selection because we don't want to abruptly switch back to it. 5864 // 5865 // Note that the user selection is also forgotten after a period of time 5866 // during which the device has been disconnected. 5867 // The default value is 30 minutes : see the code path at bottom of 5868 // setScanResults() function. 5869 mWifiConfigManager. 5870 setAndEnableLastSelectedConfiguration( 5871 WifiConfiguration.INVALID_NETWORK_ID); 5872 } 5873 mAutoRoaming = false; 5874 if (isRoaming() || linkDebouncing) { 5875 transitionTo(mRoamingState); 5876 } else if (didDisconnect) { 5877 transitionTo(mDisconnectingState); 5878 } 5879 } else { 5880 loge("Failed to connect config: " + config + " netId: " + netId); 5881 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5882 WifiManager.ERROR); 5883 reportConnectionAttemptEnd( 5884 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 5885 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5886 break; 5887 } 5888 break; 5889 case CMD_REMOVE_APP_CONFIGURATIONS: 5890 removedNetworkIds = 5891 mWifiConfigManager.removeNetworksForApp((ApplicationInfo) message.obj); 5892 if (removedNetworkIds.contains(mTargetNetworkId) || 5893 removedNetworkIds.contains(mLastNetworkId)) { 5894 // Disconnect and let autojoin reselect a new network. 5895 sendMessage(CMD_DISCONNECT); 5896 } 5897 break; 5898 case CMD_REMOVE_USER_CONFIGURATIONS: 5899 removedNetworkIds = 5900 mWifiConfigManager.removeNetworksForUser((Integer) message.arg1); 5901 if (removedNetworkIds.contains(mTargetNetworkId) || 5902 removedNetworkIds.contains(mLastNetworkId)) { 5903 // Disconnect and let autojoin reselect a new network. 5904 sendMessage(CMD_DISCONNECT); 5905 } 5906 break; 5907 case WifiManager.CONNECT_NETWORK: 5908 // Only the current foreground user and System UI (which runs as user 0 but acts 5909 // on behalf of the current foreground user) can modify networks. 5910 if (!mWifiConfigManager.isCurrentUserProfile( 5911 UserHandle.getUserId(message.sendingUid)) && 5912 message.sendingUid != mSystemUiUid) { 5913 loge("Only the current foreground user can modify networks " 5914 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 5915 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 5916 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5917 WifiManager.NOT_AUTHORIZED); 5918 break; 5919 } 5920 5921 /** 5922 * The connect message can contain a network id passed as arg1 on message or 5923 * or a config passed as obj on message. 5924 * For a new network, a config is passed to create and connect. 5925 * For an existing network, a network id is passed 5926 */ 5927 netId = message.arg1; 5928 config = (WifiConfiguration) message.obj; 5929 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5930 boolean updatedExisting = false; 5931 5932 /* Save the network config */ 5933 if (config != null) { 5934 // When connecting to an access point, WifiStateMachine wants to update the 5935 // relevant config with administrative data. This update should not be 5936 // considered a 'real' update, therefore lockdown by Device Owner must be 5937 // disregarded. 5938 if (!recordUidIfAuthorized(config, message.sendingUid, 5939 /* onlyAnnotate */ true)) { 5940 logw("Not authorized to update network " 5941 + " config=" + config.SSID 5942 + " cnid=" + config.networkId 5943 + " uid=" + message.sendingUid); 5944 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5945 WifiManager.NOT_AUTHORIZED); 5946 break; 5947 } 5948 String configKey = config.configKey(true /* allowCached */); 5949 WifiConfiguration savedConfig = 5950 mWifiConfigManager.getWifiConfiguration(configKey); 5951 if (savedConfig != null) { 5952 // There is an existing config with this netId, but it wasn't exposed 5953 // (either AUTO_JOIN_DELETED or ephemeral; see WifiConfigManager# 5954 // getConfiguredNetworks). Remove those bits and update the config. 5955 config = savedConfig; 5956 logd("CONNECT_NETWORK updating existing config with id=" + 5957 config.networkId + " configKey=" + configKey); 5958 config.ephemeral = false; 5959 mWifiConfigManager.updateNetworkSelectionStatus(config, 5960 WifiConfiguration.NetworkSelectionStatus 5961 .NETWORK_SELECTION_ENABLE); 5962 updatedExisting = true; 5963 } 5964 5965 result = mWifiConfigManager.saveNetwork(config, message.sendingUid); 5966 netId = result.getNetworkId(); 5967 } 5968 config = mWifiConfigManager.getWifiConfiguration(netId); 5969 if (config == null) { 5970 logd("CONNECT_NETWORK no config for id=" + Integer.toString(netId) + " " 5971 + mSupplicantStateTracker.getSupplicantStateName() + " my state " 5972 + getCurrentState().getName()); 5973 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5974 WifiManager.ERROR); 5975 break; 5976 } 5977 mTargetNetworkId = netId; 5978 autoRoamSetBSSID(netId, "any"); 5979 if (message.sendingUid == Process.WIFI_UID 5980 || message.sendingUid == Process.SYSTEM_UID) { 5981 // As a sanity measure, clear the BSSID in the supplicant network block. 5982 // If system or Wifi Settings want to connect, they will not 5983 // specify the BSSID. 5984 // If an app however had added a BSSID to this configuration, and the BSSID 5985 // was wrong, Then we would forever fail to connect until that BSSID 5986 // is cleaned up. 5987 clearConfigBSSID(config, "CONNECT_NETWORK"); 5988 } 5989 5990 if (deferForUserInput(message, netId, true)) { 5991 break; 5992 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 5993 WifiConfiguration.USER_BANNED) { 5994 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5995 WifiManager.NOT_AUTHORIZED); 5996 break; 5997 } 5998 5999 mAutoRoaming = false; 6000 6001 /* Tell network selection the user did try to connect to that network if from 6002 settings */ 6003 boolean persist = 6004 mWifiConfigManager.checkConfigOverridePermission(message.sendingUid); 6005 6006 6007 mWifiConfigManager.setAndEnableLastSelectedConfiguration(netId); 6008 if (mWifiConnectivityManager != null) { 6009 mWifiConnectivityManager.connectToUserSelectNetwork(netId, persist); 6010 } 6011 didDisconnect = false; 6012 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 6013 && mLastNetworkId != netId) { 6014 /** Supplicant will ignore the reconnect if we are currently associated, 6015 * hence trigger a disconnect 6016 */ 6017 didDisconnect = true; 6018 mWifiNative.disconnect(); 6019 } 6020 6021 //Start a new ConnectionEvent due to connect_network, this is always user 6022 //selected 6023 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 6024 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED); 6025 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ true, 6026 message.sendingUid) && mWifiNative.reconnect()) { 6027 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6028 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 6029 6030 /* The state tracker handles enabling networks upon completion/failure */ 6031 mSupplicantStateTracker.sendMessage(WifiManager.CONNECT_NETWORK); 6032 replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 6033 if (didDisconnect) { 6034 /* Expect a disconnection from the old connection */ 6035 transitionTo(mDisconnectingState); 6036 } else if (updatedExisting && getCurrentState() == mConnectedState && 6037 getCurrentWifiConfiguration().networkId == netId) { 6038 // Update the current set of network capabilities, but stay in the 6039 // current state. 6040 updateCapabilities(config); 6041 } else { 6042 /** 6043 * Directly go to disconnected state where we 6044 * process the connection events from supplicant 6045 */ 6046 transitionTo(mDisconnectedState); 6047 } 6048 } else { 6049 loge("Failed to connect config: " + config + " netId: " + netId); 6050 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6051 WifiManager.ERROR); 6052 reportConnectionAttemptEnd( 6053 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 6054 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6055 break; 6056 } 6057 break; 6058 case WifiManager.SAVE_NETWORK: 6059 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6060 // Fall thru 6061 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 6062 // Only the current foreground user can modify networks. 6063 if (!mWifiConfigManager.isCurrentUserProfile( 6064 UserHandle.getUserId(message.sendingUid))) { 6065 loge("Only the current foreground user can modify networks " 6066 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 6067 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6068 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6069 WifiManager.NOT_AUTHORIZED); 6070 break; 6071 } 6072 6073 lastSavedConfigurationAttempt = null; // Used for debug 6074 config = (WifiConfiguration) message.obj; 6075 if (config == null) { 6076 loge("ERROR: SAVE_NETWORK with null configuration" 6077 + mSupplicantStateTracker.getSupplicantStateName() 6078 + " my state " + getCurrentState().getName()); 6079 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6080 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6081 WifiManager.ERROR); 6082 break; 6083 } 6084 lastSavedConfigurationAttempt = new WifiConfiguration(config); 6085 int nid = config.networkId; 6086 logd("SAVE_NETWORK id=" + Integer.toString(nid) 6087 + " config=" + config.SSID 6088 + " nid=" + config.networkId 6089 + " supstate=" + mSupplicantStateTracker.getSupplicantStateName() 6090 + " my state " + getCurrentState().getName()); 6091 6092 // Only record the uid if this is user initiated 6093 boolean checkUid = (message.what == WifiManager.SAVE_NETWORK); 6094 if (checkUid && !recordUidIfAuthorized(config, message.sendingUid, 6095 /* onlyAnnotate */ false)) { 6096 logw("Not authorized to update network " 6097 + " config=" + config.SSID 6098 + " cnid=" + config.networkId 6099 + " uid=" + message.sendingUid); 6100 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6101 WifiManager.NOT_AUTHORIZED); 6102 break; 6103 } 6104 6105 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 6106 if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) { 6107 if (mWifiInfo.getNetworkId() == result.getNetworkId()) { 6108 if (result.hasIpChanged()) { 6109 // The currently connection configuration was changed 6110 // We switched from DHCP to static or from static to DHCP, or the 6111 // static IP address has changed. 6112 log("Reconfiguring IP on connection"); 6113 // TODO: clear addresses and disable IPv6 6114 // to simplify obtainingIpState. 6115 transitionTo(mObtainingIpState); 6116 } 6117 if (result.hasProxyChanged()) { 6118 log("Reconfiguring proxy on connection"); 6119 mIpManager.setHttpProxy( 6120 mWifiConfigManager.getProxyProperties(mLastNetworkId)); 6121 } 6122 } 6123 replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED); 6124 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 6125 6126 if (DBG) { 6127 logd("Success save network nid=" 6128 + Integer.toString(result.getNetworkId())); 6129 } 6130 6131 /** 6132 * If the command comes from WifiManager, then 6133 * tell autojoin the user did try to modify and save that network, 6134 * and interpret the SAVE_NETWORK as a request to connect 6135 */ 6136 boolean user = message.what == WifiManager.SAVE_NETWORK; 6137 6138 // Did this connect come from settings 6139 boolean persistConnect = 6140 mWifiConfigManager.checkConfigOverridePermission( 6141 message.sendingUid); 6142 6143 if (user) { 6144 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 6145 mWifiConfigManager.writeKnownNetworkHistory(); 6146 } 6147 6148 if (mWifiConnectivityManager != null) { 6149 mWifiConnectivityManager.connectToUserSelectNetwork( 6150 result.getNetworkId(), persistConnect); 6151 } 6152 } else { 6153 loge("Failed to save network"); 6154 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6155 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6156 WifiManager.ERROR); 6157 } 6158 break; 6159 case WifiManager.FORGET_NETWORK: 6160 // Only the current foreground user can modify networks. 6161 if (!mWifiConfigManager.isCurrentUserProfile( 6162 UserHandle.getUserId(message.sendingUid))) { 6163 loge("Only the current foreground user can modify networks " 6164 + " currentUserId=" + mWifiConfigManager.getCurrentUserId() 6165 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6166 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 6167 WifiManager.NOT_AUTHORIZED); 6168 break; 6169 } 6170 6171 // Debug only, remember last configuration that was forgotten 6172 WifiConfiguration toRemove 6173 = mWifiConfigManager.getWifiConfiguration(message.arg1); 6174 if (toRemove == null) { 6175 lastForgetConfigurationAttempt = null; 6176 } else { 6177 lastForgetConfigurationAttempt = new WifiConfiguration(toRemove); 6178 } 6179 // check that the caller owns this network 6180 netId = message.arg1; 6181 6182 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 6183 /* onlyAnnotate */ false)) { 6184 logw("Not authorized to forget network " 6185 + " cnid=" + netId 6186 + " uid=" + message.sendingUid); 6187 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 6188 WifiManager.NOT_AUTHORIZED); 6189 break; 6190 } 6191 6192 if (mWifiConfigManager.forgetNetwork(message.arg1)) { 6193 replyToMessage(message, WifiManager.FORGET_NETWORK_SUCCEEDED); 6194 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, 6195 (WifiConfiguration) message.obj); 6196 } else { 6197 loge("Failed to forget network"); 6198 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 6199 WifiManager.ERROR); 6200 } 6201 break; 6202 case WifiManager.START_WPS: 6203 WpsInfo wpsInfo = (WpsInfo) message.obj; 6204 WpsResult wpsResult; 6205 switch (wpsInfo.setup) { 6206 case WpsInfo.PBC: 6207 wpsResult = mWifiConfigManager.startWpsPbc(wpsInfo); 6208 break; 6209 case WpsInfo.KEYPAD: 6210 wpsResult = mWifiConfigManager.startWpsWithPinFromAccessPoint(wpsInfo); 6211 break; 6212 case WpsInfo.DISPLAY: 6213 wpsResult = mWifiConfigManager.startWpsWithPinFromDevice(wpsInfo); 6214 break; 6215 default: 6216 wpsResult = new WpsResult(Status.FAILURE); 6217 loge("Invalid setup for WPS"); 6218 break; 6219 } 6220 mWifiConfigManager.setAndEnableLastSelectedConfiguration 6221 (WifiConfiguration.INVALID_NETWORK_ID); 6222 if (wpsResult.status == Status.SUCCESS) { 6223 replyToMessage(message, WifiManager.START_WPS_SUCCEEDED, wpsResult); 6224 transitionTo(mWpsRunningState); 6225 } else { 6226 loge("Failed to start WPS with config " + wpsInfo.toString()); 6227 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR); 6228 } 6229 break; 6230 case CMD_ASSOCIATED_BSSID: 6231 // This is where we can confirm the connection BSSID. Use it to find the 6232 // right ScanDetail to populate metrics. 6233 String someBssid = (String) message.obj; 6234 if (someBssid != null) { 6235 //Get the config associated with this connection attempt 6236 WifiConfiguration someConf = 6237 mWifiConfigManager.getWifiConfiguration(mTargetNetworkId); 6238 // Get the ScanDetail associated with this BSSID 6239 ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCache( 6240 someConf); 6241 if (scanDetailCache != null) { 6242 mWifiMetrics.setConnectionScanDetail(scanDetailCache.getScanDetail( 6243 someBssid)); 6244 } 6245 } 6246 return NOT_HANDLED; 6247 case WifiMonitor.NETWORK_CONNECTION_EVENT: 6248 if (DBG) log("Network connection established"); 6249 mLastNetworkId = message.arg1; 6250 mLastBssid = (String) message.obj; 6251 6252 mWifiInfo.setBSSID(mLastBssid); 6253 mWifiInfo.setNetworkId(mLastNetworkId); 6254 mWifiQualifiedNetworkSelector 6255 .enableBssidForQualityNetworkSelection(mLastBssid, true); 6256 sendNetworkStateChangeBroadcast(mLastBssid); 6257 transitionTo(mObtainingIpState); 6258 break; 6259 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6260 // Calling handleNetworkDisconnect here is redundant because we might already 6261 // have called it when leaving L2ConnectedState to go to disconnecting state 6262 // or thru other path 6263 // We should normally check the mWifiInfo or mLastNetworkId so as to check 6264 // if they are valid, and only in this case call handleNEtworkDisconnect, 6265 // TODO: this should be fixed for a L MR release 6266 // The side effect of calling handleNetworkDisconnect twice is that a bunch of 6267 // idempotent commands are executed twice (stopping Dhcp, enabling the SPS mode 6268 // at the chip etc... 6269 if (DBG) log("ConnectModeState: Network connection lost "); 6270 handleNetworkDisconnect(); 6271 transitionTo(mDisconnectedState); 6272 break; 6273 case CMD_ADD_PASSPOINT_MO: 6274 res = mWifiConfigManager.addPasspointManagementObject((String) message.obj); 6275 replyToMessage(message, message.what, res); 6276 break; 6277 case CMD_MODIFY_PASSPOINT_MO: 6278 if (message.obj != null) { 6279 Bundle bundle = (Bundle) message.obj; 6280 ArrayList<PasspointManagementObjectDefinition> mos = 6281 bundle.getParcelableArrayList("MOS"); 6282 res = mWifiConfigManager.modifyPasspointMo(bundle.getString("FQDN"), mos); 6283 } else { 6284 res = 0; 6285 } 6286 replyToMessage(message, message.what, res); 6287 6288 break; 6289 case CMD_QUERY_OSU_ICON: 6290 if (mWifiConfigManager.queryPasspointIcon( 6291 ((Bundle) message.obj).getLong("BSSID"), 6292 ((Bundle) message.obj).getString("FILENAME"))) { 6293 res = 1; 6294 } else { 6295 res = 0; 6296 } 6297 replyToMessage(message, message.what, res); 6298 break; 6299 case CMD_MATCH_PROVIDER_NETWORK: 6300 res = mWifiConfigManager.matchProviderWithCurrentNetwork((String) message.obj); 6301 replyToMessage(message, message.what, res); 6302 break; 6303 default: 6304 return NOT_HANDLED; 6305 } 6306 return HANDLED; 6307 } 6308 } 6309 6310 private void updateCapabilities(WifiConfiguration config) { 6311 NetworkCapabilities networkCapabilities = new NetworkCapabilities(mDfltNetworkCapabilities); 6312 if (config != null) { 6313 if (config.ephemeral) { 6314 networkCapabilities.removeCapability( 6315 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 6316 } else { 6317 networkCapabilities.addCapability( 6318 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 6319 } 6320 6321 networkCapabilities.setSignalStrength( 6322 (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI) 6323 ? mWifiInfo.getRssi() 6324 : NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED); 6325 } 6326 6327 if (mWifiInfo.getMeteredHint()) { 6328 networkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 6329 } 6330 6331 mNetworkAgent.sendNetworkCapabilities(networkCapabilities); 6332 } 6333 6334 private class WifiNetworkAgent extends NetworkAgent { 6335 public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, 6336 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { 6337 super(l, c, TAG, ni, nc, lp, score, misc); 6338 } 6339 protected void unwanted() { 6340 // Ignore if we're not the current networkAgent. 6341 if (this != mNetworkAgent) return; 6342 if (DBG) log("WifiNetworkAgent -> Wifi unwanted score " 6343 + Integer.toString(mWifiInfo.score)); 6344 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT); 6345 } 6346 6347 @Override 6348 protected void networkStatus(int status, String redirectUrl) { 6349 if (this != mNetworkAgent) return; 6350 if (status == NetworkAgent.INVALID_NETWORK) { 6351 if (DBG) log("WifiNetworkAgent -> Wifi networkStatus invalid, score=" 6352 + Integer.toString(mWifiInfo.score)); 6353 unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED); 6354 } else if (status == NetworkAgent.VALID_NETWORK) { 6355 if (DBG) { 6356 log("WifiNetworkAgent -> Wifi networkStatus valid, score= " 6357 + Integer.toString(mWifiInfo.score)); 6358 } 6359 doNetworkStatus(status); 6360 } 6361 } 6362 6363 @Override 6364 protected void saveAcceptUnvalidated(boolean accept) { 6365 if (this != mNetworkAgent) return; 6366 WifiStateMachine.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0); 6367 } 6368 6369 @Override 6370 protected void startPacketKeepalive(Message msg) { 6371 WifiStateMachine.this.sendMessage( 6372 CMD_START_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 6373 } 6374 6375 @Override 6376 protected void stopPacketKeepalive(Message msg) { 6377 WifiStateMachine.this.sendMessage( 6378 CMD_STOP_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 6379 } 6380 6381 @Override 6382 protected void setSignalStrengthThresholds(int[] thresholds) { 6383 // 0. If there are no thresholds, or if the thresholds are invalid, stop RSSI monitoring. 6384 // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and 6385 // MAX_VALUE at the start/end of the thresholds array if necessary. 6386 // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware 6387 // event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then 6388 // re-arm the hardware event. This needs to be done on the state machine thread to 6389 // avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one 6390 // sent in the NetworkCapabilities) must be the one received from the hardware event 6391 // received, or we might skip callbacks. 6392 // 3. Ensure that when we disconnect, RSSI monitoring is stopped. 6393 log("Received signal strength thresholds: " + Arrays.toString(thresholds)); 6394 if (thresholds.length == 0) { 6395 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 6396 mWifiInfo.getRssi()); 6397 return; 6398 } 6399 int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2); 6400 rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE; 6401 rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE; 6402 Arrays.sort(rssiVals); 6403 byte[] rssiRange = new byte[rssiVals.length]; 6404 for (int i = 0; i < rssiVals.length; i++) { 6405 int val = rssiVals[i]; 6406 if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) { 6407 rssiRange[i] = (byte) val; 6408 } else { 6409 Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: " 6410 + Arrays.toString(rssiVals)); 6411 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 6412 mWifiInfo.getRssi()); 6413 return; 6414 } 6415 } 6416 // TODO: Do we quash rssi values in this sorted array which are very close? 6417 mRssiRanges = rssiRange; 6418 WifiStateMachine.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD, 6419 mWifiInfo.getRssi()); 6420 } 6421 6422 @Override 6423 protected void preventAutomaticReconnect() { 6424 if (this != mNetworkAgent) return; 6425 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN); 6426 } 6427 } 6428 6429 void unwantedNetwork(int reason) { 6430 sendMessage(CMD_UNWANTED_NETWORK, reason); 6431 } 6432 6433 void doNetworkStatus(int status) { 6434 sendMessage(CMD_NETWORK_STATUS, status); 6435 } 6436 6437 // rfc4186 & rfc4187: 6438 // create Permanent Identity base on IMSI, 6439 // identity = usernam@realm 6440 // with username = prefix | IMSI 6441 // and realm is derived MMC/MNC tuple according 3GGP spec(TS23.003) 6442 private String buildIdentity(int eapMethod, String imsi, String mccMnc) { 6443 String mcc; 6444 String mnc; 6445 String prefix; 6446 6447 if (imsi == null || imsi.isEmpty()) 6448 return ""; 6449 6450 if (eapMethod == WifiEnterpriseConfig.Eap.SIM) 6451 prefix = "1"; 6452 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA) 6453 prefix = "0"; 6454 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME) 6455 prefix = "6"; 6456 else // not a valide EapMethod 6457 return ""; 6458 6459 /* extract mcc & mnc from mccMnc */ 6460 if (mccMnc != null && !mccMnc.isEmpty()) { 6461 mcc = mccMnc.substring(0, 3); 6462 mnc = mccMnc.substring(3); 6463 if (mnc.length() == 2) 6464 mnc = "0" + mnc; 6465 } else { 6466 // extract mcc & mnc from IMSI, assume mnc size is 3 6467 mcc = imsi.substring(0, 3); 6468 mnc = imsi.substring(3, 6); 6469 } 6470 6471 return prefix + imsi + "@wlan.mnc" + mnc + ".mcc" + mcc + ".3gppnetwork.org"; 6472 } 6473 6474 boolean startScanForConfiguration(WifiConfiguration config) { 6475 if (config == null) 6476 return false; 6477 6478 // We are still seeing a fairly high power consumption triggered by autojoin scans 6479 // Hence do partial scans only for PSK configuration that are roamable since the 6480 // primary purpose of the partial scans is roaming. 6481 // Full badn scans with exponential backoff for the purpose or extended roaming and 6482 // network switching are performed unconditionally. 6483 ScanDetailCache scanDetailCache = 6484 mWifiConfigManager.getScanDetailCache(config); 6485 if (scanDetailCache == null 6486 || !config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) 6487 || scanDetailCache.size() > 6) { 6488 //return true but to not trigger the scan 6489 return true; 6490 } 6491 HashSet<Integer> freqs = mWifiConfigManager.makeChannelList(config, ONE_HOUR_MILLI); 6492 if (freqs != null && freqs.size() != 0) { 6493 //if (DBG) { 6494 logd("starting scan for " + config.configKey() + " with " + freqs); 6495 //} 6496 Set<Integer> hiddenNetworkIds = new HashSet<>(); 6497 if (config.hiddenSSID) { 6498 hiddenNetworkIds.add(config.networkId); 6499 } 6500 // Call wifi native to start the scan 6501 if (startScanNative(freqs, hiddenNetworkIds, WIFI_WORK_SOURCE)) { 6502 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; 6503 } else { 6504 // used for debug only, mark scan as failed 6505 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 6506 } 6507 return true; 6508 } else { 6509 if (DBG) logd("no channels for " + config.configKey()); 6510 return false; 6511 } 6512 } 6513 6514 void clearCurrentConfigBSSID(String dbg) { 6515 // Clear the bssid in the current config's network block 6516 WifiConfiguration config = getCurrentWifiConfiguration(); 6517 if (config == null) 6518 return; 6519 clearConfigBSSID(config, dbg); 6520 } 6521 void clearConfigBSSID(WifiConfiguration config, String dbg) { 6522 if (config == null) 6523 return; 6524 if (DBG) { 6525 logd(dbg + " " + mTargetRoamBSSID + " config " + config.configKey() 6526 + " config.NetworkSelectionStatus.mNetworkSelectionBSSID " 6527 + config.getNetworkSelectionStatus().getNetworkSelectionBSSID()); 6528 } 6529 if (DBG) { 6530 logd(dbg + " " + config.SSID 6531 + " nid=" + Integer.toString(config.networkId)); 6532 } 6533 mWifiConfigManager.saveWifiConfigBSSID(config, "any"); 6534 } 6535 6536 class L2ConnectedState extends State { 6537 @Override 6538 public void enter() { 6539 mRssiPollToken++; 6540 if (mEnableRssiPolling) { 6541 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0); 6542 } 6543 if (mNetworkAgent != null) { 6544 loge("Have NetworkAgent when entering L2Connected"); 6545 setNetworkDetailedState(DetailedState.DISCONNECTED); 6546 } 6547 setNetworkDetailedState(DetailedState.CONNECTING); 6548 6549 mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, 6550 "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter, 6551 mLinkProperties, 60, mNetworkMisc); 6552 6553 // We must clear the config BSSID, as the wifi chipset may decide to roam 6554 // from this point on and having the BSSID specified in the network block would 6555 // cause the roam to faile and the device to disconnect 6556 clearCurrentConfigBSSID("L2ConnectedState"); 6557 mCountryCode.setReadyForChange(false); 6558 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); 6559 } 6560 6561 @Override 6562 public void exit() { 6563 mIpManager.stop(); 6564 6565 // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState 6566 // Bug: 15347363 6567 // For paranoia's sake, call handleNetworkDisconnect 6568 // only if BSSID is null or last networkId 6569 // is not invalid. 6570 if (DBG) { 6571 StringBuilder sb = new StringBuilder(); 6572 sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId)); 6573 if (mLastBssid !=null) { 6574 sb.append(" ").append(mLastBssid); 6575 } 6576 } 6577 if (mLastBssid != null || mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6578 handleNetworkDisconnect(); 6579 } 6580 mCountryCode.setReadyForChange(true); 6581 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 6582 } 6583 6584 @Override 6585 public boolean processMessage(Message message) { 6586 logStateAndMessage(message, this); 6587 6588 switch (message.what) { 6589 case DhcpClient.CMD_PRE_DHCP_ACTION: 6590 handlePreDhcpSetup(); 6591 break; 6592 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 6593 mIpManager.completedPreDhcpAction(); 6594 break; 6595 case DhcpClient.CMD_POST_DHCP_ACTION: 6596 handlePostDhcpSetup(); 6597 // We advance to mConnectedState because IpManager will also send a 6598 // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(), 6599 // which calls updateLinkProperties, which then sends 6600 // CMD_IP_CONFIGURATION_SUCCESSFUL. 6601 // 6602 // In the event of failure, we transition to mDisconnectingState 6603 // similarly--via messages sent back from IpManager. 6604 break; 6605 case CMD_IPV4_PROVISIONING_SUCCESS: { 6606 handleIPv4Success((DhcpResults) message.obj); 6607 sendNetworkStateChangeBroadcast(mLastBssid); 6608 break; 6609 } 6610 case CMD_IPV4_PROVISIONING_FAILURE: { 6611 handleIPv4Failure(); 6612 break; 6613 } 6614 case CMD_IP_CONFIGURATION_SUCCESSFUL: 6615 handleSuccessfulIpConfiguration(); 6616 reportConnectionAttemptEnd( 6617 WifiMetrics.ConnectionEvent.FAILURE_NONE, 6618 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6619 sendConnectedState(); 6620 transitionTo(mConnectedState); 6621 break; 6622 case CMD_IP_CONFIGURATION_LOST: 6623 // Get Link layer stats so that we get fresh tx packet counters. 6624 getWifiLinkLayerStats(true); 6625 handleIpConfigurationLost(); 6626 transitionTo(mDisconnectingState); 6627 break; 6628 case CMD_IP_REACHABILITY_LOST: 6629 if (DBG && message.obj != null) log((String) message.obj); 6630 handleIpReachabilityLost(); 6631 transitionTo(mDisconnectingState); 6632 break; 6633 case CMD_DISCONNECT: 6634 mWifiNative.disconnect(); 6635 transitionTo(mDisconnectingState); 6636 break; 6637 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 6638 if (message.arg1 == 1) { 6639 mWifiNative.disconnect(); 6640 mTemporarilyDisconnectWifi = true; 6641 transitionTo(mDisconnectingState); 6642 } 6643 break; 6644 case CMD_SET_OPERATIONAL_MODE: 6645 if (message.arg1 != CONNECT_MODE) { 6646 sendMessage(CMD_DISCONNECT); 6647 deferMessage(message); 6648 if (message.arg1 == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 6649 noteWifiDisabledWhileAssociated(); 6650 } 6651 } 6652 mWifiConfigManager. 6653 setAndEnableLastSelectedConfiguration( 6654 WifiConfiguration.INVALID_NETWORK_ID); 6655 break; 6656 /* Ignore connection to same network */ 6657 case WifiManager.CONNECT_NETWORK: 6658 int netId = message.arg1; 6659 if (mWifiInfo.getNetworkId() == netId) { 6660 break; 6661 } 6662 return NOT_HANDLED; 6663 case WifiMonitor.NETWORK_CONNECTION_EVENT: 6664 mWifiInfo.setBSSID((String) message.obj); 6665 mLastNetworkId = message.arg1; 6666 mWifiInfo.setNetworkId(mLastNetworkId); 6667 if(!mLastBssid.equals((String) message.obj)) { 6668 mLastBssid = (String) message.obj; 6669 sendNetworkStateChangeBroadcast(mLastBssid); 6670 } 6671 break; 6672 case CMD_RSSI_POLL: 6673 if (message.arg1 == mRssiPollToken) { 6674 if (mWifiConfigManager.mEnableChipWakeUpWhenAssociated.get()) { 6675 if (DBG) log(" get link layer stats " + mWifiLinkLayerStatsSupported); 6676 WifiLinkLayerStats stats = getWifiLinkLayerStats(DBG); 6677 if (stats != null) { 6678 // Sanity check the results provided by driver 6679 if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI 6680 && (stats.rssi_mgmt == 0 6681 || stats.beacon_rx == 0)) { 6682 stats = null; 6683 } 6684 } 6685 // Get Info and continue polling 6686 fetchRssiLinkSpeedAndFrequencyNative(); 6687 mWifiScoreReport = 6688 WifiScoreReport.calculateScore(mWifiInfo, 6689 getCurrentWifiConfiguration(), 6690 mWifiConfigManager, 6691 mNetworkAgent, 6692 mWifiScoreReport, 6693 mAggressiveHandover, 6694 mWifiMetrics); 6695 } 6696 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 6697 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 6698 if (DBG) sendRssiChangeBroadcast(mWifiInfo.getRssi()); 6699 } else { 6700 // Polling has completed 6701 } 6702 break; 6703 case CMD_ENABLE_RSSI_POLL: 6704 cleanWifiScore(); 6705 if (mWifiConfigManager.mEnableRssiPollWhenAssociated.get()) { 6706 mEnableRssiPolling = (message.arg1 == 1); 6707 } else { 6708 mEnableRssiPolling = false; 6709 } 6710 mRssiPollToken++; 6711 if (mEnableRssiPolling) { 6712 // First poll 6713 fetchRssiLinkSpeedAndFrequencyNative(); 6714 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 6715 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 6716 } 6717 break; 6718 case WifiManager.RSSI_PKTCNT_FETCH: 6719 RssiPacketCountInfo info = new RssiPacketCountInfo(); 6720 fetchRssiLinkSpeedAndFrequencyNative(); 6721 info.rssi = mWifiInfo.getRssi(); 6722 fetchPktcntNative(info); 6723 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED, info); 6724 break; 6725 case CMD_DELAYED_NETWORK_DISCONNECT: 6726 if (!linkDebouncing && mWifiConfigManager.mEnableLinkDebouncing) { 6727 6728 // Ignore if we are not debouncing 6729 logd("CMD_DELAYED_NETWORK_DISCONNECT and not debouncing - ignore " 6730 + message.arg1); 6731 return HANDLED; 6732 } else { 6733 logd("CMD_DELAYED_NETWORK_DISCONNECT and debouncing - disconnect " 6734 + message.arg1); 6735 6736 linkDebouncing = false; 6737 // If we are still debouncing while this message comes, 6738 // it means we were not able to reconnect within the alloted time 6739 // = LINK_FLAPPING_DEBOUNCE_MSEC 6740 // and thus, trigger a real disconnect 6741 handleNetworkDisconnect(); 6742 transitionTo(mDisconnectedState); 6743 } 6744 break; 6745 case CMD_ASSOCIATED_BSSID: 6746 if ((String) message.obj == null) { 6747 logw("Associated command w/o BSSID"); 6748 break; 6749 } 6750 mLastBssid = (String) message.obj; 6751 if (mLastBssid != null && (mWifiInfo.getBSSID() == null 6752 || !mLastBssid.equals(mWifiInfo.getBSSID()))) { 6753 mWifiInfo.setBSSID((String) message.obj); 6754 sendNetworkStateChangeBroadcast(mLastBssid); 6755 } 6756 break; 6757 case CMD_START_RSSI_MONITORING_OFFLOAD: 6758 case CMD_RSSI_THRESHOLD_BREACH: 6759 byte currRssi = (byte) message.arg1; 6760 processRssiThreshold(currRssi, message.what); 6761 break; 6762 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 6763 stopRssiMonitoringOffload(); 6764 break; 6765 case CMD_RESET_SIM_NETWORKS: 6766 if (message.arg1 == 0 // sim was removed 6767 && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6768 WifiConfiguration config = 6769 mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 6770 if (TelephonyUtil.isSimConfig(config)) { 6771 mWifiNative.disconnect(); 6772 transitionTo(mDisconnectingState); 6773 } 6774 } 6775 /* allow parent state to reset data for other networks */ 6776 return NOT_HANDLED; 6777 default: 6778 return NOT_HANDLED; 6779 } 6780 6781 return HANDLED; 6782 } 6783 } 6784 6785 class ObtainingIpState extends State { 6786 @Override 6787 public void enter() { 6788 if (DBG) { 6789 String key = ""; 6790 if (getCurrentWifiConfiguration() != null) { 6791 key = getCurrentWifiConfiguration().configKey(); 6792 } 6793 log("enter ObtainingIpState netId=" + Integer.toString(mLastNetworkId) 6794 + " " + key + " " 6795 + " roam=" + mAutoRoaming 6796 + " static=" + mWifiConfigManager.isUsingStaticIp(mLastNetworkId) 6797 + " watchdog= " + obtainingIpWatchdogCount); 6798 } 6799 6800 // Reset link Debouncing, indicating we have successfully re-connected to the AP 6801 // We might still be roaming 6802 linkDebouncing = false; 6803 6804 // Send event to CM & network change broadcast 6805 setNetworkDetailedState(DetailedState.OBTAINING_IPADDR); 6806 6807 // We must clear the config BSSID, as the wifi chipset may decide to roam 6808 // from this point on and having the BSSID specified in the network block would 6809 // cause the roam to fail and the device to disconnect. 6810 clearCurrentConfigBSSID("ObtainingIpAddress"); 6811 6812 // Stop IpManager in case we're switching from DHCP to static 6813 // configuration or vice versa. 6814 // 6815 // TODO: Only ever enter this state the first time we connect to a 6816 // network, never on switching between static configuration and 6817 // DHCP. When we transition from static configuration to DHCP in 6818 // particular, we must tell ConnectivityService that we're 6819 // disconnected, because DHCP might take a long time during which 6820 // connectivity APIs such as getActiveNetworkInfo should not return 6821 // CONNECTED. 6822 stopIpManager(); 6823 6824 mIpManager.setHttpProxy(mWifiConfigManager.getProxyProperties(mLastNetworkId)); 6825 if (!TextUtils.isEmpty(mTcpBufferSizes)) { 6826 mIpManager.setTcpBufferSizes(mTcpBufferSizes); 6827 } 6828 6829 if (!mWifiConfigManager.isUsingStaticIp(mLastNetworkId)) { 6830 final IpManager.ProvisioningConfiguration prov = 6831 mIpManager.buildProvisioningConfiguration() 6832 .withPreDhcpAction() 6833 .withApfCapabilities(mWifiNative.getApfCapabilities()) 6834 .build(); 6835 mIpManager.startProvisioning(prov); 6836 obtainingIpWatchdogCount++; 6837 logd("Start Dhcp Watchdog " + obtainingIpWatchdogCount); 6838 // Get Link layer stats so as we get fresh tx packet counters 6839 getWifiLinkLayerStats(true); 6840 sendMessageDelayed(obtainMessage(CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER, 6841 obtainingIpWatchdogCount, 0), OBTAINING_IP_ADDRESS_GUARD_TIMER_MSEC); 6842 } else { 6843 StaticIpConfiguration config = mWifiConfigManager.getStaticIpConfiguration( 6844 mLastNetworkId); 6845 if (config.ipAddress == null) { 6846 logd("Static IP lacks address"); 6847 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 6848 } else { 6849 final IpManager.ProvisioningConfiguration prov = 6850 mIpManager.buildProvisioningConfiguration() 6851 .withStaticConfiguration(config) 6852 .withApfCapabilities(mWifiNative.getApfCapabilities()) 6853 .build(); 6854 mIpManager.startProvisioning(prov); 6855 } 6856 } 6857 } 6858 6859 @Override 6860 public boolean processMessage(Message message) { 6861 logStateAndMessage(message, this); 6862 6863 switch(message.what) { 6864 case CMD_AUTO_CONNECT: 6865 case CMD_AUTO_ROAM: 6866 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6867 break; 6868 case WifiManager.SAVE_NETWORK: 6869 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 6870 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 6871 deferMessage(message); 6872 break; 6873 /* Defer any power mode changes since we must keep active power mode at DHCP */ 6874 6875 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6876 reportConnectionAttemptEnd( 6877 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 6878 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6879 return NOT_HANDLED; 6880 case CMD_SET_HIGH_PERF_MODE: 6881 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 6882 deferMessage(message); 6883 break; 6884 /* Defer scan request since we should not switch to other channels at DHCP */ 6885 case CMD_START_SCAN: 6886 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 6887 deferMessage(message); 6888 break; 6889 case CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER: 6890 if (message.arg1 == obtainingIpWatchdogCount) { 6891 logd("ObtainingIpAddress: Watchdog Triggered, count=" 6892 + obtainingIpWatchdogCount); 6893 handleIpConfigurationLost(); 6894 transitionTo(mDisconnectingState); 6895 break; 6896 } 6897 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6898 break; 6899 default: 6900 return NOT_HANDLED; 6901 } 6902 return HANDLED; 6903 } 6904 } 6905 6906 private void sendConnectedState() { 6907 // If this network was explicitly selected by the user, evaluate whether to call 6908 // explicitlySelected() so the system can treat it appropriately. 6909 WifiConfiguration config = getCurrentWifiConfiguration(); 6910 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 6911 boolean prompt = 6912 mWifiConfigManager.checkConfigOverridePermission(config.lastConnectUid); 6913 if (DBG) { 6914 log("Network selected by UID " + config.lastConnectUid + " prompt=" + prompt); 6915 } 6916 if (prompt) { 6917 // Selected by the user via Settings or QuickSettings. If this network has Internet 6918 // access, switch to it. Otherwise, switch to it only if the user confirms that they 6919 // really want to switch, or has already confirmed and selected "Don't ask again". 6920 if (DBG) { 6921 log("explictlySelected acceptUnvalidated=" + config.noInternetAccessExpected); 6922 } 6923 mNetworkAgent.explicitlySelected(config.noInternetAccessExpected); 6924 } 6925 } 6926 6927 setNetworkDetailedState(DetailedState.CONNECTED); 6928 mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.CONNECTED); 6929 sendNetworkStateChangeBroadcast(mLastBssid); 6930 } 6931 6932 class RoamingState extends State { 6933 boolean mAssociated; 6934 @Override 6935 public void enter() { 6936 if (DBG) { 6937 log("RoamingState Enter" 6938 + " mScreenOn=" + mScreenOn ); 6939 } 6940 6941 // Make sure we disconnect if roaming fails 6942 roamWatchdogCount++; 6943 logd("Start Roam Watchdog " + roamWatchdogCount); 6944 sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER, 6945 roamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); 6946 mAssociated = false; 6947 } 6948 @Override 6949 public boolean processMessage(Message message) { 6950 logStateAndMessage(message, this); 6951 WifiConfiguration config; 6952 switch (message.what) { 6953 case CMD_IP_CONFIGURATION_LOST: 6954 config = getCurrentWifiConfiguration(); 6955 if (config != null) { 6956 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_AUTOROAM_FAILURE); 6957 mWifiConfigManager.noteRoamingFailure(config, 6958 WifiConfiguration.ROAMING_FAILURE_IP_CONFIG); 6959 } 6960 return NOT_HANDLED; 6961 case CMD_UNWANTED_NETWORK: 6962 if (DBG) log("Roaming and CS doesnt want the network -> ignore"); 6963 return HANDLED; 6964 case CMD_SET_OPERATIONAL_MODE: 6965 if (message.arg1 != CONNECT_MODE) { 6966 deferMessage(message); 6967 } 6968 break; 6969 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6970 /** 6971 * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT 6972 * before NETWORK_DISCONNECTION_EVENT 6973 * And there is an associated BSSID corresponding to our target BSSID, then 6974 * we have missed the network disconnection, transition to mDisconnectedState 6975 * and handle the rest of the events there. 6976 */ 6977 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 6978 if (stateChangeResult.state == SupplicantState.DISCONNECTED 6979 || stateChangeResult.state == SupplicantState.INACTIVE 6980 || stateChangeResult.state == SupplicantState.INTERFACE_DISABLED) { 6981 if (DBG) { 6982 log("STATE_CHANGE_EVENT in roaming state " 6983 + stateChangeResult.toString() ); 6984 } 6985 if (stateChangeResult.BSSID != null 6986 && stateChangeResult.BSSID.equals(mTargetRoamBSSID)) { 6987 handleNetworkDisconnect(); 6988 transitionTo(mDisconnectedState); 6989 } 6990 } 6991 if (stateChangeResult.state == SupplicantState.ASSOCIATED) { 6992 // We completed the layer2 roaming part 6993 mAssociated = true; 6994 if (stateChangeResult.BSSID != null) { 6995 mTargetRoamBSSID = (String) stateChangeResult.BSSID; 6996 } 6997 } 6998 break; 6999 case CMD_ROAM_WATCHDOG_TIMER: 7000 if (roamWatchdogCount == message.arg1) { 7001 if (DBG) log("roaming watchdog! -> disconnect"); 7002 mWifiMetrics.endConnectionEvent( 7003 WifiMetrics.ConnectionEvent.FAILURE_ROAM_TIMEOUT, 7004 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7005 mRoamFailCount++; 7006 handleNetworkDisconnect(); 7007 mWifiNative.disconnect(); 7008 transitionTo(mDisconnectedState); 7009 } 7010 break; 7011 case WifiMonitor.NETWORK_CONNECTION_EVENT: 7012 if (mAssociated) { 7013 if (DBG) log("roaming and Network connection established"); 7014 mLastNetworkId = message.arg1; 7015 mLastBssid = (String) message.obj; 7016 mWifiInfo.setBSSID(mLastBssid); 7017 mWifiInfo.setNetworkId(mLastNetworkId); 7018 if (mWifiConnectivityManager != null) { 7019 mWifiConnectivityManager.trackBssid(mLastBssid, true); 7020 } 7021 sendNetworkStateChangeBroadcast(mLastBssid); 7022 7023 // Successful framework roam! (probably) 7024 reportConnectionAttemptEnd( 7025 WifiMetrics.ConnectionEvent.FAILURE_NONE, 7026 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7027 7028 // We must clear the config BSSID, as the wifi chipset may decide to roam 7029 // from this point on and having the BSSID specified by QNS would cause 7030 // the roam to fail and the device to disconnect. 7031 // When transition from RoamingState to DisconnectingState or 7032 // DisconnectedState, the config BSSID is cleared by 7033 // handleNetworkDisconnect(). 7034 clearCurrentConfigBSSID("RoamingCompleted"); 7035 7036 // We used to transition to ObtainingIpState in an 7037 // attempt to do DHCPv4 RENEWs on framework roams. 7038 // DHCP can take too long to time out, and we now rely 7039 // upon IpManager's use of IpReachabilityMonitor to 7040 // confirm our current network configuration. 7041 // 7042 // mIpManager.confirmConfiguration() is called within 7043 // the handling of SupplicantState.COMPLETED. 7044 transitionTo(mConnectedState); 7045 } else { 7046 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7047 } 7048 break; 7049 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7050 // Throw away but only if it corresponds to the network we're roaming to 7051 String bssid = (String) message.obj; 7052 if (true) { 7053 String target = ""; 7054 if (mTargetRoamBSSID != null) target = mTargetRoamBSSID; 7055 log("NETWORK_DISCONNECTION_EVENT in roaming state" 7056 + " BSSID=" + bssid 7057 + " target=" + target); 7058 } 7059 if (bssid != null && bssid.equals(mTargetRoamBSSID)) { 7060 handleNetworkDisconnect(); 7061 transitionTo(mDisconnectedState); 7062 } 7063 break; 7064 case WifiMonitor.SSID_TEMP_DISABLED: 7065 // Auth error while roaming 7066 logd("SSID_TEMP_DISABLED nid=" + Integer.toString(mLastNetworkId) 7067 + " id=" + Integer.toString(message.arg1) 7068 + " isRoaming=" + isRoaming() 7069 + " roam=" + mAutoRoaming); 7070 if (message.arg1 == mLastNetworkId) { 7071 config = getCurrentWifiConfiguration(); 7072 if (config != null) { 7073 mWifiLogger.captureBugReportData( 7074 WifiLogger.REPORT_REASON_AUTOROAM_FAILURE); 7075 mWifiConfigManager.noteRoamingFailure(config, 7076 WifiConfiguration.ROAMING_FAILURE_AUTH_FAILURE); 7077 } 7078 handleNetworkDisconnect(); 7079 transitionTo(mDisconnectingState); 7080 } 7081 return NOT_HANDLED; 7082 case CMD_START_SCAN: 7083 deferMessage(message); 7084 break; 7085 default: 7086 return NOT_HANDLED; 7087 } 7088 return HANDLED; 7089 } 7090 7091 @Override 7092 public void exit() { 7093 logd("WifiStateMachine: Leaving Roaming state"); 7094 } 7095 } 7096 7097 class ConnectedState extends State { 7098 @Override 7099 public void enter() { 7100 String address; 7101 updateDefaultRouteMacAddress(1000); 7102 if (DBG) { 7103 log("Enter ConnectedState " 7104 + " mScreenOn=" + mScreenOn); 7105 } 7106 7107 if (mWifiConnectivityManager != null) { 7108 mWifiConnectivityManager.handleConnectionStateChanged( 7109 WifiConnectivityManager.WIFI_STATE_CONNECTED); 7110 } 7111 registerConnected(); 7112 lastConnectAttemptTimestamp = 0; 7113 targetWificonfiguration = null; 7114 // Paranoia 7115 linkDebouncing = false; 7116 7117 // Not roaming anymore 7118 mAutoRoaming = false; 7119 7120 if (testNetworkDisconnect) { 7121 testNetworkDisconnectCounter++; 7122 logd("ConnectedState Enter start disconnect test " + 7123 testNetworkDisconnectCounter); 7124 sendMessageDelayed(obtainMessage(CMD_TEST_NETWORK_DISCONNECT, 7125 testNetworkDisconnectCounter, 0), 15000); 7126 } 7127 7128 // Reenable all networks, allow for hidden networks to be scanned 7129 mWifiConfigManager.enableAllNetworks(); 7130 7131 mLastDriverRoamAttempt = 0; 7132 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 7133 mWifiLastResortWatchdog.connectedStateTransition(true); 7134 } 7135 @Override 7136 public boolean processMessage(Message message) { 7137 WifiConfiguration config = null; 7138 logStateAndMessage(message, this); 7139 7140 switch (message.what) { 7141 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 7142 updateAssociatedScanPermission(); 7143 break; 7144 case CMD_UNWANTED_NETWORK: 7145 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { 7146 mWifiNative.disconnect(); 7147 transitionTo(mDisconnectingState); 7148 } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN || 7149 message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { 7150 Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 7151 ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN" 7152 : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED")); 7153 config = getCurrentWifiConfiguration(); 7154 if (config != null) { 7155 // Disable autojoin 7156 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) { 7157 config.validatedInternetAccess = false; 7158 // Clear last-selected status, as being last-selected also avoids 7159 // disabling auto-join. 7160 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 7161 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 7162 WifiConfiguration.INVALID_NETWORK_ID); 7163 } 7164 mWifiConfigManager.updateNetworkSelectionStatus(config, 7165 WifiConfiguration.NetworkSelectionStatus 7166 .DISABLED_NO_INTERNET); 7167 } 7168 config.numNoInternetAccessReports += 1; 7169 mWifiConfigManager.writeKnownNetworkHistory(); 7170 } 7171 } 7172 return HANDLED; 7173 case CMD_NETWORK_STATUS: 7174 if (message.arg1 == NetworkAgent.VALID_NETWORK) { 7175 config = getCurrentWifiConfiguration(); 7176 if (config != null) { 7177 // re-enable autojoin 7178 config.numNoInternetAccessReports = 0; 7179 config.validatedInternetAccess = true; 7180 mWifiConfigManager.writeKnownNetworkHistory(); 7181 } 7182 } 7183 return HANDLED; 7184 case CMD_ACCEPT_UNVALIDATED: 7185 boolean accept = (message.arg1 != 0); 7186 config = getCurrentWifiConfiguration(); 7187 if (config != null) { 7188 config.noInternetAccessExpected = accept; 7189 mWifiConfigManager.writeKnownNetworkHistory(); 7190 } 7191 return HANDLED; 7192 case CMD_TEST_NETWORK_DISCONNECT: 7193 // Force a disconnect 7194 if (message.arg1 == testNetworkDisconnectCounter) { 7195 mWifiNative.disconnect(); 7196 } 7197 break; 7198 case CMD_ASSOCIATED_BSSID: 7199 // ASSOCIATING to a new BSSID while already connected, indicates 7200 // that driver is roaming 7201 mLastDriverRoamAttempt = System.currentTimeMillis(); 7202 return NOT_HANDLED; 7203 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7204 long lastRoam = 0; 7205 reportConnectionAttemptEnd( 7206 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 7207 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7208 if (mLastDriverRoamAttempt != 0) { 7209 // Calculate time since last driver roam attempt 7210 lastRoam = System.currentTimeMillis() - mLastDriverRoamAttempt; 7211 mLastDriverRoamAttempt = 0; 7212 } 7213 if (unexpectedDisconnectedReason(message.arg2)) { 7214 mWifiLogger.captureBugReportData( 7215 WifiLogger.REPORT_REASON_UNEXPECTED_DISCONNECT); 7216 } 7217 config = getCurrentWifiConfiguration(); 7218 if (mScreenOn 7219 && !linkDebouncing 7220 && config != null 7221 && config.getNetworkSelectionStatus().isNetworkEnabled() 7222 && !mWifiConfigManager.isLastSelectedConfiguration(config) 7223 && (message.arg2 != 3 /* reason cannot be 3, i.e. locally generated */ 7224 || (lastRoam > 0 && lastRoam < 2000) /* unless driver is roaming */) 7225 && ((ScanResult.is24GHz(mWifiInfo.getFrequency()) 7226 && mWifiInfo.getRssi() > 7227 WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND) 7228 || (ScanResult.is5GHz(mWifiInfo.getFrequency()) 7229 && mWifiInfo.getRssi() > 7230 mWifiConfigManager.mThresholdQualifiedRssi5.get()))) { 7231 // Start de-bouncing the L2 disconnection: 7232 // this L2 disconnection might be spurious. 7233 // Hence we allow 4 seconds for the state machine to try 7234 // to reconnect, go thru the 7235 // roaming cycle and enter Obtaining IP address 7236 // before signalling the disconnect to ConnectivityService and L3 7237 startScanForConfiguration(getCurrentWifiConfiguration()); 7238 linkDebouncing = true; 7239 7240 sendMessageDelayed(obtainMessage(CMD_DELAYED_NETWORK_DISCONNECT, 7241 0, mLastNetworkId), LINK_FLAPPING_DEBOUNCE_MSEC); 7242 if (DBG) { 7243 log("NETWORK_DISCONNECTION_EVENT in connected state" 7244 + " BSSID=" + mWifiInfo.getBSSID() 7245 + " RSSI=" + mWifiInfo.getRssi() 7246 + " freq=" + mWifiInfo.getFrequency() 7247 + " reason=" + message.arg2 7248 + " -> debounce"); 7249 } 7250 return HANDLED; 7251 } else { 7252 if (DBG) { 7253 log("NETWORK_DISCONNECTION_EVENT in connected state" 7254 + " BSSID=" + mWifiInfo.getBSSID() 7255 + " RSSI=" + mWifiInfo.getRssi() 7256 + " freq=" + mWifiInfo.getFrequency() 7257 + " was debouncing=" + linkDebouncing 7258 + " reason=" + message.arg2 7259 + " Network Selection Status=" + (config == null ? "Unavailable" 7260 : config.getNetworkSelectionStatus().getNetworkStatusString())); 7261 } 7262 } 7263 break; 7264 case CMD_AUTO_ROAM: 7265 // Clear the driver roam indication since we are attempting a framework roam 7266 mLastDriverRoamAttempt = 0; 7267 7268 /*<TODO> 2016-02-24 7269 Fix CMD_AUTO_ROAM to use the candidate (message.arg1) networkID, rather than 7270 the old networkID. 7271 The current code only handles roaming between BSSIDs on the same networkID, 7272 and will break for roams between different (but linked) networkIDs. This 7273 case occurs for DBDC roaming, and the CMD_AUTO_ROAM sent due to it will 7274 fail. 7275 */ 7276 /* Connect command coming from auto-join */ 7277 ScanResult candidate = (ScanResult)message.obj; 7278 String bssid = "any"; 7279 if (candidate != null) { 7280 bssid = candidate.BSSID; 7281 } 7282 int netId = message.arg1; 7283 if (netId == WifiConfiguration.INVALID_NETWORK_ID) { 7284 loge("AUTO_ROAM and no config, bail out..."); 7285 break; 7286 } else { 7287 config = mWifiConfigManager.getWifiConfiguration(netId); 7288 if (config == null) { 7289 loge("AUTO_ROAM and invalid netowrk ID, bail out..."); 7290 break; 7291 } 7292 } 7293 7294 setTargetBssid(config, bssid); 7295 mTargetNetworkId = netId; 7296 7297 logd("CMD_AUTO_ROAM sup state " 7298 + mSupplicantStateTracker.getSupplicantStateName() 7299 + " my state " + getCurrentState().getName() 7300 + " nid=" + Integer.toString(netId) 7301 + " config " + config.configKey() 7302 + " targetRoamBSSID " + mTargetRoamBSSID); 7303 7304 /* Determine if this is a regular roam (between BSSIDs sharing the same SSID), 7305 or a DBDC roam (between 2.4 & 5GHz networks on different SSID's, but with 7306 matching 16 byte BSSID prefixes): 7307 */ 7308 WifiConfiguration currentConfig = getCurrentWifiConfiguration(); 7309 if (currentConfig != null && currentConfig.isLinked(config)) { 7310 // This is dual band roaming 7311 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 7312 WifiMetricsProto.ConnectionEvent.ROAM_DBDC); 7313 } else { 7314 // This is regular roaming 7315 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 7316 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 7317 } 7318 7319 if (deferForUserInput(message, netId, false)) { 7320 reportConnectionAttemptEnd( 7321 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 7322 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7323 break; 7324 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 7325 WifiConfiguration.USER_BANNED) { 7326 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 7327 WifiManager.NOT_AUTHORIZED); 7328 reportConnectionAttemptEnd( 7329 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 7330 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7331 break; 7332 } 7333 7334 boolean ret = false; 7335 if (mLastNetworkId != netId) { 7336 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 7337 WifiConfiguration.UNKNOWN_UID) && mWifiNative.reconnect()) { 7338 ret = true; 7339 } 7340 } else { 7341 ret = mWifiNative.reassociate(); 7342 } 7343 if (ret) { 7344 lastConnectAttemptTimestamp = System.currentTimeMillis(); 7345 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 7346 7347 // replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 7348 mAutoRoaming = true; 7349 transitionTo(mRoamingState); 7350 7351 } else { 7352 loge("Failed to connect config: " + config + " netId: " + netId); 7353 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 7354 WifiManager.ERROR); 7355 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 7356 reportConnectionAttemptEnd( 7357 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 7358 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7359 break; 7360 } 7361 break; 7362 case CMD_START_IP_PACKET_OFFLOAD: { 7363 int slot = message.arg1; 7364 int intervalSeconds = message.arg2; 7365 KeepalivePacketData pkt = (KeepalivePacketData) message.obj; 7366 byte[] dstMac; 7367 try { 7368 InetAddress gateway = RouteInfo.selectBestRoute( 7369 mLinkProperties.getRoutes(), pkt.dstAddress).getGateway(); 7370 String dstMacStr = macAddressFromRoute(gateway.getHostAddress()); 7371 dstMac = macAddressFromString(dstMacStr); 7372 } catch (NullPointerException|IllegalArgumentException e) { 7373 loge("Can't find MAC address for next hop to " + pkt.dstAddress); 7374 mNetworkAgent.onPacketKeepaliveEvent(slot, 7375 ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 7376 break; 7377 } 7378 pkt.dstMac = dstMac; 7379 int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds); 7380 mNetworkAgent.onPacketKeepaliveEvent(slot, result); 7381 break; 7382 } 7383 default: 7384 return NOT_HANDLED; 7385 } 7386 return HANDLED; 7387 } 7388 7389 @Override 7390 public void exit() { 7391 logd("WifiStateMachine: Leaving Connected state"); 7392 if (mWifiConnectivityManager != null) { 7393 mWifiConnectivityManager.handleConnectionStateChanged( 7394 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 7395 } 7396 7397 mLastDriverRoamAttempt = 0; 7398 mWhiteListedSsids = null; 7399 mWifiLastResortWatchdog.connectedStateTransition(false); 7400 } 7401 } 7402 7403 class DisconnectingState extends State { 7404 7405 @Override 7406 public void enter() { 7407 7408 if (DBG) { 7409 logd(" Enter DisconnectingState State screenOn=" + mScreenOn); 7410 } 7411 7412 // Make sure we disconnect: we enter this state prior to connecting to a new 7413 // network, waiting for either a DISCONNECT event or a SUPPLICANT_STATE_CHANGE 7414 // event which in this case will be indicating that supplicant started to associate. 7415 // In some cases supplicant doesn't ignore the connect requests (it might not 7416 // find the target SSID in its cache), 7417 // Therefore we end up stuck that state, hence the need for the watchdog. 7418 disconnectingWatchdogCount++; 7419 logd("Start Disconnecting Watchdog " + disconnectingWatchdogCount); 7420 sendMessageDelayed(obtainMessage(CMD_DISCONNECTING_WATCHDOG_TIMER, 7421 disconnectingWatchdogCount, 0), DISCONNECTING_GUARD_TIMER_MSEC); 7422 } 7423 7424 @Override 7425 public boolean processMessage(Message message) { 7426 logStateAndMessage(message, this); 7427 switch (message.what) { 7428 case CMD_SET_OPERATIONAL_MODE: 7429 if (message.arg1 != CONNECT_MODE) { 7430 deferMessage(message); 7431 } 7432 break; 7433 case CMD_START_SCAN: 7434 deferMessage(message); 7435 return HANDLED; 7436 case CMD_DISCONNECT: 7437 if (DBG) log("Ignore CMD_DISCONNECT when already disconnecting."); 7438 break; 7439 case CMD_DISCONNECTING_WATCHDOG_TIMER: 7440 if (disconnectingWatchdogCount == message.arg1) { 7441 if (DBG) log("disconnecting watchdog! -> disconnect"); 7442 handleNetworkDisconnect(); 7443 transitionTo(mDisconnectedState); 7444 } 7445 break; 7446 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 7447 /** 7448 * If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT 7449 * we have missed the network disconnection, transition to mDisconnectedState 7450 * and handle the rest of the events there 7451 */ 7452 deferMessage(message); 7453 handleNetworkDisconnect(); 7454 transitionTo(mDisconnectedState); 7455 break; 7456 default: 7457 return NOT_HANDLED; 7458 } 7459 return HANDLED; 7460 } 7461 } 7462 7463 class DisconnectedState extends State { 7464 @Override 7465 public void enter() { 7466 // We dont scan frequently if this is a temporary disconnect 7467 // due to p2p 7468 if (mTemporarilyDisconnectWifi) { 7469 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 7470 return; 7471 } 7472 7473 if (DBG) { 7474 logd(" Enter DisconnectedState screenOn=" + mScreenOn); 7475 } 7476 7477 /** clear the roaming state, if we were roaming, we failed */ 7478 mAutoRoaming = false; 7479 7480 if (mWifiConnectivityManager != null) { 7481 mWifiConnectivityManager.handleConnectionStateChanged( 7482 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 7483 } 7484 7485 /** 7486 * If we have no networks saved, the supplicant stops doing the periodic scan. 7487 * The scans are useful to notify the user of the presence of an open network. 7488 * Note that these are not wake up scans. 7489 */ 7490 if (mNoNetworksPeriodicScan != 0 && !mP2pConnected.get() 7491 && mWifiConfigManager.getSavedNetworks().size() == 0) { 7492 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7493 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7494 } 7495 7496 mDisconnectedTimeStamp = System.currentTimeMillis(); 7497 } 7498 @Override 7499 public boolean processMessage(Message message) { 7500 boolean ret = HANDLED; 7501 7502 logStateAndMessage(message, this); 7503 7504 switch (message.what) { 7505 case CMD_NO_NETWORKS_PERIODIC_SCAN: 7506 if (mP2pConnected.get()) break; 7507 if (mNoNetworksPeriodicScan != 0 && message.arg1 == mPeriodicScanToken && 7508 mWifiConfigManager.getSavedNetworks().size() == 0) { 7509 startScan(UNKNOWN_SCAN_SOURCE, -1, null, WIFI_WORK_SOURCE); 7510 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7511 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7512 } 7513 break; 7514 case WifiManager.FORGET_NETWORK: 7515 case CMD_REMOVE_NETWORK: 7516 case CMD_REMOVE_APP_CONFIGURATIONS: 7517 case CMD_REMOVE_USER_CONFIGURATIONS: 7518 // Set up a delayed message here. After the forget/remove is handled 7519 // the handled delayed message will determine if there is a need to 7520 // scan and continue 7521 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7522 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7523 ret = NOT_HANDLED; 7524 break; 7525 case CMD_SET_OPERATIONAL_MODE: 7526 if (message.arg1 != CONNECT_MODE) { 7527 mOperationalMode = message.arg1; 7528 mWifiConfigManager.disableAllNetworksNative(); 7529 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 7530 mWifiP2pChannel.sendMessage(CMD_DISABLE_P2P_REQ); 7531 setWifiState(WIFI_STATE_DISABLED); 7532 } 7533 transitionTo(mScanModeState); 7534 } 7535 mWifiConfigManager. 7536 setAndEnableLastSelectedConfiguration( 7537 WifiConfiguration.INVALID_NETWORK_ID); 7538 break; 7539 case CMD_DISCONNECT: 7540 if (SupplicantState.isConnecting(mWifiInfo.getSupplicantState())) { 7541 if (DBG) { 7542 log("CMD_DISCONNECT when supplicant is connecting - do not ignore"); 7543 } 7544 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 7545 WifiConfiguration.INVALID_NETWORK_ID); 7546 mWifiNative.disconnect(); 7547 break; 7548 } 7549 if (DBG) log("Ignore CMD_DISCONNECT when already disconnected."); 7550 break; 7551 /* Ignore network disconnect */ 7552 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7553 // Interpret this as an L2 connection failure 7554 break; 7555 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 7556 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 7557 if (DBG) { 7558 logd("SUPPLICANT_STATE_CHANGE_EVENT state=" + stateChangeResult.state + 7559 " -> state= " + WifiInfo.getDetailedStateOf(stateChangeResult.state) 7560 + " debouncing=" + linkDebouncing); 7561 } 7562 setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state)); 7563 /* ConnectModeState does the rest of the handling */ 7564 ret = NOT_HANDLED; 7565 break; 7566 case CMD_START_SCAN: 7567 if (!checkOrDeferScanAllowed(message)) { 7568 // The scan request was rescheduled 7569 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 7570 return HANDLED; 7571 } 7572 7573 ret = NOT_HANDLED; 7574 break; 7575 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 7576 NetworkInfo info = (NetworkInfo) message.obj; 7577 mP2pConnected.set(info.isConnected()); 7578 if (mP2pConnected.get()) { 7579 int defaultInterval = mContext.getResources().getInteger( 7580 R.integer.config_wifi_scan_interval_p2p_connected); 7581 long scanIntervalMs = mFacade.getLongSetting(mContext, 7582 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, 7583 defaultInterval); 7584 mWifiNative.setScanInterval((int) scanIntervalMs/1000); 7585 } else if (mWifiConfigManager.getSavedNetworks().size() == 0) { 7586 if (DBG) log("Turn on scanning after p2p disconnected"); 7587 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 7588 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 7589 } 7590 break; 7591 case CMD_RECONNECT: 7592 case CMD_REASSOCIATE: 7593 if (mTemporarilyDisconnectWifi) { 7594 // Drop a third party reconnect/reassociate if STA is 7595 // temporarily disconnected for p2p 7596 break; 7597 } else { 7598 // ConnectModeState handles it 7599 ret = NOT_HANDLED; 7600 } 7601 break; 7602 case CMD_SCREEN_STATE_CHANGED: 7603 handleScreenStateChanged(message.arg1 != 0); 7604 break; 7605 default: 7606 ret = NOT_HANDLED; 7607 } 7608 return ret; 7609 } 7610 7611 @Override 7612 public void exit() { 7613 if (mWifiConnectivityManager != null) { 7614 mWifiConnectivityManager.handleConnectionStateChanged( 7615 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 7616 } 7617 } 7618 } 7619 7620 class WpsRunningState extends State { 7621 // Tracks the source to provide a reply 7622 private Message mSourceMessage; 7623 @Override 7624 public void enter() { 7625 mSourceMessage = Message.obtain(getCurrentMessage()); 7626 } 7627 @Override 7628 public boolean processMessage(Message message) { 7629 logStateAndMessage(message, this); 7630 7631 switch (message.what) { 7632 case WifiMonitor.WPS_SUCCESS_EVENT: 7633 // Ignore intermediate success, wait for full connection 7634 break; 7635 case WifiMonitor.NETWORK_CONNECTION_EVENT: 7636 replyToMessage(mSourceMessage, WifiManager.WPS_COMPLETED); 7637 mSourceMessage.recycle(); 7638 mSourceMessage = null; 7639 deferMessage(message); 7640 transitionTo(mDisconnectedState); 7641 break; 7642 case WifiMonitor.WPS_OVERLAP_EVENT: 7643 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 7644 WifiManager.WPS_OVERLAP_ERROR); 7645 mSourceMessage.recycle(); 7646 mSourceMessage = null; 7647 transitionTo(mDisconnectedState); 7648 break; 7649 case WifiMonitor.WPS_FAIL_EVENT: 7650 // Arg1 has the reason for the failure 7651 if ((message.arg1 != WifiManager.ERROR) || (message.arg2 != 0)) { 7652 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1); 7653 mSourceMessage.recycle(); 7654 mSourceMessage = null; 7655 transitionTo(mDisconnectedState); 7656 } else { 7657 if (DBG) log("Ignore unspecified fail event during WPS connection"); 7658 } 7659 break; 7660 case WifiMonitor.WPS_TIMEOUT_EVENT: 7661 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 7662 WifiManager.WPS_TIMED_OUT); 7663 mSourceMessage.recycle(); 7664 mSourceMessage = null; 7665 transitionTo(mDisconnectedState); 7666 break; 7667 case WifiManager.START_WPS: 7668 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS); 7669 break; 7670 case WifiManager.CANCEL_WPS: 7671 if (mWifiNative.cancelWps()) { 7672 replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED); 7673 } else { 7674 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR); 7675 } 7676 transitionTo(mDisconnectedState); 7677 break; 7678 /** 7679 * Defer all commands that can cause connections to a different network 7680 * or put the state machine out of connect mode 7681 */ 7682 case CMD_STOP_DRIVER: 7683 case CMD_SET_OPERATIONAL_MODE: 7684 case WifiManager.CONNECT_NETWORK: 7685 case CMD_ENABLE_NETWORK: 7686 case CMD_RECONNECT: 7687 case CMD_REASSOCIATE: 7688 case CMD_ENABLE_ALL_NETWORKS: 7689 deferMessage(message); 7690 break; 7691 case CMD_AUTO_CONNECT: 7692 case CMD_AUTO_ROAM: 7693 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7694 return HANDLED; 7695 case CMD_START_SCAN: 7696 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7697 return HANDLED; 7698 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7699 if (DBG) log("Network connection lost"); 7700 handleNetworkDisconnect(); 7701 break; 7702 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 7703 if (DBG) log("Ignore Assoc reject event during WPS Connection"); 7704 break; 7705 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 7706 // Disregard auth failure events during WPS connection. The 7707 // EAP sequence is retried several times, and there might be 7708 // failures (especially for wps pin). We will get a WPS_XXX 7709 // event at the end of the sequence anyway. 7710 if (DBG) log("Ignore auth failure during WPS connection"); 7711 break; 7712 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 7713 // Throw away supplicant state changes when WPS is running. 7714 // We will start getting supplicant state changes once we get 7715 // a WPS success or failure 7716 break; 7717 default: 7718 return NOT_HANDLED; 7719 } 7720 return HANDLED; 7721 } 7722 7723 @Override 7724 public void exit() { 7725 mWifiConfigManager.enableAllNetworks(); 7726 mWifiConfigManager.loadConfiguredNetworks(); 7727 } 7728 } 7729 7730 class SoftApState extends State { 7731 private SoftApManager mSoftApManager; 7732 7733 private class SoftApListener implements SoftApManager.Listener { 7734 @Override 7735 public void onStateChanged(int state, int reason) { 7736 if (state == WIFI_AP_STATE_DISABLED) { 7737 sendMessage(CMD_AP_STOPPED); 7738 } else if (state == WIFI_AP_STATE_FAILED) { 7739 sendMessage(CMD_START_AP_FAILURE); 7740 } 7741 7742 setWifiApState(state, reason); 7743 } 7744 } 7745 7746 @Override 7747 public void enter() { 7748 final Message message = getCurrentMessage(); 7749 if (message.what == CMD_START_AP) { 7750 WifiConfiguration config = (WifiConfiguration) message.obj; 7751 7752 if (config == null) { 7753 /** 7754 * Configuration not provided in the command, fallback to use the current 7755 * configuration. 7756 */ 7757 config = mWifiApConfigStore.getApConfiguration(); 7758 } else { 7759 /* Update AP configuration. */ 7760 mWifiApConfigStore.setApConfiguration(config); 7761 } 7762 7763 checkAndSetConnectivityInstance(); 7764 mSoftApManager = mFacade.makeSoftApManager( 7765 mContext, getHandler().getLooper(), mWifiNative, mNwService, 7766 mCm, mCountryCode.getCountryCode(), 7767 mWifiApConfigStore.getAllowed2GChannel(), 7768 new SoftApListener()); 7769 mSoftApManager.start(config); 7770 } else { 7771 throw new RuntimeException("Illegal transition to SoftApState: " + message); 7772 } 7773 } 7774 7775 @Override 7776 public void exit() { 7777 mSoftApManager = null; 7778 } 7779 7780 @Override 7781 public boolean processMessage(Message message) { 7782 logStateAndMessage(message, this); 7783 7784 switch(message.what) { 7785 case CMD_START_AP: 7786 /* Ignore start command when it is starting/started. */ 7787 break; 7788 case CMD_STOP_AP: 7789 mSoftApManager.stop(); 7790 break; 7791 case CMD_START_AP_FAILURE: 7792 transitionTo(mInitialState); 7793 break; 7794 case CMD_AP_STOPPED: 7795 transitionTo(mInitialState); 7796 break; 7797 default: 7798 return NOT_HANDLED; 7799 } 7800 return HANDLED; 7801 } 7802 } 7803 7804 /** 7805 * State machine initiated requests can have replyTo set to null indicating 7806 * there are no recepients, we ignore those reply actions. 7807 */ 7808 private void replyToMessage(Message msg, int what) { 7809 if (msg.replyTo == null) return; 7810 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 7811 mReplyChannel.replyToMessage(msg, dstMsg); 7812 } 7813 7814 private void replyToMessage(Message msg, int what, int arg1) { 7815 if (msg.replyTo == null) return; 7816 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 7817 dstMsg.arg1 = arg1; 7818 mReplyChannel.replyToMessage(msg, dstMsg); 7819 } 7820 7821 private void replyToMessage(Message msg, int what, Object obj) { 7822 if (msg.replyTo == null) return; 7823 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 7824 dstMsg.obj = obj; 7825 mReplyChannel.replyToMessage(msg, dstMsg); 7826 } 7827 7828 /** 7829 * arg2 on the source message has a unique id that needs to be retained in replies 7830 * to match the request 7831 * <p>see WifiManager for details 7832 */ 7833 private Message obtainMessageWithWhatAndArg2(Message srcMsg, int what) { 7834 Message msg = Message.obtain(); 7835 msg.what = what; 7836 msg.arg2 = srcMsg.arg2; 7837 return msg; 7838 } 7839 7840 /** 7841 * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT 7842 * @param msg Must have a WifiConfiguration obj to succeed 7843 */ 7844 private void broadcastWifiCredentialChanged(int wifiCredentialEventType, 7845 WifiConfiguration config) { 7846 if (config != null && config.preSharedKey != null) { 7847 Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); 7848 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); 7849 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, 7850 wifiCredentialEventType); 7851 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT, 7852 android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE); 7853 } 7854 } 7855 7856 private static int parseHex(char ch) { 7857 if ('0' <= ch && ch <= '9') { 7858 return ch - '0'; 7859 } else if ('a' <= ch && ch <= 'f') { 7860 return ch - 'a' + 10; 7861 } else if ('A' <= ch && ch <= 'F') { 7862 return ch - 'A' + 10; 7863 } else { 7864 throw new NumberFormatException("" + ch + " is not a valid hex digit"); 7865 } 7866 } 7867 7868 private byte[] parseHex(String hex) { 7869 /* This only works for good input; don't throw bad data at it */ 7870 if (hex == null) { 7871 return new byte[0]; 7872 } 7873 7874 if (hex.length() % 2 != 0) { 7875 throw new NumberFormatException(hex + " is not a valid hex string"); 7876 } 7877 7878 byte[] result = new byte[(hex.length())/2 + 1]; 7879 result[0] = (byte) ((hex.length())/2); 7880 for (int i = 0, j = 1; i < hex.length(); i += 2, j++) { 7881 int val = parseHex(hex.charAt(i)) * 16 + parseHex(hex.charAt(i+1)); 7882 byte b = (byte) (val & 0xFF); 7883 result[j] = b; 7884 } 7885 7886 return result; 7887 } 7888 7889 private static String makeHex(byte[] bytes) { 7890 StringBuilder sb = new StringBuilder(); 7891 for (byte b : bytes) { 7892 sb.append(String.format("%02x", b)); 7893 } 7894 return sb.toString(); 7895 } 7896 7897 private static String makeHex(byte[] bytes, int from, int len) { 7898 StringBuilder sb = new StringBuilder(); 7899 for (int i = 0; i < len; i++) { 7900 sb.append(String.format("%02x", bytes[from+i])); 7901 } 7902 return sb.toString(); 7903 } 7904 7905 private static byte[] concat(byte[] array1, byte[] array2, byte[] array3) { 7906 7907 int len = array1.length + array2.length + array3.length; 7908 7909 if (array1.length != 0) { 7910 len++; /* add another byte for size */ 7911 } 7912 7913 if (array2.length != 0) { 7914 len++; /* add another byte for size */ 7915 } 7916 7917 if (array3.length != 0) { 7918 len++; /* add another byte for size */ 7919 } 7920 7921 byte[] result = new byte[len]; 7922 7923 int index = 0; 7924 if (array1.length != 0) { 7925 result[index] = (byte) (array1.length & 0xFF); 7926 index++; 7927 for (byte b : array1) { 7928 result[index] = b; 7929 index++; 7930 } 7931 } 7932 7933 if (array2.length != 0) { 7934 result[index] = (byte) (array2.length & 0xFF); 7935 index++; 7936 for (byte b : array2) { 7937 result[index] = b; 7938 index++; 7939 } 7940 } 7941 7942 if (array3.length != 0) { 7943 result[index] = (byte) (array3.length & 0xFF); 7944 index++; 7945 for (byte b : array3) { 7946 result[index] = b; 7947 index++; 7948 } 7949 } 7950 return result; 7951 } 7952 7953 private static byte[] concatHex(byte[] array1, byte[] array2) { 7954 7955 int len = array1.length + array2.length; 7956 7957 byte[] result = new byte[len]; 7958 7959 int index = 0; 7960 if (array1.length != 0) { 7961 for (byte b : array1) { 7962 result[index] = b; 7963 index++; 7964 } 7965 } 7966 7967 if (array2.length != 0) { 7968 for (byte b : array2) { 7969 result[index] = b; 7970 index++; 7971 } 7972 } 7973 7974 return result; 7975 } 7976 7977 // TODO move to TelephonyUtil, same with utilities above 7978 String getGsmSimAuthResponse(String[] requestData, TelephonyManager tm) { 7979 StringBuilder sb = new StringBuilder(); 7980 for (String challenge : requestData) { 7981 if (challenge == null || challenge.isEmpty()) { 7982 continue; 7983 } 7984 logd("RAND = " + challenge); 7985 7986 byte[] rand = null; 7987 try { 7988 rand = parseHex(challenge); 7989 } catch (NumberFormatException e) { 7990 loge("malformed challenge"); 7991 continue; 7992 } 7993 7994 String base64Challenge = android.util.Base64.encodeToString( 7995 rand, android.util.Base64.NO_WRAP); 7996 7997 // Try USIM first for authentication. 7998 String tmResponse = tm.getIccAuthentication(tm.APPTYPE_USIM, 7999 tm.AUTHTYPE_EAP_SIM, base64Challenge); 8000 if (tmResponse == null) { 8001 /* Then, in case of failure, issue may be due to sim type, retry as a simple sim 8002 */ 8003 tmResponse = tm.getIccAuthentication(tm.APPTYPE_SIM, 8004 tm.AUTHTYPE_EAP_SIM, base64Challenge); 8005 } 8006 logv("Raw Response - " + tmResponse); 8007 8008 if (tmResponse == null || tmResponse.length() <= 4) { 8009 loge("bad response - " + tmResponse); 8010 return null; 8011 } 8012 8013 byte[] result = android.util.Base64.decode(tmResponse, android.util.Base64.DEFAULT); 8014 logv("Hex Response -" + makeHex(result)); 8015 int sres_len = result[0]; 8016 if (sres_len >= result.length) { 8017 loge("malfomed response - " + tmResponse); 8018 return null; 8019 } 8020 String sres = makeHex(result, 1, sres_len); 8021 int kc_offset = 1 + sres_len; 8022 if (kc_offset >= result.length) { 8023 loge("malfomed response - " + tmResponse); 8024 return null; 8025 } 8026 int kc_len = result[kc_offset]; 8027 if (kc_offset + kc_len > result.length) { 8028 loge("malfomed response - " + tmResponse); 8029 return null; 8030 } 8031 String kc = makeHex(result, 1 + kc_offset, kc_len); 8032 sb.append(":" + kc + ":" + sres); 8033 logv("kc:" + kc + " sres:" + sres); 8034 } 8035 8036 return sb.toString(); 8037 } 8038 8039 // TODO move to TelephonyUtil 8040 void handleGsmAuthRequest(SimAuthRequestData requestData) { 8041 if (targetWificonfiguration == null 8042 || targetWificonfiguration.networkId == requestData.networkId) { 8043 logd("id matches targetWifiConfiguration"); 8044 } else { 8045 logd("id does not match targetWifiConfiguration"); 8046 return; 8047 } 8048 8049 TelephonyManager tm = (TelephonyManager) 8050 mContext.getSystemService(Context.TELEPHONY_SERVICE); 8051 8052 if (tm == null) { 8053 loge("could not get telephony manager"); 8054 mWifiNative.simAuthFailedResponse(requestData.networkId); 8055 return; 8056 } 8057 8058 String response = getGsmSimAuthResponse(requestData.data, tm); 8059 if (response == null) { 8060 mWifiNative.simAuthFailedResponse(requestData.networkId); 8061 } else { 8062 logv("Supplicant Response -" + response); 8063 mWifiNative.simAuthResponse(requestData.networkId, "GSM-AUTH", response); 8064 } 8065 } 8066 8067 // TODO move to TelephonyUtil 8068 void handle3GAuthRequest(SimAuthRequestData requestData) { 8069 StringBuilder sb = new StringBuilder(); 8070 byte[] rand = null; 8071 byte[] authn = null; 8072 String res_type = "UMTS-AUTH"; 8073 8074 if (targetWificonfiguration == null 8075 || targetWificonfiguration.networkId == requestData.networkId) { 8076 logd("id matches targetWifiConfiguration"); 8077 } else { 8078 logd("id does not match targetWifiConfiguration"); 8079 return; 8080 } 8081 if (requestData.data.length == 2) { 8082 try { 8083 rand = parseHex(requestData.data[0]); 8084 authn = parseHex(requestData.data[1]); 8085 } catch (NumberFormatException e) { 8086 loge("malformed challenge"); 8087 } 8088 } else { 8089 loge("malformed challenge"); 8090 } 8091 8092 String tmResponse = ""; 8093 if (rand != null && authn != null) { 8094 String base64Challenge = android.util.Base64.encodeToString( 8095 concatHex(rand,authn), android.util.Base64.NO_WRAP); 8096 8097 TelephonyManager tm = (TelephonyManager) 8098 mContext.getSystemService(Context.TELEPHONY_SERVICE); 8099 if (tm != null) { 8100 tmResponse = tm.getIccAuthentication(tm.APPTYPE_USIM, 8101 tm.AUTHTYPE_EAP_AKA, base64Challenge); 8102 logv("Raw Response - " + tmResponse); 8103 } else { 8104 loge("could not get telephony manager"); 8105 } 8106 } 8107 8108 boolean good_response = false; 8109 if (tmResponse != null && tmResponse.length() > 4) { 8110 byte[] result = android.util.Base64.decode(tmResponse, 8111 android.util.Base64.DEFAULT); 8112 loge("Hex Response - " + makeHex(result)); 8113 byte tag = result[0]; 8114 if (tag == (byte) 0xdb) { 8115 logv("successful 3G authentication "); 8116 int res_len = result[1]; 8117 String res = makeHex(result, 2, res_len); 8118 int ck_len = result[res_len + 2]; 8119 String ck = makeHex(result, res_len + 3, ck_len); 8120 int ik_len = result[res_len + ck_len + 3]; 8121 String ik = makeHex(result, res_len + ck_len + 4, ik_len); 8122 sb.append(":" + ik + ":" + ck + ":" + res); 8123 logv("ik:" + ik + "ck:" + ck + " res:" + res); 8124 good_response = true; 8125 } else if (tag == (byte) 0xdc) { 8126 loge("synchronisation failure"); 8127 int auts_len = result[1]; 8128 String auts = makeHex(result, 2, auts_len); 8129 res_type = "UMTS-AUTS"; 8130 sb.append(":" + auts); 8131 logv("auts:" + auts); 8132 good_response = true; 8133 } else { 8134 loge("bad response - unknown tag = " + tag); 8135 } 8136 } else { 8137 loge("bad response - " + tmResponse); 8138 } 8139 8140 if (good_response) { 8141 String response = sb.toString(); 8142 logv("Supplicant Response -" + response); 8143 mWifiNative.simAuthResponse(requestData.networkId, res_type, response); 8144 } else { 8145 mWifiNative.umtsAuthFailedResponse(requestData.networkId); 8146 } 8147 } 8148 8149 /** 8150 * Automatically connect to the network specified 8151 * 8152 * @param networkId ID of the network to connect to 8153 * @param bssid BSSID of the network 8154 */ 8155 public void autoConnectToNetwork(int networkId, String bssid) { 8156 synchronized (mWifiReqCountLock) { 8157 if (hasConnectionRequests()) { 8158 sendMessage(CMD_AUTO_CONNECT, networkId, 0, bssid); 8159 } 8160 } 8161 } 8162 8163 /** 8164 * Automatically roam to the network specified 8165 * 8166 * @param networkId ID of the network to roam to 8167 * @param scanResult scan result which identifies the network to roam to 8168 */ 8169 public void autoRoamToNetwork(int networkId, ScanResult scanResult) { 8170 sendMessage(CMD_AUTO_ROAM, networkId, 0, scanResult); 8171 } 8172 8173 /** 8174 * Dynamically turn on/off WifiConnectivityManager 8175 * 8176 * @param enabled true-enable; false-disable 8177 */ 8178 public void enableWifiConnectivityManager(boolean enabled) { 8179 sendMessage(CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER, enabled ? 1 : 0); 8180 } 8181 8182 /** 8183 * @param reason reason code from supplicant on network disconnected event 8184 * @return true if this is a suspicious disconnect 8185 */ 8186 static boolean unexpectedDisconnectedReason(int reason) { 8187 return reason == 2 // PREV_AUTH_NOT_VALID 8188 || reason == 6 // CLASS2_FRAME_FROM_NONAUTH_STA 8189 || reason == 7 // FRAME_FROM_NONASSOC_STA 8190 || reason == 8 // STA_HAS_LEFT 8191 || reason == 9 // STA_REQ_ASSOC_WITHOUT_AUTH 8192 || reason == 14 // MICHAEL_MIC_FAILURE 8193 || reason == 15 // 4WAY_HANDSHAKE_TIMEOUT 8194 || reason == 16 // GROUP_KEY_UPDATE_TIMEOUT 8195 || reason == 18 // GROUP_CIPHER_NOT_VALID 8196 || reason == 19 // PAIRWISE_CIPHER_NOT_VALID 8197 || reason == 23 // IEEE_802_1X_AUTH_FAILED 8198 || reason == 34; // DISASSOC_LOW_ACK 8199 } 8200 8201 /** 8202 * Update WifiMetrics before dumping 8203 */ 8204 void updateWifiMetrics() { 8205 int numSavedNetworks = mWifiConfigManager.getConfiguredNetworksSize(); 8206 int numOpenNetworks = 0; 8207 int numPersonalNetworks = 0; 8208 int numEnterpriseNetworks = 0; 8209 int numNetworksAddedByUser = 0; 8210 int numNetworksAddedByApps = 0; 8211 int numHiddenNetworks = 0; 8212 int numPasspoint = 0; 8213 for (WifiConfiguration config : mWifiConfigManager.getSavedNetworks()) { 8214 if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { 8215 numOpenNetworks++; 8216 } else if (config.isEnterprise()) { 8217 numEnterpriseNetworks++; 8218 } else { 8219 numPersonalNetworks++; 8220 } 8221 if (config.selfAdded) { 8222 numNetworksAddedByUser++; 8223 } else { 8224 numNetworksAddedByApps++; 8225 } 8226 if (config.hiddenSSID) { 8227 numHiddenNetworks++; 8228 } 8229 if (config.isPasspoint()) { 8230 numPasspoint++; 8231 } 8232 } 8233 mWifiMetrics.setNumSavedNetworks(numSavedNetworks); 8234 mWifiMetrics.setNumOpenNetworks(numOpenNetworks); 8235 mWifiMetrics.setNumPersonalNetworks(numPersonalNetworks); 8236 mWifiMetrics.setNumEnterpriseNetworks(numEnterpriseNetworks); 8237 mWifiMetrics.setNumNetworksAddedByUser(numNetworksAddedByUser); 8238 mWifiMetrics.setNumNetworksAddedByApps(numNetworksAddedByApps); 8239 mWifiMetrics.setNumHiddenNetworks(numHiddenNetworks); 8240 mWifiMetrics.setNumPasspointNetworks(numPasspoint); 8241 } 8242 8243 private static String getLinkPropertiesSummary(LinkProperties lp) { 8244 List<String> attributes = new ArrayList(6); 8245 if (lp.hasIPv4Address()) { 8246 attributes.add("v4"); 8247 } 8248 if (lp.hasIPv4DefaultRoute()) { 8249 attributes.add("v4r"); 8250 } 8251 if (lp.hasIPv4DnsServer()) { 8252 attributes.add("v4dns"); 8253 } 8254 if (lp.hasGlobalIPv6Address()) { 8255 attributes.add("v6"); 8256 } 8257 if (lp.hasIPv6DefaultRoute()) { 8258 attributes.add("v6r"); 8259 } 8260 if (lp.hasIPv6DnsServer()) { 8261 attributes.add("v6dns"); 8262 } 8263 8264 return TextUtils.join(" ", attributes); 8265 } 8266 8267 private void wnmFrameReceived(WnmData event) { 8268 // %012x HS20-SUBSCRIPTION-REMEDIATION "%u %s", osu_method, url 8269 // %012x HS20-DEAUTH-IMMINENT-NOTICE "%u %u %s", code, reauth_delay, url 8270 8271 Intent intent = new Intent(WifiManager.PASSPOINT_WNM_FRAME_RECEIVED_ACTION); 8272 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 8273 8274 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_BSSID, event.getBssid()); 8275 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_URL, event.getUrl()); 8276 8277 if (event.isDeauthEvent()) { 8278 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_ESS, event.isEss()); 8279 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_DELAY, event.getDelay()); 8280 } else { 8281 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_METHOD, event.getMethod()); 8282 WifiConfiguration config = getCurrentWifiConfiguration(); 8283 if (config != null && config.FQDN != null) { 8284 intent.putExtra(WifiManager.EXTRA_PASSPOINT_WNM_PPOINT_MATCH, 8285 mWifiConfigManager.matchProviderWithCurrentNetwork(config.FQDN)); 8286 } 8287 } 8288 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 8289 } 8290 8291 /** 8292 * Gets the SSID from the WifiConfiguration pointed at by 'mTargetNetworkId' 8293 * This should match the network config framework is attempting to connect to. 8294 */ 8295 private String getTargetSsid() { 8296 WifiConfiguration currentConfig = mWifiConfigManager.getWifiConfiguration(mTargetNetworkId); 8297 if (currentConfig != null) { 8298 return currentConfig.SSID; 8299 } 8300 return null; 8301 } 8302 8303 /** 8304 * Check if there is any connection request for WiFi network. 8305 * Note, caller of this helper function must acquire mWifiReqCountLock. 8306 */ 8307 private boolean hasConnectionRequests() { 8308 return mConnectionReqCount > 0 || mUntrustedReqCount > 0; 8309 } 8310} 8311