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