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