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