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