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