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