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