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