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