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