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.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT; 20 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY; 21 import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA256; 22 import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384; 23 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; 24 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING; 25 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; 26 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING; 27 import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN; 28 29 import static com.android.server.wifi.WifiDataStall.INVALID_THROUGHPUT; 30 31 import android.annotation.IntDef; 32 import android.annotation.NonNull; 33 import android.annotation.Nullable; 34 import android.app.ActivityManager; 35 import android.bluetooth.BluetoothAdapter; 36 import android.content.BroadcastReceiver; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.content.IntentFilter; 40 import android.content.pm.PackageManager; 41 import android.net.ConnectivityManager; 42 import android.net.DhcpResultsParcelable; 43 import android.net.InvalidPacketException; 44 import android.net.IpConfiguration; 45 import android.net.KeepalivePacketData; 46 import android.net.Layer2PacketParcelable; 47 import android.net.LinkProperties; 48 import android.net.MacAddress; 49 import android.net.MatchAllNetworkSpecifier; 50 import android.net.NattKeepalivePacketData; 51 import android.net.Network; 52 import android.net.NetworkAgent; 53 import android.net.NetworkAgentConfig; 54 import android.net.NetworkCapabilities; 55 import android.net.NetworkInfo; 56 import android.net.NetworkInfo.DetailedState; 57 import android.net.NetworkProvider; 58 import android.net.SocketKeepalive; 59 import android.net.StaticIpConfiguration; 60 import android.net.TcpKeepalivePacketData; 61 import android.net.Uri; 62 import android.net.ip.IIpClient; 63 import android.net.ip.IpClientCallbacks; 64 import android.net.ip.IpClientManager; 65 import android.net.shared.Layer2Information; 66 import android.net.shared.ProvisioningConfiguration; 67 import android.net.shared.ProvisioningConfiguration.ScanResultInfo; 68 import android.net.util.MacAddressUtils; 69 import android.net.util.NetUtils; 70 import android.net.wifi.IActionListener; 71 import android.net.wifi.INetworkRequestMatchCallback; 72 import android.net.wifi.ScanResult; 73 import android.net.wifi.SupplicantState; 74 import android.net.wifi.WifiAnnotations.WifiStandard; 75 import android.net.wifi.WifiConfiguration; 76 import android.net.wifi.WifiEnterpriseConfig; 77 import android.net.wifi.WifiInfo; 78 import android.net.wifi.WifiManager; 79 import android.net.wifi.WifiManager.DeviceMobilityState; 80 import android.net.wifi.WifiNetworkAgentSpecifier; 81 import android.net.wifi.WifiScanner; 82 import android.net.wifi.hotspot2.IProvisioningCallback; 83 import android.net.wifi.hotspot2.OsuProvider; 84 import android.net.wifi.nl80211.DeviceWiphyCapabilities; 85 import android.net.wifi.nl80211.WifiNl80211Manager; 86 import android.net.wifi.p2p.WifiP2pManager; 87 import android.os.BatteryStatsManager; 88 import android.os.Bundle; 89 import android.os.ConditionVariable; 90 import android.os.IBinder; 91 import android.os.Looper; 92 import android.os.Message; 93 import android.os.Messenger; 94 import android.os.PowerManager; 95 import android.os.Process; 96 import android.os.RemoteException; 97 import android.os.UserHandle; 98 import android.os.UserManager; 99 import android.os.WorkSource; 100 import android.provider.Settings; 101 import android.system.OsConstants; 102 import android.telephony.SubscriptionManager; 103 import android.telephony.TelephonyManager; 104 import android.text.TextUtils; 105 import android.util.Log; 106 import android.util.Pair; 107 import android.util.SparseArray; 108 109 import com.android.internal.annotations.VisibleForTesting; 110 import com.android.internal.util.AsyncChannel; 111 import com.android.internal.util.MessageUtils; 112 import com.android.internal.util.Protocol; 113 import com.android.internal.util.State; 114 import com.android.internal.util.StateMachine; 115 import com.android.net.module.util.Inet4AddressUtils; 116 import com.android.server.wifi.MboOceController.BtmFrameData; 117 import com.android.server.wifi.WifiCarrierInfoManager.SimAuthRequestData; 118 import com.android.server.wifi.WifiCarrierInfoManager.SimAuthResponseData; 119 import com.android.server.wifi.hotspot2.AnqpEvent; 120 import com.android.server.wifi.hotspot2.IconEvent; 121 import com.android.server.wifi.hotspot2.NetworkDetail; 122 import com.android.server.wifi.hotspot2.PasspointManager; 123 import com.android.server.wifi.hotspot2.WnmData; 124 import com.android.server.wifi.p2p.WifiP2pServiceImpl; 125 import com.android.server.wifi.proto.WifiStatsLog; 126 import com.android.server.wifi.proto.nano.WifiMetricsProto; 127 import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent; 128 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent; 129 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; 130 import com.android.server.wifi.util.ExternalCallbackTracker; 131 import com.android.server.wifi.util.NativeUtil; 132 import com.android.server.wifi.util.RssiUtil; 133 import com.android.server.wifi.util.ScanResultUtil; 134 import com.android.server.wifi.util.WifiPermissionsUtil; 135 import com.android.server.wifi.util.WifiPermissionsWrapper; 136 import com.android.wifi.resources.R; 137 138 import java.io.BufferedReader; 139 import java.io.FileDescriptor; 140 import java.io.FileNotFoundException; 141 import java.io.FileReader; 142 import java.io.IOException; 143 import java.io.PrintWriter; 144 import java.lang.annotation.Retention; 145 import java.lang.annotation.RetentionPolicy; 146 import java.net.Inet4Address; 147 import java.net.Inet6Address; 148 import java.net.InetAddress; 149 import java.time.Duration; 150 import java.util.ArrayList; 151 import java.util.Arrays; 152 import java.util.List; 153 import java.util.Set; 154 import java.util.concurrent.atomic.AtomicBoolean; 155 import java.util.concurrent.atomic.AtomicInteger; 156 157 /** 158 * Implementation of ClientMode. Event handling for Client mode logic is done here, 159 * and all changes in connectivity state are initiated here. 160 * 161 * @hide 162 */ 163 public class ClientModeImpl extends StateMachine { 164 165 private static final String NETWORKTYPE = "WIFI"; 166 @VisibleForTesting public static final short NUM_LOG_RECS_NORMAL = 100; 167 @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE_LOW_MEMORY = 200; 168 @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE = 3000; 169 170 // Association rejection reason codes 171 @VisibleForTesting 172 protected static final int REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; 173 174 private static final String TAG = "WifiClientModeImpl"; 175 176 private static final int ONE_HOUR_MILLI = 1000 * 60 * 60; 177 178 private static final String GOOGLE_OUI = "DA-A1-19"; 179 180 private static final String EXTRA_OSU_ICON_QUERY_BSSID = "BSSID"; 181 private static final String EXTRA_OSU_ICON_QUERY_FILENAME = "FILENAME"; 182 private static final String EXTRA_OSU_PROVIDER = "OsuProvider"; 183 private static final String EXTRA_UID = "uid"; 184 private static final String EXTRA_PACKAGE_NAME = "PackageName"; 185 private static final String EXTRA_PASSPOINT_CONFIGURATION = "PasspointConfiguration"; 186 private static final int IPCLIENT_STARTUP_TIMEOUT_MS = 20 * 60 * 1000; // 20 minutes! 187 private static final int IPCLIENT_SHUTDOWN_TIMEOUT_MS = 60_000; // 60 seconds 188 189 private boolean mVerboseLoggingEnabled = false; 190 private final WifiPermissionsWrapper mWifiPermissionsWrapper; 191 192 /* debug flag, indicating if handling of ASSOCIATION_REJECT ended up blacklisting 193 * the corresponding BSSID. 194 */ 195 private boolean mDidBlackListBSSID = false; 196 197 /** 198 * Log with error attribute 199 * 200 * @param s is string log 201 */ 202 @Override loge(String s)203 protected void loge(String s) { 204 Log.e(getName(), s); 205 } 206 @Override logd(String s)207 protected void logd(String s) { 208 Log.d(getName(), s); 209 } 210 @Override log(String s)211 protected void log(String s) { 212 Log.d(getName(), s); 213 } 214 private final WifiMetrics mWifiMetrics; 215 private final WifiInjector mWifiInjector; 216 private final WifiMonitor mWifiMonitor; 217 private final WifiNative mWifiNative; 218 private final WifiPermissionsUtil mWifiPermissionsUtil; 219 private final WifiConfigManager mWifiConfigManager; 220 private final WifiConnectivityManager mWifiConnectivityManager; 221 private final BssidBlocklistMonitor mBssidBlocklistMonitor; 222 private ConnectivityManager mCm; 223 private BaseWifiDiagnostics mWifiDiagnostics; 224 private final boolean mP2pSupported; 225 private final AtomicBoolean mP2pConnected = new AtomicBoolean(false); 226 private boolean mTemporarilyDisconnectWifi = false; 227 private final Clock mClock; 228 private final PropertyService mPropertyService; 229 private final BuildProperties mBuildProperties; 230 private final WifiCountryCode mCountryCode; 231 private final WifiScoreCard mWifiScoreCard; 232 private final WifiHealthMonitor mWifiHealthMonitor; 233 private final WifiScoreReport mWifiScoreReport; 234 private final SarManager mSarManager; 235 private final WifiTrafficPoller mWifiTrafficPoller; getWifiScoreReport()236 public WifiScoreReport getWifiScoreReport() { 237 return mWifiScoreReport; 238 } 239 private final PasspointManager mPasspointManager; 240 private final WifiDataStall mWifiDataStall; 241 private final LinkProbeManager mLinkProbeManager; 242 private final MboOceController mMboOceController; 243 244 private final McastLockManagerFilterController mMcastLockManagerFilterController; 245 private final ActivityManager mActivityManager; 246 247 private boolean mScreenOn = false; 248 249 private String mInterfaceName; 250 251 private int mLastSignalLevel = -1; 252 private String mLastBssid; 253 private int mLastNetworkId; // The network Id we successfully joined 254 // The subId used by WifiConfiguration with SIM credential which was connected successfully 255 private int mLastSubId; 256 private String mLastSimBasedConnectionCarrierName; 257 258 private boolean mIpReachabilityDisconnectEnabled = true; 259 processRssiThreshold(byte curRssi, int reason, WifiNative.WifiRssiEventHandler rssiHandler)260 private void processRssiThreshold(byte curRssi, int reason, 261 WifiNative.WifiRssiEventHandler rssiHandler) { 262 if (curRssi == Byte.MAX_VALUE || curRssi == Byte.MIN_VALUE) { 263 Log.wtf(TAG, "processRssiThreshold: Invalid rssi " + curRssi); 264 return; 265 } 266 for (int i = 0; i < mRssiRanges.length; i++) { 267 if (curRssi < mRssiRanges[i]) { 268 // Assume sorted values(ascending order) for rssi, 269 // bounded by high(127) and low(-128) at extremeties 270 byte maxRssi = mRssiRanges[i]; 271 byte minRssi = mRssiRanges[i - 1]; 272 // This value of hw has to be believed as this value is averaged and has breached 273 // the rssi thresholds and raised event to host. This would be eggregious if this 274 // value is invalid 275 mWifiInfo.setRssi(curRssi); 276 updateCapabilities(); 277 int ret = startRssiMonitoringOffload(maxRssi, minRssi, rssiHandler); 278 Log.d(TAG, "Re-program RSSI thresholds for " + getWhatToString(reason) 279 + ": [" + minRssi + ", " + maxRssi + "], curRssi=" + curRssi 280 + " ret=" + ret); 281 break; 282 } 283 } 284 } 285 286 private boolean mEnableRssiPolling = false; 287 // Accessed via Binder thread ({get,set}PollRssiIntervalMsecs), and the main Wifi thread. 288 private volatile int mPollRssiIntervalMsecs = -1; 289 private int mRssiPollToken = 0; 290 /* 3 operational states for STA operation: CONNECT_MODE, SCAN_ONLY_MODE, SCAN_ONLY_WIFI_OFF_MODE 291 * In CONNECT_MODE, the STA can scan and connect to an access point 292 * In SCAN_ONLY_MODE, the STA can only scan for access points 293 * In SCAN_ONLY_WIFI_OFF_MODE, the STA can only scan for access points with wifi toggle being off 294 */ 295 private int mOperationalMode = DISABLED_MODE; 296 297 // variable indicating we are expecting a mode switch - do not attempt recovery for failures 298 private boolean mModeChange = false; 299 300 private ClientModeManager.Listener mClientModeCallback = null; 301 302 private boolean mBluetoothConnectionActive = false; 303 304 private PowerManager.WakeLock mSuspendWakeLock; 305 306 /** 307 * Maximum allowable interval in milliseconds between polling for RSSI and linkspeed 308 * information. This is also used as the polling interval for WifiTrafficPoller, which updates 309 * its data activity on every CMD_RSSI_POLL. 310 */ 311 private static final int MAXIMUM_POLL_RSSI_INTERVAL_MSECS = 6000; 312 313 /** 314 * Interval in milliseconds between receiving a disconnect event 315 * while connected to a good AP, and handling the disconnect proper 316 */ 317 private static final int LINK_FLAPPING_DEBOUNCE_MSEC = 4000; 318 319 /** 320 * Delay between supplicant restarts upon failure to establish connection 321 */ 322 private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000; 323 324 /** 325 * Number of times we attempt to restart supplicant 326 */ 327 private static final int SUPPLICANT_RESTART_TRIES = 5; 328 329 /** 330 * Value to set in wpa_supplicant "bssid" field when we don't want to restrict connection to 331 * a specific AP. 332 */ 333 public static final String SUPPLICANT_BSSID_ANY = "any"; 334 335 /** 336 * The link properties of the wifi interface. 337 * Do not modify this directly; use updateLinkProperties instead. 338 */ 339 private LinkProperties mLinkProperties; 340 341 /* Tracks sequence number on a periodic scan message */ 342 private int mPeriodicScanToken = 0; 343 344 private Context mContext; 345 346 private final Object mDhcpResultsParcelableLock = new Object(); 347 @NonNull 348 private DhcpResultsParcelable mDhcpResultsParcelable = new DhcpResultsParcelable(); 349 350 // NOTE: Do not return to clients - see syncRequestConnectionInfo() 351 private final ExtendedWifiInfo mWifiInfo; 352 // TODO : remove this member. It should be possible to only call sendNetworkChangeBroadcast when 353 // the state actually changed, and to deduce the state of the agent from the state of the 354 // machine when generating the NetworkInfo for the broadcast. 355 private DetailedState mNetworkAgentState; 356 private SupplicantStateTracker mSupplicantStateTracker; 357 358 // Indicates that framework is attempting to roam, set true on CMD_START_ROAM, set false when 359 // wifi connects or fails to connect 360 private boolean mIsAutoRoaming = false; 361 362 // Roaming failure count 363 private int mRoamFailCount = 0; 364 365 // This is the BSSID we are trying to associate to, it can be set to SUPPLICANT_BSSID_ANY 366 // if we havent selected a BSSID for joining. 367 private String mTargetBssid = SUPPLICANT_BSSID_ANY; 368 // This one is used to track the current target network ID. This is used for error 369 // handling during connection setup since many error message from supplicant does not report 370 // SSID. Once connected, it will be set to invalid 371 private int mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 372 private long mLastDriverRoamAttempt = 0; 373 private WifiConfiguration mTargetWifiConfiguration = null; 374 getPollRssiIntervalMsecs()375 int getPollRssiIntervalMsecs() { 376 if (mPollRssiIntervalMsecs > 0) { 377 return mPollRssiIntervalMsecs; 378 } 379 return Math.min(mContext.getResources().getInteger( 380 R.integer.config_wifiPollRssiIntervalMilliseconds), 381 MAXIMUM_POLL_RSSI_INTERVAL_MSECS); 382 } 383 setPollRssiIntervalMsecs(int newPollIntervalMsecs)384 void setPollRssiIntervalMsecs(int newPollIntervalMsecs) { 385 mPollRssiIntervalMsecs = newPollIntervalMsecs; 386 } 387 388 /** 389 * Method to clear {@link #mTargetBssid} and reset the current connected network's 390 * bssid in wpa_supplicant after a roam/connect attempt. 391 */ clearTargetBssid(String dbg)392 public boolean clearTargetBssid(String dbg) { 393 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 394 if (config == null) { 395 return false; 396 } 397 String bssid = SUPPLICANT_BSSID_ANY; 398 if (config.BSSID != null) { 399 bssid = config.BSSID; 400 if (mVerboseLoggingEnabled) { 401 Log.d(TAG, "force BSSID to " + bssid + "due to config"); 402 } 403 } 404 if (mVerboseLoggingEnabled) { 405 logd(dbg + " clearTargetBssid " + bssid + " key=" + config.getKey()); 406 } 407 mTargetBssid = bssid; 408 return mWifiNative.setConfiguredNetworkBSSID(mInterfaceName, bssid); 409 } 410 411 /** 412 * Set Config's default BSSID (for association purpose) and {@link #mTargetBssid} 413 * @param config config need set BSSID 414 * @param bssid default BSSID to assocaite with when connect to this network 415 * @return false -- does not change the current default BSSID of the configure 416 * true -- change the current default BSSID of the configur 417 */ setTargetBssid(WifiConfiguration config, String bssid)418 private boolean setTargetBssid(WifiConfiguration config, String bssid) { 419 if (config == null || bssid == null) { 420 return false; 421 } 422 if (config.BSSID != null) { 423 bssid = config.BSSID; 424 if (mVerboseLoggingEnabled) { 425 Log.d(TAG, "force BSSID to " + bssid + "due to config"); 426 } 427 } 428 if (mVerboseLoggingEnabled) { 429 Log.d(TAG, "setTargetBssid set to " + bssid + " key=" + config.getKey()); 430 } 431 mTargetBssid = bssid; 432 config.getNetworkSelectionStatus().setNetworkSelectionBSSID(bssid); 433 return true; 434 } 435 436 private volatile IpClientManager mIpClient; 437 private IpClientCallbacksImpl mIpClientCallbacks; 438 439 // Channel for sending replies. 440 private AsyncChannel mReplyChannel = new AsyncChannel(); 441 442 // Used to initiate a connection with WifiP2pService 443 private AsyncChannel mWifiP2pChannel; 444 445 private WifiNetworkFactory mNetworkFactory; 446 private UntrustedWifiNetworkFactory mUntrustedNetworkFactory; 447 private WifiNetworkAgent mNetworkAgent; 448 449 private byte[] mRssiRanges; 450 451 // Used to filter out requests we couldn't possibly satisfy. 452 private final NetworkCapabilities mNetworkCapabilitiesFilter; 453 454 private final ExternalCallbackTracker<IActionListener> mProcessingActionListeners; 455 456 /* The base for wifi message types */ 457 static final int BASE = Protocol.BASE_WIFI; 458 /* BT state change, e.g., on or off */ 459 static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 31; 460 /* BT connection state change, e.g., connected or disconnected */ 461 static final int CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE = BASE + 32; 462 463 /* Get adaptors */ 464 static final int CMD_GET_SUPPORTED_FEATURES = BASE + 61; 465 /* Get Link Layer Stats thru HAL */ 466 static final int CMD_GET_LINK_LAYER_STATS = BASE + 63; 467 /* Supplicant commands after driver start*/ 468 /* Set operational mode. CONNECT, SCAN ONLY, SCAN_ONLY with Wi-Fi off mode */ 469 static final int CMD_SET_OPERATIONAL_MODE = BASE + 72; 470 /* Disconnect from a network */ 471 static final int CMD_DISCONNECT = BASE + 73; 472 /* Reconnect to a network */ 473 static final int CMD_RECONNECT = BASE + 74; 474 /* Reassociate to a network */ 475 static final int CMD_REASSOCIATE = BASE + 75; 476 477 /* Controls suspend mode optimizations 478 * 479 * When high perf mode is enabled, suspend mode optimizations are disabled 480 * 481 * When high perf mode is disabled, suspend mode optimizations are enabled 482 * 483 * Suspend mode optimizations include: 484 * - packet filtering 485 * - turn off roaming 486 * - DTIM wake up settings 487 */ 488 static final int CMD_SET_HIGH_PERF_MODE = BASE + 77; 489 /* Enables RSSI poll */ 490 static final int CMD_ENABLE_RSSI_POLL = BASE + 82; 491 /* RSSI poll */ 492 static final int CMD_RSSI_POLL = BASE + 83; 493 /** Runs RSSI poll once */ 494 static final int CMD_ONESHOT_RSSI_POLL = BASE + 84; 495 /* Enable suspend mode optimizations in the driver */ 496 static final int CMD_SET_SUSPEND_OPT_ENABLED = BASE + 86; 497 498 /* Enable TDLS on a specific MAC address */ 499 static final int CMD_ENABLE_TDLS = BASE + 92; 500 501 /** 502 * Watchdog for protecting against b/16823537 503 * Leave time for 4-way handshake to succeed 504 */ 505 static final int ROAM_GUARD_TIMER_MSEC = 15000; 506 507 int mRoamWatchdogCount = 0; 508 /* Roam state watchdog */ 509 static final int CMD_ROAM_WATCHDOG_TIMER = BASE + 94; 510 /* Screen change intent handling */ 511 static final int CMD_SCREEN_STATE_CHANGED = BASE + 95; 512 513 /* Disconnecting state watchdog */ 514 static final int CMD_DISCONNECTING_WATCHDOG_TIMER = BASE + 96; 515 516 /* SIM is removed; reset any cached data for it */ 517 static final int CMD_RESET_SIM_NETWORKS = BASE + 101; 518 519 @Retention(RetentionPolicy.SOURCE) 520 @IntDef(prefix = {"RESET_SIM_REASON_"}, 521 value = { 522 RESET_SIM_REASON_SIM_REMOVED, 523 RESET_SIM_REASON_SIM_INSERTED, 524 RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED}) 525 @interface ResetSimReason {} 526 static final int RESET_SIM_REASON_SIM_REMOVED = 0; 527 static final int RESET_SIM_REASON_SIM_INSERTED = 1; 528 static final int RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED = 2; 529 530 /* OSU APIs */ 531 static final int CMD_QUERY_OSU_ICON = BASE + 104; 532 533 /* Commands from/to the SupplicantStateTracker */ 534 /* Reset the supplicant state tracker */ 535 static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111; 536 537 int mDisconnectingWatchdogCount = 0; 538 static final int DISCONNECTING_GUARD_TIMER_MSEC = 5000; 539 540 /** 541 * Indicates the end of boot process, should be used to trigger load from config store, 542 * initiate connection attempt, etc. 543 * */ 544 static final int CMD_BOOT_COMPLETED = BASE + 134; 545 /** 546 * Initialize ClientModeImpl. This is currently used to initialize the 547 * {@link HalDeviceManager} module. 548 */ 549 static final int CMD_INITIALIZE = BASE + 135; 550 551 /* We now have a valid IP configuration. */ 552 static final int CMD_IP_CONFIGURATION_SUCCESSFUL = BASE + 138; 553 /* We no longer have a valid IP configuration. */ 554 static final int CMD_IP_CONFIGURATION_LOST = BASE + 139; 555 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 556 static final int CMD_UPDATE_LINKPROPERTIES = BASE + 140; 557 558 static final int CMD_START_CONNECT = BASE + 143; 559 560 private static final int NETWORK_STATUS_UNWANTED_DISCONNECT = 0; 561 private static final int NETWORK_STATUS_UNWANTED_VALIDATION_FAILED = 1; 562 private static final int NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN = 2; 563 564 static final int CMD_UNWANTED_NETWORK = BASE + 144; 565 566 static final int CMD_START_ROAM = BASE + 145; 567 568 static final int CMD_NETWORK_STATUS = BASE + 148; 569 570 /* A layer 3 neighbor on the Wi-Fi link became unreachable. */ 571 static final int CMD_IP_REACHABILITY_LOST = BASE + 149; 572 573 static final int CMD_ACCEPT_UNVALIDATED = BASE + 153; 574 575 /* used to offload sending IP packet */ 576 static final int CMD_START_IP_PACKET_OFFLOAD = BASE + 160; 577 578 /* used to stop offload sending IP packet */ 579 static final int CMD_STOP_IP_PACKET_OFFLOAD = BASE + 161; 580 581 /* used to start rssi monitoring in hw */ 582 static final int CMD_START_RSSI_MONITORING_OFFLOAD = BASE + 162; 583 584 /* used to stop rssi moniroting in hw */ 585 static final int CMD_STOP_RSSI_MONITORING_OFFLOAD = BASE + 163; 586 587 /* used to indicated RSSI threshold breach in hw */ 588 static final int CMD_RSSI_THRESHOLD_BREACHED = BASE + 164; 589 590 /** 591 * Used to handle messages bounced between ClientModeImpl and IpClient. 592 */ 593 static final int CMD_IPV4_PROVISIONING_SUCCESS = BASE + 200; 594 static final int CMD_IPV4_PROVISIONING_FAILURE = BASE + 201; 595 596 /* Push a new APF program to the HAL */ 597 static final int CMD_INSTALL_PACKET_FILTER = BASE + 202; 598 599 /* Enable/disable fallback packet filtering */ 600 static final int CMD_SET_FALLBACK_PACKET_FILTERING = BASE + 203; 601 602 /* Enable/disable Neighbor Discovery offload functionality. */ 603 static final int CMD_CONFIG_ND_OFFLOAD = BASE + 204; 604 605 /* Read the APF program & data buffer */ 606 static final int CMD_READ_PACKET_FILTER = BASE + 208; 607 608 /** Used to add packet filter to apf. */ 609 static final int CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF = BASE + 209; 610 611 /** Used to remove packet filter from apf. */ 612 static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF = BASE + 210; 613 614 /* Indicates that diagnostics should time out a connection start event. */ 615 static final int CMD_DIAGS_CONNECT_TIMEOUT = BASE + 252; 616 617 // Start subscription provisioning with a given provider 618 private static final int CMD_START_SUBSCRIPTION_PROVISIONING = BASE + 254; 619 620 @VisibleForTesting 621 static final int CMD_PRE_DHCP_ACTION = BASE + 255; 622 private static final int CMD_PRE_DHCP_ACTION_COMPLETE = BASE + 256; 623 private static final int CMD_POST_DHCP_ACTION = BASE + 257; 624 625 private static final int CMD_CONNECT_NETWORK = BASE + 258; 626 private static final int CMD_SAVE_NETWORK = BASE + 259; 627 628 /* Start connection to FILS AP*/ 629 static final int CMD_START_FILS_CONNECTION = BASE + 262; 630 631 private static final int CMD_GET_CURRENT_NETWORK = BASE + 263; 632 633 // For message logging. 634 private static final Class[] sMessageClasses = { 635 AsyncChannel.class, ClientModeImpl.class }; 636 private static final SparseArray<String> sGetWhatToString = 637 MessageUtils.findMessageNames(sMessageClasses); 638 639 640 /* Wifi state machine modes of operation */ 641 /* CONNECT_MODE - connect to any 'known' AP when it becomes available */ 642 public static final int CONNECT_MODE = 1; 643 /* SCAN_ONLY_MODE - don't connect to any APs; scan, but only while apps hold lock */ 644 public static final int SCAN_ONLY_MODE = 2; 645 /* SCAN_ONLY_WITH_WIFI_OFF - scan, but don't connect to any APs */ 646 public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3; 647 /* DISABLED_MODE - Don't connect, don't scan, don't be an AP */ 648 public static final int DISABLED_MODE = 4; 649 650 private static final int SUCCESS = 1; 651 private static final int FAILURE = -1; 652 653 /* Tracks if suspend optimizations need to be disabled by DHCP, 654 * screen or due to high perf mode. 655 * When any of them needs to disable it, we keep the suspend optimizations 656 * disabled 657 */ 658 private int mSuspendOptNeedsDisabled = 0; 659 660 private static final int SUSPEND_DUE_TO_DHCP = 1; 661 private static final int SUSPEND_DUE_TO_HIGH_PERF = 1 << 1; 662 private static final int SUSPEND_DUE_TO_SCREEN = 1 << 2; 663 664 /** 665 * Time window in milliseconds for which we send 666 * {@link NetworkAgent#explicitlySelected(boolean, boolean)} 667 * after connecting to the network which the user last selected. 668 */ 669 @VisibleForTesting 670 public static final int LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS = 30 * 1000; 671 672 /* Tracks if user has enabled Connected Mac Randomization through settings */ 673 674 /** 675 * Supplicant scan interval in milliseconds. 676 * Comes from {@link Settings.Global#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} or 677 * from the default config if the setting is not set 678 */ 679 private long mSupplicantScanIntervalMs; 680 681 int mRunningBeaconCount = 0; 682 683 /* Default parent state */ 684 private State mDefaultState = new DefaultState(); 685 /* Connecting to an access point */ 686 private State mConnectModeState = new ConnectModeState(); 687 /* Connected at 802.11 (L2) level */ 688 private State mL2ConnectedState = new L2ConnectedState(); 689 /* fetching IP after connection to access point (assoc+auth complete) */ 690 private State mObtainingIpState = new ObtainingIpState(); 691 /* Connected with IP addr */ 692 private State mConnectedState = new ConnectedState(); 693 /* Roaming */ 694 private State mRoamingState = new RoamingState(); 695 /* disconnect issued, waiting for network disconnect confirmation */ 696 private State mDisconnectingState = new DisconnectingState(); 697 /* Network is not connected, supplicant assoc+auth is not complete */ 698 private State mDisconnectedState = new DisconnectedState(); 699 700 /* 701 * FILS connection related variables. 702 */ 703 /* To indicate to IpClient whether HLP IEs were included or not in assoc request */ 704 private boolean mSentHLPs = false; 705 /* Tracks IpClient start state until (FILS_)NETWORK_CONNECTION_EVENT event */ 706 private boolean mIpClientWithPreConnection = false; 707 708 /** 709 * One of {@link WifiManager#WIFI_STATE_DISABLED}, 710 * {@link WifiManager#WIFI_STATE_DISABLING}, 711 * {@link WifiManager#WIFI_STATE_ENABLED}, 712 * {@link WifiManager#WIFI_STATE_ENABLING}, 713 * {@link WifiManager#WIFI_STATE_UNKNOWN} 714 */ 715 private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED); 716 717 /** 718 * Work source to use to blame usage on the WiFi service 719 */ 720 public static final WorkSource WIFI_WORK_SOURCE = new WorkSource(Process.WIFI_UID); 721 722 private final BatteryStatsManager mBatteryStatsManager; 723 724 private final WifiCarrierInfoManager mWifiCarrierInfoManager; 725 726 727 // Used for debug and stats gathering 728 private static int sScanAlarmIntentCount = 0; 729 730 private FrameworkFacade mFacade; 731 private WifiStateTracker mWifiStateTracker; 732 private final BackupManagerProxy mBackupManagerProxy; 733 private final WrongPasswordNotifier mWrongPasswordNotifier; 734 private final EapFailureNotifier mEapFailureNotifier; 735 private final SimRequiredNotifier mSimRequiredNotifier; 736 private final ConnectionFailureNotifier mConnectionFailureNotifier; 737 private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; 738 // Maximum duration to continue to log Wifi usability stats after a data stall is triggered. 739 @VisibleForTesting 740 public static final long DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS = 30 * 1000; 741 private long mDataStallTriggerTimeMs = -1; 742 private int mLastStatusDataStall = WifiIsUnusableEvent.TYPE_UNKNOWN; 743 ClientModeImpl(Context context, FrameworkFacade facade, Looper looper, UserManager userManager, WifiInjector wifiInjector, BackupManagerProxy backupManagerProxy, WifiCountryCode countryCode, WifiNative wifiNative, WrongPasswordNotifier wrongPasswordNotifier, SarManager sarManager, WifiTrafficPoller wifiTrafficPoller, LinkProbeManager linkProbeManager, BatteryStatsManager batteryStatsManager, SupplicantStateTracker supplicantStateTracker, MboOceController mboOceController, WifiCarrierInfoManager wifiCarrierInfoManager, EapFailureNotifier eapFailureNotifier, SimRequiredNotifier simRequiredNotifier)744 public ClientModeImpl(Context context, FrameworkFacade facade, Looper looper, 745 UserManager userManager, WifiInjector wifiInjector, 746 BackupManagerProxy backupManagerProxy, WifiCountryCode countryCode, 747 WifiNative wifiNative, WrongPasswordNotifier wrongPasswordNotifier, 748 SarManager sarManager, WifiTrafficPoller wifiTrafficPoller, 749 LinkProbeManager linkProbeManager, 750 BatteryStatsManager batteryStatsManager, 751 SupplicantStateTracker supplicantStateTracker, 752 MboOceController mboOceController, 753 WifiCarrierInfoManager wifiCarrierInfoManager, 754 EapFailureNotifier eapFailureNotifier, 755 SimRequiredNotifier simRequiredNotifier) { 756 super(TAG, looper); 757 mWifiInjector = wifiInjector; 758 mWifiMetrics = mWifiInjector.getWifiMetrics(); 759 mClock = wifiInjector.getClock(); 760 mPropertyService = wifiInjector.getPropertyService(); 761 mBuildProperties = wifiInjector.getBuildProperties(); 762 mWifiScoreCard = wifiInjector.getWifiScoreCard(); 763 mContext = context; 764 mFacade = facade; 765 mWifiNative = wifiNative; 766 mBackupManagerProxy = backupManagerProxy; 767 mWrongPasswordNotifier = wrongPasswordNotifier; 768 mEapFailureNotifier = eapFailureNotifier; 769 mSimRequiredNotifier = simRequiredNotifier; 770 mSarManager = sarManager; 771 mWifiTrafficPoller = wifiTrafficPoller; 772 mLinkProbeManager = linkProbeManager; 773 mMboOceController = mboOceController; 774 mWifiCarrierInfoManager = wifiCarrierInfoManager; 775 mNetworkAgentState = DetailedState.DISCONNECTED; 776 777 mBatteryStatsManager = batteryStatsManager; 778 mWifiStateTracker = wifiInjector.getWifiStateTracker(); 779 780 mP2pSupported = mContext.getPackageManager().hasSystemFeature( 781 PackageManager.FEATURE_WIFI_DIRECT); 782 783 mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil(); 784 mWifiConfigManager = mWifiInjector.getWifiConfigManager(); 785 786 mPasspointManager = mWifiInjector.getPasspointManager(); 787 788 mWifiMonitor = mWifiInjector.getWifiMonitor(); 789 mWifiDiagnostics = mWifiInjector.getWifiDiagnostics(); 790 mWifiPermissionsWrapper = mWifiInjector.getWifiPermissionsWrapper(); 791 mWifiDataStall = mWifiInjector.getWifiDataStall(); 792 793 mWifiInfo = new ExtendedWifiInfo(context); 794 mSupplicantStateTracker = supplicantStateTracker; 795 mWifiConnectivityManager = mWifiInjector.makeWifiConnectivityManager(this); 796 mBssidBlocklistMonitor = mWifiInjector.getBssidBlocklistMonitor(); 797 mConnectionFailureNotifier = mWifiInjector.makeConnectionFailureNotifier( 798 mWifiConnectivityManager); 799 800 mLinkProperties = new LinkProperties(); 801 mMcastLockManagerFilterController = new McastLockManagerFilterController(); 802 mActivityManager = context.getSystemService(ActivityManager.class); 803 804 mLastBssid = null; 805 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 806 mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 807 mLastSimBasedConnectionCarrierName = null; 808 mLastSignalLevel = -1; 809 810 mCountryCode = countryCode; 811 812 mWifiScoreReport = new WifiScoreReport(mWifiInjector.getScoringParams(), mClock, 813 mWifiMetrics, mWifiInfo, mWifiNative, mBssidBlocklistMonitor, 814 mWifiInjector.getWifiThreadRunner(), mWifiInjector.getDeviceConfigFacade(), 815 mContext, looper, mFacade); 816 817 mNetworkCapabilitiesFilter = new NetworkCapabilities.Builder() 818 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 819 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 820 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) 821 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) 822 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) 823 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 824 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) 825 // TODO - needs to be a bit more dynamic 826 .setLinkUpstreamBandwidthKbps(1024 * 1024) 827 .setLinkDownstreamBandwidthKbps(1024 * 1024) 828 .setNetworkSpecifier(new MatchAllNetworkSpecifier()) 829 .build(); 830 // Make the network factories. 831 mNetworkFactory = mWifiInjector.makeWifiNetworkFactory( 832 mNetworkCapabilitiesFilter, mWifiConnectivityManager); 833 // We can't filter untrusted network in the capabilities filter because a trusted 834 // network would still satisfy a request that accepts untrusted ones. 835 // We need a second network factory for untrusted network requests because we need a 836 // different score filter for these requests. 837 mUntrustedNetworkFactory = mWifiInjector.makeUntrustedWifiNetworkFactory( 838 mNetworkCapabilitiesFilter, mWifiConnectivityManager); 839 840 mWifiNetworkSuggestionsManager = mWifiInjector.getWifiNetworkSuggestionsManager(); 841 mProcessingActionListeners = new ExternalCallbackTracker<>(getHandler()); 842 mWifiHealthMonitor = mWifiInjector.getWifiHealthMonitor(); 843 844 IntentFilter filter = new IntentFilter(); 845 filter.addAction(Intent.ACTION_SCREEN_ON); 846 filter.addAction(Intent.ACTION_SCREEN_OFF); 847 mContext.registerReceiver( 848 new BroadcastReceiver() { 849 @Override 850 public void onReceive(Context context, Intent intent) { 851 String action = intent.getAction(); 852 853 if (action.equals(Intent.ACTION_SCREEN_ON)) { 854 sendMessage(CMD_SCREEN_STATE_CHANGED, 1); 855 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 856 sendMessage(CMD_SCREEN_STATE_CHANGED, 0); 857 } 858 } 859 }, filter); 860 861 PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 862 863 mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend"); 864 mSuspendWakeLock.setReferenceCounted(false); 865 866 mWifiConfigManager.addOnNetworkUpdateListener(new OnNetworkUpdateListener()); 867 868 // CHECKSTYLE:OFF IndentationCheck 869 addState(mDefaultState); 870 addState(mConnectModeState, mDefaultState); 871 addState(mL2ConnectedState, mConnectModeState); 872 addState(mObtainingIpState, mL2ConnectedState); 873 addState(mConnectedState, mL2ConnectedState); 874 addState(mRoamingState, mL2ConnectedState); 875 addState(mDisconnectingState, mConnectModeState); 876 addState(mDisconnectedState, mConnectModeState); 877 // CHECKSTYLE:ON IndentationCheck 878 879 setInitialState(mDefaultState); 880 881 setLogRecSize(NUM_LOG_RECS_NORMAL); 882 setLogOnlyTransitions(false); 883 } 884 885 @Override start()886 public void start() { 887 super.start(); 888 889 PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 890 891 // Learn the initial state of whether the screen is on. 892 // We update this field when we receive broadcasts from the system. 893 handleScreenStateChanged(powerManager.isInteractive()); 894 } 895 registerForWifiMonitorEvents()896 private void registerForWifiMonitorEvents() { 897 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.TARGET_BSSID_EVENT, getHandler()); 898 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATED_BSSID_EVENT, 899 getHandler()); 900 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ANQP_DONE_EVENT, getHandler()); 901 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT, 902 getHandler()); 903 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 904 getHandler()); 905 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_DONE_EVENT, 906 getHandler()); 907 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_START_EVENT, 908 getHandler()); 909 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.HS20_REMEDIATION_EVENT, 910 getHandler()); 911 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT, 912 getHandler()); 913 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT, 914 getHandler()); 915 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.RX_HS20_ANQP_ICON_EVENT, 916 getHandler()); 917 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 918 getHandler()); 919 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_IDENTITY, 920 getHandler()); 921 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_SIM_AUTH, 922 getHandler()); 923 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT, 924 mWifiMetrics.getHandler()); 925 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 926 mWifiMetrics.getHandler()); 927 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT, 928 mWifiMetrics.getHandler()); 929 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT, 930 mWifiMetrics.getHandler()); 931 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 932 mWifiMetrics.getHandler()); 933 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATED_BSSID_EVENT, 934 mWifiMetrics.getHandler()); 935 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.TARGET_BSSID_EVENT, 936 mWifiMetrics.getHandler()); 937 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT, 938 mWifiInjector.getWifiLastResortWatchdog().getHandler()); 939 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT, 940 mSupplicantStateTracker.getHandler()); 941 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 942 mSupplicantStateTracker.getHandler()); 943 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 944 mSupplicantStateTracker.getHandler()); 945 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, 946 getHandler()); 947 } 948 setMulticastFilter(boolean enabled)949 private void setMulticastFilter(boolean enabled) { 950 if (mIpClient != null) { 951 mIpClient.setMulticastFilter(enabled); 952 } 953 } 954 955 /** 956 * Class to implement the MulticastLockManager.FilterController callback. 957 */ 958 class McastLockManagerFilterController implements WifiMulticastLockManager.FilterController { 959 /** 960 * Start filtering Multicast v4 packets 961 */ startFilteringMulticastPackets()962 public void startFilteringMulticastPackets() { 963 setMulticastFilter(true); 964 } 965 966 /** 967 * Stop filtering Multicast v4 packets 968 */ stopFilteringMulticastPackets()969 public void stopFilteringMulticastPackets() { 970 setMulticastFilter(false); 971 } 972 } 973 974 class IpClientCallbacksImpl extends IpClientCallbacks { 975 private final ConditionVariable mWaitForCreationCv = new ConditionVariable(false); 976 private final ConditionVariable mWaitForStopCv = new ConditionVariable(false); 977 978 @Override onIpClientCreated(IIpClient ipClient)979 public void onIpClientCreated(IIpClient ipClient) { 980 mIpClient = new IpClientManager(ipClient, getName()); 981 mWaitForCreationCv.open(); 982 } 983 984 @Override onPreDhcpAction()985 public void onPreDhcpAction() { 986 sendMessage(CMD_PRE_DHCP_ACTION); 987 } 988 989 @Override onPostDhcpAction()990 public void onPostDhcpAction() { 991 sendMessage(CMD_POST_DHCP_ACTION); 992 } 993 994 @Override onNewDhcpResults(DhcpResultsParcelable dhcpResults)995 public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) { 996 if (dhcpResults != null) { 997 sendMessage(CMD_IPV4_PROVISIONING_SUCCESS, dhcpResults); 998 } else { 999 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 1000 } 1001 } 1002 1003 @Override onProvisioningSuccess(LinkProperties newLp)1004 public void onProvisioningSuccess(LinkProperties newLp) { 1005 mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL); 1006 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); 1007 sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL); 1008 } 1009 1010 @Override onProvisioningFailure(LinkProperties newLp)1011 public void onProvisioningFailure(LinkProperties newLp) { 1012 mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST); 1013 sendMessage(CMD_IP_CONFIGURATION_LOST); 1014 } 1015 1016 @Override onLinkPropertiesChange(LinkProperties newLp)1017 public void onLinkPropertiesChange(LinkProperties newLp) { 1018 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); 1019 } 1020 1021 @Override onReachabilityLost(String logMsg)1022 public void onReachabilityLost(String logMsg) { 1023 mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_REACHABILITY_LOST); 1024 sendMessage(CMD_IP_REACHABILITY_LOST, logMsg); 1025 } 1026 1027 @Override installPacketFilter(byte[] filter)1028 public void installPacketFilter(byte[] filter) { 1029 sendMessage(CMD_INSTALL_PACKET_FILTER, filter); 1030 } 1031 1032 @Override startReadPacketFilter()1033 public void startReadPacketFilter() { 1034 sendMessage(CMD_READ_PACKET_FILTER); 1035 } 1036 1037 @Override setFallbackMulticastFilter(boolean enabled)1038 public void setFallbackMulticastFilter(boolean enabled) { 1039 sendMessage(CMD_SET_FALLBACK_PACKET_FILTERING, enabled); 1040 } 1041 1042 @Override setNeighborDiscoveryOffload(boolean enabled)1043 public void setNeighborDiscoveryOffload(boolean enabled) { 1044 sendMessage(CMD_CONFIG_ND_OFFLOAD, (enabled ? 1 : 0)); 1045 } 1046 1047 @Override onPreconnectionStart(List<Layer2PacketParcelable> packets)1048 public void onPreconnectionStart(List<Layer2PacketParcelable> packets) { 1049 sendMessage(CMD_START_FILS_CONNECTION, 0, 0, packets); 1050 } 1051 1052 @Override onQuit()1053 public void onQuit() { 1054 mWaitForStopCv.open(); 1055 } 1056 awaitCreation()1057 boolean awaitCreation() { 1058 return mWaitForCreationCv.block(IPCLIENT_STARTUP_TIMEOUT_MS); 1059 } 1060 awaitShutdown()1061 boolean awaitShutdown() { 1062 return mWaitForStopCv.block(IPCLIENT_SHUTDOWN_TIMEOUT_MS); 1063 } 1064 } 1065 stopIpClient()1066 private void stopIpClient() { 1067 // TODO(b/157943924): Adding more log to debug the issue. 1068 Log.v(TAG, "stopIpClient IpClientWithPreConnection: " + mIpClientWithPreConnection, 1069 new Throwable()); 1070 if (mIpClient != null) { 1071 if (mIpClientWithPreConnection) { 1072 mIpClient.notifyPreconnectionComplete(false); 1073 } 1074 mIpClient.stop(); 1075 } 1076 mIpClientWithPreConnection = false; 1077 mSentHLPs = false; 1078 } 1079 stopDhcpSetup()1080 private void stopDhcpSetup() { 1081 /* Restore power save and suspend optimizations */ 1082 handlePostDhcpSetup(); 1083 stopIpClient(); 1084 } 1085 1086 /** 1087 * Listener for config manager network config related events. 1088 * TODO (b/117601161) : Move some of the existing handling in WifiConnectivityManager's listener 1089 * for the same events. 1090 */ 1091 private class OnNetworkUpdateListener implements 1092 WifiConfigManager.OnNetworkUpdateListener { 1093 @Override onNetworkAdded(WifiConfiguration config)1094 public void onNetworkAdded(WifiConfiguration config) { } 1095 1096 @Override onNetworkEnabled(WifiConfiguration config)1097 public void onNetworkEnabled(WifiConfiguration config) { } 1098 1099 @Override onNetworkRemoved(WifiConfiguration config)1100 public void onNetworkRemoved(WifiConfiguration config) { 1101 // The current connected or connecting network has been removed, trigger a disconnect. 1102 if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { 1103 // Disconnect and let autojoin reselect a new network 1104 sendMessage(CMD_DISCONNECT); 1105 } 1106 mWifiNative.removeNetworkCachedData(config.networkId); 1107 } 1108 1109 @Override onNetworkUpdated(WifiConfiguration newConfig, WifiConfiguration oldConfig)1110 public void onNetworkUpdated(WifiConfiguration newConfig, WifiConfiguration oldConfig) { 1111 // Clear invalid cached data. 1112 mWifiNative.removeNetworkCachedData(oldConfig.networkId); 1113 1114 if (WifiConfigurationUtil.hasCredentialChanged(oldConfig, newConfig)) { 1115 mBssidBlocklistMonitor.handleNetworkRemoved(newConfig.SSID); 1116 } 1117 1118 // Check if user/app change meteredOverride for connected network. 1119 if (newConfig.networkId != mLastNetworkId 1120 || newConfig.meteredOverride == oldConfig.meteredOverride) { 1121 // nothing to do. 1122 return; 1123 } 1124 boolean isMetered = WifiConfiguration.isMetered(newConfig, mWifiInfo); 1125 boolean wasMetered = WifiConfiguration.isMetered(oldConfig, mWifiInfo); 1126 if (isMetered == wasMetered) { 1127 // no meteredness change, nothing to do. 1128 if (mVerboseLoggingEnabled) { 1129 Log.v(TAG, "User/app changed meteredOverride, but no change in meteredness"); 1130 } 1131 return; 1132 } 1133 // If unmetered->metered trigger a disconnect. 1134 // If metered->unmetered update capabilities. 1135 if (isMetered) { 1136 Log.w(TAG, "Network marked metered, triggering disconnect"); 1137 sendMessage(CMD_DISCONNECT); 1138 } else { 1139 Log.i(TAG, "Network marked unmetered, triggering capabilities update"); 1140 updateCapabilities(newConfig); 1141 } 1142 } 1143 1144 @Override onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason)1145 public void onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason) { 1146 if (disableReason == DISABLED_NO_INTERNET_TEMPORARY) return; 1147 if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { 1148 // Disconnect and let autojoin reselect a new network 1149 sendMessage(CMD_DISCONNECT); 1150 } 1151 1152 } 1153 1154 @Override onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason)1155 public void onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason) { 1156 // For DISABLED_NO_INTERNET_PERMANENT we do not need to remove the network 1157 // because supplicant won't be trying to reconnect. If this is due to a 1158 // preventAutomaticReconnect request from ConnectivityService, that service 1159 // will disconnect as appropriate. 1160 if (disableReason == DISABLED_NO_INTERNET_PERMANENT) return; 1161 if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { 1162 // Disconnect and let autojoin reselect a new network 1163 sendMessage(CMD_DISCONNECT); 1164 } 1165 } 1166 } 1167 1168 /** 1169 * Set wpa_supplicant log level using |mVerboseLoggingLevel| flag. 1170 */ setSupplicantLogLevel()1171 void setSupplicantLogLevel() { 1172 mWifiNative.setSupplicantLogLevel(mVerboseLoggingEnabled); 1173 } 1174 1175 /** 1176 * Method to update logging level in wifi service related classes. 1177 * 1178 * @param verbose int logging level to use 1179 */ enableVerboseLogging(int verbose)1180 public void enableVerboseLogging(int verbose) { 1181 if (verbose > 0) { 1182 mVerboseLoggingEnabled = true; 1183 setLogRecSize(mActivityManager.isLowRamDevice() 1184 ? NUM_LOG_RECS_VERBOSE_LOW_MEMORY : NUM_LOG_RECS_VERBOSE); 1185 } else { 1186 mVerboseLoggingEnabled = false; 1187 setLogRecSize(NUM_LOG_RECS_NORMAL); 1188 } 1189 setSupplicantLogLevel(); 1190 mCountryCode.enableVerboseLogging(verbose); 1191 mWifiScoreReport.enableVerboseLogging(mVerboseLoggingEnabled); 1192 mWifiDiagnostics.enableVerboseLogging(mVerboseLoggingEnabled); 1193 mWifiMonitor.enableVerboseLogging(verbose); 1194 mWifiNative.enableVerboseLogging(verbose); 1195 mWifiConfigManager.enableVerboseLogging(verbose); 1196 mSupplicantStateTracker.enableVerboseLogging(verbose); 1197 mPasspointManager.enableVerboseLogging(verbose); 1198 mNetworkFactory.enableVerboseLogging(verbose); 1199 mLinkProbeManager.enableVerboseLogging(mVerboseLoggingEnabled); 1200 mMboOceController.enableVerboseLogging(mVerboseLoggingEnabled); 1201 mWifiScoreCard.enableVerboseLogging(mVerboseLoggingEnabled); 1202 mWifiHealthMonitor.enableVerboseLogging(mVerboseLoggingEnabled); 1203 mWifiInjector.getThroughputPredictor().enableVerboseLogging(mVerboseLoggingEnabled); 1204 mWifiDataStall.enableVerboseLogging(mVerboseLoggingEnabled); 1205 mWifiConnectivityManager.enableVerboseLogging(mVerboseLoggingEnabled); 1206 } 1207 1208 /** 1209 * Initiates connection to a network specified by the user/app. This method checks if the 1210 * requesting app holds the NETWORK_SETTINGS permission. 1211 * 1212 * @param netId Id network to initiate connection. 1213 * @param uid UID of the app requesting the connection. 1214 * @param forceReconnect Whether to force a connection even if we're connected to the same 1215 * network currently. 1216 */ connectToUserSelectNetwork(int netId, int uid, boolean forceReconnect)1217 private void connectToUserSelectNetwork(int netId, int uid, boolean forceReconnect) { 1218 logd("connectToUserSelectNetwork netId " + netId + ", uid " + uid 1219 + ", forceReconnect = " + forceReconnect); 1220 if (!forceReconnect && (mLastNetworkId == netId || mTargetNetworkId == netId)) { 1221 // We're already connecting/connected to the user specified network, don't trigger a 1222 // reconnection unless it was forced. 1223 logi("connectToUserSelectNetwork already connecting/connected=" + netId); 1224 } else { 1225 mWifiConnectivityManager.prepareForForcedConnection(netId); 1226 if (uid == Process.SYSTEM_UID) { 1227 mWifiMetrics.setNominatorForNetwork(netId, 1228 WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL); 1229 } 1230 startConnectToNetwork(netId, uid, SUPPLICANT_BSSID_ANY); 1231 } 1232 } 1233 1234 /** 1235 * ****************************************************** 1236 * Methods exposed for public use 1237 * ****************************************************** 1238 */ 1239 1240 /** 1241 * Retrieve a Messenger for the ClientModeImpl Handler 1242 * 1243 * @return Messenger 1244 */ getMessenger()1245 public Messenger getMessenger() { 1246 return new Messenger(getHandler()); 1247 } 1248 1249 // Last connect attempt is used to prevent scan requests: 1250 // - for a period of 10 seconds after attempting to connect 1251 private long mLastConnectAttemptTimestamp = 0; 1252 1253 // For debugging, keep track of last message status handling 1254 // TODO, find an equivalent mechanism as part of parent class 1255 private static final int MESSAGE_HANDLING_STATUS_PROCESSED = 2; 1256 private static final int MESSAGE_HANDLING_STATUS_OK = 1; 1257 private static final int MESSAGE_HANDLING_STATUS_UNKNOWN = 0; 1258 private static final int MESSAGE_HANDLING_STATUS_REFUSED = -1; 1259 private static final int MESSAGE_HANDLING_STATUS_FAIL = -2; 1260 private static final int MESSAGE_HANDLING_STATUS_OBSOLETE = -3; 1261 private static final int MESSAGE_HANDLING_STATUS_DEFERRED = -4; 1262 private static final int MESSAGE_HANDLING_STATUS_DISCARD = -5; 1263 private static final int MESSAGE_HANDLING_STATUS_LOOPED = -6; 1264 private static final int MESSAGE_HANDLING_STATUS_HANDLING_ERROR = -7; 1265 1266 private int mMessageHandlingStatus = 0; 1267 1268 private int mOnTime = 0; 1269 private int mTxTime = 0; 1270 private int mRxTime = 0; 1271 1272 private int mOnTimeScreenStateChange = 0; 1273 private long mLastOntimeReportTimeStamp = 0; 1274 private long mLastScreenStateChangeTimeStamp = 0; 1275 private int mOnTimeLastReport = 0; 1276 private int mTxTimeLastReport = 0; 1277 private int mRxTimeLastReport = 0; 1278 1279 private WifiLinkLayerStats mLastLinkLayerStats; 1280 private long mLastLinkLayerStatsUpdate = 0; 1281 reportOnTime()1282 String reportOnTime() { 1283 long now = mClock.getWallClockMillis(); 1284 StringBuilder sb = new StringBuilder(); 1285 // Report stats since last report 1286 int on = mOnTime - mOnTimeLastReport; 1287 mOnTimeLastReport = mOnTime; 1288 int tx = mTxTime - mTxTimeLastReport; 1289 mTxTimeLastReport = mTxTime; 1290 int rx = mRxTime - mRxTimeLastReport; 1291 mRxTimeLastReport = mRxTime; 1292 int period = (int) (now - mLastOntimeReportTimeStamp); 1293 mLastOntimeReportTimeStamp = now; 1294 sb.append(String.format("[on:%d tx:%d rx:%d period:%d]", on, tx, rx, period)); 1295 // Report stats since Screen State Changed 1296 on = mOnTime - mOnTimeScreenStateChange; 1297 period = (int) (now - mLastScreenStateChangeTimeStamp); 1298 sb.append(String.format(" from screen [on:%d period:%d]", on, period)); 1299 return sb.toString(); 1300 } 1301 getWifiLinkLayerStats()1302 WifiLinkLayerStats getWifiLinkLayerStats() { 1303 if (mInterfaceName == null) { 1304 loge("getWifiLinkLayerStats called without an interface"); 1305 return null; 1306 } 1307 mLastLinkLayerStatsUpdate = mClock.getWallClockMillis(); 1308 WifiLinkLayerStats stats = mWifiNative.getWifiLinkLayerStats(mInterfaceName); 1309 if (stats != null) { 1310 mOnTime = stats.on_time; 1311 mTxTime = stats.tx_time; 1312 mRxTime = stats.rx_time; 1313 mRunningBeaconCount = stats.beacon_rx; 1314 mWifiInfo.updatePacketRates(stats, mLastLinkLayerStatsUpdate); 1315 } else { 1316 long mTxPkts = mFacade.getTxPackets(mInterfaceName); 1317 long mRxPkts = mFacade.getRxPackets(mInterfaceName); 1318 mWifiInfo.updatePacketRates(mTxPkts, mRxPkts, mLastLinkLayerStatsUpdate); 1319 } 1320 return stats; 1321 } 1322 1323 /** 1324 * Check if a Wi-Fi band is supported 1325 * 1326 * @param band A value from {@link WifiScanner.WIFI_BAND_5_GHZ} or 1327 * {@link WifiScanner.WIFI_BAND_6_GHZ} 1328 * @return {@code true} if band is supported, {@code false} otherwise. 1329 */ isWifiBandSupported(int band)1330 public boolean isWifiBandSupported(int band) { 1331 if (band == WifiScanner.WIFI_BAND_5_GHZ) { 1332 // In some cases, devices override the value by the overlay configs 1333 if (mContext.getResources().getBoolean(R.bool.config_wifi5ghzSupport)) { 1334 return true; 1335 } 1336 return (mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ).length > 0); 1337 } 1338 1339 if (band == WifiScanner.WIFI_BAND_6_GHZ) { 1340 if (mContext.getResources().getBoolean(R.bool.config_wifi6ghzSupport)) { 1341 return true; 1342 } 1343 return (mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ).length > 0); 1344 } 1345 1346 return false; 1347 } 1348 1349 /** 1350 * Update interface capabilities 1351 * This method is used to update some of interface capabilities defined in overlay 1352 * 1353 * @param ifaceName name of interface to update 1354 */ updateInterfaceCapabilities(@onNull String ifaceName)1355 private void updateInterfaceCapabilities(@NonNull String ifaceName) { 1356 DeviceWiphyCapabilities cap = mWifiNative.getDeviceWiphyCapabilities(ifaceName); 1357 if (cap != null) { 1358 // Some devices don't have support of 11ax indicated by the chip, 1359 // so an override config value is used 1360 if (mContext.getResources().getBoolean(R.bool.config_wifi11axSupportOverride)) { 1361 cap.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, true); 1362 } 1363 1364 mWifiNative.setDeviceWiphyCapabilities(ifaceName, cap); 1365 } 1366 } 1367 1368 /** 1369 * Check if a Wi-Fi standard is supported 1370 * 1371 * @param standard A value from {@link ScanResult}'s {@code WIFI_STANDARD_} 1372 * @return {@code true} if standard is supported, {@code false} otherwise. 1373 */ isWifiStandardSupported(@ifiStandard int standard)1374 public boolean isWifiStandardSupported(@WifiStandard int standard) { 1375 return mWifiNative.isWifiStandardSupported(mInterfaceName, standard); 1376 } 1377 getDstMacForKeepalive(KeepalivePacketData packetData)1378 private byte[] getDstMacForKeepalive(KeepalivePacketData packetData) 1379 throws InvalidPacketException { 1380 try { 1381 InetAddress gateway = NetUtils.selectBestRoute( 1382 mLinkProperties.getRoutes(), packetData.getDstAddress()).getGateway(); 1383 String dstMacStr = macAddressFromRoute(gateway.getHostAddress()); 1384 return NativeUtil.macAddressToByteArray(dstMacStr); 1385 } catch (NullPointerException | IllegalArgumentException e) { 1386 throw new InvalidPacketException(InvalidPacketException.ERROR_INVALID_IP_ADDRESS); 1387 } 1388 } 1389 getEtherProtoForKeepalive(KeepalivePacketData packetData)1390 private static int getEtherProtoForKeepalive(KeepalivePacketData packetData) 1391 throws InvalidPacketException { 1392 if (packetData.getDstAddress() instanceof Inet4Address) { 1393 return OsConstants.ETH_P_IP; 1394 } else if (packetData.getDstAddress() instanceof Inet6Address) { 1395 return OsConstants.ETH_P_IPV6; 1396 } else { 1397 throw new InvalidPacketException(InvalidPacketException.ERROR_INVALID_IP_ADDRESS); 1398 } 1399 } 1400 startWifiIPPacketOffload(int slot, KeepalivePacketData packetData, int intervalSeconds)1401 private int startWifiIPPacketOffload(int slot, KeepalivePacketData packetData, 1402 int intervalSeconds) { 1403 byte[] packet = null; 1404 byte[] dstMac = null; 1405 int proto = 0; 1406 1407 try { 1408 packet = packetData.getPacket(); 1409 dstMac = getDstMacForKeepalive(packetData); 1410 proto = getEtherProtoForKeepalive(packetData); 1411 } catch (InvalidPacketException e) { 1412 return e.getError(); 1413 } 1414 1415 int ret = mWifiNative.startSendingOffloadedPacket( 1416 mInterfaceName, slot, dstMac, packet, proto, intervalSeconds * 1000); 1417 if (ret != 0) { 1418 loge("startWifiIPPacketOffload(" + slot + ", " + intervalSeconds 1419 + "): hardware error " + ret); 1420 return SocketKeepalive.ERROR_HARDWARE_ERROR; 1421 } else { 1422 return SocketKeepalive.SUCCESS; 1423 } 1424 } 1425 stopWifiIPPacketOffload(int slot)1426 private int stopWifiIPPacketOffload(int slot) { 1427 int ret = mWifiNative.stopSendingOffloadedPacket(mInterfaceName, slot); 1428 if (ret != 0) { 1429 loge("stopWifiIPPacketOffload(" + slot + "): hardware error " + ret); 1430 return SocketKeepalive.ERROR_HARDWARE_ERROR; 1431 } else { 1432 return SocketKeepalive.SUCCESS; 1433 } 1434 } 1435 startRssiMonitoringOffload(byte maxRssi, byte minRssi, WifiNative.WifiRssiEventHandler rssiHandler)1436 private int startRssiMonitoringOffload(byte maxRssi, byte minRssi, 1437 WifiNative.WifiRssiEventHandler rssiHandler) { 1438 return mWifiNative.startRssiMonitoring(mInterfaceName, maxRssi, minRssi, rssiHandler); 1439 } 1440 stopRssiMonitoringOffload()1441 private int stopRssiMonitoringOffload() { 1442 return mWifiNative.stopRssiMonitoring(mInterfaceName); 1443 } 1444 1445 /** 1446 * Temporary method that allows the active ClientModeManager to set the wifi state that is 1447 * retrieved by API calls. This will be removed when WifiServiceImpl no longer directly calls 1448 * this class (b/31479117). 1449 * 1450 * @param newState new state to set, invalid states are ignored. 1451 */ setWifiStateForApiCalls(int newState)1452 public void setWifiStateForApiCalls(int newState) { 1453 switch (newState) { 1454 case WIFI_STATE_DISABLING: 1455 case WIFI_STATE_DISABLED: 1456 case WIFI_STATE_ENABLING: 1457 case WIFI_STATE_ENABLED: 1458 case WIFI_STATE_UNKNOWN: 1459 if (mVerboseLoggingEnabled) { 1460 Log.d(TAG, "setting wifi state to: " + newState); 1461 } 1462 mWifiState.set(newState); 1463 return; 1464 default: 1465 Log.d(TAG, "attempted to set an invalid state: " + newState); 1466 return; 1467 } 1468 } 1469 1470 /** 1471 * Method used by WifiServiceImpl to get the current state of Wifi (in client mode) for API 1472 * calls. This will be removed when WifiService no longer directly calls this class 1473 * (b/31479117). 1474 */ syncGetWifiState()1475 public int syncGetWifiState() { 1476 return mWifiState.get(); 1477 } 1478 1479 /** 1480 * Converts the current wifi state to a printable form. 1481 */ syncGetWifiStateByName()1482 public String syncGetWifiStateByName() { 1483 switch (mWifiState.get()) { 1484 case WIFI_STATE_DISABLING: 1485 return "disabling"; 1486 case WIFI_STATE_DISABLED: 1487 return "disabled"; 1488 case WIFI_STATE_ENABLING: 1489 return "enabling"; 1490 case WIFI_STATE_ENABLED: 1491 return "enabled"; 1492 case WIFI_STATE_UNKNOWN: 1493 return "unknown state"; 1494 default: 1495 return "[invalid state]"; 1496 } 1497 } 1498 isConnected()1499 public boolean isConnected() { 1500 return getCurrentState() == mConnectedState; 1501 } 1502 isDisconnected()1503 public boolean isDisconnected() { 1504 return getCurrentState() == mDisconnectedState; 1505 } 1506 1507 /** 1508 * Method checking if supplicant is in a transient state 1509 * 1510 * @return boolean true if in transient state 1511 */ isSupplicantTransientState()1512 public boolean isSupplicantTransientState() { 1513 SupplicantState supplicantState = mWifiInfo.getSupplicantState(); 1514 if (supplicantState == SupplicantState.ASSOCIATING 1515 || supplicantState == SupplicantState.AUTHENTICATING 1516 || supplicantState == SupplicantState.FOUR_WAY_HANDSHAKE 1517 || supplicantState == SupplicantState.GROUP_HANDSHAKE) { 1518 1519 if (mVerboseLoggingEnabled) { 1520 Log.d(TAG, "Supplicant is under transient state: " + supplicantState); 1521 } 1522 return true; 1523 } else { 1524 if (mVerboseLoggingEnabled) { 1525 Log.d(TAG, "Supplicant is under steady state: " + supplicantState); 1526 } 1527 } 1528 1529 return false; 1530 } 1531 1532 /** 1533 * Get status information for the current connection, if any. 1534 * 1535 * @return a {@link WifiInfo} object containing information about the current connection 1536 */ syncRequestConnectionInfo()1537 public WifiInfo syncRequestConnectionInfo() { 1538 WifiInfo result = new WifiInfo(mWifiInfo); 1539 return result; 1540 } 1541 1542 /** 1543 * Method to retrieve the current WifiInfo 1544 * 1545 * @returns WifiInfo 1546 */ getWifiInfo()1547 public WifiInfo getWifiInfo() { 1548 return mWifiInfo; 1549 } 1550 1551 /** 1552 * Blocking call to get the current DHCP results 1553 * 1554 * @return DhcpResultsParcelable current results 1555 */ 1556 @NonNull syncGetDhcpResultsParcelable()1557 public DhcpResultsParcelable syncGetDhcpResultsParcelable() { 1558 synchronized (mDhcpResultsParcelableLock) { 1559 return mDhcpResultsParcelable; 1560 } 1561 } 1562 1563 /** 1564 * When the underlying interface is destroyed, we must immediately tell connectivity service to 1565 * mark network agent as disconnected and stop the ip client. 1566 */ handleIfaceDestroyed()1567 public void handleIfaceDestroyed() { 1568 handleNetworkDisconnect(); 1569 } 1570 1571 /** 1572 * TODO: doc 1573 */ setOperationalMode(int mode, String ifaceName)1574 public void setOperationalMode(int mode, String ifaceName) { 1575 if (mVerboseLoggingEnabled) { 1576 log("setting operational mode to " + String.valueOf(mode) + " for iface: " + ifaceName); 1577 } 1578 mModeChange = true; 1579 if (mode != CONNECT_MODE) { 1580 // we are disabling client mode... need to exit connect mode now 1581 transitionTo(mDefaultState); 1582 } else { 1583 // do a quick sanity check on the iface name, make sure it isn't null 1584 if (ifaceName != null) { 1585 mInterfaceName = ifaceName; 1586 updateInterfaceCapabilities(ifaceName); 1587 transitionTo(mDisconnectedState); 1588 mWifiScoreReport.setInterfaceName(ifaceName); 1589 } else { 1590 Log.e(TAG, "supposed to enter connect mode, but iface is null -> DefaultState"); 1591 transitionTo(mDefaultState); 1592 } 1593 } 1594 // use the CMD_SET_OPERATIONAL_MODE to force the transitions before other messages are 1595 // handled. 1596 sendMessageAtFrontOfQueue(CMD_SET_OPERATIONAL_MODE); 1597 } 1598 checkAbnormalConnectionFailureAndTakeBugReport(String ssid)1599 private void checkAbnormalConnectionFailureAndTakeBugReport(String ssid) { 1600 if (mWifiInjector.getDeviceConfigFacade() 1601 .isAbnormalConnectionFailureBugreportEnabled()) { 1602 int reasonCode = mWifiScoreCard.detectAbnormalConnectionFailure(ssid); 1603 if (reasonCode != WifiHealthMonitor.REASON_NO_FAILURE) { 1604 String bugTitle = "Wi-Fi BugReport"; 1605 String bugDetail = "Detect abnormal " 1606 + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode]; 1607 takeBugReport(bugTitle, bugDetail); 1608 } 1609 } 1610 } 1611 checkAbnormalDisconnectionAndTakeBugReport()1612 private void checkAbnormalDisconnectionAndTakeBugReport() { 1613 if (mWifiInjector.getDeviceConfigFacade() 1614 .isAbnormalDisconnectionBugreportEnabled()) { 1615 int reasonCode = mWifiScoreCard.detectAbnormalDisconnection(); 1616 if (reasonCode != WifiHealthMonitor.REASON_NO_FAILURE) { 1617 String bugTitle = "Wi-Fi BugReport"; 1618 String bugDetail = "Detect abnormal " 1619 + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode]; 1620 takeBugReport(bugTitle, bugDetail); 1621 } 1622 } 1623 } 1624 1625 /** 1626 * Initiates a system-level bugreport, in a non-blocking fashion. 1627 */ takeBugReport(String bugTitle, String bugDetail)1628 public void takeBugReport(String bugTitle, String bugDetail) { 1629 mWifiDiagnostics.takeBugReport(bugTitle, bugDetail); 1630 } 1631 1632 /** 1633 * Allow tests to confirm the operational mode for ClientModeImpl for testing. 1634 */ 1635 @VisibleForTesting getOperationalModeForTest()1636 protected int getOperationalModeForTest() { 1637 return mOperationalMode; 1638 } 1639 1640 /** 1641 * Retrieve the WifiMulticastLockManager.FilterController callback for registration. 1642 */ getMcastLockManagerFilterController()1643 protected WifiMulticastLockManager.FilterController getMcastLockManagerFilterController() { 1644 return mMcastLockManagerFilterController; 1645 } 1646 1647 /** 1648 * Blocking method to retrieve the passpoint icon. 1649 * 1650 * @param channel AsyncChannel for the response 1651 * @param bssid representation of the bssid as a long 1652 * @param fileName name of the file 1653 * 1654 * @return boolean returning the result of the call 1655 */ syncQueryPasspointIcon(AsyncChannel channel, long bssid, String fileName)1656 public boolean syncQueryPasspointIcon(AsyncChannel channel, long bssid, String fileName) { 1657 Bundle bundle = new Bundle(); 1658 bundle.putLong(EXTRA_OSU_ICON_QUERY_BSSID, bssid); 1659 bundle.putString(EXTRA_OSU_ICON_QUERY_FILENAME, fileName); 1660 Message resultMsg = channel.sendMessageSynchronously(CMD_QUERY_OSU_ICON, bundle); 1661 int result = resultMsg.arg1; 1662 resultMsg.recycle(); 1663 return result == 1; 1664 } 1665 1666 /** 1667 * Deauthenticate and set the re-authentication hold off time for the current network 1668 * @param holdoff hold off time in milliseconds 1669 * @param ess set if the hold off pertains to an ESS rather than a BSS 1670 */ deauthenticateNetwork(AsyncChannel channel, long holdoff, boolean ess)1671 public void deauthenticateNetwork(AsyncChannel channel, long holdoff, boolean ess) { 1672 // TODO: This needs an implementation 1673 } 1674 1675 /** 1676 * Disconnect from Access Point 1677 */ disconnectCommand()1678 public void disconnectCommand() { 1679 sendMessage(CMD_DISCONNECT); 1680 } 1681 1682 /** 1683 * Method to trigger a disconnect. 1684 * 1685 * @param uid UID of requesting caller 1686 * @param reason disconnect reason 1687 */ disconnectCommand(int uid, int reason)1688 public void disconnectCommand(int uid, int reason) { 1689 sendMessage(CMD_DISCONNECT, uid, reason); 1690 } 1691 1692 /** 1693 * Initiate a reconnection to AP 1694 */ reconnectCommand(WorkSource workSource)1695 public void reconnectCommand(WorkSource workSource) { 1696 sendMessage(CMD_RECONNECT, workSource); 1697 } 1698 1699 /** 1700 * Initiate a re-association to AP 1701 */ reassociateCommand()1702 public void reassociateCommand() { 1703 sendMessage(CMD_REASSOCIATE); 1704 } 1705 1706 /** 1707 * Checks for a null Message. 1708 * 1709 * This can happen with sendMessageSynchronously, for example if an 1710 * InterruptedException occurs. If this just happens once, silently 1711 * ignore it, because it is probably a side effect of shutting down. 1712 * If it happens a second time, generate a WTF. 1713 */ messageIsNull(Message resultMsg)1714 private boolean messageIsNull(Message resultMsg) { 1715 if (resultMsg != null) return false; 1716 if (mNullMessageCounter.getAndIncrement() > 0) { 1717 Log.wtf(TAG, "Persistent null Message", new RuntimeException()); 1718 } 1719 return true; 1720 } 1721 private AtomicInteger mNullMessageCounter = new AtomicInteger(0); 1722 1723 /** 1724 * Start subscription provisioning synchronously 1725 * 1726 * @param provider {@link OsuProvider} the provider to provision with 1727 * @param callback {@link IProvisioningCallback} callback for provisioning status 1728 * @return boolean true indicates provisioning was started, false otherwise 1729 */ syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider, IProvisioningCallback callback, AsyncChannel channel)1730 public boolean syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider, 1731 IProvisioningCallback callback, AsyncChannel channel) { 1732 Message msg = Message.obtain(); 1733 msg.what = CMD_START_SUBSCRIPTION_PROVISIONING; 1734 msg.arg1 = callingUid; 1735 msg.obj = callback; 1736 msg.getData().putParcelable(EXTRA_OSU_PROVIDER, provider); 1737 Message resultMsg = channel.sendMessageSynchronously(msg); 1738 if (messageIsNull(resultMsg)) return false; 1739 boolean result = resultMsg.arg1 != 0; 1740 resultMsg.recycle(); 1741 return result; 1742 } 1743 1744 /** 1745 * Get the supported feature set synchronously 1746 */ syncGetSupportedFeatures(AsyncChannel channel)1747 public long syncGetSupportedFeatures(AsyncChannel channel) { 1748 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_SUPPORTED_FEATURES); 1749 if (messageIsNull(resultMsg)) return 0; 1750 long supportedFeatureSet = ((Long) resultMsg.obj).longValue(); 1751 resultMsg.recycle(); 1752 return supportedFeatureSet; 1753 } 1754 1755 /** 1756 * Get link layers stats for adapter synchronously 1757 */ syncGetLinkLayerStats(AsyncChannel channel)1758 public WifiLinkLayerStats syncGetLinkLayerStats(AsyncChannel channel) { 1759 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_LINK_LAYER_STATS); 1760 if (messageIsNull(resultMsg)) return null; 1761 WifiLinkLayerStats result = (WifiLinkLayerStats) resultMsg.obj; 1762 resultMsg.recycle(); 1763 return result; 1764 } 1765 1766 /** 1767 * Method to enable/disable RSSI polling 1768 * @param enabled boolean idicating if polling should start 1769 */ enableRssiPolling(boolean enabled)1770 public void enableRssiPolling(boolean enabled) { 1771 sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0); 1772 } 1773 1774 /** 1775 * Set high performance mode of operation. 1776 * Enabling would set active power mode and disable suspend optimizations; 1777 * disabling would set auto power mode and enable suspend optimizations 1778 * 1779 * @param enable true if enable, false otherwise 1780 */ setHighPerfModeEnabled(boolean enable)1781 public void setHighPerfModeEnabled(boolean enable) { 1782 sendMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0); 1783 } 1784 1785 1786 /** 1787 * reset cached SIM credential data 1788 */ resetSimAuthNetworks(@esetSimReason int resetReason)1789 public synchronized void resetSimAuthNetworks(@ResetSimReason int resetReason) { 1790 sendMessage(CMD_RESET_SIM_NETWORKS, resetReason); 1791 } 1792 1793 /** 1794 * Should only be used internally. 1795 * External callers should use {@link #syncGetCurrentNetwork(AsyncChannel)}. 1796 */ getCurrentNetwork()1797 private Network getCurrentNetwork() { 1798 if (mNetworkAgent != null) { 1799 return mNetworkAgent.getNetwork(); 1800 } else { 1801 return null; 1802 } 1803 } 1804 1805 /** 1806 * Get Network object of currently connected wifi network, or null if not connected. 1807 * @return Network object of current wifi network 1808 */ syncGetCurrentNetwork(AsyncChannel channel)1809 public Network syncGetCurrentNetwork(AsyncChannel channel) { 1810 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CURRENT_NETWORK); 1811 if (messageIsNull(resultMsg)) return null; 1812 Network network = (Network) resultMsg.obj; 1813 resultMsg.recycle(); 1814 return network; 1815 } 1816 1817 /** 1818 * Enable TDLS for a specific MAC address 1819 */ enableTdls(String remoteMacAddress, boolean enable)1820 public void enableTdls(String remoteMacAddress, boolean enable) { 1821 int enabler = enable ? 1 : 0; 1822 sendMessage(CMD_ENABLE_TDLS, enabler, 0, remoteMacAddress); 1823 } 1824 1825 /** 1826 * Send a message indicating bluetooth adapter state changed, e.g., turn on or ff 1827 */ sendBluetoothAdapterStateChange(int state)1828 public void sendBluetoothAdapterStateChange(int state) { 1829 sendMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0); 1830 } 1831 1832 /** 1833 * Send a message indicating bluetooth adapter connection state changed, e.g., connected 1834 * or disconnected. Note that turning off BT after pairing success keeps connection state in 1835 * connected state. 1836 */ sendBluetoothAdapterConnectionStateChange(int state)1837 public void sendBluetoothAdapterConnectionStateChange(int state) { 1838 sendMessage(CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE, state, 0); 1839 } 1840 1841 /** 1842 * Trigger dump on the class IpClient object. 1843 */ dumpIpClient(FileDescriptor fd, PrintWriter pw, String[] args)1844 public void dumpIpClient(FileDescriptor fd, PrintWriter pw, String[] args) { 1845 if (mIpClient != null) { 1846 // All dumpIpClient does is print this log message. 1847 // TODO: consider deleting this, since it's not useful. 1848 pw.println("IpClient logs have moved to dumpsys network_stack"); 1849 } 1850 } 1851 dhcpResultsParcelableToString(DhcpResultsParcelable dhcpResults)1852 private static String dhcpResultsParcelableToString(DhcpResultsParcelable dhcpResults) { 1853 return new StringBuilder() 1854 .append("baseConfiguration ").append(dhcpResults.baseConfiguration) 1855 .append("leaseDuration ").append(dhcpResults.leaseDuration) 1856 .append("mtu ").append(dhcpResults.mtu) 1857 .append("serverAddress ").append(dhcpResults.serverAddress) 1858 .append("serverHostName ").append(dhcpResults.serverHostName) 1859 .append("vendorInfo ").append(dhcpResults.vendorInfo) 1860 .toString(); 1861 } 1862 1863 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1864 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1865 super.dump(fd, pw, args); 1866 mSupplicantStateTracker.dump(fd, pw, args); 1867 pw.println("mLinkProperties " + mLinkProperties); 1868 pw.println("mWifiInfo " + mWifiInfo); 1869 pw.println("mDhcpResultsParcelable " 1870 + dhcpResultsParcelableToString(mDhcpResultsParcelable)); 1871 pw.println("mLastSignalLevel " + mLastSignalLevel); 1872 pw.println("mLastBssid " + mLastBssid); 1873 pw.println("mLastNetworkId " + mLastNetworkId); 1874 pw.println("mLastSubId " + mLastSubId); 1875 pw.println("mLastSimBasedConnectionCarrierName " + mLastSimBasedConnectionCarrierName); 1876 pw.println("mOperationalMode " + mOperationalMode); 1877 pw.println("mSuspendOptimizationsEnabled " + mContext.getResources().getBoolean( 1878 R.bool.config_wifiSuspendOptimizationsEnabled)); 1879 pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 1880 mCountryCode.dump(fd, pw, args); 1881 mNetworkFactory.dump(fd, pw, args); 1882 mUntrustedNetworkFactory.dump(fd, pw, args); 1883 pw.println("Wlan Wake Reasons:" + mWifiNative.getWlanWakeReasonCount()); 1884 pw.println(); 1885 1886 mWifiConfigManager.dump(fd, pw, args); 1887 pw.println(); 1888 mPasspointManager.dump(pw); 1889 pw.println(); 1890 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_USER_ACTION); 1891 mWifiDiagnostics.dump(fd, pw, args); 1892 dumpIpClient(fd, pw, args); 1893 mWifiConnectivityManager.dump(fd, pw, args); 1894 mWifiHealthMonitor.dump(fd, pw, args); 1895 mWifiInjector.getWakeupController().dump(fd, pw, args); 1896 mLinkProbeManager.dump(fd, pw, args); 1897 mWifiInjector.getWifiLastResortWatchdog().dump(fd, pw, args); 1898 } 1899 1900 /** 1901 * Trigger message to handle boot completed event. 1902 */ handleBootCompleted()1903 public void handleBootCompleted() { 1904 sendMessage(CMD_BOOT_COMPLETED); 1905 } 1906 1907 /** 1908 * ****************************************************** 1909 * Internal private functions 1910 * ****************************************************** 1911 */ 1912 logStateAndMessage(Message message, State state)1913 private void logStateAndMessage(Message message, State state) { 1914 mMessageHandlingStatus = 0; 1915 if (mVerboseLoggingEnabled) { 1916 logd(" " + state.getClass().getSimpleName() + " " + getLogRecString(message)); 1917 } 1918 } 1919 1920 @Override recordLogRec(Message msg)1921 protected boolean recordLogRec(Message msg) { 1922 switch (msg.what) { 1923 case CMD_RSSI_POLL: 1924 return mVerboseLoggingEnabled; 1925 default: 1926 return true; 1927 } 1928 } 1929 1930 /** 1931 * Return the additional string to be logged by LogRec, default 1932 * 1933 * @param msg that was processed 1934 * @return information to be logged as a String 1935 */ 1936 @Override getLogRecString(Message msg)1937 protected String getLogRecString(Message msg) { 1938 WifiConfiguration config; 1939 Long now; 1940 String report; 1941 String key; 1942 StringBuilder sb = new StringBuilder(); 1943 sb.append("screen=").append(mScreenOn ? "on" : "off"); 1944 if (mMessageHandlingStatus != MESSAGE_HANDLING_STATUS_UNKNOWN) { 1945 sb.append("(").append(mMessageHandlingStatus).append(")"); 1946 } 1947 if (msg.sendingUid > 0 && msg.sendingUid != Process.WIFI_UID) { 1948 sb.append(" uid=" + msg.sendingUid); 1949 } 1950 switch (msg.what) { 1951 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 1952 sb.append(" "); 1953 sb.append(Integer.toString(msg.arg1)); 1954 sb.append(" "); 1955 sb.append(Integer.toString(msg.arg2)); 1956 StateChangeResult stateChangeResult = (StateChangeResult) msg.obj; 1957 if (stateChangeResult != null) { 1958 sb.append(stateChangeResult.toString()); 1959 } 1960 break; 1961 case CMD_CONNECT_NETWORK: 1962 case CMD_SAVE_NETWORK: { 1963 NetworkUpdateResult result = (NetworkUpdateResult) msg.obj; 1964 sb.append(" "); 1965 sb.append(Integer.toString(result.netId)); 1966 sb.append(" "); 1967 sb.append(Integer.toString(msg.arg2)); 1968 config = mWifiConfigManager.getConfiguredNetwork(result.netId); 1969 if (config != null) { 1970 sb.append(" ").append(config.getKey()); 1971 sb.append(" nid=").append(config.networkId); 1972 if (config.hiddenSSID) { 1973 sb.append(" hidden"); 1974 } 1975 if (config.preSharedKey != null 1976 && !config.preSharedKey.equals("*")) { 1977 sb.append(" hasPSK"); 1978 } 1979 if (config.ephemeral) { 1980 sb.append(" ephemeral"); 1981 } 1982 sb.append(" cuid=").append(config.creatorUid); 1983 sb.append(" suid=").append(config.lastUpdateUid); 1984 } 1985 break; 1986 } 1987 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 1988 sb.append(" "); 1989 sb.append(" timedOut=" + Integer.toString(msg.arg1)); 1990 sb.append(" "); 1991 sb.append(Integer.toString(msg.arg2)); 1992 String bssid = (String) msg.obj; 1993 if (bssid != null && bssid.length() > 0) { 1994 sb.append(" "); 1995 sb.append(bssid); 1996 } 1997 sb.append(" blacklist=" + Boolean.toString(mDidBlackListBSSID)); 1998 break; 1999 case WifiMonitor.NETWORK_CONNECTION_EVENT: 2000 sb.append(" "); 2001 sb.append(Integer.toString(msg.arg1)); 2002 sb.append(" "); 2003 sb.append(Integer.toString(msg.arg2)); 2004 sb.append(" ").append(mLastBssid); 2005 sb.append(" nid=").append(mLastNetworkId); 2006 config = getCurrentWifiConfiguration(); 2007 if (config != null) { 2008 sb.append(" ").append(config.getKey()); 2009 } 2010 key = mWifiConfigManager.getLastSelectedNetworkConfigKey(); 2011 if (key != null) { 2012 sb.append(" last=").append(key); 2013 } 2014 break; 2015 case WifiMonitor.TARGET_BSSID_EVENT: 2016 case WifiMonitor.ASSOCIATED_BSSID_EVENT: 2017 sb.append(" "); 2018 sb.append(Integer.toString(msg.arg1)); 2019 sb.append(" "); 2020 sb.append(Integer.toString(msg.arg2)); 2021 if (msg.obj != null) { 2022 sb.append(" BSSID=").append((String) msg.obj); 2023 } 2024 if (mTargetBssid != null) { 2025 sb.append(" Target=").append(mTargetBssid); 2026 } 2027 sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming)); 2028 break; 2029 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 2030 if (msg.obj != null) { 2031 sb.append(" ").append((String) msg.obj); 2032 } 2033 sb.append(" nid=").append(msg.arg1); 2034 sb.append(" reason=").append(msg.arg2); 2035 if (mLastBssid != null) { 2036 sb.append(" lastbssid=").append(mLastBssid); 2037 } 2038 if (mWifiInfo.getFrequency() != -1) { 2039 sb.append(" freq=").append(mWifiInfo.getFrequency()); 2040 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2041 } 2042 break; 2043 case CMD_RSSI_POLL: 2044 case CMD_ONESHOT_RSSI_POLL: 2045 case CMD_UNWANTED_NETWORK: 2046 sb.append(" "); 2047 sb.append(Integer.toString(msg.arg1)); 2048 sb.append(" "); 2049 sb.append(Integer.toString(msg.arg2)); 2050 if (mWifiInfo.getSSID() != null) { 2051 if (mWifiInfo.getSSID() != null) { 2052 sb.append(" ").append(mWifiInfo.getSSID()); 2053 } 2054 } 2055 if (mWifiInfo.getBSSID() != null) { 2056 sb.append(" ").append(mWifiInfo.getBSSID()); 2057 } 2058 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2059 sb.append(" f=").append(mWifiInfo.getFrequency()); 2060 sb.append(" sc=").append(mWifiInfo.getScore()); 2061 sb.append(" link=").append(mWifiInfo.getLinkSpeed()); 2062 sb.append(String.format(" tx=%.1f,", mWifiInfo.getSuccessfulTxPacketsPerSecond())); 2063 sb.append(String.format(" %.1f,", mWifiInfo.getRetriedTxPacketsPerSecond())); 2064 sb.append(String.format(" %.1f ", mWifiInfo.getLostTxPacketsPerSecond())); 2065 sb.append(String.format(" rx=%.1f", mWifiInfo.getSuccessfulRxPacketsPerSecond())); 2066 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 2067 report = reportOnTime(); 2068 if (report != null) { 2069 sb.append(" ").append(report); 2070 } 2071 sb.append(String.format(" score=%d", mWifiInfo.getScore())); 2072 break; 2073 case CMD_START_CONNECT: 2074 sb.append(" "); 2075 sb.append(Integer.toString(msg.arg1)); 2076 sb.append(" "); 2077 sb.append(Integer.toString(msg.arg2)); 2078 config = mWifiConfigManager.getConfiguredNetwork(msg.arg1); 2079 if (config != null) { 2080 sb.append(" targetConfigKey=").append(config.getKey()); 2081 sb.append(" BSSID=" + config.BSSID); 2082 } 2083 if (mTargetBssid != null) { 2084 sb.append(" targetBssid=").append(mTargetBssid); 2085 } 2086 sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming)); 2087 config = getCurrentWifiConfiguration(); 2088 if (config != null) { 2089 sb.append(" currentConfigKey=").append(config.getKey()); 2090 } 2091 break; 2092 case CMD_START_ROAM: 2093 sb.append(" "); 2094 sb.append(Integer.toString(msg.arg1)); 2095 sb.append(" "); 2096 sb.append(Integer.toString(msg.arg2)); 2097 ScanResult result = (ScanResult) msg.obj; 2098 if (result != null) { 2099 now = mClock.getWallClockMillis(); 2100 sb.append(" bssid=").append(result.BSSID); 2101 sb.append(" rssi=").append(result.level); 2102 sb.append(" freq=").append(result.frequency); 2103 if (result.seen > 0 && result.seen < now) { 2104 sb.append(" seen=").append(now - result.seen); 2105 } else { 2106 // Somehow the timestamp for this scan result is inconsistent 2107 sb.append(" !seen=").append(result.seen); 2108 } 2109 } 2110 if (mTargetBssid != null) { 2111 sb.append(" ").append(mTargetBssid); 2112 } 2113 sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming)); 2114 sb.append(" fail count=").append(Integer.toString(mRoamFailCount)); 2115 break; 2116 case CMD_PRE_DHCP_ACTION: 2117 sb.append(" "); 2118 sb.append(Integer.toString(msg.arg1)); 2119 sb.append(" "); 2120 sb.append(Integer.toString(msg.arg2)); 2121 sb.append(" txpkts=").append(mWifiInfo.txSuccess); 2122 sb.append(",").append(mWifiInfo.txBad); 2123 sb.append(",").append(mWifiInfo.txRetries); 2124 break; 2125 case CMD_POST_DHCP_ACTION: 2126 if (mLinkProperties != null) { 2127 sb.append(" "); 2128 sb.append(getLinkPropertiesSummary(mLinkProperties)); 2129 } 2130 break; 2131 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 2132 sb.append(" "); 2133 sb.append(Integer.toString(msg.arg1)); 2134 sb.append(" "); 2135 sb.append(Integer.toString(msg.arg2)); 2136 if (msg.obj != null) { 2137 NetworkInfo info = (NetworkInfo) msg.obj; 2138 NetworkInfo.State state = info.getState(); 2139 NetworkInfo.DetailedState detailedState = info.getDetailedState(); 2140 if (state != null) { 2141 sb.append(" st=").append(state); 2142 } 2143 if (detailedState != null) { 2144 sb.append("/").append(detailedState); 2145 } 2146 } 2147 break; 2148 case CMD_IP_CONFIGURATION_LOST: 2149 int count = -1; 2150 WifiConfiguration c = getCurrentWifiConfiguration(); 2151 if (c != null) { 2152 count = c.getNetworkSelectionStatus().getDisableReasonCounter( 2153 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 2154 } 2155 sb.append(" "); 2156 sb.append(Integer.toString(msg.arg1)); 2157 sb.append(" "); 2158 sb.append(Integer.toString(msg.arg2)); 2159 sb.append(" failures: "); 2160 sb.append(Integer.toString(count)); 2161 sb.append("/"); 2162 sb.append(Integer.toString(mFacade.getIntegerSetting( 2163 mContext, Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT, 0))); 2164 if (mWifiInfo.getBSSID() != null) { 2165 sb.append(" ").append(mWifiInfo.getBSSID()); 2166 } 2167 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 2168 break; 2169 case CMD_UPDATE_LINKPROPERTIES: 2170 sb.append(" "); 2171 sb.append(Integer.toString(msg.arg1)); 2172 sb.append(" "); 2173 sb.append(Integer.toString(msg.arg2)); 2174 if (mLinkProperties != null) { 2175 sb.append(" "); 2176 sb.append(getLinkPropertiesSummary(mLinkProperties)); 2177 } 2178 break; 2179 case CMD_IP_REACHABILITY_LOST: 2180 if (msg.obj != null) { 2181 sb.append(" ").append((String) msg.obj); 2182 } 2183 break; 2184 case CMD_INSTALL_PACKET_FILTER: 2185 sb.append(" len=" + ((byte[]) msg.obj).length); 2186 break; 2187 case CMD_SET_FALLBACK_PACKET_FILTERING: 2188 sb.append(" enabled=" + (boolean) msg.obj); 2189 break; 2190 case CMD_ROAM_WATCHDOG_TIMER: 2191 sb.append(" "); 2192 sb.append(Integer.toString(msg.arg1)); 2193 sb.append(" "); 2194 sb.append(Integer.toString(msg.arg2)); 2195 sb.append(" cur=").append(mRoamWatchdogCount); 2196 break; 2197 case CMD_DISCONNECTING_WATCHDOG_TIMER: 2198 sb.append(" "); 2199 sb.append(Integer.toString(msg.arg1)); 2200 sb.append(" "); 2201 sb.append(Integer.toString(msg.arg2)); 2202 sb.append(" cur=").append(mDisconnectingWatchdogCount); 2203 break; 2204 case CMD_START_RSSI_MONITORING_OFFLOAD: 2205 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 2206 case CMD_RSSI_THRESHOLD_BREACHED: 2207 sb.append(" rssi="); 2208 sb.append(Integer.toString(msg.arg1)); 2209 sb.append(" thresholds="); 2210 sb.append(Arrays.toString(mRssiRanges)); 2211 break; 2212 case CMD_IPV4_PROVISIONING_SUCCESS: 2213 sb.append(" "); 2214 sb.append(/* DhcpResultsParcelable */ msg.obj); 2215 break; 2216 case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE: 2217 BtmFrameData frameData = (BtmFrameData) msg.obj; 2218 if (frameData != null) { 2219 sb.append(" ").append(frameData.toString()); 2220 } 2221 break; 2222 default: 2223 sb.append(" "); 2224 sb.append(Integer.toString(msg.arg1)); 2225 sb.append(" "); 2226 sb.append(Integer.toString(msg.arg2)); 2227 break; 2228 } 2229 2230 return sb.toString(); 2231 } 2232 2233 @Override getWhatToString(int what)2234 protected String getWhatToString(int what) { 2235 String s = sGetWhatToString.get(what); 2236 if (s != null) { 2237 return s; 2238 } 2239 switch (what) { 2240 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 2241 s = "CMD_CHANNEL_HALF_CONNECTED"; 2242 break; 2243 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 2244 s = "CMD_CHANNEL_DISCONNECTED"; 2245 break; 2246 case CMD_CONNECT_NETWORK: 2247 s = "CMD_CONNECT_NETWORK"; 2248 break; 2249 case CMD_SAVE_NETWORK: 2250 s = "CMD_SAVE_NETWORK"; 2251 break; 2252 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 2253 s = "SUPPLICANT_STATE_CHANGE_EVENT"; 2254 break; 2255 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 2256 s = "AUTHENTICATION_FAILURE_EVENT"; 2257 break; 2258 case WifiMonitor.SUP_REQUEST_IDENTITY: 2259 s = "SUP_REQUEST_IDENTITY"; 2260 break; 2261 case WifiMonitor.NETWORK_CONNECTION_EVENT: 2262 s = "NETWORK_CONNECTION_EVENT"; 2263 break; 2264 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 2265 s = "NETWORK_DISCONNECTION_EVENT"; 2266 break; 2267 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 2268 s = "ASSOCIATION_REJECTION_EVENT"; 2269 break; 2270 case WifiMonitor.ANQP_DONE_EVENT: 2271 s = "ANQP_DONE_EVENT"; 2272 break; 2273 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 2274 s = "RX_HS20_ANQP_ICON_EVENT"; 2275 break; 2276 case WifiMonitor.GAS_QUERY_DONE_EVENT: 2277 s = "GAS_QUERY_DONE_EVENT"; 2278 break; 2279 case WifiMonitor.HS20_REMEDIATION_EVENT: 2280 s = "HS20_REMEDIATION_EVENT"; 2281 break; 2282 case WifiMonitor.GAS_QUERY_START_EVENT: 2283 s = "GAS_QUERY_START_EVENT"; 2284 break; 2285 case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE: 2286 s = "MBO_OCE_BSS_TM_HANDLING_DONE"; 2287 break; 2288 case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT: 2289 s = "GROUP_CREATING_TIMED_OUT"; 2290 break; 2291 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 2292 s = "P2P_CONNECTION_CHANGED"; 2293 break; 2294 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 2295 s = "DISCONNECT_WIFI_REQUEST"; 2296 break; 2297 case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE: 2298 s = "DISCONNECT_WIFI_RESPONSE"; 2299 break; 2300 case WifiP2pServiceImpl.SET_MIRACAST_MODE: 2301 s = "SET_MIRACAST_MODE"; 2302 break; 2303 case WifiP2pServiceImpl.BLOCK_DISCOVERY: 2304 s = "BLOCK_DISCOVERY"; 2305 break; 2306 default: 2307 s = "what:" + Integer.toString(what); 2308 break; 2309 } 2310 return s; 2311 } 2312 handleScreenStateChanged(boolean screenOn)2313 private void handleScreenStateChanged(boolean screenOn) { 2314 mScreenOn = screenOn; 2315 if (mVerboseLoggingEnabled) { 2316 logd(" handleScreenStateChanged Enter: screenOn=" + screenOn 2317 + " mSuspendOptimizationsEnabled=" 2318 + mContext.getResources().getBoolean( 2319 R.bool.config_wifiSuspendOptimizationsEnabled) 2320 + " state " + getCurrentState().getName()); 2321 } 2322 enableRssiPolling(screenOn); 2323 if (mContext.getResources().getBoolean(R.bool.config_wifiSuspendOptimizationsEnabled)) { 2324 int shouldReleaseWakeLock = 0; 2325 if (screenOn) { 2326 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, shouldReleaseWakeLock); 2327 } else { 2328 if (isConnected()) { 2329 // Allow 2s for suspend optimizations to be set 2330 mSuspendWakeLock.acquire(2000); 2331 shouldReleaseWakeLock = 1; 2332 } 2333 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, shouldReleaseWakeLock); 2334 } 2335 } 2336 2337 getWifiLinkLayerStats(); 2338 mOnTimeScreenStateChange = mOnTime; 2339 mLastScreenStateChangeTimeStamp = mLastLinkLayerStatsUpdate; 2340 2341 mWifiMetrics.setScreenState(screenOn); 2342 2343 mWifiConnectivityManager.handleScreenStateChanged(screenOn); 2344 mNetworkFactory.handleScreenStateChanged(screenOn); 2345 2346 WifiLockManager wifiLockManager = mWifiInjector.getWifiLockManager(); 2347 if (wifiLockManager == null) { 2348 Log.w(TAG, "WifiLockManager not initialized, skipping screen state notification"); 2349 } else { 2350 wifiLockManager.handleScreenStateChanged(screenOn); 2351 } 2352 2353 mSarManager.handleScreenStateChanged(screenOn); 2354 2355 if (mVerboseLoggingEnabled) log("handleScreenStateChanged Exit: " + screenOn); 2356 } 2357 checkAndSetConnectivityInstance()2358 private boolean checkAndSetConnectivityInstance() { 2359 if (mCm == null) { 2360 mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 2361 } 2362 if (mCm == null) { 2363 Log.e(TAG, "Cannot retrieve connectivity service"); 2364 return false; 2365 } 2366 return true; 2367 } 2368 setSuspendOptimizationsNative(int reason, boolean enabled)2369 private void setSuspendOptimizationsNative(int reason, boolean enabled) { 2370 if (mVerboseLoggingEnabled) { 2371 log("setSuspendOptimizationsNative: " + reason + " " + enabled 2372 + " -want " + mContext.getResources().getBoolean( 2373 R.bool.config_wifiSuspendOptimizationsEnabled) 2374 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 2375 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 2376 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 2377 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 2378 } 2379 //mWifiNative.setSuspendOptimizations(enabled); 2380 2381 if (enabled) { 2382 mSuspendOptNeedsDisabled &= ~reason; 2383 /* None of dhcp, screen or highperf need it disabled and user wants it enabled */ 2384 if (mSuspendOptNeedsDisabled == 0 2385 && mContext.getResources().getBoolean( 2386 R.bool.config_wifiSuspendOptimizationsEnabled)) { 2387 if (mVerboseLoggingEnabled) { 2388 log("setSuspendOptimizationsNative do it " + reason + " " + enabled 2389 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 2390 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 2391 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 2392 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 2393 } 2394 mWifiNative.setSuspendOptimizations(mInterfaceName, true); 2395 } 2396 } else { 2397 mSuspendOptNeedsDisabled |= reason; 2398 mWifiNative.setSuspendOptimizations(mInterfaceName, false); 2399 } 2400 } 2401 2402 /** 2403 * Makes a record of the user intent about suspend optimizations. 2404 */ setSuspendOptimizations(int reason, boolean enabled)2405 private void setSuspendOptimizations(int reason, boolean enabled) { 2406 if (mVerboseLoggingEnabled) log("setSuspendOptimizations: " + reason + " " + enabled); 2407 if (enabled) { 2408 mSuspendOptNeedsDisabled &= ~reason; 2409 } else { 2410 mSuspendOptNeedsDisabled |= reason; 2411 } 2412 if (mVerboseLoggingEnabled) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 2413 } 2414 2415 /* 2416 * Fetch RSSI, linkspeed, and frequency on current connection 2417 */ fetchRssiLinkSpeedAndFrequencyNative()2418 private void fetchRssiLinkSpeedAndFrequencyNative() { 2419 WifiNl80211Manager.SignalPollResult pollResult = mWifiNative.signalPoll(mInterfaceName); 2420 if (pollResult == null) { 2421 return; 2422 } 2423 2424 int newRssi = pollResult.currentRssiDbm; 2425 int newTxLinkSpeed = pollResult.txBitrateMbps; 2426 int newFrequency = pollResult.associationFrequencyMHz; 2427 int newRxLinkSpeed = pollResult.rxBitrateMbps; 2428 2429 if (mVerboseLoggingEnabled) { 2430 logd("fetchRssiLinkSpeedAndFrequencyNative rssi=" + newRssi 2431 + " TxLinkspeed=" + newTxLinkSpeed + " freq=" + newFrequency 2432 + " RxLinkSpeed=" + newRxLinkSpeed); 2433 } 2434 2435 if (newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) { 2436 /* 2437 * Positive RSSI is possible when devices are close(~0m apart) to each other. 2438 * And there are some driver/firmware implementation, where they avoid 2439 * reporting large negative rssi values by adding 256. 2440 * so adjust the valid rssi reports for such implementations. 2441 */ 2442 if (newRssi > (WifiInfo.INVALID_RSSI + 256)) { 2443 Log.wtf(TAG, "Error! +ve value RSSI: " + newRssi); 2444 newRssi -= 256; 2445 } 2446 mWifiInfo.setRssi(newRssi); 2447 /* 2448 * Rather then sending the raw RSSI out every time it 2449 * changes, we precalculate the signal level that would 2450 * be displayed in the status bar, and only send the 2451 * broadcast if that much more coarse-grained number 2452 * changes. This cuts down greatly on the number of 2453 * broadcasts, at the cost of not informing others 2454 * interested in RSSI of all the changes in signal 2455 * level. 2456 */ 2457 int newSignalLevel = RssiUtil.calculateSignalLevel(mContext, newRssi); 2458 if (newSignalLevel != mLastSignalLevel) { 2459 updateCapabilities(); 2460 sendRssiChangeBroadcast(newRssi); 2461 } 2462 mLastSignalLevel = newSignalLevel; 2463 } else { 2464 mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); 2465 updateCapabilities(); 2466 } 2467 /* 2468 * set Tx link speed only if it is valid 2469 */ 2470 if (newTxLinkSpeed > 0) { 2471 mWifiInfo.setLinkSpeed(newTxLinkSpeed); 2472 mWifiInfo.setTxLinkSpeedMbps(newTxLinkSpeed); 2473 } 2474 /* 2475 * set Rx link speed only if it is valid 2476 */ 2477 if (newRxLinkSpeed > 0) { 2478 mWifiInfo.setRxLinkSpeedMbps(newRxLinkSpeed); 2479 } 2480 if (newFrequency > 0) { 2481 mWifiInfo.setFrequency(newFrequency); 2482 } 2483 mWifiConfigManager.updateScanDetailCacheFromWifiInfo(mWifiInfo); 2484 /* 2485 * Increment various performance metrics 2486 */ 2487 mWifiMetrics.handlePollResult(mWifiInfo); 2488 } 2489 2490 // Polling has completed, hence we won't have a score anymore cleanWifiScore()2491 private void cleanWifiScore() { 2492 mWifiInfo.setLostTxPacketsPerSecond(0); 2493 mWifiInfo.setSuccessfulTxPacketsPerSecond(0); 2494 mWifiInfo.setRetriedTxPacketsRate(0); 2495 mWifiInfo.setSuccessfulRxPacketsPerSecond(0); 2496 mWifiScoreReport.reset(); 2497 mLastLinkLayerStats = null; 2498 } 2499 updateLinkProperties(LinkProperties newLp)2500 private void updateLinkProperties(LinkProperties newLp) { 2501 if (mVerboseLoggingEnabled) { 2502 log("Link configuration changed for netId: " + mLastNetworkId 2503 + " old: " + mLinkProperties + " new: " + newLp); 2504 } 2505 // We own this instance of LinkProperties because IpClient passes us a copy. 2506 mLinkProperties = newLp; 2507 if (mNetworkAgent != null) { 2508 mNetworkAgent.sendLinkProperties(mLinkProperties); 2509 } 2510 2511 if (mNetworkAgentState == DetailedState.CONNECTED) { 2512 // If anything has changed and we're already connected, send out a notification. 2513 // TODO: Update all callers to use NetworkCallbacks and delete this. 2514 sendLinkConfigurationChangedBroadcast(); 2515 } 2516 2517 if (mVerboseLoggingEnabled) { 2518 StringBuilder sb = new StringBuilder(); 2519 sb.append("updateLinkProperties nid: " + mLastNetworkId); 2520 sb.append(" state: " + mNetworkAgentState); 2521 2522 if (mLinkProperties != null) { 2523 sb.append(" "); 2524 sb.append(getLinkPropertiesSummary(mLinkProperties)); 2525 } 2526 logd(sb.toString()); 2527 } 2528 } 2529 2530 /** 2531 * Clears all our link properties. 2532 */ clearLinkProperties()2533 private void clearLinkProperties() { 2534 // Clear the link properties obtained from DHCP. The only caller of this 2535 // function has already called IpClient#stop(), which clears its state. 2536 synchronized (mDhcpResultsParcelableLock) { 2537 mDhcpResultsParcelable = new DhcpResultsParcelable(); 2538 } 2539 2540 // Now clear the merged link properties. 2541 mLinkProperties.clear(); 2542 if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties); 2543 } 2544 sendRssiChangeBroadcast(final int newRssi)2545 private void sendRssiChangeBroadcast(final int newRssi) { 2546 mBatteryStatsManager.reportWifiRssiChanged(newRssi); 2547 WifiStatsLog.write(WifiStatsLog.WIFI_SIGNAL_STRENGTH_CHANGED, 2548 RssiUtil.calculateSignalLevel(mContext, newRssi)); 2549 2550 Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION); 2551 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2552 intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi); 2553 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 2554 android.Manifest.permission.ACCESS_WIFI_STATE); 2555 } 2556 sendLinkConfigurationChangedBroadcast()2557 private void sendLinkConfigurationChangedBroadcast() { 2558 Intent intent = new Intent(WifiManager.ACTION_LINK_CONFIGURATION_CHANGED); 2559 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2560 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 2561 } 2562 2563 /** 2564 * Helper method used to send state about supplicant - This is NOT information about the current 2565 * wifi connection state. 2566 * 2567 * TODO: b/79504296 This broadcast has been deprecated and should be removed 2568 */ sendSupplicantConnectionChangedBroadcast(boolean connected)2569 private void sendSupplicantConnectionChangedBroadcast(boolean connected) { 2570 Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 2571 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2572 intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected); 2573 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 2574 } 2575 2576 /** 2577 * Record the detailed state of a network. 2578 * 2579 * @param state the new {@code DetailedState} 2580 */ sendNetworkChangeBroadcast(NetworkInfo.DetailedState state)2581 private void sendNetworkChangeBroadcast(NetworkInfo.DetailedState state) { 2582 boolean hidden = false; 2583 2584 if (mIsAutoRoaming) { 2585 // There is generally a confusion in the system about colluding 2586 // WiFi Layer 2 state (as reported by supplicant) and the Network state 2587 // which leads to multiple confusion. 2588 // 2589 // If link is roaming, we already have an IP address 2590 // as well we were connected and are doing L2 cycles of 2591 // reconnecting or renewing IP address to check that we still have it 2592 // This L2 link flapping should not be reflected into the Network state 2593 // which is the state of the WiFi Network visible to Layer 3 and applications 2594 // Note that once roaming is completed, we will 2595 // set the Network state to where it should be, or leave it as unchanged 2596 // 2597 hidden = true; 2598 } 2599 if (mVerboseLoggingEnabled) { 2600 log("setDetailed state, old =" 2601 + mNetworkAgentState + " and new state=" + state 2602 + " hidden=" + hidden); 2603 } 2604 if (hidden || state == mNetworkAgentState) return; 2605 mNetworkAgentState = state; 2606 2607 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); 2608 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2609 NetworkInfo networkInfo = makeNetworkInfo(); 2610 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo); 2611 //TODO(b/69974497) This should be non-sticky, but settings needs fixing first. 2612 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 2613 } 2614 makeNetworkInfo()2615 private NetworkInfo makeNetworkInfo() { 2616 final NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, ""); 2617 ni.setDetailedState(mNetworkAgentState, null, null); 2618 return ni; 2619 } 2620 handleSupplicantStateChange(Message message)2621 private SupplicantState handleSupplicantStateChange(Message message) { 2622 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 2623 SupplicantState state = stateChangeResult.state; 2624 mWifiScoreCard.noteSupplicantStateChanging(mWifiInfo, state); 2625 // Supplicant state change 2626 // [31-13] Reserved for future use 2627 // [8 - 0] Supplicant state (as defined in SupplicantState.java) 2628 // 50023 supplicant_state_changed (custom|1|5) 2629 mWifiInfo.setSupplicantState(state); 2630 // Network id and SSID are only valid when we start connecting 2631 if (SupplicantState.isConnecting(state)) { 2632 mWifiInfo.setNetworkId(stateChangeResult.networkId); 2633 mWifiInfo.setBSSID(stateChangeResult.BSSID); 2634 mWifiInfo.setSSID(stateChangeResult.wifiSsid); 2635 if (state == SupplicantState.ASSOCIATED) { 2636 updateWifiInfoAfterAssociation(); 2637 } 2638 } else { 2639 // Reset parameters according to WifiInfo.reset() 2640 mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); 2641 mWifiInfo.setBSSID(null); 2642 mWifiInfo.setSSID(null); 2643 mWifiInfo.setWifiStandard(ScanResult.WIFI_STANDARD_UNKNOWN); 2644 } 2645 updateLayer2Information(); 2646 // SSID might have been updated, so call updateCapabilities 2647 updateCapabilities(); 2648 2649 WifiConfiguration config = getCurrentWifiConfiguration(); 2650 if (config == null) { 2651 // If not connected, this should be non-null. 2652 config = getTargetWifiConfiguration(); 2653 } 2654 if (config != null && config.networkId == mWifiInfo.getNetworkId()) { 2655 mWifiInfo.setEphemeral(config.ephemeral); 2656 mWifiInfo.setTrusted(config.trusted); 2657 mWifiInfo.setOsuAp(config.osu); 2658 if (config.fromWifiNetworkSpecifier || config.fromWifiNetworkSuggestion) { 2659 mWifiInfo.setRequestingPackageName(config.creatorName); 2660 } 2661 2662 // Set meteredHint if scan result says network is expensive 2663 ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork( 2664 config.networkId); 2665 if (scanDetailCache != null) { 2666 ScanDetail scanDetail = scanDetailCache.getScanDetail(stateChangeResult.BSSID); 2667 if (scanDetail != null) { 2668 mWifiInfo.setFrequency(scanDetail.getScanResult().frequency); 2669 NetworkDetail networkDetail = scanDetail.getNetworkDetail(); 2670 if (networkDetail != null 2671 && networkDetail.getAnt() == NetworkDetail.Ant.ChargeablePublic) { 2672 mWifiInfo.setMeteredHint(true); 2673 } 2674 } 2675 } 2676 } 2677 mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); 2678 return state; 2679 } 2680 updateWifiInfoAfterAssociation()2681 private void updateWifiInfoAfterAssociation() { 2682 WifiNative.ConnectionCapabilities capabilities = 2683 mWifiNative.getConnectionCapabilities(mInterfaceName); 2684 ThroughputPredictor throughputPredictor = mWifiInjector.getThroughputPredictor(); 2685 int maxTxLinkSpeedMbps = throughputPredictor.predictMaxTxThroughput(capabilities); 2686 int maxRxLinkSpeedMbps = throughputPredictor.predictMaxRxThroughput(capabilities); 2687 mWifiInfo.setWifiStandard(capabilities.wifiStandard); 2688 mWifiInfo.setMaxSupportedTxLinkSpeedMbps(maxTxLinkSpeedMbps); 2689 mWifiInfo.setMaxSupportedRxLinkSpeedMbps(maxRxLinkSpeedMbps); 2690 mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps( 2691 maxTxLinkSpeedMbps, maxRxLinkSpeedMbps); 2692 mWifiDataStall.setConnectionCapabilities(capabilities); 2693 if (mVerboseLoggingEnabled) { 2694 StringBuilder sb = new StringBuilder(); 2695 logd(sb.append("WifiStandard: ").append(capabilities.wifiStandard) 2696 .append(" maxTxSpeed: ").append(maxTxLinkSpeedMbps) 2697 .append(" maxRxSpeed: ").append(maxRxLinkSpeedMbps) 2698 .toString()); 2699 } 2700 } 2701 2702 /** 2703 * Tells IpClient what BSSID, L2Key and GroupHint to use for IpMemoryStore. 2704 */ updateLayer2Information()2705 private void updateLayer2Information() { 2706 if (mIpClient != null) { 2707 Pair<String, String> p = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); 2708 if (!p.equals(mLastL2KeyAndGroupHint)) { 2709 final MacAddress lastBssid = getCurrentBssid(); 2710 final Layer2Information l2Information = new Layer2Information( 2711 p.first, p.second, lastBssid); 2712 // Update current BSSID on IpClient side whenever l2Key and groupHint 2713 // pair changes (i.e. the initial connection establishment or L2 roaming 2714 // happened). If we have COMPLETED the roaming to a different BSSID, start 2715 // doing DNAv4/DNAv6 -style probing for on-link neighbors of interest (e.g. 2716 // routers/DNS servers/default gateway). 2717 if (mIpClient.updateLayer2Information(l2Information)) { 2718 mLastL2KeyAndGroupHint = p; 2719 } else { 2720 mLastL2KeyAndGroupHint = null; 2721 } 2722 } 2723 } 2724 } 2725 private @Nullable Pair<String, String> mLastL2KeyAndGroupHint = null; 2726 2727 /** 2728 * Resets the Wi-Fi Connections by clearing any state, resetting any sockets 2729 * using the interface, stopping DHCP & disabling interface 2730 */ handleNetworkDisconnect()2731 private void handleNetworkDisconnect() { 2732 if (mVerboseLoggingEnabled) { 2733 log("handleNetworkDisconnect:" 2734 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 2735 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 2736 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 2737 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 2738 } 2739 2740 WifiConfiguration wifiConfig = getCurrentWifiConfiguration(); 2741 if (wifiConfig != null) { 2742 ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromWifiConfiguration(wifiConfig); 2743 mWifiInjector.getWakeupController().setLastDisconnectInfo(matchInfo); 2744 mWifiNetworkSuggestionsManager.handleDisconnect(wifiConfig, getCurrentBSSID()); 2745 } 2746 stopRssiMonitoringOffload(); 2747 2748 clearTargetBssid("handleNetworkDisconnect"); 2749 2750 // Don't stop DHCP if Fils connection is in progress. 2751 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 2752 && mTargetNetworkId != WifiConfiguration.INVALID_NETWORK_ID 2753 && mLastNetworkId != mTargetNetworkId && mIpClientWithPreConnection) { 2754 if (mVerboseLoggingEnabled) { 2755 log("handleNetworkDisconnect: Don't stop IpClient as fils connection in progress: " 2756 + " mLastNetworkId: " + mLastNetworkId 2757 + " mTargetNetworkId" + mTargetNetworkId); 2758 } 2759 } else { 2760 stopDhcpSetup(); 2761 } 2762 2763 mWifiScoreReport.stopConnectedNetworkScorer(); 2764 /* Reset data structures */ 2765 mWifiScoreReport.reset(); 2766 mWifiInfo.reset(); 2767 /* Reset roaming parameters */ 2768 mIsAutoRoaming = false; 2769 2770 sendNetworkChangeBroadcast(DetailedState.DISCONNECTED); 2771 if (mNetworkAgent != null) { 2772 mNetworkAgent.unregister(); 2773 mNetworkAgent = null; 2774 } 2775 2776 /* Clear network properties */ 2777 clearLinkProperties(); 2778 2779 mLastBssid = null; 2780 mLastLinkLayerStats = null; 2781 registerDisconnected(); 2782 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 2783 mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 2784 mLastSimBasedConnectionCarrierName = null; 2785 checkAbnormalDisconnectionAndTakeBugReport(); 2786 mWifiScoreCard.resetConnectionState(); 2787 mWifiDataStall.reset(); 2788 updateLayer2Information(); 2789 } 2790 handlePreDhcpSetup()2791 void handlePreDhcpSetup() { 2792 if (!mBluetoothConnectionActive) { 2793 /* 2794 * There are problems setting the Wi-Fi driver's power 2795 * mode to active when bluetooth coexistence mode is 2796 * enabled or sense. 2797 * <p> 2798 * We set Wi-Fi to active mode when 2799 * obtaining an IP address because we've found 2800 * compatibility issues with some routers with low power 2801 * mode. 2802 * <p> 2803 * In order for this active power mode to properly be set, 2804 * we disable coexistence mode until we're done with 2805 * obtaining an IP address. One exception is if we 2806 * are currently connected to a headset, since disabling 2807 * coexistence would interrupt that connection. 2808 */ 2809 // Disable the coexistence mode 2810 mWifiNative.setBluetoothCoexistenceMode( 2811 mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); 2812 } 2813 2814 // Disable power save and suspend optimizations during DHCP 2815 // Note: The order here is important for now. Brcm driver changes 2816 // power settings when we control suspend mode optimizations. 2817 // TODO: Remove this comment when the driver is fixed. 2818 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false); 2819 setPowerSave(false); 2820 2821 // Update link layer stats 2822 getWifiLinkLayerStats(); 2823 2824 if (mWifiP2pChannel != null) { 2825 /* P2p discovery breaks dhcp, shut it down in order to get through this */ 2826 Message msg = new Message(); 2827 msg.what = WifiP2pServiceImpl.BLOCK_DISCOVERY; 2828 msg.arg1 = WifiP2pServiceImpl.ENABLED; 2829 msg.arg2 = CMD_PRE_DHCP_ACTION_COMPLETE; 2830 mWifiP2pChannel.sendMessage(msg); 2831 } else { 2832 // If the p2p service is not running, we can proceed directly. 2833 sendMessage(CMD_PRE_DHCP_ACTION_COMPLETE); 2834 } 2835 } 2836 addLayer2PacketsToHlpReq(List<Layer2PacketParcelable> packets)2837 void addLayer2PacketsToHlpReq(List<Layer2PacketParcelable> packets) { 2838 List<Layer2PacketParcelable> mLayer2Packet = packets; 2839 if ((mLayer2Packet != null) && (mLayer2Packet.size() > 0)) { 2840 mWifiNative.flushAllHlp(mInterfaceName); 2841 2842 for (int j = 0; j < mLayer2Packet.size(); j++) { 2843 byte [] bytes = mLayer2Packet.get(j).payload; 2844 byte [] payloadBytes = Arrays.copyOfRange(bytes, 12, bytes.length); 2845 MacAddress dstAddress = mLayer2Packet.get(j).dstMacAddress; 2846 2847 mWifiNative.addHlpReq(mInterfaceName, dstAddress, payloadBytes); 2848 } 2849 } 2850 } 2851 handlePostDhcpSetup()2852 void handlePostDhcpSetup() { 2853 /* Restore power save and suspend optimizations */ 2854 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true); 2855 setPowerSave(true); 2856 2857 p2pSendMessage(WifiP2pServiceImpl.BLOCK_DISCOVERY, WifiP2pServiceImpl.DISABLED); 2858 2859 // Set the coexistence mode back to its default value 2860 mWifiNative.setBluetoothCoexistenceMode( 2861 mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); 2862 } 2863 2864 /** 2865 * Set power save mode 2866 * 2867 * @param ps true to enable power save (default behavior) 2868 * false to disable power save. 2869 * @return true for success, false for failure 2870 */ setPowerSave(boolean ps)2871 public boolean setPowerSave(boolean ps) { 2872 if (mInterfaceName != null) { 2873 if (mVerboseLoggingEnabled) { 2874 Log.d(TAG, "Setting power save for: " + mInterfaceName + " to: " + ps); 2875 } 2876 mWifiNative.setPowerSave(mInterfaceName, ps); 2877 } else { 2878 Log.e(TAG, "Failed to setPowerSave, interfaceName is null"); 2879 return false; 2880 } 2881 return true; 2882 } 2883 2884 /** 2885 * Set low latency mode 2886 * 2887 * @param enabled true to enable low latency 2888 * false to disable low latency (default behavior). 2889 * @return true for success, false for failure 2890 */ setLowLatencyMode(boolean enabled)2891 public boolean setLowLatencyMode(boolean enabled) { 2892 if (mVerboseLoggingEnabled) { 2893 Log.d(TAG, "Setting low latency mode to " + enabled); 2894 } 2895 if (!mWifiNative.setLowLatencyMode(enabled)) { 2896 Log.e(TAG, "Failed to setLowLatencyMode"); 2897 return false; 2898 } 2899 return true; 2900 } 2901 2902 @VisibleForTesting 2903 public static final long DIAGS_CONNECT_TIMEOUT_MILLIS = 60 * 1000; 2904 /** 2905 * Inform other components that a new connection attempt is starting. 2906 */ reportConnectionAttemptStart( WifiConfiguration config, String targetBSSID, int roamType)2907 private void reportConnectionAttemptStart( 2908 WifiConfiguration config, String targetBSSID, int roamType) { 2909 int overlapWithLastConnectionMs = 2910 mWifiMetrics.startConnectionEvent(config, targetBSSID, roamType); 2911 DeviceConfigFacade deviceConfigFacade = mWifiInjector.getDeviceConfigFacade(); 2912 if (deviceConfigFacade.isOverlappingConnectionBugreportEnabled() 2913 && overlapWithLastConnectionMs 2914 > deviceConfigFacade.getOverlappingConnectionDurationThresholdMs()) { 2915 String bugTitle = "Wi-Fi BugReport"; 2916 String bugDetail = "Detect abnormal overlapping connection"; 2917 takeBugReport(bugTitle, bugDetail); 2918 } 2919 mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_STARTED); 2920 mWrongPasswordNotifier.onNewConnectionAttempt(); 2921 removeMessages(CMD_DIAGS_CONNECT_TIMEOUT); 2922 sendMessageDelayed(CMD_DIAGS_CONNECT_TIMEOUT, DIAGS_CONNECT_TIMEOUT_MILLIS); 2923 } 2924 handleConnectionAttemptEndForDiagnostics(int level2FailureCode)2925 private void handleConnectionAttemptEndForDiagnostics(int level2FailureCode) { 2926 switch (level2FailureCode) { 2927 case WifiMetrics.ConnectionEvent.FAILURE_NONE: 2928 break; 2929 case WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED: 2930 // WifiDiagnostics doesn't care about pre-empted connections, or cases 2931 // where we failed to initiate a connection attempt with supplicant. 2932 break; 2933 default: 2934 removeMessages(CMD_DIAGS_CONNECT_TIMEOUT); 2935 mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); 2936 } 2937 } 2938 2939 /** 2940 * Inform other components (WifiMetrics, WifiDiagnostics, WifiConnectivityManager, etc.) that 2941 * the current connection attempt has concluded. 2942 */ reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode, int level2FailureReason)2943 private void reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode, 2944 int level2FailureReason) { 2945 // if connected, this should be non-null. 2946 WifiConfiguration configuration = getCurrentWifiConfiguration(); 2947 if (configuration == null) { 2948 // If not connected, this should be non-null. 2949 configuration = getTargetWifiConfiguration(); 2950 } 2951 2952 String bssid = mLastBssid == null ? mTargetBssid : mLastBssid; 2953 String ssid = mWifiInfo.getSSID(); 2954 if (WifiManager.UNKNOWN_SSID.equals(ssid)) { 2955 ssid = getTargetSsid(); 2956 } 2957 if (level2FailureCode != WifiMetrics.ConnectionEvent.FAILURE_NONE) { 2958 int blocklistReason = convertToBssidBlocklistMonitorFailureReason( 2959 level2FailureCode, level2FailureReason); 2960 if (blocklistReason != -1) { 2961 int networkId = (configuration == null) ? WifiConfiguration.INVALID_NETWORK_ID 2962 : configuration.networkId; 2963 int scanRssi = mWifiConfigManager.findScanRssi(networkId, 2964 mWifiHealthMonitor.getScanRssiValidTimeMs()); 2965 mWifiScoreCard.noteConnectionFailure(mWifiInfo, scanRssi, ssid, blocklistReason); 2966 checkAbnormalConnectionFailureAndTakeBugReport(ssid); 2967 mBssidBlocklistMonitor.handleBssidConnectionFailure(bssid, ssid, blocklistReason, 2968 scanRssi); 2969 } 2970 } 2971 2972 if (configuration != null 2973 && configuration.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { 2974 if (level2FailureCode == WifiMetrics.ConnectionEvent.FAILURE_NONE) { 2975 mWifiMetrics.incrementNumOfCarrierWifiConnectionSuccess(); 2976 } else if (level2FailureCode 2977 == WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE 2978 && level2FailureReason 2979 != WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE) { 2980 mWifiMetrics.incrementNumOfCarrierWifiConnectionAuthFailure(); 2981 } else { 2982 mWifiMetrics.incrementNumOfCarrierWifiConnectionNonAuthFailure(); 2983 } 2984 } 2985 2986 boolean isAssociationRejection = level2FailureCode 2987 == WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION; 2988 boolean isAuthenticationFailure = level2FailureCode 2989 == WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE 2990 && level2FailureReason != WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD; 2991 if ((isAssociationRejection || isAuthenticationFailure) 2992 && mWifiConfigManager.isInFlakyRandomizationSsidHotlist(mTargetNetworkId)) { 2993 mConnectionFailureNotifier 2994 .showFailedToConnectDueToNoRandomizedMacSupportNotification(mTargetNetworkId); 2995 } 2996 2997 mWifiMetrics.endConnectionEvent(level2FailureCode, connectivityFailureCode, 2998 level2FailureReason); 2999 mWifiConnectivityManager.handleConnectionAttemptEnded(level2FailureCode, bssid, ssid); 3000 if (configuration != null) { 3001 mNetworkFactory.handleConnectionAttemptEnded(level2FailureCode, configuration); 3002 mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( 3003 level2FailureCode, configuration, getCurrentBSSID()); 3004 ScanResult candidate = configuration.getNetworkSelectionStatus().getCandidate(); 3005 if (candidate != null && !TextUtils.equals(candidate.BSSID, getCurrentBSSID())) { 3006 mWifiMetrics.incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware(); 3007 } 3008 } 3009 handleConnectionAttemptEndForDiagnostics(level2FailureCode); 3010 } 3011 3012 /* If this connection attempt fails after 802.1x stage, clear intermediate cached data. */ clearNetworkCachedDataIfNeeded(WifiConfiguration config, int reason)3013 void clearNetworkCachedDataIfNeeded(WifiConfiguration config, int reason) { 3014 if (config == null) return; 3015 3016 switch(reason) { 3017 case 14: // MICHAEL_MIC_FAILURE 3018 case 15: // 4WAY_HANDSHAKE_TIMEOUT 3019 case 16: // GROUP_KEY_UPDATE_TIMEOUT 3020 case 17: // IE_IN_4WAY_DIFFERS 3021 case 18: // GROUP_CIPHER_NOT_VALID 3022 case 19: // PAIRWISE_CIPHER_NOT_VALID 3023 case 20: // AKMP_NOT_VALID 3024 case 23: // IEEE_802_1X_AUTH_FAILED 3025 case 24: // CIPHER_SUITE_REJECTED 3026 case 29: // BAD_CIPHER_OR_AKM 3027 case 45: // PEERKEY_MISMATCH 3028 case 49: // INVALID_PMKID 3029 mWifiNative.removeNetworkCachedData(config.networkId); 3030 break; 3031 default: 3032 logi("Keep PMK cache for network disconnection reason " + reason); 3033 break; 3034 } 3035 } 3036 3037 /** 3038 * Returns the sufficient RSSI for the frequency that this network is last seen on. 3039 */ getSufficientRssi(int networkId, String bssid)3040 private int getSufficientRssi(int networkId, String bssid) { 3041 ScanDetailCache scanDetailCache = 3042 mWifiConfigManager.getScanDetailCacheForNetwork(networkId); 3043 if (scanDetailCache == null) { 3044 return WifiInfo.INVALID_RSSI; 3045 } 3046 ScanResult scanResult = scanDetailCache.getScanResult(bssid); 3047 if (scanResult == null) { 3048 return WifiInfo.INVALID_RSSI; 3049 } 3050 return mWifiInjector.getScoringParams().getSufficientRssi(scanResult.frequency); 3051 } 3052 convertToBssidBlocklistMonitorFailureReason( int level2FailureCode, int failureReason)3053 private int convertToBssidBlocklistMonitorFailureReason( 3054 int level2FailureCode, int failureReason) { 3055 switch (level2FailureCode) { 3056 case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT: 3057 return BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT; 3058 case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION: 3059 if (failureReason == WifiMetricsProto.ConnectionEvent 3060 .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA) { 3061 return BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA; 3062 } 3063 return BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION; 3064 case WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE: 3065 if (failureReason == WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD) { 3066 return BssidBlocklistMonitor.REASON_WRONG_PASSWORD; 3067 } else if (failureReason == WifiMetricsProto.ConnectionEvent 3068 .AUTH_FAILURE_EAP_FAILURE) { 3069 return BssidBlocklistMonitor.REASON_EAP_FAILURE; 3070 } 3071 return BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE; 3072 case WifiMetrics.ConnectionEvent.FAILURE_DHCP: 3073 return BssidBlocklistMonitor.REASON_DHCP_FAILURE; 3074 default: 3075 return -1; 3076 } 3077 } 3078 handleIPv4Success(DhcpResultsParcelable dhcpResults)3079 private void handleIPv4Success(DhcpResultsParcelable dhcpResults) { 3080 if (mVerboseLoggingEnabled) { 3081 logd("handleIPv4Success <" + dhcpResults.toString() + ">"); 3082 logd("link address " + dhcpResults.baseConfiguration.getIpAddress()); 3083 } 3084 3085 Inet4Address addr; 3086 synchronized (mDhcpResultsParcelableLock) { 3087 mDhcpResultsParcelable = dhcpResults; 3088 addr = (Inet4Address) dhcpResults.baseConfiguration.getIpAddress().getAddress(); 3089 } 3090 3091 if (mIsAutoRoaming) { 3092 int previousAddress = mWifiInfo.getIpAddress(); 3093 int newAddress = Inet4AddressUtils.inet4AddressToIntHTL(addr); 3094 if (previousAddress != newAddress) { 3095 logd("handleIPv4Success, roaming and address changed" 3096 + mWifiInfo + " got: " + addr); 3097 } 3098 } 3099 3100 mWifiInfo.setInetAddress(addr); 3101 3102 final WifiConfiguration config = getCurrentWifiConfiguration(); 3103 if (config != null) { 3104 mWifiInfo.setEphemeral(config.ephemeral); 3105 mWifiInfo.setTrusted(config.trusted); 3106 mWifiConfigManager.updateRandomizedMacExpireTime(config, dhcpResults.leaseDuration); 3107 mBssidBlocklistMonitor.handleDhcpProvisioningSuccess(mLastBssid, mWifiInfo.getSSID()); 3108 } 3109 3110 // Set meteredHint if DHCP result says network is metered 3111 if (dhcpResults.vendorInfo != null && dhcpResults.vendorInfo.contains("ANDROID_METERED")) { 3112 mWifiInfo.setMeteredHint(true); 3113 mWifiMetrics.addMeteredStat(config, true); 3114 } else { 3115 mWifiMetrics.addMeteredStat(config, false); 3116 } 3117 3118 updateCapabilities(config); 3119 } 3120 handleSuccessfulIpConfiguration()3121 private void handleSuccessfulIpConfiguration() { 3122 mLastSignalLevel = -1; // Force update of signal strength 3123 WifiConfiguration c = getCurrentWifiConfiguration(); 3124 if (c != null) { 3125 // Reset IP failure tracking 3126 c.getNetworkSelectionStatus().clearDisableReasonCounter( 3127 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3128 3129 // Tell the framework whether the newly connected network is trusted or untrusted. 3130 updateCapabilities(c); 3131 } 3132 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 3133 } 3134 handleIPv4Failure()3135 private void handleIPv4Failure() { 3136 // TODO: Move this to provisioning failure, not DHCP failure. 3137 // DHCPv4 failure is expected on an IPv6-only network. 3138 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_DHCP_FAILURE); 3139 if (mVerboseLoggingEnabled) { 3140 int count = -1; 3141 WifiConfiguration config = getCurrentWifiConfiguration(); 3142 if (config != null) { 3143 count = config.getNetworkSelectionStatus().getDisableReasonCounter( 3144 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3145 } 3146 log("DHCP failure count=" + count); 3147 } 3148 reportConnectionAttemptEnd( 3149 WifiMetrics.ConnectionEvent.FAILURE_DHCP, 3150 WifiMetricsProto.ConnectionEvent.HLF_DHCP, 3151 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 3152 synchronized (mDhcpResultsParcelableLock) { 3153 mDhcpResultsParcelable = new DhcpResultsParcelable(); 3154 } 3155 if (mVerboseLoggingEnabled) { 3156 logd("handleIPv4Failure"); 3157 } 3158 } 3159 handleIpConfigurationLost()3160 private void handleIpConfigurationLost() { 3161 mWifiInfo.setInetAddress(null); 3162 mWifiInfo.setMeteredHint(false); 3163 3164 mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId, 3165 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3166 3167 /* DHCP times out after about 30 seconds, we do a 3168 * disconnect thru supplicant, we will let autojoin retry connecting to the network 3169 */ 3170 mWifiNative.disconnect(mInterfaceName); 3171 } 3172 handleIpReachabilityLost()3173 private void handleIpReachabilityLost() { 3174 mWifiScoreCard.noteIpReachabilityLost(mWifiInfo); 3175 mWifiInfo.setInetAddress(null); 3176 mWifiInfo.setMeteredHint(false); 3177 3178 // Disconnect via supplicant, and let autojoin retry connecting to the network. 3179 mWifiNative.disconnect(mInterfaceName); 3180 } 3181 3182 /* 3183 * Read a MAC address in /proc/arp/table, used by ClientModeImpl 3184 * so as to record MAC address of default gateway. 3185 **/ macAddressFromRoute(String ipAddress)3186 private String macAddressFromRoute(String ipAddress) { 3187 String macAddress = null; 3188 BufferedReader reader = null; 3189 try { 3190 reader = new BufferedReader(new FileReader("/proc/net/arp")); 3191 3192 // Skip over the line bearing column titles 3193 String line = reader.readLine(); 3194 3195 while ((line = reader.readLine()) != null) { 3196 String[] tokens = line.split("[ ]+"); 3197 if (tokens.length < 6) { 3198 continue; 3199 } 3200 3201 // ARP column format is 3202 // Address HWType HWAddress Flags Mask IFace 3203 String ip = tokens[0]; 3204 String mac = tokens[3]; 3205 3206 if (ipAddress.equals(ip)) { 3207 macAddress = mac; 3208 break; 3209 } 3210 } 3211 3212 if (macAddress == null) { 3213 loge("Did not find remoteAddress {" + ipAddress + "} in /proc/net/arp"); 3214 } 3215 3216 } catch (FileNotFoundException e) { 3217 loge("Could not open /proc/net/arp to lookup mac address"); 3218 } catch (IOException e) { 3219 loge("Could not read /proc/net/arp to lookup mac address"); 3220 } finally { 3221 try { 3222 if (reader != null) { 3223 reader.close(); 3224 } 3225 } catch (IOException e) { 3226 // Do nothing 3227 } 3228 } 3229 return macAddress; 3230 3231 } 3232 3233 /** 3234 * Determine if the specified auth failure is considered to be a permanent wrong password 3235 * failure. The criteria for such failure is when wrong password error is detected 3236 * and the network had never been connected before. 3237 * 3238 * For networks that have previously connected successfully, we consider wrong password 3239 * failures to be temporary, to be on the conservative side. Since this might be the 3240 * case where we are trying to connect to a wrong network (e.g. A network with same SSID 3241 * but different password). 3242 */ isPermanentWrongPasswordFailure(int networkId, int reasonCode)3243 private boolean isPermanentWrongPasswordFailure(int networkId, int reasonCode) { 3244 if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD) { 3245 return false; 3246 } 3247 WifiConfiguration network = mWifiConfigManager.getConfiguredNetwork(networkId); 3248 if (network != null && network.getNetworkSelectionStatus().hasEverConnected()) { 3249 return false; 3250 } 3251 return true; 3252 } 3253 registerNetworkFactory()3254 void registerNetworkFactory() { 3255 if (!checkAndSetConnectivityInstance()) return; 3256 mNetworkFactory.register(); 3257 mUntrustedNetworkFactory.register(); 3258 } 3259 3260 /** 3261 * ClientModeImpl needs to enable/disable other services when wifi is in client mode. This 3262 * method allows ClientModeImpl to get these additional system services. 3263 * 3264 * At this time, this method is used to setup variables for P2P service and Wifi Aware. 3265 */ getAdditionalWifiServiceInterfaces()3266 private void getAdditionalWifiServiceInterfaces() { 3267 // First set up Wifi Direct 3268 if (mP2pSupported) { 3269 WifiP2pManager wifiP2pService = mContext.getSystemService(WifiP2pManager.class); 3270 3271 if (wifiP2pService != null) { 3272 mWifiP2pChannel = new AsyncChannel(); 3273 mWifiP2pChannel.connect(mContext, getHandler(), 3274 wifiP2pService.getP2pStateMachineMessenger()); 3275 } 3276 } 3277 } 3278 3279 /** 3280 * Dynamically change the MAC address to use the locally randomized 3281 * MAC address generated for each network. 3282 * @param config WifiConfiguration with mRandomizedMacAddress to change into. If the address 3283 * is masked out or not set, it will generate a new random MAC address. 3284 */ configureRandomizedMacAddress(WifiConfiguration config)3285 private void configureRandomizedMacAddress(WifiConfiguration config) { 3286 if (config == null) { 3287 Log.e(TAG, "No config to change MAC address to"); 3288 return; 3289 } 3290 String currentMacString = mWifiNative.getMacAddress(mInterfaceName); 3291 MacAddress currentMac = currentMacString == null ? null : 3292 MacAddress.fromString(currentMacString); 3293 MacAddress newMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config); 3294 if (!WifiConfiguration.isValidMacAddressForRandomization(newMac)) { 3295 Log.wtf(TAG, "Config generated an invalid MAC address"); 3296 } else if (newMac.equals(currentMac)) { 3297 Log.d(TAG, "No changes in MAC address"); 3298 } else { 3299 mWifiMetrics.logStaEvent(StaEvent.TYPE_MAC_CHANGE, config); 3300 boolean setMacSuccess = 3301 mWifiNative.setMacAddress(mInterfaceName, newMac); 3302 if (setMacSuccess) { 3303 mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, newMac); 3304 } 3305 Log.d(TAG, "ConnectedMacRandomization SSID(" + config.getPrintableSsid() 3306 + "). setMacAddress(" + newMac.toString() + ") from " 3307 + currentMacString + " = " + setMacSuccess); 3308 } 3309 } 3310 3311 /** 3312 * Sets the current MAC to the factory MAC address. 3313 */ setCurrentMacToFactoryMac(WifiConfiguration config)3314 private void setCurrentMacToFactoryMac(WifiConfiguration config) { 3315 MacAddress factoryMac = mWifiNative.getFactoryMacAddress(mInterfaceName); 3316 if (factoryMac == null) { 3317 Log.e(TAG, "Fail to set factory MAC address. Factory MAC is null."); 3318 return; 3319 } 3320 String currentMacStr = mWifiNative.getMacAddress(mInterfaceName); 3321 if (!TextUtils.equals(currentMacStr, factoryMac.toString())) { 3322 if (mWifiNative.setMacAddress(mInterfaceName, factoryMac)) { 3323 mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, factoryMac); 3324 mWifiMetrics.logStaEvent(StaEvent.TYPE_MAC_CHANGE, config); 3325 } else { 3326 Log.e(TAG, "Failed to set MAC address to " + "'" + factoryMac.toString() + "'"); 3327 } 3328 } 3329 } 3330 3331 /** 3332 * Helper method to check if Connected MAC Randomization is supported - onDown events are 3333 * skipped if this feature is enabled (b/72459123). 3334 * 3335 * @return boolean true if Connected MAC randomization is supported, false otherwise 3336 */ isConnectedMacRandomizationEnabled()3337 public boolean isConnectedMacRandomizationEnabled() { 3338 return mContext.getResources().getBoolean( 3339 R.bool.config_wifi_connected_mac_randomization_supported); 3340 } 3341 3342 /** 3343 * Helper method allowing ClientModeManager to report an error (interface went down) and trigger 3344 * recovery. 3345 * 3346 * @param reason int indicating the SelfRecovery failure type. 3347 */ failureDetected(int reason)3348 public void failureDetected(int reason) { 3349 // report a failure 3350 mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_STA_IFACE_DOWN); 3351 } 3352 3353 /** 3354 * Helper method to check if WPA2 network upgrade feature is enabled in the framework 3355 * 3356 * @return boolean true if feature is enabled. 3357 */ isWpa3SaeUpgradeEnabled()3358 private boolean isWpa3SaeUpgradeEnabled() { 3359 return mContext.getResources().getBoolean(R.bool.config_wifiSaeUpgradeEnabled); 3360 } 3361 3362 /** 3363 * Helper method to check if WPA2 network upgrade offload is enabled in the driver/fw 3364 * 3365 * @return boolean true if feature is enabled. 3366 */ isWpa3SaeUpgradeOffloadEnabled()3367 private boolean isWpa3SaeUpgradeOffloadEnabled() { 3368 return mContext.getResources().getBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled); 3369 } 3370 3371 /******************************************************** 3372 * HSM states 3373 *******************************************************/ 3374 3375 class DefaultState extends State { 3376 3377 @Override processMessage(Message message)3378 public boolean processMessage(Message message) { 3379 boolean handleStatus = HANDLED; 3380 int callbackIdentifier = -1; 3381 int netId; 3382 boolean ok; 3383 3384 switch (message.what) { 3385 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 3386 AsyncChannel ac = (AsyncChannel) message.obj; 3387 if (ac == mWifiP2pChannel) { 3388 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 3389 p2pSendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 3390 } else { 3391 // TODO: We should probably do some cleanup or attempt a retry 3392 // b/34283611 3393 loge("WifiP2pService connection failure, error=" + message.arg1); 3394 } 3395 } else { 3396 loge("got HALF_CONNECTED for unknown channel"); 3397 } 3398 break; 3399 } 3400 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 3401 AsyncChannel ac = (AsyncChannel) message.obj; 3402 if (ac == mWifiP2pChannel) { 3403 loge("WifiP2pService channel lost, message.arg1 =" + message.arg1); 3404 //TODO: Re-establish connection to state machine after a delay (b/34283611) 3405 // mWifiP2pChannel.connect(mContext, getHandler(), 3406 // mWifiP2pManager.getMessenger()); 3407 } 3408 break; 3409 } 3410 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 3411 // If BT was connected and then turned off, there is no CONNECTION_STATE_CHANGE 3412 // message. So we need to rely on STATE_CHANGE message to detect on->off 3413 // transition and update mBluetoothConnectionActive status correctly. 3414 mBluetoothConnectionActive = mBluetoothConnectionActive 3415 && message.arg1 != BluetoothAdapter.STATE_OFF; 3416 mWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive); 3417 break; 3418 case CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE: 3419 // Transition to a non-disconnected state does correctly 3420 // indicate BT is connected or being connected. 3421 mBluetoothConnectionActive = 3422 message.arg1 != BluetoothAdapter.STATE_DISCONNECTED; 3423 mWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive); 3424 break; 3425 case CMD_ENABLE_RSSI_POLL: 3426 mEnableRssiPolling = (message.arg1 == 1); 3427 break; 3428 case CMD_SET_HIGH_PERF_MODE: 3429 if (message.arg1 == 1) { 3430 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false); 3431 } else { 3432 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true); 3433 } 3434 break; 3435 case CMD_INITIALIZE: 3436 mWifiNative.initialize(); 3437 mWifiScoreReport.initialize(); 3438 break; 3439 case CMD_BOOT_COMPLETED: 3440 // get other services that we need to manage 3441 getAdditionalWifiServiceInterfaces(); 3442 registerNetworkFactory(); 3443 mSarManager.handleBootCompleted(); 3444 break; 3445 case CMD_SCREEN_STATE_CHANGED: 3446 handleScreenStateChanged(message.arg1 != 0); 3447 break; 3448 case CMD_DISCONNECT: 3449 case CMD_RECONNECT: 3450 case CMD_REASSOCIATE: 3451 case WifiMonitor.NETWORK_CONNECTION_EVENT: 3452 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 3453 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 3454 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 3455 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 3456 case CMD_RSSI_POLL: 3457 case CMD_ONESHOT_RSSI_POLL: 3458 case CMD_PRE_DHCP_ACTION: 3459 case CMD_PRE_DHCP_ACTION_COMPLETE: 3460 case CMD_POST_DHCP_ACTION: 3461 case WifiMonitor.SUP_REQUEST_IDENTITY: 3462 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 3463 case WifiMonitor.TARGET_BSSID_EVENT: 3464 case CMD_START_CONNECT: 3465 case CMD_START_ROAM: 3466 case WifiMonitor.ASSOCIATED_BSSID_EVENT: 3467 case CMD_UNWANTED_NETWORK: 3468 case CMD_DISCONNECTING_WATCHDOG_TIMER: 3469 case CMD_ROAM_WATCHDOG_TIMER: 3470 case CMD_SET_OPERATIONAL_MODE: 3471 // using the CMD_SET_OPERATIONAL_MODE (sent at front of queue) to trigger the 3472 // state transitions performed in setOperationalMode. 3473 break; 3474 case CMD_SET_SUSPEND_OPT_ENABLED: 3475 if (message.arg1 == 1) { 3476 if (message.arg2 == 1) { 3477 mSuspendWakeLock.release(); 3478 } 3479 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true); 3480 } else { 3481 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false); 3482 } 3483 break; 3484 case CMD_CONNECT_NETWORK: 3485 // wifi off, can't connect. 3486 callbackIdentifier = message.arg2; 3487 sendActionListenerFailure(callbackIdentifier, WifiManager.BUSY); 3488 break; 3489 case CMD_SAVE_NETWORK: 3490 // wifi off, nothing more to do here. 3491 callbackIdentifier = message.arg2; 3492 sendActionListenerSuccess(callbackIdentifier); 3493 break; 3494 case CMD_GET_SUPPORTED_FEATURES: 3495 long featureSet = (mWifiNative.getSupportedFeatureSet(mInterfaceName)); 3496 replyToMessage(message, message.what, Long.valueOf(featureSet)); 3497 break; 3498 case CMD_GET_LINK_LAYER_STATS: 3499 case CMD_GET_CURRENT_NETWORK: 3500 // Not supported hence reply with null message.obj 3501 replyToMessage(message, message.what, null); 3502 break; 3503 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 3504 NetworkInfo info = (NetworkInfo) message.obj; 3505 mP2pConnected.set(info.isConnected()); 3506 break; 3507 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 3508 mTemporarilyDisconnectWifi = (message.arg1 == 1); 3509 replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 3510 break; 3511 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 3512 case CMD_UPDATE_LINKPROPERTIES: 3513 updateLinkProperties((LinkProperties) message.obj); 3514 break; 3515 case CMD_START_SUBSCRIPTION_PROVISIONING: 3516 replyToMessage(message, message.what, 0); 3517 break; 3518 case CMD_IP_CONFIGURATION_SUCCESSFUL: 3519 case CMD_IP_CONFIGURATION_LOST: 3520 case CMD_IP_REACHABILITY_LOST: 3521 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3522 break; 3523 case CMD_START_IP_PACKET_OFFLOAD: 3524 /* fall-through */ 3525 case CMD_STOP_IP_PACKET_OFFLOAD: 3526 case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: 3527 case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF: 3528 if (mNetworkAgent != null) { 3529 mNetworkAgent.sendSocketKeepaliveEvent(message.arg1, 3530 SocketKeepalive.ERROR_INVALID_NETWORK); 3531 } 3532 break; 3533 case CMD_START_RSSI_MONITORING_OFFLOAD: 3534 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3535 break; 3536 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 3537 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3538 break; 3539 case CMD_QUERY_OSU_ICON: 3540 /* reply with arg1 = 0 - it returns API failure to the calling app 3541 * (message.what is not looked at) 3542 */ 3543 replyToMessage(message, message.what); 3544 break; 3545 case CMD_RESET_SIM_NETWORKS: 3546 /* Defer this message until supplicant is started. */ 3547 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 3548 deferMessage(message); 3549 break; 3550 case CMD_INSTALL_PACKET_FILTER: 3551 mWifiNative.installPacketFilter(mInterfaceName, (byte[]) message.obj); 3552 break; 3553 case CMD_READ_PACKET_FILTER: 3554 byte[] data = mWifiNative.readPacketFilter(mInterfaceName); 3555 if (mIpClient != null) { 3556 mIpClient.readPacketFilterComplete(data); 3557 } 3558 break; 3559 case CMD_SET_FALLBACK_PACKET_FILTERING: 3560 if ((boolean) message.obj) { 3561 mWifiNative.startFilteringMulticastV4Packets(mInterfaceName); 3562 } else { 3563 mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName); 3564 } 3565 break; 3566 case CMD_DIAGS_CONNECT_TIMEOUT: 3567 mWifiDiagnostics.reportConnectionEvent( 3568 BaseWifiDiagnostics.CONNECTION_EVENT_TIMEOUT); 3569 break; 3570 case 0: 3571 // We want to notice any empty messages (with what == 0) that might crop up. 3572 // For example, we may have recycled a message sent to multiple handlers. 3573 Log.wtf(TAG, "Error! empty message encountered"); 3574 break; 3575 default: 3576 loge("Error! unhandled message" + message); 3577 break; 3578 } 3579 3580 if (handleStatus == HANDLED) { 3581 logStateAndMessage(message, this); 3582 } 3583 3584 return handleStatus; 3585 } 3586 } 3587 3588 /** 3589 * Helper method to start other services and get state ready for client mode 3590 */ setupClientMode()3591 private void setupClientMode() { 3592 Log.d(TAG, "setupClientMode() ifacename = " + mInterfaceName); 3593 3594 setHighPerfModeEnabled(false); 3595 3596 mWifiStateTracker.updateState(WifiStateTracker.INVALID); 3597 mIpClientCallbacks = new IpClientCallbacksImpl(); 3598 mFacade.makeIpClient(mContext, mInterfaceName, mIpClientCallbacks); 3599 if (!mIpClientCallbacks.awaitCreation()) { 3600 Log.wtf(getName(), "Timeout waiting for IpClient"); 3601 } 3602 3603 setMulticastFilter(true); 3604 registerForWifiMonitorEvents(); 3605 mWifiInjector.getWifiLastResortWatchdog().clearAllFailureCounts(); 3606 setSupplicantLogLevel(); 3607 3608 // reset state related to supplicant starting 3609 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 3610 // Initialize data structures 3611 mLastBssid = null; 3612 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 3613 mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 3614 mLastSimBasedConnectionCarrierName = null; 3615 mLastSignalLevel = -1; 3616 if (isConnectedMacRandomizationEnabled()) { 3617 mWifiNative.setMacAddress(mInterfaceName, MacAddressUtils.createRandomUnicastAddress()); 3618 } 3619 mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); 3620 // TODO: b/79504296 This broadcast has been deprecated and should be removed 3621 sendSupplicantConnectionChangedBroadcast(true); 3622 3623 mWifiNative.setExternalSim(mInterfaceName, true); 3624 3625 mCountryCode.setReadyForChange(true); 3626 3627 mWifiDiagnostics.startPktFateMonitoring(mInterfaceName); 3628 mWifiDiagnostics.startLogging(mInterfaceName); 3629 3630 mMboOceController.enable(); 3631 mWifiDataStall.enablePhoneStateListener(); 3632 3633 /** 3634 * Enable bluetooth coexistence scan mode when bluetooth connection is active. 3635 * When this mode is on, some of the low-level scan parameters used by the 3636 * driver are changed to reduce interference with bluetooth 3637 */ 3638 mWifiNative.setBluetoothCoexistenceScanMode(mInterfaceName, mBluetoothConnectionActive); 3639 sendNetworkChangeBroadcast(DetailedState.DISCONNECTED); 3640 3641 // Disable legacy multicast filtering, which on some chipsets defaults to enabled. 3642 // Legacy IPv6 multicast filtering blocks ICMPv6 router advertisements which breaks IPv6 3643 // provisioning. Legacy IPv4 multicast filtering may be re-enabled later via 3644 // IpClient.Callback.setFallbackMulticastFilter() 3645 mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName); 3646 mWifiNative.stopFilteringMulticastV6Packets(mInterfaceName); 3647 3648 // Set the right suspend mode settings 3649 mWifiNative.setSuspendOptimizations(mInterfaceName, mSuspendOptNeedsDisabled == 0 3650 && mContext.getResources().getBoolean( 3651 R.bool.config_wifiSuspendOptimizationsEnabled)); 3652 3653 setPowerSave(true); 3654 3655 // Disable wpa_supplicant from auto reconnecting. 3656 mWifiNative.enableStaAutoReconnect(mInterfaceName, false); 3657 // STA has higher priority over P2P 3658 mWifiNative.setConcurrencyPriority(true); 3659 } 3660 3661 /** 3662 * Helper method to stop external services and clean up state from client mode. 3663 */ stopClientMode()3664 private void stopClientMode() { 3665 handleNetworkDisconnect(); 3666 // exiting supplicant started state is now only applicable to client mode 3667 mWifiDiagnostics.stopLogging(mInterfaceName); 3668 3669 mMboOceController.disable(); 3670 mWifiDataStall.disablePhoneStateListener(); 3671 if (mIpClient != null && mIpClient.shutdown()) { 3672 // Block to make sure IpClient has really shut down, lest cleanup 3673 // race with, say, bringup code over in tethering. 3674 mIpClientCallbacks.awaitShutdown(); 3675 } 3676 mCountryCode.setReadyForChange(false); 3677 mInterfaceName = null; 3678 mWifiScoreReport.setInterfaceName(null); 3679 // TODO: b/79504296 This broadcast has been deprecated and should be removed 3680 sendSupplicantConnectionChangedBroadcast(false); 3681 3682 // Remove any ephemeral or Passpoint networks, flush ANQP cache 3683 mWifiConfigManager.removeAllEphemeralOrPasspointConfiguredNetworks(); 3684 mWifiConfigManager.clearUserTemporarilyDisabledList(); 3685 mPasspointManager.clearAnqpRequestsAndFlushCache(); 3686 } 3687 registerConnected()3688 void registerConnected() { 3689 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 3690 mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId); 3691 // Notify PasspointManager of Passpoint network connected event. 3692 WifiConfiguration currentNetwork = getCurrentWifiConfiguration(); 3693 if (currentNetwork != null && currentNetwork.isPasspoint()) { 3694 mPasspointManager.onPasspointNetworkConnected(currentNetwork.getKey()); 3695 } 3696 } 3697 } 3698 registerDisconnected()3699 void registerDisconnected() { 3700 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 3701 mWifiConfigManager.updateNetworkAfterDisconnect(mLastNetworkId); 3702 } 3703 } 3704 3705 /** 3706 * Returns WifiConfiguration object corresponding to the currently connected network, null if 3707 * not connected. 3708 */ getCurrentWifiConfiguration()3709 public WifiConfiguration getCurrentWifiConfiguration() { 3710 if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 3711 return null; 3712 } 3713 return mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); 3714 } 3715 getTargetWifiConfiguration()3716 private WifiConfiguration getTargetWifiConfiguration() { 3717 if (mTargetNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 3718 return null; 3719 } 3720 return mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 3721 } 3722 getCurrentScanResult()3723 ScanResult getCurrentScanResult() { 3724 WifiConfiguration config = getCurrentWifiConfiguration(); 3725 if (config == null) { 3726 return null; 3727 } 3728 String bssid = mWifiInfo.getBSSID(); 3729 if (bssid == null) { 3730 bssid = mTargetBssid; 3731 } 3732 ScanDetailCache scanDetailCache = 3733 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); 3734 3735 if (scanDetailCache == null) { 3736 return null; 3737 } 3738 3739 return scanDetailCache.getScanResult(bssid); 3740 } 3741 getCurrentBSSID()3742 String getCurrentBSSID() { 3743 return mLastBssid; 3744 } 3745 getCurrentBssid()3746 MacAddress getCurrentBssid() { 3747 MacAddress bssid = null; 3748 try { 3749 bssid = (mLastBssid != null) ? MacAddress.fromString(mLastBssid) : null; 3750 } catch (IllegalArgumentException e) { 3751 Log.e(TAG, "Invalid BSSID format: " + mLastBssid); 3752 } 3753 return bssid; 3754 } 3755 connectToNetwork(WifiConfiguration config)3756 void connectToNetwork(WifiConfiguration config) { 3757 if ((config != null) && mWifiNative.connectToNetwork(mInterfaceName, config)) { 3758 mWifiInjector.getWifiLastResortWatchdog().noteStartConnectTime(); 3759 mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT, config); 3760 mLastConnectAttemptTimestamp = mClock.getWallClockMillis(); 3761 mIsAutoRoaming = false; 3762 if (getCurrentState() != mDisconnectedState) { 3763 transitionTo(mDisconnectingState); 3764 } 3765 } else { 3766 loge("CMD_START_CONNECT Failed to start connection to network " + config); 3767 mTargetWifiConfiguration = null; 3768 stopIpClient(); 3769 reportConnectionAttemptEnd( 3770 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 3771 WifiMetricsProto.ConnectionEvent.HLF_NONE, 3772 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 3773 } 3774 } 3775 3776 class ConnectModeState extends State { 3777 3778 @Override enter()3779 public void enter() { 3780 Log.d(TAG, "entering ConnectModeState: ifaceName = " + mInterfaceName); 3781 mOperationalMode = CONNECT_MODE; 3782 setupClientMode(); 3783 if (!mWifiNative.removeAllNetworks(mInterfaceName)) { 3784 loge("Failed to remove networks on entering connect mode"); 3785 } 3786 mWifiInfo.reset(); 3787 mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); 3788 3789 mWifiInjector.getWakeupController().reset(); 3790 sendNetworkChangeBroadcast(DetailedState.DISCONNECTED); 3791 3792 // Inform WifiConnectivityManager that Wifi is enabled 3793 mWifiConnectivityManager.setWifiEnabled(true); 3794 mNetworkFactory.setWifiState(true); 3795 // Inform metrics that Wifi is Enabled (but not yet connected) 3796 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 3797 mWifiMetrics.logStaEvent(StaEvent.TYPE_WIFI_ENABLED); 3798 mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); 3799 mWifiHealthMonitor.setWifiEnabled(true); 3800 mWifiDataStall.init(); 3801 } 3802 3803 @Override exit()3804 public void exit() { 3805 mOperationalMode = DISABLED_MODE; 3806 3807 // Inform WifiConnectivityManager that Wifi is disabled 3808 mWifiConnectivityManager.setWifiEnabled(false); 3809 mNetworkFactory.setWifiState(false); 3810 // Inform metrics that Wifi is being disabled (Toggled, airplane enabled, etc) 3811 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISABLED); 3812 mWifiMetrics.logStaEvent(StaEvent.TYPE_WIFI_DISABLED); 3813 // Inform scorecard that wifi is being disabled 3814 mWifiScoreCard.noteWifiDisabled(mWifiInfo); 3815 3816 if (!mWifiNative.removeAllNetworks(mInterfaceName)) { 3817 loge("Failed to remove networks on exiting connect mode"); 3818 } 3819 mWifiInfo.reset(); 3820 mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); 3821 mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); 3822 mWifiHealthMonitor.setWifiEnabled(false); 3823 mWifiDataStall.reset(); 3824 stopClientMode(); 3825 } 3826 3827 @Override processMessage(Message message)3828 public boolean processMessage(Message message) { 3829 WifiConfiguration config; 3830 int netId; 3831 boolean ok; 3832 boolean didDisconnect; 3833 String bssid; 3834 String ssid; 3835 NetworkUpdateResult result; 3836 Set<Integer> removedNetworkIds; 3837 int reasonCode; 3838 boolean timedOut; 3839 boolean handleStatus = HANDLED; 3840 int callbackIdentifier = -1; 3841 3842 int level2FailureReason = 3843 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN; 3844 switch (message.what) { 3845 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 3846 stopIpClient(); 3847 mWifiDiagnostics.captureBugReportData( 3848 WifiDiagnostics.REPORT_REASON_ASSOC_FAILURE); 3849 mDidBlackListBSSID = false; 3850 bssid = (String) message.obj; 3851 timedOut = message.arg1 > 0; 3852 reasonCode = message.arg2; 3853 Log.d(TAG, "Association Rejection event: bssid=" + bssid + " reason code=" 3854 + reasonCode + " timedOut=" + Boolean.toString(timedOut)); 3855 if (bssid == null || TextUtils.isEmpty(bssid)) { 3856 // If BSSID is null, use the target roam BSSID 3857 bssid = mTargetBssid; 3858 } else if (mTargetBssid == SUPPLICANT_BSSID_ANY) { 3859 // This is needed by BssidBlocklistMonitor to block continuously 3860 // failing BSSIDs. Need to set here because mTargetBssid is currently 3861 // not being set until association success. 3862 mTargetBssid = bssid; 3863 } 3864 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 3865 WifiConfiguration.NetworkSelectionStatus 3866 .DISABLED_ASSOCIATION_REJECTION); 3867 mWifiConfigManager.setRecentFailureAssociationStatus(mTargetNetworkId, 3868 reasonCode); 3869 3870 if (reasonCode == REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA) { 3871 level2FailureReason = WifiMetricsProto.ConnectionEvent 3872 .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA; 3873 } 3874 // If rejection occurred while Metrics is tracking a ConnnectionEvent, end it. 3875 reportConnectionAttemptEnd( 3876 timedOut 3877 ? WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT 3878 : WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, 3879 WifiMetricsProto.ConnectionEvent.HLF_NONE, 3880 level2FailureReason); 3881 if (reasonCode != REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA) { 3882 mWifiInjector.getWifiLastResortWatchdog() 3883 .noteConnectionFailureAndTriggerIfNeeded( 3884 getTargetSsid(), bssid, 3885 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 3886 } 3887 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 3888 break; 3889 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 3890 stopIpClient(); 3891 mWifiDiagnostics.captureBugReportData( 3892 WifiDiagnostics.REPORT_REASON_AUTH_FAILURE); 3893 int disableReason = WifiConfiguration.NetworkSelectionStatus 3894 .DISABLED_AUTHENTICATION_FAILURE; 3895 reasonCode = message.arg1; 3896 WifiConfiguration targetedNetwork = 3897 mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 3898 // Check if this is a permanent wrong password failure. 3899 if (isPermanentWrongPasswordFailure(mTargetNetworkId, reasonCode)) { 3900 disableReason = WifiConfiguration.NetworkSelectionStatus 3901 .DISABLED_BY_WRONG_PASSWORD; 3902 if (targetedNetwork != null) { 3903 mWrongPasswordNotifier.onWrongPasswordError( 3904 targetedNetwork.SSID); 3905 } 3906 } else if (reasonCode == WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE) { 3907 int errorCode = message.arg2; 3908 if (targetedNetwork != null && targetedNetwork.enterpriseConfig != null 3909 && targetedNetwork.enterpriseConfig.isAuthenticationSimBased()) { 3910 mEapFailureNotifier.onEapFailure(errorCode, targetedNetwork); 3911 } 3912 handleEapAuthFailure(mTargetNetworkId, errorCode); 3913 if (errorCode == WifiNative.EAP_SIM_NOT_SUBSCRIBED) { 3914 disableReason = WifiConfiguration.NetworkSelectionStatus 3915 .DISABLED_AUTHENTICATION_NO_SUBSCRIPTION; 3916 } 3917 } 3918 mWifiConfigManager.updateNetworkSelectionStatus( 3919 mTargetNetworkId, disableReason); 3920 mWifiConfigManager.clearRecentFailureReason(mTargetNetworkId); 3921 3922 //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. 3923 switch (reasonCode) { 3924 case WifiManager.ERROR_AUTH_FAILURE_NONE: 3925 level2FailureReason = 3926 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE; 3927 break; 3928 case WifiManager.ERROR_AUTH_FAILURE_TIMEOUT: 3929 level2FailureReason = 3930 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT; 3931 break; 3932 case WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD: 3933 level2FailureReason = 3934 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD; 3935 break; 3936 case WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE: 3937 level2FailureReason = 3938 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE; 3939 break; 3940 default: 3941 level2FailureReason = 3942 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN; 3943 break; 3944 } 3945 reportConnectionAttemptEnd( 3946 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, 3947 WifiMetricsProto.ConnectionEvent.HLF_NONE, 3948 level2FailureReason); 3949 if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD && reasonCode 3950 != WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE) { 3951 mWifiInjector.getWifiLastResortWatchdog() 3952 .noteConnectionFailureAndTriggerIfNeeded( 3953 getTargetSsid(), 3954 (mLastBssid == null) ? mTargetBssid : mLastBssid, 3955 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 3956 } 3957 break; 3958 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 3959 SupplicantState state = handleSupplicantStateChange(message); 3960 3961 // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT 3962 // when authentication times out after a successful connection, 3963 // we can figure this from the supplicant state. If supplicant 3964 // state is DISCONNECTED, but the agent is not disconnected, we 3965 // need to handle a disconnection 3966 if (state == SupplicantState.DISCONNECTED && mNetworkAgent != null) { 3967 if (mVerboseLoggingEnabled) { 3968 log("Missed CTRL-EVENT-DISCONNECTED, disconnect"); 3969 } 3970 handleNetworkDisconnect(); 3971 transitionTo(mDisconnectedState); 3972 } 3973 3974 if (state == SupplicantState.COMPLETED) { 3975 mWifiScoreReport.noteIpCheck(); 3976 } 3977 break; 3978 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 3979 if (message.arg1 == 1) { 3980 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 3981 StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); 3982 mWifiNative.disconnect(mInterfaceName); 3983 mTemporarilyDisconnectWifi = true; 3984 } else { 3985 mWifiNative.reconnect(mInterfaceName); 3986 mTemporarilyDisconnectWifi = false; 3987 } 3988 break; 3989 case WifiMonitor.SUP_REQUEST_IDENTITY: 3990 netId = message.arg2; 3991 boolean identitySent = false; 3992 // For SIM & AKA/AKA' EAP method Only, get identity from ICC 3993 if (mTargetWifiConfiguration != null 3994 && mTargetWifiConfiguration.networkId == netId 3995 && mTargetWifiConfiguration.enterpriseConfig != null 3996 && mTargetWifiConfiguration.enterpriseConfig 3997 .isAuthenticationSimBased()) { 3998 // Pair<identity, encrypted identity> 3999 Pair<String, String> identityPair = mWifiCarrierInfoManager 4000 .getSimIdentity(mTargetWifiConfiguration); 4001 if (identityPair != null && identityPair.first != null) { 4002 Log.i(TAG, "SUP_REQUEST_IDENTITY: identityPair=[" 4003 + ((identityPair.first.length() >= 7) 4004 ? identityPair.first.substring(0, 7 /* Prefix+PLMN ID */) 4005 + "****" 4006 : identityPair.first) + ", " 4007 + (!TextUtils.isEmpty(identityPair.second) ? identityPair.second 4008 : "<NONE>") + "]"); 4009 mWifiNative.simIdentityResponse(mInterfaceName, identityPair.first, 4010 identityPair.second); 4011 identitySent = true; 4012 } else { 4013 Log.e(TAG, "Unable to retrieve identity from Telephony"); 4014 } 4015 } 4016 4017 if (!identitySent) { 4018 // Supplicant lacks credentials to connect to that network, hence black list 4019 ssid = (String) message.obj; 4020 if (mTargetWifiConfiguration != null && ssid != null 4021 && mTargetWifiConfiguration.SSID != null 4022 && mTargetWifiConfiguration.SSID.equals("\"" + ssid + "\"")) { 4023 mWifiConfigManager.updateNetworkSelectionStatus( 4024 mTargetWifiConfiguration.networkId, 4025 WifiConfiguration.NetworkSelectionStatus 4026 .DISABLED_AUTHENTICATION_NO_CREDENTIALS); 4027 } 4028 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 4029 StaEvent.DISCONNECT_GENERIC); 4030 mWifiNative.disconnect(mInterfaceName); 4031 } 4032 break; 4033 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 4034 logd("Received SUP_REQUEST_SIM_AUTH"); 4035 SimAuthRequestData requestData = (SimAuthRequestData) message.obj; 4036 if (requestData != null) { 4037 if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) { 4038 handleGsmAuthRequest(requestData); 4039 } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA 4040 || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) { 4041 handle3GAuthRequest(requestData); 4042 } 4043 } else { 4044 loge("Invalid SIM auth request"); 4045 } 4046 break; 4047 case CMD_START_SUBSCRIPTION_PROVISIONING: 4048 IProvisioningCallback callback = (IProvisioningCallback) message.obj; 4049 OsuProvider provider = 4050 (OsuProvider) message.getData().getParcelable(EXTRA_OSU_PROVIDER); 4051 int res = mPasspointManager.startSubscriptionProvisioning( 4052 message.arg1, provider, callback) ? 1 : 0; 4053 replyToMessage(message, message.what, res); 4054 break; 4055 case CMD_RECONNECT: 4056 WorkSource workSource = (WorkSource) message.obj; 4057 mWifiConnectivityManager.forceConnectivityScan(workSource); 4058 break; 4059 case CMD_REASSOCIATE: 4060 mLastConnectAttemptTimestamp = mClock.getWallClockMillis(); 4061 mWifiNative.reassociate(mInterfaceName); 4062 break; 4063 case CMD_START_ROAM: 4064 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4065 break; 4066 case CMD_START_CONNECT: 4067 /* connect command coming from auto-join */ 4068 netId = message.arg1; 4069 int uid = message.arg2; 4070 bssid = (String) message.obj; 4071 mSentHLPs = false; 4072 4073 if (!hasConnectionRequests()) { 4074 if (mNetworkAgent == null) { 4075 loge("CMD_START_CONNECT but no requests and not connected," 4076 + " bailing"); 4077 break; 4078 } else if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 4079 loge("CMD_START_CONNECT but no requests and connected, but app " 4080 + "does not have sufficient permissions, bailing"); 4081 break; 4082 } 4083 } 4084 config = mWifiConfigManager.getConfiguredNetworkWithoutMasking(netId); 4085 logd("CMD_START_CONNECT " 4086 + " my state " + getCurrentState().getName() 4087 + " nid=" + Integer.toString(netId) 4088 + " roam=" + Boolean.toString(mIsAutoRoaming)); 4089 if (config == null) { 4090 loge("CMD_START_CONNECT and no config, bail out..."); 4091 break; 4092 } 4093 mTargetNetworkId = netId; 4094 // Update scorecard while there is still state from existing connection 4095 int scanRssi = mWifiConfigManager.findScanRssi(netId, 4096 mWifiHealthMonitor.getScanRssiValidTimeMs()); 4097 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, scanRssi, config.SSID); 4098 mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(config.SSID); 4099 4100 updateWifiConfigOnStartConnection(config, bssid); 4101 reportConnectionAttemptStart(config, mTargetBssid, 4102 WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); 4103 4104 String currentMacAddress = mWifiNative.getMacAddress(mInterfaceName); 4105 mWifiInfo.setMacAddress(currentMacAddress); 4106 Log.i(TAG, "Connecting with " + currentMacAddress + " as the mac address"); 4107 4108 mTargetWifiConfiguration = config; 4109 /* Check for FILS configuration again after updating the config */ 4110 if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256) 4111 || config.allowedKeyManagement.get( 4112 WifiConfiguration.KeyMgmt.FILS_SHA384)) { 4113 4114 boolean isIpClientStarted = startIpClient(config, true); 4115 if (isIpClientStarted) { 4116 mIpClientWithPreConnection = true; 4117 break; 4118 } 4119 } 4120 connectToNetwork(config); 4121 break; 4122 case CMD_START_FILS_CONNECTION: 4123 mWifiMetrics.incrementConnectRequestWithFilsAkmCount(); 4124 List<Layer2PacketParcelable> packets; 4125 packets = (List<Layer2PacketParcelable>) message.obj; 4126 if (mVerboseLoggingEnabled) { 4127 Log.d(TAG, "Send HLP IEs to supplicant"); 4128 } 4129 addLayer2PacketsToHlpReq(packets); 4130 config = mTargetWifiConfiguration; 4131 connectToNetwork(config); 4132 break; 4133 case CMD_CONNECT_NETWORK: 4134 callbackIdentifier = message.arg2; 4135 result = (NetworkUpdateResult) message.obj; 4136 netId = result.getNetworkId(); 4137 connectToUserSelectNetwork( 4138 netId, message.sendingUid, result.hasCredentialChanged()); 4139 mWifiMetrics.logStaEvent( 4140 StaEvent.TYPE_CONNECT_NETWORK, 4141 mWifiConfigManager.getConfiguredNetwork(netId)); 4142 sendActionListenerSuccess(callbackIdentifier); 4143 break; 4144 case CMD_SAVE_NETWORK: 4145 callbackIdentifier = message.arg2; 4146 result = (NetworkUpdateResult) message.obj; 4147 netId = result.getNetworkId(); 4148 if (mWifiInfo.getNetworkId() == netId) { 4149 if (result.hasCredentialChanged()) { 4150 // The network credentials changed and we're connected to this network, 4151 // start a new connection with the updated credentials. 4152 logi("CMD_SAVE_NETWORK credential changed for nid=" 4153 + netId + ". Reconnecting."); 4154 startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY); 4155 } else { 4156 if (result.hasProxyChanged()) { 4157 if (mIpClient != null) { 4158 log("Reconfiguring proxy on connection"); 4159 WifiConfiguration currentConfig = getCurrentWifiConfiguration(); 4160 if (currentConfig != null) { 4161 mIpClient.setHttpProxy(currentConfig.getHttpProxy()); 4162 } else { 4163 Log.w(TAG, 4164 "CMD_SAVE_NETWORK proxy change - but no current " 4165 + "Wi-Fi config"); 4166 } 4167 } 4168 } 4169 if (result.hasIpChanged()) { 4170 // The current connection configuration was changed 4171 // We switched from DHCP to static or from static to DHCP, or the 4172 // static IP address has changed. 4173 log("Reconfiguring IP on connection"); 4174 WifiConfiguration currentConfig = getCurrentWifiConfiguration(); 4175 if (currentConfig != null) { 4176 transitionTo(mObtainingIpState); 4177 } else { 4178 Log.w(TAG, "CMD_SAVE_NETWORK Ip change - but no current " 4179 + "Wi-Fi config"); 4180 } 4181 } 4182 } 4183 } else if (mWifiInfo.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID 4184 && result.hasCredentialChanged()) { 4185 logi("CMD_SAVE_NETWORK credential changed for nid=" 4186 + netId + " while disconnected. Connecting."); 4187 startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY); 4188 } 4189 sendActionListenerSuccess(callbackIdentifier); 4190 break; 4191 case WifiMonitor.ASSOCIATED_BSSID_EVENT: 4192 // This is where we can confirm the connection BSSID. Use it to find the 4193 // right ScanDetail to populate metrics. 4194 String someBssid = (String) message.obj; 4195 if (someBssid != null) { 4196 // Get the ScanDetail associated with this BSSID. 4197 ScanDetailCache scanDetailCache = 4198 mWifiConfigManager.getScanDetailCacheForNetwork(mTargetNetworkId); 4199 if (scanDetailCache != null) { 4200 mWifiMetrics.setConnectionScanDetail(scanDetailCache.getScanDetail( 4201 someBssid)); 4202 } 4203 // Update last associated BSSID 4204 mLastBssid = someBssid; 4205 } 4206 handleStatus = NOT_HANDLED; 4207 break; 4208 case WifiMonitor.NETWORK_CONNECTION_EVENT: 4209 if (mVerboseLoggingEnabled) log("Network connection established"); 4210 mLastNetworkId = message.arg1; 4211 mSentHLPs = message.arg2 == 1; 4212 if (mSentHLPs) mWifiMetrics.incrementL2ConnectionThroughFilsAuthCount(); 4213 mWifiConfigManager.clearRecentFailureReason(mLastNetworkId); 4214 mLastBssid = (String) message.obj; 4215 reasonCode = message.arg2; 4216 // TODO: This check should not be needed after ClientModeImpl refactor. 4217 // Currently, the last connected network configuration is left in 4218 // wpa_supplicant, this may result in wpa_supplicant initiating connection 4219 // to it after a config store reload. Hence the old network Id lookups may not 4220 // work, so disconnect the network and let network selector reselect a new 4221 // network. 4222 config = getCurrentWifiConfiguration(); 4223 if (config != null) { 4224 mWifiInfo.setBSSID(mLastBssid); 4225 mWifiInfo.setNetworkId(mLastNetworkId); 4226 mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); 4227 4228 ScanDetailCache scanDetailCache = 4229 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); 4230 if (scanDetailCache != null && mLastBssid != null) { 4231 ScanResult scanResult = scanDetailCache.getScanResult(mLastBssid); 4232 if (scanResult != null) { 4233 mWifiInfo.setFrequency(scanResult.frequency); 4234 } 4235 } 4236 4237 // We need to get the updated pseudonym from supplicant for EAP-SIM/AKA/AKA' 4238 if (config.enterpriseConfig != null 4239 && config.enterpriseConfig.isAuthenticationSimBased()) { 4240 mLastSubId = mWifiCarrierInfoManager.getBestMatchSubscriptionId(config); 4241 mLastSimBasedConnectionCarrierName = 4242 mWifiCarrierInfoManager.getCarrierNameforSubId(mLastSubId); 4243 String anonymousIdentity = 4244 mWifiNative.getEapAnonymousIdentity(mInterfaceName); 4245 if (!TextUtils.isEmpty(anonymousIdentity) 4246 && !WifiCarrierInfoManager 4247 .isAnonymousAtRealmIdentity(anonymousIdentity)) { 4248 String decoratedPseudonym = mWifiCarrierInfoManager 4249 .decoratePseudonymWith3GppRealm(config, 4250 anonymousIdentity); 4251 if (decoratedPseudonym != null) { 4252 anonymousIdentity = decoratedPseudonym; 4253 } 4254 if (mVerboseLoggingEnabled) { 4255 log("EAP Pseudonym: " + anonymousIdentity); 4256 } 4257 // Save the pseudonym only if it is a real one 4258 config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity); 4259 } else { 4260 // Clear any stored pseudonyms 4261 config.enterpriseConfig.setAnonymousIdentity(null); 4262 } 4263 mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID); 4264 } 4265 transitionTo(mObtainingIpState); 4266 } else { 4267 logw("Connected to unknown networkId " + mLastNetworkId 4268 + ", disconnecting..."); 4269 sendMessage(CMD_DISCONNECT); 4270 } 4271 break; 4272 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 4273 // Calling handleNetworkDisconnect here is redundant because we might already 4274 // have called it when leaving L2ConnectedState to go to disconnecting state 4275 // or thru other path 4276 // We should normally check the mWifiInfo or mLastNetworkId so as to check 4277 // if they are valid, and only in this case call handleNEtworkDisconnect, 4278 // TODO: this should be fixed for a L MR release 4279 // The side effect of calling handleNetworkDisconnect twice is that a bunch of 4280 // idempotent commands are executed twice (stopping Dhcp, enabling the SPS mode 4281 // at the chip etc... 4282 if (mVerboseLoggingEnabled) log("ConnectModeState: Network connection lost "); 4283 clearNetworkCachedDataIfNeeded(getTargetWifiConfiguration(), message.arg2); 4284 handleNetworkDisconnect(); 4285 transitionTo(mDisconnectedState); 4286 break; 4287 case CMD_QUERY_OSU_ICON: 4288 mPasspointManager.queryPasspointIcon( 4289 ((Bundle) message.obj).getLong(EXTRA_OSU_ICON_QUERY_BSSID), 4290 ((Bundle) message.obj).getString(EXTRA_OSU_ICON_QUERY_FILENAME)); 4291 break; 4292 case WifiMonitor.TARGET_BSSID_EVENT: 4293 // Trying to associate to this BSSID 4294 if (message.obj != null) { 4295 mTargetBssid = (String) message.obj; 4296 } 4297 break; 4298 case CMD_GET_LINK_LAYER_STATS: 4299 WifiLinkLayerStats stats = getWifiLinkLayerStats(); 4300 replyToMessage(message, message.what, stats); 4301 break; 4302 case CMD_RESET_SIM_NETWORKS: 4303 log("resetting EAP-SIM/AKA/AKA' networks since SIM was changed"); 4304 int resetReason = message.arg1; 4305 if (resetReason == RESET_SIM_REASON_SIM_INSERTED) { 4306 // whenever a SIM is inserted clear all SIM related notifications 4307 mSimRequiredNotifier.dismissSimRequiredNotification(); 4308 } else { 4309 mWifiConfigManager.resetSimNetworks(); 4310 } 4311 if (resetReason != RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED) { 4312 mWifiNetworkSuggestionsManager.resetCarrierPrivilegedApps(); 4313 } 4314 break; 4315 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 4316 // If BT was connected and then turned off, there is no CONNECTION_STATE_CHANGE 4317 // message. So we need to rely on STATE_CHANGE message to detect on->off 4318 // transition and update mBluetoothConnectionActive status correctly. 4319 mBluetoothConnectionActive = mBluetoothConnectionActive 4320 && message.arg1 != BluetoothAdapter.STATE_OFF; 4321 mWifiNative.setBluetoothCoexistenceScanMode( 4322 mInterfaceName, mBluetoothConnectionActive); 4323 mWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive); 4324 break; 4325 case CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE: 4326 // Transition to a non-disconnected state does correctly 4327 // indicate BT is connected or being connected. 4328 mBluetoothConnectionActive = 4329 message.arg1 != BluetoothAdapter.STATE_DISCONNECTED; 4330 mWifiNative.setBluetoothCoexistenceScanMode( 4331 mInterfaceName, mBluetoothConnectionActive); 4332 mWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive); 4333 break; 4334 case CMD_SET_SUSPEND_OPT_ENABLED: 4335 if (message.arg1 == 1) { 4336 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); 4337 if (message.arg2 == 1) { 4338 mSuspendWakeLock.release(); 4339 } 4340 } else { 4341 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); 4342 } 4343 break; 4344 case CMD_SET_HIGH_PERF_MODE: 4345 if (message.arg1 == 1) { 4346 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); 4347 } else { 4348 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); 4349 } 4350 break; 4351 case CMD_ENABLE_TDLS: 4352 if (message.obj != null) { 4353 String remoteAddress = (String) message.obj; 4354 boolean enable = (message.arg1 == 1); 4355 mWifiNative.startTdls(mInterfaceName, remoteAddress, enable); 4356 } 4357 break; 4358 case WifiMonitor.ANQP_DONE_EVENT: 4359 // TODO(zqiu): remove this when switch over to wificond for ANQP requests. 4360 mPasspointManager.notifyANQPDone((AnqpEvent) message.obj); 4361 break; 4362 case CMD_STOP_IP_PACKET_OFFLOAD: { 4363 int slot = message.arg1; 4364 int ret = stopWifiIPPacketOffload(slot); 4365 if (mNetworkAgent != null) { 4366 mNetworkAgent.sendSocketKeepaliveEvent(slot, ret); 4367 } 4368 break; 4369 } 4370 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 4371 // TODO(zqiu): remove this when switch over to wificond for icon requests. 4372 mPasspointManager.notifyIconDone((IconEvent) message.obj); 4373 break; 4374 case WifiMonitor.HS20_REMEDIATION_EVENT: 4375 // TODO(zqiu): remove this when switch over to wificond for WNM frames 4376 // monitoring. 4377 mPasspointManager.receivedWnmFrame((WnmData) message.obj); 4378 break; 4379 case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE: 4380 handleBssTransitionRequest((BtmFrameData) message.obj); 4381 break; 4382 case CMD_CONFIG_ND_OFFLOAD: 4383 final boolean enabled = (message.arg1 > 0); 4384 mWifiNative.configureNeighborDiscoveryOffload(mInterfaceName, enabled); 4385 break; 4386 case CMD_PRE_DHCP_ACTION: 4387 case CMD_PRE_DHCP_ACTION_COMPLETE: 4388 case CMD_POST_DHCP_ACTION: 4389 case CMD_IPV4_PROVISIONING_SUCCESS: 4390 case CMD_IP_CONFIGURATION_SUCCESSFUL: 4391 case CMD_IPV4_PROVISIONING_FAILURE: 4392 handleStatus = handleL3MessagesWhenNotConnected(message); 4393 break; 4394 default: 4395 handleStatus = NOT_HANDLED; 4396 break; 4397 } 4398 4399 if (handleStatus == HANDLED) { 4400 logStateAndMessage(message, this); 4401 } 4402 4403 return handleStatus; 4404 } 4405 } 4406 handleL3MessagesWhenNotConnected(Message message)4407 private boolean handleL3MessagesWhenNotConnected(Message message) { 4408 boolean handleStatus = HANDLED; 4409 4410 if (!mIpClientWithPreConnection) { 4411 return NOT_HANDLED; 4412 } 4413 4414 switch (message.what) { 4415 case CMD_PRE_DHCP_ACTION: 4416 handlePreDhcpSetup(); 4417 break; 4418 case CMD_PRE_DHCP_ACTION_COMPLETE: 4419 if (mIpClient != null) { 4420 mIpClient.completedPreDhcpAction(); 4421 } 4422 break; 4423 case CMD_IPV4_PROVISIONING_FAILURE: 4424 stopDhcpSetup(); 4425 deferMessage(message); 4426 break; 4427 case CMD_POST_DHCP_ACTION: 4428 case CMD_IPV4_PROVISIONING_SUCCESS: 4429 case CMD_IP_CONFIGURATION_SUCCESSFUL: 4430 deferMessage(message); 4431 break; 4432 default: 4433 return NOT_HANDLED; 4434 } 4435 4436 return handleStatus; 4437 } 4438 createNetworkAgentSpecifier( @onNull WifiConfiguration currentWifiConfiguration, @Nullable String currentBssid)4439 private WifiNetworkAgentSpecifier createNetworkAgentSpecifier( 4440 @NonNull WifiConfiguration currentWifiConfiguration, @Nullable String currentBssid) { 4441 currentWifiConfiguration.BSSID = currentBssid; 4442 WifiNetworkAgentSpecifier wns = 4443 new WifiNetworkAgentSpecifier(currentWifiConfiguration); 4444 return wns; 4445 } 4446 getCapabilities(WifiConfiguration currentWifiConfiguration)4447 private NetworkCapabilities getCapabilities(WifiConfiguration currentWifiConfiguration) { 4448 final NetworkCapabilities.Builder builder = 4449 new NetworkCapabilities.Builder(mNetworkCapabilitiesFilter); 4450 // MatchAllNetworkSpecifier set in the mNetworkCapabilitiesFilter should never be set in the 4451 // agent's specifier. 4452 builder.setNetworkSpecifier(null); 4453 if (currentWifiConfiguration == null) { 4454 return builder.build(); 4455 } 4456 4457 if (mWifiInfo.isTrusted()) { 4458 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED); 4459 } else { 4460 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED); 4461 } 4462 4463 builder.setOwnerUid(currentWifiConfiguration.creatorUid); 4464 builder.setAdministratorUids(new int[] {currentWifiConfiguration.creatorUid}); 4465 4466 if (!WifiConfiguration.isMetered(currentWifiConfiguration, mWifiInfo)) { 4467 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 4468 } else { 4469 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 4470 } 4471 4472 if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI) { 4473 builder.setSignalStrength(mWifiInfo.getRssi()); 4474 } else { 4475 builder.setSignalStrength(NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED); 4476 } 4477 4478 if (currentWifiConfiguration.osu) { 4479 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 4480 } 4481 4482 if (!mWifiInfo.getSSID().equals(WifiManager.UNKNOWN_SSID)) { 4483 builder.setSsid(mWifiInfo.getSSID()); 4484 } 4485 Pair<Integer, String> specificRequestUidAndPackageName = 4486 mNetworkFactory.getSpecificNetworkRequestUidAndPackageName( 4487 currentWifiConfiguration); 4488 // There is an active specific request. 4489 if (specificRequestUidAndPackageName.first != Process.INVALID_UID) { 4490 // Remove internet capability. 4491 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 4492 // Fill up the uid/packageName for this connection. 4493 builder.setRequestorUid(specificRequestUidAndPackageName.first); 4494 builder.setRequestorPackageName(specificRequestUidAndPackageName.second); 4495 // Fill up the network agent specifier for this connection. 4496 builder.setNetworkSpecifier(createNetworkAgentSpecifier( 4497 currentWifiConfiguration, getCurrentBSSID())); 4498 } 4499 updateLinkBandwidth(builder); 4500 return builder.build(); 4501 } 4502 updateLinkBandwidth(NetworkCapabilities.Builder networkCapabilitiesBuilder)4503 private void updateLinkBandwidth(NetworkCapabilities.Builder networkCapabilitiesBuilder) { 4504 int rssiDbm = mWifiInfo.getRssi(); 4505 int txTputKbps = INVALID_THROUGHPUT; 4506 int rxTputKbps = INVALID_THROUGHPUT; 4507 // If RSSI is available, check if throughput is available 4508 if (rssiDbm != WifiInfo.INVALID_RSSI && mWifiDataStall != null) { 4509 txTputKbps = mWifiDataStall.getTxThroughputKbps(); 4510 rxTputKbps = mWifiDataStall.getRxThroughputKbps(); 4511 } 4512 if (txTputKbps == INVALID_THROUGHPUT && rxTputKbps != INVALID_THROUGHPUT) { 4513 txTputKbps = rxTputKbps; 4514 } else if (rxTputKbps == INVALID_THROUGHPUT && txTputKbps != INVALID_THROUGHPUT) { 4515 rxTputKbps = txTputKbps; 4516 } else if (txTputKbps == INVALID_THROUGHPUT && rxTputKbps == INVALID_THROUGHPUT) { 4517 int maxTxLinkSpeedMbps = mWifiInfo.getMaxSupportedTxLinkSpeedMbps(); 4518 int maxRxLinkSpeedMbps = mWifiInfo.getMaxSupportedRxLinkSpeedMbps(); 4519 if (maxTxLinkSpeedMbps > 0) { 4520 txTputKbps = maxTxLinkSpeedMbps * 1000; 4521 } 4522 if (maxRxLinkSpeedMbps > 0) { 4523 rxTputKbps = maxRxLinkSpeedMbps * 1000; 4524 } 4525 } 4526 if (mVerboseLoggingEnabled) { 4527 logd("tx tput in kbps: " + txTputKbps); 4528 logd("rx tput in kbps: " + rxTputKbps); 4529 } 4530 if (txTputKbps > 0) { 4531 networkCapabilitiesBuilder.setLinkUpstreamBandwidthKbps(txTputKbps); 4532 } 4533 if (rxTputKbps > 0) { 4534 networkCapabilitiesBuilder.setLinkDownstreamBandwidthKbps(rxTputKbps); 4535 } 4536 } 4537 4538 /** 4539 * Method to update network capabilities from the current WifiConfiguration. 4540 */ updateCapabilities()4541 public void updateCapabilities() { 4542 updateCapabilities(getCurrentWifiConfiguration()); 4543 } 4544 updateCapabilities(WifiConfiguration currentWifiConfiguration)4545 private void updateCapabilities(WifiConfiguration currentWifiConfiguration) { 4546 updateCapabilities(getCapabilities(currentWifiConfiguration)); 4547 } 4548 updateCapabilities(NetworkCapabilities networkCapabilities)4549 private void updateCapabilities(NetworkCapabilities networkCapabilities) { 4550 if (mNetworkAgent == null) { 4551 return; 4552 } 4553 mNetworkAgent.sendNetworkCapabilities(networkCapabilities); 4554 } 4555 handleEapAuthFailure(int networkId, int errorCode)4556 private void handleEapAuthFailure(int networkId, int errorCode) { 4557 WifiConfiguration targetedNetwork = 4558 mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 4559 if (targetedNetwork != null) { 4560 switch (targetedNetwork.enterpriseConfig.getEapMethod()) { 4561 case WifiEnterpriseConfig.Eap.SIM: 4562 case WifiEnterpriseConfig.Eap.AKA: 4563 case WifiEnterpriseConfig.Eap.AKA_PRIME: 4564 if (errorCode == WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED) { 4565 mWifiCarrierInfoManager.resetCarrierKeysForImsiEncryption(targetedNetwork); 4566 } 4567 break; 4568 4569 default: 4570 // Do Nothing 4571 } 4572 } 4573 } 4574 4575 private class WifiNetworkAgent extends NetworkAgent { WifiNetworkAgent(Context c, Looper l, String tag, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, NetworkProvider provider)4576 WifiNetworkAgent(Context c, Looper l, String tag, NetworkCapabilities nc, LinkProperties lp, 4577 int score, NetworkAgentConfig config, NetworkProvider provider) { 4578 super(c, l, tag, nc, lp, score, config, provider); 4579 register(); 4580 } 4581 private int mLastNetworkStatus = -1; // To detect when the status really changes 4582 4583 @Override onNetworkUnwanted()4584 public void onNetworkUnwanted() { 4585 // Ignore if we're not the current networkAgent. 4586 if (this != mNetworkAgent) return; 4587 if (mVerboseLoggingEnabled) { 4588 logd("WifiNetworkAgent -> Wifi unwanted score " + Integer.toString( 4589 mWifiInfo.getScore())); 4590 } 4591 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT); 4592 } 4593 4594 @Override onValidationStatus(int status, @Nullable Uri redirectUri)4595 public void onValidationStatus(int status, @Nullable Uri redirectUri) { 4596 if (this != mNetworkAgent) return; 4597 if (status == mLastNetworkStatus) return; 4598 mLastNetworkStatus = status; 4599 if (status == NetworkAgent.VALIDATION_STATUS_NOT_VALID) { 4600 if (mVerboseLoggingEnabled) { 4601 logd("WifiNetworkAgent -> Wifi networkStatus invalid, score=" 4602 + Integer.toString(mWifiInfo.getScore())); 4603 } 4604 unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED); 4605 } else if (status == NetworkAgent.VALIDATION_STATUS_VALID) { 4606 if (mVerboseLoggingEnabled) { 4607 logd("WifiNetworkAgent -> Wifi networkStatus valid, score= " 4608 + Integer.toString(mWifiInfo.getScore())); 4609 } 4610 mWifiMetrics.logStaEvent(StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK); 4611 doNetworkStatus(status); 4612 } 4613 } 4614 4615 @Override onSaveAcceptUnvalidated(boolean accept)4616 public void onSaveAcceptUnvalidated(boolean accept) { 4617 if (this != mNetworkAgent) return; 4618 ClientModeImpl.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0); 4619 } 4620 4621 @Override onStartSocketKeepalive(int slot, @NonNull Duration interval, @NonNull KeepalivePacketData packet)4622 public void onStartSocketKeepalive(int slot, @NonNull Duration interval, 4623 @NonNull KeepalivePacketData packet) { 4624 if (this != mNetworkAgent) return; 4625 ClientModeImpl.this.sendMessage( 4626 CMD_START_IP_PACKET_OFFLOAD, slot, (int) interval.getSeconds(), packet); 4627 } 4628 4629 @Override onStopSocketKeepalive(int slot)4630 public void onStopSocketKeepalive(int slot) { 4631 if (this != mNetworkAgent) return; 4632 ClientModeImpl.this.sendMessage(CMD_STOP_IP_PACKET_OFFLOAD, slot); 4633 } 4634 4635 @Override onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet)4636 public void onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet) { 4637 if (this != mNetworkAgent) return; 4638 ClientModeImpl.this.sendMessage( 4639 CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0, packet); 4640 } 4641 4642 @Override onRemoveKeepalivePacketFilter(int slot)4643 public void onRemoveKeepalivePacketFilter(int slot) { 4644 if (this != mNetworkAgent) return; 4645 ClientModeImpl.this.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF, slot); 4646 } 4647 4648 @Override onSignalStrengthThresholdsUpdated(@onNull int[] thresholds)4649 public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { 4650 if (this != mNetworkAgent) return; 4651 // 0. If there are no thresholds, or if the thresholds are invalid, 4652 // stop RSSI monitoring. 4653 // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and 4654 // MAX_VALUE at the start/end of the thresholds array if necessary. 4655 // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware 4656 // event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then 4657 // re-arm the hardware event. This needs to be done on the state machine thread to 4658 // avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one 4659 // sent in the NetworkCapabilities) must be the one received from the hardware event 4660 // received, or we might skip callbacks. 4661 // 3. Ensure that when we disconnect, RSSI monitoring is stopped. 4662 logd("Received signal strength thresholds: " + Arrays.toString(thresholds)); 4663 if (thresholds.length == 0) { 4664 ClientModeImpl.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 4665 mWifiInfo.getRssi()); 4666 return; 4667 } 4668 int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2); 4669 rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE; 4670 rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE; 4671 Arrays.sort(rssiVals); 4672 byte[] rssiRange = new byte[rssiVals.length]; 4673 for (int i = 0; i < rssiVals.length; i++) { 4674 int val = rssiVals[i]; 4675 if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) { 4676 rssiRange[i] = (byte) val; 4677 } else { 4678 Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: " 4679 + Arrays.toString(rssiVals)); 4680 ClientModeImpl.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 4681 mWifiInfo.getRssi()); 4682 return; 4683 } 4684 } 4685 // TODO: Do we quash rssi values in this sorted array which are very close? 4686 mRssiRanges = rssiRange; 4687 ClientModeImpl.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD, 4688 mWifiInfo.getRssi()); 4689 } 4690 4691 @Override onAutomaticReconnectDisabled()4692 public void onAutomaticReconnectDisabled() { 4693 if (this != mNetworkAgent) return; 4694 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN); 4695 } 4696 } 4697 unwantedNetwork(int reason)4698 void unwantedNetwork(int reason) { 4699 sendMessage(CMD_UNWANTED_NETWORK, reason); 4700 } 4701 doNetworkStatus(int status)4702 void doNetworkStatus(int status) { 4703 sendMessage(CMD_NETWORK_STATUS, status); 4704 } 4705 4706 class L2ConnectedState extends State { 4707 class RssiEventHandler implements WifiNative.WifiRssiEventHandler { 4708 @Override onRssiThresholdBreached(byte curRssi)4709 public void onRssiThresholdBreached(byte curRssi) { 4710 if (mVerboseLoggingEnabled) { 4711 Log.e(TAG, "onRssiThresholdBreach event. Cur Rssi = " + curRssi); 4712 } 4713 sendMessage(CMD_RSSI_THRESHOLD_BREACHED, curRssi); 4714 } 4715 } 4716 4717 RssiEventHandler mRssiEventHandler = new RssiEventHandler(); 4718 4719 @Override enter()4720 public void enter() { 4721 mRssiPollToken++; 4722 if (mEnableRssiPolling) { 4723 mLinkProbeManager.resetOnNewConnection(); 4724 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0); 4725 } 4726 sendNetworkChangeBroadcast(DetailedState.CONNECTING); 4727 4728 // If this network was explicitly selected by the user, evaluate whether to inform 4729 // ConnectivityService of that fact so the system can treat it appropriately. 4730 final WifiConfiguration config = getCurrentWifiConfiguration(); 4731 4732 boolean explicitlySelected = false; 4733 if (shouldEvaluateWhetherToSendExplicitlySelected(config)) { 4734 // If explicitlySelected is true, the network was selected by the user via Settings 4735 // or QuickSettings. If this network has Internet access, switch to it. Otherwise, 4736 // switch to it only if the user confirms that they really want to switch, or has 4737 // already confirmed and selected "Don't ask again". 4738 explicitlySelected = 4739 mWifiPermissionsUtil.checkNetworkSettingsPermission(config.lastConnectUid); 4740 if (mVerboseLoggingEnabled) { 4741 log("Network selected by UID " + config.lastConnectUid + " explicitlySelected=" 4742 + explicitlySelected); 4743 } 4744 } 4745 4746 if (mVerboseLoggingEnabled) { 4747 log("explicitlySelected=" + explicitlySelected + " acceptUnvalidated=" 4748 + config.noInternetAccessExpected); 4749 } 4750 4751 final NetworkAgentConfig naConfig = new NetworkAgentConfig.Builder() 4752 .setLegacyType(ConnectivityManager.TYPE_WIFI) 4753 .setLegacyTypeName(NETWORKTYPE) 4754 .setExplicitlySelected(explicitlySelected) 4755 .setUnvalidatedConnectivityAcceptable( 4756 explicitlySelected && config.noInternetAccessExpected) 4757 .setPartialConnectivityAcceptable(config.noInternetAccessExpected) 4758 .build(); 4759 final NetworkCapabilities nc = getCapabilities(getCurrentWifiConfiguration()); 4760 // This should never happen. 4761 if (mNetworkAgent != null) { 4762 Log.wtf(TAG, "mNetworkAgent is not null: " + mNetworkAgent); 4763 mNetworkAgent.unregister(); 4764 } 4765 mNetworkAgent = new WifiNetworkAgent(mContext, getHandler().getLooper(), 4766 "WifiNetworkAgent", nc, mLinkProperties, 60, naConfig, 4767 mNetworkFactory.getProvider()); 4768 mWifiScoreReport.setNetworkAgent(mNetworkAgent); 4769 4770 // We must clear the config BSSID, as the wifi chipset may decide to roam 4771 // from this point on and having the BSSID specified in the network block would 4772 // cause the roam to faile and the device to disconnect 4773 clearTargetBssid("L2ConnectedState"); 4774 mCountryCode.setReadyForChange(false); 4775 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); 4776 mWifiScoreCard.noteNetworkAgentCreated(mWifiInfo, 4777 mNetworkAgent.getNetwork().getNetId()); 4778 mBssidBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid, mWifiInfo.getSSID()); 4779 } 4780 4781 @Override exit()4782 public void exit() { 4783 // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState 4784 // Bug: 15347363 4785 // For paranoia's sake, call handleNetworkDisconnect 4786 // only if BSSID is null or last networkId 4787 // is not invalid. 4788 if (mVerboseLoggingEnabled) { 4789 StringBuilder sb = new StringBuilder(); 4790 sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId)); 4791 if (mLastBssid != null) { 4792 sb.append(" ").append(mLastBssid); 4793 } 4794 } 4795 mCountryCode.setReadyForChange(true); 4796 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 4797 mWifiStateTracker.updateState(WifiStateTracker.DISCONNECTED); 4798 //Inform WifiLockManager 4799 WifiLockManager wifiLockManager = mWifiInjector.getWifiLockManager(); 4800 wifiLockManager.updateWifiClientConnected(false); 4801 } 4802 4803 @Override processMessage(Message message)4804 public boolean processMessage(Message message) { 4805 boolean handleStatus = HANDLED; 4806 int callbackIdentifier = -1; 4807 4808 switch (message.what) { 4809 case CMD_PRE_DHCP_ACTION: 4810 handlePreDhcpSetup(); 4811 break; 4812 case CMD_PRE_DHCP_ACTION_COMPLETE: 4813 if (mIpClient != null) { 4814 mIpClient.completedPreDhcpAction(); 4815 } 4816 break; 4817 case CMD_POST_DHCP_ACTION: 4818 handlePostDhcpSetup(); 4819 // We advance to mConnectedState because IpClient will also send a 4820 // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(), 4821 // which calls updateLinkProperties, which then sends 4822 // CMD_IP_CONFIGURATION_SUCCESSFUL. 4823 // 4824 // In the event of failure, we transition to mDisconnectingState 4825 // similarly--via messages sent back from IpClient. 4826 break; 4827 case CMD_IPV4_PROVISIONING_SUCCESS: { 4828 handleIPv4Success((DhcpResultsParcelable) message.obj); 4829 break; 4830 } 4831 case CMD_IPV4_PROVISIONING_FAILURE: { 4832 handleIPv4Failure(); 4833 mWifiInjector.getWifiLastResortWatchdog() 4834 .noteConnectionFailureAndTriggerIfNeeded( 4835 getTargetSsid(), 4836 (mLastBssid == null) ? mTargetBssid : mLastBssid, 4837 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 4838 break; 4839 } 4840 case CMD_IP_CONFIGURATION_SUCCESSFUL: 4841 if (getCurrentWifiConfiguration() == null) { 4842 // The current config may have been removed while we were connecting, 4843 // trigger a disconnect to clear up state. 4844 reportConnectionAttemptEnd( 4845 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 4846 WifiMetricsProto.ConnectionEvent.HLF_NONE, 4847 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 4848 mWifiNative.disconnect(mInterfaceName); 4849 transitionTo(mDisconnectingState); 4850 } else { 4851 handleSuccessfulIpConfiguration(); 4852 sendConnectedState(); 4853 transitionTo(mConnectedState); 4854 } 4855 break; 4856 case CMD_IP_CONFIGURATION_LOST: 4857 // Get Link layer stats so that we get fresh tx packet counters. 4858 getWifiLinkLayerStats(); 4859 handleIpConfigurationLost(); 4860 reportConnectionAttemptEnd( 4861 WifiMetrics.ConnectionEvent.FAILURE_DHCP, 4862 WifiMetricsProto.ConnectionEvent.HLF_NONE, 4863 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 4864 mWifiInjector.getWifiLastResortWatchdog() 4865 .noteConnectionFailureAndTriggerIfNeeded( 4866 getTargetSsid(), 4867 (mLastBssid == null) ? mTargetBssid : mLastBssid, 4868 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 4869 transitionTo(mDisconnectingState); 4870 break; 4871 case CMD_IP_REACHABILITY_LOST: 4872 if (mVerboseLoggingEnabled && message.obj != null) log((String) message.obj); 4873 mWifiDiagnostics.captureBugReportData( 4874 WifiDiagnostics.REPORT_REASON_REACHABILITY_LOST); 4875 mWifiMetrics.logWifiIsUnusableEvent( 4876 WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST); 4877 mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, 4878 WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1); 4879 if (mIpReachabilityDisconnectEnabled) { 4880 handleIpReachabilityLost(); 4881 transitionTo(mDisconnectingState); 4882 } else { 4883 logd("CMD_IP_REACHABILITY_LOST but disconnect disabled -- ignore"); 4884 } 4885 break; 4886 case CMD_DISCONNECT: 4887 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 4888 StaEvent.DISCONNECT_GENERIC); 4889 mWifiNative.disconnect(mInterfaceName); 4890 transitionTo(mDisconnectingState); 4891 break; 4892 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 4893 if (message.arg1 == 1) { 4894 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 4895 StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); 4896 mWifiNative.disconnect(mInterfaceName); 4897 mTemporarilyDisconnectWifi = true; 4898 transitionTo(mDisconnectingState); 4899 } 4900 break; 4901 case WifiMonitor.NETWORK_CONNECTION_EVENT: 4902 mWifiInfo.setBSSID((String) message.obj); 4903 mLastNetworkId = message.arg1; 4904 mWifiInfo.setNetworkId(mLastNetworkId); 4905 mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); 4906 mLastBssid = (String) message.obj; 4907 break; 4908 case CMD_ONESHOT_RSSI_POLL: 4909 if (!mEnableRssiPolling) { 4910 updateLinkLayerStatsRssiAndScoreReportInternal(); 4911 } 4912 break; 4913 case CMD_RSSI_POLL: 4914 if (message.arg1 == mRssiPollToken) { 4915 WifiLinkLayerStats stats = updateLinkLayerStatsRssiAndScoreReportInternal(); 4916 mWifiMetrics.updateWifiUsabilityStatsEntries(mWifiInfo, stats); 4917 if (mWifiScoreReport.shouldCheckIpLayer()) { 4918 if (mIpClient != null) { 4919 mIpClient.confirmConfiguration(); 4920 } 4921 mWifiScoreReport.noteIpCheck(); 4922 } 4923 int statusDataStall = mWifiDataStall.checkDataStallAndThroughputSufficiency( 4924 mLastLinkLayerStats, stats, mWifiInfo); 4925 if (mDataStallTriggerTimeMs == -1 4926 && statusDataStall != WifiIsUnusableEvent.TYPE_UNKNOWN) { 4927 mDataStallTriggerTimeMs = mClock.getElapsedSinceBootMillis(); 4928 mLastStatusDataStall = statusDataStall; 4929 } 4930 if (mDataStallTriggerTimeMs != -1) { 4931 long elapsedTime = mClock.getElapsedSinceBootMillis() 4932 - mDataStallTriggerTimeMs; 4933 if (elapsedTime >= DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS) { 4934 mDataStallTriggerTimeMs = -1; 4935 mWifiMetrics.addToWifiUsabilityStatsList( 4936 WifiUsabilityStats.LABEL_BAD, 4937 convertToUsabilityStatsTriggerType(mLastStatusDataStall), 4938 -1); 4939 mLastStatusDataStall = WifiIsUnusableEvent.TYPE_UNKNOWN; 4940 } 4941 } 4942 mWifiMetrics.incrementWifiLinkLayerUsageStats(stats); 4943 mLastLinkLayerStats = stats; 4944 mWifiScoreCard.noteSignalPoll(mWifiInfo); 4945 mLinkProbeManager.updateConnectionStats( 4946 mWifiInfo, mInterfaceName); 4947 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0), 4948 getPollRssiIntervalMsecs()); 4949 if (mVerboseLoggingEnabled) sendRssiChangeBroadcast(mWifiInfo.getRssi()); 4950 mWifiTrafficPoller.notifyOnDataActivity(mWifiInfo.txSuccess, 4951 mWifiInfo.rxSuccess); 4952 } else { 4953 // Polling has completed 4954 } 4955 break; 4956 case CMD_ENABLE_RSSI_POLL: 4957 cleanWifiScore(); 4958 mEnableRssiPolling = (message.arg1 == 1); 4959 mRssiPollToken++; 4960 if (mEnableRssiPolling) { 4961 // First poll 4962 mLastSignalLevel = -1; 4963 mLinkProbeManager.resetOnScreenTurnedOn(); 4964 fetchRssiLinkSpeedAndFrequencyNative(); 4965 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0), 4966 getPollRssiIntervalMsecs()); 4967 } 4968 break; 4969 case WifiMonitor.ASSOCIATED_BSSID_EVENT: 4970 if ((String) message.obj == null) { 4971 logw("Associated command w/o BSSID"); 4972 break; 4973 } 4974 mLastBssid = (String) message.obj; 4975 if (mLastBssid != null && (mWifiInfo.getBSSID() == null 4976 || !mLastBssid.equals(mWifiInfo.getBSSID()))) { 4977 mWifiInfo.setBSSID(mLastBssid); 4978 WifiConfiguration config = getCurrentWifiConfiguration(); 4979 if (config != null) { 4980 ScanDetailCache scanDetailCache = mWifiConfigManager 4981 .getScanDetailCacheForNetwork(config.networkId); 4982 if (scanDetailCache != null) { 4983 ScanResult scanResult = scanDetailCache.getScanResult(mLastBssid); 4984 if (scanResult != null) { 4985 mWifiInfo.setFrequency(scanResult.frequency); 4986 } 4987 } 4988 } 4989 } 4990 break; 4991 case CMD_START_RSSI_MONITORING_OFFLOAD: 4992 case CMD_RSSI_THRESHOLD_BREACHED: 4993 byte currRssi = (byte) message.arg1; 4994 processRssiThreshold(currRssi, message.what, mRssiEventHandler); 4995 break; 4996 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 4997 stopRssiMonitoringOffload(); 4998 break; 4999 case CMD_RECONNECT: 5000 log(" Ignore CMD_RECONNECT request because wifi is already connected"); 5001 break; 5002 case CMD_RESET_SIM_NETWORKS: 5003 if (message.arg1 != RESET_SIM_REASON_SIM_INSERTED 5004 && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 5005 WifiConfiguration config = 5006 mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); 5007 if (config != null 5008 && ((message.arg1 == RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED 5009 && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) 5010 || (config.enterpriseConfig != null 5011 && config.enterpriseConfig.isAuthenticationSimBased() 5012 && !mWifiCarrierInfoManager.isSimPresent(mLastSubId)))) { 5013 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 5014 StaEvent.DISCONNECT_RESET_SIM_NETWORKS); 5015 // remove local PMKSA cache in framework 5016 mWifiNative.removeNetworkCachedData(mLastNetworkId); 5017 // remove network so that supplicant's PMKSA cache is cleared 5018 mWifiNative.removeAllNetworks(mInterfaceName); 5019 mSimRequiredNotifier.showSimRequiredNotification( 5020 config, mLastSimBasedConnectionCarrierName); 5021 transitionTo(mDisconnectingState); 5022 } 5023 } 5024 /* allow parent state to reset data for other networks */ 5025 handleStatus = NOT_HANDLED; 5026 break; 5027 case CMD_START_IP_PACKET_OFFLOAD: { 5028 int slot = message.arg1; 5029 int intervalSeconds = message.arg2; 5030 KeepalivePacketData pkt = (KeepalivePacketData) message.obj; 5031 int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds); 5032 if (mNetworkAgent != null) { 5033 mNetworkAgent.sendSocketKeepaliveEvent(slot, result); 5034 } 5035 break; 5036 } 5037 case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: { 5038 if (mIpClient != null) { 5039 final int slot = message.arg1; 5040 if (message.obj instanceof NattKeepalivePacketData) { 5041 final NattKeepalivePacketData pkt = 5042 (NattKeepalivePacketData) message.obj; 5043 mIpClient.addKeepalivePacketFilter(slot, pkt); 5044 } else if (message.obj instanceof TcpKeepalivePacketData) { 5045 final TcpKeepalivePacketData pkt = 5046 (TcpKeepalivePacketData) message.obj; 5047 mIpClient.addKeepalivePacketFilter(slot, pkt); 5048 } 5049 } 5050 break; 5051 } 5052 case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF: { 5053 if (mIpClient != null) { 5054 mIpClient.removeKeepalivePacketFilter(message.arg1); 5055 } 5056 break; 5057 } 5058 default: 5059 handleStatus = NOT_HANDLED; 5060 break; 5061 } 5062 5063 if (handleStatus == HANDLED) { 5064 logStateAndMessage(message, this); 5065 } 5066 5067 return handleStatus; 5068 } 5069 5070 /** 5071 * Fetches link stats and updates Wifi Score Report. 5072 */ updateLinkLayerStatsRssiAndScoreReportInternal()5073 private WifiLinkLayerStats updateLinkLayerStatsRssiAndScoreReportInternal() { 5074 WifiLinkLayerStats stats = getWifiLinkLayerStats(); 5075 // Get Info and continue polling 5076 fetchRssiLinkSpeedAndFrequencyNative(); 5077 // Send the update score to network agent. 5078 mWifiScoreReport.calculateAndReportScore(); 5079 return stats; 5080 } 5081 } 5082 5083 /** 5084 * Fetches link stats and updates Wifi Score Report. 5085 */ updateLinkLayerStatsRssiAndScoreReport()5086 public void updateLinkLayerStatsRssiAndScoreReport() { 5087 sendMessage(CMD_ONESHOT_RSSI_POLL); 5088 } 5089 convertToUsabilityStatsTriggerType(int unusableEventTriggerType)5090 private static int convertToUsabilityStatsTriggerType(int unusableEventTriggerType) { 5091 int triggerType; 5092 switch (unusableEventTriggerType) { 5093 case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX: 5094 triggerType = WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX; 5095 break; 5096 case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX: 5097 triggerType = WifiUsabilityStats.TYPE_DATA_STALL_TX_WITHOUT_RX; 5098 break; 5099 case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH: 5100 triggerType = WifiUsabilityStats.TYPE_DATA_STALL_BOTH; 5101 break; 5102 case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT: 5103 triggerType = WifiUsabilityStats.TYPE_FIRMWARE_ALERT; 5104 break; 5105 case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST: 5106 triggerType = WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST; 5107 break; 5108 default: 5109 triggerType = WifiUsabilityStats.TYPE_UNKNOWN; 5110 Log.e(TAG, "Unknown WifiIsUnusableEvent: " + unusableEventTriggerType); 5111 } 5112 return triggerType; 5113 } 5114 5115 class ObtainingIpState extends State { 5116 @Override enter()5117 public void enter() { 5118 WifiConfiguration currentConfig = getCurrentWifiConfiguration(); 5119 if (mIpClientWithPreConnection && mIpClient != null) { 5120 mIpClient.notifyPreconnectionComplete(mSentHLPs); 5121 mIpClientWithPreConnection = false; 5122 mSentHLPs = false; 5123 } else { 5124 startIpClient(currentConfig, false); 5125 } 5126 // Get Link layer stats so as we get fresh tx packet counters 5127 getWifiLinkLayerStats(); 5128 } 5129 5130 @Override processMessage(Message message)5131 public boolean processMessage(Message message) { 5132 boolean handleStatus = HANDLED; 5133 5134 switch(message.what) { 5135 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5136 reportConnectionAttemptEnd( 5137 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 5138 WifiMetricsProto.ConnectionEvent.HLF_NONE, 5139 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 5140 mWifiInjector.getWifiLastResortWatchdog() 5141 .noteConnectionFailureAndTriggerIfNeeded( 5142 getTargetSsid(), 5143 (message.obj == null) 5144 ? mTargetBssid : (String) message.obj, 5145 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 5146 handleStatus = NOT_HANDLED; 5147 break; 5148 case CMD_SET_HIGH_PERF_MODE: 5149 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5150 deferMessage(message); 5151 break; 5152 default: 5153 handleStatus = NOT_HANDLED; 5154 break; 5155 } 5156 5157 if (handleStatus == HANDLED) { 5158 logStateAndMessage(message, this); 5159 } 5160 return handleStatus; 5161 } 5162 } 5163 5164 /** 5165 * Helper function to check if we need to invoke 5166 * {@link NetworkAgent#explicitlySelected(boolean, boolean)} to indicate that we connected to a 5167 * network which the user just chose 5168 * (i.e less than {@link #LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS) before). 5169 */ 5170 @VisibleForTesting shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration currentConfig)5171 public boolean shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration currentConfig) { 5172 if (currentConfig == null) { 5173 Log.wtf(TAG, "Current WifiConfiguration is null, but IP provisioning just succeeded"); 5174 return false; 5175 } 5176 long currentTimeMillis = mClock.getElapsedSinceBootMillis(); 5177 return (mWifiConfigManager.getLastSelectedNetwork() == currentConfig.networkId 5178 && currentTimeMillis - mWifiConfigManager.getLastSelectedTimeStamp() 5179 < LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS); 5180 } 5181 sendConnectedState()5182 private void sendConnectedState() { 5183 mNetworkAgent.markConnected(); 5184 sendNetworkChangeBroadcast(DetailedState.CONNECTED); 5185 } 5186 5187 class RoamingState extends State { 5188 boolean mAssociated; 5189 @Override enter()5190 public void enter() { 5191 if (mVerboseLoggingEnabled) { 5192 log("RoamingState Enter mScreenOn=" + mScreenOn); 5193 } 5194 5195 // Make sure we disconnect if roaming fails 5196 mRoamWatchdogCount++; 5197 logd("Start Roam Watchdog " + mRoamWatchdogCount); 5198 sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER, 5199 mRoamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); 5200 mAssociated = false; 5201 } 5202 @Override processMessage(Message message)5203 public boolean processMessage(Message message) { 5204 WifiConfiguration config; 5205 boolean handleStatus = HANDLED; 5206 5207 switch (message.what) { 5208 case CMD_IP_CONFIGURATION_LOST: 5209 config = getCurrentWifiConfiguration(); 5210 if (config != null) { 5211 mWifiDiagnostics.captureBugReportData( 5212 WifiDiagnostics.REPORT_REASON_AUTOROAM_FAILURE); 5213 } 5214 handleStatus = NOT_HANDLED; 5215 break; 5216 case CMD_UNWANTED_NETWORK: 5217 if (mVerboseLoggingEnabled) { 5218 log("Roaming and CS doesn't want the network -> ignore"); 5219 } 5220 break; 5221 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5222 /** 5223 * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT 5224 * before NETWORK_DISCONNECTION_EVENT 5225 * And there is an associated BSSID corresponding to our target BSSID, then 5226 * we have missed the network disconnection, transition to mDisconnectedState 5227 * and handle the rest of the events there. 5228 */ 5229 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 5230 if (stateChangeResult.state == SupplicantState.DISCONNECTED 5231 || stateChangeResult.state == SupplicantState.INACTIVE 5232 || stateChangeResult.state == SupplicantState.INTERFACE_DISABLED) { 5233 if (mVerboseLoggingEnabled) { 5234 log("STATE_CHANGE_EVENT in roaming state " 5235 + stateChangeResult.toString()); 5236 } 5237 if (stateChangeResult.BSSID != null 5238 && stateChangeResult.BSSID.equals(mTargetBssid)) { 5239 handleNetworkDisconnect(); 5240 transitionTo(mDisconnectedState); 5241 } 5242 } 5243 if (stateChangeResult.state == SupplicantState.ASSOCIATED) { 5244 // We completed the layer2 roaming part 5245 mAssociated = true; 5246 if (stateChangeResult.BSSID != null) { 5247 mTargetBssid = stateChangeResult.BSSID; 5248 } 5249 } 5250 break; 5251 case CMD_ROAM_WATCHDOG_TIMER: 5252 if (mRoamWatchdogCount == message.arg1) { 5253 if (mVerboseLoggingEnabled) log("roaming watchdog! -> disconnect"); 5254 mWifiMetrics.endConnectionEvent( 5255 WifiMetrics.ConnectionEvent.FAILURE_ROAM_TIMEOUT, 5256 WifiMetricsProto.ConnectionEvent.HLF_NONE, 5257 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 5258 mRoamFailCount++; 5259 handleNetworkDisconnect(); 5260 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 5261 StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER); 5262 mWifiNative.disconnect(mInterfaceName); 5263 transitionTo(mDisconnectedState); 5264 } 5265 break; 5266 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5267 if (mAssociated) { 5268 if (mVerboseLoggingEnabled) { 5269 log("roaming and Network connection established"); 5270 } 5271 mLastNetworkId = message.arg1; 5272 mLastBssid = (String) message.obj; 5273 mWifiInfo.setBSSID(mLastBssid); 5274 mWifiInfo.setNetworkId(mLastNetworkId); 5275 5276 // Successful framework roam! (probably) 5277 mBssidBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid, 5278 mWifiInfo.getSSID()); 5279 reportConnectionAttemptEnd( 5280 WifiMetrics.ConnectionEvent.FAILURE_NONE, 5281 WifiMetricsProto.ConnectionEvent.HLF_NONE, 5282 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 5283 5284 // We must clear the config BSSID, as the wifi chipset may decide to roam 5285 // from this point on and having the BSSID specified by QNS would cause 5286 // the roam to fail and the device to disconnect. 5287 // When transition from RoamingState to DisconnectingState or 5288 // DisconnectedState, the config BSSID is cleared by 5289 // handleNetworkDisconnect(). 5290 clearTargetBssid("RoamingCompleted"); 5291 5292 // We used to transition to ObtainingIpState in an 5293 // attempt to do DHCPv4 RENEWs on framework roams. 5294 // DHCP can take too long to time out, and we now rely 5295 // upon IpClient's use of IpReachabilityMonitor to 5296 // confirm our current network configuration. 5297 // 5298 // mIpClient.confirmConfiguration() is called within 5299 // the handling of SupplicantState.COMPLETED. 5300 transitionTo(mConnectedState); 5301 } else { 5302 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5303 } 5304 break; 5305 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5306 // Throw away but only if it corresponds to the network we're roaming to 5307 String bssid = (String) message.obj; 5308 if (true) { 5309 String target = ""; 5310 if (mTargetBssid != null) target = mTargetBssid; 5311 log("NETWORK_DISCONNECTION_EVENT in roaming state" 5312 + " BSSID=" + bssid 5313 + " target=" + target); 5314 } 5315 clearNetworkCachedDataIfNeeded(getTargetWifiConfiguration(), message.arg2); 5316 if (bssid != null && bssid.equals(mTargetBssid)) { 5317 handleNetworkDisconnect(); 5318 transitionTo(mDisconnectedState); 5319 } 5320 break; 5321 case CMD_GET_CURRENT_NETWORK: 5322 replyToMessage(message, message.what, getCurrentNetwork()); 5323 break; 5324 default: 5325 handleStatus = NOT_HANDLED; 5326 break; 5327 } 5328 5329 if (handleStatus == HANDLED) { 5330 logStateAndMessage(message, this); 5331 } 5332 return handleStatus; 5333 } 5334 5335 @Override exit()5336 public void exit() { 5337 logd("ClientModeImpl: Leaving Roaming state"); 5338 } 5339 } 5340 5341 class ConnectedState extends State { 5342 @Override enter()5343 public void enter() { 5344 if (mVerboseLoggingEnabled) { 5345 log("Enter ConnectedState mScreenOn=" + mScreenOn); 5346 } 5347 5348 reportConnectionAttemptEnd( 5349 WifiMetrics.ConnectionEvent.FAILURE_NONE, 5350 WifiMetricsProto.ConnectionEvent.HLF_NONE, 5351 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 5352 mWifiConnectivityManager.handleConnectionStateChanged( 5353 WifiConnectivityManager.WIFI_STATE_CONNECTED); 5354 registerConnected(); 5355 mLastConnectAttemptTimestamp = 0; 5356 mTargetWifiConfiguration = null; 5357 mWifiScoreReport.reset(); 5358 mLastSignalLevel = -1; 5359 5360 // Not roaming anymore 5361 mIsAutoRoaming = false; 5362 5363 mLastDriverRoamAttempt = 0; 5364 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 5365 mWifiInjector.getWifiLastResortWatchdog().connectedStateTransition(true); 5366 mWifiStateTracker.updateState(WifiStateTracker.CONNECTED); 5367 //Inform WifiLockManager 5368 WifiLockManager wifiLockManager = mWifiInjector.getWifiLockManager(); 5369 wifiLockManager.updateWifiClientConnected(true); 5370 mWifiScoreReport.startConnectedNetworkScorer(mNetworkAgent.getNetwork().getNetId()); 5371 updateLinkLayerStatsRssiAndScoreReport(); 5372 } 5373 @Override processMessage(Message message)5374 public boolean processMessage(Message message) { 5375 WifiConfiguration config = null; 5376 boolean handleStatus = HANDLED; 5377 5378 switch (message.what) { 5379 case CMD_UNWANTED_NETWORK: 5380 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { 5381 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 5382 StaEvent.DISCONNECT_UNWANTED); 5383 mWifiNative.disconnect(mInterfaceName); 5384 transitionTo(mDisconnectingState); 5385 } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 5386 || message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { 5387 Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 5388 ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN" 5389 : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED")); 5390 config = getCurrentWifiConfiguration(); 5391 if (config != null) { 5392 // Disable autojoin 5393 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) { 5394 mWifiConfigManager.setNetworkValidatedInternetAccess( 5395 config.networkId, false); 5396 mWifiConfigManager.updateNetworkSelectionStatus(config.networkId, 5397 DISABLED_NO_INTERNET_PERMANENT); 5398 } else { 5399 // stop collect last-mile stats since validation fail 5400 removeMessages(CMD_DIAGS_CONNECT_TIMEOUT); 5401 mWifiDiagnostics.reportConnectionEvent( 5402 WifiDiagnostics.CONNECTION_EVENT_FAILED); 5403 mWifiConfigManager.incrementNetworkNoInternetAccessReports( 5404 config.networkId); 5405 // If this was not the last selected network, update network 5406 // selection status to temporarily disable the network. 5407 if (mWifiConfigManager.getLastSelectedNetwork() != config.networkId 5408 && !config.noInternetAccessExpected) { 5409 Log.i(TAG, "Temporarily disabling network because of" 5410 + "no-internet access"); 5411 mWifiConfigManager.updateNetworkSelectionStatus( 5412 config.networkId, 5413 DISABLED_NO_INTERNET_TEMPORARY); 5414 mBssidBlocklistMonitor.handleBssidConnectionFailure( 5415 mLastBssid, config.SSID, 5416 BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE, 5417 mWifiInfo.getRssi()); 5418 } 5419 mWifiScoreCard.noteValidationFailure(mWifiInfo); 5420 } 5421 } 5422 } 5423 break; 5424 case CMD_NETWORK_STATUS: 5425 if (message.arg1 == NetworkAgent.VALIDATION_STATUS_VALID) { 5426 // stop collect last-mile stats since validation pass 5427 removeMessages(CMD_DIAGS_CONNECT_TIMEOUT); 5428 mWifiDiagnostics.reportConnectionEvent( 5429 WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); 5430 mWifiScoreCard.noteValidationSuccess(mWifiInfo); 5431 mBssidBlocklistMonitor.handleNetworkValidationSuccess(mLastBssid, 5432 mWifiInfo.getSSID()); 5433 config = getCurrentWifiConfiguration(); 5434 if (config != null) { 5435 // re-enable autojoin 5436 mWifiConfigManager.updateNetworkSelectionStatus( 5437 config.networkId, 5438 WifiConfiguration.NetworkSelectionStatus 5439 .DISABLED_NONE); 5440 mWifiConfigManager.setNetworkValidatedInternetAccess( 5441 config.networkId, true); 5442 } 5443 } 5444 break; 5445 case CMD_ACCEPT_UNVALIDATED: 5446 boolean accept = (message.arg1 != 0); 5447 mWifiConfigManager.setNetworkNoInternetAccessExpected(mLastNetworkId, accept); 5448 break; 5449 case WifiMonitor.ASSOCIATED_BSSID_EVENT: 5450 // ASSOCIATING to a new BSSID while already connected, indicates 5451 // that driver is roaming 5452 mLastDriverRoamAttempt = mClock.getWallClockMillis(); 5453 handleStatus = NOT_HANDLED; 5454 break; 5455 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5456 long lastRoam = 0; 5457 reportConnectionAttemptEnd( 5458 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 5459 WifiMetricsProto.ConnectionEvent.HLF_NONE, 5460 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 5461 if (mLastDriverRoamAttempt != 0) { 5462 // Calculate time since last driver roam attempt 5463 lastRoam = mClock.getWallClockMillis() - mLastDriverRoamAttempt; 5464 mLastDriverRoamAttempt = 0; 5465 } 5466 if (unexpectedDisconnectedReason(message.arg2)) { 5467 mWifiDiagnostics.captureBugReportData( 5468 WifiDiagnostics.REPORT_REASON_UNEXPECTED_DISCONNECT); 5469 } 5470 5471 boolean localGen = message.arg1 == 1; 5472 if (!localGen) { // ignore disconnects initiated by wpa_supplicant. 5473 mWifiScoreCard.noteNonlocalDisconnect(message.arg2); 5474 mBssidBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(), 5475 mWifiInfo.getSSID(), 5476 BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, 5477 mWifiInfo.getRssi()); 5478 } 5479 config = getCurrentWifiConfiguration(); 5480 5481 if (mVerboseLoggingEnabled) { 5482 log("NETWORK_DISCONNECTION_EVENT in connected state" 5483 + " BSSID=" + mWifiInfo.getBSSID() 5484 + " RSSI=" + mWifiInfo.getRssi() 5485 + " freq=" + mWifiInfo.getFrequency() 5486 + " reason=" + message.arg2 5487 + " Network Selection Status=" + (config == null ? "Unavailable" 5488 : config.getNetworkSelectionStatus().getNetworkStatusString())); 5489 } 5490 break; 5491 case CMD_START_ROAM: 5492 // Clear the driver roam indication since we are attempting a framework roam 5493 mLastDriverRoamAttempt = 0; 5494 5495 /* Connect command coming from auto-join */ 5496 int netId = message.arg1; 5497 ScanResult candidate = (ScanResult) message.obj; 5498 String bssid = SUPPLICANT_BSSID_ANY; 5499 if (candidate != null) { 5500 bssid = candidate.BSSID; 5501 } 5502 config = mWifiConfigManager.getConfiguredNetworkWithoutMasking(netId); 5503 if (config == null) { 5504 loge("CMD_START_ROAM and no config, bail out..."); 5505 break; 5506 } 5507 int scanRssi = mWifiConfigManager.findScanRssi(netId, 5508 mWifiHealthMonitor.getScanRssiValidTimeMs()); 5509 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, scanRssi, config.SSID); 5510 setTargetBssid(config, bssid); 5511 mTargetNetworkId = netId; 5512 5513 logd("CMD_START_ROAM sup state " 5514 + " my state " + getCurrentState().getName() 5515 + " nid=" + Integer.toString(netId) 5516 + " config " + config.getKey() 5517 + " targetRoamBSSID " + mTargetBssid); 5518 5519 reportConnectionAttemptStart(config, mTargetBssid, 5520 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 5521 if (mWifiNative.roamToNetwork(mInterfaceName, config)) { 5522 mLastConnectAttemptTimestamp = mClock.getWallClockMillis(); 5523 mTargetWifiConfiguration = config; 5524 mIsAutoRoaming = true; 5525 mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_ROAM, config); 5526 transitionTo(mRoamingState); 5527 } else { 5528 loge("CMD_START_ROAM Failed to start roaming to network " + config); 5529 reportConnectionAttemptEnd( 5530 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 5531 WifiMetricsProto.ConnectionEvent.HLF_NONE, 5532 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 5533 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5534 break; 5535 } 5536 break; 5537 case CMD_IP_CONFIGURATION_LOST: 5538 mWifiMetrics.incrementIpRenewalFailure(); 5539 handleStatus = NOT_HANDLED; 5540 break; 5541 case CMD_GET_CURRENT_NETWORK: 5542 replyToMessage(message, message.what, getCurrentNetwork()); 5543 break; 5544 default: 5545 handleStatus = NOT_HANDLED; 5546 break; 5547 } 5548 5549 if (handleStatus == HANDLED) { 5550 logStateAndMessage(message, this); 5551 } 5552 5553 return handleStatus; 5554 } 5555 5556 @Override exit()5557 public void exit() { 5558 logd("ClientModeImpl: Leaving Connected state"); 5559 mWifiConnectivityManager.handleConnectionStateChanged( 5560 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 5561 5562 mLastDriverRoamAttempt = 0; 5563 mWifiInjector.getWifiLastResortWatchdog().connectedStateTransition(false); 5564 } 5565 } 5566 5567 class DisconnectingState extends State { 5568 5569 @Override enter()5570 public void enter() { 5571 5572 if (mVerboseLoggingEnabled) { 5573 logd(" Enter DisconnectingState State screenOn=" + mScreenOn); 5574 } 5575 5576 // Make sure we disconnect: we enter this state prior to connecting to a new 5577 // network, waiting for either a DISCONNECT event or a SUPPLICANT_STATE_CHANGE 5578 // event which in this case will be indicating that supplicant started to associate. 5579 // In some cases supplicant doesn't ignore the connect requests (it might not 5580 // find the target SSID in its cache), 5581 // Therefore we end up stuck that state, hence the need for the watchdog. 5582 mDisconnectingWatchdogCount++; 5583 logd("Start Disconnecting Watchdog " + mDisconnectingWatchdogCount); 5584 sendMessageDelayed(obtainMessage(CMD_DISCONNECTING_WATCHDOG_TIMER, 5585 mDisconnectingWatchdogCount, 0), DISCONNECTING_GUARD_TIMER_MSEC); 5586 } 5587 5588 @Override processMessage(Message message)5589 public boolean processMessage(Message message) { 5590 boolean handleStatus = HANDLED; 5591 5592 switch (message.what) { 5593 case CMD_CONNECT_NETWORK: 5594 case CMD_SAVE_NETWORK: 5595 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5596 deferMessage(message); 5597 break; 5598 case CMD_DISCONNECT: 5599 if (mVerboseLoggingEnabled) { 5600 log("Ignore CMD_DISCONNECT when already disconnecting."); 5601 } 5602 break; 5603 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5604 if (mVerboseLoggingEnabled) { 5605 log("Ignore NETWORK_CONNECTION_EVENT when already disconnecting."); 5606 } 5607 break; 5608 case CMD_DISCONNECTING_WATCHDOG_TIMER: 5609 if (mDisconnectingWatchdogCount == message.arg1) { 5610 if (mVerboseLoggingEnabled) log("disconnecting watchdog! -> disconnect"); 5611 handleNetworkDisconnect(); 5612 transitionTo(mDisconnectedState); 5613 } 5614 break; 5615 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5616 /** 5617 * If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT 5618 * we have missed the network disconnection, transition to mDisconnectedState 5619 * and handle the rest of the events there 5620 */ 5621 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5622 deferMessage(message); 5623 handleNetworkDisconnect(); 5624 transitionTo(mDisconnectedState); 5625 break; 5626 default: 5627 handleStatus = NOT_HANDLED; 5628 break; 5629 } 5630 5631 if (handleStatus == HANDLED) { 5632 logStateAndMessage(message, this); 5633 } 5634 return handleStatus; 5635 } 5636 } 5637 5638 class DisconnectedState extends State { 5639 @Override enter()5640 public void enter() { 5641 Log.i(TAG, "disconnectedstate enter"); 5642 // We don't scan frequently if this is a temporary disconnect 5643 // due to p2p 5644 if (mTemporarilyDisconnectWifi) { 5645 p2pSendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 5646 return; 5647 } 5648 5649 if (mVerboseLoggingEnabled) { 5650 logd(" Enter DisconnectedState screenOn=" + mScreenOn); 5651 } 5652 5653 /** clear the roaming state, if we were roaming, we failed */ 5654 mIsAutoRoaming = false; 5655 5656 mWifiConnectivityManager.handleConnectionStateChanged( 5657 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 5658 } 5659 5660 @Override processMessage(Message message)5661 public boolean processMessage(Message message) { 5662 boolean handleStatus = HANDLED; 5663 5664 switch (message.what) { 5665 case CMD_DISCONNECT: 5666 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 5667 StaEvent.DISCONNECT_GENERIC); 5668 mWifiNative.disconnect(mInterfaceName); 5669 break; 5670 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5671 stopIpClient(); 5672 if (message.arg2 == 15 /* FOURWAY_HANDSHAKE_TIMEOUT */) { 5673 String bssid = (message.obj == null) 5674 ? mTargetBssid : (String) message.obj; 5675 mWifiInjector.getWifiLastResortWatchdog() 5676 .noteConnectionFailureAndTriggerIfNeeded( 5677 getTargetSsid(), bssid, 5678 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 5679 } 5680 clearNetworkCachedDataIfNeeded(getTargetWifiConfiguration(), message.arg2); 5681 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 5682 mWifiInfo.reset(); 5683 break; 5684 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5685 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 5686 if (mVerboseLoggingEnabled) { 5687 logd("SUPPLICANT_STATE_CHANGE_EVENT state=" + stateChangeResult.state 5688 + " -> state= " 5689 + WifiInfo.getDetailedStateOf(stateChangeResult.state)); 5690 } 5691 if (SupplicantState.isConnecting(stateChangeResult.state)) { 5692 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork( 5693 stateChangeResult.networkId); 5694 5695 // Update Passpoint information before setNetworkDetailedState as 5696 // WifiTracker monitors NETWORK_STATE_CHANGED_ACTION to update UI. 5697 mWifiInfo.setFQDN(null); 5698 mWifiInfo.setPasspointUniqueId(null); 5699 mWifiInfo.setOsuAp(false); 5700 mWifiInfo.setProviderFriendlyName(null); 5701 if (config != null && (config.isPasspoint() || config.osu)) { 5702 if (config.isPasspoint()) { 5703 mWifiInfo.setFQDN(config.FQDN); 5704 mWifiInfo.setPasspointUniqueId(config.getPasspointUniqueId()); 5705 } else { 5706 mWifiInfo.setOsuAp(true); 5707 } 5708 mWifiInfo.setProviderFriendlyName(config.providerFriendlyName); 5709 } 5710 } 5711 sendNetworkChangeBroadcast( 5712 WifiInfo.getDetailedStateOf(stateChangeResult.state)); 5713 /* ConnectModeState does the rest of the handling */ 5714 handleStatus = NOT_HANDLED; 5715 break; 5716 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 5717 NetworkInfo info = (NetworkInfo) message.obj; 5718 mP2pConnected.set(info.isConnected()); 5719 break; 5720 case CMD_RECONNECT: 5721 case CMD_REASSOCIATE: 5722 if (mTemporarilyDisconnectWifi) { 5723 // Drop a third party reconnect/reassociate if STA is 5724 // temporarily disconnected for p2p 5725 break; 5726 } else { 5727 // ConnectModeState handles it 5728 handleStatus = NOT_HANDLED; 5729 } 5730 break; 5731 case CMD_SCREEN_STATE_CHANGED: 5732 handleScreenStateChanged(message.arg1 != 0); 5733 break; 5734 default: 5735 handleStatus = NOT_HANDLED; 5736 break; 5737 } 5738 5739 if (handleStatus == HANDLED) { 5740 logStateAndMessage(message, this); 5741 } 5742 return handleStatus; 5743 } 5744 5745 @Override exit()5746 public void exit() { 5747 mWifiConnectivityManager.handleConnectionStateChanged( 5748 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 5749 } 5750 } 5751 5752 /** 5753 * State machine initiated requests can have replyTo set to null, indicating 5754 * there are no recipients, we ignore those reply actions. 5755 */ replyToMessage(Message msg, int what)5756 private void replyToMessage(Message msg, int what) { 5757 if (msg.replyTo == null) return; 5758 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 5759 mReplyChannel.replyToMessage(msg, dstMsg); 5760 } 5761 replyToMessage(Message msg, int what, int arg1)5762 private void replyToMessage(Message msg, int what, int arg1) { 5763 if (msg.replyTo == null) return; 5764 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 5765 dstMsg.arg1 = arg1; 5766 mReplyChannel.replyToMessage(msg, dstMsg); 5767 } 5768 replyToMessage(Message msg, int what, Object obj)5769 private void replyToMessage(Message msg, int what, Object obj) { 5770 if (msg.replyTo == null) return; 5771 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 5772 dstMsg.obj = obj; 5773 mReplyChannel.replyToMessage(msg, dstMsg); 5774 } 5775 5776 /** 5777 * arg2 on the source message has a unique id that needs to be retained in replies 5778 * to match the request 5779 * <p>see WifiManager for details 5780 */ obtainMessageWithWhatAndArg2(Message srcMsg, int what)5781 private Message obtainMessageWithWhatAndArg2(Message srcMsg, int what) { 5782 Message msg = Message.obtain(); 5783 msg.what = what; 5784 msg.arg2 = srcMsg.arg2; 5785 return msg; 5786 } 5787 5788 /** 5789 * Notify interested parties if a wifi config has been changed. 5790 * 5791 * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT 5792 * @param config Must have a WifiConfiguration object to succeed 5793 * TODO: b/35258354 investigate if this can be removed. Is the broadcast sent by 5794 * WifiConfigManager sufficient? 5795 */ broadcastWifiCredentialChanged(int wifiCredentialEventType, WifiConfiguration config)5796 private void broadcastWifiCredentialChanged(int wifiCredentialEventType, 5797 WifiConfiguration config) { 5798 Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); 5799 if (config != null && config.SSID != null && mWifiPermissionsUtil.isLocationModeEnabled()) { 5800 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); 5801 } 5802 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, wifiCredentialEventType); 5803 mContext.createContextAsUser(UserHandle.CURRENT, 0) 5804 .sendBroadcastWithMultiplePermissions( 5805 intent, 5806 new String[]{ 5807 android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE, 5808 android.Manifest.permission.ACCESS_FINE_LOCATION, 5809 }); 5810 } 5811 handleGsmAuthRequest(SimAuthRequestData requestData)5812 void handleGsmAuthRequest(SimAuthRequestData requestData) { 5813 WifiConfiguration requestingWifiConfiguration = null; 5814 if (mTargetWifiConfiguration != null 5815 && mTargetWifiConfiguration.networkId 5816 == requestData.networkId) { 5817 requestingWifiConfiguration = mTargetWifiConfiguration; 5818 logd("id matches targetWifiConfiguration"); 5819 } else if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 5820 && mLastNetworkId == requestData.networkId) { 5821 requestingWifiConfiguration = getCurrentWifiConfiguration(); 5822 logd("id matches currentWifiConfiguration"); 5823 } 5824 5825 if (requestingWifiConfiguration == null) { 5826 logd("GsmAuthRequest received with null target/current WifiConfiguration."); 5827 return; 5828 } 5829 5830 /* 5831 * Try authentication in the following order. 5832 * 5833 * Standard Cellular_auth Type Command 5834 * 5835 * 1. 3GPP TS 31.102 3G_authentication [Length][RAND][Length][AUTN] 5836 * [Length][RES][Length][CK][Length][IK] and more 5837 * 2. 3GPP TS 31.102 2G_authentication [Length][RAND] 5838 * [Length][SRES][Length][Cipher Key Kc] 5839 * 3. 3GPP TS 11.11 2G_authentication [RAND] 5840 * [SRES][Cipher Key Kc] 5841 */ 5842 String response = mWifiCarrierInfoManager 5843 .getGsmSimAuthResponse(requestData.data, requestingWifiConfiguration); 5844 if (response == null) { 5845 // In case of failure, issue may be due to sim type, retry as No.2 case 5846 response = mWifiCarrierInfoManager 5847 .getGsmSimpleSimAuthResponse(requestData.data, requestingWifiConfiguration); 5848 if (response == null) { 5849 // In case of failure, issue may be due to sim type, retry as No.3 case 5850 response = mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse( 5851 requestData.data, requestingWifiConfiguration); 5852 } 5853 } 5854 if (response == null || response.length() == 0) { 5855 mWifiNative.simAuthFailedResponse(mInterfaceName); 5856 } else { 5857 logv("Supplicant Response -" + response); 5858 mWifiNative.simAuthResponse( 5859 mInterfaceName, WifiNative.SIM_AUTH_RESP_TYPE_GSM_AUTH, response); 5860 } 5861 } 5862 handle3GAuthRequest(SimAuthRequestData requestData)5863 void handle3GAuthRequest(SimAuthRequestData requestData) { 5864 WifiConfiguration requestingWifiConfiguration = null; 5865 if (mTargetWifiConfiguration != null 5866 && mTargetWifiConfiguration.networkId 5867 == requestData.networkId) { 5868 requestingWifiConfiguration = mTargetWifiConfiguration; 5869 logd("id matches targetWifiConfiguration"); 5870 } else if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 5871 && mLastNetworkId == requestData.networkId) { 5872 requestingWifiConfiguration = getCurrentWifiConfiguration(); 5873 logd("id matches currentWifiConfiguration"); 5874 } 5875 5876 if (requestingWifiConfiguration == null) { 5877 logd("3GAuthRequest received with null target/current WifiConfiguration."); 5878 return; 5879 } 5880 5881 SimAuthResponseData response = mWifiCarrierInfoManager 5882 .get3GAuthResponse(requestData, requestingWifiConfiguration); 5883 if (response != null) { 5884 mWifiNative.simAuthResponse( 5885 mInterfaceName, response.type, response.response); 5886 } else { 5887 mWifiNative.umtsAuthFailedResponse(mInterfaceName); 5888 } 5889 } 5890 5891 /** 5892 * Automatically connect to the network specified 5893 * 5894 * @param networkId ID of the network to connect to 5895 * @param uid UID of the app triggering the connection. 5896 * @param bssid BSSID of the network 5897 */ startConnectToNetwork(int networkId, int uid, String bssid)5898 public void startConnectToNetwork(int networkId, int uid, String bssid) { 5899 sendMessage(CMD_START_CONNECT, networkId, uid, bssid); 5900 } 5901 5902 /** 5903 * Automatically roam to the network specified 5904 * 5905 * @param networkId ID of the network to roam to 5906 * @param scanResult scan result which identifies the network to roam to 5907 */ startRoamToNetwork(int networkId, ScanResult scanResult)5908 public void startRoamToNetwork(int networkId, ScanResult scanResult) { 5909 sendMessage(CMD_START_ROAM, networkId, 0, scanResult); 5910 } 5911 5912 /** 5913 * Dynamically turn on/off WifiConnectivityManager 5914 * 5915 * @param choice true-enable; false-disable 5916 */ allowAutoJoinGlobal(boolean choice)5917 public void allowAutoJoinGlobal(boolean choice) { 5918 mWifiConnectivityManager.setAutoJoinEnabledExternal(choice); 5919 } 5920 5921 /** 5922 * @param reason reason code from supplicant on network disconnected event 5923 * @return true if this is a suspicious disconnect 5924 */ unexpectedDisconnectedReason(int reason)5925 static boolean unexpectedDisconnectedReason(int reason) { 5926 return reason == 2 // PREV_AUTH_NOT_VALID 5927 || reason == 6 // CLASS2_FRAME_FROM_NONAUTH_STA 5928 || reason == 7 // FRAME_FROM_NONASSOC_STA 5929 || reason == 8 // STA_HAS_LEFT 5930 || reason == 9 // STA_REQ_ASSOC_WITHOUT_AUTH 5931 || reason == 14 // MICHAEL_MIC_FAILURE 5932 || reason == 15 // 4WAY_HANDSHAKE_TIMEOUT 5933 || reason == 16 // GROUP_KEY_UPDATE_TIMEOUT 5934 || reason == 18 // GROUP_CIPHER_NOT_VALID 5935 || reason == 19 // PAIRWISE_CIPHER_NOT_VALID 5936 || reason == 23 // IEEE_802_1X_AUTH_FAILED 5937 || reason == 34; // DISASSOC_LOW_ACK 5938 } 5939 getLinkPropertiesSummary(LinkProperties lp)5940 private static String getLinkPropertiesSummary(LinkProperties lp) { 5941 List<String> attributes = new ArrayList<>(6); 5942 if (lp.hasIpv4Address()) { 5943 attributes.add("v4"); 5944 } 5945 if (lp.hasIpv4DefaultRoute()) { 5946 attributes.add("v4r"); 5947 } 5948 if (lp.hasIpv4DnsServer()) { 5949 attributes.add("v4dns"); 5950 } 5951 if (lp.hasGlobalIpv6Address()) { 5952 attributes.add("v6"); 5953 } 5954 if (lp.hasIpv6DefaultRoute()) { 5955 attributes.add("v6r"); 5956 } 5957 if (lp.hasIpv6DnsServer()) { 5958 attributes.add("v6dns"); 5959 } 5960 5961 return TextUtils.join(" ", attributes); 5962 } 5963 5964 /** 5965 * Gets the SSID from the WifiConfiguration pointed at by 'mTargetNetworkId' 5966 * This should match the network config framework is attempting to connect to. 5967 */ getTargetSsid()5968 private String getTargetSsid() { 5969 WifiConfiguration currentConfig = mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 5970 if (currentConfig != null) { 5971 return currentConfig.SSID; 5972 } 5973 return null; 5974 } 5975 5976 /** 5977 * Send message to WifiP2pServiceImpl. 5978 * @return true if message is sent. 5979 * false if there is no channel configured for WifiP2pServiceImpl. 5980 */ p2pSendMessage(int what)5981 private boolean p2pSendMessage(int what) { 5982 if (mWifiP2pChannel != null) { 5983 mWifiP2pChannel.sendMessage(what); 5984 return true; 5985 } 5986 return false; 5987 } 5988 5989 /** 5990 * Send message to WifiP2pServiceImpl with an additional param |arg1|. 5991 * @return true if message is sent. 5992 * false if there is no channel configured for WifiP2pServiceImpl. 5993 */ p2pSendMessage(int what, int arg1)5994 private boolean p2pSendMessage(int what, int arg1) { 5995 if (mWifiP2pChannel != null) { 5996 mWifiP2pChannel.sendMessage(what, arg1); 5997 return true; 5998 } 5999 return false; 6000 } 6001 6002 /** 6003 * Check if there is any connection request for WiFi network. 6004 */ hasConnectionRequests()6005 private boolean hasConnectionRequests() { 6006 return mNetworkFactory.hasConnectionRequests() 6007 || mUntrustedNetworkFactory.hasConnectionRequests(); 6008 } 6009 6010 /** 6011 * Returns whether CMD_IP_REACHABILITY_LOST events should trigger disconnects. 6012 */ getIpReachabilityDisconnectEnabled()6013 public boolean getIpReachabilityDisconnectEnabled() { 6014 return mIpReachabilityDisconnectEnabled; 6015 } 6016 6017 /** 6018 * Sets whether CMD_IP_REACHABILITY_LOST events should trigger disconnects. 6019 */ setIpReachabilityDisconnectEnabled(boolean enabled)6020 public void setIpReachabilityDisconnectEnabled(boolean enabled) { 6021 mIpReachabilityDisconnectEnabled = enabled; 6022 } 6023 6024 /** 6025 * Sends a message to initialize the ClientModeImpl. 6026 */ initialize()6027 public void initialize() { 6028 sendMessage(CMD_INITIALIZE); 6029 } 6030 6031 /** 6032 * Add a network request match callback to {@link WifiNetworkFactory}. 6033 */ addNetworkRequestMatchCallback(IBinder binder, INetworkRequestMatchCallback callback, int callbackIdentifier)6034 public void addNetworkRequestMatchCallback(IBinder binder, 6035 INetworkRequestMatchCallback callback, 6036 int callbackIdentifier) { 6037 mNetworkFactory.addCallback(binder, callback, callbackIdentifier); 6038 } 6039 6040 /** 6041 * Remove a network request match callback from {@link WifiNetworkFactory}. 6042 */ removeNetworkRequestMatchCallback(int callbackIdentifier)6043 public void removeNetworkRequestMatchCallback(int callbackIdentifier) { 6044 mNetworkFactory.removeCallback(callbackIdentifier); 6045 } 6046 6047 /** 6048 * Approve all access points from {@link WifiNetworkFactory} for the provided package. 6049 * Used by shell commands. 6050 */ setNetworkRequestUserApprovedApp(@onNull String packageName, boolean approved)6051 public void setNetworkRequestUserApprovedApp(@NonNull String packageName, boolean approved) { 6052 mNetworkFactory.setUserApprovedApp(packageName, approved); 6053 } 6054 6055 /** 6056 * Whether all access points are approved for the specified app. 6057 * Used by shell commands. 6058 */ hasNetworkRequestUserApprovedApp(@onNull String packageName)6059 public boolean hasNetworkRequestUserApprovedApp(@NonNull String packageName) { 6060 return mNetworkFactory.hasUserApprovedApp(packageName); 6061 } 6062 6063 /** 6064 * Remove all approved access points from {@link WifiNetworkFactory} for the provided package. 6065 */ removeNetworkRequestUserApprovedAccessPointsForApp(@onNull String packageName)6066 public void removeNetworkRequestUserApprovedAccessPointsForApp(@NonNull String packageName) { 6067 mNetworkFactory.removeUserApprovedAccessPointsForApp(packageName); 6068 } 6069 6070 /** 6071 * Clear all approved access points from {@link WifiNetworkFactory}. 6072 */ clearNetworkRequestUserApprovedAccessPoints()6073 public void clearNetworkRequestUserApprovedAccessPoints() { 6074 mNetworkFactory.clear(); 6075 } 6076 6077 /** 6078 * Gets the factory MAC address of wlan0 (station interface). 6079 * @return String representation of the factory MAC address. 6080 */ getFactoryMacAddress()6081 public String getFactoryMacAddress() { 6082 MacAddress macAddress = mWifiNative.getFactoryMacAddress(mInterfaceName); 6083 if (macAddress != null) { 6084 return macAddress.toString(); 6085 } 6086 if (!isConnectedMacRandomizationEnabled()) { 6087 return mWifiNative.getMacAddress(mInterfaceName); 6088 } 6089 return null; 6090 } 6091 6092 /** 6093 * Sets the current device mobility state. 6094 * @param state the new device mobility state 6095 */ setDeviceMobilityState(@eviceMobilityState int state)6096 public void setDeviceMobilityState(@DeviceMobilityState int state) { 6097 mWifiConnectivityManager.setDeviceMobilityState(state); 6098 mWifiHealthMonitor.setDeviceMobilityState(state); 6099 mWifiDataStall.setDeviceMobilityState(state); 6100 } 6101 6102 /** 6103 * Updates the Wi-Fi usability score. 6104 * @param seqNum Sequence number of the Wi-Fi usability score. 6105 * @param score The Wi-Fi usability score. 6106 * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score. 6107 */ updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec)6108 public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { 6109 mWifiMetrics.incrementWifiUsabilityScoreCount(seqNum, score, predictionHorizonSec); 6110 } 6111 6112 /** 6113 * Sends a link probe. 6114 */ 6115 @VisibleForTesting probeLink(WifiNl80211Manager.SendMgmtFrameCallback callback, int mcs)6116 public void probeLink(WifiNl80211Manager.SendMgmtFrameCallback callback, int mcs) { 6117 mWifiNative.probeLink(mInterfaceName, MacAddress.fromString(mWifiInfo.getBSSID()), 6118 callback, mcs); 6119 } 6120 sendActionListenerFailure(int callbackIdentifier, int reason)6121 private void sendActionListenerFailure(int callbackIdentifier, int reason) { 6122 IActionListener actionListener; 6123 synchronized (mProcessingActionListeners) { 6124 actionListener = mProcessingActionListeners.remove(callbackIdentifier); 6125 } 6126 if (actionListener != null) { 6127 try { 6128 actionListener.onFailure(reason); 6129 } catch (RemoteException e) { 6130 // no-op (client may be dead, nothing to be done) 6131 } 6132 } 6133 } 6134 sendActionListenerSuccess(int callbackIdentifier)6135 private void sendActionListenerSuccess(int callbackIdentifier) { 6136 IActionListener actionListener; 6137 synchronized (mProcessingActionListeners) { 6138 actionListener = mProcessingActionListeners.remove(callbackIdentifier); 6139 } 6140 if (actionListener != null) { 6141 try { 6142 actionListener.onSuccess(); 6143 } catch (RemoteException e) { 6144 // no-op (client may be dead, nothing to be done) 6145 } 6146 } 6147 } 6148 6149 /** 6150 * Trigger network connection and provide status via the provided callback. 6151 */ connect(WifiConfiguration config, int netId, @Nullable IBinder binder, @Nullable IActionListener callback, int callbackIdentifier, int callingUid)6152 public void connect(WifiConfiguration config, int netId, @Nullable IBinder binder, 6153 @Nullable IActionListener callback, int callbackIdentifier, int callingUid) { 6154 mWifiInjector.getWifiThreadRunner().post(() -> { 6155 if (callback != null && binder != null) { 6156 mProcessingActionListeners.add(binder, callback, callbackIdentifier); 6157 } 6158 /** 6159 * The connect message can contain a network id passed as arg1 on message or 6160 * or a config passed as obj on message. 6161 * For a new network, a config is passed to create and connect. 6162 * For an existing network, a network id is passed 6163 */ 6164 NetworkUpdateResult result = null; 6165 if (config != null) { 6166 result = mWifiConfigManager.addOrUpdateNetwork(config, callingUid); 6167 if (!result.isSuccess()) { 6168 loge("connectNetwork adding/updating config=" + config + " failed"); 6169 sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); 6170 return; 6171 } 6172 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 6173 } else { 6174 if (mWifiConfigManager.getConfiguredNetwork(netId) == null) { 6175 loge("connectNetwork Invalid network Id=" + netId); 6176 sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); 6177 return; 6178 } 6179 result = new NetworkUpdateResult(netId); 6180 } 6181 final int networkId = result.getNetworkId(); 6182 mWifiConfigManager.userEnabledNetwork(networkId); 6183 if (!mWifiConfigManager.enableNetwork(networkId, true, callingUid, null) 6184 || !mWifiConfigManager.updateLastConnectUid(networkId, callingUid)) { 6185 logi("connect Allowing uid " + callingUid 6186 + " with insufficient permissions to connect=" + networkId); 6187 } else if (mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid)) { 6188 // Note user connect choice here, so that it will be considered in the 6189 // next network selection. 6190 mWifiConnectivityManager.setUserConnectChoice(networkId); 6191 } 6192 Message message = 6193 obtainMessage(CMD_CONNECT_NETWORK, -1, callbackIdentifier, result); 6194 message.sendingUid = callingUid; 6195 sendMessage(message); 6196 }); 6197 } 6198 6199 /** 6200 * Trigger network save and provide status via the provided callback. 6201 */ save(WifiConfiguration config, @Nullable IBinder binder, @Nullable IActionListener callback, int callbackIdentifier, int callingUid)6202 public void save(WifiConfiguration config, @Nullable IBinder binder, 6203 @Nullable IActionListener callback, int callbackIdentifier, int callingUid) { 6204 mWifiInjector.getWifiThreadRunner().post(() -> { 6205 if (callback != null && binder != null) { 6206 mProcessingActionListeners.add(binder, callback, callbackIdentifier); 6207 } 6208 if (config == null) { 6209 loge("saveNetwork with null configuration my state " 6210 + getCurrentState().getName()); 6211 sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); 6212 return; 6213 } 6214 NetworkUpdateResult result = 6215 mWifiConfigManager.addOrUpdateNetwork(config, callingUid); 6216 if (!result.isSuccess()) { 6217 loge("saveNetwork adding/updating config=" + config + " failed"); 6218 sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); 6219 return; 6220 } 6221 if (!mWifiConfigManager.enableNetwork( 6222 result.getNetworkId(), false, callingUid, null)) { 6223 loge("saveNetwork enabling config=" + config + " failed"); 6224 sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); 6225 return; 6226 } 6227 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 6228 Message message = 6229 obtainMessage(CMD_SAVE_NETWORK, -1 , callbackIdentifier, result); 6230 message.sendingUid = callingUid; 6231 sendMessage(message); 6232 }); 6233 } 6234 6235 /** 6236 * Trigger network forget and provide status via the provided callback. 6237 */ forget(int netId, @Nullable IBinder binder, @Nullable IActionListener callback, int callbackIdentifier, int callingUid)6238 public void forget(int netId, @Nullable IBinder binder, @Nullable IActionListener callback, 6239 int callbackIdentifier, int callingUid) { 6240 mWifiInjector.getWifiThreadRunner().post(() -> { 6241 if (callback != null && binder != null) { 6242 mProcessingActionListeners.add(binder, callback, callbackIdentifier); 6243 } 6244 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId); 6245 boolean success = mWifiConfigManager.removeNetwork(netId, callingUid, null); 6246 if (!success) { 6247 loge("Failed to remove network"); 6248 sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); 6249 } 6250 sendActionListenerSuccess(callbackIdentifier); 6251 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, config); 6252 }); 6253 } 6254 6255 /** 6256 * Handle BSS transition request from Connected BSS. 6257 * 6258 * @param frameData Data retrieved from received BTM request frame. 6259 */ handleBssTransitionRequest(BtmFrameData frameData)6260 private void handleBssTransitionRequest(BtmFrameData frameData) { 6261 if (frameData == null) { 6262 return; 6263 } 6264 6265 String bssid = mWifiInfo.getBSSID(); 6266 String ssid = mWifiInfo.getSSID(); 6267 if ((bssid == null) || (ssid == null) || WifiManager.UNKNOWN_SSID.equals(ssid)) { 6268 Log.e(TAG, "Failed to handle BSS transition: bssid: " + bssid + " ssid: " + ssid); 6269 return; 6270 } 6271 6272 if ((frameData.mBssTmDataFlagsMask 6273 & MboOceConstants.BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED) 6274 != 0) { 6275 mWifiMetrics.incrementMboCellularSwitchRequestCount(); 6276 } 6277 6278 6279 if ((frameData.mBssTmDataFlagsMask 6280 & MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT) != 0) { 6281 long duration = 0; 6282 if ((frameData.mBssTmDataFlagsMask 6283 & MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED) != 0) { 6284 mWifiMetrics.incrementSteeringRequestCountIncludingMboAssocRetryDelay(); 6285 duration = frameData.mBlockListDurationMs; 6286 } 6287 if (duration == 0) { 6288 /* 6289 * When disassoc imminent bit alone is set or MBO assoc retry delay is 6290 * set to zero(reserved as per spec), blocklist the BSS for sometime to 6291 * avoid AP rejecting the re-connect request. 6292 */ 6293 duration = MboOceConstants.DEFAULT_BLOCKLIST_DURATION_MS; 6294 } 6295 // Blocklist the current BSS 6296 mBssidBlocklistMonitor.blockBssidForDurationMs(bssid, ssid, duration, 6297 BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE, 0); 6298 } 6299 6300 if (frameData.mStatus != MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT) { 6301 // Trigger the network selection and re-connect to new network if available. 6302 mWifiMetrics.incrementForceScanCountDueToSteeringRequest(); 6303 mWifiConnectivityManager.forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE); 6304 } 6305 } 6306 6307 /** 6308 * @return true if this device supports FILS-SHA256 6309 */ isFilsSha256Supported()6310 private boolean isFilsSha256Supported() { 6311 return (mWifiNative.getSupportedFeatureSet(mInterfaceName) & WIFI_FEATURE_FILS_SHA256) != 0; 6312 } 6313 6314 /** 6315 * @return true if this device supports FILS-SHA384 6316 */ isFilsSha384Supported()6317 private boolean isFilsSha384Supported() { 6318 return (mWifiNative.getSupportedFeatureSet(mInterfaceName) & WIFI_FEATURE_FILS_SHA384) != 0; 6319 } 6320 6321 /** 6322 * Helper method to set the allowed key management schemes from 6323 * scan result. 6324 */ updateAllowedKeyManagementSchemesFromScanResult( WifiConfiguration config, ScanResult scanResult)6325 private void updateAllowedKeyManagementSchemesFromScanResult( 6326 WifiConfiguration config, ScanResult scanResult) { 6327 if (isFilsSha256Supported() 6328 && ScanResultUtil.isScanResultForFilsSha256Network(scanResult)) { 6329 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.FILS_SHA256); 6330 } 6331 if (isFilsSha384Supported() 6332 && ScanResultUtil.isScanResultForFilsSha384Network(scanResult)) { 6333 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.FILS_SHA384); 6334 } 6335 } 6336 /** 6337 * Update wifi configuration based on the matching scan result. 6338 * 6339 * @param config Wifi configuration object. 6340 * @param scanResult Scan result matching the network. 6341 */ updateWifiConfigFromMatchingScanResult(WifiConfiguration config, ScanResult scanResult)6342 private void updateWifiConfigFromMatchingScanResult(WifiConfiguration config, 6343 ScanResult scanResult) { 6344 updateAllowedKeyManagementSchemesFromScanResult(config, scanResult); 6345 if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256) 6346 || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA384)) { 6347 config.enterpriseConfig.setFieldValue(WifiEnterpriseConfig.EAP_ERP, "1"); 6348 } 6349 } 6350 6351 /** 6352 * Update the wifi configuration before sending connect to 6353 * supplicant/driver. 6354 * 6355 * @param config wifi configuration object. 6356 * @param bssid BSSID to assocaite with. 6357 */ updateWifiConfigOnStartConnection(WifiConfiguration config, String bssid)6358 void updateWifiConfigOnStartConnection(WifiConfiguration config, String bssid) { 6359 boolean canUpgradePskToSae = false; 6360 boolean isFrameworkWpa3SaeUpgradePossible = false; 6361 boolean isLegacyWpa2ApInScanResult = false; 6362 6363 setTargetBssid(config, bssid); 6364 6365 if (isWpa3SaeUpgradeEnabled() && config.allowedKeyManagement.get( 6366 WifiConfiguration.KeyMgmt.WPA_PSK)) { 6367 isFrameworkWpa3SaeUpgradePossible = true; 6368 } 6369 6370 if (isFrameworkWpa3SaeUpgradePossible && isWpa3SaeUpgradeOffloadEnabled()) { 6371 // Driver offload of upgrading legacy WPA/WPA2 connection to WPA3 6372 if (mVerboseLoggingEnabled) { 6373 Log.d(TAG, "Driver upgrade legacy WPA/WPA2 connection to WPA3"); 6374 } 6375 config.allowedAuthAlgorithms.clear(); 6376 // Note: KeyMgmt.WPA2_PSK is already enabled, enable SAE as well 6377 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); 6378 isFrameworkWpa3SaeUpgradePossible = false; 6379 } 6380 // Check if network selection selected a good WPA3 candidate AP for a WPA2 6381 // saved network. 6382 ScanResult scanResultCandidate = config.getNetworkSelectionStatus().getCandidate(); 6383 if (isFrameworkWpa3SaeUpgradePossible && scanResultCandidate != null) { 6384 ScanResultMatchInfo scanResultMatchInfo = ScanResultMatchInfo 6385 .fromScanResult(scanResultCandidate); 6386 if ((scanResultMatchInfo.networkType == WifiConfiguration.SECURITY_TYPE_SAE)) { 6387 canUpgradePskToSae = true; 6388 } else { 6389 // No SAE candidate 6390 isFrameworkWpa3SaeUpgradePossible = false; 6391 } 6392 } 6393 6394 /** 6395 * Go through the matching scan results and update wifi config. 6396 */ 6397 ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(config); 6398 ScanRequestProxy scanRequestProxy = mWifiInjector.getScanRequestProxy(); 6399 List<ScanResult> scanResults = scanRequestProxy.getScanResults(); 6400 for (ScanResult scanResult : scanResults) { 6401 if (!config.SSID.equals(ScanResultUtil.createQuotedSSID(scanResult.SSID))) { 6402 continue; 6403 } 6404 if (isFrameworkWpa3SaeUpgradePossible && !isLegacyWpa2ApInScanResult) { 6405 if (ScanResultUtil.isScanResultForPskNetwork(scanResult) 6406 && !ScanResultUtil.isScanResultForSaeNetwork(scanResult)) { 6407 // Found a legacy WPA2 AP in range. Do not upgrade the connection to WPA3 to 6408 // allow seamless roaming within the ESS. 6409 if (mVerboseLoggingEnabled) { 6410 Log.d(TAG, "Found legacy WPA2 AP, do not upgrade to WPA3"); 6411 } 6412 isLegacyWpa2ApInScanResult = true; 6413 canUpgradePskToSae = false; 6414 } 6415 if (ScanResultUtil.isScanResultForSaeNetwork(scanResult) 6416 && scanResultCandidate == null) { 6417 // When the user manually selected a network from the Wi-Fi picker, evaluate 6418 // if to upgrade based on the scan results. The most typical use case during 6419 // the WPA3 transition mode is to have a WPA2/WPA3 AP in transition mode. In 6420 // this case, we would like to upgrade the connection. 6421 canUpgradePskToSae = true; 6422 } 6423 } 6424 6425 ScanResultMatchInfo key2 = ScanResultMatchInfo.fromScanResult(scanResult); 6426 if (!key1.equals(key2)) { 6427 continue; 6428 } 6429 updateWifiConfigFromMatchingScanResult(config, scanResult); 6430 } 6431 6432 if (isFrameworkWpa3SaeUpgradePossible && canUpgradePskToSae 6433 && !(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256) 6434 || config.allowedKeyManagement.get( 6435 WifiConfiguration.KeyMgmt.FILS_SHA384))) { 6436 // Upgrade legacy WPA/WPA2 connection to WPA3 6437 if (mVerboseLoggingEnabled) { 6438 Log.d(TAG, "Upgrade legacy WPA/WPA2 connection to WPA3"); 6439 } 6440 config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); 6441 } 6442 6443 if (isConnectedMacRandomizationEnabled()) { 6444 if (config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) { 6445 configureRandomizedMacAddress(config); 6446 } else { 6447 setCurrentMacToFactoryMac(config); 6448 } 6449 } 6450 6451 if (config.enterpriseConfig != null 6452 && config.enterpriseConfig.isAuthenticationSimBased() 6453 && mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable( 6454 mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)) 6455 && TextUtils.isEmpty(config.enterpriseConfig.getAnonymousIdentity())) { 6456 String anonAtRealm = mWifiCarrierInfoManager 6457 .getAnonymousIdentityWith3GppRealm(config); 6458 // Use anonymous@<realm> when pseudonym is not available 6459 config.enterpriseConfig.setAnonymousIdentity(anonAtRealm); 6460 } 6461 } 6462 setConfigurationsPriorToIpClientProvisioning(WifiConfiguration config)6463 private void setConfigurationsPriorToIpClientProvisioning(WifiConfiguration config) { 6464 mIpClient.setHttpProxy(config.getHttpProxy()); 6465 if (!TextUtils.isEmpty(mContext.getResources().getString( 6466 R.string.config_wifi_tcp_buffers))) { 6467 mIpClient.setTcpBufferSizes(mContext.getResources().getString( 6468 R.string.config_wifi_tcp_buffers)); 6469 } 6470 } 6471 startIpClient(WifiConfiguration config, boolean isFilsConnection)6472 private boolean startIpClient(WifiConfiguration config, boolean isFilsConnection) { 6473 if (mIpClient == null) { 6474 return false; 6475 } 6476 6477 final boolean isUsingStaticIp = 6478 (config.getIpAssignment() == IpConfiguration.IpAssignment.STATIC); 6479 final boolean isUsingMacRandomization = 6480 config.macRandomizationSetting 6481 == WifiConfiguration.RANDOMIZATION_PERSISTENT 6482 && isConnectedMacRandomizationEnabled(); 6483 if (mVerboseLoggingEnabled) { 6484 final String key = config.getKey(); 6485 log("startIpClient netId=" + Integer.toString(mLastNetworkId) 6486 + " " + key + " " 6487 + " roam=" + mIsAutoRoaming 6488 + " static=" + isUsingStaticIp 6489 + " randomMac=" + isUsingMacRandomization 6490 + " isFilsConnection=" + isFilsConnection); 6491 } 6492 6493 final MacAddress currentBssid = getCurrentBssid(); 6494 final String l2Key = mLastL2KeyAndGroupHint != null 6495 ? mLastL2KeyAndGroupHint.first : null; 6496 final String groupHint = mLastL2KeyAndGroupHint != null 6497 ? mLastL2KeyAndGroupHint.second : null; 6498 final Layer2Information layer2Info = new Layer2Information(l2Key, groupHint, 6499 currentBssid); 6500 6501 if (isFilsConnection) { 6502 stopIpClient(); 6503 if (isUsingStaticIp) { 6504 mWifiNative.flushAllHlp(mInterfaceName); 6505 return false; 6506 } 6507 setConfigurationsPriorToIpClientProvisioning(config); 6508 final ProvisioningConfiguration.Builder prov = 6509 new ProvisioningConfiguration.Builder() 6510 .withPreDhcpAction() 6511 .withPreconnection() 6512 .withApfCapabilities( 6513 mWifiNative.getApfCapabilities(mInterfaceName)) 6514 .withLayer2Information(layer2Info); 6515 if (isUsingMacRandomization) { 6516 // Use EUI64 address generation for link-local IPv6 addresses. 6517 prov.withRandomMacAddress(); 6518 } 6519 mIpClient.startProvisioning(prov.build()); 6520 } else { 6521 sendNetworkChangeBroadcast(DetailedState.OBTAINING_IPADDR); 6522 // We must clear the config BSSID, as the wifi chipset may decide to roam 6523 // from this point on and having the BSSID specified in the network block would 6524 // cause the roam to fail and the device to disconnect. 6525 clearTargetBssid("ObtainingIpAddress"); 6526 6527 // Stop IpClient in case we're switching from DHCP to static 6528 // configuration or vice versa. 6529 // 6530 // When we transition from static configuration to DHCP in 6531 // particular, we must tell ConnectivityService that we're 6532 // disconnected, because DHCP might take a long time during which 6533 // connectivity APIs such as getActiveNetworkInfo should not return 6534 // CONNECTED. 6535 stopDhcpSetup(); 6536 setConfigurationsPriorToIpClientProvisioning(config); 6537 ScanDetailCache scanDetailCache = 6538 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); 6539 ScanResult scanResult = null; 6540 if (mLastBssid != null) { 6541 if (scanDetailCache != null) { 6542 scanResult = scanDetailCache.getScanResult(mLastBssid); 6543 } 6544 6545 // The cached scan result of connected network would be null at the first 6546 // connection, try to check full scan result list again to look up matched 6547 // scan result associated to the current SSID and BSSID. 6548 if (scanResult == null) { 6549 ScanRequestProxy scanRequestProxy = mWifiInjector.getScanRequestProxy(); 6550 List<ScanResult> scanResults = scanRequestProxy.getScanResults(); 6551 for (ScanResult result : scanResults) { 6552 if (result.SSID.equals(WifiInfo.removeDoubleQuotes(config.SSID)) 6553 && result.BSSID.equals(mLastBssid)) { 6554 scanResult = result; 6555 break; 6556 } 6557 } 6558 } 6559 } 6560 6561 final ProvisioningConfiguration.Builder prov; 6562 ProvisioningConfiguration.ScanResultInfo scanResultInfo = null; 6563 if (scanResult != null) { 6564 final List<ScanResultInfo.InformationElement> ies = 6565 new ArrayList<ScanResultInfo.InformationElement>(); 6566 for (ScanResult.InformationElement ie : scanResult.getInformationElements()) { 6567 ScanResultInfo.InformationElement scanResultInfoIe = 6568 new ScanResultInfo.InformationElement(ie.getId(), ie.getBytes()); 6569 ies.add(scanResultInfoIe); 6570 } 6571 scanResultInfo = new ProvisioningConfiguration.ScanResultInfo(scanResult.SSID, 6572 scanResult.BSSID, ies); 6573 } 6574 6575 if (!isUsingStaticIp) { 6576 prov = new ProvisioningConfiguration.Builder() 6577 .withPreDhcpAction() 6578 .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName)) 6579 .withNetwork(getCurrentNetwork()) 6580 .withDisplayName(config.SSID) 6581 .withScanResultInfo(scanResultInfo) 6582 .withLayer2Information(layer2Info); 6583 } else { 6584 StaticIpConfiguration staticIpConfig = config.getStaticIpConfiguration(); 6585 prov = new ProvisioningConfiguration.Builder() 6586 .withStaticConfiguration(staticIpConfig) 6587 .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName)) 6588 .withNetwork(getCurrentNetwork()) 6589 .withDisplayName(config.SSID) 6590 .withLayer2Information(layer2Info); 6591 } 6592 if (isUsingMacRandomization) { 6593 // Use EUI64 address generation for link-local IPv6 addresses. 6594 prov.withRandomMacAddress(); 6595 } 6596 mIpClient.startProvisioning(prov.build()); 6597 } 6598 6599 return true; 6600 } 6601 6602 } 6603