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