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