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