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