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