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