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