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