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