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