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