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