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