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