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