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.util.KeepalivePacketDataUtil.parseTcpKeepalivePacketData; 20 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE; 21 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT; 22 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY; 23 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_UNWANTED_LOW_RSSI; 24 import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA256; 25 import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384; 26 import static android.net.wifi.WifiManager.WIFI_FEATURE_TDLS; 27 import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE; 28 29 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY; 30 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; 31 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY; 32 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED; 33 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT; 34 import static com.android.server.wifi.WifiSettingsConfigStore.SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS; 35 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STA_FACTORY_MAC_ADDRESS; 36 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__SUPPLICANT_DISCONNECTED; 37 38 import android.annotation.IntDef; 39 import android.annotation.NonNull; 40 import android.annotation.Nullable; 41 import android.annotation.SuppressLint; 42 import android.app.ActivityManager; 43 import android.app.BroadcastOptions; 44 import android.app.admin.SecurityLog; 45 import android.content.BroadcastReceiver; 46 import android.content.Context; 47 import android.content.Intent; 48 import android.content.IntentFilter; 49 import android.net.CaptivePortalData; 50 import android.net.ConnectivityManager; 51 import android.net.DhcpResultsParcelable; 52 import android.net.InvalidPacketException; 53 import android.net.IpConfiguration; 54 import android.net.KeepalivePacketData; 55 import android.net.Layer2PacketParcelable; 56 import android.net.LinkProperties; 57 import android.net.MacAddress; 58 import android.net.NattKeepalivePacketData; 59 import android.net.Network; 60 import android.net.NetworkAgent; 61 import android.net.NetworkAgentConfig; 62 import android.net.NetworkCapabilities; 63 import android.net.NetworkInfo; 64 import android.net.NetworkInfo.DetailedState; 65 import android.net.RouteInfo; 66 import android.net.SocketKeepalive; 67 import android.net.StaticIpConfiguration; 68 import android.net.TcpKeepalivePacketData; 69 import android.net.TcpKeepalivePacketDataParcelable; 70 import android.net.Uri; 71 import android.net.ip.IIpClient; 72 import android.net.ip.IpClientCallbacks; 73 import android.net.ip.IpClientManager; 74 import android.net.networkstack.aidl.dhcp.DhcpOption; 75 import android.net.networkstack.aidl.ip.ReachabilityLossInfoParcelable; 76 import android.net.networkstack.aidl.ip.ReachabilityLossReason; 77 import android.net.shared.Layer2Information; 78 import android.net.shared.ProvisioningConfiguration; 79 import android.net.shared.ProvisioningConfiguration.ScanResultInfo; 80 import android.net.vcn.VcnManager; 81 import android.net.vcn.VcnNetworkPolicyResult; 82 import android.net.wifi.IWifiConnectedNetworkScorer; 83 import android.net.wifi.MloLink; 84 import android.net.wifi.ScanResult; 85 import android.net.wifi.SecurityParams; 86 import android.net.wifi.SupplicantState; 87 import android.net.wifi.WifiAnnotations.WifiStandard; 88 import android.net.wifi.WifiConfiguration; 89 import android.net.wifi.WifiContext; 90 import android.net.wifi.WifiEnterpriseConfig; 91 import android.net.wifi.WifiInfo; 92 import android.net.wifi.WifiManager; 93 import android.net.wifi.WifiManager.DeviceMobilityState; 94 import android.net.wifi.WifiNetworkAgentSpecifier; 95 import android.net.wifi.WifiNetworkSpecifier; 96 import android.net.wifi.WifiSsid; 97 import android.net.wifi.hotspot2.IProvisioningCallback; 98 import android.net.wifi.hotspot2.OsuProvider; 99 import android.net.wifi.nl80211.DeviceWiphyCapabilities; 100 import android.net.wifi.util.ScanResultUtil; 101 import android.os.BatteryStatsManager; 102 import android.os.Build; 103 import android.os.Bundle; 104 import android.os.ConditionVariable; 105 import android.os.IBinder; 106 import android.os.Looper; 107 import android.os.Message; 108 import android.os.Messenger; 109 import android.os.PowerManager; 110 import android.os.Process; 111 import android.os.UserHandle; 112 import android.os.WorkSource; 113 import android.provider.Settings; 114 import android.system.OsConstants; 115 import android.telephony.SubscriptionManager; 116 import android.telephony.TelephonyManager; 117 import android.text.TextUtils; 118 import android.util.ArraySet; 119 import android.util.Log; 120 import android.util.Pair; 121 import android.util.Range; 122 123 import androidx.annotation.RequiresApi; 124 125 import com.android.internal.annotations.VisibleForTesting; 126 import com.android.internal.util.IState; 127 import com.android.internal.util.Protocol; 128 import com.android.internal.util.State; 129 import com.android.internal.util.StateMachine; 130 import com.android.modules.utils.HandlerExecutor; 131 import com.android.modules.utils.build.SdkLevel; 132 import com.android.net.module.util.Inet4AddressUtils; 133 import com.android.net.module.util.MacAddressUtils; 134 import com.android.net.module.util.NetUtils; 135 import com.android.server.wifi.ActiveModeManager.ClientRole; 136 import com.android.server.wifi.MboOceController.BtmFrameData; 137 import com.android.server.wifi.SupplicantStaIfaceHal.QosPolicyRequest; 138 import com.android.server.wifi.SupplicantStaIfaceHal.StaIfaceReasonCode; 139 import com.android.server.wifi.SupplicantStaIfaceHal.StaIfaceStatusCode; 140 import com.android.server.wifi.SupplicantStaIfaceHal.SupplicantEventCode; 141 import com.android.server.wifi.WifiCarrierInfoManager.SimAuthRequestData; 142 import com.android.server.wifi.WifiCarrierInfoManager.SimAuthResponseData; 143 import com.android.server.wifi.WifiNative.RxFateReport; 144 import com.android.server.wifi.WifiNative.TxFateReport; 145 import com.android.server.wifi.hotspot2.AnqpEvent; 146 import com.android.server.wifi.hotspot2.IconEvent; 147 import com.android.server.wifi.hotspot2.NetworkDetail; 148 import com.android.server.wifi.hotspot2.PasspointManager; 149 import com.android.server.wifi.hotspot2.WnmData; 150 import com.android.server.wifi.p2p.WifiP2pServiceImpl; 151 import com.android.server.wifi.proto.WifiStatsLog; 152 import com.android.server.wifi.proto.nano.WifiMetricsProto; 153 import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent; 154 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent; 155 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; 156 import com.android.server.wifi.util.ActionListenerWrapper; 157 import com.android.server.wifi.util.InformationElementUtil; 158 import com.android.server.wifi.util.NativeUtil; 159 import com.android.server.wifi.util.RssiUtil; 160 import com.android.server.wifi.util.StateMachineObituary; 161 import com.android.server.wifi.util.WifiPermissionsUtil; 162 import com.android.wifi.resources.R; 163 164 import java.io.BufferedReader; 165 import java.io.FileDescriptor; 166 import java.io.FileNotFoundException; 167 import java.io.IOException; 168 import java.io.PrintWriter; 169 import java.lang.annotation.Retention; 170 import java.lang.annotation.RetentionPolicy; 171 import java.net.Inet4Address; 172 import java.net.Inet6Address; 173 import java.net.InetAddress; 174 import java.net.URL; 175 import java.time.Duration; 176 import java.util.ArrayList; 177 import java.util.Arrays; 178 import java.util.Collections; 179 import java.util.List; 180 import java.util.Map; 181 import java.util.Objects; 182 import java.util.Set; 183 import java.util.stream.Collectors; 184 185 /** 186 * Implementation of ClientMode. Event handling for Client mode logic is done here, 187 * and all changes in connectivity state are initiated here. 188 * 189 * Note: No external modules should be calling into {@link ClientModeImpl}. Please plumb it via 190 * {@link ClientModeManager} until b/160014176 is fixed. 191 */ 192 public class ClientModeImpl extends StateMachine implements ClientMode { 193 private static final String NETWORKTYPE = "WIFI"; 194 @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE_LOW_MEMORY = 200; 195 @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE = 3000; 196 197 private static final String TAG = "WifiClientModeImpl"; 198 199 private static final int IPCLIENT_STARTUP_TIMEOUT_MS = 2_000; 200 private static final int IPCLIENT_SHUTDOWN_TIMEOUT_MS = 60_000; // 60 seconds 201 private static final int NETWORK_AGENT_TEARDOWN_DELAY_MS = 5_000; // Max teardown delay. 202 @VisibleForTesting public static final long CONNECTING_WATCHDOG_TIMEOUT_MS = 30_000; // 30 secs. 203 @VisibleForTesting 204 public static final String ARP_TABLE_PATH = "/proc/net/arp"; 205 206 private boolean mVerboseLoggingEnabled = false; 207 208 /** 209 * Log with error attribute 210 * 211 * @param s is string log 212 */ 213 @Override loge(String s)214 protected void loge(String s) { 215 Log.e(getTag(), s); 216 } 217 @Override logd(String s)218 protected void logd(String s) { 219 Log.d(getTag(), s); 220 } 221 @Override log(String s)222 protected void log(String s) { 223 Log.d(getTag(), s); 224 } 225 private final WifiContext mContext; 226 private final WifiMetrics mWifiMetrics; 227 private final WifiMonitor mWifiMonitor; 228 private final WifiNative mWifiNative; 229 private final WifiPermissionsUtil mWifiPermissionsUtil; 230 private final WifiConfigManager mWifiConfigManager; 231 private final WifiConnectivityManager mWifiConnectivityManager; 232 private final WifiBlocklistMonitor mWifiBlocklistMonitor; 233 private final WifiDiagnostics mWifiDiagnostics; 234 private final Clock mClock; 235 private final WifiScoreCard mWifiScoreCard; 236 private final WifiHealthMonitor mWifiHealthMonitor; 237 private final WifiScoreReport mWifiScoreReport; 238 private final WifiTrafficPoller mWifiTrafficPoller; 239 private final PasspointManager mPasspointManager; 240 private final WifiDataStall mWifiDataStall; 241 private final RssiMonitor mRssiMonitor; 242 private final LinkProbeManager mLinkProbeManager; 243 private final MboOceController mMboOceController; 244 private final McastLockManagerFilterController mMcastLockManagerFilterController; 245 private final ActivityManager mActivityManager; 246 private final FrameworkFacade mFacade; 247 private final WifiStateTracker mWifiStateTracker; 248 private final WrongPasswordNotifier mWrongPasswordNotifier; 249 private final EapFailureNotifier mEapFailureNotifier; 250 private final SimRequiredNotifier mSimRequiredNotifier; 251 private final ConnectionFailureNotifier mConnectionFailureNotifier; 252 private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; 253 private final ThroughputPredictor mThroughputPredictor; 254 private final DeviceConfigFacade mDeviceConfigFacade; 255 private final ScoringParams mScoringParams; 256 private final WifiThreadRunner mWifiThreadRunner; 257 private final ScanRequestProxy mScanRequestProxy; 258 private final WifiLastResortWatchdog mWifiLastResortWatchdog; 259 private final WakeupController mWakeupController; 260 private final WifiLockManager mWifiLockManager; 261 private final WifiP2pConnection mWifiP2pConnection; 262 private final WifiGlobals mWifiGlobals; 263 private final ClientModeManagerBroadcastQueue mBroadcastQueue; 264 private final TelephonyManager mTelephonyManager; 265 private final WifiSettingsConfigStore mSettingsConfigStore; 266 private final long mId; 267 268 private boolean mScreenOn = false; 269 270 private final String mInterfaceName; 271 private final ConcreteClientModeManager mClientModeManager; 272 273 private final WifiNotificationManager mNotificationManager; 274 private final QosPolicyRequestHandler mQosPolicyRequestHandler; 275 276 private boolean mFailedToResetMacAddress = false; 277 private int mLastSignalLevel = -1; 278 private int mLastTxKbps = -1; 279 private int mLastRxKbps = -1; 280 private int mLastScanRssi = WifiInfo.INVALID_RSSI; 281 private String mLastBssid; 282 // TODO (b/162942761): Ensure this is reset when mTargetNetworkId is set. 283 private int mLastNetworkId; // The network Id we successfully joined 284 // The subId used by WifiConfiguration with SIM credential which was connected successfully 285 private int mLastSubId; 286 private String mLastSimBasedConnectionCarrierName; 287 private URL mTermsAndConditionsUrl; // Indicates that the Passpoint network is captive 288 @Nullable 289 private WifiNative.ConnectionCapabilities mLastConnectionCapabilities; 290 private int mPowerSaveDisableRequests = 0; // mask based on @PowerSaveClientType 291 private boolean mIsUserSelected = false; 292 private boolean mCurrentConnectionDetectedCaptivePortal; 293 getTag()294 private String getTag() { 295 return TAG + "[" + mId + ":" + (mInterfaceName == null ? "unknown" : mInterfaceName) + "]"; 296 } 297 298 private boolean mEnableRssiPolling = false; 299 private int mRssiPollToken = 0; 300 301 private PowerManager.WakeLock mSuspendWakeLock; 302 303 /** 304 * Value to set in wpa_supplicant "bssid" field when we don't want to restrict connection to 305 * a specific AP. 306 */ 307 public static final String SUPPLICANT_BSSID_ANY = "any"; 308 309 /** 310 * The link properties of the wifi interface. 311 * Do not modify this directly; use updateLinkProperties instead. 312 */ 313 private LinkProperties mLinkProperties; 314 315 private final Object mDhcpResultsParcelableLock = new Object(); 316 @NonNull 317 private DhcpResultsParcelable mDhcpResultsParcelable = new DhcpResultsParcelable(); 318 319 // NOTE: Do not return to clients - see getConnectionInfo() 320 private final ExtendedWifiInfo mWifiInfo; 321 // TODO : remove this member. It should be possible to only call sendNetworkChangeBroadcast when 322 // the state actually changed, and to deduce the state of the agent from the state of the 323 // machine when generating the NetworkInfo for the broadcast. 324 private DetailedState mNetworkAgentState; 325 private final SupplicantStateTracker mSupplicantStateTracker; 326 327 // Indicates that framework is attempting to roam, set true on CMD_START_ROAM, set false when 328 // wifi connects or fails to connect 329 private boolean mIsAutoRoaming = false; 330 331 // Indicates that driver is attempting to allowlist roaming, set true on allowlist roam BSSID 332 // associated, set false when wifi connects or fails to connect 333 private boolean mIsLinkedNetworkRoaming = false; 334 335 // Roaming failure count 336 private int mRoamFailCount = 0; 337 338 // This is the BSSID we are trying to associate to, it can be set to SUPPLICANT_BSSID_ANY 339 // if we havent selected a BSSID for joining. 340 private String mTargetBssid = SUPPLICANT_BSSID_ANY; 341 private int mTargetBand = ScanResult.UNSPECIFIED; 342 // This one is used to track the current target network ID. This is used for error 343 // handling during connection setup since many error message from supplicant does not report 344 // SSID. Once connected, it will be set to invalid 345 // TODO (b/162942761): Ensure this is reset when mLastNetworkId is set. 346 private int mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 347 private WifiConfiguration mTargetWifiConfiguration = null; 348 @Nullable private VcnManager mVcnManager = null; 349 350 // This is is used to track the number of TDLS peers enabled in driver via enableTdls() 351 private Set<String> mEnabledTdlsPeers = new ArraySet<>(); 352 353 /** 354 * Method to clear {@link #mTargetBssid} and reset the current connected network's 355 * bssid in wpa_supplicant after a roam/connect attempt. 356 */ clearTargetBssid(String dbg)357 public boolean clearTargetBssid(String dbg) { 358 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 359 if (config == null) { 360 return false; 361 } 362 String bssid = SUPPLICANT_BSSID_ANY; 363 if (config.BSSID != null) { 364 bssid = config.BSSID; 365 if (mVerboseLoggingEnabled) { 366 Log.d(getTag(), "force BSSID to " + bssid + "due to config"); 367 } 368 } 369 if (mVerboseLoggingEnabled) { 370 logd(dbg + " clearTargetBssid " + bssid + " key=" + config.getProfileKey()); 371 } 372 mTargetBssid = bssid; 373 return mWifiNative.setNetworkBSSID(mInterfaceName, bssid); 374 } 375 376 /** 377 * Set Config's default BSSID (for association purpose) and {@link #mTargetBssid} 378 * @param config config need set BSSID 379 * @param bssid default BSSID to assocaite with when connect to this network 380 * @return false -- does not change the current default BSSID of the configure 381 * true -- change the current default BSSID of the configur 382 */ setTargetBssid(WifiConfiguration config, String bssid)383 private boolean setTargetBssid(WifiConfiguration config, String bssid) { 384 if (config == null || bssid == null) { 385 return false; 386 } 387 if (config.BSSID != null) { 388 bssid = config.BSSID; 389 if (mVerboseLoggingEnabled) { 390 Log.d(getTag(), "force BSSID to " + bssid + "due to config"); 391 } 392 } 393 if (mVerboseLoggingEnabled) { 394 Log.d(getTag(), "setTargetBssid set to " + bssid + " key=" 395 + config.getProfileKey()); 396 } 397 mTargetBssid = bssid; 398 config.getNetworkSelectionStatus().setNetworkSelectionBSSID(bssid); 399 return true; 400 } 401 402 private volatile IpClientManager mIpClient; 403 private IpClientCallbacksImpl mIpClientCallbacks; 404 405 private final WifiNetworkFactory mNetworkFactory; 406 private final UntrustedWifiNetworkFactory mUntrustedNetworkFactory; 407 private final OemWifiNetworkFactory mOemWifiNetworkFactory; 408 private final RestrictedWifiNetworkFactory mRestrictedWifiNetworkFactory; 409 @VisibleForTesting 410 InsecureEapNetworkHandler mInsecureEapNetworkHandler; 411 boolean mLeafCertSent; 412 @VisibleForTesting 413 InsecureEapNetworkHandler.InsecureEapNetworkHandlerCallbacks 414 mInsecureEapNetworkHandlerCallbacksImpl; 415 private final MultiInternetManager mMultiInternetManager; 416 417 @VisibleForTesting 418 @Nullable 419 WifiNetworkAgent mNetworkAgent; 420 421 422 // Used to filter out requests we couldn't possibly satisfy. 423 private final NetworkCapabilities mNetworkCapabilitiesFilter; 424 425 /* The base for wifi message types */ 426 static final int BASE = Protocol.BASE_WIFI; 427 428 /* BT connection state changed, e.g., connected/disconnected */ 429 static final int CMD_BLUETOOTH_CONNECTION_STATE_CHANGE = BASE + 31; 430 431 /* Supplicant commands after driver start*/ 432 /* Disconnect from a network */ 433 static final int CMD_DISCONNECT = BASE + 73; 434 /* Reconnect to a network */ 435 static final int CMD_RECONNECT = BASE + 74; 436 /* Reassociate to a network */ 437 static final int CMD_REASSOCIATE = BASE + 75; 438 439 /* Enables RSSI poll */ 440 static final int CMD_ENABLE_RSSI_POLL = BASE + 82; 441 /* RSSI poll */ 442 static final int CMD_RSSI_POLL = BASE + 83; 443 /** Runs RSSI poll once */ 444 static final int CMD_ONESHOT_RSSI_POLL = BASE + 84; 445 /* Enable suspend mode optimizations in the driver */ 446 static final int CMD_SET_SUSPEND_OPT_ENABLED = BASE + 86; 447 448 /** 449 * Watchdog for protecting against b/16823537 450 * Leave time for 4-way handshake to succeed 451 */ 452 static final int ROAM_GUARD_TIMER_MSEC = 15000; 453 454 int mRoamWatchdogCount = 0; 455 /* Roam state watchdog */ 456 static final int CMD_ROAM_WATCHDOG_TIMER = BASE + 94; 457 /* Screen change intent handling */ 458 static final int CMD_SCREEN_STATE_CHANGED = BASE + 95; 459 460 /* Disconnecting state watchdog */ 461 static final int CMD_CONNECTING_WATCHDOG_TIMER = BASE + 96; 462 463 /* SIM is removed; reset any cached data for it */ 464 static final int CMD_RESET_SIM_NETWORKS = BASE + 101; 465 466 /** 467 * Update the OOB Pseudonym which is retrieved from the carrier's entitlement server for 468 * EAP-SIM/AKA/AKA' into supplicant. 469 */ 470 static final int CMD_UPDATE_OOB_PSEUDONYM = BASE + 102; 471 472 @Retention(RetentionPolicy.SOURCE) 473 @IntDef(prefix = {"RESET_SIM_REASON_"}, 474 value = { 475 RESET_SIM_REASON_SIM_REMOVED, 476 RESET_SIM_REASON_SIM_INSERTED, 477 RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED}) 478 @interface ResetSimReason {} 479 static final int RESET_SIM_REASON_SIM_REMOVED = 0; 480 static final int RESET_SIM_REASON_SIM_INSERTED = 1; 481 static final int RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED = 2; 482 483 /** Connecting watchdog timeout counter */ 484 private int mConnectingWatchdogCount = 0; 485 486 /* We now have a valid IP configuration. */ 487 static final int CMD_IP_CONFIGURATION_SUCCESSFUL = BASE + 138; 488 /* We no longer have a valid IP configuration. */ 489 static final int CMD_IP_CONFIGURATION_LOST = BASE + 139; 490 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 491 static final int CMD_UPDATE_LINKPROPERTIES = BASE + 140; 492 493 static final int CMD_START_CONNECT = BASE + 143; 494 495 @VisibleForTesting 496 public static final int NETWORK_STATUS_UNWANTED_DISCONNECT = 0; 497 private static final int NETWORK_STATUS_UNWANTED_VALIDATION_FAILED = 1; 498 @VisibleForTesting 499 public static final int NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN = 2; 500 501 static final int CMD_UNWANTED_NETWORK = BASE + 144; 502 503 static final int CMD_START_ROAM = BASE + 145; 504 505 static final int CMD_NETWORK_STATUS = BASE + 148; 506 507 /* A layer 3 neighbor on the Wi-Fi link became unreachable. */ 508 static final int CMD_IP_REACHABILITY_LOST = BASE + 149; 509 510 static final int CMD_IP_REACHABILITY_FAILURE = BASE + 150; 511 512 static final int CMD_ACCEPT_UNVALIDATED = BASE + 153; 513 514 /* used to offload sending IP packet */ 515 static final int CMD_START_IP_PACKET_OFFLOAD = BASE + 160; 516 517 /* used to stop offload sending IP packet */ 518 static final int CMD_STOP_IP_PACKET_OFFLOAD = BASE + 161; 519 520 /* Used to time out the creation of an IpClient instance. */ 521 static final int CMD_IPCLIENT_STARTUP_TIMEOUT = BASE + 165; 522 523 /** 524 * Used to handle messages bounced between ClientModeImpl and IpClient. 525 */ 526 static final int CMD_IPV4_PROVISIONING_SUCCESS = BASE + 200; 527 static final int CMD_IPV4_PROVISIONING_FAILURE = BASE + 201; 528 529 /* Push a new APF program to the HAL */ 530 static final int CMD_INSTALL_PACKET_FILTER = BASE + 202; 531 532 /* Enable/disable fallback packet filtering */ 533 static final int CMD_SET_FALLBACK_PACKET_FILTERING = BASE + 203; 534 535 /* Enable/disable Neighbor Discovery offload functionality. */ 536 static final int CMD_CONFIG_ND_OFFLOAD = BASE + 204; 537 538 /* Read the APF program & data buffer */ 539 static final int CMD_READ_PACKET_FILTER = BASE + 208; 540 541 /** Used to add packet filter to apf. */ 542 static final int CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF = BASE + 209; 543 544 /** Used to remove packet filter from apf. */ 545 static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF = BASE + 210; 546 547 /** 548 * Set maximum acceptable DTIM multiplier to hardware driver. Any multiplier larger than the 549 * maximum value must not be accepted, it will cause packet loss higher than what the system 550 * can accept, which will cause unexpected behavior for apps, and may interrupt the network 551 * connection. 552 */ 553 static final int CMD_SET_MAX_DTIM_MULTIPLIER = BASE + 211; 554 555 @VisibleForTesting 556 static final int CMD_PRE_DHCP_ACTION = BASE + 255; 557 private static final int CMD_PRE_DHCP_ACTION_COMPLETE = BASE + 256; 558 private static final int CMD_POST_DHCP_ACTION = BASE + 257; 559 560 private static final int CMD_CONNECT_NETWORK = BASE + 258; 561 private static final int CMD_SAVE_NETWORK = BASE + 259; 562 563 /* Start connection to FILS AP*/ 564 static final int CMD_START_FILS_CONNECTION = BASE + 262; 565 566 static final int CMD_IPCLIENT_CREATED = BASE + 300; 567 568 @VisibleForTesting 569 static final int CMD_ACCEPT_EAP_SERVER_CERTIFICATE = BASE + 301; 570 571 @VisibleForTesting 572 static final int CMD_REJECT_EAP_INSECURE_CONNECTION = BASE + 302; 573 574 /* Tracks if suspend optimizations need to be disabled by DHCP, 575 * screen or due to high perf mode. 576 * When any of them needs to disable it, we keep the suspend optimizations 577 * disabled 578 */ 579 private int mSuspendOptNeedsDisabled = 0; 580 581 private static final int SUSPEND_DUE_TO_DHCP = 1; 582 private static final int SUSPEND_DUE_TO_HIGH_PERF = 1 << 1; 583 private static final int SUSPEND_DUE_TO_SCREEN = 1 << 2; 584 585 /** @see #isRecentlySelectedByTheUser */ 586 @VisibleForTesting 587 public static final int LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS = 30 * 1000; 588 589 /* Tracks if user has enabled Connected Mac Randomization through settings */ 590 591 int mRunningBeaconCount = 0; 592 593 /* Parent state where connections are allowed */ 594 private State mConnectableState; 595 /* Connecting/Connected to an access point */ 596 private State mConnectingOrConnectedState; 597 /* Connecting to an access point */ 598 private State mL2ConnectingState; 599 /* Connected at 802.11 (L2) level */ 600 private State mL2ConnectedState; 601 /* Waiting for IpClient recreation completes */ 602 private State mWaitBeforeL3ProvisioningState; 603 /* fetching IP after connection to access point (assoc+auth complete) */ 604 private State mL3ProvisioningState; 605 /* Connected with IP addr */ 606 private State mL3ConnectedState; 607 /* Roaming */ 608 private State mRoamingState; 609 /* Network is not connected, supplicant assoc+auth is not complete */ 610 private State mDisconnectedState; 611 612 /* 613 * FILS connection related variables. 614 */ 615 /* To indicate to IpClient whether HLP IEs were included or not in assoc request */ 616 private boolean mSentHLPs = false; 617 /* Tracks IpClient start state until (FILS_)NETWORK_CONNECTION_EVENT event */ 618 private boolean mIpClientWithPreConnection = false; 619 620 /** 621 * Work source to use to blame usage on the WiFi service 622 */ 623 public static final WorkSource WIFI_WORK_SOURCE = new WorkSource(Process.WIFI_UID); 624 625 private final BatteryStatsManager mBatteryStatsManager; 626 627 private final WifiCarrierInfoManager mWifiCarrierInfoManager; 628 629 private final WifiPseudonymManager mWifiPseudonymManager; 630 631 private final OnNetworkUpdateListener mOnNetworkUpdateListener; 632 633 private final OnCarrierOffloadDisabledListener mOnCarrierOffloadDisabledListener; 634 635 private final ClientModeImplMonitor mCmiMonitor; 636 637 private final WifiNetworkSelector mWifiNetworkSelector; 638 639 private final WifiInjector mWifiInjector; 640 641 // Permanently disable a network due to no internet if the estimated probability of having 642 // internet is less than this value. 643 @VisibleForTesting 644 public static final int PROBABILITY_WITH_INTERNET_TO_PERMANENTLY_DISABLE_NETWORK = 60; 645 // Disable a network permanently due to wrong password even if the network had successfully 646 // connected before wrong password failure on this network reached this threshold. 647 public static final int THRESHOLD_TO_PERM_WRONG_PASSWORD = 3; 648 649 // Maximum duration to continue to log Wifi usability stats after a data stall is triggered. 650 @VisibleForTesting 651 public static final long DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS = 30 * 1000; 652 private long mDataStallTriggerTimeMs = -1; 653 private int mLastStatusDataStall = WifiIsUnusableEvent.TYPE_UNKNOWN; 654 655 @Nullable 656 private StateMachineObituary mObituary = null; 657 658 @Nullable 659 private WifiVcnNetworkPolicyChangeListener mVcnPolicyChangeListener; 660 661 /** NETWORK_NOT_FOUND_EVENT event counter */ 662 private int mNetworkNotFoundEventCount = 0; 663 664 private final WifiPseudonymManager.PseudonymUpdatingListener mPseudonymUpdatingListener; 665 666 private final ApplicationQosPolicyRequestHandler mApplicationQosPolicyRequestHandler; 667 668 669 /** Note that this constructor will also start() the StateMachine. */ ClientModeImpl( @onNull WifiContext context, @NonNull WifiMetrics wifiMetrics, @NonNull Clock clock, @NonNull WifiScoreCard wifiScoreCard, @NonNull WifiStateTracker wifiStateTracker, @NonNull WifiPermissionsUtil wifiPermissionsUtil, @NonNull WifiConfigManager wifiConfigManager, @NonNull PasspointManager passpointManager, @NonNull WifiMonitor wifiMonitor, @NonNull WifiDiagnostics wifiDiagnostics, @NonNull WifiDataStall wifiDataStall, @NonNull ScoringParams scoringParams, @NonNull WifiThreadRunner wifiThreadRunner, @NonNull WifiNetworkSuggestionsManager wifiNetworkSuggestionsManager, @NonNull WifiHealthMonitor wifiHealthMonitor, @NonNull ThroughputPredictor throughputPredictor, @NonNull DeviceConfigFacade deviceConfigFacade, @NonNull ScanRequestProxy scanRequestProxy, @NonNull ExtendedWifiInfo wifiInfo, @NonNull WifiConnectivityManager wifiConnectivityManager, @NonNull WifiBlocklistMonitor wifiBlocklistMonitor, @NonNull ConnectionFailureNotifier connectionFailureNotifier, @NonNull NetworkCapabilities networkCapabilitiesFilter, @NonNull WifiNetworkFactory networkFactory, @NonNull UntrustedWifiNetworkFactory untrustedWifiNetworkFactory, @NonNull OemWifiNetworkFactory oemPaidWifiNetworkFactory, @NonNull RestrictedWifiNetworkFactory restrictedWifiNetworkFactory, @NonNull MultiInternetManager multiInternetManager, @NonNull WifiLastResortWatchdog wifiLastResortWatchdog, @NonNull WakeupController wakeupController, @NonNull WifiLockManager wifiLockManager, @NonNull FrameworkFacade facade, @NonNull Looper looper, @NonNull WifiNative wifiNative, @NonNull WrongPasswordNotifier wrongPasswordNotifier, @NonNull WifiTrafficPoller wifiTrafficPoller, @NonNull LinkProbeManager linkProbeManager, long id, @NonNull BatteryStatsManager batteryStatsManager, @NonNull SupplicantStateTracker supplicantStateTracker, @NonNull MboOceController mboOceController, @NonNull WifiCarrierInfoManager wifiCarrierInfoManager, @NonNull WifiPseudonymManager wifiPseudonymManager, @NonNull EapFailureNotifier eapFailureNotifier, @NonNull SimRequiredNotifier simRequiredNotifier, @NonNull WifiScoreReport wifiScoreReport, @NonNull WifiP2pConnection wifiP2pConnection, @NonNull WifiGlobals wifiGlobals, @NonNull String ifaceName, @NonNull ConcreteClientModeManager clientModeManager, @NonNull ClientModeImplMonitor cmiMonitor, @NonNull ClientModeManagerBroadcastQueue broadcastQueue, @NonNull WifiNetworkSelector wifiNetworkSelector, @NonNull TelephonyManager telephonyManager, @NonNull WifiInjector wifiInjector, @NonNull WifiSettingsConfigStore settingsConfigStore, boolean verboseLoggingEnabled, @NonNull WifiNotificationManager wifiNotificationManager)670 public ClientModeImpl( 671 @NonNull WifiContext context, 672 @NonNull WifiMetrics wifiMetrics, 673 @NonNull Clock clock, 674 @NonNull WifiScoreCard wifiScoreCard, 675 @NonNull WifiStateTracker wifiStateTracker, 676 @NonNull WifiPermissionsUtil wifiPermissionsUtil, 677 @NonNull WifiConfigManager wifiConfigManager, 678 @NonNull PasspointManager passpointManager, 679 @NonNull WifiMonitor wifiMonitor, 680 @NonNull WifiDiagnostics wifiDiagnostics, 681 @NonNull WifiDataStall wifiDataStall, 682 @NonNull ScoringParams scoringParams, 683 @NonNull WifiThreadRunner wifiThreadRunner, 684 @NonNull WifiNetworkSuggestionsManager wifiNetworkSuggestionsManager, 685 @NonNull WifiHealthMonitor wifiHealthMonitor, 686 @NonNull ThroughputPredictor throughputPredictor, 687 @NonNull DeviceConfigFacade deviceConfigFacade, 688 @NonNull ScanRequestProxy scanRequestProxy, 689 @NonNull ExtendedWifiInfo wifiInfo, 690 @NonNull WifiConnectivityManager wifiConnectivityManager, 691 @NonNull WifiBlocklistMonitor wifiBlocklistMonitor, 692 @NonNull ConnectionFailureNotifier connectionFailureNotifier, 693 @NonNull NetworkCapabilities networkCapabilitiesFilter, 694 @NonNull WifiNetworkFactory networkFactory, 695 @NonNull UntrustedWifiNetworkFactory untrustedWifiNetworkFactory, 696 @NonNull OemWifiNetworkFactory oemPaidWifiNetworkFactory, 697 @NonNull RestrictedWifiNetworkFactory restrictedWifiNetworkFactory, 698 @NonNull MultiInternetManager multiInternetManager, 699 @NonNull WifiLastResortWatchdog wifiLastResortWatchdog, 700 @NonNull WakeupController wakeupController, 701 @NonNull WifiLockManager wifiLockManager, 702 @NonNull FrameworkFacade facade, 703 @NonNull Looper looper, 704 @NonNull WifiNative wifiNative, 705 @NonNull WrongPasswordNotifier wrongPasswordNotifier, 706 @NonNull WifiTrafficPoller wifiTrafficPoller, 707 @NonNull LinkProbeManager linkProbeManager, 708 long id, 709 @NonNull BatteryStatsManager batteryStatsManager, 710 @NonNull SupplicantStateTracker supplicantStateTracker, 711 @NonNull MboOceController mboOceController, 712 @NonNull WifiCarrierInfoManager wifiCarrierInfoManager, 713 @NonNull WifiPseudonymManager wifiPseudonymManager, 714 @NonNull EapFailureNotifier eapFailureNotifier, 715 @NonNull SimRequiredNotifier simRequiredNotifier, 716 @NonNull WifiScoreReport wifiScoreReport, 717 @NonNull WifiP2pConnection wifiP2pConnection, 718 @NonNull WifiGlobals wifiGlobals, 719 @NonNull String ifaceName, 720 @NonNull ConcreteClientModeManager clientModeManager, 721 @NonNull ClientModeImplMonitor cmiMonitor, 722 @NonNull ClientModeManagerBroadcastQueue broadcastQueue, 723 @NonNull WifiNetworkSelector wifiNetworkSelector, 724 @NonNull TelephonyManager telephonyManager, 725 @NonNull WifiInjector wifiInjector, 726 @NonNull WifiSettingsConfigStore settingsConfigStore, 727 boolean verboseLoggingEnabled, 728 @NonNull WifiNotificationManager wifiNotificationManager) { 729 super(TAG, looper); 730 mWifiMetrics = wifiMetrics; 731 mClock = clock; 732 mWifiScoreCard = wifiScoreCard; 733 mContext = context; 734 mFacade = facade; 735 mWifiNative = wifiNative; 736 mWrongPasswordNotifier = wrongPasswordNotifier; 737 mId = id; 738 mEapFailureNotifier = eapFailureNotifier; 739 mSimRequiredNotifier = simRequiredNotifier; 740 mWifiTrafficPoller = wifiTrafficPoller; 741 mLinkProbeManager = linkProbeManager; 742 mMboOceController = mboOceController; 743 mWifiCarrierInfoManager = wifiCarrierInfoManager; 744 mWifiPseudonymManager = wifiPseudonymManager; 745 mBroadcastQueue = broadcastQueue; 746 mNetworkAgentState = DetailedState.DISCONNECTED; 747 748 mBatteryStatsManager = batteryStatsManager; 749 mWifiStateTracker = wifiStateTracker; 750 751 mWifiPermissionsUtil = wifiPermissionsUtil; 752 mWifiConfigManager = wifiConfigManager; 753 754 mPasspointManager = passpointManager; 755 756 mWifiMonitor = wifiMonitor; 757 mWifiDiagnostics = wifiDiagnostics; 758 mWifiDataStall = wifiDataStall; 759 mThroughputPredictor = throughputPredictor; 760 mDeviceConfigFacade = deviceConfigFacade; 761 762 mWifiInfo = wifiInfo; 763 mSupplicantStateTracker = supplicantStateTracker; 764 mWifiConnectivityManager = wifiConnectivityManager; 765 mWifiBlocklistMonitor = wifiBlocklistMonitor; 766 mConnectionFailureNotifier = connectionFailureNotifier; 767 768 mLinkProperties = new LinkProperties(); 769 mMcastLockManagerFilterController = new McastLockManagerFilterController(); 770 mActivityManager = context.getSystemService(ActivityManager.class); 771 772 mLastBssid = null; 773 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 774 mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 775 mLastSimBasedConnectionCarrierName = null; 776 mLastSignalLevel = -1; 777 778 mScoringParams = scoringParams; 779 mWifiThreadRunner = wifiThreadRunner; 780 mScanRequestProxy = scanRequestProxy; 781 mWifiScoreReport = wifiScoreReport; 782 783 mNetworkCapabilitiesFilter = networkCapabilitiesFilter; 784 mNetworkFactory = networkFactory; 785 786 mUntrustedNetworkFactory = untrustedWifiNetworkFactory; 787 mOemWifiNetworkFactory = oemPaidWifiNetworkFactory; 788 mRestrictedWifiNetworkFactory = restrictedWifiNetworkFactory; 789 mMultiInternetManager = multiInternetManager; 790 791 mWifiLastResortWatchdog = wifiLastResortWatchdog; 792 mWakeupController = wakeupController; 793 mWifiLockManager = wifiLockManager; 794 795 mWifiNetworkSuggestionsManager = wifiNetworkSuggestionsManager; 796 mWifiHealthMonitor = wifiHealthMonitor; 797 mWifiP2pConnection = wifiP2pConnection; 798 mWifiGlobals = wifiGlobals; 799 800 mInterfaceName = ifaceName; 801 mClientModeManager = clientModeManager; 802 mCmiMonitor = cmiMonitor; 803 mTelephonyManager = telephonyManager; 804 mSettingsConfigStore = settingsConfigStore; 805 updateInterfaceCapabilities(); 806 807 PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 808 809 mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend"); 810 mSuspendWakeLock.setReferenceCounted(false); 811 812 mOnNetworkUpdateListener = new OnNetworkUpdateListener(); 813 mWifiConfigManager.addOnNetworkUpdateListener(mOnNetworkUpdateListener); 814 815 mOnCarrierOffloadDisabledListener = new OnCarrierOffloadDisabledListener(); 816 mWifiCarrierInfoManager.addOnCarrierOffloadDisabledListener( 817 mOnCarrierOffloadDisabledListener); 818 819 mWifiNetworkSelector = wifiNetworkSelector; 820 mWifiInjector = wifiInjector; 821 mQosPolicyRequestHandler = new QosPolicyRequestHandler(mInterfaceName, mWifiNative, this, 822 mWifiInjector.getWifiHandlerThread()); 823 824 mRssiMonitor = new RssiMonitor(mWifiGlobals, mWifiThreadRunner, mWifiInfo, mWifiNative, 825 mInterfaceName, 826 () -> { 827 updateCapabilities(); 828 updateCurrentConnectionInfo(); 829 }, 830 mDeviceConfigFacade); 831 832 enableVerboseLogging(verboseLoggingEnabled); 833 834 mNotificationManager = wifiNotificationManager; 835 mInsecureEapNetworkHandlerCallbacksImpl = 836 new InsecureEapNetworkHandler.InsecureEapNetworkHandlerCallbacks() { 837 @Override 838 public void onAccept(String ssid, int networkId) { 839 log("Accept Root CA cert for " + ssid); 840 sendMessage(CMD_ACCEPT_EAP_SERVER_CERTIFICATE, networkId); 841 } 842 843 @Override 844 public void onReject(String ssid, boolean disconnectRequired) { 845 log("Reject Root CA cert for " + ssid); 846 sendMessage(CMD_REJECT_EAP_INSECURE_CONNECTION, 847 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_REJECTED_BY_USER, 848 disconnectRequired ? 1 : 0, ssid); 849 } 850 851 @Override 852 public void onError(String ssid) { 853 log("Insecure EAP network error for " + ssid); 854 sendMessage(CMD_REJECT_EAP_INSECURE_CONNECTION, 855 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE, 856 0, ssid); 857 }}; 858 mInsecureEapNetworkHandler = new InsecureEapNetworkHandler( 859 mContext, 860 mWifiConfigManager, 861 mWifiNative, 862 mFacade, 863 mNotificationManager, 864 mWifiInjector.getWifiDialogManager(), 865 isTrustOnFirstUseSupported(), 866 mWifiGlobals.isInsecureEnterpriseConfigurationAllowed(), 867 mInsecureEapNetworkHandlerCallbacksImpl, 868 mInterfaceName, 869 getHandler()); 870 871 mPseudonymUpdatingListener = this::updatePseudonymFromOob; 872 mApplicationQosPolicyRequestHandler = mWifiInjector.getApplicationQosPolicyRequestHandler(); 873 874 final int threshold = mContext.getResources().getInteger( 875 R.integer.config_wifiConfigurationWifiRunnerThresholdInMs); 876 mConnectableState = new ConnectableState(threshold); 877 mConnectingOrConnectedState = new ConnectingOrConnectedState(threshold); 878 mL2ConnectingState = new L2ConnectingState(threshold); 879 mL2ConnectedState = new L2ConnectedState(threshold); 880 mWaitBeforeL3ProvisioningState = new WaitBeforeL3ProvisioningState(threshold); 881 mL3ProvisioningState = new L3ProvisioningState(threshold); 882 mL3ConnectedState = new L3ConnectedState(threshold); 883 mRoamingState = new RoamingState(threshold); 884 mDisconnectedState = new DisconnectedState(threshold); 885 886 addState(mConnectableState); { 887 addState(mConnectingOrConnectedState, mConnectableState); { 888 addState(mL2ConnectingState, mConnectingOrConnectedState); 889 addState(mL2ConnectedState, mConnectingOrConnectedState); { 890 addState(mWaitBeforeL3ProvisioningState, mL2ConnectedState); 891 addState(mL3ProvisioningState, mL2ConnectedState); 892 addState(mL3ConnectedState, mL2ConnectedState); 893 addState(mRoamingState, mL2ConnectedState); 894 } 895 } 896 addState(mDisconnectedState, mConnectableState); 897 } 898 899 setInitialState(mDisconnectedState); 900 901 setLogOnlyTransitions(false); 902 903 // Start the StateMachine 904 start(); 905 906 // update with initial role for ConcreteClientModeManager 907 onRoleChanged(); 908 // Update current connection wifiInfo 909 updateCurrentConnectionInfo(); 910 } 911 912 private static final int[] WIFI_MONITOR_EVENTS = { 913 WifiMonitor.TARGET_BSSID_EVENT, 914 WifiMonitor.ASSOCIATED_BSSID_EVENT, 915 WifiMonitor.ANQP_DONE_EVENT, 916 WifiMonitor.ASSOCIATION_REJECTION_EVENT, 917 WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 918 WifiMonitor.GAS_QUERY_DONE_EVENT, 919 WifiMonitor.GAS_QUERY_START_EVENT, 920 WifiMonitor.HS20_REMEDIATION_EVENT, 921 WifiMonitor.HS20_DEAUTH_IMMINENT_EVENT, 922 WifiMonitor.HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT, 923 WifiMonitor.NETWORK_CONNECTION_EVENT, 924 WifiMonitor.NETWORK_DISCONNECTION_EVENT, 925 WifiMonitor.RX_HS20_ANQP_ICON_EVENT, 926 WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 927 WifiMonitor.SUP_REQUEST_IDENTITY, 928 WifiMonitor.SUP_REQUEST_SIM_AUTH, 929 WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, 930 WifiMonitor.TRANSITION_DISABLE_INDICATION, 931 WifiMonitor.NETWORK_NOT_FOUND_EVENT, 932 WifiMonitor.TOFU_CERTIFICATE_EVENT, 933 WifiMonitor.AUXILIARY_SUPPLICANT_EVENT, 934 WifiMonitor.QOS_POLICY_RESET_EVENT, 935 WifiMonitor.QOS_POLICY_REQUEST_EVENT, 936 WifiMonitor.BSS_FREQUENCY_CHANGED_EVENT, 937 }; 938 registerForWifiMonitorEvents()939 private void registerForWifiMonitorEvents() { 940 for (int event : WIFI_MONITOR_EVENTS) { 941 mWifiMonitor.registerHandler(mInterfaceName, event, getHandler()); 942 } 943 944 mWifiMetrics.registerForWifiMonitorEvents(mInterfaceName); 945 mWifiLastResortWatchdog.registerForWifiMonitorEvents(mInterfaceName); 946 } 947 deregisterForWifiMonitorEvents()948 private void deregisterForWifiMonitorEvents() { 949 for (int event : WIFI_MONITOR_EVENTS) { 950 mWifiMonitor.deregisterHandler(mInterfaceName, event, getHandler()); 951 } 952 953 mWifiMetrics.deregisterForWifiMonitorEvents(mInterfaceName); 954 mWifiLastResortWatchdog.deregisterForWifiMonitorEvents(mInterfaceName); 955 } 956 isValidBssid(String bssidStr)957 private static boolean isValidBssid(String bssidStr) { 958 try { 959 MacAddress bssid = MacAddress.fromString(bssidStr); 960 return !Objects.equals(bssid, WifiManager.ALL_ZEROS_MAC_ADDRESS); 961 } catch (IllegalArgumentException e) { 962 return false; 963 } 964 } 965 setMulticastFilter(boolean enabled)966 private void setMulticastFilter(boolean enabled) { 967 if (mIpClient != null) { 968 mIpClient.setMulticastFilter(enabled); 969 } 970 } 971 972 /* 973 * Log wifi event to SecurityLog if the event occurred on a managed network. 974 */ logEventIfManagedNetwork(@ullable WifiConfiguration config, @SupplicantEventCode int eventCode, MacAddress bssid, String reasonString)975 private void logEventIfManagedNetwork(@Nullable WifiConfiguration config, 976 @SupplicantEventCode int eventCode, MacAddress bssid, String reasonString) { 977 if (config == null || !mWifiPermissionsUtil 978 .isAdmin(config.creatorUid, config.creatorName)) { 979 return; 980 } 981 982 if (SdkLevel.isAtLeastT()) { 983 int numRedactedOctets = mContext.getResources() 984 .getInteger(R.integer.config_wifiNumMaskedBssidOctetsInSecurityLog); 985 String redactedBssid = ScanResultUtil.redactBssid(bssid, numRedactedOctets); 986 if (eventCode == SupplicantStaIfaceHal.SUPPLICANT_EVENT_DISCONNECTED) { 987 SecurityLog.writeEvent(SecurityLog.TAG_WIFI_DISCONNECTION, redactedBssid, 988 reasonString); 989 } else { 990 SecurityLog.writeEvent(SecurityLog.TAG_WIFI_CONNECTION, redactedBssid, 991 SupplicantStaIfaceHal.supplicantEventCodeToString(eventCode), reasonString); 992 } 993 } 994 } 995 clearQueuedQosMessages()996 protected void clearQueuedQosMessages() { 997 removeMessages(WifiMonitor.QOS_POLICY_RESET_EVENT); 998 removeMessages(WifiMonitor.QOS_POLICY_REQUEST_EVENT); 999 } 1000 1001 /** 1002 * Class to implement the MulticastLockManager.FilterController callback. 1003 */ 1004 class McastLockManagerFilterController implements WifiMulticastLockManager.FilterController { 1005 /** 1006 * Start filtering Multicast v4 packets 1007 */ startFilteringMulticastPackets()1008 public void startFilteringMulticastPackets() { 1009 setMulticastFilter(true); 1010 } 1011 1012 /** 1013 * Stop filtering Multicast v4 packets 1014 */ stopFilteringMulticastPackets()1015 public void stopFilteringMulticastPackets() { 1016 setMulticastFilter(false); 1017 } 1018 } 1019 1020 class IpClientCallbacksImpl extends IpClientCallbacks { 1021 private final ConditionVariable mWaitForCreationCv = new ConditionVariable(false); 1022 private final ConditionVariable mWaitForStopCv = new ConditionVariable(false); 1023 1024 @Override onIpClientCreated(IIpClient ipClient)1025 public void onIpClientCreated(IIpClient ipClient) { 1026 if (mIpClientCallbacks != this) return; 1027 // IpClient may take a very long time (many minutes) to start at boot time. But after 1028 // that IpClient should start pretty quickly (a few seconds). 1029 // Blocking wait for 5 seconds first (for when the wait is short) 1030 // If IpClient is still not ready after blocking wait, async wait (for when wait is 1031 // long). Will drop all connection requests until IpClient is ready. Other requests 1032 // will still be processed. 1033 sendMessageAtFrontOfQueue(CMD_IPCLIENT_CREATED, 1034 new IpClientManager(ipClient, getName())); 1035 mWaitForCreationCv.open(); 1036 } 1037 1038 @Override onPreDhcpAction()1039 public void onPreDhcpAction() { 1040 if (mIpClientCallbacks != this) return; 1041 sendMessage(CMD_PRE_DHCP_ACTION); 1042 } 1043 1044 @Override onPostDhcpAction()1045 public void onPostDhcpAction() { 1046 if (mIpClientCallbacks != this) return; 1047 sendMessage(CMD_POST_DHCP_ACTION); 1048 } 1049 1050 @Override onNewDhcpResults(DhcpResultsParcelable dhcpResults)1051 public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) { 1052 if (mIpClientCallbacks != this) return; 1053 if (dhcpResults != null) { 1054 sendMessage(CMD_IPV4_PROVISIONING_SUCCESS, dhcpResults); 1055 } else { 1056 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 1057 } 1058 } 1059 1060 @Override onProvisioningSuccess(LinkProperties newLp)1061 public void onProvisioningSuccess(LinkProperties newLp) { 1062 if (mIpClientCallbacks != this) return; 1063 addPasspointInfoToLinkProperties(newLp); 1064 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL); 1065 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); 1066 sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL); 1067 } 1068 1069 @Override onProvisioningFailure(LinkProperties newLp)1070 public void onProvisioningFailure(LinkProperties newLp) { 1071 if (mIpClientCallbacks != this) return; 1072 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST); 1073 sendMessage(CMD_IP_CONFIGURATION_LOST); 1074 } 1075 1076 @Override onLinkPropertiesChange(LinkProperties newLp)1077 public void onLinkPropertiesChange(LinkProperties newLp) { 1078 if (mIpClientCallbacks != this) return; 1079 addPasspointInfoToLinkProperties(newLp); 1080 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); 1081 } 1082 1083 @Override onReachabilityLost(String logMsg)1084 public void onReachabilityLost(String logMsg) { 1085 if (mIpClientCallbacks != this) return; 1086 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_REACHABILITY_LOST); 1087 sendMessage(CMD_IP_REACHABILITY_LOST, logMsg); 1088 } 1089 1090 @Override onReachabilityFailure(ReachabilityLossInfoParcelable lossInfo)1091 public void onReachabilityFailure(ReachabilityLossInfoParcelable lossInfo) { 1092 if (mIpClientCallbacks != this) return; 1093 sendMessage(CMD_IP_REACHABILITY_FAILURE, lossInfo); 1094 } 1095 1096 @Override installPacketFilter(byte[] filter)1097 public void installPacketFilter(byte[] filter) { 1098 if (mIpClientCallbacks != this) return; 1099 sendMessage(CMD_INSTALL_PACKET_FILTER, filter); 1100 } 1101 1102 @Override startReadPacketFilter()1103 public void startReadPacketFilter() { 1104 if (mIpClientCallbacks != this) return; 1105 sendMessage(CMD_READ_PACKET_FILTER); 1106 } 1107 1108 @Override setFallbackMulticastFilter(boolean enabled)1109 public void setFallbackMulticastFilter(boolean enabled) { 1110 if (mIpClientCallbacks != this) return; 1111 sendMessage(CMD_SET_FALLBACK_PACKET_FILTERING, enabled); 1112 } 1113 1114 @Override setNeighborDiscoveryOffload(boolean enabled)1115 public void setNeighborDiscoveryOffload(boolean enabled) { 1116 if (mIpClientCallbacks != this) return; 1117 sendMessage(CMD_CONFIG_ND_OFFLOAD, (enabled ? 1 : 0)); 1118 } 1119 1120 @Override onPreconnectionStart(List<Layer2PacketParcelable> packets)1121 public void onPreconnectionStart(List<Layer2PacketParcelable> packets) { 1122 if (mIpClientCallbacks != this) return; 1123 sendMessage(CMD_START_FILS_CONNECTION, 0, 0, packets); 1124 } 1125 1126 @Override setMaxDtimMultiplier(int multiplier)1127 public void setMaxDtimMultiplier(int multiplier) { 1128 if (mIpClientCallbacks != this) return; 1129 sendMessage(CMD_SET_MAX_DTIM_MULTIPLIER, multiplier); 1130 } 1131 1132 @Override onQuit()1133 public void onQuit() { 1134 if (mIpClientCallbacks != this) return; 1135 mWaitForStopCv.open(); 1136 } 1137 awaitCreation()1138 boolean awaitCreation() { 1139 return mWaitForCreationCv.block(IPCLIENT_STARTUP_TIMEOUT_MS); 1140 } 1141 awaitShutdown()1142 boolean awaitShutdown() { 1143 return mWaitForStopCv.block(IPCLIENT_SHUTDOWN_TIMEOUT_MS); 1144 } 1145 } 1146 stopIpClient()1147 private void stopIpClient() { 1148 if (mVerboseLoggingEnabled) { 1149 Log.v(getTag(), "stopIpClient IpClientWithPreConnection: " 1150 + mIpClientWithPreConnection); 1151 } 1152 if (mIpClient != null) { 1153 if (mIpClientWithPreConnection) { 1154 mIpClient.notifyPreconnectionComplete(false); 1155 } 1156 mIpClient.stop(); 1157 } 1158 mIpClientWithPreConnection = false; 1159 mSentHLPs = false; 1160 } 1161 stopDhcpSetup()1162 private void stopDhcpSetup() { 1163 /* Restore power save and suspend optimizations */ 1164 handlePostDhcpSetup(); 1165 stopIpClient(); 1166 } 1167 convertToInternalDhcpOptions(List<android.net.DhcpOption> options)1168 private List<DhcpOption> convertToInternalDhcpOptions(List<android.net.DhcpOption> options) { 1169 List<DhcpOption> internalOptions = new ArrayList<DhcpOption>(); 1170 for (android.net.DhcpOption option : options) { 1171 DhcpOption internalOption = new DhcpOption(); 1172 internalOption.type = option.getType(); 1173 if (option.getValue() != null) { 1174 byte[] value = option.getValue(); 1175 internalOption.value = Arrays.copyOf(value, value.length); 1176 } 1177 internalOptions.add(internalOption); 1178 } 1179 return internalOptions; 1180 } 1181 1182 /** 1183 * Listener for config manager network config related events. 1184 * TODO (b/117601161) : Move some of the existing handling in WifiConnectivityManager's listener 1185 * for the same events. 1186 */ 1187 private class OnNetworkUpdateListener implements 1188 WifiConfigManager.OnNetworkUpdateListener { 1189 @Override onNetworkRemoved(WifiConfiguration config)1190 public void onNetworkRemoved(WifiConfiguration config) { 1191 // The current connected or connecting network has been removed, trigger a disconnect. 1192 if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { 1193 // Disconnect and let autojoin reselect a new network 1194 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_REMOVED); 1195 // Log disconnection here, since the network config won't exist when the 1196 // disconnection event is received. 1197 String bssid = getConnectedBssidInternal(); 1198 logEventIfManagedNetwork(config, 1199 SupplicantStaIfaceHal.SUPPLICANT_EVENT_DISCONNECTED, 1200 bssid != null ? MacAddress.fromString(bssid) : null, 1201 "Network was removed"); 1202 } else { 1203 WifiConfiguration currentConfig = getConnectedWifiConfiguration(); 1204 if (currentConfig != null && currentConfig.isLinked(config)) { 1205 logi("current network linked config removed, update allowlist networks"); 1206 updateLinkedNetworks(currentConfig); 1207 } 1208 } 1209 mWifiNative.removeNetworkCachedData(config.networkId); 1210 } 1211 1212 @Override onNetworkUpdated(WifiConfiguration newConfig, WifiConfiguration oldConfig)1213 public void onNetworkUpdated(WifiConfiguration newConfig, WifiConfiguration oldConfig) { 1214 1215 if (WifiConfigurationUtil.hasCredentialChanged(oldConfig, newConfig)) { 1216 // Clear invalid cached data. 1217 mWifiNative.removeNetworkCachedData(oldConfig.networkId); 1218 mWifiBlocklistMonitor.handleNetworkRemoved(newConfig.SSID); 1219 } 1220 1221 if (newConfig.networkId != mLastNetworkId) { 1222 // nothing to do. 1223 return; 1224 } 1225 boolean isMetered = WifiConfiguration.isMetered(newConfig, mWifiInfo); 1226 boolean wasMetered = WifiConfiguration.isMetered(oldConfig, mWifiInfo); 1227 // Check if user/app change meteredOverride or trusted for connected network. 1228 if (isMetered == wasMetered 1229 && (!SdkLevel.isAtLeastT() || newConfig.trusted == oldConfig.trusted)) { 1230 return; 1231 } 1232 1233 if (SdkLevel.isAtLeastT()) { 1234 mWifiInfo.setTrusted(newConfig.trusted); 1235 if (!newConfig.trusted) { 1236 Log.w(getTag(), "Network marked untrusted, triggering disconnect"); 1237 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED); 1238 return; 1239 } 1240 } 1241 1242 if (isMetered) { 1243 Log.w(getTag(), "Network marked metered, triggering disconnect"); 1244 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_METERED); 1245 return; 1246 } 1247 1248 Log.i(getTag(), "Network marked metered=" + isMetered 1249 + " trusted=" + newConfig.trusted + ", triggering capabilities update"); 1250 updateCapabilities(newConfig); 1251 updateCurrentConnectionInfo(); 1252 } 1253 1254 @Override onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason)1255 public void onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason) { 1256 if (disableReason == DISABLED_NO_INTERNET_TEMPORARY) return; 1257 if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { 1258 // Disconnect and let autojoin reselect a new network 1259 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_TEMPORARY_DISABLED); 1260 } 1261 1262 } 1263 1264 @Override onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason)1265 public void onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason) { 1266 // For DISABLED_NO_INTERNET_PERMANENT we do not need to remove the network 1267 // because supplicant won't be trying to reconnect. If this is due to a 1268 // preventAutomaticReconnect request from ConnectivityService, that service 1269 // will disconnect as appropriate. 1270 if (disableReason == DISABLED_NO_INTERNET_PERMANENT) return; 1271 if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { 1272 // Disconnect and let autojoin reselect a new network 1273 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_PERMANENT_DISABLED); 1274 } 1275 } 1276 } 1277 1278 private class OnCarrierOffloadDisabledListener implements 1279 WifiCarrierInfoManager.OnCarrierOffloadDisabledListener { 1280 1281 @Override onCarrierOffloadDisabled(int subscriptionId, boolean merged)1282 public void onCarrierOffloadDisabled(int subscriptionId, boolean merged) { 1283 int networkId = mTargetNetworkId == WifiConfiguration.INVALID_NETWORK_ID 1284 ? mLastNetworkId : mTargetNetworkId; 1285 if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { 1286 return; 1287 } 1288 WifiConfiguration configuration = mWifiConfigManager.getConfiguredNetwork(networkId); 1289 if (configuration != null && configuration.subscriptionId == subscriptionId 1290 && configuration.carrierMerged == merged) { 1291 Log.i(getTag(), "Carrier network offload disabled, triggering disconnect"); 1292 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_CARRIER_OFFLOAD_DISABLED); 1293 } 1294 mWifiConnectivityManager.clearCachedCandidates(); 1295 } 1296 } 1297 1298 /** 1299 * Method to update logging level in wifi service related classes. 1300 * 1301 * @param verbose int logging level to use 1302 */ enableVerboseLogging(boolean verbose)1303 public void enableVerboseLogging(boolean verbose) { 1304 if (verbose) { 1305 mVerboseLoggingEnabled = true; 1306 setLogRecSize(mActivityManager.isLowRamDevice() 1307 ? NUM_LOG_RECS_VERBOSE_LOW_MEMORY : NUM_LOG_RECS_VERBOSE); 1308 } else { 1309 mVerboseLoggingEnabled = false; 1310 setLogRecSize(mWifiGlobals.getClientModeImplNumLogRecs()); 1311 } 1312 1313 mWifiScoreReport.enableVerboseLogging(mVerboseLoggingEnabled); 1314 mSupplicantStateTracker.enableVerboseLogging(mVerboseLoggingEnabled); 1315 mWifiNative.enableVerboseLogging(mVerboseLoggingEnabled, mVerboseLoggingEnabled); 1316 mQosPolicyRequestHandler.enableVerboseLogging(mVerboseLoggingEnabled); 1317 mRssiMonitor.enableVerboseLogging(mVerboseLoggingEnabled); 1318 } 1319 1320 /** 1321 * If there is only SAE-only networks with this auto-upgrade type, 1322 * this auto-upgrade SAE type is considered to be added explicitly. 1323 * 1324 * For R, Settings/WifiTrackerLib maps WPA3 SAE to WPA2, so there is 1325 * no chance to add or update a WPA3 SAE configuration to update 1326 * the auto-upgrade flag. 1327 */ updateSaeAutoUpgradeFlagForUserSelectNetwork(int networkId)1328 private void updateSaeAutoUpgradeFlagForUserSelectNetwork(int networkId) { 1329 if (SdkLevel.isAtLeastS()) return; 1330 if (mWifiGlobals.isWpa3SaeUpgradeEnabled()) return; 1331 1332 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(networkId); 1333 if (null == config) return; 1334 SecurityParams params = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); 1335 if (null == params || !params.isAddedByAutoUpgrade()) return; 1336 1337 if (!mScanRequestProxy.isWpa3PersonalOnlyNetworkInRange(config.SSID)) return; 1338 if (mScanRequestProxy.isWpa2PersonalOnlyNetworkInRange(config.SSID)) return; 1339 if (mScanRequestProxy.isWpa2Wpa3PersonalTransitionNetworkInRange(config.SSID)) return; 1340 1341 logd("update auto-upgrade flag for SAE"); 1342 mWifiConfigManager.updateIsAddedByAutoUpgradeFlag( 1343 config.networkId, WifiConfiguration.SECURITY_TYPE_SAE, false); 1344 } 1345 1346 /** 1347 * Given a network ID for connection, check the security parameters for a 1348 * disabled security type. 1349 * 1350 * Allow the connection only when there are APs with the better security 1351 * type (or transition mode), or no APs with the disabled security type. 1352 * 1353 * @param networkIdForConnection indicates the network id for the desired connection. 1354 * @return {@code true} if this connection request should be dropped; {@code false} otherwise. 1355 */ shouldDropConnectionRequest(int networkIdForConnection)1356 private boolean shouldDropConnectionRequest(int networkIdForConnection) { 1357 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(networkIdForConnection); 1358 if (null == config) return false; 1359 1360 List<ScanResult> scanResults = mScanRequestProxy.getScanResults().stream() 1361 .filter(r -> TextUtils.equals(config.SSID, r.getWifiSsid().toString())) 1362 .collect(Collectors.toList()); 1363 if (0 == scanResults.size()) return false; 1364 1365 SecurityParams params; 1366 // Check disabled PSK network. 1367 params = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); 1368 if (null != params && !params.isEnabled()) { 1369 if (scanResults.stream().anyMatch(r -> 1370 ScanResultUtil.isScanResultForSaeNetwork(r))) { 1371 return false; 1372 } 1373 if (!scanResults.stream().anyMatch(r -> 1374 ScanResultUtil.isScanResultForPskOnlyNetwork(r))) { 1375 return false; 1376 } 1377 return true; 1378 } 1379 // Check disabled OPEN network. 1380 params = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); 1381 if (null != params && !params.isEnabled()) { 1382 if (scanResults.stream().anyMatch(r -> 1383 ScanResultUtil.isScanResultForOweNetwork(r))) { 1384 return false; 1385 } 1386 if (!scanResults.stream().anyMatch(r -> 1387 ScanResultUtil.isScanResultForOpenOnlyNetwork(r))) { 1388 return false; 1389 } 1390 return true; 1391 } 1392 // Check disabled WPA2 Enterprise network. 1393 params = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); 1394 if (null != params && !params.isEnabled()) { 1395 if (scanResults.stream().anyMatch(r -> 1396 ScanResultUtil.isScanResultForWpa3EnterpriseOnlyNetwork(r))) { 1397 return false; 1398 } 1399 if (scanResults.stream().anyMatch(r -> 1400 ScanResultUtil.isScanResultForWpa3EnterpriseTransitionNetwork(r))) { 1401 return false; 1402 } 1403 if (!scanResults.stream().anyMatch(r -> 1404 ScanResultUtil.isScanResultForWpa2EnterpriseOnlyNetwork(r))) { 1405 return false; 1406 } 1407 return true; 1408 } 1409 return false; 1410 } 1411 1412 /** 1413 * Initiates connection to a network specified by the user/app. This method checks if the 1414 * requesting app holds the NETWORK_SETTINGS permission. 1415 * 1416 * @param netId Id network to initiate connection. 1417 * @param uid UID of the app requesting the connection. 1418 * @param forceReconnect Whether to force a connection even if we're connected to the same 1419 * network currently. 1420 * @param packageName package name of the app requesting the connection. 1421 */ connectToUserSelectNetwork(int netId, int uid, boolean forceReconnect, @NonNull String packageName)1422 private void connectToUserSelectNetwork(int netId, int uid, boolean forceReconnect, 1423 @NonNull String packageName) { 1424 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 1425 || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)) { 1426 mIsUserSelected = true; 1427 } 1428 logd("connectToUserSelectNetwork netId " + netId + ", uid " + uid + ", package " 1429 + packageName + ", forceReconnect = " + forceReconnect + ", isUserSelected = " 1430 + mIsUserSelected); 1431 updateSaeAutoUpgradeFlagForUserSelectNetwork(netId); 1432 if (!forceReconnect && (mLastNetworkId == netId || mTargetNetworkId == netId)) { 1433 // We're already connecting/connected to the user specified network, don't trigger a 1434 // reconnection unless it was forced. 1435 logi("connectToUserSelectNetwork already connecting/connected=" + netId); 1436 } else if (mIsUserSelected && shouldDropConnectionRequest(netId)) { 1437 logi("connectToUserSelectNetwork this network is disabled by admin."); 1438 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId); 1439 String title = mContext.getString(R.string.wifi_network_disabled_by_admin_title); 1440 String message = mContext.getString(R.string.wifi_network_disabled_by_admin_message, 1441 config.SSID); 1442 String buttonText = mContext.getString(R.string.wifi_network_disabled_by_admin_button); 1443 mWifiInjector.getWifiDialogManager().createLegacySimpleDialog( 1444 title, message, 1445 null /* positiveButtonText */, 1446 null /* negativeButtonText */, 1447 buttonText, 1448 new WifiDialogManager.SimpleDialogCallback() { 1449 @Override 1450 public void onPositiveButtonClicked() { 1451 // Not used. 1452 } 1453 @Override 1454 public void onNegativeButtonClicked() { 1455 // Not used. 1456 } 1457 @Override 1458 public void onNeutralButtonClicked() { 1459 // Not used. 1460 } 1461 @Override 1462 public void onCancelled() { 1463 // Not used. 1464 } 1465 }, mWifiThreadRunner).launchDialog(); 1466 } else { 1467 mWifiConnectivityManager.prepareForForcedConnection(netId); 1468 if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) { 1469 mWifiMetrics.setNominatorForNetwork(netId, 1470 WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL); 1471 } 1472 startConnectToNetwork(netId, uid, SUPPLICANT_BSSID_ANY); 1473 } 1474 } 1475 1476 /** 1477 * ****************************************************** 1478 * Methods exposed for public use 1479 * ****************************************************** 1480 */ 1481 1482 /** 1483 * Retrieve a Messenger for the ClientModeImpl Handler 1484 * 1485 * @return Messenger 1486 */ getMessenger()1487 public Messenger getMessenger() { 1488 return new Messenger(getHandler()); 1489 } 1490 1491 // For debugging, keep track of last message status handling 1492 // TODO, find an equivalent mechanism as part of parent class 1493 private static final int MESSAGE_HANDLING_STATUS_PROCESSED = 2; 1494 private static final int MESSAGE_HANDLING_STATUS_OK = 1; 1495 private static final int MESSAGE_HANDLING_STATUS_UNKNOWN = 0; 1496 private static final int MESSAGE_HANDLING_STATUS_REFUSED = -1; 1497 private static final int MESSAGE_HANDLING_STATUS_FAIL = -2; 1498 private static final int MESSAGE_HANDLING_STATUS_OBSOLETE = -3; 1499 private static final int MESSAGE_HANDLING_STATUS_DEFERRED = -4; 1500 private static final int MESSAGE_HANDLING_STATUS_DISCARD = -5; 1501 private static final int MESSAGE_HANDLING_STATUS_LOOPED = -6; 1502 private static final int MESSAGE_HANDLING_STATUS_HANDLING_ERROR = -7; 1503 1504 private int mMessageHandlingStatus = 0; 1505 1506 private int mOnTime = 0; 1507 private int mTxTime = 0; 1508 private int mRxTime = 0; 1509 1510 private int mOnTimeScreenStateChange = 0; 1511 private long mLastOntimeReportTimeStamp = 0; 1512 private long mLastScreenStateChangeTimeStamp = 0; 1513 private int mOnTimeLastReport = 0; 1514 private int mTxTimeLastReport = 0; 1515 private int mRxTimeLastReport = 0; 1516 1517 private WifiLinkLayerStats mLastLinkLayerStats; 1518 private long mLastLinkLayerStatsUpdate = 0; 1519 reportOnTime()1520 String reportOnTime() { 1521 long now = mClock.getWallClockMillis(); 1522 StringBuilder sb = new StringBuilder(); 1523 // Report stats since last report 1524 int on = mOnTime - mOnTimeLastReport; 1525 mOnTimeLastReport = mOnTime; 1526 int tx = mTxTime - mTxTimeLastReport; 1527 mTxTimeLastReport = mTxTime; 1528 int rx = mRxTime - mRxTimeLastReport; 1529 mRxTimeLastReport = mRxTime; 1530 int period = (int) (now - mLastOntimeReportTimeStamp); 1531 mLastOntimeReportTimeStamp = now; 1532 sb.append("[on:" + on + " tx:" + tx + " rx:" + rx + " period:" + period + "]"); 1533 // Report stats since Screen State Changed 1534 on = mOnTime - mOnTimeScreenStateChange; 1535 period = (int) (now - mLastScreenStateChangeTimeStamp); 1536 sb.append(" from screen [on:" + on + " period:" + period + "]"); 1537 return sb.toString(); 1538 } 1539 1540 /** 1541 * receives changes in the interface up/down events for the interface associated with this 1542 * ClientModeImpl. This is expected to be called from the ClientModeManager running on the 1543 * wifi handler thread. 1544 */ onUpChanged(boolean isUp)1545 public void onUpChanged(boolean isUp) { 1546 if (isUp && mFailedToResetMacAddress) { 1547 // When the firmware does a subsystem restart, wifi will disconnect but we may fail to 1548 // re-randomize the MAC address of the interface since it's undergoing recovery. Thus, 1549 // check every time the interface goes up and re-randomize if the failure was detected. 1550 if (mWifiGlobals.isConnectedMacRandomizationEnabled()) { 1551 mFailedToResetMacAddress = !mWifiNative.setStaMacAddress( 1552 mInterfaceName, MacAddressUtils.createRandomUnicastAddress()); 1553 if (mFailedToResetMacAddress) { 1554 Log.e(getTag(), "Failed to set random MAC address on interface up"); 1555 } 1556 } 1557 } 1558 // No need to handle interface down since it's already handled in the ClientModeManager. 1559 } 1560 getWifiLinkLayerStats()1561 public WifiLinkLayerStats getWifiLinkLayerStats() { 1562 if (mInterfaceName == null) { 1563 loge("getWifiLinkLayerStats called without an interface"); 1564 return null; 1565 } 1566 mLastLinkLayerStatsUpdate = mClock.getWallClockMillis(); 1567 WifiLinkLayerStats stats = null; 1568 if (isPrimary()) { 1569 stats = mWifiNative.getWifiLinkLayerStats(mInterfaceName); 1570 } else { 1571 if (mVerboseLoggingEnabled) { 1572 Log.w(getTag(), "Can't getWifiLinkLayerStats on secondary iface"); 1573 } 1574 } 1575 if (stats != null) { 1576 mOnTime = stats.on_time; 1577 mTxTime = stats.tx_time; 1578 mRxTime = stats.rx_time; 1579 mRunningBeaconCount = stats.beacon_rx; 1580 mWifiInfo.updatePacketRates(stats, mLastLinkLayerStatsUpdate); 1581 } else { 1582 long mTxPkts = mFacade.getTxPackets(mInterfaceName); 1583 long mRxPkts = mFacade.getRxPackets(mInterfaceName); 1584 mWifiInfo.updatePacketRates(mTxPkts, mRxPkts, mLastLinkLayerStatsUpdate); 1585 } 1586 mWifiMetrics.incrementWifiLinkLayerUsageStats(mInterfaceName, stats); 1587 updateCurrentConnectionInfo(); 1588 return stats; 1589 } 1590 1591 /** 1592 * Update interface capabilities 1593 * This method is used to update some of interface capabilities defined in overlay 1594 */ updateInterfaceCapabilities()1595 private void updateInterfaceCapabilities() { 1596 DeviceWiphyCapabilities cap = getDeviceWiphyCapabilities(); 1597 if (cap != null) { 1598 // Some devices don't have support of 11ax/be indicated by the chip, 1599 // so an override config value is used 1600 if (mContext.getResources().getBoolean(R.bool.config_wifi11beSupportOverride)) { 1601 cap.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11BE, true); 1602 } 1603 if (mContext.getResources().getBoolean(R.bool.config_wifi11axSupportOverride)) { 1604 cap.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, true); 1605 } 1606 1607 mWifiNative.setDeviceWiphyCapabilities(mInterfaceName, cap); 1608 } 1609 } 1610 1611 @Override getDeviceWiphyCapabilities()1612 public DeviceWiphyCapabilities getDeviceWiphyCapabilities() { 1613 return mWifiNative.getDeviceWiphyCapabilities(mInterfaceName); 1614 } 1615 1616 /** 1617 * Check if a Wi-Fi standard is supported 1618 * 1619 * @param standard A value from {@link ScanResult}'s {@code WIFI_STANDARD_} 1620 * @return {@code true} if standard is supported, {@code false} otherwise. 1621 */ isWifiStandardSupported(@ifiStandard int standard)1622 public boolean isWifiStandardSupported(@WifiStandard int standard) { 1623 return mWifiNative.isWifiStandardSupported(mInterfaceName, standard); 1624 } 1625 getDstMacForKeepalive(KeepalivePacketData packetData)1626 private byte[] getDstMacForKeepalive(KeepalivePacketData packetData) 1627 throws InvalidPacketException { 1628 try { 1629 InetAddress gateway = NetUtils.selectBestRoute( 1630 mLinkProperties.getRoutes(), packetData.getDstAddress()).getGateway(); 1631 String dstMacStr = macAddressFromRoute(gateway.getHostAddress()); 1632 return NativeUtil.macAddressToByteArray(dstMacStr); 1633 } catch (NullPointerException | IllegalArgumentException e) { 1634 throw new InvalidPacketException(InvalidPacketException.ERROR_INVALID_IP_ADDRESS); 1635 } 1636 } 1637 getEtherProtoForKeepalive(KeepalivePacketData packetData)1638 private static int getEtherProtoForKeepalive(KeepalivePacketData packetData) 1639 throws InvalidPacketException { 1640 if (packetData.getDstAddress() instanceof Inet4Address) { 1641 return OsConstants.ETH_P_IP; 1642 } else if (packetData.getDstAddress() instanceof Inet6Address) { 1643 return OsConstants.ETH_P_IPV6; 1644 } else { 1645 throw new InvalidPacketException(InvalidPacketException.ERROR_INVALID_IP_ADDRESS); 1646 } 1647 } 1648 startWifiIPPacketOffload(int slot, KeepalivePacketData packetData, int intervalSeconds)1649 private int startWifiIPPacketOffload(int slot, KeepalivePacketData packetData, 1650 int intervalSeconds) { 1651 byte[] packet = null; 1652 byte[] dstMac = null; 1653 int proto = 0; 1654 1655 try { 1656 packet = packetData.getPacket(); 1657 dstMac = getDstMacForKeepalive(packetData); 1658 proto = getEtherProtoForKeepalive(packetData); 1659 } catch (InvalidPacketException e) { 1660 return e.getError(); 1661 } 1662 1663 int ret = mWifiNative.startSendingOffloadedPacket( 1664 mInterfaceName, slot, dstMac, packet, proto, intervalSeconds * 1000); 1665 if (ret != 0) { 1666 loge("startWifiIPPacketOffload(" + slot + ", " + intervalSeconds 1667 + "): hardware error " + ret); 1668 return SocketKeepalive.ERROR_HARDWARE_ERROR; 1669 } else { 1670 return SocketKeepalive.SUCCESS; 1671 } 1672 } 1673 stopWifiIPPacketOffload(int slot)1674 private int stopWifiIPPacketOffload(int slot) { 1675 int ret = mWifiNative.stopSendingOffloadedPacket(mInterfaceName, slot); 1676 if (ret != 0) { 1677 loge("stopWifiIPPacketOffload(" + slot + "): hardware error " + ret); 1678 return SocketKeepalive.ERROR_HARDWARE_ERROR; 1679 } else { 1680 return SocketKeepalive.SUCCESS; 1681 } 1682 } 1683 1684 @Override isConnected()1685 public boolean isConnected() { 1686 return getCurrentState() == mL3ConnectedState; 1687 } 1688 1689 @Override isConnecting()1690 public boolean isConnecting() { 1691 IState state = getCurrentState(); 1692 return state == mL2ConnectingState || state == mL2ConnectedState 1693 || state == mWaitBeforeL3ProvisioningState || state == mL3ProvisioningState; 1694 } 1695 1696 @Override isRoaming()1697 public boolean isRoaming() { 1698 return getCurrentState() == mRoamingState; 1699 } 1700 1701 @Override isDisconnected()1702 public boolean isDisconnected() { 1703 return getCurrentState() == mDisconnectedState; 1704 } 1705 1706 /** 1707 * Method checking if supplicant is in a transient state 1708 * 1709 * @return boolean true if in transient state 1710 */ isSupplicantTransientState()1711 public boolean isSupplicantTransientState() { 1712 SupplicantState supplicantState = mWifiInfo.getSupplicantState(); 1713 if (supplicantState == SupplicantState.ASSOCIATING 1714 || supplicantState == SupplicantState.AUTHENTICATING 1715 || supplicantState == SupplicantState.FOUR_WAY_HANDSHAKE 1716 || supplicantState == SupplicantState.GROUP_HANDSHAKE) { 1717 1718 if (mVerboseLoggingEnabled) { 1719 Log.d(getTag(), "Supplicant is under transient state: " + supplicantState); 1720 } 1721 return true; 1722 } else { 1723 if (mVerboseLoggingEnabled) { 1724 Log.d(getTag(), "Supplicant is under steady state: " + supplicantState); 1725 } 1726 } 1727 1728 return false; 1729 } 1730 1731 /** 1732 * Get status information for the current connection, if any. 1733 * Note: This call is synchronized and hence safe to call from any thread (if called from wifi 1734 * thread, will execute synchronously). 1735 * 1736 * @return a {@link WifiInfo} object containing information about the current connection 1737 */ 1738 @Override getConnectionInfo()1739 public WifiInfo getConnectionInfo() { 1740 return new WifiInfo(mWifiInfo); 1741 } 1742 1743 /** 1744 * Blocking call to get the current DHCP results 1745 * 1746 * @return DhcpResultsParcelable current results 1747 */ 1748 @NonNull syncGetDhcpResultsParcelable()1749 public DhcpResultsParcelable syncGetDhcpResultsParcelable() { 1750 synchronized (mDhcpResultsParcelableLock) { 1751 return mDhcpResultsParcelable; 1752 } 1753 } 1754 1755 /** 1756 * When the underlying interface is destroyed, we must immediately tell connectivity service to 1757 * mark network agent as disconnected and stop the ip client. 1758 */ handleIfaceDestroyed()1759 public void handleIfaceDestroyed() { 1760 handleNetworkDisconnect(false, 1761 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__IFACE_DESTROYED); 1762 } 1763 1764 /** Stop this ClientModeImpl. Do not interact with ClientModeImpl after it has been stopped. */ stop()1765 public void stop() { 1766 mInsecureEapNetworkHandler.cleanup(); 1767 mSupplicantStateTracker.stop(); 1768 mWifiScoreCard.noteWifiDisabled(mWifiInfo); 1769 // capture StateMachine LogRecs since we will lose them after we call quitNow() 1770 // This is used for debugging. 1771 mObituary = new StateMachineObituary(this); 1772 1773 // quit discarding all unprocessed messages - this is to preserve the legacy behavior of 1774 // using sendMessageAtFrontOfQueue(CMD_SET_OPERATIONAL_MODE) which would force a state 1775 // transition immediately 1776 quitNow(); 1777 1778 mWifiConfigManager.removeOnNetworkUpdateListener(mOnNetworkUpdateListener); 1779 mWifiCarrierInfoManager 1780 .removeOnCarrierOffloadDisabledListener(mOnCarrierOffloadDisabledListener); 1781 if (mVcnPolicyChangeListener != null && SdkLevel.isAtLeastS()) { 1782 mVcnManager.removeVcnNetworkPolicyChangeListener(mVcnPolicyChangeListener); 1783 mVcnPolicyChangeListener = null; 1784 } 1785 } 1786 checkAbnormalConnectionFailureAndTakeBugReport(String ssid)1787 private void checkAbnormalConnectionFailureAndTakeBugReport(String ssid) { 1788 if (mDeviceConfigFacade.isAbnormalConnectionFailureBugreportEnabled()) { 1789 int reasonCode = mWifiScoreCard.detectAbnormalConnectionFailure(ssid); 1790 if (reasonCode != WifiHealthMonitor.REASON_NO_FAILURE) { 1791 String bugTitle = "Wi-Fi BugReport: abnormal " 1792 + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode]; 1793 String bugDetail = "Detect abnormal " 1794 + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode]; 1795 mWifiDiagnostics.takeBugReport(bugTitle, bugDetail); 1796 } 1797 } 1798 } 1799 checkAbnormalDisconnectionAndTakeBugReport()1800 private void checkAbnormalDisconnectionAndTakeBugReport() { 1801 if (mDeviceConfigFacade.isAbnormalDisconnectionBugreportEnabled()) { 1802 int reasonCode = mWifiScoreCard.detectAbnormalDisconnection(mInterfaceName); 1803 if (reasonCode != WifiHealthMonitor.REASON_NO_FAILURE) { 1804 String bugTitle = "Wi-Fi BugReport: abnormal " 1805 + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode]; 1806 String bugDetail = "Detect abnormal " 1807 + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode]; 1808 mWifiDiagnostics.takeBugReport(bugTitle, bugDetail); 1809 } 1810 } 1811 } 1812 1813 /** 1814 * Retrieve the WifiMulticastLockManager.FilterController callback for registration. 1815 */ getMcastLockManagerFilterController()1816 public WifiMulticastLockManager.FilterController getMcastLockManagerFilterController() { 1817 return mMcastLockManagerFilterController; 1818 } 1819 1820 /** 1821 * Blocking method to retrieve the passpoint icon. 1822 * 1823 * @param bssid representation of the bssid as a long 1824 * @param fileName name of the file 1825 * 1826 * @return boolean returning the result of the call 1827 */ syncQueryPasspointIcon(long bssid, String fileName)1828 public boolean syncQueryPasspointIcon(long bssid, String fileName) { 1829 return mWifiThreadRunner.call( 1830 () -> mPasspointManager.queryPasspointIcon(bssid, fileName), false); 1831 } 1832 1833 @Override requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes)1834 public boolean requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes) { 1835 return mWifiNative.requestAnqp(mInterfaceName, bssid, anqpIds, hs20Subtypes); 1836 } 1837 1838 @Override requestVenueUrlAnqp(String bssid)1839 public boolean requestVenueUrlAnqp(String bssid) { 1840 return mWifiNative.requestVenueUrlAnqp(mInterfaceName, bssid); 1841 } 1842 1843 @Override requestIcon(String bssid, String fileName)1844 public boolean requestIcon(String bssid, String fileName) { 1845 return mWifiNative.requestIcon(mInterfaceName, bssid, fileName); 1846 } 1847 1848 /** 1849 * Disconnect from Access Point 1850 */ disconnect()1851 public void disconnect() { 1852 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_GENERIC); 1853 } 1854 1855 /** 1856 * Initiate a reconnection to AP 1857 */ reconnect(WorkSource workSource)1858 public void reconnect(WorkSource workSource) { 1859 sendMessage(CMD_RECONNECT, workSource); 1860 } 1861 1862 /** 1863 * Initiate a re-association to AP 1864 */ reassociate()1865 public void reassociate() { 1866 sendMessage(CMD_REASSOCIATE); 1867 } 1868 1869 /** 1870 * Start subscription provisioning synchronously 1871 * 1872 * @param provider {@link OsuProvider} the provider to provision with 1873 * @param callback {@link IProvisioningCallback} callback for provisioning status 1874 * @return boolean true indicates provisioning was started, false otherwise 1875 */ syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider, IProvisioningCallback callback)1876 public boolean syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider, 1877 IProvisioningCallback callback) { 1878 return mWifiThreadRunner.call( 1879 () -> mPasspointManager.startSubscriptionProvisioning( 1880 callingUid, provider, callback), false); 1881 } 1882 1883 /** 1884 * Get the supported feature set synchronously 1885 */ getSupportedFeatures()1886 public long getSupportedFeatures() { 1887 return mWifiNative.getSupportedFeatureSet(mInterfaceName); 1888 } 1889 1890 /** 1891 * Method to enable/disable RSSI polling 1892 * @param enabled boolean idicating if polling should start 1893 */ 1894 @VisibleForTesting enableRssiPolling(boolean enabled)1895 public void enableRssiPolling(boolean enabled) { 1896 sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0); 1897 } 1898 1899 /** 1900 * reset cached SIM credential data 1901 */ resetSimAuthNetworks(@esetSimReason int resetReason)1902 public void resetSimAuthNetworks(@ResetSimReason int resetReason) { 1903 sendMessage(CMD_RESET_SIM_NETWORKS, resetReason); 1904 } 1905 1906 /** 1907 * Get Network object of currently connected wifi network, or null if not connected. 1908 * @return Network object of current wifi network 1909 */ getCurrentNetwork()1910 public Network getCurrentNetwork() { 1911 if (getCurrentState() != mL3ConnectedState 1912 && getCurrentState() != mRoamingState) return null; 1913 return (mNetworkAgent != null) ? mNetworkAgent.getNetwork() : null; 1914 } 1915 1916 /** 1917 * Enable TDLS for a specific MAC address 1918 */ enableTdls(String remoteMacAddress, boolean enable)1919 public boolean enableTdls(String remoteMacAddress, boolean enable) { 1920 boolean ret; 1921 if (!canEnableTdls()) { 1922 return false; 1923 } 1924 ret = mWifiNative.startTdls(mInterfaceName, remoteMacAddress, enable); 1925 if (enable && ret) { 1926 mEnabledTdlsPeers.add(remoteMacAddress); 1927 } else { 1928 mEnabledTdlsPeers.remove(remoteMacAddress); 1929 } 1930 return ret; 1931 } 1932 1933 /** 1934 * Enable TDLS for a specific IP address 1935 */ enableTdlsWithRemoteIpAddress(String remoteIpAddress, boolean enable)1936 public boolean enableTdlsWithRemoteIpAddress(String remoteIpAddress, boolean enable) { 1937 boolean ret; 1938 String remoteMacAddress = macAddressFromRoute(remoteIpAddress); 1939 if (remoteMacAddress == null) { 1940 return false; 1941 } 1942 ret = enableTdls(remoteMacAddress, enable); 1943 return ret; 1944 } 1945 1946 /** 1947 * Check if a TDLS session can be established 1948 */ isTdlsOperationCurrentlyAvailable()1949 public boolean isTdlsOperationCurrentlyAvailable() { 1950 return (getSupportedFeatures() & WIFI_FEATURE_TDLS) != 0 && isConnected() 1951 && canEnableTdls(); 1952 } 1953 1954 /** 1955 * Return the number of Mac addresses configured in the driver for TDLS connection. 1956 */ getNumberOfEnabledTdlsSessions()1957 public int getNumberOfEnabledTdlsSessions() { 1958 return mEnabledTdlsPeers.size(); 1959 } 1960 1961 /** 1962 * Return the maximum number of TDLS sessions supported by the device. 1963 */ getMaxSupportedConcurrentTdlsSessions()1964 public int getMaxSupportedConcurrentTdlsSessions() { 1965 return mWifiNative.getMaxSupportedConcurrentTdlsSessions(mInterfaceName); 1966 } 1967 canEnableTdls()1968 private boolean canEnableTdls() { 1969 // This function returns -1 if HAL doesn't have support for retrieving this info. 1970 int maxTdlsSessionCount = mWifiNative.getMaxSupportedConcurrentTdlsSessions(mInterfaceName); 1971 if (maxTdlsSessionCount < 0) { 1972 return true; 1973 } 1974 if (mEnabledTdlsPeers.size() >= maxTdlsSessionCount) { 1975 Log.e(TAG, "canEnableTdls() returned false: maxTdlsSessionCount: " 1976 + maxTdlsSessionCount + "EnabledTdlsPeers count: " + mEnabledTdlsPeers.size()); 1977 return false; 1978 } 1979 return true; 1980 } 1981 1982 /** Send a message indicating bluetooth connection state changed, e.g. connected/disconnected */ onBluetoothConnectionStateChanged()1983 public void onBluetoothConnectionStateChanged() { 1984 sendMessage(CMD_BLUETOOTH_CONNECTION_STATE_CHANGE); 1985 } 1986 1987 /** 1988 * Trigger dump on the class IpClient object. 1989 */ dumpIpClient(FileDescriptor fd, PrintWriter pw, String[] args)1990 public void dumpIpClient(FileDescriptor fd, PrintWriter pw, String[] args) { 1991 if (mIpClient != null) { 1992 // All dumpIpClient does is print this log message. 1993 // TODO: consider deleting this, since it's not useful. 1994 pw.println("IpClient logs have moved to dumpsys network_stack"); 1995 } 1996 } 1997 dhcpResultsParcelableToString(DhcpResultsParcelable dhcpResults)1998 private static String dhcpResultsParcelableToString(DhcpResultsParcelable dhcpResults) { 1999 return new StringBuilder() 2000 .append("baseConfiguration ").append(dhcpResults.baseConfiguration) 2001 .append("leaseDuration ").append(dhcpResults.leaseDuration) 2002 .append("mtu ").append(dhcpResults.mtu) 2003 .append("serverAddress ").append(dhcpResults.serverAddress) 2004 .append("serverHostName ").append(dhcpResults.serverHostName) 2005 .append("vendorInfo ").append(dhcpResults.vendorInfo) 2006 .toString(); 2007 } 2008 2009 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)2010 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2011 pw.println("Dump of ClientModeImpl id=" + mId); 2012 if (mObituary == null) { 2013 // StateMachine hasn't quit yet, dump `this` via StateMachineObituary's dump() 2014 // method for consistency with `else` branch. 2015 new StateMachineObituary(this).dump(fd, pw, args); 2016 } else { 2017 // StateMachine has quit and cleared all LogRecs. 2018 // Get them from the obituary instead. 2019 mObituary.dump(fd, pw, args); 2020 } 2021 mSupplicantStateTracker.dump(fd, pw, args); 2022 // Polls link layer stats and RSSI. This allows the stats to show up in 2023 // WifiScoreReport's dump() output when taking a bug report even if the screen is off. 2024 updateLinkLayerStatsRssiAndScoreReport(); 2025 pw.println("mLinkProperties " + mLinkProperties); 2026 pw.println("mWifiInfo " + mWifiInfo); 2027 pw.println("mDhcpResultsParcelable " 2028 + dhcpResultsParcelableToString(mDhcpResultsParcelable)); 2029 pw.println("mLastSignalLevel " + mLastSignalLevel); 2030 pw.println("mLastTxKbps " + mLastTxKbps); 2031 pw.println("mLastRxKbps " + mLastRxKbps); 2032 pw.println("mLastBssid " + mLastBssid); 2033 pw.println("mLastNetworkId " + mLastNetworkId); 2034 pw.println("mLastSubId " + mLastSubId); 2035 pw.println("mLastSimBasedConnectionCarrierName " + mLastSimBasedConnectionCarrierName); 2036 pw.println("mSuspendOptimizationsEnabled " + mContext.getResources().getBoolean( 2037 R.bool.config_wifiSuspendOptimizationsEnabled)); 2038 pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 2039 pw.println("mPowerSaveDisableRequests " + mPowerSaveDisableRequests); 2040 dumpIpClient(fd, pw, args); 2041 pw.println("WifiScoreReport:"); 2042 mWifiScoreReport.dump(fd, pw, args); 2043 pw.println("QosPolicyRequestHandler:"); 2044 mQosPolicyRequestHandler.dump(fd, pw, args); 2045 pw.println(); 2046 } 2047 2048 /** 2049 * ****************************************************** 2050 * Internal private functions 2051 * ****************************************************** 2052 */ 2053 logStateAndMessage(Message message, State state)2054 private void logStateAndMessage(Message message, State state) { 2055 mMessageHandlingStatus = 0; 2056 if (mVerboseLoggingEnabled) { 2057 logd(" " + state.getClass().getSimpleName() + " " + getLogRecString(message)); 2058 } 2059 } 2060 2061 @Override recordLogRec(Message msg)2062 protected boolean recordLogRec(Message msg) { 2063 switch (msg.what) { 2064 case CMD_RSSI_POLL: 2065 return mVerboseLoggingEnabled; 2066 default: 2067 return true; 2068 } 2069 } 2070 2071 /** 2072 * Return the additional string to be logged by LogRec, default 2073 * 2074 * @param msg that was processed 2075 * @return information to be logged as a String 2076 */ 2077 @Override getLogRecString(Message msg)2078 protected String getLogRecString(Message msg) { 2079 WifiConfiguration config; 2080 Long now; 2081 String report; 2082 String key; 2083 StringBuilder sb = new StringBuilder(); 2084 sb.append("screen=").append(mScreenOn ? "on" : "off"); 2085 if (mMessageHandlingStatus != MESSAGE_HANDLING_STATUS_UNKNOWN) { 2086 sb.append("(").append(mMessageHandlingStatus).append(")"); 2087 } 2088 if (msg.sendingUid > 0 && msg.sendingUid != Process.WIFI_UID) { 2089 sb.append(" uid=" + msg.sendingUid); 2090 } 2091 switch (msg.what) { 2092 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 2093 sb.append(" "); 2094 sb.append(Integer.toString(msg.arg1)); 2095 sb.append(" "); 2096 sb.append(Integer.toString(msg.arg2)); 2097 StateChangeResult stateChangeResult = (StateChangeResult) msg.obj; 2098 if (stateChangeResult != null) { 2099 sb.append(stateChangeResult.toString()); 2100 } 2101 break; 2102 case CMD_CONNECT_NETWORK: 2103 case CMD_SAVE_NETWORK: { 2104 ConnectNetworkMessage cnm = (ConnectNetworkMessage) msg.obj; 2105 sb.append(" "); 2106 sb.append(cnm.result.getNetworkId()); 2107 config = mWifiConfigManager.getConfiguredNetwork(cnm.result.getNetworkId()); 2108 if (config != null) { 2109 sb.append(" ").append(config.getProfileKey()); 2110 sb.append(" nid=").append(config.networkId); 2111 if (config.hiddenSSID) { 2112 sb.append(" hidden"); 2113 } 2114 if (config.preSharedKey != null 2115 && !config.preSharedKey.equals("*")) { 2116 sb.append(" hasPSK"); 2117 } 2118 if (config.ephemeral) { 2119 sb.append(" ephemeral"); 2120 } 2121 sb.append(" cuid=").append(config.creatorUid); 2122 sb.append(" suid=").append(config.lastUpdateUid); 2123 } 2124 break; 2125 } 2126 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 2127 if (msg.obj != null) { 2128 sb.append(" ").append((AssocRejectEventInfo) msg.obj); 2129 } 2130 break; 2131 case WifiMonitor.NETWORK_CONNECTION_EVENT: { 2132 NetworkConnectionEventInfo connectionInfo = (NetworkConnectionEventInfo) msg.obj; 2133 sb.append(" "); 2134 sb.append(connectionInfo.networkId); 2135 sb.append(" "); 2136 sb.append(connectionInfo.isFilsConnection); 2137 sb.append(" ").append(mLastBssid); 2138 sb.append(" nid=").append(mLastNetworkId); 2139 config = getConnectedWifiConfigurationInternal(); 2140 if (config != null) { 2141 sb.append(" ").append(config.getProfileKey()); 2142 } 2143 key = mWifiConfigManager.getLastSelectedNetworkConfigKey(); 2144 if (key != null) { 2145 sb.append(" last=").append(key); 2146 } 2147 break; 2148 } 2149 case WifiMonitor.TARGET_BSSID_EVENT: 2150 case WifiMonitor.ASSOCIATED_BSSID_EVENT: 2151 sb.append(" "); 2152 sb.append(Integer.toString(msg.arg1)); 2153 sb.append(" "); 2154 sb.append(Integer.toString(msg.arg2)); 2155 if (msg.obj != null) { 2156 sb.append(" BSSID=").append((String) msg.obj); 2157 } 2158 if (mTargetBssid != null) { 2159 sb.append(" Target Bssid=").append(mTargetBssid); 2160 } 2161 if (mLastBssid != null) { 2162 sb.append(" Last Bssid=").append(mLastBssid); 2163 } 2164 sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming)); 2165 break; 2166 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 2167 if (msg.obj != null) { 2168 sb.append(" ").append((DisconnectEventInfo) msg.obj); 2169 } 2170 if (mLastBssid != null) { 2171 sb.append(" lastbssid=").append(mLastBssid); 2172 } 2173 if (mWifiInfo.getFrequency() != -1) { 2174 sb.append(" freq=").append(mWifiInfo.getFrequency()); 2175 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2176 } 2177 break; 2178 case CMD_RSSI_POLL: 2179 case CMD_ONESHOT_RSSI_POLL: 2180 case CMD_UNWANTED_NETWORK: 2181 sb.append(" "); 2182 sb.append(Integer.toString(msg.arg1)); 2183 sb.append(" "); 2184 sb.append(Integer.toString(msg.arg2)); 2185 if (mWifiInfo.getSSID() != null) { 2186 if (mWifiInfo.getSSID() != null) { 2187 sb.append(" ").append(mWifiInfo.getSSID()); 2188 } 2189 } 2190 if (mWifiInfo.getBSSID() != null) { 2191 sb.append(" ").append(mWifiInfo.getBSSID()); 2192 } 2193 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2194 sb.append(" f=").append(mWifiInfo.getFrequency()); 2195 sb.append(" sc=").append(mWifiInfo.getScore()); 2196 sb.append(" link=").append(mWifiInfo.getLinkSpeed()); 2197 sb.append(" tx=").append( 2198 ((int) (mWifiInfo.getSuccessfulTxPacketsPerSecond() * 10)) / 10.0); 2199 sb.append(", ").append( 2200 ((int) (mWifiInfo.getRetriedTxPacketsPerSecond() * 10)) / 10.0); 2201 sb.append(", ").append(((int) (mWifiInfo.getLostTxPacketsPerSecond() * 10)) / 10.0); 2202 sb.append(" rx=").append( 2203 ((int) (mWifiInfo.getSuccessfulRxPacketsPerSecond() * 10)) / 10.0); 2204 sb.append(" bcn=" + mRunningBeaconCount); 2205 report = reportOnTime(); 2206 if (report != null) { 2207 sb.append(" ").append(report); 2208 } 2209 sb.append(" score=" + mWifiInfo.getScore()); 2210 break; 2211 case CMD_START_CONNECT: 2212 sb.append(" "); 2213 sb.append(Integer.toString(msg.arg1)); 2214 sb.append(" "); 2215 sb.append(Integer.toString(msg.arg2)); 2216 config = mWifiConfigManager.getConfiguredNetwork(msg.arg1); 2217 if (config != null) { 2218 sb.append(" targetConfigKey=").append(config.getProfileKey()); 2219 sb.append(" BSSID=" + config.BSSID); 2220 } 2221 if (mTargetBssid != null) { 2222 sb.append(" targetBssid=").append(mTargetBssid); 2223 } 2224 sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming)); 2225 config = getConnectedWifiConfigurationInternal(); 2226 if (config != null) { 2227 sb.append(" currentConfigKey=").append(config.getProfileKey()); 2228 } 2229 break; 2230 case CMD_START_ROAM: 2231 sb.append(" "); 2232 sb.append(Integer.toString(msg.arg1)); 2233 sb.append(" "); 2234 sb.append(Integer.toString(msg.arg2)); 2235 String bssid = (String) msg.obj; 2236 sb.append(" bssid=").append(bssid); 2237 if (mTargetBssid != null) { 2238 sb.append(" ").append(mTargetBssid); 2239 } 2240 sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming)); 2241 sb.append(" fail count=").append(Integer.toString(mRoamFailCount)); 2242 break; 2243 case CMD_PRE_DHCP_ACTION: 2244 sb.append(" "); 2245 sb.append(Integer.toString(msg.arg1)); 2246 sb.append(" "); 2247 sb.append(Integer.toString(msg.arg2)); 2248 sb.append(" txpkts=").append(mWifiInfo.txSuccess); 2249 sb.append(",").append(mWifiInfo.txBad); 2250 sb.append(",").append(mWifiInfo.txRetries); 2251 break; 2252 case CMD_POST_DHCP_ACTION: 2253 if (mLinkProperties != null) { 2254 sb.append(" "); 2255 sb.append(getLinkPropertiesSummary(mLinkProperties)); 2256 } 2257 break; 2258 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 2259 sb.append(" "); 2260 sb.append(Integer.toString(msg.arg1)); 2261 sb.append(" "); 2262 sb.append(Integer.toString(msg.arg2)); 2263 if (msg.obj != null) { 2264 NetworkInfo info = (NetworkInfo) msg.obj; 2265 NetworkInfo.State state = info.getState(); 2266 NetworkInfo.DetailedState detailedState = info.getDetailedState(); 2267 if (state != null) { 2268 sb.append(" st=").append(state); 2269 } 2270 if (detailedState != null) { 2271 sb.append("/").append(detailedState); 2272 } 2273 } 2274 break; 2275 case CMD_IP_CONFIGURATION_LOST: 2276 int count = -1; 2277 WifiConfiguration c = getConnectedWifiConfigurationInternal(); 2278 if (c != null) { 2279 count = c.getNetworkSelectionStatus().getDisableReasonCounter( 2280 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 2281 } 2282 sb.append(" "); 2283 sb.append(Integer.toString(msg.arg1)); 2284 sb.append(" "); 2285 sb.append(Integer.toString(msg.arg2)); 2286 sb.append(" failures: "); 2287 sb.append(Integer.toString(count)); 2288 sb.append("/"); 2289 sb.append(Integer.toString(mFacade.getIntegerSetting( 2290 mContext, Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT, 0))); 2291 if (mWifiInfo.getBSSID() != null) { 2292 sb.append(" ").append(mWifiInfo.getBSSID()); 2293 } 2294 sb.append(" bcn=" + mRunningBeaconCount); 2295 break; 2296 case CMD_UPDATE_LINKPROPERTIES: 2297 sb.append(" "); 2298 sb.append(Integer.toString(msg.arg1)); 2299 sb.append(" "); 2300 sb.append(Integer.toString(msg.arg2)); 2301 if (mLinkProperties != null) { 2302 sb.append(" "); 2303 sb.append(getLinkPropertiesSummary(mLinkProperties)); 2304 } 2305 break; 2306 case CMD_IP_REACHABILITY_LOST: 2307 if (msg.obj != null) { 2308 sb.append(" ").append((String) msg.obj); 2309 } 2310 break; 2311 case CMD_IP_REACHABILITY_FAILURE: 2312 if (msg.obj != null) { 2313 sb.append(" ").append(/* ReachabilityLossInfoParcelable */ msg.obj); 2314 } 2315 break; 2316 case CMD_INSTALL_PACKET_FILTER: 2317 sb.append(" len=" + ((byte[]) msg.obj).length); 2318 break; 2319 case CMD_SET_FALLBACK_PACKET_FILTERING: 2320 sb.append(" enabled=" + (boolean) msg.obj); 2321 break; 2322 case CMD_SET_MAX_DTIM_MULTIPLIER: 2323 sb.append(" maximum multiplier=" + msg.arg1); 2324 break; 2325 case CMD_ROAM_WATCHDOG_TIMER: 2326 sb.append(" "); 2327 sb.append(Integer.toString(msg.arg1)); 2328 sb.append(" "); 2329 sb.append(Integer.toString(msg.arg2)); 2330 sb.append(" cur=").append(mRoamWatchdogCount); 2331 break; 2332 case CMD_CONNECTING_WATCHDOG_TIMER: 2333 sb.append(" "); 2334 sb.append(Integer.toString(msg.arg1)); 2335 sb.append(" "); 2336 sb.append(Integer.toString(msg.arg2)); 2337 sb.append(" cur=").append(mConnectingWatchdogCount); 2338 break; 2339 case CMD_IPV4_PROVISIONING_SUCCESS: 2340 sb.append(" "); 2341 sb.append(/* DhcpResultsParcelable */ msg.obj); 2342 break; 2343 case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE: 2344 BtmFrameData frameData = (BtmFrameData) msg.obj; 2345 if (frameData != null) { 2346 sb.append(" ").append(frameData.toString()); 2347 } 2348 break; 2349 case WifiMonitor.NETWORK_NOT_FOUND_EVENT: 2350 sb.append(" ssid=" + msg.obj); 2351 break; 2352 case WifiMonitor.BSS_FREQUENCY_CHANGED_EVENT: 2353 sb.append(" frequency=" + msg.arg1); 2354 break; 2355 default: 2356 sb.append(" "); 2357 sb.append(Integer.toString(msg.arg1)); 2358 sb.append(" "); 2359 sb.append(Integer.toString(msg.arg2)); 2360 break; 2361 } 2362 2363 return sb.toString(); 2364 } 2365 2366 @Override getWhatToString(int what)2367 protected String getWhatToString(int what) { 2368 switch (what) { 2369 case CMD_ACCEPT_UNVALIDATED: 2370 return "CMD_ACCEPT_UNVALIDATED"; 2371 case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: 2372 return "CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF"; 2373 case CMD_BLUETOOTH_CONNECTION_STATE_CHANGE: 2374 return "CMD_BLUETOOTH_CONNECTION_STATE_CHANGE"; 2375 case CMD_CONFIG_ND_OFFLOAD: 2376 return "CMD_CONFIG_ND_OFFLOAD"; 2377 case CMD_CONNECTING_WATCHDOG_TIMER: 2378 return "CMD_CONNECTING_WATCHDOG_TIMER"; 2379 case CMD_CONNECT_NETWORK: 2380 return "CMD_CONNECT_NETWORK"; 2381 case CMD_DISCONNECT: 2382 return "CMD_DISCONNECT"; 2383 case CMD_ENABLE_RSSI_POLL: 2384 return "CMD_ENABLE_RSSI_POLL"; 2385 case CMD_INSTALL_PACKET_FILTER: 2386 return "CMD_INSTALL_PACKET_FILTER"; 2387 case CMD_IP_CONFIGURATION_LOST: 2388 return "CMD_IP_CONFIGURATION_LOST"; 2389 case CMD_IP_CONFIGURATION_SUCCESSFUL: 2390 return "CMD_IP_CONFIGURATION_SUCCESSFUL"; 2391 case CMD_IP_REACHABILITY_LOST: 2392 return "CMD_IP_REACHABILITY_LOST"; 2393 case CMD_IP_REACHABILITY_FAILURE: 2394 return "CMD_IP_REACHABILITY_FAILURE"; 2395 case CMD_IPCLIENT_STARTUP_TIMEOUT: 2396 return "CMD_IPCLIENT_STARTUP_TIMEOUT"; 2397 case CMD_IPV4_PROVISIONING_FAILURE: 2398 return "CMD_IPV4_PROVISIONING_FAILURE"; 2399 case CMD_IPV4_PROVISIONING_SUCCESS: 2400 return "CMD_IPV4_PROVISIONING_SUCCESS"; 2401 case CMD_NETWORK_STATUS: 2402 return "CMD_NETWORK_STATUS"; 2403 case CMD_ONESHOT_RSSI_POLL: 2404 return "CMD_ONESHOT_RSSI_POLL"; 2405 case CMD_POST_DHCP_ACTION: 2406 return "CMD_POST_DHCP_ACTION"; 2407 case CMD_PRE_DHCP_ACTION: 2408 return "CMD_PRE_DHCP_ACTION"; 2409 case CMD_PRE_DHCP_ACTION_COMPLETE: 2410 return "CMD_PRE_DHCP_ACTION_COMPLETE"; 2411 case CMD_READ_PACKET_FILTER: 2412 return "CMD_READ_PACKET_FILTER"; 2413 case CMD_REASSOCIATE: 2414 return "CMD_REASSOCIATE"; 2415 case CMD_RECONNECT: 2416 return "CMD_RECONNECT"; 2417 case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF: 2418 return "CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF"; 2419 case CMD_RESET_SIM_NETWORKS: 2420 return "CMD_RESET_SIM_NETWORKS"; 2421 case CMD_ROAM_WATCHDOG_TIMER: 2422 return "CMD_ROAM_WATCHDOG_TIMER"; 2423 case CMD_RSSI_POLL: 2424 return "CMD_RSSI_POLL"; 2425 case CMD_SAVE_NETWORK: 2426 return "CMD_SAVE_NETWORK"; 2427 case CMD_SCREEN_STATE_CHANGED: 2428 return "CMD_SCREEN_STATE_CHANGED"; 2429 case CMD_SET_FALLBACK_PACKET_FILTERING: 2430 return "CMD_SET_FALLBACK_PACKET_FILTERING"; 2431 case CMD_SET_MAX_DTIM_MULTIPLIER: 2432 return "CMD_SET_MAX_DTIM_MULTIPLIER"; 2433 case CMD_SET_SUSPEND_OPT_ENABLED: 2434 return "CMD_SET_SUSPEND_OPT_ENABLED"; 2435 case CMD_START_CONNECT: 2436 return "CMD_START_CONNECT"; 2437 case CMD_START_FILS_CONNECTION: 2438 return "CMD_START_FILS_CONNECTION"; 2439 case CMD_START_IP_PACKET_OFFLOAD: 2440 return "CMD_START_IP_PACKET_OFFLOAD"; 2441 case CMD_START_ROAM: 2442 return "CMD_START_ROAM"; 2443 case CMD_STOP_IP_PACKET_OFFLOAD: 2444 return "CMD_STOP_IP_PACKET_OFFLOAD"; 2445 case CMD_UNWANTED_NETWORK: 2446 return "CMD_UNWANTED_NETWORK"; 2447 case CMD_UPDATE_LINKPROPERTIES: 2448 return "CMD_UPDATE_LINKPROPERTIES"; 2449 case CMD_IPCLIENT_CREATED: 2450 return "CMD_IPCLIENT_CREATED"; 2451 case CMD_ACCEPT_EAP_SERVER_CERTIFICATE: 2452 return "CMD_ACCEPT_EAP_SERVER_CERTIFICATE"; 2453 case CMD_REJECT_EAP_INSECURE_CONNECTION: 2454 return "CMD_REJECT_EAP_SERVER_CERTIFICATE"; 2455 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 2456 return "SUPPLICANT_STATE_CHANGE_EVENT"; 2457 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 2458 return "AUTHENTICATION_FAILURE_EVENT"; 2459 case WifiMonitor.SUP_REQUEST_IDENTITY: 2460 return "SUP_REQUEST_IDENTITY"; 2461 case WifiMonitor.NETWORK_CONNECTION_EVENT: 2462 return "NETWORK_CONNECTION_EVENT"; 2463 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 2464 return "NETWORK_DISCONNECTION_EVENT"; 2465 case WifiMonitor.ASSOCIATED_BSSID_EVENT: 2466 return "ASSOCIATED_BSSID_EVENT"; 2467 case WifiMonitor.TARGET_BSSID_EVENT: 2468 return "TARGET_BSSID_EVENT"; 2469 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 2470 return "ASSOCIATION_REJECTION_EVENT"; 2471 case WifiMonitor.ANQP_DONE_EVENT: 2472 return "ANQP_DONE_EVENT"; 2473 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 2474 return "RX_HS20_ANQP_ICON_EVENT"; 2475 case WifiMonitor.GAS_QUERY_DONE_EVENT: 2476 return "GAS_QUERY_DONE_EVENT"; 2477 case WifiMonitor.HS20_REMEDIATION_EVENT: 2478 return "HS20_REMEDIATION_EVENT"; 2479 case WifiMonitor.HS20_DEAUTH_IMMINENT_EVENT: 2480 return "HS20_DEAUTH_IMMINENT_EVENT"; 2481 case WifiMonitor.HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT: 2482 return "HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT"; 2483 case WifiMonitor.GAS_QUERY_START_EVENT: 2484 return "GAS_QUERY_START_EVENT"; 2485 case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE: 2486 return "MBO_OCE_BSS_TM_HANDLING_DONE"; 2487 case WifiMonitor.TRANSITION_DISABLE_INDICATION: 2488 return "TRANSITION_DISABLE_INDICATION"; 2489 case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT: 2490 return "GROUP_CREATING_TIMED_OUT"; 2491 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 2492 return "P2P_CONNECTION_CHANGED"; 2493 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 2494 return "DISCONNECT_WIFI_REQUEST"; 2495 case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE: 2496 return "DISCONNECT_WIFI_RESPONSE"; 2497 case WifiP2pServiceImpl.SET_MIRACAST_MODE: 2498 return "SET_MIRACAST_MODE"; 2499 case WifiP2pServiceImpl.BLOCK_DISCOVERY: 2500 return "BLOCK_DISCOVERY"; 2501 case WifiMonitor.NETWORK_NOT_FOUND_EVENT: 2502 return "NETWORK_NOT_FOUND_EVENT"; 2503 case WifiMonitor.TOFU_CERTIFICATE_EVENT: 2504 return "TOFU_CERTIFICATE_EVENT"; 2505 case WifiMonitor.BSS_FREQUENCY_CHANGED_EVENT: 2506 return "BSS_FREQUENCY_CHANGED_EVENT"; 2507 case RunnerState.STATE_ENTER_CMD: 2508 return "Enter"; 2509 case RunnerState.STATE_EXIT_CMD: 2510 return "Exit"; 2511 default: 2512 return "what:" + what; 2513 } 2514 } 2515 2516 /** Check whether this connection is the primary connection on the device. */ isPrimary()2517 private boolean isPrimary() { 2518 return mClientModeManager.getRole() == ROLE_CLIENT_PRIMARY; 2519 } 2520 isScanOnly()2521 private boolean isScanOnly() { 2522 return mClientModeManager.getRole() == ActiveModeManager.ROLE_CLIENT_SCAN_ONLY; 2523 } 2524 2525 /** Check whether this connection is the secondary internet wifi connection. */ isSecondaryInternet()2526 private boolean isSecondaryInternet() { 2527 return mClientModeManager.getRole() == ROLE_CLIENT_SECONDARY_LONG_LIVED 2528 && mClientModeManager.isSecondaryInternet(); 2529 } 2530 2531 /** Check whether this connection is for local only network. */ isLocalOnly()2532 private boolean isLocalOnly() { 2533 return mClientModeManager.getRole() == ROLE_CLIENT_LOCAL_ONLY; 2534 } 2535 2536 /** 2537 * Check if originaly requested as local only for ClientModeManager before fallback. 2538 * A secondary role could fallback to primary due to hardware support limit. 2539 * @return true if the original request for ClientModeManager is local only. 2540 */ isRequestedForLocalOnly(WifiConfiguration currentWifiConfiguration, String currentBssid)2541 public boolean isRequestedForLocalOnly(WifiConfiguration currentWifiConfiguration, 2542 String currentBssid) { 2543 Set<Integer> uids = 2544 mNetworkFactory.getSpecificNetworkRequestUids( 2545 currentWifiConfiguration, currentBssid); 2546 // Check if there is an active specific request in WifiNetworkFactory for local only. 2547 return !uids.isEmpty(); 2548 } 2549 handleScreenStateChanged(boolean screenOn)2550 private void handleScreenStateChanged(boolean screenOn) { 2551 mScreenOn = screenOn; 2552 if (mVerboseLoggingEnabled) { 2553 logd(" handleScreenStateChanged Enter: screenOn=" + screenOn 2554 + " mSuspendOptimizationsEnabled=" 2555 + mContext.getResources().getBoolean( 2556 R.bool.config_wifiSuspendOptimizationsEnabled) 2557 + " state " + getCurrentState().getName()); 2558 } 2559 if (isPrimary() || isSecondaryInternet()) { 2560 // Only enable RSSI polling on primary STA, none of the secondary STA use-cases 2561 // can become the default route when other networks types that provide internet 2562 // connectivity (e.g. cellular) are available. So, no point in scoring 2563 // these connections for the purpose of switching between wifi and other network 2564 // types. 2565 // TODO(b/179518316): Enable this for secondary transient STA also if external scorer 2566 // is in charge of MBB. 2567 enableRssiPolling(screenOn); 2568 } 2569 if (mContext.getResources().getBoolean(R.bool.config_wifiSuspendOptimizationsEnabled)) { 2570 int shouldReleaseWakeLock = 0; 2571 if (screenOn) { 2572 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, shouldReleaseWakeLock); 2573 } else { 2574 if (isConnected()) { 2575 // Allow 2s for suspend optimizations to be set 2576 mSuspendWakeLock.acquire(2000); 2577 shouldReleaseWakeLock = 1; 2578 } 2579 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, shouldReleaseWakeLock); 2580 } 2581 } 2582 2583 if (isConnected()) { 2584 getWifiLinkLayerStats(); 2585 } 2586 mOnTimeScreenStateChange = mOnTime; 2587 mLastScreenStateChangeTimeStamp = mLastLinkLayerStatsUpdate; 2588 2589 if (mVerboseLoggingEnabled) log("handleScreenStateChanged Exit: " + screenOn); 2590 } 2591 setSuspendOptimizationsNative(int reason, boolean enabled)2592 private void setSuspendOptimizationsNative(int reason, boolean enabled) { 2593 if (mVerboseLoggingEnabled) { 2594 log("setSuspendOptimizationsNative: " + reason + " " + enabled 2595 + " -want " + mContext.getResources().getBoolean( 2596 R.bool.config_wifiSuspendOptimizationsEnabled) 2597 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 2598 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 2599 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 2600 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 2601 } 2602 //mWifiNative.setSuspendOptimizations(enabled); 2603 2604 if (enabled) { 2605 mSuspendOptNeedsDisabled &= ~reason; 2606 /* None of dhcp, screen or highperf need it disabled and user wants it enabled */ 2607 if (mSuspendOptNeedsDisabled == 0 2608 && mContext.getResources().getBoolean( 2609 R.bool.config_wifiSuspendOptimizationsEnabled)) { 2610 if (mVerboseLoggingEnabled) { 2611 log("setSuspendOptimizationsNative do it " + reason + " " + enabled 2612 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 2613 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 2614 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 2615 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 2616 } 2617 mWifiNative.setSuspendOptimizations(mInterfaceName, true); 2618 } 2619 } else { 2620 mSuspendOptNeedsDisabled |= reason; 2621 mWifiNative.setSuspendOptimizations(mInterfaceName, false); 2622 } 2623 } 2624 2625 /** 2626 * Makes a record of the user intent about suspend optimizations. 2627 */ setSuspendOptimizations(int reason, boolean enabled)2628 private void setSuspendOptimizations(int reason, boolean enabled) { 2629 if (mVerboseLoggingEnabled) log("setSuspendOptimizations: " + reason + " " + enabled); 2630 if (enabled) { 2631 mSuspendOptNeedsDisabled &= ~reason; 2632 } else { 2633 mSuspendOptNeedsDisabled |= reason; 2634 } 2635 if (mVerboseLoggingEnabled) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 2636 } 2637 2638 /* 2639 * Fetch link layer stats, RSSI, linkspeed, and frequency on current connection 2640 * and update Network capabilities 2641 */ updateLinkLayerStatsRssiSpeedFrequencyCapabilities(long txBytes, long rxBytes)2642 private WifiLinkLayerStats updateLinkLayerStatsRssiSpeedFrequencyCapabilities(long txBytes, 2643 long rxBytes) { 2644 WifiLinkLayerStats stats = getWifiLinkLayerStats(); 2645 WifiSignalPollResults pollResults = mWifiNative.signalPoll(mInterfaceName); 2646 if (pollResults == null) { 2647 return stats; 2648 } 2649 2650 int newRssi = pollResults.getRssi(); 2651 int newTxLinkSpeed = pollResults.getTxLinkSpeed(); 2652 int newFrequency = pollResults.getFrequency(); 2653 int newRxLinkSpeed = pollResults.getRxLinkSpeed(); 2654 boolean updateNetworkCapabilities = false; 2655 2656 if (mVerboseLoggingEnabled) { 2657 logd("updateLinkLayerStatsRssiSpeedFrequencyCapabilities rssi=" + newRssi 2658 + " TxLinkspeed=" + newTxLinkSpeed + " freq=" + newFrequency 2659 + " RxLinkSpeed=" + newRxLinkSpeed); 2660 } 2661 2662 /* Set link specific signal poll results */ 2663 for (MloLink link : mWifiInfo.getAffiliatedMloLinks()) { 2664 int linkId = link.getLinkId(); 2665 link.setRssi(pollResults.getRssi(linkId)); 2666 link.setTxLinkSpeedMbps(pollResults.getTxLinkSpeed(linkId)); 2667 link.setRxLinkSpeedMbps(pollResults.getRxLinkSpeed(linkId)); 2668 link.setChannel(ScanResult.convertFrequencyMhzToChannelIfSupported( 2669 pollResults.getFrequency(linkId))); 2670 link.setBand(ScanResult.toBand(pollResults.getFrequency(linkId))); 2671 if (mVerboseLoggingEnabled) { 2672 logd("linkId=" + linkId + " rssi=" + link.getRssi() 2673 + " channel=" + link.getChannel() 2674 + " band=" + link.getBand() 2675 + " TxLinkspeed=" + link.getTxLinkSpeedMbps() 2676 + " RxLinkSpeed=" + link.getRxLinkSpeedMbps()); 2677 } 2678 } 2679 2680 /* 2681 * set Tx link speed only if it is valid 2682 */ 2683 if (newTxLinkSpeed > 0) { 2684 mWifiInfo.setLinkSpeed(newTxLinkSpeed); 2685 mWifiInfo.setTxLinkSpeedMbps(newTxLinkSpeed); 2686 } 2687 /* 2688 * set Rx link speed only if it is valid 2689 */ 2690 if (newRxLinkSpeed > 0) { 2691 mWifiInfo.setRxLinkSpeedMbps(newRxLinkSpeed); 2692 } 2693 if (newFrequency > 0) { 2694 if (mWifiInfo.getFrequency() != newFrequency) { 2695 updateNetworkCapabilities = true; 2696 } 2697 mWifiInfo.setFrequency(newFrequency); 2698 } 2699 // updateLinkBandwidth() requires the latest frequency information 2700 if (newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) { 2701 /* 2702 * Positive RSSI is possible when devices are close(~0m apart) to each other. 2703 * And there are some driver/firmware implementation, where they avoid 2704 * reporting large negative rssi values by adding 256. 2705 * so adjust the valid rssi reports for such implementations. 2706 */ 2707 if (newRssi > (WifiInfo.INVALID_RSSI + 256)) { 2708 Log.wtf(getTag(), "Error! +ve value RSSI: " + newRssi); 2709 newRssi -= 256; 2710 } 2711 mWifiInfo.setRssi(newRssi); 2712 /* 2713 * Rather than sending the raw RSSI out every time it 2714 * changes, we precalculate the signal level that would 2715 * be displayed in the status bar, and only send the 2716 * broadcast if that much more coarse-grained number 2717 * changes. This cuts down greatly on the number of 2718 * broadcasts, at the cost of not informing others 2719 * interested in RSSI of all the changes in signal 2720 * level. 2721 */ 2722 int newSignalLevel = RssiUtil.calculateSignalLevel(mContext, newRssi); 2723 if (newSignalLevel != mLastSignalLevel) { 2724 sendRssiChangeBroadcast(newRssi); 2725 updateNetworkCapabilities = true; 2726 } 2727 updateLinkBandwidthAndCapabilities(stats, updateNetworkCapabilities, txBytes, 2728 rxBytes); 2729 mLastSignalLevel = newSignalLevel; 2730 } else { 2731 mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); 2732 updateCapabilities(); 2733 mLastSignalLevel = -1; 2734 } 2735 mWifiConfigManager.updateScanDetailCacheFromWifiInfo(mWifiInfo); 2736 /* 2737 * Increment various performance metrics 2738 */ 2739 mWifiMetrics.handlePollResult(mInterfaceName, mWifiInfo); 2740 updateCurrentConnectionInfo(); 2741 return stats; 2742 } 2743 2744 // Update the link bandwidth. Also update network capabilities if the link bandwidth changes 2745 // by a large amount or there is a change in signal level or frequency. updateLinkBandwidthAndCapabilities(WifiLinkLayerStats stats, boolean updateNetworkCapabilities, long txBytes, long rxBytes)2746 private void updateLinkBandwidthAndCapabilities(WifiLinkLayerStats stats, 2747 boolean updateNetworkCapabilities, long txBytes, long rxBytes) { 2748 WifiScoreCard.PerNetwork network = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 2749 network.updateLinkBandwidth(mLastLinkLayerStats, stats, mWifiInfo, txBytes, rxBytes); 2750 int newTxKbps = network.getTxLinkBandwidthKbps(); 2751 int newRxKbps = network.getRxLinkBandwidthKbps(); 2752 int txDeltaKbps = Math.abs(newTxKbps - mLastTxKbps); 2753 int rxDeltaKbps = Math.abs(newRxKbps - mLastRxKbps); 2754 int bwUpdateThresholdPercent = mContext.getResources().getInteger( 2755 R.integer.config_wifiLinkBandwidthUpdateThresholdPercent); 2756 if ((txDeltaKbps * 100 > bwUpdateThresholdPercent * mLastTxKbps) 2757 || (rxDeltaKbps * 100 > bwUpdateThresholdPercent * mLastRxKbps) 2758 || updateNetworkCapabilities) { 2759 mLastTxKbps = newTxKbps; 2760 mLastRxKbps = newRxKbps; 2761 updateCapabilities(); 2762 } 2763 2764 int l2TxKbps = mWifiDataStall.getTxThroughputKbps(); 2765 int l2RxKbps = mWifiDataStall.getRxThroughputKbps(); 2766 if (l2RxKbps < 0 && l2TxKbps > 0) { 2767 l2RxKbps = l2TxKbps; 2768 } 2769 int [] reportedKbps = {mLastTxKbps, mLastRxKbps}; 2770 int [] l2Kbps = {l2TxKbps, l2RxKbps}; 2771 network.updateBwMetrics(reportedKbps, l2Kbps); 2772 } 2773 2774 // Polling has completed, hence we won't have a score anymore cleanWifiScore()2775 private void cleanWifiScore() { 2776 mWifiInfo.setLostTxPacketsPerSecond(0); 2777 mWifiInfo.setSuccessfulTxPacketsPerSecond(0); 2778 mWifiInfo.setRetriedTxPacketsRate(0); 2779 mWifiInfo.setSuccessfulRxPacketsPerSecond(0); 2780 mWifiScoreReport.reset(); 2781 mLastLinkLayerStats = null; 2782 updateCurrentConnectionInfo(); 2783 } 2784 updateLinkProperties(LinkProperties newLp)2785 private void updateLinkProperties(LinkProperties newLp) { 2786 if (mVerboseLoggingEnabled) { 2787 log("Link configuration changed for netId: " + mLastNetworkId 2788 + " old: " + mLinkProperties + " new: " + newLp); 2789 } 2790 // We own this instance of LinkProperties because IpClient passes us a copy. 2791 mLinkProperties = newLp; 2792 2793 if (mNetworkAgent != null) { 2794 mNetworkAgent.sendLinkProperties(mLinkProperties); 2795 } 2796 2797 if (mNetworkAgentState == DetailedState.CONNECTED) { 2798 // If anything has changed and we're already connected, send out a notification. 2799 // TODO: Update all callers to use NetworkCallbacks and delete this. 2800 sendLinkConfigurationChangedBroadcast(); 2801 } 2802 if (mVerboseLoggingEnabled) { 2803 StringBuilder sb = new StringBuilder(); 2804 sb.append("updateLinkProperties nid: " + mLastNetworkId); 2805 sb.append(" state: " + mNetworkAgentState); 2806 2807 if (mLinkProperties != null) { 2808 sb.append(" "); 2809 sb.append(getLinkPropertiesSummary(mLinkProperties)); 2810 } 2811 logd(sb.toString()); 2812 } 2813 } 2814 2815 /** 2816 * Clears all our link properties. 2817 */ clearLinkProperties()2818 private void clearLinkProperties() { 2819 // Clear the link properties obtained from DHCP. The only caller of this 2820 // function has already called IpClient#stop(), which clears its state. 2821 synchronized (mDhcpResultsParcelableLock) { 2822 mDhcpResultsParcelable = new DhcpResultsParcelable(); 2823 } 2824 2825 // Now clear the merged link properties. 2826 mLinkProperties.clear(); 2827 if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties); 2828 } 2829 2830 // TODO(b/193460475): Remove when tooling supports SystemApi to public API. 2831 @SuppressLint("NewApi") sendRssiChangeBroadcast(final int newRssi)2832 private void sendRssiChangeBroadcast(final int newRssi) { 2833 mBatteryStatsManager.reportWifiRssiChanged(newRssi); 2834 WifiStatsLog.write(WifiStatsLog.WIFI_SIGNAL_STRENGTH_CHANGED, 2835 RssiUtil.calculateSignalLevel(mContext, newRssi)); 2836 2837 Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION); 2838 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2839 intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi); 2840 final Bundle opts; 2841 if (SdkLevel.isAtLeastU()) { 2842 opts = BroadcastOptions.makeBasic() 2843 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) 2844 .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE) 2845 .toBundle(); 2846 } else { 2847 opts = null; 2848 } 2849 mBroadcastQueue.queueOrSendBroadcast( 2850 mClientModeManager, 2851 () -> mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 2852 android.Manifest.permission.ACCESS_WIFI_STATE, opts)); 2853 } 2854 sendLinkConfigurationChangedBroadcast()2855 private void sendLinkConfigurationChangedBroadcast() { 2856 Intent intent = new Intent(WifiManager.ACTION_LINK_CONFIGURATION_CHANGED); 2857 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2858 String summary = "broadcast=ACTION_LINK_CONFIGURATION_CHANGED"; 2859 if (mVerboseLoggingEnabled) Log.d(getTag(), "Queuing " + summary); 2860 mBroadcastQueue.queueOrSendBroadcast( 2861 mClientModeManager, 2862 () -> { 2863 if (mVerboseLoggingEnabled) Log.d(getTag(), "Sending " + summary); 2864 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 2865 }); 2866 } 2867 2868 /** 2869 * Helper method used to send state about supplicant - This is NOT information about the current 2870 * wifi connection state. 2871 * 2872 * TODO: b/79504296 This broadcast has been deprecated and should be removed 2873 */ sendSupplicantConnectionChangedBroadcast(boolean connected)2874 private void sendSupplicantConnectionChangedBroadcast(boolean connected) { 2875 Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 2876 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2877 intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected); 2878 String summary = "broadcast=SUPPLICANT_CONNECTION_CHANGE_ACTION" 2879 + " EXTRA_SUPPLICANT_CONNECTED=" + connected; 2880 if (mVerboseLoggingEnabled) Log.d(getTag(), "Queuing " + summary); 2881 mBroadcastQueue.queueOrSendBroadcast( 2882 mClientModeManager, 2883 () -> { 2884 if (mVerboseLoggingEnabled) Log.d(getTag(), "Sending " + summary); 2885 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 2886 }); 2887 } 2888 2889 /** 2890 * Record the detailed state of a network. 2891 * 2892 * @param state the new {@code DetailedState} 2893 */ sendNetworkChangeBroadcast(NetworkInfo.DetailedState state)2894 private void sendNetworkChangeBroadcast(NetworkInfo.DetailedState state) { 2895 boolean hidden = false; 2896 2897 if (mIsAutoRoaming) { 2898 // There is generally a confusion in the system about colluding 2899 // WiFi Layer 2 state (as reported by supplicant) and the Network state 2900 // which leads to multiple confusion. 2901 // 2902 // If link is roaming, we already have an IP address 2903 // as well we were connected and are doing L2 cycles of 2904 // reconnecting or renewing IP address to check that we still have it 2905 // This L2 link flapping should not be reflected into the Network state 2906 // which is the state of the WiFi Network visible to Layer 3 and applications 2907 // Note that once roaming is completed, we will 2908 // set the Network state to where it should be, or leave it as unchanged 2909 // 2910 hidden = true; 2911 } 2912 if (mVerboseLoggingEnabled) { 2913 log("sendNetworkChangeBroadcast" 2914 + " oldState=" + mNetworkAgentState 2915 + " newState=" + state 2916 + " hidden=" + hidden); 2917 } 2918 if (hidden || state == mNetworkAgentState) return; 2919 mNetworkAgentState = state; 2920 sendNetworkChangeBroadcastWithCurrentState(); 2921 } 2922 getNetworkStateListenerCmmRole()2923 private int getNetworkStateListenerCmmRole() { 2924 if (isPrimary() || isScanOnly()) { 2925 // Wifi disconnect could be received in ScanOnlyMode when wifi scanning is enabled since 2926 // the mode switch happens before the disconnect actually happens. Therefore, treat 2927 // the scan only mode the same as primary since only the primary is allowed to change 2928 // into scan only mode. 2929 return WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY; 2930 } 2931 if (isSecondaryInternet()) { 2932 return WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_SECONDARY_INTERNET; 2933 } 2934 if (isLocalOnly()) { 2935 return WifiManager.WifiNetworkStateChangedListener 2936 .WIFI_ROLE_CLIENT_SECONDARY_LOCAL_ONLY; 2937 } 2938 return -1; 2939 } 2940 convertDetailedStateToNetworkStateChangedCode(DetailedState detailedState)2941 private int convertDetailedStateToNetworkStateChangedCode(DetailedState detailedState) { 2942 switch (detailedState) { 2943 case IDLE: 2944 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_IDLE; 2945 case SCANNING: 2946 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_SCANNING; 2947 case CONNECTING: 2948 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_CONNECTING; 2949 case AUTHENTICATING: 2950 return WifiManager.WifiNetworkStateChangedListener 2951 .WIFI_NETWORK_STATUS_AUTHENTICATING; 2952 case OBTAINING_IPADDR: 2953 return WifiManager.WifiNetworkStateChangedListener 2954 .WIFI_NETWORK_STATUS_OBTAINING_IPADDR; 2955 case CONNECTED: 2956 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_CONNECTED; 2957 case DISCONNECTED: 2958 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_DISCONNECTED; 2959 case FAILED: 2960 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_FAILED; 2961 default: 2962 // There are some DetailedState codes that are not being used in wifi, so ignore 2963 // them. 2964 return -1; 2965 } 2966 } 2967 sendNetworkChangeBroadcastWithCurrentState()2968 private void sendNetworkChangeBroadcastWithCurrentState() { 2969 // copy into local variables to force lambda to capture by value and not reference, since 2970 // mNetworkAgentState is mutable and can change 2971 final DetailedState networkAgentState = mNetworkAgentState; 2972 if (mVerboseLoggingEnabled) { 2973 Log.d(getTag(), "Queueing broadcast=NETWORK_STATE_CHANGED_ACTION" 2974 + " networkAgentState=" + networkAgentState); 2975 } 2976 int networkStateChangedCmmRole = getNetworkStateListenerCmmRole(); 2977 int networkStateChangedState = convertDetailedStateToNetworkStateChangedCode( 2978 networkAgentState); 2979 if (networkStateChangedCmmRole != -1 && networkStateChangedState != -1) { 2980 mWifiInjector.getActiveModeWarden().onNetworkStateChanged( 2981 networkStateChangedCmmRole, networkStateChangedState); 2982 } 2983 mBroadcastQueue.queueOrSendBroadcast( 2984 mClientModeManager, 2985 () -> sendNetworkChangeBroadcast( 2986 mContext, networkAgentState, mVerboseLoggingEnabled)); 2987 } 2988 2989 /** Send a NETWORK_STATE_CHANGED_ACTION broadcast. */ sendNetworkChangeBroadcast( Context context, DetailedState networkAgentState, boolean verboseLoggingEnabled)2990 public static void sendNetworkChangeBroadcast( 2991 Context context, DetailedState networkAgentState, boolean verboseLoggingEnabled) { 2992 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); 2993 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2994 NetworkInfo networkInfo = makeNetworkInfo(networkAgentState); 2995 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo); 2996 if (verboseLoggingEnabled) { 2997 Log.d(TAG, "Sending broadcast=NETWORK_STATE_CHANGED_ACTION" 2998 + " networkAgentState=" + networkAgentState); 2999 } 3000 //TODO(b/69974497) This should be non-sticky, but settings needs fixing first. 3001 if (SdkLevel.isAtLeastU()) { 3002 final Context userAllContext = context.createContextAsUser( 3003 UserHandle.ALL, 0 /* flags */); 3004 final Bundle opts = BroadcastOptions.makeBasic() 3005 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) 3006 .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE) 3007 .toBundle(); 3008 userAllContext.sendStickyBroadcast(intent, opts); 3009 } else { 3010 context.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3011 } 3012 } 3013 makeNetworkInfo(DetailedState networkAgentState)3014 private static NetworkInfo makeNetworkInfo(DetailedState networkAgentState) { 3015 final NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, ""); 3016 ni.setDetailedState(networkAgentState, null, null); 3017 return ni; 3018 } 3019 findMatchingInfoElements(@ullable String bssid)3020 private List<ScanResult.InformationElement> findMatchingInfoElements(@Nullable String bssid) { 3021 if (bssid == null) return null; 3022 ScanResult matchingScanResult = mScanRequestProxy.getScanResult(bssid); 3023 if (matchingScanResult == null || matchingScanResult.informationElements == null) { 3024 return null; 3025 } 3026 return Arrays.asList(matchingScanResult.informationElements); 3027 } 3028 setMultiLinkInfoFromScanCache(@ullable String bssid)3029 private void setMultiLinkInfoFromScanCache(@Nullable String bssid) { 3030 if (bssid == null) return; 3031 ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork( 3032 mWifiInfo.getNetworkId()); 3033 ScanResult matchingScanResult = null; 3034 if (scanDetailCache != null) { 3035 matchingScanResult = scanDetailCache.getScanResult(bssid); 3036 } 3037 /** 3038 * If FW roams to a new AP, the BSSID may not be in the scan detailed cache. Set Multi-Link 3039 * info only if the BSSID is present in the scan detailed cache and AP is a Multi-Link 3040 * Device. If not, clear Multi-Link info from WifiInfo. After association 3041 * {@link ClientModeImpl#updateMloLinkAddrAndStates(ConnectionMloLinksInfo)} will update 3042 * the Multi-Link info from supplicant if present. 3043 */ 3044 if (matchingScanResult != null && matchingScanResult.getApMldMacAddress() != null) { 3045 mWifiInfo.setApMldMacAddress(matchingScanResult.getApMldMacAddress()); 3046 mWifiInfo.setApMloLinkId(matchingScanResult.getApMloLinkId()); 3047 mWifiInfo.setAffiliatedMloLinks(matchingScanResult.getAffiliatedMloLinks()); 3048 } else { 3049 mWifiInfo.setApMldMacAddress(null); 3050 mWifiInfo.setApMloLinkId(MloLink.INVALID_MLO_LINK_ID); 3051 mWifiInfo.setAffiliatedMloLinks(Collections.emptyList()); 3052 } 3053 updateCurrentConnectionInfo(); 3054 } 3055 3056 /** 3057 * Multi-link info should not be set from scan cache after 'SupplicantState.ASSOCIATED' as it 3058 * overwrites link states collected during ASSOCIATION. Return if multi-link info is settable 3059 * on the current state. 3060 */ isMultiLinkInfoSettableFromScanCache(SupplicantState currentState)3061 private boolean isMultiLinkInfoSettableFromScanCache(SupplicantState currentState) { 3062 return currentState != SupplicantState.FOUR_WAY_HANDSHAKE 3063 && currentState != SupplicantState.GROUP_HANDSHAKE 3064 && currentState != SupplicantState.COMPLETED; 3065 } 3066 handleSupplicantStateChange(StateChangeResult stateChangeResult)3067 private SupplicantState handleSupplicantStateChange(StateChangeResult stateChangeResult) { 3068 SupplicantState state = stateChangeResult.state; 3069 mWifiScoreCard.noteSupplicantStateChanging(mWifiInfo, state); 3070 // Supplicant state change 3071 // [31-13] Reserved for future use 3072 // [8 - 0] Supplicant state (as defined in SupplicantState.java) 3073 // 50023 supplicant_state_changed (custom|1|5) 3074 mWifiInfo.setSupplicantState(state); 3075 // Network id and SSID are only valid when we start connecting 3076 if (SupplicantState.isConnecting(state)) { 3077 mWifiInfo.setNetworkId(stateChangeResult.networkId); 3078 mWifiInfo.setBSSID(stateChangeResult.bssid); 3079 mWifiInfo.setSSID(stateChangeResult.wifiSsid); 3080 if (stateChangeResult.frequencyMhz > 0) { 3081 mWifiInfo.setFrequency(stateChangeResult.frequencyMhz); 3082 } 3083 // Multi-link info is set from scan cache (multi-link state: unassociated). On 3084 // association, connection capabilities and multi-link state are queried from 3085 // supplicant and link info is updated. (multi-link state: active/idle). After 3086 // association, don't set the multi-link info from scan cache. 3087 if (isMultiLinkInfoSettableFromScanCache(state)) { 3088 setMultiLinkInfoFromScanCache(stateChangeResult.bssid); 3089 } 3090 if (state == SupplicantState.ASSOCIATED) { 3091 updateWifiInfoLinkParamsAfterAssociation(); 3092 } 3093 mWifiInfo.setInformationElements(findMatchingInfoElements(stateChangeResult.bssid)); 3094 } else { 3095 // Reset parameters according to WifiInfo.reset() 3096 mWifiBlocklistMonitor.removeAffiliatedBssids(mWifiInfo.getBSSID()); 3097 mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); 3098 mWifiInfo.setBSSID(null); 3099 mWifiInfo.setSSID(null); 3100 mWifiInfo.setWifiStandard(ScanResult.WIFI_STANDARD_UNKNOWN); 3101 mWifiInfo.setInformationElements(null); 3102 mWifiInfo.clearCurrentSecurityType(); 3103 mWifiInfo.resetMultiLinkInfo(); 3104 } 3105 3106 // SSID might have been updated, so call updateCapabilities 3107 updateCapabilities(); 3108 3109 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 3110 if (config == null) { 3111 // If not connected, this should be non-null. 3112 config = getConnectingWifiConfigurationInternal(); 3113 } 3114 if (config != null && config.networkId == mWifiInfo.getNetworkId()) { 3115 updateWifiInfoWhenConnected(config); 3116 3117 // Set meteredHint if scan result says network is expensive 3118 ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork( 3119 config.networkId); 3120 if (scanDetailCache != null) { 3121 ScanDetail scanDetail = scanDetailCache.getScanDetail(stateChangeResult.bssid); 3122 if (scanDetail != null) { 3123 mWifiInfo.setFrequency(scanDetail.getScanResult().frequency); 3124 NetworkDetail networkDetail = scanDetail.getNetworkDetail(); 3125 if (networkDetail != null 3126 && networkDetail.getAnt() == NetworkDetail.Ant.ChargeablePublic) { 3127 mWifiInfo.setMeteredHint(true); 3128 } 3129 } 3130 } 3131 } 3132 mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); 3133 updateCurrentConnectionInfo(); 3134 return state; 3135 } 3136 handleNetworkConnectionEventInfo( WifiConfiguration config, NetworkConnectionEventInfo connectionInfo)3137 private void handleNetworkConnectionEventInfo( 3138 WifiConfiguration config, NetworkConnectionEventInfo connectionInfo) { 3139 if (connectionInfo == null) return; 3140 3141 mWifiInfo.setBSSID(connectionInfo.bssid); 3142 mWifiInfo.setNetworkId(connectionInfo.networkId); 3143 3144 if (config != null && connectionInfo.keyMgmtMask != null) { 3145 // Besides allowed key management, pmf and wep keys are necessary to 3146 // identify WPA3 Enterprise and WEP, so the original configuration 3147 // is still necessary. 3148 WifiConfiguration tmp = new WifiConfiguration(config); 3149 tmp.setSecurityParams(connectionInfo.keyMgmtMask); 3150 mWifiInfo.setCurrentSecurityType(tmp.getDefaultSecurityParams().getSecurityType()); 3151 // Update the last used security params. 3152 config.getNetworkSelectionStatus().setLastUsedSecurityParams( 3153 tmp.getDefaultSecurityParams()); 3154 mWifiConfigManager.setNetworkLastUsedSecurityParams(config.networkId, 3155 tmp.getDefaultSecurityParams()); 3156 Log.i(getTag(), "Update current security type to " + mWifiInfo.getCurrentSecurityType() 3157 + " from network connection event."); 3158 } 3159 } 3160 updateWifiInfoWhenConnected(@onNull WifiConfiguration config)3161 private void updateWifiInfoWhenConnected(@NonNull WifiConfiguration config) { 3162 mWifiInfo.setEphemeral(config.ephemeral); 3163 mWifiInfo.setTrusted(config.trusted); 3164 mWifiInfo.setOemPaid(config.oemPaid); 3165 mWifiInfo.setOemPrivate(config.oemPrivate); 3166 mWifiInfo.setCarrierMerged(config.carrierMerged); 3167 mWifiInfo.setSubscriptionId(config.subscriptionId); 3168 mWifiInfo.setOsuAp(config.osu); 3169 mWifiInfo.setRestricted(config.restricted); 3170 if (config.fromWifiNetworkSpecifier || config.fromWifiNetworkSuggestion) { 3171 mWifiInfo.setRequestingPackageName(config.creatorName); 3172 } 3173 mWifiInfo.setIsPrimary(isPrimary()); 3174 SecurityParams securityParams = config.getNetworkSelectionStatus() 3175 .getLastUsedSecurityParams(); 3176 if (securityParams != null) { 3177 Log.i(getTag(), "Update current security type to " + securityParams.getSecurityType()); 3178 mWifiInfo.setCurrentSecurityType(securityParams.getSecurityType()); 3179 } else { 3180 mWifiInfo.clearCurrentSecurityType(); 3181 Log.e(TAG, "Network connection candidate with no security parameters"); 3182 } 3183 updateCurrentConnectionInfo(); 3184 } 3185 3186 /** 3187 * Update mapping of affiliated BSSID in blocklist. Called when there is a change in MLO links. 3188 */ updateBlockListAffiliatedBssids()3189 private void updateBlockListAffiliatedBssids() { 3190 /** 3191 * getAffiliatedMloLinks() returns a list of MloLink objects for all the links 3192 * advertised by AP-MLD including the associated link. Update mWifiBlocklistMonitor 3193 * with all affiliated AP link MAC addresses, excluding the associated link, indexed 3194 * with associated AP link MAC address (BSSID). 3195 * For e.g. 3196 * link1_bssid -> affiliated {link2_bssid, link3_bssid} 3197 * Above mapping is used to block list all affiliated links when associated link is 3198 * block listed. 3199 */ 3200 List<String> affiliatedBssids = new ArrayList<>(); 3201 for (MloLink link : mWifiInfo.getAffiliatedMloLinks()) { 3202 if (link.getApMacAddress() != null && !Objects.equals(mWifiInfo.getBSSID(), 3203 link.getApMacAddress().toString())) { 3204 affiliatedBssids.add(link.getApMacAddress().toString()); 3205 } 3206 } 3207 mWifiBlocklistMonitor.setAffiliatedBssids(mWifiInfo.getBSSID(), affiliatedBssids); 3208 } 3209 3210 /** 3211 * Clear MLO link states to UNASSOCIATED. 3212 */ clearMloLinkStates()3213 private void clearMloLinkStates() { 3214 for (MloLink link : mWifiInfo.getAffiliatedMloLinks()) { 3215 link.setState(MloLink.MLO_LINK_STATE_UNASSOCIATED); 3216 } 3217 } 3218 3219 /** 3220 * Update the MLO link states to ACTIVE or IDLE depending on any traffic stream is mapped to the 3221 * link. 3222 * 3223 * @param info MLO link object from HAL. 3224 */ updateMloLinkStates(@ullable WifiNative.ConnectionMloLinksInfo info)3225 private void updateMloLinkStates(@Nullable WifiNative.ConnectionMloLinksInfo info) { 3226 if (info == null) return; 3227 for (int i = 0; i < info.links.length; i++) { 3228 mWifiInfo.updateMloLinkState(info.links[i].getLinkId(), 3229 info.links[i].isAnyTidMapped() ? MloLink.MLO_LINK_STATE_ACTIVE 3230 : MloLink.MLO_LINK_STATE_IDLE); 3231 } 3232 } 3233 /** 3234 * Update the MLO link states to ACTIVE or IDLE depending on any traffic stream is mapped to the 3235 * link. Also, update the link MAC address. 3236 * 3237 * @param info MLO link object from HAL. 3238 */ updateMloLinkAddrAndStates(@ullable WifiNative.ConnectionMloLinksInfo info)3239 private void updateMloLinkAddrAndStates(@Nullable WifiNative.ConnectionMloLinksInfo info) { 3240 if (info == null) return; 3241 // At this stage, the expectation is that we already have MLO link information collected 3242 // from scan detailed cache. If the MLO link information is empty, probably FW/driver roamed 3243 // to a new AP which is not in scan detailed cache. Update MLO links with the details 3244 // provided by the supplicant in ConnectionMloLinksInfo. The supplicant provides only the 3245 // associated links. 3246 if (mWifiInfo.getAffiliatedMloLinks().isEmpty()) { 3247 mWifiInfo.setApMldMacAddress(info.apMldMacAddress); 3248 mWifiInfo.setApMloLinkId(info.apMloLinkId); 3249 List<MloLink> affiliatedMloLinks = new ArrayList<>(); 3250 for (int i = 0; i < info.links.length; i++) { 3251 MloLink link = new MloLink(); 3252 link.setLinkId(info.links[i].getLinkId()); 3253 link.setStaMacAddress(info.links[i].getStaMacAddress()); 3254 link.setApMacAddress(info.links[i].getApMacAddress()); 3255 link.setChannel(ScanResult.convertFrequencyMhzToChannelIfSupported( 3256 info.links[i].getFrequencyMHz())); 3257 link.setBand(ScanResult.toBand(info.links[i].getFrequencyMHz())); 3258 link.setState(info.links[i].isAnyTidMapped() ? MloLink.MLO_LINK_STATE_ACTIVE 3259 : MloLink.MLO_LINK_STATE_IDLE); 3260 affiliatedMloLinks.add(link); 3261 } 3262 mWifiInfo.setAffiliatedMloLinks(affiliatedMloLinks); 3263 } else { 3264 for (int i = 0; i < info.links.length; i++) { 3265 mWifiInfo.updateMloLinkStaAddress(info.links[i].getLinkId(), 3266 info.links[i].getStaMacAddress()); 3267 mWifiInfo.updateMloLinkState(info.links[i].getLinkId(), 3268 info.links[i].isAnyTidMapped() ? MloLink.MLO_LINK_STATE_ACTIVE 3269 : MloLink.MLO_LINK_STATE_IDLE); 3270 } 3271 } 3272 } 3273 updateWifiInfoLinkParamsAfterAssociation()3274 private void updateWifiInfoLinkParamsAfterAssociation() { 3275 mLastConnectionCapabilities = mWifiNative.getConnectionCapabilities(mInterfaceName); 3276 int maxTxLinkSpeedMbps = mThroughputPredictor.predictMaxTxThroughput( 3277 mLastConnectionCapabilities); 3278 int maxRxLinkSpeedMbps = mThroughputPredictor.predictMaxRxThroughput( 3279 mLastConnectionCapabilities); 3280 mWifiInfo.setWifiStandard(mLastConnectionCapabilities.wifiStandard); 3281 mWifiInfo.setMaxSupportedTxLinkSpeedMbps(maxTxLinkSpeedMbps); 3282 mWifiInfo.setMaxSupportedRxLinkSpeedMbps(maxRxLinkSpeedMbps); 3283 mWifiInfo.enableApTidToLinkMappingNegotiationSupport( 3284 mLastConnectionCapabilities.apTidToLinkMapNegotiationSupported); 3285 mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(mInterfaceName, 3286 maxTxLinkSpeedMbps, maxRxLinkSpeedMbps); 3287 if (mLastConnectionCapabilities.wifiStandard == ScanResult.WIFI_STANDARD_11BE) { 3288 updateMloLinkAddrAndStates(mWifiNative.getConnectionMloLinksInfo(mInterfaceName)); 3289 updateBlockListAffiliatedBssids(); 3290 } 3291 if (mVerboseLoggingEnabled) { 3292 StringBuilder sb = new StringBuilder(); 3293 logd(sb.append("WifiStandard: ").append(ScanResult.wifiStandardToString( 3294 mLastConnectionCapabilities.wifiStandard)) 3295 .append(" maxTxSpeed: ").append(maxTxLinkSpeedMbps) 3296 .append(" maxRxSpeed: ").append(maxRxLinkSpeedMbps) 3297 .toString()); 3298 } 3299 updateCurrentConnectionInfo(); 3300 } 3301 3302 /** 3303 * Tells IpClient what BSSID, L2Key and GroupHint to use for IpMemoryStore. 3304 */ updateLayer2Information()3305 private void updateLayer2Information() { 3306 if (mIpClient != null) { 3307 Pair<String, String> p = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); 3308 if (!p.equals(mLastL2KeyAndGroupHint)) { 3309 final MacAddress currentBssid = 3310 NativeUtil.getMacAddressOrNull(mWifiInfo.getBSSID()); 3311 final Layer2Information l2Information = new Layer2Information( 3312 p.first, p.second, currentBssid); 3313 // Update current BSSID on IpClient side whenever l2Key and groupHint 3314 // pair changes (i.e. the initial connection establishment or L2 roaming 3315 // happened). If we have COMPLETED the roaming to a different BSSID, start 3316 // doing DNAv4/DNAv6 -style probing for on-link neighbors of interest (e.g. 3317 // routers/DNS servers/default gateway). 3318 if (mIpClient.updateLayer2Information(l2Information)) { 3319 mLastL2KeyAndGroupHint = p; 3320 } else { 3321 mLastL2KeyAndGroupHint = null; 3322 } 3323 } 3324 } 3325 } 3326 private @Nullable Pair<String, String> mLastL2KeyAndGroupHint = null; 3327 3328 /** 3329 * Resets the Wi-Fi Connections by clearing any state, resetting any sockets 3330 * using the interface, stopping DHCP & disabling interface 3331 * 3332 * @param disconnectReason must be one of WifiDisconnectReported.FailureReason values 3333 * defined in /frameworks/proto_logging/stats/atoms.proto 3334 */ handleNetworkDisconnect(boolean newConnectionInProgress, int disconnectReason)3335 private void handleNetworkDisconnect(boolean newConnectionInProgress, int disconnectReason) { 3336 mWifiMetrics.reportNetworkDisconnect(mInterfaceName, disconnectReason, 3337 mWifiInfo.getRssi(), 3338 mWifiInfo.getLinkSpeed()); 3339 3340 if (mVerboseLoggingEnabled) { 3341 Log.v(getTag(), "handleNetworkDisconnect: newConnectionInProgress: " 3342 + newConnectionInProgress, new Throwable()); 3343 } 3344 3345 if (isPrimary()) { 3346 WifiConfiguration wifiConfig = getConnectedWifiConfigurationInternal(); 3347 if (wifiConfig != null) { 3348 ScanResultMatchInfo matchInfo = 3349 ScanResultMatchInfo.fromWifiConfiguration(wifiConfig); 3350 // WakeupController should only care about the primary, internet providing network 3351 mWakeupController.setLastDisconnectInfo(matchInfo); 3352 } 3353 mRssiMonitor.reset(); 3354 } 3355 3356 clearTargetBssid("handleNetworkDisconnect"); 3357 3358 // Don't stop DHCP if Fils connection is in progress. 3359 if (newConnectionInProgress && mIpClientWithPreConnection) { 3360 if (mVerboseLoggingEnabled) { 3361 log("handleNetworkDisconnect: Don't stop IpClient as fils connection in progress: " 3362 + " mLastNetworkId: " + mLastNetworkId 3363 + " mTargetNetworkId" + mTargetNetworkId); 3364 } 3365 } else { 3366 stopDhcpSetup(); 3367 } 3368 3369 // DISASSOC_AP_BUSY could be received in both after L3 connection is successful or right 3370 // after BSSID association if the AP can't accept more stations. 3371 if (disconnectReason == StaIfaceReasonCode.DISASSOC_AP_BUSY) { 3372 mWifiConfigManager.setRecentFailureAssociationStatus( 3373 mWifiInfo.getNetworkId(), 3374 WifiConfiguration.RECENT_FAILURE_DISCONNECTION_AP_BUSY); 3375 } 3376 3377 mWifiScoreReport.stopConnectedNetworkScorer(); 3378 /* Reset data structures */ 3379 mWifiScoreReport.reset(); 3380 mWifiBlocklistMonitor.removeAffiliatedBssids(mWifiInfo.getBSSID()); 3381 mWifiInfo.reset(); 3382 /* Reset roaming parameters */ 3383 mIsAutoRoaming = false; 3384 3385 sendNetworkChangeBroadcast(DetailedState.DISCONNECTED); 3386 if (mNetworkAgent != null) { 3387 mNetworkAgent.unregister(); 3388 mNetworkAgent = null; 3389 mQosPolicyRequestHandler.setNetworkAgent(null); 3390 } 3391 3392 /* Clear network properties */ 3393 clearLinkProperties(); 3394 3395 mLastBssid = null; 3396 mLastLinkLayerStats = null; 3397 registerDisconnected(); 3398 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 3399 mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 3400 mCurrentConnectionDetectedCaptivePortal = false; 3401 mLastSimBasedConnectionCarrierName = null; 3402 checkAbnormalDisconnectionAndTakeBugReport(); 3403 mWifiScoreCard.resetConnectionState(mInterfaceName); 3404 updateLayer2Information(); 3405 // If there is new connection in progress, this is for the new connection, so keept it. 3406 if (!newConnectionInProgress) { 3407 mIsUserSelected = false; 3408 } 3409 updateCurrentConnectionInfo(); 3410 } 3411 handlePreDhcpSetup()3412 void handlePreDhcpSetup() { 3413 if (!mWifiGlobals.isBluetoothConnected()) { 3414 /* 3415 * There are problems setting the Wi-Fi driver's power 3416 * mode to active when bluetooth coexistence mode is 3417 * enabled or sense. 3418 * <p> 3419 * We set Wi-Fi to active mode when 3420 * obtaining an IP address because we've found 3421 * compatibility issues with some routers with low power 3422 * mode. 3423 * <p> 3424 * In order for this active power mode to properly be set, 3425 * we disable coexistence mode until we're done with 3426 * obtaining an IP address. One exception is if we 3427 * are currently connected to a headset, since disabling 3428 * coexistence would interrupt that connection. 3429 */ 3430 // Disable the coexistence mode 3431 mWifiNative.setBluetoothCoexistenceMode( 3432 mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); 3433 } 3434 3435 // Disable power save and suspend optimizations during DHCP 3436 // Note: The order here is important for now. Brcm driver changes 3437 // power settings when we control suspend mode optimizations. 3438 // TODO: Remove this comment when the driver is fixed. 3439 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false); 3440 setPowerSave(POWER_SAVE_CLIENT_DHCP, false); 3441 3442 // Update link layer stats 3443 getWifiLinkLayerStats(); 3444 3445 if (mWifiP2pConnection.isConnected()) { 3446 // P2P discovery breaks DHCP, so shut it down in order to get through this. 3447 // Once P2P service receives this message and processes it accordingly, it is supposed 3448 // to send arg2 (i.e. CMD_PRE_DHCP_ACTION_COMPLETE) in a new Message.what back to 3449 // ClientModeImpl so that we can continue. 3450 // TODO(b/159060934): Need to ensure that CMD_PRE_DHCP_ACTION_COMPLETE is sent back to 3451 // the ClientModeImpl instance that originally sent it. Right now it is sent back to 3452 // all ClientModeImpl instances by WifiP2pConnection. 3453 mWifiP2pConnection.sendMessage( 3454 WifiP2pServiceImpl.BLOCK_DISCOVERY, 3455 WifiP2pServiceImpl.ENABLED, 3456 CMD_PRE_DHCP_ACTION_COMPLETE); 3457 } else { 3458 // If the p2p service is not running, we can proceed directly. 3459 sendMessage(CMD_PRE_DHCP_ACTION_COMPLETE); 3460 } 3461 } 3462 addLayer2PacketsToHlpReq(List<Layer2PacketParcelable> packets)3463 void addLayer2PacketsToHlpReq(List<Layer2PacketParcelable> packets) { 3464 List<Layer2PacketParcelable> mLayer2Packet = packets; 3465 if ((mLayer2Packet != null) && (mLayer2Packet.size() > 0)) { 3466 mWifiNative.flushAllHlp(mInterfaceName); 3467 3468 for (int j = 0; j < mLayer2Packet.size(); j++) { 3469 byte [] bytes = mLayer2Packet.get(j).payload; 3470 byte [] payloadBytes = Arrays.copyOfRange(bytes, 12, bytes.length); 3471 MacAddress dstAddress = mLayer2Packet.get(j).dstMacAddress; 3472 3473 mWifiNative.addHlpReq(mInterfaceName, dstAddress, payloadBytes); 3474 } 3475 } 3476 } 3477 handlePostDhcpSetup()3478 void handlePostDhcpSetup() { 3479 /* Restore power save and suspend optimizations */ 3480 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true); 3481 setPowerSave(POWER_SAVE_CLIENT_DHCP, true); 3482 3483 mWifiP2pConnection.sendMessage( 3484 WifiP2pServiceImpl.BLOCK_DISCOVERY, WifiP2pServiceImpl.DISABLED); 3485 3486 // Set the coexistence mode back to its default value 3487 mWifiNative.setBluetoothCoexistenceMode( 3488 mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); 3489 } 3490 3491 /** 3492 * Set power save mode 3493 * 3494 * @param ps true to enable power save (default behavior) 3495 * false to disable power save. 3496 * @return true for success, false for failure 3497 */ setPowerSave(@owerSaveClientType int client, boolean ps)3498 public boolean setPowerSave(@PowerSaveClientType int client, boolean ps) { 3499 if (mInterfaceName != null) { 3500 if (mVerboseLoggingEnabled) { 3501 Log.d(getTag(), "Request to set power save for: " + mInterfaceName + " to: " + ps 3502 + " requested by: " + client + ", mPowerSaveDisableRequests = " 3503 + mPowerSaveDisableRequests); 3504 } 3505 if (ps) { 3506 mPowerSaveDisableRequests &= ~client; 3507 } else { 3508 mPowerSaveDisableRequests |= client; 3509 } 3510 boolean actualPs = mPowerSaveDisableRequests == 0; 3511 if (mVerboseLoggingEnabled) { 3512 Log.d(getTag(), "Setting power save to: " + actualPs 3513 + ", mPowerSaveDisableRequests = " + mPowerSaveDisableRequests); 3514 } 3515 3516 mWifiNative.setPowerSave(mInterfaceName, actualPs); 3517 } else { 3518 Log.e(getTag(), "Failed to setPowerSave, interfaceName is null"); 3519 return false; 3520 } 3521 return true; 3522 } 3523 3524 /** 3525 * Enable power save. 3526 * 3527 * @return true for success, false for failure. 3528 */ enablePowerSave()3529 public boolean enablePowerSave() { 3530 return setPowerSave(~0, true); 3531 } 3532 3533 /** 3534 * Set low latency mode 3535 * 3536 * @param enabled true to enable low latency 3537 * false to disable low latency (default behavior). 3538 * @return true for success, false for failure 3539 */ setLowLatencyMode(boolean enabled)3540 public boolean setLowLatencyMode(boolean enabled) { 3541 if (mVerboseLoggingEnabled) { 3542 Log.d(getTag(), "Setting low latency mode to " + enabled); 3543 } 3544 if (!mWifiNative.setLowLatencyMode(enabled)) { 3545 Log.e(getTag(), "Failed to setLowLatencyMode"); 3546 return false; 3547 } 3548 return true; 3549 } 3550 getClientRoleForMetrics(WifiConfiguration config)3551 private int getClientRoleForMetrics(WifiConfiguration config) { 3552 ActiveModeManager.ClientRole clientRole = mClientModeManager.getRole(); 3553 if (clientRole == ROLE_CLIENT_PRIMARY) { 3554 return config != null && config.fromWifiNetworkSpecifier 3555 ? WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_LOCAL_ONLY 3556 : WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_PRIMARY; 3557 } else if (clientRole == ROLE_CLIENT_LOCAL_ONLY) { 3558 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_LOCAL_ONLY; 3559 } else if (clientRole == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 3560 return mClientModeManager.isSecondaryInternet() 3561 ? WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_INTERNET 3562 : WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_LONG_LIVED; 3563 } else if (clientRole == ROLE_CLIENT_SECONDARY_TRANSIENT) { 3564 return WifiStatsLog 3565 .WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_TRANSIENT; 3566 } 3567 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_OTHERS; 3568 } 3569 3570 /** 3571 * Inform other components that a new connection attempt is starting. 3572 */ reportConnectionAttemptStart( WifiConfiguration config, String targetBSSID, int roamType)3573 private void reportConnectionAttemptStart( 3574 WifiConfiguration config, String targetBSSID, int roamType) { 3575 boolean isOobPseudonymEnabled = false; 3576 if (config.enterpriseConfig != null && config.enterpriseConfig.isAuthenticationSimBased() 3577 && mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(config.carrierId)) { 3578 isOobPseudonymEnabled = true; 3579 } 3580 int overlapWithLastConnectionMs = 3581 mWifiMetrics.startConnectionEvent( 3582 mInterfaceName, config, targetBSSID, roamType, isOobPseudonymEnabled, 3583 getClientRoleForMetrics(config)); 3584 if (mDeviceConfigFacade.isOverlappingConnectionBugreportEnabled() 3585 && overlapWithLastConnectionMs 3586 > mDeviceConfigFacade.getOverlappingConnectionDurationThresholdMs()) { 3587 String bugTitle = "Wi-Fi BugReport: overlapping connection"; 3588 String bugDetail = "Detect abnormal overlapping connection"; 3589 mWifiDiagnostics.takeBugReport(bugTitle, bugDetail); 3590 } 3591 mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_STARTED, 3592 mClientModeManager); 3593 if (isPrimary()) { 3594 mWrongPasswordNotifier.onNewConnectionAttempt(); 3595 } 3596 } 3597 handleConnectionAttemptEndForDiagnostics(int level2FailureCode)3598 private void handleConnectionAttemptEndForDiagnostics(int level2FailureCode) { 3599 switch (level2FailureCode) { 3600 case WifiMetrics.ConnectionEvent.FAILURE_NONE: 3601 break; 3602 case WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED: 3603 // WifiDiagnostics doesn't care about pre-empted connections, or cases 3604 // where we failed to initiate a connection attempt with supplicant. 3605 break; 3606 case WifiMetrics.ConnectionEvent.FAILURE_NO_RESPONSE: 3607 mWifiDiagnostics.reportConnectionEvent( 3608 WifiDiagnostics.CONNECTION_EVENT_TIMEOUT, mClientModeManager); 3609 break; 3610 default: 3611 mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED, 3612 mClientModeManager); 3613 } 3614 } 3615 3616 /** 3617 * Inform other components (WifiMetrics, WifiDiagnostics, WifiConnectivityManager, etc.) that 3618 * the current connection attempt has concluded. 3619 */ reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode, int level2FailureReason)3620 private void reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode, 3621 int level2FailureReason) { 3622 // if connected, this should be non-null. 3623 WifiConfiguration configuration = getConnectedWifiConfigurationInternal(); 3624 if (configuration == null) { 3625 // If not connected, this should be non-null. 3626 configuration = getConnectingWifiConfigurationInternal(); 3627 } 3628 if (configuration == null) { 3629 Log.e(TAG, "Unexpected null WifiConfiguration. Config may have been removed."); 3630 return; 3631 } 3632 3633 String bssid = mLastBssid == null ? mTargetBssid : mLastBssid; 3634 String ssid = mWifiInfo.getSSID(); 3635 if (WifiManager.UNKNOWN_SSID.equals(ssid)) { 3636 ssid = getConnectingSsidInternal(); 3637 } 3638 if (level2FailureCode != WifiMetrics.ConnectionEvent.FAILURE_NONE) { 3639 int blocklistReason = convertToWifiBlocklistMonitorFailureReason( 3640 level2FailureCode, level2FailureReason); 3641 if (blocklistReason != -1) { 3642 mWifiScoreCard.noteConnectionFailure(mWifiInfo, mLastScanRssi, ssid, 3643 blocklistReason); 3644 checkAbnormalConnectionFailureAndTakeBugReport(ssid); 3645 mWifiBlocklistMonitor.handleBssidConnectionFailure(bssid, configuration, 3646 blocklistReason, mLastScanRssi); 3647 WifiScoreCard.NetworkConnectionStats recentStats = mWifiScoreCard.lookupNetwork( 3648 ssid).getRecentStats(); 3649 // Skip the secondary internet connection failure for association rejection 3650 final boolean shouldSkip = isSecondaryInternet() && 3651 (level2FailureCode 3652 == WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT 3653 || level2FailureCode 3654 == WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION); 3655 if (recentStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE) 3656 >= WifiBlocklistMonitor.NUM_CONSECUTIVE_FAILURES_PER_NETWORK_EXP_BACKOFF 3657 && configuration.getNetworkSelectionStatus().isNetworkEnabled() 3658 && !shouldSkip) { 3659 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 3660 WifiConfiguration.NetworkSelectionStatus.DISABLED_CONSECUTIVE_FAILURES); 3661 } 3662 if (recentStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE) 3663 >= THRESHOLD_TO_PERM_WRONG_PASSWORD) { 3664 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 3665 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD); 3666 } 3667 } 3668 } 3669 3670 if (configuration.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { 3671 if (level2FailureCode == WifiMetrics.ConnectionEvent.FAILURE_NONE) { 3672 mWifiMetrics.incrementNumOfCarrierWifiConnectionSuccess(); 3673 } else if (level2FailureCode 3674 == WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE 3675 && level2FailureReason 3676 != WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE) { 3677 mWifiMetrics.incrementNumOfCarrierWifiConnectionAuthFailure(); 3678 } else { 3679 mWifiMetrics.incrementNumOfCarrierWifiConnectionNonAuthFailure(); 3680 } 3681 } 3682 3683 boolean isAssociationRejection = level2FailureCode 3684 == WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION; 3685 boolean isAuthenticationFailure = level2FailureCode 3686 == WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE 3687 && level2FailureReason != WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD; 3688 if ((isAssociationRejection || isAuthenticationFailure) 3689 && mWifiConfigManager.isInFlakyRandomizationSsidHotlist(mTargetNetworkId) 3690 && isPrimary()) { 3691 mConnectionFailureNotifier 3692 .showFailedToConnectDueToNoRandomizedMacSupportNotification(mTargetNetworkId); 3693 } 3694 3695 ScanResult candidate = configuration.getNetworkSelectionStatus().getCandidate(); 3696 int frequency = mWifiInfo.getFrequency(); 3697 if (frequency == WifiInfo.UNKNOWN_FREQUENCY && candidate != null) { 3698 frequency = candidate.frequency; 3699 } 3700 mWifiMetrics.endConnectionEvent(mInterfaceName, level2FailureCode, 3701 connectivityFailureCode, level2FailureReason, frequency); 3702 mWifiConnectivityManager.handleConnectionAttemptEnded( 3703 mClientModeManager, level2FailureCode, level2FailureReason, bssid, 3704 configuration); 3705 mNetworkFactory.handleConnectionAttemptEnded(level2FailureCode, configuration, bssid, 3706 level2FailureReason); 3707 mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( 3708 level2FailureCode, configuration, getConnectedBssidInternal()); 3709 if (candidate != null 3710 && !TextUtils.equals(candidate.BSSID, getConnectedBssidInternal())) { 3711 mWifiMetrics.incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware(); 3712 } 3713 handleConnectionAttemptEndForDiagnostics(level2FailureCode); 3714 } 3715 3716 /* If this connection attempt fails after 802.1x stage, clear intermediate cached data. */ clearNetworkCachedDataIfNeeded(WifiConfiguration config, int reason)3717 void clearNetworkCachedDataIfNeeded(WifiConfiguration config, int reason) { 3718 if (config == null) return; 3719 3720 switch(reason) { 3721 case StaIfaceReasonCode.UNSPECIFIED: 3722 case StaIfaceReasonCode.DEAUTH_LEAVING: 3723 logi("Keep PMK cache for network disconnection reason " + reason); 3724 break; 3725 default: 3726 mWifiNative.removeNetworkCachedData(config.networkId); 3727 break; 3728 } 3729 } 3730 3731 /** 3732 * Returns the sufficient RSSI for the frequency that this network is last seen on. 3733 */ getSufficientRssi(int networkId, String bssid)3734 private int getSufficientRssi(int networkId, String bssid) { 3735 ScanDetailCache scanDetailCache = 3736 mWifiConfigManager.getScanDetailCacheForNetwork(networkId); 3737 if (scanDetailCache == null) { 3738 return WifiInfo.INVALID_RSSI; 3739 } 3740 ScanResult scanResult = scanDetailCache.getScanResult(bssid); 3741 if (scanResult == null) { 3742 return WifiInfo.INVALID_RSSI; 3743 } 3744 return mScoringParams.getSufficientRssi(scanResult.frequency); 3745 } 3746 convertToWifiBlocklistMonitorFailureReason( int level2FailureCode, int failureReason)3747 private int convertToWifiBlocklistMonitorFailureReason( 3748 int level2FailureCode, int failureReason) { 3749 switch (level2FailureCode) { 3750 case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT: 3751 return WifiBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT; 3752 case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION: 3753 if (failureReason == WifiMetricsProto.ConnectionEvent 3754 .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA) { 3755 return WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA; 3756 } 3757 return WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION; 3758 case WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE: 3759 if (failureReason == WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD) { 3760 return WifiBlocklistMonitor.REASON_WRONG_PASSWORD; 3761 } else if (failureReason == WifiMetricsProto.ConnectionEvent 3762 .AUTH_FAILURE_EAP_FAILURE) { 3763 return WifiBlocklistMonitor.REASON_EAP_FAILURE; 3764 } 3765 return WifiBlocklistMonitor.REASON_AUTHENTICATION_FAILURE; 3766 case WifiMetrics.ConnectionEvent.FAILURE_DHCP: 3767 return WifiBlocklistMonitor.REASON_DHCP_FAILURE; 3768 case WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION: 3769 if (failureReason == WifiMetricsProto.ConnectionEvent.DISCONNECTION_NON_LOCAL) { 3770 return WifiBlocklistMonitor.REASON_NONLOCAL_DISCONNECT_CONNECTING; 3771 } 3772 return -1; 3773 case WifiMetrics.ConnectionEvent.FAILURE_NO_RESPONSE: 3774 return WifiBlocklistMonitor.REASON_FAILURE_NO_RESPONSE; 3775 default: 3776 return -1; 3777 } 3778 } 3779 handleIPv4Success(DhcpResultsParcelable dhcpResults)3780 private void handleIPv4Success(DhcpResultsParcelable dhcpResults) { 3781 if (mVerboseLoggingEnabled) { 3782 logd("handleIPv4Success <" + dhcpResults.toString() + ">"); 3783 logd("link address " + dhcpResults.baseConfiguration.getIpAddress()); 3784 } 3785 3786 Inet4Address addr; 3787 synchronized (mDhcpResultsParcelableLock) { 3788 mDhcpResultsParcelable = dhcpResults; 3789 addr = (Inet4Address) dhcpResults.baseConfiguration.getIpAddress().getAddress(); 3790 } 3791 3792 if (mIsAutoRoaming) { 3793 int previousAddress = mWifiInfo.getIpAddress(); 3794 int newAddress = Inet4AddressUtils.inet4AddressToIntHTL(addr); 3795 if (previousAddress != newAddress) { 3796 logd("handleIPv4Success, roaming and address changed" 3797 + mWifiInfo + " got: " + addr); 3798 } 3799 } 3800 3801 mWifiInfo.setInetAddress(addr); 3802 3803 final WifiConfiguration config = getConnectedWifiConfigurationInternal(); 3804 if (config != null) { 3805 updateWifiInfoWhenConnected(config); 3806 mWifiConfigManager.updateRandomizedMacExpireTime(config, dhcpResults.leaseDuration); 3807 mWifiBlocklistMonitor.handleDhcpProvisioningSuccess(mLastBssid, mWifiInfo.getSSID()); 3808 } 3809 3810 // Set meteredHint if DHCP result says network is metered 3811 if (dhcpResults.vendorInfo != null && dhcpResults.vendorInfo.contains("ANDROID_METERED")) { 3812 mWifiInfo.setMeteredHint(true); 3813 mWifiMetrics.addMeteredStat(config, true); 3814 } else { 3815 mWifiMetrics.addMeteredStat(config, false); 3816 } 3817 3818 updateCapabilities(); 3819 updateCurrentConnectionInfo(); 3820 } 3821 handleSuccessfulIpConfiguration()3822 private void handleSuccessfulIpConfiguration() { 3823 mLastSignalLevel = -1; // Force update of signal strength 3824 WifiConfiguration c = getConnectedWifiConfigurationInternal(); 3825 if (c != null) { 3826 // Reset IP failure tracking 3827 c.getNetworkSelectionStatus().clearDisableReasonCounter( 3828 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3829 } 3830 } 3831 handleIPv4Failure()3832 private void handleIPv4Failure() { 3833 // TODO: Move this to provisioning failure, not DHCP failure. 3834 // DHCPv4 failure is expected on an IPv6-only network. 3835 mWifiDiagnostics.triggerBugReportDataCapture(WifiDiagnostics.REPORT_REASON_DHCP_FAILURE); 3836 if (mVerboseLoggingEnabled) { 3837 int count = -1; 3838 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 3839 if (config != null) { 3840 count = config.getNetworkSelectionStatus().getDisableReasonCounter( 3841 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3842 } 3843 log("DHCP failure count=" + count); 3844 } 3845 synchronized (mDhcpResultsParcelableLock) { 3846 mDhcpResultsParcelable = new DhcpResultsParcelable(); 3847 } 3848 if (mVerboseLoggingEnabled) { 3849 logd("handleIPv4Failure"); 3850 } 3851 } 3852 handleIpConfigurationLost()3853 private void handleIpConfigurationLost() { 3854 mWifiInfo.setInetAddress(null); 3855 mWifiInfo.setMeteredHint(false); 3856 3857 mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId, 3858 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3859 3860 /* DHCP times out after about 30 seconds, we do a 3861 * disconnect thru supplicant, we will let autojoin retry connecting to the network 3862 */ 3863 mWifiNative.disconnect(mInterfaceName); 3864 updateCurrentConnectionInfo(); 3865 } 3866 handleIpReachabilityLost()3867 private void handleIpReachabilityLost() { 3868 mWifiBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(), 3869 getConnectedWifiConfiguration(), 3870 WifiBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, mWifiInfo.getRssi()); 3871 mWifiScoreCard.noteIpReachabilityLost(mWifiInfo); 3872 mWifiInfo.setInetAddress(null); 3873 mWifiInfo.setMeteredHint(false); 3874 3875 // Disconnect via supplicant, and let autojoin retry connecting to the network. 3876 mWifiNative.disconnect(mInterfaceName); 3877 updateCurrentConnectionInfo(); 3878 } 3879 3880 /** 3881 * Process IP Reachability failures by recreating a new IpClient instance to refresh L3 3882 * provisioning while keeping L2 still connected. 3883 * 3884 * This method is invoked only upon receiving reachability failure post roaming or triggered 3885 * from Wi-Fi RSSI polling or organic kernel probe. 3886 */ processIpReachabilityFailure()3887 private void processIpReachabilityFailure() { 3888 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 3889 if (config == null) { 3890 // special case for IP reachability lost which happens right after linked network 3891 // roaming. The linked network roaming reset the mLastNetworkId which results in 3892 // the connected configuration to be null. 3893 config = getConnectingWifiConfigurationInternal(); 3894 } 3895 if (config == null) { 3896 // config could be null if it had been removed from WifiConfigManager. In this case 3897 // we should simply disconnect. 3898 handleIpReachabilityLost(); 3899 return; 3900 } 3901 final NetworkAgentConfig naConfig = getNetworkAgentConfigInternal(config); 3902 final NetworkCapabilities nc = getCapabilities( 3903 getConnectedWifiConfigurationInternal(), getConnectedBssidInternal()); 3904 3905 mWifiInfo.setInetAddress(null); 3906 if (mNetworkAgent != null) { 3907 if (SdkLevel.isAtLeastT()) { 3908 mNetworkAgent.unregisterAfterReplacement(NETWORK_AGENT_TEARDOWN_DELAY_MS); 3909 } else { 3910 mNetworkAgent.unregister(); 3911 } 3912 } 3913 mNetworkAgent = mWifiInjector.makeWifiNetworkAgent(nc, mLinkProperties, naConfig, 3914 mNetworkFactory.getProvider(), new WifiNetworkAgentCallback()); 3915 mWifiScoreReport.setNetworkAgent(mNetworkAgent); 3916 if (SdkLevel.isAtLeastT()) { 3917 mQosPolicyRequestHandler.setNetworkAgent(mNetworkAgent); 3918 } 3919 3920 transitionTo(mWaitBeforeL3ProvisioningState); 3921 3922 updateCurrentConnectionInfo(); 3923 } 3924 processLegacyIpReachabilityLost()3925 private void processLegacyIpReachabilityLost() { 3926 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_REACHABILITY_LOST); 3927 mWifiMetrics.logWifiIsUnusableEvent(mInterfaceName, 3928 WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST); 3929 mWifiMetrics.addToWifiUsabilityStatsList(mInterfaceName, 3930 WifiUsabilityStats.LABEL_BAD, 3931 WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1); 3932 if (mWifiGlobals.getIpReachabilityDisconnectEnabled()) { 3933 handleIpReachabilityLost(); 3934 } else { 3935 logd("CMD_IP_REACHABILITY_LOST but disconnect disabled -- ignore"); 3936 } 3937 } 3938 handleIpReachabilityFailure(@onNull ReachabilityLossInfoParcelable lossInfo)3939 private void handleIpReachabilityFailure(@NonNull ReachabilityLossInfoParcelable lossInfo) { 3940 if (lossInfo == null) { 3941 Log.e(getTag(), "lossInfo should never be null"); 3942 processLegacyIpReachabilityLost(); 3943 return; 3944 } 3945 3946 switch (lossInfo.reason) { 3947 case ReachabilityLossReason.ROAM: 3948 processIpReachabilityFailure(); 3949 break; 3950 case ReachabilityLossReason.CONFIRM: 3951 case ReachabilityLossReason.ORGANIC: 3952 if (mDeviceConfigFacade.isHandleRssiOrganicKernelFailuresEnabled()) { 3953 processIpReachabilityFailure(); 3954 } else { 3955 processLegacyIpReachabilityLost(); 3956 } 3957 break; 3958 default: 3959 logd("Invalid failure reason " + lossInfo.reason + "from onIpReachabilityFailure"); 3960 } 3961 } 3962 getNetworkAgentConfigInternal(WifiConfiguration config)3963 private NetworkAgentConfig getNetworkAgentConfigInternal(WifiConfiguration config) { 3964 boolean explicitlySelected = false; 3965 // Non primary CMMs is never user selected. This prevents triggering the No Internet 3966 // dialog for those networks, which is difficult to handle. 3967 if (isPrimary() && isRecentlySelectedByTheUser(config)) { 3968 // If explicitlySelected is true, the network was selected by the user via Settings 3969 // or QuickSettings. If this network has Internet access, switch to it. Otherwise, 3970 // switch to it only if the user confirms that they really want to switch, or has 3971 // already confirmed and selected "Don't ask again". 3972 explicitlySelected = 3973 mWifiPermissionsUtil.checkNetworkSettingsPermission(config.lastConnectUid); 3974 if (mVerboseLoggingEnabled) { 3975 log("Network selected by UID " + config.lastConnectUid 3976 + " explicitlySelected=" + explicitlySelected); 3977 } 3978 } 3979 NetworkAgentConfig.Builder naConfigBuilder = new NetworkAgentConfig.Builder() 3980 .setLegacyType(ConnectivityManager.TYPE_WIFI) 3981 .setLegacyTypeName(NETWORKTYPE) 3982 .setExplicitlySelected(explicitlySelected) 3983 .setUnvalidatedConnectivityAcceptable( 3984 explicitlySelected && config.noInternetAccessExpected) 3985 .setPartialConnectivityAcceptable(config.noInternetAccessExpected); 3986 if (config.carrierMerged) { 3987 String subscriberId = null; 3988 TelephonyManager subMgr = mTelephonyManager.createForSubscriptionId( 3989 config.subscriptionId); 3990 if (subMgr != null) { 3991 subscriberId = subMgr.getSubscriberId(); 3992 } 3993 if (subscriberId != null) { 3994 naConfigBuilder.setSubscriberId(subscriberId); 3995 } 3996 } 3997 if (mVcnManager == null && SdkLevel.isAtLeastS()) { 3998 mVcnManager = mContext.getSystemService(VcnManager.class); 3999 } 4000 if (mVcnManager != null && mVcnPolicyChangeListener == null && SdkLevel.isAtLeastS()) { 4001 mVcnPolicyChangeListener = new WifiVcnNetworkPolicyChangeListener(); 4002 mVcnManager.addVcnNetworkPolicyChangeListener(new HandlerExecutor(getHandler()), 4003 mVcnPolicyChangeListener); 4004 } 4005 return naConfigBuilder.build(); 4006 } 4007 4008 /* 4009 * Read a MAC address in /proc/net/arp, used by ClientModeImpl 4010 * so as to record MAC address of default gateway. 4011 **/ macAddressFromRoute(String ipAddress)4012 private String macAddressFromRoute(String ipAddress) { 4013 String macAddress = null; 4014 BufferedReader reader = null; 4015 try { 4016 reader = mWifiInjector.createBufferedReader(ARP_TABLE_PATH); 4017 4018 // Skip over the line bearing column titles 4019 String line = reader.readLine(); 4020 4021 while ((line = reader.readLine()) != null) { 4022 String[] tokens = line.split("[ ]+"); 4023 if (tokens.length < 6) { 4024 continue; 4025 } 4026 4027 // ARP column format is 4028 // IPAddress HWType Flags HWAddress Mask Device 4029 String ip = tokens[0]; 4030 String mac = tokens[3]; 4031 4032 if (TextUtils.equals(ipAddress, ip)) { 4033 macAddress = mac; 4034 break; 4035 } 4036 } 4037 4038 if (macAddress == null) { 4039 loge("Did not find remoteAddress {" + ipAddress + "} in /proc/net/arp"); 4040 } 4041 4042 } catch (FileNotFoundException e) { 4043 loge("Could not open /proc/net/arp to lookup mac address"); 4044 } catch (IOException e) { 4045 loge("Could not read /proc/net/arp to lookup mac address"); 4046 } finally { 4047 try { 4048 if (reader != null) { 4049 reader.close(); 4050 } 4051 } catch (IOException e) { 4052 // Do nothing 4053 } 4054 } 4055 return macAddress; 4056 4057 } 4058 4059 /** 4060 * Determine if the specified auth failure is considered to be a permanent wrong password 4061 * failure. The criteria for such failure is when wrong password error is detected 4062 * and the network had never been connected before. 4063 * 4064 * For networks that have previously connected successfully, we consider wrong password 4065 * failures to be temporary, to be on the conservative side. Since this might be the 4066 * case where we are trying to connect to a wrong network (e.g. A network with same SSID 4067 * but different password). 4068 */ isPermanentWrongPasswordFailure(int networkId, int reasonCode)4069 private boolean isPermanentWrongPasswordFailure(int networkId, int reasonCode) { 4070 if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD) { 4071 return false; 4072 } 4073 WifiConfiguration network = mWifiConfigManager.getConfiguredNetwork(networkId); 4074 if (network != null && network.getNetworkSelectionStatus().hasEverConnected()) { 4075 return false; 4076 } 4077 return true; 4078 } 4079 4080 /** 4081 * Dynamically change the MAC address to use the locally randomized 4082 * MAC address generated for each network. 4083 * @param config WifiConfiguration with mRandomizedMacAddress to change into. If the address 4084 * is masked out or not set, it will generate a new random MAC address. 4085 */ configureRandomizedMacAddress(WifiConfiguration config)4086 private void configureRandomizedMacAddress(WifiConfiguration config) { 4087 if (config == null) { 4088 Log.e(getTag(), "No config to change MAC address to"); 4089 return; 4090 } 4091 String currentMacString = mWifiNative.getMacAddress(mInterfaceName); 4092 MacAddress currentMac = NativeUtil.getMacAddressOrNull(currentMacString); 4093 MacAddress newMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config, 4094 isSecondaryInternet() && mClientModeManager.isSecondaryInternetDbsAp()); 4095 if (!WifiConfiguration.isValidMacAddressForRandomization(newMac)) { 4096 Log.wtf(getTag(), "Config generated an invalid MAC address"); 4097 } else if (Objects.equals(newMac, currentMac)) { 4098 Log.d(getTag(), "No changes in MAC address"); 4099 } else { 4100 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_MAC_CHANGE, config); 4101 boolean setMacSuccess = 4102 mWifiNative.setStaMacAddress(mInterfaceName, newMac); 4103 if (setMacSuccess) { 4104 mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, newMac); 4105 } 4106 if (mVerboseLoggingEnabled) { 4107 Log.d(getTag(), "ConnectedMacRandomization SSID(" + config.getPrintableSsid() 4108 + "). setMacAddress(" + newMac.toString() + ") from " 4109 + currentMacString + " = " + setMacSuccess); 4110 } 4111 } 4112 } 4113 4114 /** 4115 * Sets the current MAC to the factory MAC address. 4116 */ setCurrentMacToFactoryMac(WifiConfiguration config)4117 private void setCurrentMacToFactoryMac(WifiConfiguration config) { 4118 MacAddress factoryMac = retrieveFactoryMacAddressAndStoreIfNecessary(); 4119 if (factoryMac == null) { 4120 Log.e(getTag(), "Fail to set factory MAC address. Factory MAC is null."); 4121 return; 4122 } 4123 String currentMacStr = mWifiNative.getMacAddress(mInterfaceName); 4124 if (!TextUtils.equals(currentMacStr, factoryMac.toString())) { 4125 if (mWifiNative.setStaMacAddress(mInterfaceName, factoryMac)) { 4126 mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, factoryMac); 4127 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_MAC_CHANGE, config); 4128 } else { 4129 Log.e(getTag(), "Failed to set MAC address to " + "'" 4130 + factoryMac.toString() + "'"); 4131 } 4132 } 4133 } 4134 4135 /** 4136 * Helper method to start other services and get state ready for client mode 4137 */ setupClientMode()4138 private void setupClientMode() { 4139 Log.d(getTag(), "setupClientMode() ifacename = " + mInterfaceName); 4140 4141 setMulticastFilter(true); 4142 registerForWifiMonitorEvents(); 4143 if (isPrimary()) { 4144 mWifiLastResortWatchdog.clearAllFailureCounts(); 4145 } 4146 mWifiNative.setSupplicantLogLevel(mVerboseLoggingEnabled); 4147 4148 // Initialize data structures 4149 mTargetBssid = SUPPLICANT_BSSID_ANY; 4150 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 4151 mLastBssid = null; 4152 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 4153 mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 4154 mLastSimBasedConnectionCarrierName = null; 4155 mLastSignalLevel = -1; 4156 mEnabledTdlsPeers.clear(); 4157 // TODO: b/79504296 This broadcast has been deprecated and should be removed 4158 sendSupplicantConnectionChangedBroadcast(true); 4159 4160 mWifiNative.setExternalSim(mInterfaceName, true); 4161 4162 mWifiDiagnostics.startPktFateMonitoring(mInterfaceName); 4163 mWifiDiagnostics.startLogging(mInterfaceName); 4164 4165 mMboOceController.enable(); 4166 4167 // Enable bluetooth coexistence scan mode when bluetooth connection is active. 4168 // When this mode is on, some of the low-level scan parameters used by the 4169 // driver are changed to reduce interference with bluetooth 4170 mWifiNative.setBluetoothCoexistenceScanMode( 4171 mInterfaceName, mWifiGlobals.isBluetoothConnected()); 4172 sendNetworkChangeBroadcast(DetailedState.DISCONNECTED); 4173 4174 // Disable legacy multicast filtering, which on some chipsets defaults to enabled. 4175 // Legacy IPv6 multicast filtering blocks ICMPv6 router advertisements which breaks IPv6 4176 // provisioning. Legacy IPv4 multicast filtering may be re-enabled later via 4177 // IpClient.Callback.setFallbackMulticastFilter() 4178 mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName); 4179 mWifiNative.stopFilteringMulticastV6Packets(mInterfaceName); 4180 4181 // Set the right suspend mode settings 4182 mWifiNative.setSuspendOptimizations(mInterfaceName, mSuspendOptNeedsDisabled == 0 4183 && mContext.getResources().getBoolean( 4184 R.bool.config_wifiSuspendOptimizationsEnabled)); 4185 4186 enablePowerSave(); 4187 4188 // Disable wpa_supplicant from auto reconnecting. 4189 mWifiNative.enableStaAutoReconnect(mInterfaceName, false); 4190 // STA has higher priority over P2P 4191 mWifiNative.setConcurrencyPriority(true); 4192 4193 // Retrieve and store the factory MAC address (on first bootup). 4194 retrieveFactoryMacAddressAndStoreIfNecessary(); 4195 updateCurrentConnectionInfo(); 4196 } 4197 4198 /** 4199 * Helper method to stop external services and clean up state from client mode. 4200 */ stopClientMode()4201 private void stopClientMode() { 4202 handleNetworkDisconnect(false, 4203 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__WIFI_DISABLED); 4204 // exiting supplicant started state is now only applicable to client mode 4205 mWifiDiagnostics.stopLogging(mInterfaceName); 4206 4207 mMboOceController.disable(); 4208 maybeShutdownIpclient(); 4209 deregisterForWifiMonitorEvents(); // uses mInterfaceName, must call before nulling out 4210 // TODO: b/79504296 This broadcast has been deprecated and should be removed 4211 sendSupplicantConnectionChangedBroadcast(false); 4212 } 4213 4214 /** 4215 * Helper method called when a L3 connection is successfully established to a network. 4216 */ registerConnected()4217 void registerConnected() { 4218 if (isPrimary()) { 4219 mWifiInjector.getActiveModeWarden().setCurrentNetwork(getCurrentNetwork()); 4220 } 4221 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 4222 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 4223 boolean shouldSetUserConnectChoice = config != null 4224 && isRecentlySelectedByTheUser(config) 4225 && (config.getNetworkSelectionStatus().hasEverConnected() 4226 || config.isEphemeral()) 4227 && mWifiPermissionsUtil.checkNetworkSettingsPermission(config.lastConnectUid); 4228 mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId, 4229 mIsUserSelected, shouldSetUserConnectChoice, mWifiInfo.getRssi()); 4230 // Notify PasspointManager of Passpoint network connected event. 4231 WifiConfiguration currentNetwork = getConnectedWifiConfigurationInternal(); 4232 if (currentNetwork != null && currentNetwork.isPasspoint()) { 4233 mPasspointManager.onPasspointNetworkConnected( 4234 currentNetwork.getProfileKey(), currentNetwork.SSID); 4235 } 4236 } 4237 } 4238 registerDisconnected()4239 void registerDisconnected() { 4240 // The role of the ClientModeManager may have been changed to scan only before handling 4241 // the network disconnect. 4242 if (isPrimary() || mClientModeManager.getRole() == ROLE_CLIENT_SCAN_ONLY) { 4243 mWifiInjector.getActiveModeWarden().setCurrentNetwork(getCurrentNetwork()); 4244 } 4245 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 4246 mWifiConfigManager.updateNetworkAfterDisconnect(mLastNetworkId); 4247 } 4248 } 4249 4250 /** 4251 * Returns WifiConfiguration object corresponding to the currently connected network, null if 4252 * not connected. 4253 */ getConnectedWifiConfigurationInternal()4254 @Nullable private WifiConfiguration getConnectedWifiConfigurationInternal() { 4255 if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 4256 return null; 4257 } 4258 return mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); 4259 } 4260 4261 /** 4262 * Returns WifiConfiguration object corresponding to the currently connecting network, null if 4263 * not connecting. 4264 */ getConnectingWifiConfigurationInternal()4265 @Nullable private WifiConfiguration getConnectingWifiConfigurationInternal() { 4266 if (mTargetNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 4267 return null; 4268 } 4269 return mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 4270 } 4271 getConnectedBssidInternal()4272 @Nullable private String getConnectedBssidInternal() { 4273 return mLastBssid; 4274 } 4275 getConnectingBssidInternal()4276 @Nullable private String getConnectingBssidInternal() { 4277 return mTargetBssid; 4278 } 4279 4280 /** 4281 * Returns WifiConfiguration object corresponding to the currently connected network, null if 4282 * not connected. 4283 */ 4284 @Override getConnectedWifiConfiguration()4285 @Nullable public WifiConfiguration getConnectedWifiConfiguration() { 4286 if (!isConnected()) return null; 4287 return getConnectedWifiConfigurationInternal(); 4288 } 4289 4290 /** 4291 * Returns WifiConfiguration object corresponding to the currently connecting network, null if 4292 * not connecting. 4293 */ 4294 @Override getConnectingWifiConfiguration()4295 @Nullable public WifiConfiguration getConnectingWifiConfiguration() { 4296 if (!isConnecting() && !isRoaming()) return null; 4297 return getConnectingWifiConfigurationInternal(); 4298 } 4299 4300 @Override getConnectedBssid()4301 @Nullable public String getConnectedBssid() { 4302 if (!isConnected()) return null; 4303 return getConnectedBssidInternal(); 4304 } 4305 4306 @Override getConnectingBssid()4307 @Nullable public String getConnectingBssid() { 4308 if (!isConnecting() && !isRoaming()) return null; 4309 return getConnectingBssidInternal(); 4310 } 4311 getCurrentScanResult()4312 ScanResult getCurrentScanResult() { 4313 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 4314 if (config == null) { 4315 return null; 4316 } 4317 String bssid = mWifiInfo.getBSSID(); 4318 if (bssid == null) { 4319 bssid = mTargetBssid; 4320 } 4321 ScanDetailCache scanDetailCache = 4322 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); 4323 4324 if (scanDetailCache == null) { 4325 return null; 4326 } 4327 4328 return scanDetailCache.getScanResult(bssid); 4329 } 4330 getCurrentBssidInternalMacAddress()4331 private MacAddress getCurrentBssidInternalMacAddress() { 4332 return NativeUtil.getMacAddressOrNull(mLastBssid); 4333 } 4334 connectToNetwork(WifiConfiguration config)4335 private void connectToNetwork(WifiConfiguration config) { 4336 if ((config != null) && mWifiNative.connectToNetwork(mInterfaceName, config)) { 4337 // Update the internal config once the connection request is accepted. 4338 mWifiConfigManager.setNetworkLastUsedSecurityParams(config.networkId, 4339 config.getNetworkSelectionStatus().getCandidateSecurityParams()); 4340 mWifiLastResortWatchdog.noteStartConnectTime(config.networkId); 4341 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_START_CONNECT, config); 4342 mIsAutoRoaming = false; 4343 transitionTo(mL2ConnectingState); 4344 } else { 4345 loge("CMD_START_CONNECT Failed to start connection to network " + config); 4346 mTargetWifiConfiguration = null; 4347 stopIpClient(); 4348 reportConnectionAttemptEnd( 4349 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 4350 WifiMetricsProto.ConnectionEvent.HLF_NONE, 4351 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 4352 } 4353 } 4354 makeIpClient()4355 private void makeIpClient() { 4356 mIpClientCallbacks = new IpClientCallbacksImpl(); 4357 mFacade.makeIpClient(mContext, mInterfaceName, mIpClientCallbacks); 4358 mIpClientCallbacks.awaitCreation(); 4359 } 4360 maybeShutdownIpclient()4361 private void maybeShutdownIpclient() { 4362 if (mIpClient == null) return; 4363 if (!mIpClient.shutdown()) { 4364 logd("Fail to shut down IpClient"); 4365 return; 4366 } 4367 4368 // Block to make sure IpClient has really shut down, lest cleanup 4369 // race with, say, bringup code over in tethering. 4370 mIpClientCallbacks.awaitShutdown(); 4371 mIpClientCallbacks = null; 4372 mIpClient = null; 4373 } 4374 4375 /******************************************************** 4376 * HSM states 4377 *******************************************************/ 4378 4379 class ConnectableState extends RunnerState { 4380 private boolean mIsScreenStateChangeReceiverRegistered = false; 4381 BroadcastReceiver mScreenStateChangeReceiver = new BroadcastReceiver() { 4382 @Override 4383 public void onReceive(Context context, Intent intent) { 4384 String action = intent.getAction(); 4385 if (TextUtils.equals(action, Intent.ACTION_SCREEN_ON)) { 4386 sendMessage(CMD_SCREEN_STATE_CHANGED, 1); 4387 } else if (TextUtils.equals(action, Intent.ACTION_SCREEN_OFF)) { 4388 sendMessage(CMD_SCREEN_STATE_CHANGED, 0); 4389 } 4390 } 4391 }; 4392 ConnectableState(int threshold)4393 ConnectableState(int threshold) { 4394 super(threshold, mWifiInjector.getWifiHandlerLocalLog()); 4395 } 4396 4397 @Override enterImpl()4398 public void enterImpl() { 4399 Log.d(getTag(), "entering ConnectableState: ifaceName = " + mInterfaceName); 4400 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); 4401 if (mWifiGlobals.isConnectedMacRandomizationEnabled()) { 4402 mFailedToResetMacAddress = !mWifiNative.setStaMacAddress( 4403 mInterfaceName, MacAddressUtils.createRandomUnicastAddress()); 4404 if (mFailedToResetMacAddress) { 4405 Log.e(getTag(), "Failed to set random MAC address on ClientMode creation"); 4406 } 4407 } 4408 mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); 4409 updateCurrentConnectionInfo(); 4410 mWifiStateTracker.updateState(mInterfaceName, WifiStateTracker.INVALID); 4411 makeIpClient(); 4412 } 4413 continueEnterSetup(IpClientManager ipClientManager)4414 private void continueEnterSetup(IpClientManager ipClientManager) { 4415 mIpClient = ipClientManager; 4416 setupClientMode(); 4417 4418 IntentFilter filter = new IntentFilter(); 4419 filter.addAction(Intent.ACTION_SCREEN_ON); 4420 filter.addAction(Intent.ACTION_SCREEN_OFF); 4421 if (!mIsScreenStateChangeReceiverRegistered) { 4422 mContext.registerReceiver(mScreenStateChangeReceiver, filter); 4423 mIsScreenStateChangeReceiverRegistered = true; 4424 } 4425 // Learn the initial state of whether the screen is on. 4426 // We update this field when we receive broadcasts from the system. 4427 handleScreenStateChanged(mContext.getSystemService(PowerManager.class).isInteractive()); 4428 4429 if (!mWifiNative.removeAllNetworks(mInterfaceName)) { 4430 loge("Failed to remove networks on entering connect mode"); 4431 } 4432 mWifiInfo.reset(); 4433 mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); 4434 4435 sendNetworkChangeBroadcast(DetailedState.DISCONNECTED); 4436 4437 // Inform metrics that Wifi is Enabled (but not yet connected) 4438 mWifiMetrics.setWifiState(mInterfaceName, WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 4439 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_WIFI_ENABLED); 4440 mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); 4441 updateCurrentConnectionInfo(); 4442 } 4443 4444 @Override exitImpl()4445 public void exitImpl() { 4446 // Inform metrics that Wifi is being disabled (Toggled, airplane enabled, etc) 4447 mWifiMetrics.setWifiState(mInterfaceName, WifiMetricsProto.WifiLog.WIFI_DISABLED); 4448 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_WIFI_DISABLED); 4449 4450 if (!mWifiNative.removeAllNetworks(mInterfaceName)) { 4451 loge("Failed to remove networks on exiting connect mode"); 4452 } 4453 if (mIsScreenStateChangeReceiverRegistered) { 4454 mContext.unregisterReceiver(mScreenStateChangeReceiver); 4455 mIsScreenStateChangeReceiverRegistered = false; 4456 } 4457 4458 stopClientMode(); 4459 mWifiScoreCard.doWrites(); 4460 } 4461 4462 @Override getMessageLogRec(int what)4463 String getMessageLogRec(int what) { 4464 return ClientModeImpl.class.getSimpleName() + "." 4465 + ConnectableState.class.getSimpleName() + "." + getWhatToString(what); 4466 } 4467 4468 @Override processMessageImpl(Message message)4469 public boolean processMessageImpl(Message message) { 4470 switch (message.what) { 4471 case CMD_IPCLIENT_CREATED: 4472 if (mIpClient != null) { 4473 loge("Setup connectable state again when IpClient is ready?"); 4474 } else { 4475 IpClientManager ipClientManager = (IpClientManager) message.obj; 4476 continueEnterSetup(ipClientManager); 4477 } 4478 break; 4479 case CMD_ENABLE_RSSI_POLL: { 4480 mEnableRssiPolling = (message.arg1 == 1); 4481 break; 4482 } 4483 case CMD_SCREEN_STATE_CHANGED: { 4484 handleScreenStateChanged(message.arg1 != 0); 4485 break; 4486 } 4487 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: { 4488 if (mIpClient == null) { 4489 logd("IpClient is not ready, " 4490 + "WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST dropped"); 4491 break; 4492 } 4493 if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) { 4494 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, 4495 StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); 4496 mWifiNative.disconnect(mInterfaceName); 4497 } else { 4498 mWifiNative.reconnect(mInterfaceName); 4499 } 4500 break; 4501 } 4502 case CMD_RECONNECT: { 4503 WorkSource workSource = (WorkSource) message.obj; 4504 mWifiConnectivityManager.forceConnectivityScan(workSource); 4505 break; 4506 } 4507 case CMD_REASSOCIATE: { 4508 if (mIpClient != null) { 4509 logd("IpClient is not ready, REASSOCIATE dropped"); 4510 4511 mWifiNative.reassociate(mInterfaceName); 4512 } 4513 break; 4514 } 4515 case CMD_START_CONNECT: { 4516 if (mIpClient == null) { 4517 logd("IpClient is not ready, START_CONNECT dropped"); 4518 4519 break; 4520 } 4521 /* connect command coming from auto-join */ 4522 int netId = message.arg1; 4523 int uid = message.arg2; 4524 String bssid = (String) message.obj; 4525 mSentHLPs = false; 4526 // Stop lingering (if it was lingering before) if we start a new connection. 4527 // This means that the ClientModeManager was reused for another purpose, so it 4528 // should no longer be in lingering mode. 4529 mClientModeManager.setShouldReduceNetworkScore(false); 4530 4531 if (!hasConnectionRequests()) { 4532 if (mNetworkAgent == null) { 4533 loge("CMD_START_CONNECT but no requests and not connected," 4534 + " bailing"); 4535 break; 4536 } else if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 4537 loge("CMD_START_CONNECT but no requests and connected, but app " 4538 + "does not have sufficient permissions, bailing"); 4539 break; 4540 } 4541 } 4542 WifiConfiguration config = 4543 mWifiConfigManager.getConfiguredNetworkWithoutMasking(netId); 4544 logd("CMD_START_CONNECT " 4545 + " my state " + getCurrentState().getName() 4546 + " nid=" + netId 4547 + " roam=" + mIsAutoRoaming); 4548 if (config == null) { 4549 loge("CMD_START_CONNECT and no config, bail out..."); 4550 break; 4551 } 4552 mCurrentConnectionDetectedCaptivePortal = false; 4553 mTargetNetworkId = netId; 4554 // Update scorecard while there is still state from existing connection 4555 mLastScanRssi = mWifiConfigManager.findScanRssi(netId, 4556 mWifiHealthMonitor.getScanRssiValidTimeMs()); 4557 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, mLastScanRssi, config.SSID); 4558 if (isPrimary()) { 4559 mWifiBlocklistMonitor.setAllowlistSsids(config.SSID, 4560 Collections.emptyList()); 4561 mWifiBlocklistMonitor.updateFirmwareRoamingConfiguration( 4562 Set.of(config.SSID)); 4563 } 4564 4565 updateWifiConfigOnStartConnection(config, bssid); 4566 reportConnectionAttemptStart(config, mTargetBssid, 4567 WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); 4568 4569 String currentMacAddress = mWifiNative.getMacAddress(mInterfaceName); 4570 mWifiInfo.setMacAddress(currentMacAddress); 4571 updateCurrentConnectionInfo(); 4572 if (mVerboseLoggingEnabled) { 4573 Log.i(getTag(), "Connecting with " + currentMacAddress 4574 + " as the mac address"); 4575 } 4576 mWifiPseudonymManager.enableStrictConservativePeerModeIfSupported(config); 4577 mTargetWifiConfiguration = config; 4578 mNetworkNotFoundEventCount = 0; 4579 /* Check for FILS configuration again after updating the config */ 4580 if (config.isFilsSha256Enabled() || config.isFilsSha384Enabled()) { 4581 boolean isIpClientStarted = startIpClient(config, true); 4582 if (isIpClientStarted) { 4583 mIpClientWithPreConnection = true; 4584 transitionTo(mL2ConnectingState); 4585 break; 4586 } 4587 } 4588 setSelectedRcoiForPasspoint(config); 4589 4590 // TOFU flow for devices that do not support this feature 4591 mInsecureEapNetworkHandler.prepareConnection(mTargetWifiConfiguration); 4592 mLeafCertSent = false; 4593 if (!isTrustOnFirstUseSupported()) { 4594 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(mIsUserSelected); 4595 } 4596 connectToNetwork(config); 4597 break; 4598 } 4599 case CMD_START_FILS_CONNECTION: { 4600 if (mIpClient == null) { 4601 logd("IpClient is not ready, START_FILS_CONNECTION dropped"); 4602 break; 4603 } 4604 mWifiMetrics.incrementConnectRequestWithFilsAkmCount(); 4605 List<Layer2PacketParcelable> packets; 4606 packets = (List<Layer2PacketParcelable>) message.obj; 4607 if (mVerboseLoggingEnabled) { 4608 Log.d(getTag(), "Send HLP IEs to supplicant"); 4609 } 4610 addLayer2PacketsToHlpReq(packets); 4611 WifiConfiguration config = mTargetWifiConfiguration; 4612 connectToNetwork(config); 4613 break; 4614 } 4615 case CMD_CONNECT_NETWORK: { 4616 ConnectNetworkMessage cnm = (ConnectNetworkMessage) message.obj; 4617 if (mIpClient == null) { 4618 logd("IpClient is not ready, CONNECT_NETWORK dropped"); 4619 cnm.listener.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR); 4620 break; 4621 } 4622 NetworkUpdateResult result = cnm.result; 4623 int netId = result.getNetworkId(); 4624 connectToUserSelectNetwork( 4625 netId, message.sendingUid, result.hasCredentialChanged(), 4626 cnm.packageName); 4627 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CONNECT_NETWORK, 4628 mWifiConfigManager.getConfiguredNetwork(netId)); 4629 cnm.listener.sendSuccess(); 4630 break; 4631 } 4632 case CMD_SAVE_NETWORK: { 4633 ConnectNetworkMessage cnm = (ConnectNetworkMessage) message.obj; 4634 if (mIpClient == null) { 4635 logd("IpClient is not ready, SAVE_NETWORK dropped"); 4636 cnm.listener.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR); 4637 break; 4638 } 4639 NetworkUpdateResult result = cnm.result; 4640 int netId = result.getNetworkId(); 4641 if (mWifiInfo.getNetworkId() == netId) { 4642 if (result.hasCredentialChanged()) { 4643 // The network credentials changed and we're connected to this network, 4644 // start a new connection with the updated credentials. 4645 logi("CMD_SAVE_NETWORK credential changed for nid=" 4646 + netId + ". Reconnecting."); 4647 startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY); 4648 } else { 4649 if (result.hasProxyChanged()) { 4650 if (mIpClient != null) { 4651 log("Reconfiguring proxy on connection"); 4652 WifiConfiguration currentConfig = 4653 getConnectedWifiConfigurationInternal(); 4654 if (currentConfig != null) { 4655 mIpClient.setHttpProxy(currentConfig.getHttpProxy()); 4656 } else { 4657 Log.w(getTag(), 4658 "CMD_SAVE_NETWORK proxy change - but no current " 4659 + "Wi-Fi config"); 4660 } 4661 } 4662 } 4663 if (result.hasIpChanged()) { 4664 // The current connection configuration was changed 4665 // We switched from DHCP to static or from static to DHCP, or the 4666 // static IP address has changed. 4667 log("Reconfiguring IP on connection"); 4668 WifiConfiguration currentConfig = 4669 getConnectedWifiConfigurationInternal(); 4670 if (currentConfig != null) { 4671 transitionTo(mL3ProvisioningState); 4672 } else { 4673 Log.w(getTag(), "CMD_SAVE_NETWORK Ip change - but no current " 4674 + "Wi-Fi config"); 4675 } 4676 } 4677 } 4678 } else if (mWifiInfo.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID 4679 && result.hasCredentialChanged()) { 4680 logi("CMD_SAVE_NETWORK credential changed for nid=" 4681 + netId + " while disconnected. Connecting."); 4682 WifiConfiguration config = 4683 mWifiConfigManager.getConfiguredNetwork(netId); 4684 if (!mWifiPermissionsUtil.isAdminRestrictedNetwork(config) 4685 && !mWifiGlobals.isDeprecatedSecurityTypeNetwork(config)) { 4686 startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY); 4687 } 4688 } else if (result.hasCredentialChanged()) { 4689 WifiConfiguration currentConfig = 4690 getConnectedWifiConfigurationInternal(); 4691 WifiConfiguration updatedConfig = 4692 mWifiConfigManager.getConfiguredNetwork(netId); 4693 if (currentConfig != null && currentConfig.isLinked(updatedConfig)) { 4694 logi("current network linked config saved, update linked networks"); 4695 updateLinkedNetworks(currentConfig); 4696 } 4697 } 4698 cnm.listener.sendSuccess(); 4699 break; 4700 } 4701 case CMD_BLUETOOTH_CONNECTION_STATE_CHANGE: { 4702 mWifiNative.setBluetoothCoexistenceScanMode( 4703 mInterfaceName, mWifiGlobals.isBluetoothConnected()); 4704 break; 4705 } 4706 case CMD_SET_SUSPEND_OPT_ENABLED: { 4707 if (message.arg1 == 1) { 4708 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); 4709 if (message.arg2 == 1) { 4710 mSuspendWakeLock.release(); 4711 } 4712 } else { 4713 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); 4714 } 4715 break; 4716 } 4717 case WifiMonitor.ANQP_DONE_EVENT: { 4718 mPasspointManager.notifyANQPDone((AnqpEvent) message.obj); 4719 break; 4720 } 4721 case CMD_STOP_IP_PACKET_OFFLOAD: { 4722 int slot = message.arg1; 4723 int ret = stopWifiIPPacketOffload(slot); 4724 if (mNetworkAgent != null) { 4725 mNetworkAgent.sendSocketKeepaliveEvent(slot, ret); 4726 } 4727 break; 4728 } 4729 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: { 4730 mPasspointManager.notifyIconDone((IconEvent) message.obj); 4731 break; 4732 } 4733 case WifiMonitor.HS20_DEAUTH_IMMINENT_EVENT: 4734 mPasspointManager.handleDeauthImminentEvent((WnmData) message.obj, 4735 getConnectedWifiConfigurationInternal()); 4736 break; 4737 case WifiMonitor.HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT: 4738 mWifiMetrics 4739 .incrementTotalNumberOfPasspointConnectionsWithTermsAndConditionsUrl(); 4740 mTermsAndConditionsUrl = mPasspointManager 4741 .handleTermsAndConditionsEvent((WnmData) message.obj, 4742 getConnectedWifiConfigurationInternal()); 4743 if (mTermsAndConditionsUrl == null) { 4744 loge("Disconnecting from Passpoint network due to an issue with the " 4745 + "Terms and Conditions URL"); 4746 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_PASSPOINT_TAC); 4747 } 4748 break; 4749 case WifiMonitor.HS20_REMEDIATION_EVENT: 4750 mPasspointManager.receivedWnmFrame((WnmData) message.obj); 4751 break; 4752 case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE: { 4753 handleBssTransitionRequest((BtmFrameData) message.obj); 4754 break; 4755 } 4756 case CMD_CONFIG_ND_OFFLOAD: { 4757 final boolean enabled = (message.arg1 > 0); 4758 mWifiNative.configureNeighborDiscoveryOffload(mInterfaceName, enabled); 4759 break; 4760 } 4761 // Link configuration (IP address, DNS, ...) changes notified via netlink 4762 case CMD_UPDATE_LINKPROPERTIES: { 4763 updateLinkProperties((LinkProperties) message.obj); 4764 break; 4765 } 4766 case CMD_START_IP_PACKET_OFFLOAD: 4767 case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: 4768 case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF: { 4769 if (mNetworkAgent != null) { 4770 mNetworkAgent.sendSocketKeepaliveEvent(message.arg1, 4771 SocketKeepalive.ERROR_INVALID_NETWORK); 4772 } 4773 break; 4774 } 4775 case CMD_INSTALL_PACKET_FILTER: { 4776 if (mContext.getResources().getBoolean( 4777 R.bool.config_wifiEnableApfOnNonPrimarySta) 4778 || isPrimary()) { 4779 mWifiNative.installPacketFilter(mInterfaceName, (byte[]) message.obj); 4780 } else { 4781 Log.i(TAG, "Not applying packet filter on non primary CMM"); 4782 } 4783 break; 4784 } 4785 case CMD_READ_PACKET_FILTER: { 4786 byte[] packetFilter = null; 4787 if (mContext.getResources().getBoolean( 4788 R.bool.config_wifiEnableApfOnNonPrimarySta) 4789 || isPrimary()) { 4790 packetFilter = mWifiNative.readPacketFilter(mInterfaceName); 4791 } else { 4792 Log.v(TAG, "APF not supported on non primary CMM - return null"); 4793 } 4794 if (mIpClient != null) { 4795 mIpClient.readPacketFilterComplete(packetFilter); 4796 } 4797 break; 4798 } 4799 case CMD_SET_FALLBACK_PACKET_FILTERING: { 4800 if ((boolean) message.obj) { 4801 mWifiNative.startFilteringMulticastV4Packets(mInterfaceName); 4802 } else { 4803 mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName); 4804 } 4805 break; 4806 } 4807 case CMD_SET_MAX_DTIM_MULTIPLIER: { 4808 final int maxMultiplier = message.arg1; 4809 final boolean success = 4810 mWifiNative.setDtimMultiplier(mInterfaceName, maxMultiplier); 4811 if (mVerboseLoggingEnabled) { 4812 Log.d(TAG, "Set maximum DTIM Multiplier to " + maxMultiplier 4813 + (success ? " SUCCESS" : " FAIL")); 4814 } 4815 break; 4816 } 4817 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 4818 case CMD_RESET_SIM_NETWORKS: 4819 case WifiMonitor.NETWORK_CONNECTION_EVENT: 4820 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 4821 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4822 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 4823 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 4824 case CMD_RSSI_POLL: 4825 case CMD_ONESHOT_RSSI_POLL: 4826 case CMD_PRE_DHCP_ACTION: 4827 case CMD_PRE_DHCP_ACTION_COMPLETE: 4828 case CMD_POST_DHCP_ACTION: 4829 case WifiMonitor.SUP_REQUEST_IDENTITY: 4830 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 4831 case WifiMonitor.TARGET_BSSID_EVENT: 4832 case WifiMonitor.ASSOCIATED_BSSID_EVENT: 4833 case WifiMonitor.TRANSITION_DISABLE_INDICATION: 4834 case CMD_UNWANTED_NETWORK: 4835 case CMD_CONNECTING_WATCHDOG_TIMER: 4836 case WifiMonitor.NETWORK_NOT_FOUND_EVENT: 4837 case CMD_ROAM_WATCHDOG_TIMER: { 4838 // no-op: all messages must be handled in the base state in case it was missed 4839 // in one of the child states. 4840 break; 4841 } 4842 case CMD_ACCEPT_EAP_SERVER_CERTIFICATE: 4843 // If TOFU is not supported, then we are already connected 4844 if (!isTrustOnFirstUseSupported()) break; 4845 // Got an approval for a TOFU network. Disconnect (if connected) and trigger 4846 // a connection to the new approved network. 4847 logd("User accepted TOFU provided certificate"); 4848 startConnectToNetwork(message.arg1, Process.WIFI_UID, SUPPLICANT_BSSID_ANY); 4849 break; 4850 case CMD_REJECT_EAP_INSECURE_CONNECTION: 4851 case CMD_START_ROAM: 4852 case CMD_IP_CONFIGURATION_SUCCESSFUL: 4853 case CMD_IP_CONFIGURATION_LOST: 4854 case CMD_IP_REACHABILITY_LOST: 4855 case CMD_IP_REACHABILITY_FAILURE: { 4856 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4857 break; 4858 } 4859 case 0: { 4860 // We want to notice any empty messages (with what == 0) that might crop up. 4861 // For example, we may have recycled a message sent to multiple handlers. 4862 Log.wtf(getTag(), "Error! empty message encountered"); 4863 break; 4864 } 4865 default: { 4866 loge("Error! unhandled message" + message); 4867 break; 4868 } 4869 } 4870 4871 logStateAndMessage(message, this); 4872 return HANDLED; 4873 } 4874 } 4875 handleL3MessagesWhenNotConnected(Message message)4876 private boolean handleL3MessagesWhenNotConnected(Message message) { 4877 boolean handleStatus = HANDLED; 4878 4879 if (!mIpClientWithPreConnection) { 4880 return NOT_HANDLED; 4881 } 4882 4883 switch (message.what) { 4884 case CMD_PRE_DHCP_ACTION: 4885 handlePreDhcpSetup(); 4886 break; 4887 case CMD_PRE_DHCP_ACTION_COMPLETE: 4888 if (mIpClient != null) { 4889 mIpClient.completedPreDhcpAction(); 4890 } 4891 break; 4892 case CMD_IPV4_PROVISIONING_FAILURE: 4893 stopDhcpSetup(); 4894 deferMessage(message); 4895 break; 4896 case CMD_POST_DHCP_ACTION: 4897 case CMD_IPV4_PROVISIONING_SUCCESS: 4898 case CMD_IP_CONFIGURATION_SUCCESSFUL: 4899 deferMessage(message); 4900 break; 4901 default: 4902 return NOT_HANDLED; 4903 } 4904 4905 return handleStatus; 4906 } 4907 createNetworkAgentSpecifier( @onNull WifiConfiguration currentWifiConfiguration, @Nullable String currentBssid, boolean matchLocationSensitiveInformation)4908 private WifiNetworkAgentSpecifier createNetworkAgentSpecifier( 4909 @NonNull WifiConfiguration currentWifiConfiguration, @Nullable String currentBssid, 4910 boolean matchLocationSensitiveInformation) { 4911 // Defensive copy to avoid mutating the passed argument 4912 final WifiConfiguration conf = new WifiConfiguration(currentWifiConfiguration); 4913 conf.BSSID = currentBssid; 4914 WifiNetworkAgentSpecifier wns = 4915 new WifiNetworkAgentSpecifier(conf, 4916 WifiNetworkSpecifier.getBand(mWifiInfo.getFrequency()), 4917 matchLocationSensitiveInformation); 4918 return wns; 4919 } 4920 getCapabilities( WifiConfiguration currentWifiConfiguration, String currentBssid)4921 private NetworkCapabilities getCapabilities( 4922 WifiConfiguration currentWifiConfiguration, String currentBssid) { 4923 final NetworkCapabilities.Builder builder = 4924 new NetworkCapabilities.Builder(mNetworkCapabilitiesFilter); 4925 // MatchAllNetworkSpecifier set in the mNetworkCapabilitiesFilter should never be set in the 4926 // agent's specifier. 4927 builder.setNetworkSpecifier(null); 4928 if (currentWifiConfiguration == null) { 4929 return builder.build(); 4930 } 4931 4932 if (mWifiInfo.isTrusted()) { 4933 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED); 4934 } else { 4935 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED); 4936 } 4937 4938 if (mWifiInfo.isRestricted()) { 4939 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); 4940 } 4941 4942 if (SdkLevel.isAtLeastS()) { 4943 if (mWifiInfo.isOemPaid()) { 4944 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID); 4945 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); 4946 } else { 4947 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID); 4948 } 4949 if (mWifiInfo.isOemPrivate()) { 4950 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE); 4951 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); 4952 } else { 4953 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE); 4954 } 4955 } 4956 4957 builder.setOwnerUid(currentWifiConfiguration.creatorUid); 4958 builder.setAdministratorUids(new int[]{currentWifiConfiguration.creatorUid}); 4959 if (SdkLevel.isAtLeastT()) { 4960 builder.setAllowedUids(Set.of(currentWifiConfiguration.creatorUid)); 4961 } 4962 4963 if (!WifiConfiguration.isMetered(currentWifiConfiguration, mWifiInfo)) { 4964 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 4965 } else { 4966 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 4967 } 4968 4969 if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI) { 4970 builder.setSignalStrength(mWifiInfo.getRssi()); 4971 } else { 4972 builder.setSignalStrength(NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED); 4973 } 4974 4975 if (currentWifiConfiguration.osu) { 4976 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 4977 } 4978 4979 if (!WifiManager.UNKNOWN_SSID.equals(mWifiInfo.getSSID())) { 4980 builder.setSsid(mWifiInfo.getSSID()); 4981 } 4982 4983 // Only send out WifiInfo in >= Android S devices. 4984 if (SdkLevel.isAtLeastS()) { 4985 builder.setTransportInfo(new WifiInfo(mWifiInfo)); 4986 4987 if (mWifiInfo.getSubscriptionId() != SubscriptionManager.INVALID_SUBSCRIPTION_ID 4988 && mWifiInfo.isCarrierMerged()) { 4989 builder.setSubscriptionIds(Collections.singleton(mWifiInfo.getSubscriptionId())); 4990 } 4991 } 4992 4993 List<Integer> uids = new ArrayList<>(mNetworkFactory 4994 .getSpecificNetworkRequestUids( 4995 currentWifiConfiguration, currentBssid)); 4996 // There is an active local only specific request. 4997 if (!uids.isEmpty()) { 4998 // Remove internet capability. 4999 if (!mNetworkFactory.shouldHaveInternetCapabilities()) { 5000 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 5001 } 5002 if (SdkLevel.isAtLeastS()) { 5003 builder.setUids(getUidRangeSet(uids)); 5004 } else { 5005 // Use requestor Uid and PackageName on pre-S device. 5006 Pair<Integer, String> specificRequestUidAndPackageName = mNetworkFactory 5007 .getSpecificNetworkRequestUidAndPackageName(currentWifiConfiguration, 5008 currentBssid); 5009 // Fill up the uid/packageName for this connection. 5010 builder.setRequestorUid(specificRequestUidAndPackageName.first); 5011 builder.setRequestorPackageName(specificRequestUidAndPackageName.second); 5012 } 5013 // Fill up the network agent specifier for this connection, allowing NetworkCallbacks 5014 // to match local-only specifiers in requests. TODO(b/187921303): a third-party app can 5015 // observe this location-sensitive information by registering a NetworkCallback. 5016 builder.setNetworkSpecifier(createNetworkAgentSpecifier(currentWifiConfiguration, 5017 getConnectedBssidInternal(), true /* matchLocalOnlySpecifiers */)); 5018 } else { 5019 // Fill up the network agent specifier for this connection, without allowing 5020 // NetworkCallbacks to match local-only specifiers in requests. 5021 builder.setNetworkSpecifier(createNetworkAgentSpecifier(currentWifiConfiguration, 5022 getConnectedBssidInternal(), false /* matchLocalOnlySpecifiers */)); 5023 } 5024 5025 updateLinkBandwidth(builder); 5026 final NetworkCapabilities networkCapabilities = builder.build(); 5027 if (mVcnManager == null || !currentWifiConfiguration.carrierMerged 5028 || !SdkLevel.isAtLeastS()) { 5029 return networkCapabilities; 5030 } 5031 final VcnNetworkPolicyResult vcnNetworkPolicy = 5032 mVcnManager.applyVcnNetworkPolicy(networkCapabilities, mLinkProperties); 5033 if (vcnNetworkPolicy.isTeardownRequested()) { 5034 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_VCN_REQUEST); 5035 } 5036 final NetworkCapabilities vcnCapability = vcnNetworkPolicy.getNetworkCapabilities(); 5037 if (!vcnCapability.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)) { 5038 if (mVerboseLoggingEnabled) { 5039 logd("NET_CAPABILITY_NOT_VCN_MANAGED is removed"); 5040 } 5041 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); 5042 } 5043 if (!vcnCapability.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) { 5044 if (mVerboseLoggingEnabled) { 5045 logd("NET_CAPABILITY_NOT_RESTRICTED is removed"); 5046 } 5047 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); 5048 } 5049 return builder.build(); 5050 } 5051 getUidRangeSet(List<Integer> uids)5052 private Set<Range<Integer>> getUidRangeSet(List<Integer> uids) { 5053 Collections.sort(uids); 5054 Set<Range<Integer>> uidRanges = new ArraySet<>(); 5055 int start = 0; 5056 int next = 0; 5057 for (int i : uids) { 5058 if (start == next) { 5059 start = i; 5060 next = start + 1; 5061 } else if (i == next) { 5062 next++; 5063 } else { 5064 uidRanges.add(new Range<>(start, next - 1)); 5065 start = i; 5066 next = start + 1; 5067 } 5068 } 5069 uidRanges.add(new Range<>(start, next - 1)); 5070 return uidRanges; 5071 } 5072 updateLinkBandwidth(NetworkCapabilities.Builder networkCapabilitiesBuilder)5073 private void updateLinkBandwidth(NetworkCapabilities.Builder networkCapabilitiesBuilder) { 5074 int txTputKbps = 0; 5075 int rxTputKbps = 0; 5076 int currRssi = mWifiInfo.getRssi(); 5077 if (currRssi != WifiInfo.INVALID_RSSI) { 5078 WifiScoreCard.PerNetwork network = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 5079 txTputKbps = network.getTxLinkBandwidthKbps(); 5080 rxTputKbps = network.getRxLinkBandwidthKbps(); 5081 } else { 5082 // Fall back to max link speed. This should rarely happen if ever 5083 int maxTxLinkSpeedMbps = mWifiInfo.getMaxSupportedTxLinkSpeedMbps(); 5084 int maxRxLinkSpeedMbps = mWifiInfo.getMaxSupportedRxLinkSpeedMbps(); 5085 txTputKbps = maxTxLinkSpeedMbps * 1000; 5086 rxTputKbps = maxRxLinkSpeedMbps * 1000; 5087 } 5088 if (mVerboseLoggingEnabled) { 5089 logd("reported txKbps " + txTputKbps + " rxKbps " + rxTputKbps); 5090 } 5091 if (txTputKbps > 0) { 5092 networkCapabilitiesBuilder.setLinkUpstreamBandwidthKbps(txTputKbps); 5093 } 5094 if (rxTputKbps > 0) { 5095 networkCapabilitiesBuilder.setLinkDownstreamBandwidthKbps(rxTputKbps); 5096 } 5097 } 5098 5099 /** 5100 * Method to update network capabilities from the current WifiConfiguration. 5101 */ 5102 @Override updateCapabilities()5103 public void updateCapabilities() { 5104 updateCapabilities(getConnectedWifiConfigurationInternal()); 5105 } 5106 5107 /** 5108 * Check if BSSID belongs to any of the affiliated link BSSID's. 5109 * @param bssid BSSID of the AP. 5110 * @return true if BSSID matches to one of the affiliated link BSSIDs, false otherwise. 5111 */ isAffiliatedLinkBssid(@onNull MacAddress bssid)5112 public boolean isAffiliatedLinkBssid(@NonNull MacAddress bssid) { 5113 List<MloLink> links = mWifiInfo.getAffiliatedMloLinks(); 5114 for (MloLink link: links) { 5115 if (link.getApMacAddress().equals(bssid)) { 5116 return true; 5117 } 5118 } 5119 return false; 5120 } 5121 5122 /** 5123 * Check if the connection is MLO (Multi-Link Operation). 5124 * @return true if connection is MLO, otherwise false. 5125 */ isMlo()5126 public boolean isMlo() { 5127 return !mWifiInfo.getAssociatedMloLinks().isEmpty(); 5128 } 5129 updateCapabilities(WifiConfiguration currentWifiConfiguration)5130 private void updateCapabilities(WifiConfiguration currentWifiConfiguration) { 5131 updateCapabilities(getCapabilities(currentWifiConfiguration, getConnectedBssidInternal())); 5132 } 5133 updateCapabilities(NetworkCapabilities networkCapabilities)5134 private void updateCapabilities(NetworkCapabilities networkCapabilities) { 5135 if (mNetworkAgent == null) { 5136 return; 5137 } 5138 mNetworkAgent.sendNetworkCapabilitiesAndCache(networkCapabilities); 5139 } 5140 handleEapAuthFailure(int networkId, int errorCode)5141 private void handleEapAuthFailure(int networkId, int errorCode) { 5142 WifiConfiguration targetedNetwork = 5143 mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 5144 if (targetedNetwork != null) { 5145 switch (targetedNetwork.enterpriseConfig.getEapMethod()) { 5146 case WifiEnterpriseConfig.Eap.SIM: 5147 case WifiEnterpriseConfig.Eap.AKA: 5148 case WifiEnterpriseConfig.Eap.AKA_PRIME: 5149 if (errorCode == WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED) { 5150 mWifiCarrierInfoManager.resetCarrierKeysForImsiEncryption(targetedNetwork); 5151 } else { 5152 int carrierId = targetedNetwork.carrierId; 5153 if (mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(carrierId)) { 5154 mWifiPseudonymManager.retrieveOobPseudonymWithRateLimit(carrierId); 5155 } 5156 } 5157 break; 5158 5159 default: 5160 // Do Nothing 5161 } 5162 } 5163 } 5164 5165 /** 5166 * All callbacks are triggered on the main Wifi thread. 5167 * See {@link WifiNetworkAgent#WifiNetworkAgent}'s looper argument in 5168 * {@link WifiInjector#makeWifiNetworkAgent}. 5169 */ 5170 private class WifiNetworkAgentCallback implements WifiNetworkAgent.Callback { 5171 private int mLastNetworkStatus = -1; // To detect when the status really changes 5172 isThisCallbackActive()5173 private boolean isThisCallbackActive() { 5174 return mNetworkAgent != null && mNetworkAgent.getCallback() == this; 5175 } 5176 5177 @Override onNetworkUnwanted()5178 public void onNetworkUnwanted() { 5179 // Ignore if we're not the current networkAgent. 5180 if (!isThisCallbackActive()) return; 5181 if (mVerboseLoggingEnabled) { 5182 logd("WifiNetworkAgent -> Wifi unwanted score " + mWifiInfo.getScore()); 5183 } 5184 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT); 5185 } 5186 5187 @Override onValidationStatus(int status, @Nullable Uri redirectUri)5188 public void onValidationStatus(int status, @Nullable Uri redirectUri) { 5189 if (!isThisCallbackActive()) return; 5190 if (status == mLastNetworkStatus) return; 5191 mLastNetworkStatus = status; 5192 if (status == NetworkAgent.VALIDATION_STATUS_NOT_VALID) { 5193 if (mVerboseLoggingEnabled) { 5194 logd("WifiNetworkAgent -> Wifi networkStatus invalid, score=" 5195 + mWifiInfo.getScore()); 5196 } 5197 unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED); 5198 } else if (status == NetworkAgent.VALIDATION_STATUS_VALID) { 5199 if (mVerboseLoggingEnabled) { 5200 logd("WifiNetworkAgent -> Wifi networkStatus valid, score= " 5201 + mWifiInfo.getScore()); 5202 } 5203 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK); 5204 doNetworkStatus(status); 5205 } 5206 boolean captivePortalDetected = redirectUri != null 5207 && redirectUri.toString() != null 5208 && redirectUri.toString().length() > 0; 5209 if (captivePortalDetected) { 5210 Log.i(getTag(), "Captive Portal detected, status=" + status 5211 + ", redirectUri=" + redirectUri); 5212 mWifiConfigManager.noteCaptivePortalDetected(mWifiInfo.getNetworkId()); 5213 mCmiMonitor.onCaptivePortalDetected(mClientModeManager); 5214 mCurrentConnectionDetectedCaptivePortal = true; 5215 } 5216 } 5217 5218 @Override onSaveAcceptUnvalidated(boolean accept)5219 public void onSaveAcceptUnvalidated(boolean accept) { 5220 if (!isThisCallbackActive()) return; 5221 ClientModeImpl.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0); 5222 } 5223 5224 @Override onStartSocketKeepalive(int slot, @NonNull Duration interval, @NonNull KeepalivePacketData packet)5225 public void onStartSocketKeepalive(int slot, @NonNull Duration interval, 5226 @NonNull KeepalivePacketData packet) { 5227 if (!isThisCallbackActive()) return; 5228 ClientModeImpl.this.sendMessage( 5229 CMD_START_IP_PACKET_OFFLOAD, slot, (int) interval.getSeconds(), packet); 5230 } 5231 5232 @Override onStopSocketKeepalive(int slot)5233 public void onStopSocketKeepalive(int slot) { 5234 if (!isThisCallbackActive()) return; 5235 ClientModeImpl.this.sendMessage(CMD_STOP_IP_PACKET_OFFLOAD, slot); 5236 } 5237 5238 @Override onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet)5239 public void onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet) { 5240 if (!isThisCallbackActive()) return; 5241 ClientModeImpl.this.sendMessage( 5242 CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0, packet); 5243 } 5244 5245 @Override onRemoveKeepalivePacketFilter(int slot)5246 public void onRemoveKeepalivePacketFilter(int slot) { 5247 if (!isThisCallbackActive()) return; 5248 ClientModeImpl.this.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF, slot); 5249 } 5250 5251 @Override onSignalStrengthThresholdsUpdated(@onNull int[] thresholds)5252 public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { 5253 if (!isThisCallbackActive()) return; 5254 // Enable RSSI monitoring only on primary STA 5255 if (!isPrimary()) { 5256 return; 5257 } 5258 mWifiThreadRunner.post( 5259 () -> mRssiMonitor.updateAppThresholdsAndStartMonitor(thresholds)); 5260 } 5261 5262 @Override onAutomaticReconnectDisabled()5263 public void onAutomaticReconnectDisabled() { 5264 if (!isThisCallbackActive()) return; 5265 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN); 5266 } 5267 5268 @Override onDscpPolicyStatusUpdated(int policyId, int status)5269 public void onDscpPolicyStatusUpdated(int policyId, int status) { 5270 mQosPolicyRequestHandler.setQosPolicyStatus(policyId, status); 5271 } 5272 } 5273 5274 @Override onDeviceMobilityStateUpdated(@eviceMobilityState int newState)5275 public void onDeviceMobilityStateUpdated(@DeviceMobilityState int newState) { 5276 if (!mScreenOn) { 5277 return; 5278 } 5279 if (isPrimary()) { 5280 mRssiMonitor.updatePollRssiInterval(newState); 5281 } 5282 } 5283 5284 @Override setLinkLayerStatsPollingInterval(int newIntervalMs)5285 public void setLinkLayerStatsPollingInterval(int newIntervalMs) { 5286 mRssiMonitor.overridePollRssiInterval(newIntervalMs); 5287 } 5288 isNewConnectionInProgress(@onNull String disconnectingSsid)5289 private boolean isNewConnectionInProgress(@NonNull String disconnectingSsid) { 5290 String targetSsid = getConnectingSsidInternal(); 5291 // If network is removed while connecting, targetSsid can be null. 5292 if (targetSsid == null) { 5293 return false; 5294 } 5295 // When connecting to another network while already connected, the old network will first 5296 // disconnect before the new connection can begin. Thus, the presence of a mLastNetworkId 5297 // that's different from the mTargetNetworkId indicates that this network disconnection is 5298 // triggered for the previously connected network as opposed to the current ongoing 5299 // connection. 5300 boolean isConnectingWhileAlreadyConnected = 5301 mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 5302 && mLastNetworkId != mTargetNetworkId; 5303 5304 // This second condition is needed to catch cases where 2 simultaneous connections happen 5305 // back-to-back. When a new connection start before the previous one finishes, the 5306 // previous network will get removed from the supplicant and cause a disconnect message 5307 // to be received with the previous network's SSID. Thus, if the disconnecting SSID does not 5308 // match the target SSID, it means a new connection is in progress. 5309 boolean isConnectingToAnotherNetwork = !disconnectingSsid.equals(targetSsid); 5310 return isConnectingWhileAlreadyConnected || isConnectingToAnotherNetwork; 5311 } 5312 unwantedNetwork(int reason)5313 private void unwantedNetwork(int reason) { 5314 sendMessage(CMD_UNWANTED_NETWORK, reason); 5315 } 5316 doNetworkStatus(int status)5317 private void doNetworkStatus(int status) { 5318 sendMessage(CMD_NETWORK_STATUS, status); 5319 } 5320 updatePseudonymFromOob(int carrierId, String pseudonym)5321 private void updatePseudonymFromOob(int carrierId, String pseudonym) { 5322 sendMessage(CMD_UPDATE_OOB_PSEUDONYM, carrierId, 0, pseudonym); 5323 } 5324 5325 class ConnectingOrConnectedState extends RunnerState { ConnectingOrConnectedState(int threshold)5326 ConnectingOrConnectedState(int threshold) { 5327 super(threshold, mWifiInjector.getWifiHandlerLocalLog()); 5328 } 5329 5330 @Override enterImpl()5331 public void enterImpl() { 5332 if (mVerboseLoggingEnabled) Log.v(getTag(), "Entering ConnectingOrConnectedState"); 5333 mCmiMonitor.onConnectionStart(mClientModeManager); 5334 } 5335 5336 @Override exitImpl()5337 public void exitImpl() { 5338 if (mVerboseLoggingEnabled) Log.v(getTag(), "Exiting ConnectingOrConnectedState"); 5339 mCmiMonitor.onConnectionEnd(mClientModeManager); 5340 5341 // Not connected/connecting to any network: 5342 // 1. Disable the network in supplicant to prevent it from auto-connecting. We don't 5343 // remove the network to avoid losing any cached info in supplicant (reauth, etc) in 5344 // case we reconnect back to the same network. 5345 // 2. Set a random MAC address to ensure that we're not leaking the MAC address. 5346 mWifiNative.disableNetwork(mInterfaceName); 5347 if (mWifiGlobals.isConnectedMacRandomizationEnabled()) { 5348 mFailedToResetMacAddress = !mWifiNative.setStaMacAddress( 5349 mInterfaceName, MacAddressUtils.createRandomUnicastAddress()); 5350 if (mFailedToResetMacAddress) { 5351 Log.e(getTag(), "Failed to set random MAC address on disconnect"); 5352 } 5353 } 5354 if (mWifiInfo.getBSSID() != null) { 5355 mWifiBlocklistMonitor.removeAffiliatedBssids(mWifiInfo.getBSSID()); 5356 } 5357 mWifiInfo.reset(); 5358 mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); 5359 mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); 5360 updateCurrentConnectionInfo(); 5361 5362 // For secondary client roles, they should stop themselves upon disconnection. 5363 // - Primary role shouldn't because it is persistent, and should try connecting to other 5364 // networks upon disconnection. 5365 // - ROLE_CLIENT_LOCAL_ONLY shouldn't because it has auto-retry logic if the connection 5366 // fails. WifiNetworkFactory will explicitly remove the CMM when the request is 5367 // complete. 5368 // TODO(b/160346062): Maybe clean this up by having ClientModeManager register a 5369 // onExitConnectingOrConnectedState() callback with ClientModeImpl and implementing 5370 // this logic in ClientModeManager. ClientModeImpl should be role-agnostic. 5371 ClientRole role = mClientModeManager.getRole(); 5372 if (role == ROLE_CLIENT_SECONDARY_LONG_LIVED 5373 || role == ROLE_CLIENT_SECONDARY_TRANSIENT) { 5374 if (mVerboseLoggingEnabled) { 5375 Log.d(getTag(), "Disconnected in ROLE_CLIENT_SECONDARY_*, " 5376 + "stop ClientModeManager=" + mClientModeManager); 5377 } 5378 // stop owner ClientModeManager, which will in turn stop this ClientModeImpl 5379 mClientModeManager.stop(); 5380 } 5381 } 5382 5383 @Override getMessageLogRec(int what)5384 String getMessageLogRec(int what) { 5385 return ClientModeImpl.class.getSimpleName() + "." 5386 + ConnectingOrConnectedState.class.getSimpleName() + "." + getWhatToString( 5387 what); 5388 } 5389 5390 @Override processMessageImpl(Message message)5391 public boolean processMessageImpl(Message message) { 5392 boolean handleStatus = HANDLED; 5393 switch (message.what) { 5394 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: { 5395 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 5396 SupplicantState state = handleSupplicantStateChange(stateChangeResult); 5397 // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT 5398 // when authentication times out after a successful connection, 5399 // we can figure this from the supplicant state. If supplicant 5400 // state is DISCONNECTED, but the agent is not disconnected, we 5401 // need to handle a disconnection 5402 if (mVerboseLoggingEnabled) { 5403 log("ConnectingOrConnectedState: Supplicant State change " 5404 + stateChangeResult); 5405 } 5406 @SupplicantEventCode int supplicantEvent; 5407 switch (stateChangeResult.state) { 5408 case COMPLETED: 5409 supplicantEvent = SupplicantStaIfaceHal.SUPPLICANT_EVENT_CONNECTED; 5410 break; 5411 case ASSOCIATING: 5412 supplicantEvent = SupplicantStaIfaceHal.SUPPLICANT_EVENT_ASSOCIATING; 5413 break; 5414 case ASSOCIATED: 5415 supplicantEvent = SupplicantStaIfaceHal.SUPPLICANT_EVENT_ASSOCIATED; 5416 break; 5417 default: 5418 supplicantEvent = -1; 5419 } 5420 if (supplicantEvent != -1) { 5421 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork( 5422 stateChangeResult.networkId); 5423 try { 5424 logEventIfManagedNetwork(config, supplicantEvent, 5425 MacAddress.fromString(stateChangeResult.bssid), ""); 5426 } catch (IllegalArgumentException e) { 5427 Log.i(TAG, "Invalid bssid received for state change event"); 5428 } 5429 } 5430 if (state == SupplicantState.DISCONNECTED && mNetworkAgent != null) { 5431 if (mVerboseLoggingEnabled) { 5432 log("Missed CTRL-EVENT-DISCONNECTED, disconnect"); 5433 } 5434 handleNetworkDisconnect(false, 5435 WIFI_DISCONNECT_REPORTED__FAILURE_CODE__SUPPLICANT_DISCONNECTED); 5436 transitionTo(mDisconnectedState); 5437 } 5438 if (state == SupplicantState.COMPLETED) { 5439 mWifiScoreReport.noteIpCheck(); 5440 } 5441 break; 5442 } 5443 case WifiMonitor.ASSOCIATED_BSSID_EVENT: { 5444 // This is where we can confirm the connection BSSID. Use it to find the 5445 // right ScanDetail to populate metrics. 5446 String someBssid = (String) message.obj; 5447 if (someBssid != null) { 5448 // Get the ScanDetail associated with this BSSID. 5449 ScanDetailCache scanDetailCache = 5450 mWifiConfigManager.getScanDetailCacheForNetwork(mTargetNetworkId); 5451 if (scanDetailCache != null) { 5452 mWifiMetrics.setConnectionScanDetail(mInterfaceName, 5453 scanDetailCache.getScanDetail(someBssid)); 5454 } 5455 // Update last associated BSSID 5456 mLastBssid = someBssid; 5457 } 5458 handleStatus = NOT_HANDLED; 5459 break; 5460 } 5461 case WifiMonitor.NETWORK_CONNECTION_EVENT: { 5462 if (mVerboseLoggingEnabled) log("Network connection established"); 5463 NetworkConnectionEventInfo connectionInfo = 5464 (NetworkConnectionEventInfo) message.obj; 5465 mLastNetworkId = connectionInfo.networkId; 5466 mSentHLPs = connectionInfo.isFilsConnection; 5467 if (mSentHLPs) mWifiMetrics.incrementL2ConnectionThroughFilsAuthCount(); 5468 mWifiConfigManager.clearRecentFailureReason(mLastNetworkId); 5469 mLastBssid = connectionInfo.bssid; 5470 // TODO: This check should not be needed after ClientModeImpl refactor. 5471 // Currently, the last connected network configuration is left in 5472 // wpa_supplicant, this may result in wpa_supplicant initiating connection 5473 // to it after a config store reload. Hence the old network Id lookups may not 5474 // work, so disconnect the network and let network selector reselect a new 5475 // network. 5476 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 5477 if (config == null) { 5478 logw("Connected to unknown networkId " + mLastNetworkId 5479 + ", disconnecting..."); 5480 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_UNKNOWN_NETWORK); 5481 break; 5482 } 5483 handleNetworkConnectionEventInfo(config, connectionInfo); 5484 mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); 5485 5486 ScanDetailCache scanDetailCache = 5487 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); 5488 ScanResult scanResult = null; 5489 if (scanDetailCache != null && mLastBssid != null) { 5490 scanResult = scanDetailCache.getScanResult(mLastBssid); 5491 if (scanResult != null) { 5492 mWifiInfo.setFrequency(scanResult.frequency); 5493 } 5494 } 5495 5496 // We need to get the updated pseudonym from supplicant for EAP-SIM/AKA/AKA' 5497 if (config.enterpriseConfig != null 5498 && config.enterpriseConfig.isAuthenticationSimBased()) { 5499 if (mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled( 5500 config.carrierId)) { 5501 if (mVerboseLoggingEnabled) { 5502 logd("add PseudonymUpdatingListener"); 5503 } 5504 mWifiPseudonymManager.registerPseudonymUpdatingListener( 5505 mPseudonymUpdatingListener); 5506 } 5507 mLastSubId = mWifiCarrierInfoManager.getBestMatchSubscriptionId(config); 5508 mLastSimBasedConnectionCarrierName = 5509 mWifiCarrierInfoManager.getCarrierNameForSubId(mLastSubId); 5510 String anonymousIdentity = 5511 mWifiNative.getEapAnonymousIdentity(mInterfaceName); 5512 if (!TextUtils.isEmpty(anonymousIdentity) 5513 && !WifiCarrierInfoManager 5514 .isAnonymousAtRealmIdentity(anonymousIdentity)) { 5515 String decoratedPseudonym = mWifiCarrierInfoManager 5516 .decoratePseudonymWith3GppRealm(config, 5517 anonymousIdentity); 5518 boolean updateToNativeService = false; 5519 if (decoratedPseudonym != null 5520 && !decoratedPseudonym.equals(anonymousIdentity)) { 5521 anonymousIdentity = decoratedPseudonym; 5522 // propagate to the supplicant to avoid using 5523 // the original anonymous identity for firmware 5524 // roaming. 5525 if (mVerboseLoggingEnabled) { 5526 log("Update decorated pseudonym: " + anonymousIdentity); 5527 } 5528 updateToNativeService = true; 5529 } 5530 // This needs native change to avoid disconnecting from the current 5531 // network. Consider that older releases might not be able to have 5532 // the vendor partition updated, only update to native service on T 5533 // or newer. 5534 if (SdkLevel.isAtLeastT()) { 5535 mWifiNative.setEapAnonymousIdentity(mInterfaceName, 5536 anonymousIdentity, updateToNativeService); 5537 } 5538 if (mVerboseLoggingEnabled) { 5539 log("EAP Pseudonym: " + anonymousIdentity); 5540 } 5541 // Save the pseudonym only if it is a real one 5542 config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity); 5543 int carrierId = config.carrierId; 5544 if (mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled( 5545 carrierId)) { 5546 mWifiPseudonymManager.setInBandPseudonym(carrierId, 5547 anonymousIdentity); 5548 } 5549 } else { 5550 // Clear any stored pseudonyms 5551 config.enterpriseConfig.setAnonymousIdentity(null); 5552 } 5553 mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID); 5554 if (config.isPasspoint()) { 5555 mPasspointManager.setAnonymousIdentity(config); 5556 } else if (config.fromWifiNetworkSuggestion) { 5557 mWifiNetworkSuggestionsManager.setAnonymousIdentity(config); 5558 } 5559 } 5560 // When connecting to Passpoint, ask for the Venue URL 5561 if (config.isPasspoint()) { 5562 mTermsAndConditionsUrl = null; 5563 if (scanResult == null && mLastBssid != null) { 5564 // The cached scan result of connected network would be null at the 5565 // first connection, try to check full scan result list again to look up 5566 // matched scan result associated to the current SSID and BSSID. 5567 scanResult = mScanRequestProxy.getScanResult(mLastBssid); 5568 } 5569 if (scanResult != null) { 5570 mPasspointManager.requestVenueUrlAnqpElement(scanResult); 5571 } 5572 } 5573 mWifiInfo.setNetworkKey(config.getNetworkKeyFromSecurityType( 5574 mWifiInfo.getCurrentSecurityType())); 5575 if (mApplicationQosPolicyRequestHandler.isFeatureEnabled()) { 5576 mApplicationQosPolicyRequestHandler.queueAllPoliciesOnIface(mInterfaceName); 5577 } 5578 updateLayer2Information(); 5579 updateCurrentConnectionInfo(); 5580 transitionTo(mL3ProvisioningState); 5581 break; 5582 } 5583 case CMD_UPDATE_OOB_PSEUDONYM: { 5584 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 5585 if (config == null) { 5586 log("OOB pseudonym is updated, but no valid connected network."); 5587 break; 5588 } 5589 int updatingCarrierId = message.arg1; 5590 if (config.enterpriseConfig == null 5591 || !config.enterpriseConfig.isAuthenticationSimBased() 5592 || !mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled( 5593 config.carrierId) 5594 || updatingCarrierId != config.carrierId) { 5595 log("OOB pseudonym is not applied."); 5596 break; 5597 } 5598 if (SdkLevel.isAtLeastT()) { 5599 log("send OOB pseudonym to supplicant"); 5600 String pseudonym = (String) message.obj; 5601 mWifiNative.setEapAnonymousIdentity(mInterfaceName, 5602 mWifiCarrierInfoManager.decoratePseudonymWith3GppRealm( 5603 config, pseudonym), 5604 /*updateToNativeService=*/ true); 5605 } 5606 break; 5607 } 5608 case WifiMonitor.SUP_REQUEST_SIM_AUTH: { 5609 logd("Received SUP_REQUEST_SIM_AUTH"); 5610 SimAuthRequestData requestData = (SimAuthRequestData) message.obj; 5611 if (requestData != null) { 5612 if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) { 5613 handleGsmAuthRequest(requestData); 5614 } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA 5615 || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) { 5616 handle3GAuthRequest(requestData); 5617 } 5618 } else { 5619 loge("Invalid SIM auth request"); 5620 } 5621 break; 5622 } 5623 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: { 5624 DisconnectEventInfo eventInfo = (DisconnectEventInfo) message.obj; 5625 if (mVerboseLoggingEnabled) { 5626 log("ConnectingOrConnectedState: Network disconnection " + eventInfo); 5627 } 5628 if (eventInfo.reasonCode 5629 == StaIfaceReasonCode.FOURWAY_HANDSHAKE_TIMEOUT) { 5630 String bssid = !isValidBssid(eventInfo.bssid) 5631 ? mTargetBssid : eventInfo.bssid; 5632 mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 5633 getConnectingSsidInternal(), bssid, 5634 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION, 5635 isConnected()); 5636 } 5637 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 5638 if (config == null) { 5639 config = getConnectingWifiConfigurationInternal(); 5640 } 5641 clearNetworkCachedDataIfNeeded(config, eventInfo.reasonCode); 5642 try { 5643 logEventIfManagedNetwork(config, 5644 SupplicantStaIfaceHal.SUPPLICANT_EVENT_DISCONNECTED, 5645 MacAddress.fromString(eventInfo.bssid), 5646 "reason=" + StaIfaceReasonCode.toString(eventInfo.reasonCode)); 5647 } catch (IllegalArgumentException e) { 5648 Log.e(TAG, "Invalid bssid received for disconnection event"); 5649 } 5650 boolean newConnectionInProgress = isNewConnectionInProgress(eventInfo.ssid); 5651 if (!newConnectionInProgress) { 5652 int level2FailureReason = eventInfo.locallyGenerated 5653 ? WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN : 5654 WifiMetricsProto.ConnectionEvent.DISCONNECTION_NON_LOCAL; 5655 if (!eventInfo.locallyGenerated) { 5656 mWifiScoreCard.noteNonlocalDisconnect( 5657 mInterfaceName, eventInfo.reasonCode); 5658 } 5659 reportConnectionAttemptEnd( 5660 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 5661 WifiMetricsProto.ConnectionEvent.HLF_NONE, level2FailureReason); 5662 } 5663 handleNetworkDisconnect(newConnectionInProgress, eventInfo.reasonCode); 5664 if (!newConnectionInProgress) { 5665 transitionTo(mDisconnectedState); 5666 } 5667 mTermsAndConditionsUrl = null; 5668 break; 5669 } 5670 case WifiMonitor.TARGET_BSSID_EVENT: { 5671 // Trying to associate to this BSSID 5672 if (message.obj != null) { 5673 mTargetBssid = (String) message.obj; 5674 } 5675 break; 5676 } 5677 case WifiMonitor.AUXILIARY_SUPPLICANT_EVENT: { 5678 SupplicantEventInfo eventInfo = (SupplicantEventInfo) message.obj; 5679 logEventIfManagedNetwork(getConnectingWifiConfigurationInternal(), 5680 eventInfo.eventCode, eventInfo.bssid, 5681 eventInfo.reasonString); 5682 break; 5683 } 5684 case CMD_DISCONNECT: { 5685 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, 5686 message.arg1); 5687 mWifiNative.disconnect(mInterfaceName); 5688 break; 5689 } 5690 case CMD_PRE_DHCP_ACTION: 5691 case CMD_PRE_DHCP_ACTION_COMPLETE: 5692 case CMD_POST_DHCP_ACTION: 5693 case CMD_IPV4_PROVISIONING_SUCCESS: 5694 case CMD_IP_CONFIGURATION_SUCCESSFUL: 5695 case CMD_IPV4_PROVISIONING_FAILURE: { 5696 handleStatus = handleL3MessagesWhenNotConnected(message); 5697 break; 5698 } 5699 case WifiMonitor.TRANSITION_DISABLE_INDICATION: { 5700 log("Received TRANSITION_DISABLE_INDICATION: networkId=" + message.arg1 5701 + ", indication=" + message.arg2 + ", bssid=" + mLastBssid); 5702 if (isValidTransitionDisableIndicationSource(mLastBssid, message.arg2)) { 5703 mWifiConfigManager.updateNetworkTransitionDisable(message.arg1, 5704 message.arg2); 5705 } else { 5706 Log.w(getTag(), "Drop TRANSITION_DISABLE_INDICATION event" 5707 + " from an invalid source."); 5708 } 5709 break; 5710 } 5711 case WifiMonitor.QOS_POLICY_RESET_EVENT: { 5712 if (SdkLevel.isAtLeastT() && mNetworkAgent != null 5713 && mWifiNative.isQosPolicyFeatureEnabled()) { 5714 mNetworkAgent.sendRemoveAllDscpPolicies(); 5715 } 5716 break; 5717 } 5718 case WifiMonitor.QOS_POLICY_REQUEST_EVENT: { 5719 if (SdkLevel.isAtLeastT() && mWifiNative.isQosPolicyFeatureEnabled()) { 5720 mQosPolicyRequestHandler.queueQosPolicyRequest( 5721 message.arg1, (List<QosPolicyRequest>) message.obj); 5722 } 5723 break; 5724 } 5725 case CMD_REJECT_EAP_INSECURE_CONNECTION: { 5726 log("Received CMD_REJECT_EAP_INSECURE_CONNECTION event"); 5727 boolean disconnectRequired = message.arg2 == 1; 5728 5729 // TOFU connections are not established until the user approves the certificate. 5730 // If TOFU is not supported and the network is already connected, this will 5731 // disconnect the network. 5732 if (disconnectRequired) { 5733 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED); 5734 } 5735 break; 5736 } 5737 default: { 5738 handleStatus = NOT_HANDLED; 5739 break; 5740 } 5741 } 5742 if (handleStatus == HANDLED) { 5743 logStateAndMessage(message, this); 5744 } 5745 return handleStatus; 5746 } 5747 isValidTransitionDisableIndicationSource(String bssid, @WifiMonitor.TransitionDisableIndication int indicationBit)5748 private boolean isValidTransitionDisableIndicationSource(String bssid, 5749 @WifiMonitor.TransitionDisableIndication int indicationBit) { 5750 ScanResult result = mScanRequestProxy.getScanResult(mLastBssid); 5751 if (null == result) return false; 5752 5753 // SAE TDI should only come from a PSK/SAE BSS or a SAE BSS. 5754 if (0 != (indicationBit & WifiMonitor.TDI_USE_WPA3_PERSONAL)) { 5755 return ScanResultUtil.isScanResultForSaeNetwork(result) 5756 || ScanResultUtil.isScanResultForPskSaeTransitionNetwork(result); 5757 } 5758 // SAE_PK TDI should only come from a SAE BSS. 5759 if (0 != (indicationBit & WifiMonitor.TDI_USE_SAE_PK)) { 5760 return ScanResultUtil.isScanResultForSaeNetwork(result); 5761 } 5762 // WPA3 Enterprise TDI should only come from a WPA2/WPA3 Enterprise 5763 // BSS or a WPA3 Enterprise BSS. 5764 if (0 != (indicationBit & WifiMonitor.TDI_USE_WPA3_ENTERPRISE)) { 5765 return ScanResultUtil.isScanResultForWpa3EnterpriseOnlyNetwork(result) 5766 || ScanResultUtil.isScanResultForWpa3EnterpriseTransitionNetwork(result); 5767 } 5768 // OWE TDI should only come from an OPEN/OWE BSS or an OWE BSS. 5769 if (0 != (indicationBit & WifiMonitor.TDI_USE_ENHANCED_OPEN)) { 5770 return ScanResultUtil.isScanResultForOweNetwork(result) 5771 || ScanResultUtil.isScanResultForOweTransitionNetwork(result); 5772 } 5773 return false; 5774 } 5775 } 5776 5777 class L2ConnectingState extends RunnerState { L2ConnectingState(int threshold)5778 L2ConnectingState(int threshold) { 5779 super(threshold, mWifiInjector.getWifiHandlerLocalLog()); 5780 } 5781 5782 @Override enterImpl()5783 public void enterImpl() { 5784 if (mVerboseLoggingEnabled) Log.v(getTag(), "Entering L2ConnectingState"); 5785 // Make sure we connect: we enter this state prior to connecting to a new 5786 // network. In some cases supplicant ignores the connect requests (it might not 5787 // find the target SSID in its cache), Therefore we end up stuck that state, hence the 5788 // need for the watchdog. 5789 mConnectingWatchdogCount++; 5790 logd("Start Connecting Watchdog " + mConnectingWatchdogCount); 5791 sendMessageDelayed(obtainMessage(CMD_CONNECTING_WATCHDOG_TIMER, 5792 mConnectingWatchdogCount, 0), CONNECTING_WATCHDOG_TIMEOUT_MS); 5793 } 5794 5795 @Override exitImpl()5796 public void exitImpl() { 5797 if (mVerboseLoggingEnabled) Log.v(getTag(), "Exiting L2ConnectingState"); 5798 // Cancel any pending CMD_CONNECTING_WATCHDOG_TIMER since this is only valid in 5799 // L2ConnectingState anyway. 5800 removeMessages(CMD_CONNECTING_WATCHDOG_TIMER); 5801 } 5802 5803 @Override getMessageLogRec(int what)5804 String getMessageLogRec(int what) { 5805 return ClientModeImpl.class.getSimpleName() + "." 5806 + L2ConnectingState.class.getSimpleName() + "." + getWhatToString(what); 5807 } 5808 5809 @Override processMessageImpl(Message message)5810 public boolean processMessageImpl(Message message) { 5811 boolean handleStatus = HANDLED; 5812 switch (message.what) { 5813 case WifiMonitor.NETWORK_NOT_FOUND_EVENT: 5814 mNetworkNotFoundEventCount++; 5815 String networkName = (String) message.obj; 5816 if (networkName != null && !networkName.equals(getConnectingSsidInternal())) { 5817 loge("Network not found event received, network: " + networkName 5818 + " which is not the target network: " 5819 + getConnectingSsidInternal()); 5820 break; 5821 } 5822 Log.d(getTag(), "Network not found event received: network: " + networkName); 5823 if (mNetworkNotFoundEventCount 5824 >= mWifiGlobals.getNetworkNotFoundEventThreshold() 5825 && mTargetWifiConfiguration != null 5826 && mTargetWifiConfiguration.SSID != null 5827 && mTargetWifiConfiguration.SSID.equals(networkName)) { 5828 stopIpClient(); 5829 mWifiConfigManager.updateNetworkSelectionStatus( 5830 mTargetWifiConfiguration.networkId, 5831 WifiConfiguration.NetworkSelectionStatus 5832 .DISABLED_NETWORK_NOT_FOUND); 5833 if (SdkLevel.isAtLeastS()) { 5834 mWifiConfigManager.setRecentFailureAssociationStatus( 5835 mTargetWifiConfiguration.networkId, 5836 WifiConfiguration.RECENT_FAILURE_NETWORK_NOT_FOUND); 5837 } 5838 reportConnectionAttemptEnd( 5839 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_NOT_FOUND, 5840 WifiMetricsProto.ConnectionEvent.HLF_NONE, 5841 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 5842 handleNetworkDisconnect(false, 5843 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__UNSPECIFIED); 5844 transitionTo(mDisconnectedState); // End of connection attempt. 5845 } 5846 break; 5847 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: { 5848 AssocRejectEventInfo assocRejectEventInfo = (AssocRejectEventInfo) message.obj; 5849 log("L2ConnectingState: Association rejection " + assocRejectEventInfo); 5850 if (!assocRejectEventInfo.ssid.equals(getConnectingSsidInternal())) { 5851 loge("Association rejection event received on not target network"); 5852 break; 5853 } 5854 stopIpClient(); 5855 mWifiDiagnostics.triggerBugReportDataCapture( 5856 WifiDiagnostics.REPORT_REASON_ASSOC_FAILURE); 5857 String bssid = assocRejectEventInfo.bssid; 5858 boolean timedOut = assocRejectEventInfo.timedOut; 5859 int statusCode = assocRejectEventInfo.statusCode; 5860 if (!isValidBssid(bssid)) { 5861 // If BSSID is null, use the target roam BSSID 5862 bssid = mTargetBssid; 5863 } else if (SUPPLICANT_BSSID_ANY.equals(mTargetBssid)) { 5864 // This is needed by WifiBlocklistMonitor to block continuously 5865 // failing BSSIDs. Need to set here because mTargetBssid is currently 5866 // not being set until association success. 5867 mTargetBssid = bssid; 5868 } 5869 if (!isSecondaryInternet()) { 5870 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 5871 WifiConfiguration.NetworkSelectionStatus 5872 .DISABLED_ASSOCIATION_REJECTION); 5873 } 5874 setAssociationRejectionStatusInConfig(mTargetNetworkId, assocRejectEventInfo); 5875 int level2FailureReason = 5876 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN; 5877 if (statusCode == StaIfaceStatusCode.AP_UNABLE_TO_HANDLE_NEW_STA 5878 || statusCode == StaIfaceStatusCode.ASSOC_REJECTED_TEMPORARILY 5879 || statusCode == StaIfaceStatusCode.DENIED_INSUFFICIENT_BANDWIDTH) { 5880 level2FailureReason = WifiMetricsProto.ConnectionEvent 5881 .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA; 5882 } 5883 5884 // If rejection occurred while Metrics is tracking a ConnectionEvent, end it. 5885 reportConnectionAttemptEnd( 5886 timedOut 5887 ? WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT 5888 : WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, 5889 WifiMetricsProto.ConnectionEvent.HLF_NONE, 5890 level2FailureReason); 5891 5892 if (level2FailureReason != WifiMetricsProto.ConnectionEvent 5893 .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA 5894 && !isSecondaryInternet()) { 5895 mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 5896 getConnectingSsidInternal(), bssid, 5897 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION, 5898 isConnected()); 5899 } 5900 handleNetworkDisconnect(false, 5901 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__UNSPECIFIED); 5902 transitionTo(mDisconnectedState); // End of connection attempt. 5903 break; 5904 } 5905 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: { 5906 AuthenticationFailureEventInfo authenticationFailureEventInfo = 5907 (AuthenticationFailureEventInfo) message.obj; 5908 if (!TextUtils.equals(authenticationFailureEventInfo.ssid, 5909 getConnectingSsidInternal())) { 5910 logw("Authentication failure event received on not target network"); 5911 break; 5912 } 5913 stopIpClient(); 5914 mWifiDiagnostics.triggerBugReportDataCapture( 5915 WifiDiagnostics.REPORT_REASON_AUTH_FAILURE); 5916 int disableReason = WifiConfiguration.NetworkSelectionStatus 5917 .DISABLED_AUTHENTICATION_FAILURE; 5918 int reasonCode = authenticationFailureEventInfo.reasonCode; 5919 int errorCode = authenticationFailureEventInfo.errorCode; 5920 log("L2ConnectingState: Authentication failure " 5921 + " reason=" + reasonCode + " error=" + errorCode); 5922 WifiConfiguration targetedNetwork = 5923 mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 5924 // Check if this is a permanent wrong password failure. 5925 if (isPermanentWrongPasswordFailure(mTargetNetworkId, reasonCode)) { 5926 disableReason = WifiConfiguration.NetworkSelectionStatus 5927 .DISABLED_BY_WRONG_PASSWORD; 5928 // For primary role, send error notification except for local only network, 5929 // for secondary role, send only for secondary internet. 5930 final boolean isForLocalOnly = isRequestedForLocalOnly( 5931 targetedNetwork, mTargetBssid) || isLocalOnly(); 5932 final boolean needNotifyError = isPrimary() ? !isForLocalOnly 5933 : isSecondaryInternet(); 5934 if (targetedNetwork != null && needNotifyError) { 5935 mWrongPasswordNotifier.onWrongPasswordError(targetedNetwork); 5936 } 5937 } else if (reasonCode == WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE) { 5938 logEventIfManagedNetwork(targetedNetwork, 5939 SupplicantStaIfaceHal.SUPPLICANT_EVENT_EAP_FAILURE, 5940 authenticationFailureEventInfo.bssid, "error=" + errorCode); 5941 if (targetedNetwork != null && targetedNetwork.enterpriseConfig != null 5942 && targetedNetwork.enterpriseConfig.isAuthenticationSimBased()) { 5943 // only show EAP failure notification if primary 5944 WifiBlocklistMonitor.CarrierSpecificEapFailureConfig eapFailureConfig = 5945 mEapFailureNotifier.onEapFailure(errorCode, targetedNetwork, 5946 isPrimary()); 5947 if (eapFailureConfig != null) { 5948 disableReason = WifiConfiguration.NetworkSelectionStatus 5949 .DISABLED_AUTHENTICATION_PRIVATE_EAP_ERROR; 5950 mWifiBlocklistMonitor.loadCarrierConfigsForDisableReasonInfos( 5951 eapFailureConfig); 5952 } 5953 } 5954 handleEapAuthFailure(mTargetNetworkId, errorCode); 5955 if (errorCode == WifiNative.EAP_SIM_NOT_SUBSCRIBED) { 5956 disableReason = WifiConfiguration.NetworkSelectionStatus 5957 .DISABLED_AUTHENTICATION_NO_SUBSCRIPTION; 5958 } 5959 } 5960 mWifiConfigManager.updateNetworkSelectionStatus( 5961 mTargetNetworkId, disableReason); 5962 mWifiConfigManager.clearRecentFailureReason(mTargetNetworkId); 5963 5964 //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. 5965 int level2FailureReason; 5966 switch (reasonCode) { 5967 case WifiManager.ERROR_AUTH_FAILURE_NONE: 5968 level2FailureReason = 5969 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE; 5970 break; 5971 case WifiManager.ERROR_AUTH_FAILURE_TIMEOUT: 5972 level2FailureReason = 5973 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT; 5974 break; 5975 case WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD: 5976 level2FailureReason = 5977 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD; 5978 break; 5979 case WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE: 5980 level2FailureReason = 5981 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE; 5982 break; 5983 default: 5984 level2FailureReason = 5985 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN; 5986 break; 5987 } 5988 reportConnectionAttemptEnd( 5989 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, 5990 WifiMetricsProto.ConnectionEvent.HLF_NONE, 5991 level2FailureReason); 5992 if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD && reasonCode 5993 != WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE) { 5994 mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 5995 getConnectingSsidInternal(), 5996 (mLastBssid == null) ? mTargetBssid : mLastBssid, 5997 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION, 5998 isConnected()); 5999 } 6000 handleNetworkDisconnect(false, 6001 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__UNSPECIFIED); 6002 transitionTo(mDisconnectedState); // End of connection attempt. 6003 break; 6004 } 6005 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: { 6006 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 6007 if (SupplicantState.isConnecting(stateChangeResult.state)) { 6008 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork( 6009 stateChangeResult.networkId); 6010 // Update Passpoint information before setNetworkDetailedState as 6011 // WifiTracker monitors NETWORK_STATE_CHANGED_ACTION to update UI. 6012 mWifiInfo.setFQDN(null); 6013 mWifiInfo.setPasspointUniqueId(null); 6014 mWifiInfo.setOsuAp(false); 6015 mWifiInfo.setProviderFriendlyName(null); 6016 if (config != null && (config.isPasspoint() || config.osu)) { 6017 if (config.isPasspoint()) { 6018 mWifiInfo.setFQDN(config.FQDN); 6019 mWifiInfo.setPasspointUniqueId(config.getPasspointUniqueId()); 6020 } else { 6021 mWifiInfo.setOsuAp(true); 6022 } 6023 mWifiInfo.setProviderFriendlyName(config.providerFriendlyName); 6024 mWifiInfo.setNetworkKey( 6025 config.getNetworkKeyFromSecurityType( 6026 mWifiInfo.getCurrentSecurityType())); 6027 } 6028 updateCurrentConnectionInfo(); 6029 } 6030 sendNetworkChangeBroadcast( 6031 WifiInfo.getDetailedStateOf(stateChangeResult.state)); 6032 // Let the parent state handle the rest of the state changed. 6033 handleStatus = NOT_HANDLED; 6034 break; 6035 } 6036 case WifiMonitor.SUP_REQUEST_IDENTITY: { 6037 int netId = message.arg2; 6038 boolean identitySent = false; 6039 // For SIM & AKA/AKA' EAP method Only, get identity from ICC 6040 if (mTargetWifiConfiguration != null 6041 && mTargetWifiConfiguration.networkId == netId 6042 && mTargetWifiConfiguration.enterpriseConfig != null 6043 && mTargetWifiConfiguration.enterpriseConfig 6044 .isAuthenticationSimBased()) { 6045 // Pair<identity, encrypted identity> 6046 Pair<String, String> identityPair = mWifiCarrierInfoManager 6047 .getSimIdentity(mTargetWifiConfiguration); 6048 if (identityPair != null && identityPair.first != null) { 6049 Log.i(getTag(), "SUP_REQUEST_IDENTITY: identityPair=[" 6050 + ((identityPair.first.length() >= 7) 6051 ? identityPair.first.substring(0, 7 /* Prefix+PLMN ID */) 6052 + "****" 6053 : identityPair.first) + ", " 6054 + (!TextUtils.isEmpty(identityPair.second) ? identityPair.second 6055 : "<NONE>") + "]"); 6056 mWifiNative.simIdentityResponse(mInterfaceName, identityPair.first, 6057 identityPair.second); 6058 identitySent = true; 6059 } else { 6060 Log.e(getTag(), "Unable to retrieve identity from Telephony"); 6061 } 6062 } 6063 6064 if (!identitySent) { 6065 // Supplicant lacks credentials to connect to that network, hence block list 6066 String ssid = (String) message.obj; 6067 if (mTargetWifiConfiguration != null && ssid != null 6068 && mTargetWifiConfiguration.SSID != null 6069 && mTargetWifiConfiguration.SSID.equals("\"" + ssid + "\"")) { 6070 mWifiConfigManager.updateNetworkSelectionStatus( 6071 mTargetWifiConfiguration.networkId, 6072 WifiConfiguration.NetworkSelectionStatus 6073 .DISABLED_AUTHENTICATION_NO_CREDENTIALS); 6074 } 6075 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, 6076 StaEvent.DISCONNECT_GENERIC); 6077 mWifiNative.disconnect(mInterfaceName); 6078 } 6079 break; 6080 } 6081 case CMD_CONNECTING_WATCHDOG_TIMER: { 6082 if (mConnectingWatchdogCount == message.arg1) { 6083 if (mVerboseLoggingEnabled) log("Connecting watchdog! -> disconnect"); 6084 reportConnectionAttemptEnd( 6085 WifiMetrics.ConnectionEvent.FAILURE_NO_RESPONSE, 6086 WifiMetricsProto.ConnectionEvent.HLF_NONE, 6087 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 6088 handleNetworkDisconnect(false, 6089 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__CONNECTING_WATCHDOG_TIMER); 6090 transitionTo(mDisconnectedState); 6091 } 6092 break; 6093 } 6094 case WifiMonitor.NETWORK_CONNECTION_EVENT: { 6095 NetworkConnectionEventInfo connectionInfo = 6096 (NetworkConnectionEventInfo) message.obj; 6097 String quotedOrHexConnectingSsid = getConnectingSsidInternal(); 6098 String quotedOrHexConnectedSsid = connectionInfo.wifiSsid.toString(); 6099 if (quotedOrHexConnectingSsid != null 6100 && !quotedOrHexConnectingSsid.equals(quotedOrHexConnectedSsid)) { 6101 // possibly a NETWORK_CONNECTION_EVENT for a successful roam on the previous 6102 // network while connecting to a new network, ignore it. 6103 Log.d(TAG, "Connecting to ssid=" + quotedOrHexConnectingSsid + ", but got " 6104 + "NETWORK_CONNECTION_EVENT for ssid=" + quotedOrHexConnectedSsid 6105 + ", ignoring"); 6106 break; 6107 } 6108 handleStatus = NOT_HANDLED; 6109 break; 6110 } 6111 case WifiMonitor.TOFU_CERTIFICATE_EVENT: { 6112 if (null == mTargetWifiConfiguration) break; 6113 final int certificateDepth = message.arg2; 6114 final CertificateEventInfo eventInfo = (CertificateEventInfo) message.obj; 6115 if (!mInsecureEapNetworkHandler.addPendingCertificate( 6116 mTargetWifiConfiguration.SSID, certificateDepth, eventInfo)) { 6117 Log.d(TAG, "Cannot set pending cert."); 6118 } 6119 // Launch user approval upon receiving the server certificate and disconnect 6120 if (certificateDepth == 0 && !mLeafCertSent && mInsecureEapNetworkHandler 6121 .startUserApprovalIfNecessary(mIsUserSelected)) { 6122 // In the TOFU flow, the user approval dialog is now displayed and the 6123 // network remains disconnected and disabled until it is approved. 6124 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED); 6125 mLeafCertSent = true; 6126 } 6127 break; 6128 } 6129 default: { 6130 handleStatus = NOT_HANDLED; 6131 break; 6132 } 6133 } 6134 if (handleStatus == HANDLED) { 6135 logStateAndMessage(message, this); 6136 } 6137 return handleStatus; 6138 } 6139 } 6140 6141 class L2ConnectedState extends RunnerState { L2ConnectedState(int threshold)6142 L2ConnectedState(int threshold) { 6143 super(threshold, mWifiInjector.getWifiHandlerLocalLog()); 6144 } 6145 6146 @Override enterImpl()6147 public void enterImpl() { 6148 mRssiPollToken++; 6149 if (mEnableRssiPolling) { 6150 if (isPrimary()) { 6151 mLinkProbeManager.resetOnNewConnection(); 6152 } 6153 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0); 6154 } 6155 sendNetworkChangeBroadcast(DetailedState.CONNECTING); 6156 6157 // If this network was explicitly selected by the user, evaluate whether to inform 6158 // ConnectivityService of that fact so the system can treat it appropriately. 6159 final WifiConfiguration config = getConnectedWifiConfigurationInternal(); 6160 6161 final NetworkAgentConfig naConfig = getNetworkAgentConfigInternal(config); 6162 final NetworkCapabilities nc = getCapabilities( 6163 getConnectedWifiConfigurationInternal(), getConnectedBssidInternal()); 6164 // This should never happen. 6165 if (mNetworkAgent != null) { 6166 Log.wtf(getTag(), "mNetworkAgent is not null: " + mNetworkAgent); 6167 mNetworkAgent.unregister(); 6168 } 6169 mNetworkAgent = mWifiInjector.makeWifiNetworkAgent(nc, mLinkProperties, naConfig, 6170 mNetworkFactory.getProvider(), new WifiNetworkAgentCallback()); 6171 mWifiScoreReport.setNetworkAgent(mNetworkAgent); 6172 if (SdkLevel.isAtLeastT()) { 6173 mQosPolicyRequestHandler.setNetworkAgent(mNetworkAgent); 6174 } 6175 6176 // We must clear the config BSSID, as the wifi chipset may decide to roam 6177 // from this point on and having the BSSID specified in the network block would 6178 // cause the roam to faile and the device to disconnect 6179 clearTargetBssid("L2ConnectedState"); 6180 mWifiMetrics.setWifiState(mInterfaceName, WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); 6181 mWifiScoreCard.noteNetworkAgentCreated(mWifiInfo, 6182 mNetworkAgent.getNetwork().getNetId()); 6183 mWifiBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid, mWifiInfo.getSSID()); 6184 // too many places to record connection failure with too many failure reasons. 6185 // So only record success here. 6186 mWifiMetrics.noteFirstL2ConnectionAfterBoot(true); 6187 mCmiMonitor.onL2Connected(mClientModeManager); 6188 mIsLinkedNetworkRoaming = false; 6189 } 6190 6191 @Override exitImpl()6192 public void exitImpl() { 6193 // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectableState 6194 // Bug: 15347363 6195 // For paranoia's sake, call handleNetworkDisconnect 6196 // only if BSSID is null or last networkId 6197 // is not invalid. 6198 if (mVerboseLoggingEnabled) { 6199 StringBuilder sb = new StringBuilder(); 6200 sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId)); 6201 if (mLastBssid != null) { 6202 sb.append(" ").append(mLastBssid); 6203 } 6204 } 6205 mWifiMetrics.setWifiState(mInterfaceName, WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 6206 mWifiStateTracker.updateState(mInterfaceName, WifiStateTracker.DISCONNECTED); 6207 // Inform WifiLockManager 6208 mWifiLockManager.updateWifiClientConnected(mClientModeManager, false); 6209 mLastConnectionCapabilities = null; 6210 } 6211 6212 @Override getMessageLogRec(int what)6213 String getMessageLogRec(int what) { 6214 return ClientModeImpl.class.getSimpleName() + "." 6215 + L2ConnectedState.class.getSimpleName() + "." + getWhatToString(what); 6216 } 6217 6218 @Override processMessageImpl(Message message)6219 public boolean processMessageImpl(Message message) { 6220 boolean handleStatus = HANDLED; 6221 6222 switch (message.what) { 6223 case CMD_PRE_DHCP_ACTION: { 6224 handlePreDhcpSetup(); 6225 break; 6226 } 6227 case CMD_PRE_DHCP_ACTION_COMPLETE: { 6228 if (mIpClient != null) { 6229 mIpClient.completedPreDhcpAction(); 6230 } 6231 break; 6232 } 6233 case CMD_POST_DHCP_ACTION: { 6234 handlePostDhcpSetup(); 6235 // We advance to mL3ConnectedState because IpClient will also send a 6236 // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(), 6237 // which calls updateLinkProperties, which then sends 6238 // CMD_IP_CONFIGURATION_SUCCESSFUL. 6239 break; 6240 } 6241 case CMD_IPV4_PROVISIONING_SUCCESS: { 6242 handleIPv4Success((DhcpResultsParcelable) message.obj); 6243 sendNetworkChangeBroadcastWithCurrentState(); 6244 break; 6245 } 6246 case CMD_IPV4_PROVISIONING_FAILURE: { 6247 handleIPv4Failure(); 6248 mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 6249 getConnectingSsidInternal(), 6250 (mLastBssid == null) ? mTargetBssid : mLastBssid, 6251 WifiLastResortWatchdog.FAILURE_CODE_DHCP, 6252 isConnected()); 6253 break; 6254 } 6255 case CMD_IP_CONFIGURATION_SUCCESSFUL: { 6256 if (getConnectedWifiConfigurationInternal() == null || mNetworkAgent == null) { 6257 // The current config may have been removed while we were connecting, 6258 // trigger a disconnect to clear up state. 6259 reportConnectionAttemptEnd( 6260 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 6261 WifiMetricsProto.ConnectionEvent.HLF_NONE, 6262 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 6263 mWifiNative.disconnect(mInterfaceName); 6264 } else { 6265 handleSuccessfulIpConfiguration(); 6266 sendConnectedState(); 6267 transitionTo(mL3ConnectedState); 6268 } 6269 break; 6270 } 6271 case CMD_IP_CONFIGURATION_LOST: { 6272 // Get Link layer stats so that we get fresh tx packet counters. 6273 getWifiLinkLayerStats(); 6274 handleIpConfigurationLost(); 6275 reportConnectionAttemptEnd( 6276 WifiMetrics.ConnectionEvent.FAILURE_DHCP, 6277 WifiMetricsProto.ConnectionEvent.HLF_NONE, 6278 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 6279 mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 6280 getConnectingSsidInternal(), 6281 (mLastBssid == null) ? mTargetBssid : mLastBssid, 6282 WifiLastResortWatchdog.FAILURE_CODE_DHCP, 6283 isConnected()); 6284 handleNetworkDisconnect(false, 6285 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__UNSPECIFIED); 6286 transitionTo(mDisconnectedState); // End of connection attempt. 6287 break; 6288 } 6289 case CMD_IP_REACHABILITY_LOST: { 6290 if (mVerboseLoggingEnabled && message.obj != null) log((String) message.obj); 6291 mWifiDiagnostics.triggerBugReportDataCapture( 6292 WifiDiagnostics.REPORT_REASON_REACHABILITY_LOST); 6293 mWifiMetrics.logWifiIsUnusableEvent(mInterfaceName, 6294 WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST); 6295 mWifiMetrics.addToWifiUsabilityStatsList(mInterfaceName, 6296 WifiUsabilityStats.LABEL_BAD, 6297 WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1); 6298 if (mWifiGlobals.getIpReachabilityDisconnectEnabled()) { 6299 handleIpReachabilityLost(); 6300 } else { 6301 logd("CMD_IP_REACHABILITY_LOST but disconnect disabled -- ignore"); 6302 } 6303 break; 6304 } 6305 case CMD_IP_REACHABILITY_FAILURE: { 6306 mWifiDiagnostics.triggerBugReportDataCapture( 6307 WifiDiagnostics.REPORT_REASON_REACHABILITY_FAILURE); 6308 handleIpReachabilityFailure((ReachabilityLossInfoParcelable) message.obj); 6309 break; 6310 } 6311 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: { 6312 if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) { 6313 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, 6314 StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); 6315 mWifiNative.disconnect(mInterfaceName); 6316 } 6317 break; 6318 } 6319 case WifiMonitor.NETWORK_CONNECTION_EVENT: { 6320 NetworkConnectionEventInfo connectionInfo = 6321 (NetworkConnectionEventInfo) message.obj; 6322 mLastNetworkId = connectionInfo.networkId; 6323 handleNetworkConnectionEventInfo( 6324 getConnectedWifiConfigurationInternal(), connectionInfo); 6325 mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); 6326 updateLayer2Information(); 6327 updateCurrentConnectionInfo(); 6328 if (!Objects.equals(mLastBssid, connectionInfo.bssid)) { 6329 mLastBssid = connectionInfo.bssid; 6330 sendNetworkChangeBroadcastWithCurrentState(); 6331 } 6332 if (mIsLinkedNetworkRoaming) { 6333 mIsLinkedNetworkRoaming = false; 6334 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 6335 mTargetWifiConfiguration = null; 6336 clearTargetBssid("AllowlistRoamingCompleted"); 6337 sendNetworkChangeBroadcast(DetailedState.CONNECTED); 6338 } 6339 checkIfNeedDisconnectSecondaryWifi(); 6340 if (mApplicationQosPolicyRequestHandler.isFeatureEnabled()) { 6341 mApplicationQosPolicyRequestHandler.queueAllPoliciesOnIface(mInterfaceName); 6342 } 6343 break; 6344 } 6345 case WifiMonitor.BSS_FREQUENCY_CHANGED_EVENT: { 6346 int newFrequency = message.arg1; 6347 if (newFrequency > 0) { 6348 if (mWifiInfo.getFrequency() != newFrequency) { 6349 mWifiInfo.setFrequency(newFrequency); 6350 updateCurrentConnectionInfo(); 6351 updateCapabilities(); 6352 } 6353 } 6354 break; 6355 } 6356 case CMD_ONESHOT_RSSI_POLL: { 6357 if (!mEnableRssiPolling) { 6358 updateLinkLayerStatsRssiDataStallScoreReport(); 6359 } 6360 break; 6361 } 6362 case CMD_RSSI_POLL: { 6363 // TODO(b/179792830): getBSSID() shouldn't be null in L2ConnectedState, 6364 // add debug logs in the meantime. Remove once root cause identified. 6365 if (mWifiInfo.getBSSID() == null) { 6366 Log.wtf(getTag(), "WifiInfo.getBSSID() is null in L2ConnectedState!"); 6367 break; 6368 } 6369 if (message.arg1 == mRssiPollToken) { 6370 updateLinkLayerStatsRssiDataStallScoreReport(); 6371 mWifiScoreCard.noteSignalPoll(mWifiInfo); 6372 if (isPrimary()) { 6373 mLinkProbeManager.updateConnectionStats(mWifiInfo, mInterfaceName); 6374 } 6375 // Update the polling interval as needed before sending the delayed message 6376 // so that the next polling can happen after the updated interval 6377 if (isPrimary()) { 6378 int curState = mWifiInjector.getActiveModeWarden() 6379 .getDeviceMobilityState(); 6380 mRssiMonitor.updatePollRssiInterval(curState); 6381 } 6382 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0), 6383 mWifiGlobals.getPollRssiIntervalMillis()); 6384 if (isPrimary()) { 6385 mWifiTrafficPoller.notifyOnDataActivity( 6386 mWifiInfo.txSuccess, mWifiInfo.rxSuccess); 6387 } 6388 } else { 6389 // Polling has completed 6390 } 6391 break; 6392 } 6393 case CMD_ENABLE_RSSI_POLL: { 6394 cleanWifiScore(); 6395 mEnableRssiPolling = (message.arg1 == 1); 6396 mRssiPollToken++; 6397 if (mEnableRssiPolling) { 6398 // First poll 6399 mLastSignalLevel = -1; 6400 if (isPrimary()) { 6401 mLinkProbeManager.resetOnScreenTurnedOn(); 6402 } 6403 long txBytes = mFacade.getTotalTxBytes() - mFacade.getMobileTxBytes(); 6404 long rxBytes = mFacade.getTotalRxBytes() - mFacade.getMobileRxBytes(); 6405 updateLinkLayerStatsRssiSpeedFrequencyCapabilities(txBytes, rxBytes); 6406 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0), 6407 mWifiGlobals.getPollRssiIntervalMillis()); 6408 } 6409 else { 6410 mRssiMonitor.setShortPollRssiInterval(); 6411 } 6412 break; 6413 } 6414 case WifiMonitor.ASSOCIATED_BSSID_EVENT: { 6415 if ((String) message.obj == null) { 6416 logw("Associated command w/o BSSID"); 6417 break; 6418 } 6419 mLastBssid = (String) message.obj; 6420 if (checkAndHandleLinkedNetworkRoaming(mLastBssid)) { 6421 Log.i(TAG, "Driver initiated allowlist SSID roaming"); 6422 break; 6423 } 6424 if (mLastBssid != null && (mWifiInfo.getBSSID() == null 6425 || !mLastBssid.equals(mWifiInfo.getBSSID()))) { 6426 mWifiInfo.setBSSID(mLastBssid); 6427 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 6428 if (config != null) { 6429 ScanDetailCache scanDetailCache = mWifiConfigManager 6430 .getScanDetailCacheForNetwork(config.networkId); 6431 if (scanDetailCache != null) { 6432 ScanResult scanResult = scanDetailCache.getScanResult(mLastBssid); 6433 if (scanResult != null) { 6434 mWifiInfo.setFrequency(scanResult.frequency); 6435 boolean isHidden = true; 6436 for (byte b : scanResult.getWifiSsid().getBytes()) { 6437 if (b != 0) { 6438 isHidden = false; 6439 break; 6440 } 6441 } 6442 mWifiInfo.setHiddenSSID(isHidden); 6443 } 6444 } 6445 } 6446 sendNetworkChangeBroadcastWithCurrentState(); 6447 mMultiInternetManager.notifyBssidAssociatedEvent(mClientModeManager); 6448 updateCurrentConnectionInfo(); 6449 } 6450 break; 6451 } 6452 case CMD_RECONNECT: { 6453 log(" Ignore CMD_RECONNECT request because wifi is already connected"); 6454 break; 6455 } 6456 case CMD_RESET_SIM_NETWORKS: { 6457 if (message.arg1 != RESET_SIM_REASON_SIM_INSERTED 6458 && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6459 WifiConfiguration config = 6460 mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); 6461 if (config != null 6462 && ((message.arg1 == RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED 6463 && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) 6464 || (config.enterpriseConfig != null 6465 && config.enterpriseConfig.isAuthenticationSimBased() 6466 && !mWifiCarrierInfoManager.isSimReady(mLastSubId)))) { 6467 mWifiMetrics.logStaEvent(mInterfaceName, 6468 StaEvent.TYPE_FRAMEWORK_DISCONNECT, 6469 StaEvent.DISCONNECT_RESET_SIM_NETWORKS); 6470 // remove local PMKSA cache in framework 6471 mWifiNative.removeNetworkCachedData(mLastNetworkId); 6472 // remove network so that supplicant's PMKSA cache is cleared 6473 mWifiNative.removeAllNetworks(mInterfaceName); 6474 if (isPrimary() && !mWifiCarrierInfoManager.isSimReady(mLastSubId)) { 6475 mSimRequiredNotifier.showSimRequiredNotification( 6476 config, mLastSimBasedConnectionCarrierName); 6477 } 6478 } 6479 } 6480 break; 6481 } 6482 case CMD_START_IP_PACKET_OFFLOAD: { 6483 int slot = message.arg1; 6484 int intervalSeconds = message.arg2; 6485 KeepalivePacketData pkt = (KeepalivePacketData) message.obj; 6486 int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds); 6487 if (mNetworkAgent != null) { 6488 mNetworkAgent.sendSocketKeepaliveEvent(slot, result); 6489 } 6490 break; 6491 } 6492 case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: { 6493 if (mIpClient != null) { 6494 final int slot = message.arg1; 6495 if (message.obj instanceof NattKeepalivePacketData) { 6496 final NattKeepalivePacketData pkt = 6497 (NattKeepalivePacketData) message.obj; 6498 mIpClient.addKeepalivePacketFilter(slot, pkt); 6499 } else if (SdkLevel.isAtLeastS()) { 6500 if (message.obj instanceof TcpKeepalivePacketData) { 6501 final TcpKeepalivePacketData pkt = 6502 (TcpKeepalivePacketData) message.obj; 6503 mIpClient.addKeepalivePacketFilter(slot, pkt); 6504 } 6505 // Otherwise unsupported keepalive data class: skip 6506 } else { 6507 // Before S, non-NattKeepalivePacketData KeepalivePacketData would be 6508 // the not-yet-SystemApi android.net.TcpKeepalivePacketData. 6509 // Attempt to parse TcpKeepalivePacketDataParcelable from the 6510 // KeepalivePacketData superclass. 6511 final TcpKeepalivePacketDataParcelable p = 6512 parseTcpKeepalivePacketData((KeepalivePacketData) message.obj); 6513 if (p != null) { 6514 mIpClient.addKeepalivePacketFilter(slot, p); 6515 } 6516 } 6517 } 6518 break; 6519 } 6520 case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF: { 6521 if (mIpClient != null) { 6522 mIpClient.removeKeepalivePacketFilter(message.arg1); 6523 } 6524 break; 6525 } 6526 case WifiMonitor.MLO_LINKS_INFO_CHANGED: 6527 WifiMonitor.MloLinkInfoChangeReason reason = 6528 (WifiMonitor.MloLinkInfoChangeReason) message.obj; 6529 WifiNative.ConnectionMloLinksInfo newInfo = 6530 mWifiNative.getConnectionMloLinksInfo(mInterfaceName); 6531 if (reason == WifiMonitor.MloLinkInfoChangeReason.TID_TO_LINK_MAP) { 6532 // Traffic stream mapping changed. Update link states. 6533 updateMloLinkStates(newInfo); 6534 // There is a change in link capabilities. Will trigger android.net 6535 // .ConnectivityManager.NetworkCallback.onCapabilitiesChanged(). 6536 updateCapabilities(); 6537 } else if (reason 6538 == WifiMonitor.MloLinkInfoChangeReason.MULTI_LINK_RECONFIG_AP_REMOVAL) { 6539 // Link is removed. Set removed link state to MLO_LINK_STATE_UNASSOCIATED. 6540 // Also update block list mapping, as there is a change in affiliated 6541 // BSSIDs. 6542 clearMloLinkStates(); 6543 updateMloLinkStates(newInfo); 6544 updateBlockListAffiliatedBssids(); 6545 // There is a change in link capabilities. Will trigger android.net 6546 // .ConnectivityManager.NetworkCallback.onCapabilitiesChanged(). 6547 updateCapabilities(); 6548 } else { 6549 logw("MLO_LINKS_INFO_CHANGED with UNKNOWN reason"); 6550 } 6551 break; 6552 default: { 6553 handleStatus = NOT_HANDLED; 6554 break; 6555 } 6556 } 6557 6558 if (handleStatus == HANDLED) { 6559 logStateAndMessage(message, this); 6560 } 6561 6562 return handleStatus; 6563 } 6564 6565 /** 6566 * Fetches link stats, updates Wifi Data Stall, Score Card and Score Report. 6567 */ updateLinkLayerStatsRssiDataStallScoreReport()6568 private WifiLinkLayerStats updateLinkLayerStatsRssiDataStallScoreReport() { 6569 // Get Info and continue polling 6570 long txBytes; 6571 long rxBytes; 6572 if (SdkLevel.isAtLeastS()) { 6573 txBytes = mFacade.getTxBytes(mInterfaceName); 6574 rxBytes = mFacade.getRxBytes(mInterfaceName); 6575 } else { 6576 txBytes = mFacade.getTotalTxBytes() - mFacade.getMobileTxBytes(); 6577 rxBytes = mFacade.getTotalRxBytes() - mFacade.getMobileRxBytes(); 6578 } 6579 WifiLinkLayerStats stats = updateLinkLayerStatsRssiSpeedFrequencyCapabilities(txBytes, 6580 rxBytes); 6581 mWifiMetrics.updateWifiUsabilityStatsEntries(mInterfaceName, mWifiInfo, stats); 6582 // checkDataStallAndThroughputSufficiency() should be called before 6583 // mWifiScoreReport.calculateAndReportScore() which needs the latest throughput 6584 int statusDataStall = mWifiDataStall.checkDataStallAndThroughputSufficiency( 6585 mInterfaceName, mLastConnectionCapabilities, mLastLinkLayerStats, stats, 6586 mWifiInfo, txBytes, rxBytes); 6587 if (mDataStallTriggerTimeMs == -1 6588 && statusDataStall != WifiIsUnusableEvent.TYPE_UNKNOWN) { 6589 mDataStallTriggerTimeMs = mClock.getElapsedSinceBootMillis(); 6590 mLastStatusDataStall = statusDataStall; 6591 } 6592 if (mDataStallTriggerTimeMs != -1) { 6593 long elapsedTime = mClock.getElapsedSinceBootMillis() 6594 - mDataStallTriggerTimeMs; 6595 if (elapsedTime >= DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS) { 6596 mDataStallTriggerTimeMs = -1; 6597 mWifiMetrics.addToWifiUsabilityStatsList(mInterfaceName, 6598 WifiUsabilityStats.LABEL_BAD, 6599 convertToUsabilityStatsTriggerType(mLastStatusDataStall), 6600 -1); 6601 mLastStatusDataStall = WifiIsUnusableEvent.TYPE_UNKNOWN; 6602 } 6603 } 6604 // Send the update score to network agent. 6605 mWifiScoreReport.calculateAndReportScore(); 6606 6607 if (mWifiScoreReport.shouldCheckIpLayer()) { 6608 if (mIpClient != null) { 6609 mIpClient.confirmConfiguration(); 6610 } 6611 mWifiScoreReport.noteIpCheck(); 6612 } 6613 6614 mLastLinkLayerStats = stats; 6615 return stats; 6616 } 6617 } 6618 6619 /** 6620 * Fetches link stats and updates Wifi Score Report. 6621 */ updateLinkLayerStatsRssiAndScoreReport()6622 private void updateLinkLayerStatsRssiAndScoreReport() { 6623 sendMessage(CMD_ONESHOT_RSSI_POLL); 6624 } 6625 convertToUsabilityStatsTriggerType(int unusableEventTriggerType)6626 private int convertToUsabilityStatsTriggerType(int unusableEventTriggerType) { 6627 int triggerType; 6628 switch (unusableEventTriggerType) { 6629 case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX: 6630 triggerType = WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX; 6631 break; 6632 case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX: 6633 triggerType = WifiUsabilityStats.TYPE_DATA_STALL_TX_WITHOUT_RX; 6634 break; 6635 case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH: 6636 triggerType = WifiUsabilityStats.TYPE_DATA_STALL_BOTH; 6637 break; 6638 case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT: 6639 triggerType = WifiUsabilityStats.TYPE_FIRMWARE_ALERT; 6640 break; 6641 case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST: 6642 triggerType = WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST; 6643 break; 6644 default: 6645 triggerType = WifiUsabilityStats.TYPE_UNKNOWN; 6646 Log.e(getTag(), "Unknown WifiIsUnusableEvent: " + unusableEventTriggerType); 6647 } 6648 return triggerType; 6649 } 6650 6651 // Before transition to L3ProvisioningState, always shut down the current IpClient 6652 // instance and recreate a new IpClient and IpClientCallbacks instance, defer received 6653 // messages in this state except CMD_IPCLIENT_CREATED, recreation of a new IpClient 6654 // guarantees the out-of-date callbacks will be ignored, otherwise, it's not easy to 6655 // differentiate callbacks which comes from new IpClient or legacy IpClient. So far 6656 // only transit to this state iff IP reachability gets lost post roam. 6657 class WaitBeforeL3ProvisioningState extends RunnerState { WaitBeforeL3ProvisioningState(int threshold)6658 WaitBeforeL3ProvisioningState(int threshold) { 6659 super(threshold, mWifiInjector.getWifiHandlerLocalLog()); 6660 } 6661 6662 @Override enterImpl()6663 public void enterImpl() { 6664 // Recreate a new IpClient instance. 6665 maybeShutdownIpclient(); 6666 makeIpClient(); 6667 6668 // Given that {@link IpClientCallbacks#awaitCreation} is invoked when making a 6669 // IpClient instance, which waits for {@link IPCLIENT_STARTUP_TIMEOUT_MS}. 6670 // If await IpClient recreation times out, then send timeout message to proceed 6671 // to Disconnected state, otherwise, we will never exit this state. 6672 sendMessage(CMD_IPCLIENT_STARTUP_TIMEOUT); 6673 } 6674 6675 @Override exitImpl()6676 public void exitImpl() { 6677 removeMessages(CMD_IPCLIENT_STARTUP_TIMEOUT); 6678 } 6679 6680 @Override processMessageImpl(Message message)6681 public boolean processMessageImpl(Message message) { 6682 switch(message.what) { 6683 case CMD_IPCLIENT_CREATED: { 6684 mIpClient = (IpClientManager) message.obj; 6685 transitionTo(mL3ProvisioningState); 6686 break; 6687 } 6688 6689 case CMD_IPCLIENT_STARTUP_TIMEOUT: { 6690 Log.e(getTag(), "Fail to create an IpClient instance within " 6691 + IPCLIENT_STARTUP_TIMEOUT_MS + "ms"); 6692 handleNetworkDisconnect(false, 6693 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__TIMEOUT); 6694 transitionTo(mDisconnectedState); 6695 break; 6696 } 6697 6698 default: 6699 // Do not process any other messages except CMD_IPCLIENT_CREATED and 6700 // CMD_IPCLIENT_STARTUP_TIMEOUT. This means that this state can be very 6701 // simple because it does not need to worry about messasge ordering. 6702 // Re-creating IpClient should only take a few milliseconds, but in the 6703 // worst case, this will result in the state machine not processing any 6704 // messages for IPCLIENT_STARTUP_TIMEOUT_MS. 6705 deferMessage(message); 6706 } 6707 6708 logStateAndMessage(message, this); 6709 return HANDLED; 6710 } 6711 6712 @Override getMessageLogRec(int what)6713 String getMessageLogRec(int what) { 6714 return ClientModeImpl.class.getSimpleName() + "." 6715 + WaitBeforeL3ProvisioningState.class.getSimpleName() + "." 6716 + getWhatToString(what); 6717 } 6718 } 6719 6720 class L3ProvisioningState extends RunnerState { L3ProvisioningState(int threshold)6721 L3ProvisioningState(int threshold) { 6722 super(threshold, mWifiInjector.getWifiHandlerLocalLog()); 6723 } 6724 6725 @Override enterImpl()6726 public void enterImpl() { 6727 startL3Provisioning(); 6728 } 6729 6730 @Override exitImpl()6731 public void exitImpl() { 6732 } 6733 6734 @Override getMessageLogRec(int what)6735 String getMessageLogRec(int what) { 6736 return ClientModeImpl.class.getSimpleName() + "." 6737 + L3ProvisioningState.class.getSimpleName() + "." + getWhatToString(what); 6738 } 6739 6740 @Override processMessageImpl(Message message)6741 public boolean processMessageImpl(Message message) { 6742 boolean handleStatus = HANDLED; 6743 6744 switch(message.what) { 6745 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: { 6746 DisconnectEventInfo eventInfo = (DisconnectEventInfo) message.obj; 6747 mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 6748 getConnectingSsidInternal(), 6749 !isValidBssid(eventInfo.bssid) 6750 ? mTargetBssid : eventInfo.bssid, 6751 WifiLastResortWatchdog.FAILURE_CODE_DHCP, 6752 isConnected()); 6753 handleStatus = NOT_HANDLED; 6754 break; 6755 } 6756 default: { 6757 handleStatus = NOT_HANDLED; 6758 break; 6759 } 6760 } 6761 6762 if (handleStatus == HANDLED) { 6763 logStateAndMessage(message, this); 6764 } 6765 return handleStatus; 6766 } 6767 startL3Provisioning()6768 private void startL3Provisioning() { 6769 WifiConfiguration currentConfig = getConnectedWifiConfigurationInternal(); 6770 if (mIpClientWithPreConnection && mIpClient != null) { 6771 mIpClient.notifyPreconnectionComplete(mSentHLPs); 6772 mIpClientWithPreConnection = false; 6773 mSentHLPs = false; 6774 } else { 6775 startIpClient(currentConfig, false); 6776 } 6777 // Get Link layer stats so as we get fresh tx packet counters 6778 getWifiLinkLayerStats(); 6779 } 6780 } 6781 6782 /** 6783 * Helper function to check if a network has been recently selected by the user. 6784 * (i.e less than {@link #LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS) before). 6785 */ 6786 @VisibleForTesting isRecentlySelectedByTheUser(@onNull WifiConfiguration currentConfig)6787 public boolean isRecentlySelectedByTheUser(@NonNull WifiConfiguration currentConfig) { 6788 long currentTimeMillis = mClock.getElapsedSinceBootMillis(); 6789 return mWifiConfigManager.getLastSelectedNetwork() == currentConfig.networkId 6790 && currentTimeMillis - mWifiConfigManager.getLastSelectedTimeStamp() 6791 < LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS; 6792 } 6793 sendConnectedState()6794 private void sendConnectedState() { 6795 mNetworkAgent.markConnected(); 6796 sendNetworkChangeBroadcast(DetailedState.CONNECTED); 6797 } 6798 6799 class RoamingState extends RunnerState { 6800 boolean mAssociated; 6801 RoamingState(int threshold)6802 RoamingState(int threshold) { 6803 super(threshold, mWifiInjector.getWifiHandlerLocalLog()); 6804 } 6805 6806 @Override enterImpl()6807 public void enterImpl() { 6808 if (mVerboseLoggingEnabled) { 6809 log("RoamingState Enter mScreenOn=" + mScreenOn); 6810 } 6811 6812 // Make sure we disconnect if roaming fails 6813 mRoamWatchdogCount++; 6814 logd("Start Roam Watchdog " + mRoamWatchdogCount); 6815 sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER, 6816 mRoamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); 6817 mAssociated = false; 6818 } 6819 6820 @Override exitImpl()6821 public void exitImpl() { 6822 } 6823 6824 @Override getMessageLogRec(int what)6825 String getMessageLogRec(int what) { 6826 return ClientModeImpl.class.getSimpleName() + "." + RoamingState.class.getSimpleName() 6827 + "." + getWhatToString(what); 6828 } 6829 6830 @Override processMessageImpl(Message message)6831 public boolean processMessageImpl(Message message) { 6832 boolean handleStatus = HANDLED; 6833 6834 switch (message.what) { 6835 case CMD_IP_CONFIGURATION_LOST: { 6836 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 6837 if (config != null) { 6838 mWifiDiagnostics.triggerBugReportDataCapture( 6839 WifiDiagnostics.REPORT_REASON_AUTOROAM_FAILURE); 6840 } 6841 handleStatus = NOT_HANDLED; 6842 break; 6843 } 6844 case CMD_UNWANTED_NETWORK: { 6845 if (mVerboseLoggingEnabled) { 6846 log("Roaming and CS doesn't want the network -> ignore"); 6847 } 6848 break; 6849 } 6850 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: { 6851 /** 6852 * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT 6853 * before NETWORK_DISCONNECTION_EVENT 6854 * And there is an associated BSSID corresponding to our target BSSID, then 6855 * we have missed the network disconnection, transition to mDisconnectedState 6856 * and handle the rest of the events there. 6857 */ 6858 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 6859 SupplicantState state = handleSupplicantStateChange(stateChangeResult); 6860 if (state == SupplicantState.DISCONNECTED 6861 || state == SupplicantState.INACTIVE 6862 || state == SupplicantState.INTERFACE_DISABLED) { 6863 if (mVerboseLoggingEnabled) { 6864 log("RoamingState: Supplicant State change " + stateChangeResult); 6865 } 6866 handleNetworkDisconnect(false, 6867 WIFI_DISCONNECT_REPORTED__FAILURE_CODE__SUPPLICANT_DISCONNECTED); 6868 transitionTo(mDisconnectedState); 6869 } 6870 if (stateChangeResult.state == SupplicantState.ASSOCIATED) { 6871 // We completed the layer2 roaming part 6872 mAssociated = true; 6873 mTargetBssid = stateChangeResult.bssid; 6874 } 6875 break; 6876 } 6877 case CMD_ROAM_WATCHDOG_TIMER: { 6878 if (mRoamWatchdogCount == message.arg1) { 6879 if (mVerboseLoggingEnabled) log("roaming watchdog! -> disconnect"); 6880 mWifiMetrics.endConnectionEvent( 6881 mInterfaceName, 6882 WifiMetrics.ConnectionEvent.FAILURE_ROAM_TIMEOUT, 6883 WifiMetricsProto.ConnectionEvent.HLF_NONE, 6884 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 6885 mWifiInfo.getFrequency()); 6886 mRoamFailCount++; 6887 handleNetworkDisconnect(false, 6888 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__ROAM_WATCHDOG_TIMER); 6889 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, 6890 StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER); 6891 mWifiNative.disconnect(mInterfaceName); 6892 transitionTo(mDisconnectedState); 6893 } 6894 break; 6895 } 6896 case WifiMonitor.NETWORK_CONNECTION_EVENT: { 6897 if (mAssociated) { 6898 if (mVerboseLoggingEnabled) { 6899 log("roaming and Network connection established"); 6900 } 6901 NetworkConnectionEventInfo connectionInfo = 6902 (NetworkConnectionEventInfo) message.obj; 6903 mLastNetworkId = connectionInfo.networkId; 6904 mLastBssid = connectionInfo.bssid; 6905 handleNetworkConnectionEventInfo( 6906 getConnectedWifiConfigurationInternal(), connectionInfo); 6907 updateLayer2Information(); 6908 sendNetworkChangeBroadcastWithCurrentState(); 6909 updateCurrentConnectionInfo(); 6910 // Successful framework roam! (probably) 6911 mWifiBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid, 6912 mWifiInfo.getSSID()); 6913 reportConnectionAttemptEnd( 6914 WifiMetrics.ConnectionEvent.FAILURE_NONE, 6915 WifiMetricsProto.ConnectionEvent.HLF_NONE, 6916 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 6917 6918 // We must clear the config BSSID, as the wifi chipset may decide to roam 6919 // from this point on and having the BSSID specified by QNS would cause 6920 // the roam to fail and the device to disconnect. 6921 // When transition from RoamingState to DisconnectedState, the config BSSID 6922 // is cleared by handleNetworkDisconnect(). 6923 clearTargetBssid("RoamingCompleted"); 6924 6925 // We used to transition to L3ProvisioningState in an 6926 // attempt to do DHCPv4 RENEWs on framework roams. 6927 // DHCP can take too long to time out, and we now rely 6928 // upon IpClient's use of IpReachabilityMonitor to 6929 // confirm our current network configuration. 6930 // 6931 // mIpClient.confirmConfiguration() is called within 6932 // the handling of SupplicantState.COMPLETED. 6933 transitionTo(mL3ConnectedState); 6934 } else { 6935 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6936 } 6937 break; 6938 } 6939 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: { 6940 // Throw away but only if it corresponds to the network we're roaming to 6941 DisconnectEventInfo eventInfo = (DisconnectEventInfo) message.obj; 6942 if (true) { 6943 String target = ""; 6944 if (mTargetBssid != null) target = mTargetBssid; 6945 log("NETWORK_DISCONNECTION_EVENT in roaming state" 6946 + " BSSID=" + eventInfo.bssid 6947 + " target=" + target); 6948 } 6949 clearNetworkCachedDataIfNeeded( 6950 getConnectingWifiConfigurationInternal(), eventInfo.reasonCode); 6951 if (eventInfo.bssid.equals(mTargetBssid)) { 6952 handleNetworkDisconnect(false, eventInfo.reasonCode); 6953 transitionTo(mDisconnectedState); 6954 } 6955 break; 6956 } 6957 default: { 6958 handleStatus = NOT_HANDLED; 6959 break; 6960 } 6961 } 6962 6963 if (handleStatus == HANDLED) { 6964 logStateAndMessage(message, this); 6965 } 6966 return handleStatus; 6967 } 6968 6969 @Override exit()6970 public void exit() { 6971 logd("ClientModeImpl: Leaving Roaming state"); 6972 } 6973 } 6974 6975 class L3ConnectedState extends RunnerState { L3ConnectedState(int threshold)6976 L3ConnectedState(int threshold) { 6977 super(threshold, mWifiInjector.getWifiHandlerLocalLog()); 6978 } 6979 6980 @Override enterImpl()6981 public void enterImpl() { 6982 if (mVerboseLoggingEnabled) { 6983 log("Enter ConnectedState mScreenOn=" + mScreenOn); 6984 } 6985 6986 reportConnectionAttemptEnd( 6987 WifiMetrics.ConnectionEvent.FAILURE_NONE, 6988 WifiMetricsProto.ConnectionEvent.HLF_NONE, 6989 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 6990 mWifiConnectivityManager.handleConnectionStateChanged( 6991 mClientModeManager, 6992 WifiConnectivityManager.WIFI_STATE_CONNECTED); 6993 registerConnected(); 6994 mTargetWifiConfiguration = null; 6995 mWifiScoreReport.reset(); 6996 mLastSignalLevel = -1; 6997 6998 // Not roaming anymore 6999 mIsAutoRoaming = false; 7000 7001 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 7002 mWifiLastResortWatchdog.connectedStateTransition(true); 7003 mWifiStateTracker.updateState(mInterfaceName, WifiStateTracker.CONNECTED); 7004 // Inform WifiLockManager 7005 mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); 7006 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 7007 mWifiScoreReport.startConnectedNetworkScorer( 7008 mNetworkAgent.getNetwork().getNetId(), isRecentlySelectedByTheUser(config)); 7009 updateLinkLayerStatsRssiAndScoreReport(); 7010 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 7011 // too many places to record L3 failure with too many failure reasons. 7012 // So only record success here. 7013 mWifiMetrics.noteFirstL3ConnectionAfterBoot(true); 7014 updateCurrentConnectionInfo(); 7015 } 7016 7017 @Override getMessageLogRec(int what)7018 String getMessageLogRec(int what) { 7019 return ClientModeImpl.class.getSimpleName() + "." 7020 + L3ConnectedState.class.getSimpleName() + "." + getWhatToString(what); 7021 } 7022 7023 @Override processMessageImpl(Message message)7024 public boolean processMessageImpl(Message message) { 7025 boolean handleStatus = HANDLED; 7026 7027 switch (message.what) { 7028 case CMD_UNWANTED_NETWORK: { 7029 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { 7030 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, 7031 StaEvent.DISCONNECT_UNWANTED); 7032 if (mClientModeManager.getRole() == ROLE_CLIENT_SECONDARY_TRANSIENT 7033 && mClientModeManager.getPreviousRole() == ROLE_CLIENT_PRIMARY) { 7034 mWifiMetrics.incrementMakeBeforeBreakLingerCompletedCount( 7035 mClock.getElapsedSinceBootMillis() 7036 - mClientModeManager.getLastRoleChangeSinceBootMs()); 7037 } 7038 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 7039 if (mWifiGlobals.disableUnwantedNetworkOnLowRssi() && isPrimary() 7040 && config != null && !isRecentlySelectedByTheUser(config) 7041 && config.getNetworkSelectionStatus() 7042 .getNetworkSelectionDisableReason() 7043 == DISABLED_NONE && mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI 7044 && mWifiInfo.getRssi() < mScoringParams.getSufficientRssi( 7045 mWifiInfo.getFrequency())) { 7046 if (mVerboseLoggingEnabled) { 7047 Log.i(getTag(), "CMD_UNWANTED_NETWORK update network " 7048 + config.networkId + " with DISABLED_UNWANTED_LOW_RSSI " 7049 + "under rssi:" + mWifiInfo.getRssi()); 7050 } 7051 mWifiConfigManager.updateNetworkSelectionStatus( 7052 config.networkId, 7053 DISABLED_UNWANTED_LOW_RSSI); 7054 } 7055 mWifiNative.disconnect(mInterfaceName); 7056 } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 7057 || message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { 7058 Log.d(getTag(), (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 7059 ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN" 7060 : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED")); 7061 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 7062 if (config != null) { 7063 // Disable autojoin 7064 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) { 7065 mWifiConfigManager.setNetworkValidatedInternetAccess( 7066 config.networkId, false); 7067 WifiScoreCard.PerBssid perBssid = mWifiScoreCard.lookupBssid( 7068 mWifiInfo.getSSID(), mWifiInfo.getBSSID()); 7069 int probInternet = perBssid.estimatePercentInternetAvailability(); 7070 if (mVerboseLoggingEnabled) { 7071 Log.d(TAG, "Potentially disabling network due to no " 7072 + "internet. Probability of having internet = " 7073 + probInternet); 7074 } 7075 // Only permanently disable a network if probability of having 7076 // internet from the currently connected BSSID is less than 60%. 7077 // If there is no historically information of the current BSSID, 7078 // the probability of internet will default to 50%, and the network 7079 // will be permanently disabled. 7080 mWifiConfigManager.updateNetworkSelectionStatus(config.networkId, 7081 probInternet < PROBABILITY_WITH_INTERNET_TO_PERMANENTLY_DISABLE_NETWORK 7082 ? DISABLED_NO_INTERNET_PERMANENT 7083 : DISABLED_NO_INTERNET_TEMPORARY); 7084 } else { // NETWORK_STATUS_UNWANTED_VALIDATION_FAILED 7085 // stop collect last-mile stats since validation fail 7086 mWifiDiagnostics.reportConnectionEvent( 7087 WifiDiagnostics.CONNECTION_EVENT_FAILED, 7088 mClientModeManager); 7089 mWifiConfigManager.incrementNetworkNoInternetAccessReports( 7090 config.networkId); 7091 // If this was not recently selected by the user, update network 7092 // selection status to temporarily disable the network. 7093 if (!isRecentlySelectedByTheUser(config) 7094 && !config.noInternetAccessExpected) { 7095 if (config.getNetworkSelectionStatus() 7096 .getNetworkSelectionDisableReason() 7097 != DISABLED_NO_INTERNET_PERMANENT) { 7098 Log.i(getTag(), "Temporarily disabling network " 7099 + "because of no-internet access"); 7100 mWifiConfigManager.updateNetworkSelectionStatus( 7101 config.networkId, 7102 DISABLED_NO_INTERNET_TEMPORARY); 7103 } 7104 mWifiBlocklistMonitor.handleBssidConnectionFailure( 7105 mLastBssid, config, 7106 WifiBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE, 7107 mWifiInfo.getRssi()); 7108 } 7109 mWifiScoreCard.noteValidationFailure(mWifiInfo); 7110 mCmiMonitor.onInternetValidationFailed(mClientModeManager, 7111 mCurrentConnectionDetectedCaptivePortal); 7112 } 7113 } 7114 } 7115 break; 7116 } 7117 case CMD_NETWORK_STATUS: { 7118 if (message.arg1 == NetworkAgent.VALIDATION_STATUS_VALID) { 7119 // stop collect last-mile stats since validation pass 7120 mWifiDiagnostics.reportConnectionEvent( 7121 WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED, mClientModeManager); 7122 mWifiScoreCard.noteValidationSuccess(mWifiInfo); 7123 mWifiBlocklistMonitor.handleNetworkValidationSuccess(mLastBssid, 7124 mWifiInfo.getSSID()); 7125 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 7126 if (config != null) { 7127 // re-enable autojoin 7128 mWifiConfigManager.updateNetworkSelectionStatus( 7129 config.networkId, 7130 WifiConfiguration.NetworkSelectionStatus 7131 .DISABLED_NONE); 7132 mWifiConfigManager.setNetworkValidatedInternetAccess( 7133 config.networkId, true); 7134 if (config.isPasspoint() 7135 && mTermsAndConditionsUrl != null) { 7136 // Clear the T&C after the user accepted them and the we are 7137 // notified that the network validation is successful 7138 mTermsAndConditionsUrl = null; 7139 LinkProperties newLp = new LinkProperties(mLinkProperties); 7140 addPasspointInfoToLinkProperties(newLp); 7141 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); 7142 mWifiMetrics 7143 .incrementTotalNumberOfPasspointAcceptanceOfTermsAndConditions(); 7144 } 7145 if (retrieveConnectedNetworkDefaultGateway()) { 7146 updateLinkedNetworks(config); 7147 } 7148 } 7149 mCmiMonitor.onInternetValidated(mClientModeManager); 7150 } 7151 break; 7152 } 7153 case CMD_ACCEPT_UNVALIDATED: { 7154 boolean accept = (message.arg1 != 0); 7155 mWifiConfigManager.setNetworkNoInternetAccessExpected(mLastNetworkId, accept); 7156 break; 7157 } 7158 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: { 7159 DisconnectEventInfo eventInfo = (DisconnectEventInfo) message.obj; 7160 reportConnectionAttemptEnd( 7161 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 7162 WifiMetricsProto.ConnectionEvent.HLF_NONE, 7163 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 7164 if (unexpectedDisconnectedReason(eventInfo.reasonCode)) { 7165 mWifiDiagnostics.triggerBugReportDataCapture( 7166 WifiDiagnostics.REPORT_REASON_UNEXPECTED_DISCONNECT); 7167 } 7168 7169 if (!eventInfo.locallyGenerated) { 7170 // ignore disconnects initiated by wpa_supplicant. 7171 mWifiScoreCard.noteNonlocalDisconnect(mInterfaceName, eventInfo.reasonCode); 7172 int rssi = mWifiInfo.getRssi(); 7173 mWifiBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(), 7174 getConnectedWifiConfiguration(), 7175 WifiBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, rssi); 7176 } 7177 WifiConfiguration config = getConnectedWifiConfigurationInternal(); 7178 7179 if (mVerboseLoggingEnabled) { 7180 log("NETWORK_DISCONNECTION_EVENT in connected state" 7181 + " BSSID=" + mWifiInfo.getBSSID() 7182 + " RSSI=" + mWifiInfo.getRssi() 7183 + " freq=" + mWifiInfo.getFrequency() 7184 + " reason=" + eventInfo.reasonCode 7185 + " Network Selection Status=" + (config == null ? "Unavailable" 7186 : config.getNetworkSelectionStatus().getNetworkStatusString())); 7187 } 7188 handleNetworkDisconnect(false, eventInfo.reasonCode); 7189 transitionTo(mDisconnectedState); 7190 break; 7191 } 7192 case CMD_START_ROAM: { 7193 /* Connect command coming from auto-join */ 7194 int netId = message.arg1; 7195 String bssid = (String) message.obj; 7196 if (bssid == null) { 7197 bssid = SUPPLICANT_BSSID_ANY; 7198 } 7199 WifiConfiguration config = 7200 mWifiConfigManager.getConfiguredNetworkWithoutMasking(netId); 7201 if (config == null) { 7202 loge("CMD_START_ROAM and no config, bail out..."); 7203 break; 7204 } 7205 mLastScanRssi = mWifiConfigManager.findScanRssi(netId, 7206 mWifiHealthMonitor.getScanRssiValidTimeMs()); 7207 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, mLastScanRssi, config.SSID); 7208 setTargetBssid(config, bssid); 7209 mTargetNetworkId = netId; 7210 mWifiPseudonymManager.enableStrictConservativePeerModeIfSupported(config); 7211 logd("CMD_START_ROAM sup state " 7212 + " my state " + getCurrentState().getName() 7213 + " nid=" + Integer.toString(netId) 7214 + " config " + config.getProfileKey() 7215 + " targetRoamBSSID " + mTargetBssid); 7216 7217 reportConnectionAttemptStart(config, mTargetBssid, 7218 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 7219 if (mWifiNative.roamToNetwork(mInterfaceName, config)) { 7220 mTargetWifiConfiguration = config; 7221 mIsAutoRoaming = true; 7222 mWifiMetrics.logStaEvent( 7223 mInterfaceName, StaEvent.TYPE_CMD_START_ROAM, config); 7224 transitionTo(mRoamingState); 7225 } else { 7226 loge("CMD_START_ROAM Failed to start roaming to network " + config); 7227 reportConnectionAttemptEnd( 7228 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 7229 WifiMetricsProto.ConnectionEvent.HLF_NONE, 7230 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); 7231 mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 7232 break; 7233 } 7234 break; 7235 } 7236 case CMD_IP_CONFIGURATION_LOST: { 7237 mWifiMetrics.incrementIpRenewalFailure(); 7238 handleStatus = NOT_HANDLED; 7239 break; 7240 } 7241 default: { 7242 handleStatus = NOT_HANDLED; 7243 break; 7244 } 7245 } 7246 7247 if (handleStatus == HANDLED) { 7248 logStateAndMessage(message, this); 7249 } 7250 7251 return handleStatus; 7252 } 7253 7254 @Override exitImpl()7255 public void exitImpl() { 7256 logd("ClientModeImpl: Leaving Connected state"); 7257 mWifiConnectivityManager.handleConnectionStateChanged( 7258 mClientModeManager, 7259 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 7260 7261 mWifiLastResortWatchdog.connectedStateTransition(false); 7262 } 7263 } 7264 7265 class DisconnectedState extends RunnerState { DisconnectedState(int threshold)7266 DisconnectedState(int threshold) { 7267 super(threshold, mWifiInjector.getWifiHandlerLocalLog()); 7268 } 7269 7270 @Override enterImpl()7271 public void enterImpl() { 7272 Log.i(getTag(), "disconnectedstate enter"); 7273 // We don't scan frequently if this is a temporary disconnect 7274 // due to p2p 7275 if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) { 7276 // TODO(b/161569371): P2P should wait for all ClientModeImpls to enter 7277 // DisconnectedState, not just one instance. 7278 // (Does P2P Service support STA+P2P concurrency?) 7279 mWifiP2pConnection.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 7280 return; 7281 } 7282 7283 if (mVerboseLoggingEnabled) { 7284 logd(" Enter DisconnectedState screenOn=" + mScreenOn); 7285 } 7286 7287 /** clear the roaming state, if we were roaming, we failed */ 7288 mIsAutoRoaming = false; 7289 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 7290 7291 mWifiConnectivityManager.handleConnectionStateChanged( 7292 mClientModeManager, 7293 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 7294 7295 if (mDeviceConfigFacade.isOobPseudonymEnabled()) { 7296 if (mVerboseLoggingEnabled) { 7297 logd("unregister PseudonymUpdatingListener"); 7298 } 7299 // unregister it any way, if it was not registered, it's no OP. 7300 mWifiPseudonymManager 7301 .unregisterPseudonymUpdatingListener(mPseudonymUpdatingListener); 7302 } 7303 } 7304 7305 @Override getMessageLogRec(int what)7306 String getMessageLogRec(int what) { 7307 return ClientModeImpl.class.getSimpleName() + "." 7308 + DisconnectedState.class.getSimpleName() + "." + getWhatToString(what); 7309 } 7310 7311 @Override processMessageImpl(Message message)7312 public boolean processMessageImpl(Message message) { 7313 boolean handleStatus = HANDLED; 7314 7315 switch (message.what) { 7316 case CMD_RECONNECT: 7317 case CMD_REASSOCIATE: { 7318 if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) { 7319 // Drop a third party reconnect/reassociate if STA is 7320 // temporarily disconnected for p2p 7321 break; 7322 } else { 7323 // ConnectableState handles it 7324 handleStatus = NOT_HANDLED; 7325 } 7326 break; 7327 } 7328 default: { 7329 handleStatus = NOT_HANDLED; 7330 break; 7331 } 7332 } 7333 7334 if (handleStatus == HANDLED) { 7335 logStateAndMessage(message, this); 7336 } 7337 return handleStatus; 7338 } 7339 7340 @Override exitImpl()7341 public void exitImpl() { 7342 mWifiConnectivityManager.handleConnectionStateChanged( 7343 mClientModeManager, 7344 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 7345 } 7346 } 7347 handleGsmAuthRequest(SimAuthRequestData requestData)7348 void handleGsmAuthRequest(SimAuthRequestData requestData) { 7349 WifiConfiguration requestingWifiConfiguration = null; 7350 if (mTargetWifiConfiguration != null 7351 && mTargetWifiConfiguration.networkId 7352 == requestData.networkId) { 7353 requestingWifiConfiguration = mTargetWifiConfiguration; 7354 logd("id matches targetWifiConfiguration"); 7355 } else if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 7356 && mLastNetworkId == requestData.networkId) { 7357 requestingWifiConfiguration = getConnectedWifiConfigurationInternal(); 7358 logd("id matches currentWifiConfiguration"); 7359 } 7360 7361 if (requestingWifiConfiguration == null) { 7362 logd("GsmAuthRequest received with null target/current WifiConfiguration."); 7363 return; 7364 } 7365 7366 /* 7367 * Try authentication in the following order. 7368 * 7369 * Standard Cellular_auth Type Command 7370 * 7371 * 1. 3GPP TS 31.102 3G_authentication [Length][RAND][Length][AUTN] 7372 * [Length][RES][Length][CK][Length][IK] and more 7373 * 2. 3GPP TS 31.102 2G_authentication [Length][RAND] 7374 * [Length][SRES][Length][Cipher Key Kc] 7375 * 3. 3GPP TS 11.11 2G_authentication [RAND] 7376 * [SRES][Cipher Key Kc] 7377 */ 7378 String response = mWifiCarrierInfoManager 7379 .getGsmSimAuthResponse(requestData.data, requestingWifiConfiguration); 7380 if (response == null) { 7381 // In case of failure, issue may be due to sim type, retry as No.2 case 7382 response = mWifiCarrierInfoManager 7383 .getGsmSimpleSimAuthResponse(requestData.data, requestingWifiConfiguration); 7384 if (response == null) { 7385 // In case of failure, issue may be due to sim type, retry as No.3 case 7386 response = mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse( 7387 requestData.data, requestingWifiConfiguration); 7388 } 7389 } 7390 if (response == null || response.length() == 0) { 7391 mWifiNative.simAuthFailedResponse(mInterfaceName); 7392 } else { 7393 logv("Supplicant Response -" + response); 7394 mWifiNative.simAuthResponse( 7395 mInterfaceName, WifiNative.SIM_AUTH_RESP_TYPE_GSM_AUTH, response); 7396 } 7397 } 7398 handle3GAuthRequest(SimAuthRequestData requestData)7399 void handle3GAuthRequest(SimAuthRequestData requestData) { 7400 WifiConfiguration requestingWifiConfiguration = null; 7401 if (mTargetWifiConfiguration != null 7402 && mTargetWifiConfiguration.networkId 7403 == requestData.networkId) { 7404 requestingWifiConfiguration = mTargetWifiConfiguration; 7405 logd("id matches targetWifiConfiguration"); 7406 } else if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 7407 && mLastNetworkId == requestData.networkId) { 7408 requestingWifiConfiguration = getConnectedWifiConfigurationInternal(); 7409 logd("id matches currentWifiConfiguration"); 7410 } 7411 7412 if (requestingWifiConfiguration == null) { 7413 logd("3GAuthRequest received with null target/current WifiConfiguration."); 7414 return; 7415 } 7416 7417 SimAuthResponseData response = mWifiCarrierInfoManager 7418 .get3GAuthResponse(requestData, requestingWifiConfiguration); 7419 if (response != null) { 7420 mWifiNative.simAuthResponse( 7421 mInterfaceName, response.type, response.response); 7422 } else { 7423 mWifiNative.umtsAuthFailedResponse(mInterfaceName); 7424 } 7425 } 7426 7427 /** 7428 * Automatically connect to the network specified 7429 * 7430 * @param networkId ID of the network to connect to 7431 * @param uid UID of the app triggering the connection. 7432 * @param bssid BSSID of the network 7433 */ startConnectToNetwork(int networkId, int uid, String bssid)7434 public void startConnectToNetwork(int networkId, int uid, String bssid) { 7435 sendMessage(CMD_START_CONNECT, networkId, uid, bssid); 7436 } 7437 7438 /** 7439 * Automatically roam to the network specified 7440 * 7441 * @param networkId ID of the network to roam to 7442 * @param bssid BSSID of the access point to roam to. 7443 */ startRoamToNetwork(int networkId, String bssid)7444 public void startRoamToNetwork(int networkId, String bssid) { 7445 sendMessage(CMD_START_ROAM, networkId, 0, bssid); 7446 } 7447 7448 /** 7449 * @param reason reason code from supplicant on network disconnected event 7450 * @return true if this is a suspicious disconnect 7451 */ unexpectedDisconnectedReason(int reason)7452 static boolean unexpectedDisconnectedReason(int reason) { 7453 return reason == StaIfaceReasonCode.PREV_AUTH_NOT_VALID 7454 || reason == StaIfaceReasonCode.CLASS2_FRAME_FROM_NONAUTH_STA 7455 || reason == StaIfaceReasonCode.CLASS3_FRAME_FROM_NONASSOC_STA 7456 || reason == StaIfaceReasonCode.DISASSOC_STA_HAS_LEFT 7457 || reason == StaIfaceReasonCode.STA_REQ_ASSOC_WITHOUT_AUTH 7458 || reason == StaIfaceReasonCode.MICHAEL_MIC_FAILURE 7459 || reason == StaIfaceReasonCode.FOURWAY_HANDSHAKE_TIMEOUT 7460 || reason == StaIfaceReasonCode.GROUP_KEY_UPDATE_TIMEOUT 7461 || reason == StaIfaceReasonCode.GROUP_CIPHER_NOT_VALID 7462 || reason == StaIfaceReasonCode.PAIRWISE_CIPHER_NOT_VALID 7463 || reason == StaIfaceReasonCode.IEEE_802_1X_AUTH_FAILED 7464 || reason == StaIfaceReasonCode.DISASSOC_LOW_ACK; 7465 } 7466 getLinkPropertiesSummary(LinkProperties lp)7467 private static String getLinkPropertiesSummary(LinkProperties lp) { 7468 List<String> attributes = new ArrayList<>(6); 7469 if (lp.hasIpv4Address()) { 7470 attributes.add("v4"); 7471 } 7472 if (lp.hasIpv4DefaultRoute()) { 7473 attributes.add("v4r"); 7474 } 7475 if (lp.hasIpv4DnsServer()) { 7476 attributes.add("v4dns"); 7477 } 7478 if (lp.hasGlobalIpv6Address()) { 7479 attributes.add("v6"); 7480 } 7481 if (lp.hasIpv6DefaultRoute()) { 7482 attributes.add("v6r"); 7483 } 7484 if (lp.hasIpv6DnsServer()) { 7485 attributes.add("v6dns"); 7486 } 7487 7488 return TextUtils.join(" ", attributes); 7489 } 7490 7491 /** 7492 * Gets the SSID from the WifiConfiguration pointed at by 'mTargetNetworkId' 7493 * This should match the network config framework is attempting to connect to. 7494 */ getConnectingSsidInternal()7495 private String getConnectingSsidInternal() { 7496 WifiConfiguration config = getConnectingWifiConfigurationInternal(); 7497 return config != null ? config.SSID : null; 7498 } 7499 7500 /** 7501 * Check if there is any connection request for WiFi network. 7502 */ hasConnectionRequests()7503 private boolean hasConnectionRequests() { 7504 return mNetworkFactory.hasConnectionRequests() 7505 || mUntrustedNetworkFactory.hasConnectionRequests() 7506 || mOemWifiNetworkFactory.hasConnectionRequests() 7507 || mRestrictedWifiNetworkFactory.hasConnectionRequests() 7508 || mMultiInternetManager.hasPendingConnectionRequests(); 7509 } 7510 7511 /** 7512 * Retrieve the factory MAC address from config store (stored on first bootup). If we don't have 7513 * a factory MAC address stored in config store, retrieve it now and store it. 7514 * 7515 * Note: 7516 * <li> Retries added to deal with any transient failures when invoking 7517 * {@link WifiNative#getStaFactoryMacAddress(String)}. 7518 */ 7519 @Nullable retrieveFactoryMacAddressAndStoreIfNecessary()7520 private MacAddress retrieveFactoryMacAddressAndStoreIfNecessary() { 7521 boolean saveFactoryMacInConfigStore = 7522 mWifiGlobals.isSaveFactoryMacToConfigStoreEnabled(); 7523 if (saveFactoryMacInConfigStore) { 7524 // Already present, just return. 7525 String factoryMacAddressStr = mSettingsConfigStore.get(isPrimary() 7526 ? WIFI_STA_FACTORY_MAC_ADDRESS : SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS); 7527 if (factoryMacAddressStr != null) return MacAddress.fromString(factoryMacAddressStr); 7528 } 7529 MacAddress factoryMacAddress = mWifiNative.getStaFactoryMacAddress(mInterfaceName); 7530 if (factoryMacAddress == null) { 7531 // the device may be running an older HAL (version < 1.3). 7532 Log.w(TAG, (isPrimary() ? "Primary" : "Secondary") 7533 + " failed to retrieve factory MAC address"); 7534 return null; 7535 } 7536 if (saveFactoryMacInConfigStore) { 7537 mSettingsConfigStore.put(isPrimary() 7538 ? WIFI_STA_FACTORY_MAC_ADDRESS : SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS, 7539 factoryMacAddress.toString()); 7540 Log.i(TAG, (isPrimary() ? "Primary" : "Secondary") 7541 + " factory MAC address stored in config store: " + factoryMacAddress); 7542 } 7543 Log.i(TAG, (isPrimary() ? "Primary" : "Secondary") 7544 + " factory MAC address retrieved: " + factoryMacAddress); 7545 return factoryMacAddress; 7546 } 7547 7548 /** 7549 * Gets the factory MAC address of wlan0 (station interface). 7550 * @return String representation of the factory MAC address. 7551 */ 7552 @Nullable getFactoryMacAddress()7553 public String getFactoryMacAddress() { 7554 MacAddress factoryMacAddress = retrieveFactoryMacAddressAndStoreIfNecessary(); 7555 if (factoryMacAddress != null) return factoryMacAddress.toString(); 7556 7557 // For devices with older HAL's (version < 1.3), no API exists to retrieve factory MAC 7558 // address (and also does not support MAC randomization - needs verson 1.2). So, just 7559 // return the regular MAC address from the interface. 7560 if (!mWifiGlobals.isConnectedMacRandomizationEnabled()) { 7561 Log.w(TAG, "Can't get factory MAC address, return the MAC address"); 7562 return mWifiNative.getMacAddress(mInterfaceName); 7563 } 7564 return null; 7565 } 7566 7567 /** Sends a link probe. */ probeLink(LinkProbeCallback callback, int mcs)7568 public void probeLink(LinkProbeCallback callback, int mcs) { 7569 String bssid = mWifiInfo.getBSSID(); 7570 if (bssid == null) { 7571 Log.w(getTag(), "Attempted to send link probe when not connected!"); 7572 callback.onFailure(LinkProbeCallback.LINK_PROBE_ERROR_NOT_CONNECTED); 7573 return; 7574 } 7575 mWifiNative.probeLink(mInterfaceName, MacAddress.fromString(bssid), callback, mcs); 7576 } 7577 7578 private static class ConnectNetworkMessage { 7579 public final NetworkUpdateResult result; 7580 public final ActionListenerWrapper listener; 7581 public final String packageName; 7582 ConnectNetworkMessage(NetworkUpdateResult result, ActionListenerWrapper listener, String packageName)7583 ConnectNetworkMessage(NetworkUpdateResult result, ActionListenerWrapper listener, 7584 String packageName) { 7585 this.result = result; 7586 this.listener = listener; 7587 this.packageName = packageName; 7588 } 7589 } 7590 7591 /** Trigger network connection and provide status via the provided callback. */ connectNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper, int callingUid, @NonNull String packageName)7592 public void connectNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper, 7593 int callingUid, @NonNull String packageName) { 7594 Message message = 7595 obtainMessage(CMD_CONNECT_NETWORK, 7596 new ConnectNetworkMessage(result, wrapper, packageName)); 7597 message.sendingUid = callingUid; 7598 sendMessage(message); 7599 } 7600 7601 /** Trigger network save and provide status via the provided callback. */ saveNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper, int callingUid, @NonNull String packageName)7602 public void saveNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper, 7603 int callingUid, @NonNull String packageName) { 7604 Message message = 7605 obtainMessage(CMD_SAVE_NETWORK, 7606 new ConnectNetworkMessage(result, wrapper, packageName)); 7607 message.sendingUid = callingUid; 7608 sendMessage(message); 7609 } 7610 7611 /** 7612 * Handle BSS transition request from Connected BSS. 7613 * 7614 * @param frameData Data retrieved from received BTM request frame. 7615 */ handleBssTransitionRequest(BtmFrameData frameData)7616 private void handleBssTransitionRequest(BtmFrameData frameData) { 7617 if (frameData == null) { 7618 return; 7619 } 7620 7621 String bssid = mWifiInfo.getBSSID(); 7622 String ssid = mWifiInfo.getSSID(); 7623 if ((bssid == null) || (ssid == null) || WifiManager.UNKNOWN_SSID.equals(ssid)) { 7624 Log.e(getTag(), "Failed to handle BSS transition: bssid: " + bssid + " ssid: " + ssid); 7625 return; 7626 } 7627 7628 mWifiMetrics.incrementSteeringRequestCount(); 7629 7630 if ((frameData.mBssTmDataFlagsMask 7631 & MboOceConstants.BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED) 7632 != 0) { 7633 mWifiMetrics.incrementMboCellularSwitchRequestCount(); 7634 } 7635 7636 7637 if ((frameData.mBssTmDataFlagsMask 7638 & MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT) != 0) { 7639 long duration = 0; 7640 if ((frameData.mBssTmDataFlagsMask 7641 & MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED) != 0) { 7642 mWifiMetrics.incrementSteeringRequestCountIncludingMboAssocRetryDelay(); 7643 duration = frameData.mBlockListDurationMs; 7644 } 7645 if (duration == 0) { 7646 /* 7647 * When disassoc imminent bit alone is set or MBO assoc retry delay is 7648 * set to zero(reserved as per spec), blocklist the BSS for sometime to 7649 * avoid AP rejecting the re-connect request. 7650 */ 7651 duration = MboOceConstants.DEFAULT_BLOCKLIST_DURATION_MS; 7652 } 7653 // Blocklist the current BSS 7654 WifiConfiguration config = getConnectedWifiConfiguration(); 7655 if (config == null) { 7656 config = getConnectingWifiConfiguration(); 7657 } 7658 mWifiBlocklistMonitor.blockBssidForDurationMs(bssid, config, duration, 7659 WifiBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE, 0); 7660 } 7661 7662 if (frameData.mStatus != MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT) { 7663 // Trigger the network selection and re-connect to new network if available. 7664 mWifiMetrics.incrementForceScanCountDueToSteeringRequest(); 7665 mWifiConnectivityManager.forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE); 7666 } 7667 } 7668 7669 /** 7670 * @return true if this device supports FILS-SHA256 7671 */ isFilsSha256Supported()7672 private boolean isFilsSha256Supported() { 7673 return (getSupportedFeatures() & WIFI_FEATURE_FILS_SHA256) != 0; 7674 } 7675 7676 /** 7677 * @return true if this device supports FILS-SHA384 7678 */ isFilsSha384Supported()7679 private boolean isFilsSha384Supported() { 7680 return (getSupportedFeatures() & WIFI_FEATURE_FILS_SHA384) != 0; 7681 } 7682 7683 /** 7684 * @return true if this device supports Trust On First Use 7685 */ isTrustOnFirstUseSupported()7686 private boolean isTrustOnFirstUseSupported() { 7687 return (getSupportedFeatures() & WIFI_FEATURE_TRUST_ON_FIRST_USE) != 0; 7688 } 7689 7690 /** 7691 * Helper method to set the allowed key management schemes from 7692 * scan result. 7693 * When the AKM is updated, changes should be propagated to the 7694 * actual saved network, and the correct AKM could be retrieved 7695 * on selecting the security params. 7696 */ updateAllowedKeyManagementSchemesFromScanResult( WifiConfiguration config, ScanResult scanResult)7697 private void updateAllowedKeyManagementSchemesFromScanResult( 7698 WifiConfiguration config, ScanResult scanResult) { 7699 config.enableFils( 7700 isFilsSha256Supported() 7701 && ScanResultUtil.isScanResultForFilsSha256Network(scanResult), 7702 isFilsSha384Supported() 7703 && ScanResultUtil.isScanResultForFilsSha384Network(scanResult)); 7704 mWifiConfigManager.updateFilsAkms(config.networkId, 7705 config.isFilsSha256Enabled(), config.isFilsSha384Enabled()); 7706 } 7707 /** 7708 * Update wifi configuration based on the matching scan result. 7709 * 7710 * @param config Wifi configuration object. 7711 * @param scanResult Scan result matching the network. 7712 */ updateWifiConfigFromMatchingScanResult(WifiConfiguration config, ScanResult scanResult)7713 private void updateWifiConfigFromMatchingScanResult(WifiConfiguration config, 7714 ScanResult scanResult) { 7715 updateAllowedKeyManagementSchemesFromScanResult(config, scanResult); 7716 if (config.isFilsSha256Enabled() || config.isFilsSha384Enabled()) { 7717 config.enterpriseConfig.setFieldValue(WifiEnterpriseConfig.EAP_ERP, "1"); 7718 } 7719 } 7720 selectCandidateSecurityParamsIfNecessary( WifiConfiguration config, List<ScanResult> scanResults)7721 private void selectCandidateSecurityParamsIfNecessary( 7722 WifiConfiguration config, 7723 List<ScanResult> scanResults) { 7724 if (null != config.getNetworkSelectionStatus().getCandidateSecurityParams()) return; 7725 if (mVerboseLoggingEnabled) { 7726 Log.d(getTag(), "Select candidate security params for " + config.getProfileKey()); 7727 } 7728 7729 // This comes from wifi picker directly so there is no candidate security params. 7730 // Run network selection against this SSID. 7731 List<ScanDetail> scanDetailsList = scanResults.stream() 7732 .filter(scanResult -> config.SSID.equals( 7733 ScanResultUtil.createQuotedSsid(scanResult.SSID))) 7734 .map(ScanDetail::new) 7735 .collect(Collectors.toList()); 7736 List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector 7737 .getCandidatesForUserSelection(config, scanDetailsList); 7738 mWifiNetworkSelector.selectNetwork(candidates); 7739 7740 SecurityParams params = null; 7741 // Get the fresh copy again to retrieve the candidate security params. 7742 WifiConfiguration freshConfig = mWifiConfigManager.getConfiguredNetwork(config.networkId); 7743 if (null != freshConfig 7744 && null != freshConfig.getNetworkSelectionStatus().getCandidateSecurityParams()) { 7745 params = freshConfig.getNetworkSelectionStatus().getCandidateSecurityParams(); 7746 Log.i(getTag(), "Select best-fit security params: " + params.getSecurityType()); 7747 } else if (null != config.getNetworkSelectionStatus().getLastUsedSecurityParams() 7748 && config.getNetworkSelectionStatus().getLastUsedSecurityParams().isEnabled()) { 7749 params = config.getNetworkSelectionStatus().getLastUsedSecurityParams(); 7750 Log.i(getTag(), "Select the last used security params: " + params.getSecurityType()); 7751 } else { 7752 params = config.getSecurityParamsList().stream() 7753 .filter(WifiConfigurationUtil::isSecurityParamsValid) 7754 .findFirst().orElse(null); 7755 if (null != params) { 7756 Log.i(getTag(), "Select the first available security params: " 7757 + params.getSecurityType()); 7758 } else { 7759 Log.w(getTag(), "No available security params."); 7760 } 7761 } 7762 7763 config.getNetworkSelectionStatus().setCandidateSecurityParams(params); 7764 // populate the target security params to the internal configuration manually, 7765 // and then wifi info could retrieve this information. 7766 mWifiConfigManager.setNetworkCandidateScanResult( 7767 config.networkId, 7768 freshConfig == null ? null : freshConfig.getNetworkSelectionStatus().getCandidate(), 7769 0, params); 7770 } 7771 7772 /** 7773 * Update the wifi configuration before sending connect to 7774 * supplicant/driver. 7775 * 7776 * @param config wifi configuration object. 7777 * @param bssid BSSID to assocaite with. 7778 */ updateWifiConfigOnStartConnection(WifiConfiguration config, String bssid)7779 void updateWifiConfigOnStartConnection(WifiConfiguration config, String bssid) { 7780 setTargetBssid(config, bssid); 7781 7782 // Go through the matching scan results and update wifi config. 7783 ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(config); 7784 List<ScanResult> scanResults = mScanRequestProxy.getScanResults(); 7785 for (ScanResult scanResult : scanResults) { 7786 if (!config.SSID.equals(ScanResultUtil.createQuotedSsid(scanResult.SSID))) { 7787 continue; 7788 } 7789 ScanResultMatchInfo key2 = ScanResultMatchInfo.fromScanResult(scanResult); 7790 if (!key1.equals(key2)) { 7791 continue; 7792 } 7793 updateWifiConfigFromMatchingScanResult(config, scanResult); 7794 } 7795 7796 selectCandidateSecurityParamsIfNecessary(config, scanResults); 7797 7798 if (mWifiGlobals.isConnectedMacRandomizationEnabled()) { 7799 boolean isMacRandomizationForceDisabled = isMacRandomizationForceDisabledOnSsid(config); 7800 if (config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_NONE 7801 || isMacRandomizationForceDisabled) { 7802 setCurrentMacToFactoryMac(config); 7803 } else { 7804 configureRandomizedMacAddress(config); 7805 } 7806 if (isMacRandomizationForceDisabled 7807 && config.macRandomizationSetting != WifiConfiguration.RANDOMIZATION_NONE) { 7808 // update WifiConfigManager to disable MAC randomization so Settings show the right 7809 // MAC randomization information. 7810 config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; 7811 mWifiConfigManager.addOrUpdateNetwork(config, Process.SYSTEM_UID); 7812 } 7813 } 7814 7815 if (config.enterpriseConfig != null 7816 && config.enterpriseConfig.isAuthenticationSimBased() 7817 && mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable( 7818 mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)) 7819 && TextUtils.isEmpty(config.enterpriseConfig.getAnonymousIdentity())) { 7820 String anonAtRealm = mWifiCarrierInfoManager 7821 .getAnonymousIdentityWith3GppRealm(config); 7822 // Use anonymous@<realm> when pseudonym is not available 7823 config.enterpriseConfig.setAnonymousIdentity(anonAtRealm); 7824 } 7825 } 7826 isMacRandomizationForceDisabledOnSsid(WifiConfiguration config)7827 private boolean isMacRandomizationForceDisabledOnSsid(WifiConfiguration config) { 7828 Set<String> unsupportedSsids = new ArraySet<>(mContext.getResources().getStringArray( 7829 R.array.config_wifiForceDisableMacRandomizationSsidList)); 7830 Set<String> unsupportedPrefixes = mWifiGlobals.getMacRandomizationUnsupportedSsidPrefixes(); 7831 boolean isUnsupportedByPrefix = 7832 unsupportedPrefixes.stream().anyMatch(ssid -> config.SSID.startsWith(ssid)); 7833 return isUnsupportedByPrefix || unsupportedSsids.contains(config.SSID); 7834 } 7835 setConfigurationsPriorToIpClientProvisioning(WifiConfiguration config)7836 private void setConfigurationsPriorToIpClientProvisioning(WifiConfiguration config) { 7837 mIpClient.setHttpProxy(config.getHttpProxy()); 7838 if (!TextUtils.isEmpty(mContext.getResources().getString( 7839 R.string.config_wifi_tcp_buffers))) { 7840 mIpClient.setTcpBufferSizes(mContext.getResources().getString( 7841 R.string.config_wifi_tcp_buffers)); 7842 } 7843 } 7844 startIpClient(WifiConfiguration config, boolean isFilsConnection)7845 private boolean startIpClient(WifiConfiguration config, boolean isFilsConnection) { 7846 if (mIpClient == null || config == null) { 7847 return false; 7848 } 7849 7850 final boolean isUsingStaticIp = 7851 (config.getIpAssignment() == IpConfiguration.IpAssignment.STATIC); 7852 final boolean isUsingMacRandomization = 7853 config.macRandomizationSetting 7854 != WifiConfiguration.RANDOMIZATION_NONE 7855 && mWifiGlobals.isConnectedMacRandomizationEnabled(); 7856 final List<byte[]> ouis = getOuiInternal(config); 7857 final List<android.net.DhcpOption> options = 7858 mWifiConfigManager.getCustomDhcpOptions(WifiSsid.fromString(config.SSID), ouis); 7859 if (mVerboseLoggingEnabled) { 7860 final String key = config.getProfileKey(); 7861 log("startIpClient netId=" + Integer.toString(mLastNetworkId) 7862 + " " + key + " " 7863 + " roam=" + mIsAutoRoaming 7864 + " static=" + isUsingStaticIp 7865 + " randomMac=" + isUsingMacRandomization 7866 + " isFilsConnection=" + isFilsConnection); 7867 } 7868 7869 final MacAddress currentBssid = getCurrentBssidInternalMacAddress(); 7870 final String l2Key = mLastL2KeyAndGroupHint != null 7871 ? mLastL2KeyAndGroupHint.first : null; 7872 final String groupHint = mLastL2KeyAndGroupHint != null 7873 ? mLastL2KeyAndGroupHint.second : null; 7874 final Layer2Information layer2Info = new Layer2Information(l2Key, groupHint, 7875 currentBssid); 7876 7877 if (isFilsConnection) { 7878 stopIpClient(); 7879 if (isUsingStaticIp) { 7880 mWifiNative.flushAllHlp(mInterfaceName); 7881 return false; 7882 } 7883 setConfigurationsPriorToIpClientProvisioning(config); 7884 final ProvisioningConfiguration.Builder prov = 7885 new ProvisioningConfiguration.Builder() 7886 .withPreDhcpAction() 7887 .withPreconnection() 7888 .withDisplayName(config.SSID) 7889 .withLayer2Information(layer2Info); 7890 if (mContext.getResources().getBoolean(R.bool.config_wifiEnableApfOnNonPrimarySta) 7891 || isPrimary()) { 7892 // unclear if the native layer will return the correct non-capabilities if APF is 7893 // not supported on secondary interfaces. 7894 prov.withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName)); 7895 } 7896 if (isUsingMacRandomization) { 7897 // Use EUI64 address generation for link-local IPv6 addresses. 7898 prov.withRandomMacAddress(); 7899 } 7900 prov.withDhcpOptions(convertToInternalDhcpOptions(options)); 7901 mIpClient.startProvisioning(prov.build()); 7902 } else { 7903 sendNetworkChangeBroadcast(DetailedState.OBTAINING_IPADDR); 7904 // We must clear the config BSSID, as the wifi chipset may decide to roam 7905 // from this point on and having the BSSID specified in the network block would 7906 // cause the roam to fail and the device to disconnect. 7907 clearTargetBssid("ObtainingIpAddress"); 7908 7909 // Stop IpClient in case we're switching from DHCP to static 7910 // configuration or vice versa. 7911 // 7912 // When we transition from static configuration to DHCP in 7913 // particular, we must tell ConnectivityService that we're 7914 // disconnected, because DHCP might take a long time during which 7915 // connectivity APIs such as getActiveNetworkInfo should not return 7916 // CONNECTED. 7917 stopDhcpSetup(); 7918 setConfigurationsPriorToIpClientProvisioning(config); 7919 ScanResult scanResult = getScanResultInternal(config); 7920 7921 final ProvisioningConfiguration.Builder prov; 7922 ProvisioningConfiguration.ScanResultInfo scanResultInfo = null; 7923 if (scanResult != null) { 7924 final List<ScanResultInfo.InformationElement> ies = 7925 new ArrayList<ScanResultInfo.InformationElement>(); 7926 for (ScanResult.InformationElement ie : scanResult.getInformationElements()) { 7927 ScanResultInfo.InformationElement scanResultInfoIe = 7928 new ScanResultInfo.InformationElement(ie.getId(), ie.getBytes()); 7929 ies.add(scanResultInfoIe); 7930 } 7931 scanResultInfo = new ProvisioningConfiguration.ScanResultInfo(scanResult.SSID, 7932 scanResult.BSSID, ies); 7933 } 7934 final Network network = (mNetworkAgent != null) ? mNetworkAgent.getNetwork() : null; 7935 if (!isUsingStaticIp) { 7936 prov = new ProvisioningConfiguration.Builder() 7937 .withPreDhcpAction() 7938 .withNetwork(network) 7939 .withDisplayName(config.SSID) 7940 .withScanResultInfo(scanResultInfo) 7941 .withLayer2Information(layer2Info); 7942 } else { 7943 StaticIpConfiguration staticIpConfig = config.getStaticIpConfiguration(); 7944 prov = new ProvisioningConfiguration.Builder() 7945 .withStaticConfiguration(staticIpConfig) 7946 .withNetwork(network) 7947 .withDisplayName(config.SSID) 7948 .withLayer2Information(layer2Info); 7949 } 7950 if (mContext.getResources().getBoolean(R.bool.config_wifiEnableApfOnNonPrimarySta) 7951 || isPrimary()) { 7952 // unclear if the native layer will return the correct non-capabilities if APF is 7953 // not supported on secondary interfaces. 7954 prov.withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName)); 7955 } 7956 if (isUsingMacRandomization) { 7957 // Use EUI64 address generation for link-local IPv6 addresses. 7958 prov.withRandomMacAddress(); 7959 } 7960 prov.withDhcpOptions(convertToInternalDhcpOptions(options)); 7961 mIpClient.startProvisioning(prov.build()); 7962 } 7963 7964 return true; 7965 } 7966 getOuiInternal(WifiConfiguration config)7967 private List<byte[]> getOuiInternal(WifiConfiguration config) { 7968 List<byte[]> ouis = new ArrayList<>(); 7969 ScanResult scanResult = getScanResultInternal(config); 7970 if (scanResult == null) { 7971 return ouis; 7972 } 7973 List<InformationElementUtil.Vsa> vsas = InformationElementUtil.getVendorSpecificIE( 7974 scanResult.informationElements); 7975 for (InformationElementUtil.Vsa vsa : vsas) { 7976 byte[] oui = vsa.oui; 7977 if (oui != null) { 7978 ouis.add(oui); 7979 } 7980 } 7981 return ouis; 7982 } 7983 getScanResultInternal(WifiConfiguration config)7984 private ScanResult getScanResultInternal(WifiConfiguration config) { 7985 ScanDetailCache scanDetailCache = 7986 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); 7987 ScanResult scanResult = null; 7988 if (mLastBssid != null) { 7989 if (scanDetailCache != null) { 7990 scanResult = scanDetailCache.getScanResult(mLastBssid); 7991 } 7992 // The cached scan result of connected network would be null at the first 7993 // connection, try to check full scan result list again to look up matched 7994 // scan result associated to the current BSSID. 7995 if (scanResult == null) { 7996 scanResult = mScanRequestProxy.getScanResult(mLastBssid); 7997 } 7998 } 7999 return scanResult; 8000 } 8001 8002 @Override setWifiConnectedNetworkScorer(IBinder binder, IWifiConnectedNetworkScorer scorer)8003 public boolean setWifiConnectedNetworkScorer(IBinder binder, 8004 IWifiConnectedNetworkScorer scorer) { 8005 return mWifiScoreReport.setWifiConnectedNetworkScorer(binder, scorer); 8006 } 8007 8008 @Override clearWifiConnectedNetworkScorer()8009 public void clearWifiConnectedNetworkScorer() { 8010 mWifiScoreReport.clearWifiConnectedNetworkScorer(); 8011 } 8012 8013 @Override onNetworkSwitchAccepted(int targetNetworkId, String targetBssid)8014 public void onNetworkSwitchAccepted(int targetNetworkId, String targetBssid) { 8015 mWifiScoreReport.onNetworkSwitchAccepted(targetNetworkId, targetBssid); 8016 } 8017 8018 @Override onNetworkSwitchRejected(int targetNetworkId, String targetBssid)8019 public void onNetworkSwitchRejected(int targetNetworkId, String targetBssid) { 8020 mWifiScoreReport.onNetworkSwitchRejected(targetNetworkId, targetBssid); 8021 } 8022 8023 @Override sendMessageToClientModeImpl(Message msg)8024 public void sendMessageToClientModeImpl(Message msg) { 8025 sendMessage(msg); 8026 } 8027 8028 @Override getId()8029 public long getId() { 8030 return mId; 8031 } 8032 8033 @Override dumpWifiScoreReport(FileDescriptor fd, PrintWriter pw, String[] args)8034 public void dumpWifiScoreReport(FileDescriptor fd, PrintWriter pw, String[] args) { 8035 mWifiScoreReport.dump(fd, pw, args); 8036 } 8037 8038 /** 8039 * Notifies changes in data connectivity of the default data SIM. 8040 */ 8041 @Override onCellularConnectivityChanged(@ifiDataStall.CellularDataStatusCode int status)8042 public void onCellularConnectivityChanged(@WifiDataStall.CellularDataStatusCode int status) { 8043 mWifiConfigManager.onCellularConnectivityChanged(status); 8044 // do a scan if no cell data and currently not connect to wifi 8045 if (status == WifiDataStall.CELLULAR_DATA_NOT_AVAILABLE 8046 && getConnectedWifiConfigurationInternal() == null) { 8047 if (mContext.getResources().getBoolean( 8048 R.bool.config_wifiScanOnCellularDataLossEnabled)) { 8049 mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); 8050 } 8051 } 8052 } 8053 8054 @Override setMboCellularDataStatus(boolean available)8055 public void setMboCellularDataStatus(boolean available) { 8056 mWifiNative.setMboCellularDataStatus(mInterfaceName, available); 8057 } 8058 8059 @Override getRoamingCapabilities()8060 public WifiNative.RoamingCapabilities getRoamingCapabilities() { 8061 return mWifiNative.getRoamingCapabilities(mInterfaceName); 8062 } 8063 8064 @Override configureRoaming(WifiNative.RoamingConfig config)8065 public boolean configureRoaming(WifiNative.RoamingConfig config) { 8066 return mWifiNative.configureRoaming(mInterfaceName, config); 8067 } 8068 8069 @Override enableRoaming(boolean enabled)8070 public boolean enableRoaming(boolean enabled) { 8071 int status = mWifiNative.enableFirmwareRoaming( 8072 mInterfaceName, enabled 8073 ? WifiNative.ENABLE_FIRMWARE_ROAMING 8074 : WifiNative.DISABLE_FIRMWARE_ROAMING); 8075 return status == WifiNative.SET_FIRMWARE_ROAMING_SUCCESS; 8076 } 8077 8078 @Override setCountryCode(String countryCode)8079 public boolean setCountryCode(String countryCode) { 8080 return mWifiNative.setStaCountryCode(mInterfaceName, countryCode); 8081 } 8082 8083 @Override getTxPktFates()8084 public List<TxFateReport> getTxPktFates() { 8085 return mWifiNative.getTxPktFates(mInterfaceName); 8086 } 8087 8088 @Override getRxPktFates()8089 public List<RxFateReport> getRxPktFates() { 8090 return mWifiNative.getRxPktFates(mInterfaceName); 8091 } 8092 8093 @Override setShouldReduceNetworkScore(boolean shouldReduceNetworkScore)8094 public void setShouldReduceNetworkScore(boolean shouldReduceNetworkScore) { 8095 mWifiScoreReport.setShouldReduceNetworkScore(shouldReduceNetworkScore); 8096 } 8097 updateApfCapabilitiesOnRoleChangedToPrimary()8098 private void updateApfCapabilitiesOnRoleChangedToPrimary() { 8099 // If packet filter is supported on both connections, ignore since we would have already 8100 // specified the APF during the ipClient provisioning. 8101 if (mContext.getResources().getBoolean(R.bool.config_wifiEnableApfOnNonPrimarySta)) { 8102 return; 8103 } 8104 if (mIpClient != null) { 8105 Log.i(TAG, "Role changed to primary - Update APF capabilities in IpClient"); 8106 mIpClient.updateApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName)); 8107 } 8108 } 8109 8110 /** 8111 * Invoked by parent ConcreteClientModeManager whenever a role change occurs. 8112 */ onRoleChanged()8113 public void onRoleChanged() { 8114 ClientRole role = mClientModeManager.getRole(); 8115 if (role == ROLE_CLIENT_PRIMARY) { 8116 updateApfCapabilitiesOnRoleChangedToPrimary(); 8117 if (mScreenOn) { 8118 // Start RSSI polling for the new primary network to enable scoring. 8119 enableRssiPolling(true); 8120 } 8121 } else { 8122 if (mScreenOn && !isSecondaryInternet()) { 8123 // Stop RSSI polling (if enabled) for the secondary network. 8124 enableRssiPolling(false); 8125 } 8126 } 8127 WifiConfiguration connectedNetwork = getConnectedWifiConfiguration(); 8128 if (connectedNetwork != null) { 8129 updateWifiInfoWhenConnected(connectedNetwork); 8130 // Update capabilities after a role change. 8131 updateCapabilities(connectedNetwork); 8132 } 8133 mWifiScoreReport.onRoleChanged(role); 8134 } 8135 addPasspointInfoToLinkProperties(LinkProperties linkProperties)8136 private void addPasspointInfoToLinkProperties(LinkProperties linkProperties) { 8137 // CaptivePortalData.Builder.setVenueFriendlyName API not available on R 8138 if (!SdkLevel.isAtLeastS()) { 8139 return; 8140 } 8141 WifiConfiguration currentNetwork = getConnectedWifiConfigurationInternal(); 8142 if (currentNetwork == null || !currentNetwork.isPasspoint()) { 8143 return; 8144 } 8145 ScanResult scanResult = mScanRequestProxy.getScanResult(mLastBssid); 8146 8147 if (scanResult == null) { 8148 return; 8149 } 8150 URL venueUrl = mPasspointManager.getVenueUrl(scanResult); 8151 8152 // Update the friendly name to populate the notification 8153 CaptivePortalData.Builder captivePortalDataBuilder = new CaptivePortalData.Builder() 8154 .setVenueFriendlyName(currentNetwork.providerFriendlyName); 8155 8156 // Update the Venue URL if available 8157 if (venueUrl != null) { 8158 captivePortalDataBuilder.setVenueInfoUrl(Uri.parse(venueUrl.toString()), 8159 CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT); 8160 } 8161 8162 // Update the T&C URL if available. The network is captive if T&C URL is available 8163 if (mTermsAndConditionsUrl != null) { 8164 captivePortalDataBuilder.setUserPortalUrl( 8165 Uri.parse(mTermsAndConditionsUrl.toString()), 8166 CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT).setCaptive(true); 8167 } 8168 8169 linkProperties.setCaptivePortalData(captivePortalDataBuilder.build()); 8170 } 8171 8172 private boolean mHasQuit = false; 8173 8174 @Override onQuitting()8175 protected void onQuitting() { 8176 mHasQuit = true; 8177 mClientModeManager.onClientModeImplQuit(); 8178 } 8179 8180 /** Returns true if the ClientModeImpl has fully stopped, false otherwise. */ hasQuit()8181 public boolean hasQuit() { 8182 return mHasQuit; 8183 } 8184 8185 /** 8186 * WifiVcnNetworkPolicyChangeListener tracks VCN-defined Network policies for a 8187 * WifiNetworkAgent. These policies are used to restart Networks or update their 8188 * NetworkCapabilities. 8189 */ 8190 @SuppressLint("NewApi") 8191 private class WifiVcnNetworkPolicyChangeListener 8192 implements VcnManager.VcnNetworkPolicyChangeListener { 8193 @Override onPolicyChanged()8194 public void onPolicyChanged() { 8195 if (mNetworkAgent == null) { 8196 return; 8197 } 8198 // Update the NetworkAgent's NetworkCapabilities which will merge the current 8199 // capabilities with VcnManagementService's underlying Network policy. 8200 Log.i(getTag(), "VCN policy changed, updating NetworkCapabilities."); 8201 updateCapabilities(); 8202 } 8203 } 8204 8205 /** 8206 * Updates the default gateway mac address of the connected network config and updates the 8207 * linked networks resulting from the new default gateway. 8208 */ retrieveConnectedNetworkDefaultGateway()8209 private boolean retrieveConnectedNetworkDefaultGateway() { 8210 WifiConfiguration currentConfig = getConnectedWifiConfiguration(); 8211 if (currentConfig == null) { 8212 logi("can't fetch config of current network id " + mLastNetworkId); 8213 return false; 8214 } 8215 8216 // Find IPv4 default gateway. 8217 if (mLinkProperties == null) { 8218 logi("cannot retrieve default gateway from null link properties"); 8219 return false; 8220 } 8221 String gatewayIPv4 = null; 8222 for (RouteInfo routeInfo : mLinkProperties.getRoutes()) { 8223 if (routeInfo.isDefaultRoute() 8224 && routeInfo.getDestination().getAddress() instanceof Inet4Address 8225 && routeInfo.hasGateway()) { 8226 gatewayIPv4 = routeInfo.getGateway().getHostAddress(); 8227 break; 8228 } 8229 } 8230 8231 if (TextUtils.isEmpty(gatewayIPv4)) { 8232 logi("default gateway ipv4 is null"); 8233 return false; 8234 } 8235 8236 String gatewayMac = macAddressFromRoute(gatewayIPv4); 8237 if (TextUtils.isEmpty(gatewayMac)) { 8238 logi("default gateway mac fetch failed for ipv4 addr = " + gatewayIPv4); 8239 return false; 8240 } 8241 8242 if (mVerboseLoggingEnabled) { 8243 logi("Default Gateway MAC address of " + mLastBssid + " from routes is : " 8244 + gatewayMac); 8245 } 8246 if (!mWifiConfigManager.setNetworkDefaultGwMacAddress(mLastNetworkId, gatewayMac)) { 8247 logi("default gateway mac set failed for " + currentConfig.getKey() + " network"); 8248 return false; 8249 } 8250 8251 return mWifiConfigManager.saveToStore(true); 8252 } 8253 8254 /** 8255 * Links the supplied config to all matching saved configs and updates the WifiBlocklistMonitor 8256 * SSID allowlist with the linked networks. 8257 */ updateLinkedNetworks(@onNull WifiConfiguration config)8258 private void updateLinkedNetworks(@NonNull WifiConfiguration config) { 8259 if (!isPrimary()) { 8260 return; 8261 } 8262 if (!mContext.getResources().getBoolean(R.bool.config_wifiEnableLinkedNetworkRoaming)) { 8263 return; 8264 } 8265 8266 SecurityParams params = mWifiNative.getCurrentNetworkSecurityParams(mInterfaceName); 8267 if (params == null) return; 8268 8269 WifiConfiguration tmpConfigForCurrentSecurityParams = new WifiConfiguration(); 8270 tmpConfigForCurrentSecurityParams.setSecurityParams(params); 8271 if (!WifiConfigurationUtil.isConfigLinkable(tmpConfigForCurrentSecurityParams)) return; 8272 8273 // Don't set SSID allowlist if we're connected to a network with Fast BSS Transition. 8274 ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork( 8275 config.networkId); 8276 if (scanDetailCache == null) { 8277 Log.i(TAG, "Do not update linked networks - no ScanDetailCache found for netId: " 8278 + config.networkId); 8279 return; 8280 } 8281 ScanResult matchingScanResult = scanDetailCache.getScanResult(mLastBssid); 8282 if (matchingScanResult == null) { 8283 Log.i(TAG, "Do not update linked networks - no matching ScanResult found for BSSID: " 8284 + mLastBssid); 8285 return; 8286 } 8287 String caps = matchingScanResult.capabilities; 8288 if (caps.contains("FT/PSK") || caps.contains("FT/SAE")) { 8289 Log.i(TAG, "Do not update linked networks - current connection is FT-PSK/FT-SAE"); 8290 return; 8291 } 8292 8293 mWifiConfigManager.updateLinkedNetworks(config.networkId); 8294 Map<String, WifiConfiguration> linkedNetworks = mWifiConfigManager 8295 .getLinkedNetworksWithoutMasking(config.networkId); 8296 8297 if (!mWifiNative.updateLinkedNetworks(mInterfaceName, config.networkId, linkedNetworks)) { 8298 return; 8299 } 8300 // Update internal configs once the connection requests are accepted. 8301 linkedNetworks.values().forEach(linkedConfig -> 8302 mWifiConfigManager.setNetworkLastUsedSecurityParams( 8303 linkedConfig.networkId, params)); 8304 8305 List<String> allowlistSsids = new ArrayList<>(linkedNetworks.values().stream() 8306 .filter(linkedConfig -> linkedConfig.allowAutojoin) 8307 .map(linkedConfig -> linkedConfig.SSID) 8308 .collect(Collectors.toList())); 8309 if (allowlistSsids.size() > 0) { 8310 allowlistSsids.add(config.SSID); 8311 } 8312 mWifiBlocklistMonitor.setAllowlistSsids(config.SSID, allowlistSsids); 8313 mWifiBlocklistMonitor.updateFirmwareRoamingConfiguration(new ArraySet<>(allowlistSsids)); 8314 } 8315 checkAndHandleLinkedNetworkRoaming(String associatedBssid)8316 private boolean checkAndHandleLinkedNetworkRoaming(String associatedBssid) { 8317 if (!mContext.getResources().getBoolean(R.bool.config_wifiEnableLinkedNetworkRoaming)) { 8318 return false; 8319 } 8320 8321 ScanResult scanResult = mScanRequestProxy.getScanResult(associatedBssid); 8322 if (scanResult == null) { 8323 return false; 8324 } 8325 8326 WifiConfiguration config = mWifiConfigManager 8327 .getSavedNetworkForScanResult(scanResult); 8328 if (config == null || !config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) 8329 || mLastNetworkId == config.networkId) { 8330 return false; 8331 } 8332 8333 mIsLinkedNetworkRoaming = true; 8334 setTargetBssid(config, associatedBssid); 8335 mTargetNetworkId = config.networkId; 8336 mTargetWifiConfiguration = config; 8337 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 8338 sendNetworkChangeBroadcast(DetailedState.CONNECTING); 8339 mWifiInfo.setFrequency(scanResult.frequency); 8340 mWifiInfo.setBSSID(associatedBssid); 8341 updateCurrentConnectionInfo(); 8342 return true; 8343 } 8344 8345 @RequiresApi(Build.VERSION_CODES.S) 8346 private @WifiConfiguration.RecentFailureReason int mboAssocDisallowedReasonCodeToWifiConfigurationRecentFailureReason( @boOceConstants.MboAssocDisallowedReasonCode int reasonCode)8347 mboAssocDisallowedReasonCodeToWifiConfigurationRecentFailureReason( 8348 @MboOceConstants.MboAssocDisallowedReasonCode int reasonCode) { 8349 switch (reasonCode) { 8350 case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_MAX_NUM_STA_ASSOCIATED: 8351 return WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_MAX_NUM_STA_ASSOCIATED; 8352 case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_AIR_INTERFACE_OVERLOADED: 8353 return WifiConfiguration 8354 .RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AIR_INTERFACE_OVERLOADED; 8355 case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_AUTH_SERVER_OVERLOADED: 8356 return WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AUTH_SERVER_OVERLOADED; 8357 case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_INSUFFICIENT_RSSI: 8358 return WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_INSUFFICIENT_RSSI; 8359 case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_UNSPECIFIED: 8360 case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_RESERVED_0: 8361 case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_RESERVED: 8362 default: 8363 return WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_UNSPECIFIED; 8364 } 8365 } 8366 8367 /** 8368 * To set association rejection status in wifi config. 8369 * @param netId The network ID. 8370 * @param assocRejectEventInfo Association rejection information. 8371 */ setAssociationRejectionStatusInConfig(int netId, AssocRejectEventInfo assocRejectEventInfo)8372 private void setAssociationRejectionStatusInConfig(int netId, 8373 AssocRejectEventInfo assocRejectEventInfo) { 8374 int statusCode = assocRejectEventInfo.statusCode; 8375 @WifiConfiguration.RecentFailureReason int reason; 8376 8377 switch (statusCode) { 8378 case StaIfaceStatusCode.AP_UNABLE_TO_HANDLE_NEW_STA: 8379 reason = WifiConfiguration.RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA; 8380 break; 8381 case StaIfaceStatusCode.ASSOC_REJECTED_TEMPORARILY: 8382 reason = WifiConfiguration.RECENT_FAILURE_REFUSED_TEMPORARILY; 8383 break; 8384 case StaIfaceStatusCode.DENIED_POOR_CHANNEL_CONDITIONS: 8385 reason = WifiConfiguration.RECENT_FAILURE_POOR_CHANNEL_CONDITIONS; 8386 break; 8387 default: 8388 // do nothing 8389 return; 8390 } 8391 8392 if (SdkLevel.isAtLeastS()) { 8393 if (assocRejectEventInfo.mboAssocDisallowedInfo != null) { 8394 reason = mboAssocDisallowedReasonCodeToWifiConfigurationRecentFailureReason( 8395 assocRejectEventInfo.mboAssocDisallowedInfo.mReasonCode); 8396 } else if (assocRejectEventInfo.oceRssiBasedAssocRejectInfo != null) { 8397 reason = WifiConfiguration.RECENT_FAILURE_OCE_RSSI_BASED_ASSOCIATION_REJECTION; 8398 } 8399 } 8400 8401 mWifiConfigManager.setRecentFailureAssociationStatus(netId, reason); 8402 8403 } 8404 checkIfNeedDisconnectSecondaryWifi()8405 private void checkIfNeedDisconnectSecondaryWifi() { 8406 if (!isPrimary()) { 8407 return; 8408 } 8409 if (isConnected()) { 8410 ConcreteClientModeManager ccmm = 8411 mWifiInjector.getActiveModeWarden().getClientModeManagerInRole( 8412 ROLE_CLIENT_SECONDARY_LONG_LIVED); 8413 if (ccmm != null && ccmm.isConnected() && ccmm.isSecondaryInternet()) { 8414 WifiInfo secondaryWifiInfo = ccmm.getConnectionInfo(); 8415 if (secondaryWifiInfo == null) return; 8416 if ((secondaryWifiInfo.is5GHz() && mWifiInfo.is5GHz()) 8417 || (secondaryWifiInfo.is6GHz() && mWifiInfo.is6GHz()) 8418 || (secondaryWifiInfo.is24GHz() && mWifiInfo.is24GHz())) { 8419 if (mVerboseLoggingEnabled) { 8420 Log.d(TAG, "The master wifi and secondary wifi are at the same band," 8421 + " disconnect the secondary wifi"); 8422 } 8423 ccmm.disconnect(); 8424 } 8425 } 8426 } 8427 } 8428 setSelectedRcoiForPasspoint(WifiConfiguration config)8429 private void setSelectedRcoiForPasspoint(WifiConfiguration config) { 8430 // Only relevant for Passpoint providers with roaming consortium subscriptions 8431 if (config.isPasspoint() && config.roamingConsortiumIds != null 8432 && config.roamingConsortiumIds.length > 0) { 8433 long selectedRcoi = mPasspointManager.getSelectedRcoiForNetwork( 8434 config.getPasspointUniqueId(), config.SSID); 8435 if (selectedRcoi != 0) { 8436 config.enterpriseConfig.setSelectedRcoi(selectedRcoi); 8437 } 8438 } 8439 } 8440 updateCurrentConnectionInfo()8441 private void updateCurrentConnectionInfo() { 8442 if (isPrimary()) { 8443 mWifiInjector.getActiveModeWarden().updateCurrentConnectionInfo(); 8444 } 8445 } 8446 } 8447