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