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