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