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