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