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