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