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