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