WifiStateMachine.java revision 0ea5062316013cd4173faf16c2a0f3ecd1b9ed43
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 17package com.android.server.wifi; 18 19import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; 20import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; 21import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; 22import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING; 23import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; 24import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; 25import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING; 26import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; 27import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING; 28import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN; 29import static android.system.OsConstants.ARPHRD_ETHER; 30 31import android.Manifest; 32import android.app.ActivityManager; 33import android.app.AlarmManager; 34import android.app.PendingIntent; 35import android.bluetooth.BluetoothAdapter; 36import android.content.BroadcastReceiver; 37import android.content.Context; 38import android.content.Intent; 39import android.content.IntentFilter; 40import android.content.pm.ApplicationInfo; 41import android.content.pm.IPackageManager; 42import android.content.pm.PackageManager; 43import android.content.pm.UserInfo; 44import android.database.ContentObserver; 45import android.net.ConnectivityManager; 46import android.net.DhcpResults; 47import android.net.LinkProperties; 48import android.net.Network; 49import android.net.NetworkAgent; 50import android.net.NetworkCapabilities; 51import android.net.NetworkFactory; 52import android.net.NetworkInfo; 53import android.net.NetworkInfo.DetailedState; 54import android.net.NetworkMisc; 55import android.net.NetworkRequest; 56import android.net.NetworkUtils; 57import android.net.RouteInfo; 58import android.net.StaticIpConfiguration; 59import android.net.dhcp.DhcpClient; 60import android.net.ip.IpManager; 61import android.net.wifi.PasspointManagementObjectDefinition; 62import android.net.wifi.RssiPacketCountInfo; 63import android.net.wifi.ScanResult; 64import android.net.wifi.ScanSettings; 65import android.net.wifi.SupplicantState; 66import android.net.wifi.WifiChannel; 67import android.net.wifi.WifiConfiguration; 68import android.net.wifi.WifiConnectionStatistics; 69import android.net.wifi.WifiEnterpriseConfig; 70import android.net.wifi.WifiInfo; 71import android.net.wifi.WifiLinkLayerStats; 72import android.net.wifi.WifiManager; 73import android.net.wifi.WifiScanner; 74import android.net.wifi.WifiSsid; 75import android.net.wifi.WpsInfo; 76import android.net.wifi.WpsResult; 77import android.net.wifi.WpsResult.Status; 78import android.net.wifi.p2p.IWifiP2pManager; 79import android.os.BatteryStats; 80import android.os.Binder; 81import android.os.Bundle; 82import android.os.IBinder; 83import android.os.INetworkManagementService; 84import android.os.Looper; 85import android.os.Message; 86import android.os.Messenger; 87import android.os.PowerManager; 88import android.os.Process; 89import android.os.RemoteException; 90import android.os.SystemClock; 91import android.os.SystemProperties; 92import android.os.UserHandle; 93import android.os.UserManager; 94import android.os.WorkSource; 95import android.provider.Settings; 96import android.security.KeyStore; 97import android.telephony.TelephonyManager; 98import android.text.TextUtils; 99import android.util.Log; 100import android.util.SparseArray; 101 102import com.android.internal.R; 103import com.android.internal.app.IBatteryStats; 104import com.android.internal.util.AsyncChannel; 105import com.android.internal.util.MessageUtils; 106import com.android.internal.util.Protocol; 107import com.android.internal.util.State; 108import com.android.internal.util.StateMachine; 109import com.android.server.connectivity.KeepalivePacketData; 110import com.android.server.wifi.hotspot2.IconEvent; 111import com.android.server.wifi.hotspot2.NetworkDetail; 112import com.android.server.wifi.hotspot2.Utils; 113import com.android.server.wifi.p2p.WifiP2pServiceImpl; 114 115import java.io.BufferedReader; 116import java.io.FileDescriptor; 117import java.io.FileNotFoundException; 118import java.io.FileReader; 119import java.io.IOException; 120import java.io.PrintWriter; 121import java.net.Inet4Address; 122import java.net.InetAddress; 123import java.util.ArrayList; 124import java.util.Arrays; 125import java.util.Calendar; 126import java.util.HashSet; 127import java.util.LinkedList; 128import java.util.List; 129import java.util.Queue; 130import java.util.Random; 131import java.util.Set; 132import java.util.concurrent.atomic.AtomicBoolean; 133import java.util.concurrent.atomic.AtomicInteger; 134 135/** 136 * TODO: 137 * Deprecate WIFI_STATE_UNKNOWN 138 */ 139 140/** 141 * Track the state of Wifi connectivity. All event handling is done here, 142 * and all changes in connectivity state are initiated here. 143 * 144 * Wi-Fi now supports three modes of operation: Client, SoftAp and p2p 145 * In the current implementation, we support concurrent wifi p2p and wifi operation. 146 * The WifiStateMachine handles SoftAp and Client operations while WifiP2pService 147 * handles p2p operation. 148 * 149 * @hide 150 */ 151public class WifiStateMachine extends StateMachine implements WifiNative.PnoEventHandler, 152 WifiNative.WifiRssiEventHandler { 153 154 private static final String NETWORKTYPE = "WIFI"; 155 private static final String NETWORKTYPE_UNTRUSTED = "WIFI_UT"; 156 private static boolean DBG = false; 157 private static boolean USE_PAUSE_SCANS = false; 158 private static final String TAG = "WifiStateMachine"; 159 160 private static final int ONE_HOUR_MILLI = 1000 * 60 * 60; 161 162 private static final String GOOGLE_OUI = "DA-A1-19"; 163 164 private int mVerboseLoggingLevel = 0; 165 /* debug flag, indicating if handling of ASSOCIATION_REJECT ended up blacklisting 166 * the corresponding BSSID. 167 */ 168 private boolean didBlackListBSSID = false; 169 170 /** 171 * Log with error attribute 172 * 173 * @param s is string log 174 */ 175 protected void loge(String s) { 176 Log.e(getName(), s); 177 } 178 protected void logd(String s) { 179 Log.d(getName(), s); 180 } 181 protected void log(String s) {; 182 Log.d(getName(), s); 183 } 184 185 private WifiMetrics mWifiMetrics; 186 private WifiMonitor mWifiMonitor; 187 private WifiNative mWifiNative; 188 private WifiConfigManager mWifiConfigManager; 189 private WifiQualifiedNetworkSelector mWifiQualifiedNetworkSelector; 190 private INetworkManagementService mNwService; 191 private ConnectivityManager mCm; 192 private BaseWifiLogger mWifiLogger; 193 private WifiApConfigStore mWifiApConfigStore; 194 private final boolean mP2pSupported; 195 private final AtomicBoolean mP2pConnected = new AtomicBoolean(false); 196 private boolean mTemporarilyDisconnectWifi = false; 197 private final String mPrimaryDeviceType; 198 private final UserManager mUserManager; 199 private final Clock mClock = new Clock(); 200 private final WifiCountryCode mCountryCode; 201 202 /* Scan results handling */ 203 private List<ScanDetail> mScanResults = new ArrayList<>(); 204 private final Object mScanResultsLock = new Object(); 205 206 // For debug, number of known scan results that were found as part of last scan result event, 207 // as well the number of scans results returned by the supplicant with that message 208 private int mNumScanResultsKnown; 209 private int mNumScanResultsReturned; 210 211 private boolean mScreenOn = false; 212 213 /* Chipset supports background scan */ 214 private final boolean mBackgroundScanSupported; 215 216 private final String mInterfaceName; 217 /* Tethering interface could be separate from wlan interface */ 218 private String mTetherInterfaceName; 219 220 private int mLastSignalLevel = -1; 221 private String mLastBssid; 222 private int mLastNetworkId; // The network Id we successfully joined 223 private ScanDetail mActiveScanDetail; // ScanDetail associated with active network 224 private boolean linkDebouncing = false; 225 226 private boolean mHalBasedPnoDriverSupported = false; 227 228 private boolean mHalBasedPnoEnableInDevSettings = false; 229 230 private int mHalFeatureSet = 0; 231 private static int mPnoResultFound = 0; 232 233 private int mCurrentUserId = UserHandle.USER_SYSTEM; 234 235 private boolean mAllowUntrustedConnections = false; 236 237 @Override 238 public void onPnoNetworkFound(ScanResult results[]) { 239 if (DBG) { 240 Log.e(TAG, "onPnoNetworkFound event received num = " + results.length); 241 for (int i = 0; i < results.length; i++) { 242 Log.e(TAG, results[i].toString()); 243 } 244 } 245 sendMessage(CMD_PNO_NETWORK_FOUND, results.length, 0, results); 246 } 247 248 /** 249 * Ignore Pno scan failed events. This is needed for WifiScanner 250 * TODO(rpius): Remove this once PNO scan logic is removed from WifiStateMachine. 251 */ 252 @Override 253 public void onPnoScanFailed() { 254 return; 255 } 256 257 public void processPnoNetworkFound(ScanResult results[]) { 258 ScanSettings settings = new ScanSettings(); 259 settings.channelSet = new ArrayList<WifiChannel>(); 260 StringBuilder sb = new StringBuilder(); 261 sb.append(""); 262 for (int i=0; i<results.length; i++) { 263 WifiChannel channel = new WifiChannel(); 264 channel.freqMHz = results[i].frequency; 265 settings.channelSet.add(channel); 266 sb.append(results[i].SSID).append(" "); 267 } 268 269 stopPnoOffload(); 270 271 Log.e(TAG, "processPnoNetworkFound starting scan cnt=" + mPnoResultFound); 272 startScan(PNO_NETWORK_FOUND_SOURCE, mPnoResultFound, settings, null); 273 mPnoResultFound ++; 274 //sendMessage(CMD_SCAN_RESULTS_AVAILABLE); 275 int delay = 30 * 1000; 276 // reconfigure Pno after 1 minutes if we're still in disconnected state 277 sendMessageDelayed(CMD_RESTART_AUTOJOIN_OFFLOAD, delay, 278 mRestartAutoJoinOffloadCounter, " processPnoNetworkFound " + sb.toString(), 279 (long)delay); 280 mRestartAutoJoinOffloadCounter++; 281 } 282 283 @Override 284 public void onRssiThresholdBreached(byte curRssi) { 285 if (DBG) { 286 Log.e(TAG, "onRssiThresholdBreach event. Cur Rssi = " + curRssi); 287 } 288 sendMessage(CMD_RSSI_THRESHOLD_BREACH, curRssi); 289 } 290 291 public void processRssiThreshold(byte curRssi, int reason) { 292 if (curRssi == Byte.MAX_VALUE || curRssi == Byte.MIN_VALUE) { 293 Log.wtf(TAG, "processRssiThreshold: Invalid rssi " + curRssi); 294 return; 295 } 296 for (int i = 0; i < mRssiRanges.length; i++) { 297 if (curRssi < mRssiRanges[i]) { 298 // Assume sorted values(ascending order) for rssi, 299 // bounded by high(127) and low(-128) at extremeties 300 byte maxRssi = mRssiRanges[i]; 301 byte minRssi = mRssiRanges[i-1]; 302 // This value of hw has to be believed as this value is averaged and has breached 303 // the rssi thresholds and raised event to host. This would be eggregious if this 304 // value is invalid 305 mWifiInfo.setRssi((int) curRssi); 306 updateCapabilities(getCurrentWifiConfiguration()); 307 int ret = startRssiMonitoringOffload(maxRssi, minRssi); 308 Log.d(TAG, "Re-program RSSI thresholds for " + smToString(reason) + 309 ": [" + minRssi + ", " + maxRssi + "], curRssi=" + curRssi + " ret=" + ret); 310 break; 311 } 312 } 313 } 314 public void registerNetworkDisabled(int netId) { 315 // Restart legacy PNO and autojoin offload if needed 316 sendMessage(CMD_RESTART_AUTOJOIN_OFFLOAD, 0, 317 mRestartAutoJoinOffloadCounter, " registerNetworkDisabled " + netId); 318 mRestartAutoJoinOffloadCounter++; 319 } 320 321 // Testing various network disconnect cases by sending lots of spurious 322 // disconnect to supplicant 323 private boolean testNetworkDisconnect = false; 324 325 private boolean mEnableRssiPolling = false; 326 private boolean mLegacyPnoEnabled = false; 327 private int mRssiPollToken = 0; 328 /* 3 operational states for STA operation: CONNECT_MODE, SCAN_ONLY_MODE, SCAN_ONLY_WIFI_OFF_MODE 329 * In CONNECT_MODE, the STA can scan and connect to an access point 330 * In SCAN_ONLY_MODE, the STA can only scan for access points 331 * In SCAN_ONLY_WIFI_OFF_MODE, the STA can only scan for access points with wifi toggle being off 332 */ 333 private int mOperationalMode = CONNECT_MODE; 334 private boolean mIsScanOngoing = false; 335 private boolean mIsFullScanOngoing = false; 336 private boolean mSendScanResultsBroadcast = false; 337 338 private final Queue<Message> mBufferedScanMsg = new LinkedList<Message>(); 339 private WorkSource mScanWorkSource = null; 340 private static final int UNKNOWN_SCAN_SOURCE = -1; 341 private static final int SCAN_ALARM_SOURCE = -2; 342 private static final int ADD_OR_UPDATE_SOURCE = -3; 343 private static final int SET_ALLOW_UNTRUSTED_SOURCE = -4; 344 private static final int ENABLE_WIFI = -5; 345 public static final int DFS_RESTRICTED_SCAN_REQUEST = -6; 346 public static final int PNO_NETWORK_FOUND_SOURCE = -7; 347 348 private static final int SCAN_REQUEST_BUFFER_MAX_SIZE = 10; 349 private static final String CUSTOMIZED_SCAN_SETTING = "customized_scan_settings"; 350 private static final String CUSTOMIZED_SCAN_WORKSOURCE = "customized_scan_worksource"; 351 private static final String SCAN_REQUEST_TIME = "scan_request_time"; 352 353 /* Tracks if state machine has received any screen state change broadcast yet. 354 * We can miss one of these at boot. 355 */ 356 private AtomicBoolean mScreenBroadcastReceived = new AtomicBoolean(false); 357 358 private boolean mBluetoothConnectionActive = false; 359 360 private PowerManager.WakeLock mSuspendWakeLock; 361 362 /** 363 * Interval in milliseconds between polling for RSSI 364 * and linkspeed information 365 */ 366 private static final int POLL_RSSI_INTERVAL_MSECS = 3000; 367 368 /** 369 * Interval in milliseconds between receiving a disconnect event 370 * while connected to a good AP, and handling the disconnect proper 371 */ 372 private static final int LINK_FLAPPING_DEBOUNCE_MSEC = 4000; 373 374 /** 375 * Delay between supplicant restarts upon failure to establish connection 376 */ 377 private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000; 378 379 /** 380 * Number of times we attempt to restart supplicant 381 */ 382 private static final int SUPPLICANT_RESTART_TRIES = 5; 383 384 private int mSupplicantRestartCount = 0; 385 /* Tracks sequence number on stop failure message */ 386 private int mSupplicantStopFailureToken = 0; 387 388 /** 389 * Tether state change notification time out 390 */ 391 private static final int TETHER_NOTIFICATION_TIME_OUT_MSECS = 5000; 392 393 /* Tracks sequence number on a tether notification time out */ 394 private int mTetherToken = 0; 395 396 /** 397 * Driver start time out. 398 */ 399 private static final int DRIVER_START_TIME_OUT_MSECS = 10000; 400 401 /* Tracks sequence number on a driver time out */ 402 private int mDriverStartToken = 0; 403 404 /** 405 * Don't select new network when previous network selection is 406 * pending connection for this much time 407 */ 408 private static final int CONNECT_TIMEOUT_MSEC = 3000; 409 410 /** 411 * The link properties of the wifi interface. 412 * Do not modify this directly; use updateLinkProperties instead. 413 */ 414 private LinkProperties mLinkProperties; 415 416 /* Tracks sequence number on a periodic scan message */ 417 private int mPeriodicScanToken = 0; 418 419 // Wakelock held during wifi start/stop and driver load/unload 420 private PowerManager.WakeLock mWakeLock; 421 422 private Context mContext; 423 424 private final Object mDhcpResultsLock = new Object(); 425 private DhcpResults mDhcpResults; 426 427 // NOTE: Do not return to clients - use #getWiFiInfoForUid(int) 428 private final WifiInfo mWifiInfo; 429 private NetworkInfo mNetworkInfo; 430 private final NetworkCapabilities mDfltNetworkCapabilities; 431 private SupplicantStateTracker mSupplicantStateTracker; 432 433 private int mWifiLinkLayerStatsSupported = 4; // Temporary disable 434 435 // Whether the state machine goes thru the Disconnecting->Disconnected->ObtainingIpAddress 436 private boolean mAutoRoaming = false; 437 438 // Roaming failure count 439 private int mRoamFailCount = 0; 440 441 // This is the BSSID we are trying to associate to, it can be set to "any" 442 // if we havent selected a BSSID for joining. 443 // if we havent selected a BSSID for joining. 444 // The BSSID we are associated to is found in mWifiInfo 445 private String mTargetRoamBSSID = "any"; 446 //This one is used to track whta is the current target network ID. This is used for error 447 // handling during connection setup since many error message from supplicant does not report 448 // SSID Once connected, it will be set to invalid 449 private int mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 450 451 private long mLastDriverRoamAttempt = 0; 452 453 private WifiConfiguration targetWificonfiguration = null; 454 455 // Used as debug to indicate which configuration last was saved 456 private WifiConfiguration lastSavedConfigurationAttempt = null; 457 458 // Used as debug to indicate which configuration last was removed 459 private WifiConfiguration lastForgetConfigurationAttempt = null; 460 461 //Random used by softAP channel Selection 462 private static Random mRandom = new Random(Calendar.getInstance().getTimeInMillis()); 463 464 boolean isRoaming() { 465 return mAutoRoaming; 466 } 467 468 public void autoRoamSetBSSID(int netId, String bssid) { 469 autoRoamSetBSSID(mWifiConfigManager.getWifiConfiguration(netId), bssid); 470 } 471 472 public boolean autoRoamSetBSSID(WifiConfiguration config, String bssid) { 473 boolean ret = true; 474 if (mTargetRoamBSSID == null) mTargetRoamBSSID = "any"; 475 if (bssid == null) bssid = "any"; 476 if (config == null) return false; // Nothing to do 477 478 if (mTargetRoamBSSID != null && bssid == mTargetRoamBSSID && bssid == config.BSSID) { 479 return false; // We didnt change anything 480 } 481 if (!mTargetRoamBSSID.equals("any") && bssid.equals("any")) { 482 // Changing to ANY 483 if (!mWifiConfigManager.roamOnAny) { 484 ret = false; // Nothing to do 485 } 486 } 487 if (config.BSSID != null) { 488 bssid = config.BSSID; 489 if (DBG) { 490 Log.d(TAG, "force BSSID to " + bssid + "due to config"); 491 } 492 } 493 494 if (DBG) { 495 logd("autoRoamSetBSSID " + bssid + " key=" + config.configKey()); 496 } 497 mTargetRoamBSSID = bssid; 498 mWifiConfigManager.saveWifiConfigBSSID(config, bssid); 499 return ret; 500 } 501 502 /** 503 * set Config's default BSSID (for association purpose) 504 * @param config config need set BSSID 505 * @param bssid default BSSID to assocaite with when connect to this network 506 * @return false -- does not change the current default BSSID of the configure 507 * true -- change the current default BSSID of the configur 508 */ 509 private boolean setTargetBssid(WifiConfiguration config, String bssid) { 510 if (config == null) { 511 return false; 512 } 513 514 if (config.BSSID != null) { 515 bssid = config.BSSID; 516 if (DBG) { 517 Log.d(TAG, "force BSSID to " + bssid + "due to config"); 518 } 519 } 520 521 if (bssid == null) { 522 bssid = "any"; 523 } 524 525 String networkSelectionBSSID = config.getNetworkSelectionStatus() 526 .getNetworkSelectionBSSID(); 527 if (networkSelectionBSSID != null && networkSelectionBSSID.equals(bssid)) { 528 if (DBG) { 529 Log.d(TAG, "Current prefered BSSID is same as target"); 530 return false; 531 } 532 } 533 534 if (DBG) { 535 Log.d(TAG, "target set to " + config.SSID + ":" + bssid); 536 } 537 mTargetRoamBSSID = bssid; 538 mWifiConfigManager.saveWifiConfigBSSID(config, bssid); 539 return true; 540 } 541 /** 542 * Save the UID correctly depending on if this is a new or existing network. 543 * @return true if operation is authorized, false otherwise 544 */ 545 boolean recordUidIfAuthorized(WifiConfiguration config, int uid, boolean onlyAnnotate) { 546 if (!mWifiConfigManager.isNetworkConfigured(config)) { 547 config.creatorUid = uid; 548 config.creatorName = mContext.getPackageManager().getNameForUid(uid); 549 } else if (!mWifiConfigManager.canModifyNetwork(uid, config, onlyAnnotate)) { 550 return false; 551 } 552 553 config.lastUpdateUid = uid; 554 config.lastUpdateName = mContext.getPackageManager().getNameForUid(uid); 555 556 return true; 557 558 } 559 560 /** 561 * Checks to see if user has specified if the apps configuration is connectable. 562 * If the user hasn't specified we query the user and return true. 563 * 564 * @param message The message to be deferred 565 * @param netId Network id of the configuration to check against 566 * @param allowOverride If true we won't defer to the user if the uid of the message holds the 567 * CONFIG_OVERRIDE_PERMISSION 568 * @return True if we are waiting for user feedback or netId is invalid. False otherwise. 569 */ 570 boolean deferForUserInput(Message message, int netId, boolean allowOverride){ 571 final WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(netId); 572 573 // We can only evaluate saved configurations. 574 if (config == null) { 575 logd("deferForUserInput: configuration for netId=" + netId + " not stored"); 576 return true; 577 } 578 579 switch (config.userApproved) { 580 case WifiConfiguration.USER_APPROVED: 581 case WifiConfiguration.USER_BANNED: 582 return false; 583 case WifiConfiguration.USER_PENDING: 584 default: // USER_UNSPECIFIED 585 /* the intention was to ask user here; but a dialog box is * 586 * too invasive; so we are going to allow connection for now */ 587 config.userApproved = WifiConfiguration.USER_APPROVED; 588 return false; 589 } 590 } 591 592 private final IpManager mIpManager; 593 594 private AlarmManager mAlarmManager; 595 private PendingIntent mScanIntent; 596 private PendingIntent mPnoIntent; 597 598 private int mDisconnectedPnoAlarmCount = 0; 599 /* Tracks current frequency mode */ 600 private AtomicInteger mFrequencyBand = new AtomicInteger(WifiManager.WIFI_FREQUENCY_BAND_AUTO); 601 602 /* Tracks if we are filtering Multicast v4 packets. Default is to filter. */ 603 private AtomicBoolean mFilteringMulticastV4Packets = new AtomicBoolean(true); 604 605 // Channel for sending replies. 606 private AsyncChannel mReplyChannel = new AsyncChannel(); 607 608 private WifiP2pServiceImpl mWifiP2pServiceImpl; 609 610 // Used to initiate a connection with WifiP2pService 611 private AsyncChannel mWifiP2pChannel; 612 613 private WifiScanner mWifiScanner; 614 615 private int mConnectionRequests = 0; 616 private WifiNetworkFactory mNetworkFactory; 617 private UntrustedWifiNetworkFactory mUntrustedNetworkFactory; 618 private WifiNetworkAgent mNetworkAgent; 619 620 private String[] mWhiteListedSsids = null; 621 622 private byte[] mRssiRanges; 623 624 // Keep track of various statistics, for retrieval by System Apps, i.e. under @SystemApi 625 // We should really persist that into the networkHistory.txt file, and read it back when 626 // WifiStateMachine starts up 627 private WifiConnectionStatistics mWifiConnectionStatistics = new WifiConnectionStatistics(); 628 629 // Used to filter out requests we couldn't possibly satisfy. 630 private final NetworkCapabilities mNetworkCapabilitiesFilter = new NetworkCapabilities(); 631 632 // Provide packet filter capabilities to ConnectivityService. 633 private final NetworkMisc mNetworkMisc = new NetworkMisc(); 634 635 /* The base for wifi message types */ 636 static final int BASE = Protocol.BASE_WIFI; 637 /* Start the supplicant */ 638 static final int CMD_START_SUPPLICANT = BASE + 11; 639 /* Stop the supplicant */ 640 static final int CMD_STOP_SUPPLICANT = BASE + 12; 641 /* Start the driver */ 642 static final int CMD_START_DRIVER = BASE + 13; 643 /* Stop the driver */ 644 static final int CMD_STOP_DRIVER = BASE + 14; 645 /* Indicates Static IP succeeded */ 646 static final int CMD_STATIC_IP_SUCCESS = BASE + 15; 647 /* Indicates Static IP failed */ 648 static final int CMD_STATIC_IP_FAILURE = BASE + 16; 649 /* Indicates supplicant stop failed */ 650 static final int CMD_STOP_SUPPLICANT_FAILED = BASE + 17; 651 /* A delayed message sent to start driver when it fail to come up */ 652 static final int CMD_DRIVER_START_TIMED_OUT = BASE + 19; 653 654 /* Start the soft access point */ 655 static final int CMD_START_AP = BASE + 21; 656 /* Indicates soft ap start failed */ 657 static final int CMD_START_AP_FAILURE = BASE + 22; 658 /* Stop the soft access point */ 659 static final int CMD_STOP_AP = BASE + 23; 660 /* Soft access point teardown is completed. */ 661 static final int CMD_AP_STOPPED = BASE + 24; 662 663 static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 31; 664 665 /* Supplicant commands */ 666 /* Is supplicant alive ? */ 667 static final int CMD_PING_SUPPLICANT = BASE + 51; 668 /* Add/update a network configuration */ 669 static final int CMD_ADD_OR_UPDATE_NETWORK = BASE + 52; 670 /* Delete a network */ 671 static final int CMD_REMOVE_NETWORK = BASE + 53; 672 /* Enable a network. The device will attempt a connection to the given network. */ 673 static final int CMD_ENABLE_NETWORK = BASE + 54; 674 /* Enable all networks */ 675 static final int CMD_ENABLE_ALL_NETWORKS = BASE + 55; 676 /* Blacklist network. De-prioritizes the given BSSID for connection. */ 677 static final int CMD_BLACKLIST_NETWORK = BASE + 56; 678 /* Clear the blacklist network list */ 679 static final int CMD_CLEAR_BLACKLIST = BASE + 57; 680 /* Save configuration */ 681 static final int CMD_SAVE_CONFIG = BASE + 58; 682 /* Get configured networks */ 683 static final int CMD_GET_CONFIGURED_NETWORKS = BASE + 59; 684 /* Get available frequencies */ 685 static final int CMD_GET_CAPABILITY_FREQ = BASE + 60; 686 /* Get adaptors */ 687 static final int CMD_GET_SUPPORTED_FEATURES = BASE + 61; 688 /* Get configured networks with real preSharedKey */ 689 static final int CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS = BASE + 62; 690 /* Get Link Layer Stats thru HAL */ 691 static final int CMD_GET_LINK_LAYER_STATS = BASE + 63; 692 /* Supplicant commands after driver start*/ 693 /* Initiate a scan */ 694 static final int CMD_START_SCAN = BASE + 71; 695 /* Set operational mode. CONNECT, SCAN ONLY, SCAN_ONLY with Wi-Fi off mode */ 696 static final int CMD_SET_OPERATIONAL_MODE = BASE + 72; 697 /* Disconnect from a network */ 698 static final int CMD_DISCONNECT = BASE + 73; 699 /* Reconnect to a network */ 700 static final int CMD_RECONNECT = BASE + 74; 701 /* Reassociate to a network */ 702 static final int CMD_REASSOCIATE = BASE + 75; 703 /* Get Connection Statistis */ 704 static final int CMD_GET_CONNECTION_STATISTICS = BASE + 76; 705 706 /* Controls suspend mode optimizations 707 * 708 * When high perf mode is enabled, suspend mode optimizations are disabled 709 * 710 * When high perf mode is disabled, suspend mode optimizations are enabled 711 * 712 * Suspend mode optimizations include: 713 * - packet filtering 714 * - turn off roaming 715 * - DTIM wake up settings 716 */ 717 static final int CMD_SET_HIGH_PERF_MODE = BASE + 77; 718 /* Enables RSSI poll */ 719 static final int CMD_ENABLE_RSSI_POLL = BASE + 82; 720 /* RSSI poll */ 721 static final int CMD_RSSI_POLL = BASE + 83; 722 /* Set up packet filtering */ 723 static final int CMD_START_PACKET_FILTERING = BASE + 84; 724 /* Clear packet filter */ 725 static final int CMD_STOP_PACKET_FILTERING = BASE + 85; 726 /* Enable suspend mode optimizations in the driver */ 727 static final int CMD_SET_SUSPEND_OPT_ENABLED = BASE + 86; 728 /* Delayed NETWORK_DISCONNECT */ 729 static final int CMD_DELAYED_NETWORK_DISCONNECT = BASE + 87; 730 /* When there are no saved networks, we do a periodic scan to notify user of 731 * an open network */ 732 static final int CMD_NO_NETWORKS_PERIODIC_SCAN = BASE + 88; 733 /* Test network Disconnection NETWORK_DISCONNECT */ 734 static final int CMD_TEST_NETWORK_DISCONNECT = BASE + 89; 735 736 private int testNetworkDisconnectCounter = 0; 737 738 /* arg1 values to CMD_STOP_PACKET_FILTERING and CMD_START_PACKET_FILTERING */ 739 static final int MULTICAST_V6 = 1; 740 static final int MULTICAST_V4 = 0; 741 742 /* Set the frequency band */ 743 static final int CMD_SET_FREQUENCY_BAND = BASE + 90; 744 /* Enable TDLS on a specific MAC address */ 745 static final int CMD_ENABLE_TDLS = BASE + 92; 746 /* DHCP/IP configuration watchdog */ 747 static final int CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER = BASE + 93; 748 749 /** 750 * Watchdog for protecting against b/16823537 751 * Leave time for 4-way handshake to succeed 752 */ 753 static final int ROAM_GUARD_TIMER_MSEC = 15000; 754 755 int roamWatchdogCount = 0; 756 /* Roam state watchdog */ 757 static final int CMD_ROAM_WATCHDOG_TIMER = BASE + 94; 758 /* Screen change intent handling */ 759 static final int CMD_SCREEN_STATE_CHANGED = BASE + 95; 760 761 /* Disconnecting state watchdog */ 762 static final int CMD_DISCONNECTING_WATCHDOG_TIMER = BASE + 96; 763 764 /* Remove a packages associated configrations */ 765 static final int CMD_REMOVE_APP_CONFIGURATIONS = BASE + 97; 766 767 /* Disable an ephemeral network */ 768 static final int CMD_DISABLE_EPHEMERAL_NETWORK = BASE + 98; 769 770 /* Get matching network */ 771 static final int CMD_GET_MATCHING_CONFIG = BASE + 99; 772 773 /* alert from firmware */ 774 static final int CMD_FIRMWARE_ALERT = BASE + 100; 775 776 /* SIM is removed; reset any cached data for it */ 777 static final int CMD_RESET_SIM_NETWORKS = BASE + 101; 778 779 /* OSU APIs */ 780 static final int CMD_ADD_PASSPOINT_MO = BASE + 102; 781 static final int CMD_MODIFY_PASSPOINT_MO = BASE + 103; 782 static final int CMD_QUERY_OSU_ICON = BASE + 104; 783 784 /* try to match a provider with current network */ 785 static final int CMD_MATCH_PROVIDER_NETWORK = BASE + 105; 786 787 /** 788 * Make this timer 40 seconds, which is about the normal DHCP timeout. 789 * In no valid case, the WiFiStateMachine should remain stuck in ObtainingIpAddress 790 * for more than 30 seconds. 791 */ 792 static final int OBTAINING_IP_ADDRESS_GUARD_TIMER_MSEC = 40000; 793 794 int obtainingIpWatchdogCount = 0; 795 796 /* Commands from/to the SupplicantStateTracker */ 797 /* Reset the supplicant state tracker */ 798 static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111; 799 800 int disconnectingWatchdogCount = 0; 801 static final int DISCONNECTING_GUARD_TIMER_MSEC = 5000; 802 803 /* P2p commands */ 804 /* We are ok with no response here since we wont do much with it anyway */ 805 public static final int CMD_ENABLE_P2P = BASE + 131; 806 /* In order to shut down supplicant cleanly, we wait till p2p has 807 * been disabled */ 808 public static final int CMD_DISABLE_P2P_REQ = BASE + 132; 809 public static final int CMD_DISABLE_P2P_RSP = BASE + 133; 810 811 public static final int CMD_BOOT_COMPLETED = BASE + 134; 812 813 /* We now have a valid IP configuration. */ 814 static final int CMD_IP_CONFIGURATION_SUCCESSFUL = BASE + 138; 815 /* We no longer have a valid IP configuration. */ 816 static final int CMD_IP_CONFIGURATION_LOST = BASE + 139; 817 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 818 static final int CMD_UPDATE_LINKPROPERTIES = BASE + 140; 819 820 /* Supplicant is trying to associate to a given BSSID */ 821 static final int CMD_TARGET_BSSID = BASE + 141; 822 823 /* Reload all networks and reconnect */ 824 static final int CMD_RELOAD_TLS_AND_RECONNECT = BASE + 142; 825 826 static final int CMD_AUTO_CONNECT = BASE + 143; 827 828 private static final int NETWORK_STATUS_UNWANTED_DISCONNECT = 0; 829 private static final int NETWORK_STATUS_UNWANTED_VALIDATION_FAILED = 1; 830 private static final int NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN = 2; 831 832 static final int CMD_UNWANTED_NETWORK = BASE + 144; 833 834 static final int CMD_AUTO_ROAM = BASE + 145; 835 836 static final int CMD_AUTO_SAVE_NETWORK = BASE + 146; 837 838 static final int CMD_ASSOCIATED_BSSID = BASE + 147; 839 840 static final int CMD_NETWORK_STATUS = BASE + 148; 841 842 /* A layer 3 neighbor on the Wi-Fi link became unreachable. */ 843 static final int CMD_IP_REACHABILITY_LOST = BASE + 149; 844 845 /* Remove a packages associated configrations */ 846 static final int CMD_REMOVE_USER_CONFIGURATIONS = BASE + 152; 847 848 static final int CMD_ACCEPT_UNVALIDATED = BASE + 153; 849 850 /* used to restart PNO when it was stopped due to association attempt */ 851 static final int CMD_RESTART_AUTOJOIN_OFFLOAD = BASE + 154; 852 853 static int mRestartAutoJoinOffloadCounter = 0; 854 855 /* used to log if PNO was started */ 856 static final int CMD_STARTED_PNO_DBG = BASE + 155; 857 858 static final int CMD_PNO_NETWORK_FOUND = BASE + 156; 859 860 /* used to log if PNO was started */ 861 static final int CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION = BASE + 158; 862 863 /* used to log if GSCAN was started */ 864 static final int CMD_STARTED_GSCAN_DBG = BASE + 159; 865 866 /* used to offload sending IP packet */ 867 static final int CMD_START_IP_PACKET_OFFLOAD = BASE + 160; 868 869 /* used to stop offload sending IP packet */ 870 static final int CMD_STOP_IP_PACKET_OFFLOAD = BASE + 161; 871 872 /* used to start rssi monitoring in hw */ 873 static final int CMD_START_RSSI_MONITORING_OFFLOAD = BASE + 162; 874 875 /* used to stop rssi moniroting in hw */ 876 static final int CMD_STOP_RSSI_MONITORING_OFFLOAD = BASE + 163; 877 878 /* used to indicated RSSI threshold breach in hw */ 879 static final int CMD_RSSI_THRESHOLD_BREACH = BASE + 164; 880 881 /* used to indicate that the foreground user was switched */ 882 static final int CMD_USER_SWITCH = BASE + 165; 883 884 /** 885 * Used temporarily to handle messages bounced between WifiStateMachine and IpManager. 886 * 887 * These will be deleted when DHCPv4 and static IP configuration are moved out. 888 */ 889 static final int CMD_IPV4_PROVISIONING_SUCCESS = BASE + 200; 890 static final int CMD_IPV4_PROVISIONING_FAILURE = BASE + 201; 891 892 /* Push a new APF program to the HAL */ 893 static final int CMD_INSTALL_PACKET_FILTER = BASE + 202; 894 895 // For message logging. 896 private static final Class[] sMessageClasses = { 897 AsyncChannel.class, WifiStateMachine.class, DhcpClient.class }; 898 private static final SparseArray<String> sSmToString = 899 MessageUtils.findMessageNames(sMessageClasses); 900 901 902 /* Wifi state machine modes of operation */ 903 /* CONNECT_MODE - connect to any 'known' AP when it becomes available */ 904 public static final int CONNECT_MODE = 1; 905 /* SCAN_ONLY_MODE - don't connect to any APs; scan, but only while apps hold lock */ 906 public static final int SCAN_ONLY_MODE = 2; 907 /* SCAN_ONLY_WITH_WIFI_OFF - scan, but don't connect to any APs */ 908 public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3; 909 910 private static final int SUCCESS = 1; 911 private static final int FAILURE = -1; 912 913 /* Tracks if suspend optimizations need to be disabled by DHCP, 914 * screen or due to high perf mode. 915 * When any of them needs to disable it, we keep the suspend optimizations 916 * disabled 917 */ 918 private int mSuspendOptNeedsDisabled = 0; 919 920 private static final int SUSPEND_DUE_TO_DHCP = 1; 921 private static final int SUSPEND_DUE_TO_HIGH_PERF = 1 << 1; 922 private static final int SUSPEND_DUE_TO_SCREEN = 1 << 2; 923 924 /* Tracks if user has enabled suspend optimizations through settings */ 925 private AtomicBoolean mUserWantsSuspendOpt = new AtomicBoolean(true); 926 927 /** 928 * Default framework scan interval in milliseconds. This is used in the scenario in which 929 * wifi chipset does not support background scanning to set up a 930 * periodic wake up scan so that the device can connect to a new access 931 * point on the move. {@link Settings.Global#WIFI_FRAMEWORK_SCAN_INTERVAL_MS} can 932 * override this. 933 */ 934 private final int mDefaultFrameworkScanIntervalMs; 935 936 937 /** 938 * Scan period for the NO_NETWORKS_PERIIDOC_SCAN_FEATURE 939 */ 940 private final int mNoNetworksPeriodicScan; 941 942 /** 943 * Supplicant scan interval in milliseconds. 944 * Comes from {@link Settings.Global#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} or 945 * from the default config if the setting is not set 946 */ 947 private long mSupplicantScanIntervalMs; 948 949 /** 950 * timeStamp of last full band scan we perfoemed for autojoin while connected with screen lit 951 */ 952 private long lastFullBandConnectedTimeMilli; 953 954 /** 955 * time interval to the next full band scan we will perform for 956 * autojoin while connected with screen lit 957 */ 958 private long fullBandConnectedTimeIntervalMilli; 959 960 /** 961 * max time interval to the next full band scan we will perform for 962 * autojoin while connected with screen lit 963 * Max time is 5 minutes 964 */ 965 private static final long maxFullBandConnectedTimeIntervalMilli = 1000 * 60 * 5; 966 967 /** 968 * Minimum time interval between enabling all networks. 969 * A device can end up repeatedly connecting to a bad network on screen on/off toggle 970 * due to enabling every time. We add a threshold to avoid this. 971 */ 972 private static final int MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS = 10 * 60 * 1000; /* 10 minutes */ 973 private long mLastEnableAllNetworksTime; 974 975 int mRunningBeaconCount = 0; 976 977 /* Default parent state */ 978 private State mDefaultState = new DefaultState(); 979 /* Temporary initial state */ 980 private State mInitialState = new InitialState(); 981 /* Driver loaded, waiting for supplicant to start */ 982 private State mSupplicantStartingState = new SupplicantStartingState(); 983 /* Driver loaded and supplicant ready */ 984 private State mSupplicantStartedState = new SupplicantStartedState(); 985 /* Waiting for supplicant to stop and monitor to exit */ 986 private State mSupplicantStoppingState = new SupplicantStoppingState(); 987 /* Driver start issued, waiting for completed event */ 988 private State mDriverStartingState = new DriverStartingState(); 989 /* Driver started */ 990 private State mDriverStartedState = new DriverStartedState(); 991 /* Wait until p2p is disabled 992 * This is a special state which is entered right after we exit out of DriverStartedState 993 * before transitioning to another state. 994 */ 995 private State mWaitForP2pDisableState = new WaitForP2pDisableState(); 996 /* Driver stopping */ 997 private State mDriverStoppingState = new DriverStoppingState(); 998 /* Driver stopped */ 999 private State mDriverStoppedState = new DriverStoppedState(); 1000 /* Scan for networks, no connection will be established */ 1001 private State mScanModeState = new ScanModeState(); 1002 /* Connecting to an access point */ 1003 private State mConnectModeState = new ConnectModeState(); 1004 /* Connected at 802.11 (L2) level */ 1005 private State mL2ConnectedState = new L2ConnectedState(); 1006 /* fetching IP after connection to access point (assoc+auth complete) */ 1007 private State mObtainingIpState = new ObtainingIpState(); 1008 /* Connected with IP addr */ 1009 private State mConnectedState = new ConnectedState(); 1010 /* Roaming */ 1011 private State mRoamingState = new RoamingState(); 1012 /* disconnect issued, waiting for network disconnect confirmation */ 1013 private State mDisconnectingState = new DisconnectingState(); 1014 /* Network is not connected, supplicant assoc+auth is not complete */ 1015 private State mDisconnectedState = new DisconnectedState(); 1016 /* Waiting for WPS to be completed*/ 1017 private State mWpsRunningState = new WpsRunningState(); 1018 /* Soft ap state */ 1019 private State mSoftApState = new SoftApState(); 1020 1021 private class WifiScanListener implements WifiScanner.ScanListener { 1022 @Override 1023 public void onSuccess() { 1024 Log.e(TAG, "WifiScanListener onSuccess"); 1025 }; 1026 @Override 1027 public void onFailure(int reason, String description) { 1028 Log.e(TAG, "WifiScanListener onFailure"); 1029 }; 1030 @Override 1031 public void onPeriodChanged(int periodInMs) { 1032 Log.e(TAG, "WifiScanListener onPeriodChanged period=" + periodInMs); 1033 } 1034 @Override 1035 public void onResults(WifiScanner.ScanData[] results) { 1036 Log.e(TAG, "WifiScanListener onResults2 " + results.length); 1037 } 1038 @Override 1039 public void onFullResult(ScanResult fullScanResult) { 1040 Log.e(TAG, "WifiScanListener onFullResult " + fullScanResult.toString()); 1041 } 1042 1043 WifiScanListener() {} 1044 } 1045 1046 WifiScanListener mWifiScanListener = new WifiScanListener(); 1047 1048 public static class SimAuthRequestData { 1049 int networkId; 1050 int protocol; 1051 String ssid; 1052 // EAP-SIM: data[] contains the 3 rand, one for each of the 3 challenges 1053 // EAP-AKA/AKA': data[] contains rand & authn couple for the single challenge 1054 String[] data; 1055 } 1056 1057 /** 1058 * One of {@link WifiManager#WIFI_STATE_DISABLED}, 1059 * {@link WifiManager#WIFI_STATE_DISABLING}, 1060 * {@link WifiManager#WIFI_STATE_ENABLED}, 1061 * {@link WifiManager#WIFI_STATE_ENABLING}, 1062 * {@link WifiManager#WIFI_STATE_UNKNOWN} 1063 */ 1064 private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED); 1065 1066 /** 1067 * One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 1068 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 1069 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 1070 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 1071 * {@link WifiManager#WIFI_AP_STATE_FAILED} 1072 */ 1073 private final AtomicInteger mWifiApState = new AtomicInteger(WIFI_AP_STATE_DISABLED); 1074 1075 private static final int SCAN_REQUEST = 0; 1076 private static final String ACTION_START_SCAN = 1077 "com.android.server.WifiManager.action.START_SCAN"; 1078 1079 private static final int PNO_START_REQUEST = 0; 1080 private static final String ACTION_START_PNO = 1081 "com.android.server.WifiManager.action.START_PNO"; 1082 1083 /** 1084 * Keep track of whether WIFI is running. 1085 */ 1086 private boolean mIsRunning = false; 1087 1088 /** 1089 * Keep track of whether we last told the battery stats we had started. 1090 */ 1091 private boolean mReportedRunning = false; 1092 1093 /** 1094 * Most recently set source of starting WIFI. 1095 */ 1096 private final WorkSource mRunningWifiUids = new WorkSource(); 1097 1098 /** 1099 * The last reported UIDs that were responsible for starting WIFI. 1100 */ 1101 private final WorkSource mLastRunningWifiUids = new WorkSource(); 1102 1103 private final IBatteryStats mBatteryStats; 1104 1105 private final String mTcpBufferSizes; 1106 1107 // Used for debug and stats gathering 1108 private static int sScanAlarmIntentCount = 0; 1109 1110 private static final int sFrameworkMinScanIntervalSaneValue = 10000; 1111 1112 private boolean mPnoEnabled; 1113 private long mGScanStartTimeMilli; 1114 private long mGScanPeriodMilli; 1115 1116 private FrameworkFacade mFacade; 1117 1118 private final BackupManagerProxy mBackupManagerProxy; 1119 1120 public WifiStateMachine(Context context, FrameworkFacade facade, Looper looper, 1121 UserManager userManager, WifiInjector wifiInjector, 1122 BackupManagerProxy backupManagerProxy, 1123 WifiCountryCode countryCode) { 1124 super("WifiStateMachine", looper); 1125 1126 mWifiMetrics = wifiInjector.getWifiMetrics(); 1127 mContext = context; 1128 mFacade = facade; 1129 mUserManager = userManager; 1130 mWifiNative = WifiNative.getWlanNativeInterface(); 1131 mBackupManagerProxy = backupManagerProxy; 1132 1133 // TODO refactor WifiNative use of context out into it's own class 1134 mWifiNative.initContext(mContext); 1135 mInterfaceName = mWifiNative.getInterfaceName(); 1136 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, ""); 1137 mBatteryStats = IBatteryStats.Stub.asInterface(mFacade.getService( 1138 BatteryStats.SERVICE_NAME)); 1139 1140 IBinder b = mFacade.getService(Context.NETWORKMANAGEMENT_SERVICE); 1141 mNwService = INetworkManagementService.Stub.asInterface(b); 1142 1143 mP2pSupported = mContext.getPackageManager().hasSystemFeature( 1144 PackageManager.FEATURE_WIFI_DIRECT); 1145 1146 mWifiConfigManager = mFacade.makeWifiConfigManager(context, this, mWifiNative, facade, 1147 mClock, userManager, KeyStore.getInstance()); 1148 1149 mWifiMonitor = WifiMonitor.getInstance(); 1150 1151 boolean enableFirmwareLogs = mContext.getResources().getBoolean( 1152 R.bool.config_wifi_enable_wifi_firmware_debugging); 1153 1154 if (enableFirmwareLogs) { 1155 int maxRingBufferSizeBytes = mContext.getResources().getInteger( 1156 R.integer.config_wifi_logger_ring_buffer_size_limit_kb) * 1024; 1157 mWifiLogger = facade.makeRealLogger(this, mWifiNative, maxRingBufferSizeBytes); 1158 } else { 1159 mWifiLogger = facade.makeBaseLogger(); 1160 } 1161 1162 mWifiInfo = new WifiInfo(); 1163 mWifiQualifiedNetworkSelector = new WifiQualifiedNetworkSelector(mWifiConfigManager, 1164 mContext, mWifiInfo, mClock); 1165 mSupplicantStateTracker = mFacade.makeSupplicantStateTracker( 1166 context, mWifiConfigManager, getHandler()); 1167 1168 mLinkProperties = new LinkProperties(); 1169 1170 IBinder s1 = mFacade.getService(Context.WIFI_P2P_SERVICE); 1171 mWifiP2pServiceImpl = (WifiP2pServiceImpl) IWifiP2pManager.Stub.asInterface(s1); 1172 1173 mNetworkInfo.setIsAvailable(false); 1174 mLastBssid = null; 1175 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 1176 mLastSignalLevel = -1; 1177 1178 mIpManager = mFacade.makeIpManager(mContext, mInterfaceName, new IpManagerCallback()); 1179 1180 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 1181 mScanIntent = getPrivateBroadcast(ACTION_START_SCAN, SCAN_REQUEST); 1182 mPnoIntent = getPrivateBroadcast(ACTION_START_PNO, PNO_START_REQUEST); 1183 1184 // Make sure the interval is not configured less than 10 seconds 1185 int period = mContext.getResources().getInteger( 1186 R.integer.config_wifi_framework_scan_interval); 1187 if (period < sFrameworkMinScanIntervalSaneValue) { 1188 period = sFrameworkMinScanIntervalSaneValue; 1189 } 1190 mDefaultFrameworkScanIntervalMs = period; 1191 1192 mNoNetworksPeriodicScan = mContext.getResources().getInteger( 1193 R.integer.config_wifi_no_network_periodic_scan_interval); 1194 1195 mBackgroundScanSupported = mContext.getResources().getBoolean( 1196 R.bool.config_wifi_background_scan_support); 1197 1198 mPrimaryDeviceType = mContext.getResources().getString( 1199 R.string.config_wifi_p2p_device_type); 1200 1201 mCountryCode = countryCode; 1202 1203 mUserWantsSuspendOpt.set(mFacade.getIntegerSetting(mContext, 1204 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1); 1205 1206 mNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); 1207 mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 1208 mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 1209 mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); 1210 mNetworkCapabilitiesFilter.setLinkUpstreamBandwidthKbps(1024 * 1024); 1211 mNetworkCapabilitiesFilter.setLinkDownstreamBandwidthKbps(1024 * 1024); 1212 // TODO - needs to be a bit more dynamic 1213 mDfltNetworkCapabilities = new NetworkCapabilities(mNetworkCapabilitiesFilter); 1214 1215 mContext.registerReceiver( 1216 new BroadcastReceiver() { 1217 @Override 1218 public void onReceive(Context context, Intent intent) { 1219 sScanAlarmIntentCount++; // Used for debug only 1220 startScan(SCAN_ALARM_SOURCE, mDelayedScanCounter.incrementAndGet(), null, null); 1221 if (DBG) 1222 logd("SCAN ALARM -> " + mDelayedScanCounter.get()); 1223 } 1224 }, 1225 new IntentFilter(ACTION_START_SCAN)); 1226 1227 mContext.registerReceiver( 1228 new BroadcastReceiver() { 1229 @Override 1230 public void onReceive(Context context, Intent intent) { 1231 sendMessage(CMD_RESTART_AUTOJOIN_OFFLOAD, 0, 1232 mRestartAutoJoinOffloadCounter, "pno alarm"); 1233 if (DBG) 1234 logd("PNO START ALARM sent"); 1235 } 1236 }, 1237 new IntentFilter(ACTION_START_PNO)); 1238 1239 1240 IntentFilter filter = new IntentFilter(); 1241 filter.addAction(Intent.ACTION_SCREEN_ON); 1242 filter.addAction(Intent.ACTION_SCREEN_OFF); 1243 mContext.registerReceiver( 1244 new BroadcastReceiver() { 1245 @Override 1246 public void onReceive(Context context, Intent intent) { 1247 String action = intent.getAction(); 1248 1249 if (action.equals(Intent.ACTION_SCREEN_ON)) { 1250 sendMessage(CMD_SCREEN_STATE_CHANGED, 1); 1251 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1252 sendMessage(CMD_SCREEN_STATE_CHANGED, 0); 1253 } 1254 } 1255 }, filter); 1256 1257 mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor( 1258 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED), false, 1259 new ContentObserver(getHandler()) { 1260 @Override 1261 public void onChange(boolean selfChange) { 1262 mUserWantsSuspendOpt.set(mFacade.getIntegerSetting(mContext, 1263 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1); 1264 } 1265 }); 1266 1267 mContext.registerReceiver( 1268 new BroadcastReceiver() { 1269 @Override 1270 public void onReceive(Context context, Intent intent) { 1271 sendMessage(CMD_BOOT_COMPLETED); 1272 } 1273 }, 1274 new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); 1275 1276 PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 1277 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getName()); 1278 1279 mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend"); 1280 mSuspendWakeLock.setReferenceCounted(false); 1281 1282 mTcpBufferSizes = mContext.getResources().getString( 1283 com.android.internal.R.string.config_wifi_tcp_buffers); 1284 1285 // CHECKSTYLE:OFF IndentationCheck 1286 addState(mDefaultState); 1287 addState(mInitialState, mDefaultState); 1288 addState(mSupplicantStartingState, mDefaultState); 1289 addState(mSupplicantStartedState, mDefaultState); 1290 addState(mDriverStartingState, mSupplicantStartedState); 1291 addState(mDriverStartedState, mSupplicantStartedState); 1292 addState(mScanModeState, mDriverStartedState); 1293 addState(mConnectModeState, mDriverStartedState); 1294 addState(mL2ConnectedState, mConnectModeState); 1295 addState(mObtainingIpState, mL2ConnectedState); 1296 addState(mConnectedState, mL2ConnectedState); 1297 addState(mRoamingState, mL2ConnectedState); 1298 addState(mDisconnectingState, mConnectModeState); 1299 addState(mDisconnectedState, mConnectModeState); 1300 addState(mWpsRunningState, mConnectModeState); 1301 addState(mWaitForP2pDisableState, mSupplicantStartedState); 1302 addState(mDriverStoppingState, mSupplicantStartedState); 1303 addState(mDriverStoppedState, mSupplicantStartedState); 1304 addState(mSupplicantStoppingState, mDefaultState); 1305 addState(mSoftApState, mDefaultState); 1306 // CHECKSTYLE:ON IndentationCheck 1307 1308 setInitialState(mInitialState); 1309 1310 setLogRecSize(ActivityManager.isLowRamDeviceStatic() ? 100 : 3000); 1311 setLogOnlyTransitions(false); 1312 1313 //start the state machine 1314 start(); 1315 1316 mWifiMonitor.registerHandler(mInterfaceName, CMD_TARGET_BSSID, getHandler()); 1317 mWifiMonitor.registerHandler(mInterfaceName, CMD_ASSOCIATED_BSSID, getHandler()); 1318 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ANQP_DONE_EVENT, getHandler()); 1319 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT, 1320 getHandler()); 1321 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 1322 getHandler()); 1323 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.DRIVER_HUNG_EVENT, getHandler()); 1324 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_DONE_EVENT, getHandler()); 1325 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_START_EVENT, 1326 getHandler()); 1327 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.HS20_REMEDIATION_EVENT, 1328 getHandler()); 1329 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT, 1330 getHandler()); 1331 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT, 1332 getHandler()); 1333 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.RX_HS20_ANQP_ICON_EVENT, 1334 getHandler()); 1335 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SCAN_FAILED_EVENT, getHandler()); 1336 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SCAN_RESULTS_EVENT, getHandler()); 1337 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SSID_REENABLED, getHandler()); 1338 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SSID_TEMP_DISABLED, getHandler()); 1339 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_CONNECTION_EVENT, getHandler()); 1340 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_DISCONNECTION_EVENT, 1341 getHandler()); 1342 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 1343 getHandler()); 1344 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_IDENTITY, getHandler()); 1345 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_SIM_AUTH, getHandler()); 1346 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_FAIL_EVENT, getHandler()); 1347 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_OVERLAP_EVENT, getHandler()); 1348 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_SUCCESS_EVENT, getHandler()); 1349 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_TIMEOUT_EVENT, getHandler()); 1350 1351 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 1352 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1353 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); 1354 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 1355 } 1356 1357 class IpManagerCallback extends IpManager.Callback { 1358 @Override 1359 public void onPreDhcpAction() { 1360 sendMessage(DhcpClient.CMD_PRE_DHCP_ACTION); 1361 } 1362 1363 @Override 1364 public void onPostDhcpAction() { 1365 sendMessage(DhcpClient.CMD_POST_DHCP_ACTION); 1366 } 1367 1368 @Override 1369 public void onNewDhcpResults(DhcpResults dhcpResults) { 1370 if (dhcpResults != null) { 1371 sendMessage(CMD_IPV4_PROVISIONING_SUCCESS, dhcpResults); 1372 } else { 1373 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 1374 } 1375 } 1376 1377 @Override 1378 public void onProvisioningSuccess(LinkProperties newLp) { 1379 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); 1380 sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL); 1381 } 1382 1383 @Override 1384 public void onProvisioningFailure(LinkProperties newLp) { 1385 sendMessage(CMD_IP_CONFIGURATION_LOST); 1386 } 1387 1388 @Override 1389 public void on464XlatChange(boolean enabled) { 1390 mWifiNative.configureNeighborDiscoveryOffload(!enabled); 1391 } 1392 1393 @Override 1394 public void onLinkPropertiesChange(LinkProperties newLp) { 1395 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); 1396 } 1397 1398 @Override 1399 public void onReachabilityLost(String logMsg) { 1400 sendMessage(CMD_IP_REACHABILITY_LOST, logMsg); 1401 } 1402 1403 @Override 1404 public void installPacketFilter(byte[] filter) { 1405 sendMessage(CMD_INSTALL_PACKET_FILTER, filter); 1406 } 1407 } 1408 1409 private void stopIpManager() { 1410 /* Restore power save and suspend optimizations */ 1411 handlePostDhcpSetup(); 1412 mIpManager.stop(); 1413 } 1414 1415 PendingIntent getPrivateBroadcast(String action, int requestCode) { 1416 Intent intent = new Intent(action, null); 1417 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1418 intent.setPackage("android"); 1419 return mFacade.getBroadcast(mContext, requestCode, intent, 0); 1420 } 1421 1422 int getVerboseLoggingLevel() { 1423 return mVerboseLoggingLevel; 1424 } 1425 1426 void enableVerboseLogging(int verbose) { 1427 mVerboseLoggingLevel = verbose; 1428 if (mVerboseLoggingLevel > 0) { 1429 DBG = true; 1430 mWifiNative.setSupplicantLogLevel("DEBUG"); 1431 } else { 1432 DBG = false; 1433 mWifiNative.setSupplicantLogLevel("INFO"); 1434 } 1435 mCountryCode.enableVerboseLogging(verbose); 1436 mWifiLogger.startLogging(DBG); 1437 mWifiMonitor.enableVerboseLogging(verbose); 1438 mWifiNative.enableVerboseLogging(verbose); 1439 mWifiConfigManager.enableVerboseLogging(verbose); 1440 mSupplicantStateTracker.enableVerboseLogging(verbose); 1441 mWifiQualifiedNetworkSelector.enableVerboseLogging(verbose); 1442 } 1443 1444 public void setHalBasedAutojoinOffload(int enabled) { 1445 // Shoult be used for debug only, triggered form developper settings 1446 // enabling HAl based PNO dynamically is not safe and not a normal operation 1447 mHalBasedPnoEnableInDevSettings = enabled > 0; 1448 mWifiConfigManager.enableHalBasedPno.set(mHalBasedPnoEnableInDevSettings); 1449 mWifiConfigManager.enableSsidWhitelist.set(mHalBasedPnoEnableInDevSettings); 1450 sendMessage(CMD_DISCONNECT); 1451 } 1452 1453 int getHalBasedAutojoinOffload() { 1454 return mHalBasedPnoEnableInDevSettings ? 1 : 0; 1455 } 1456 1457 boolean useHalBasedAutoJoinOffload() { 1458 // all three settings need to be true: 1459 // - developper settings switch 1460 // - driver support 1461 // - config option 1462 return mHalBasedPnoEnableInDevSettings 1463 && mHalBasedPnoDriverSupported 1464 && mWifiConfigManager.enableHalBasedPno.get(); 1465 } 1466 1467 boolean allowFullBandScanAndAssociated() { 1468 1469 if (!getEnableAutoJoinWhenAssociated()) { 1470 if (DBG) { 1471 Log.e(TAG, "allowFullBandScanAndAssociated: " 1472 + " enableAutoJoinWhenAssociated : disallow"); 1473 } 1474 return false; 1475 } 1476 1477 if (mWifiInfo.txSuccessRate > 1478 mWifiConfigManager.maxTxPacketForFullScans 1479 || mWifiInfo.rxSuccessRate > 1480 mWifiConfigManager.maxRxPacketForFullScans) { 1481 if (DBG) { 1482 Log.e(TAG, "allowFullBandScanAndAssociated: packet rate tx" 1483 + mWifiInfo.txSuccessRate + " rx " 1484 + mWifiInfo.rxSuccessRate 1485 + " allow scan with traffic " + getAllowScansWithTraffic()); 1486 } 1487 // Too much traffic at the interface, hence no full band scan 1488 if (getAllowScansWithTraffic() == 0) { 1489 return false; 1490 } 1491 } 1492 1493 if (getCurrentState() != mConnectedState) { 1494 if (DBG) { 1495 Log.e(TAG, "allowFullBandScanAndAssociated: getCurrentState() : disallow"); 1496 } 1497 return false; 1498 } 1499 1500 return true; 1501 } 1502 1503 long mLastScanPermissionUpdate = 0; 1504 boolean mConnectedModeGScanOffloadStarted = false; 1505 // Don't do a G-scan enable/re-enable cycle more than once within 20seconds 1506 // The function updateAssociatedScanPermission() can be called quite frequently, hence 1507 // we want to throttle the GScan Stop->Start transition 1508 static final long SCAN_PERMISSION_UPDATE_THROTTLE_MILLI = 20000; 1509 void updateAssociatedScanPermission() { 1510 1511 if (useHalBasedAutoJoinOffload()) { 1512 boolean allowed = allowFullBandScanAndAssociated(); 1513 1514 long now = System.currentTimeMillis(); 1515 if (mConnectedModeGScanOffloadStarted && !allowed) { 1516 if (DBG) { 1517 Log.e(TAG, " useHalBasedAutoJoinOffload stop offload"); 1518 } 1519 stopPnoOffload(); 1520 stopGScan(" useHalBasedAutoJoinOffload"); 1521 } 1522 if (!mConnectedModeGScanOffloadStarted && allowed) { 1523 if ((now - mLastScanPermissionUpdate) > SCAN_PERMISSION_UPDATE_THROTTLE_MILLI) { 1524 // Re-enable Gscan offload, this will trigger periodic scans and allow firmware 1525 // to look for 5GHz BSSIDs and better networks 1526 if (DBG) { 1527 Log.e(TAG, " useHalBasedAutoJoinOffload restart offload"); 1528 } 1529 startGScanConnectedModeOffload("updatePermission " 1530 + (now - mLastScanPermissionUpdate) + "ms"); 1531 mLastScanPermissionUpdate = now; 1532 } 1533 } 1534 } 1535 } 1536 1537 private int mAggressiveHandover = 0; 1538 1539 int getAggressiveHandover() { 1540 return mAggressiveHandover; 1541 } 1542 1543 void enableAggressiveHandover(int enabled) { 1544 mAggressiveHandover = enabled; 1545 } 1546 1547 public void clearANQPCache() { 1548 mWifiConfigManager.trimANQPCache(true); 1549 } 1550 1551 public void setAllowScansWithTraffic(int enabled) { 1552 mWifiConfigManager.alwaysEnableScansWhileAssociated.set(enabled); 1553 } 1554 1555 public int getAllowScansWithTraffic() { 1556 return mWifiConfigManager.alwaysEnableScansWhileAssociated.get(); 1557 } 1558 1559 public boolean enableAutoJoinWhenAssociated(boolean enabled) { 1560 boolean old_state = getEnableAutoJoinWhenAssociated(); 1561 mWifiConfigManager.enableAutoJoinWhenAssociated.set(enabled); 1562 if (!old_state && enabled && mScreenOn && getCurrentState() == mConnectedState) { 1563 startDelayedScan(mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get(), null, 1564 null); 1565 } 1566 return true; 1567 } 1568 1569 public boolean getEnableAutoJoinWhenAssociated() { 1570 return mWifiConfigManager.enableAutoJoinWhenAssociated.get(); 1571 } 1572 /* 1573 * 1574 * Framework scan control 1575 */ 1576 1577 private boolean mAlarmEnabled = false; 1578 1579 private AtomicInteger mDelayedScanCounter = new AtomicInteger(); 1580 1581 private void setScanAlarm(boolean enabled) { 1582 if (DBG) { 1583 String state; 1584 if (enabled) state = "enabled"; else state = "disabled"; 1585 logd("setScanAlarm " + state 1586 + " defaultperiod " + mDefaultFrameworkScanIntervalMs 1587 + " mBackgroundScanSupported " + mBackgroundScanSupported); 1588 } 1589 if (mBackgroundScanSupported == false) { 1590 // Scan alarm is only used for background scans if they are not 1591 // offloaded to the wifi chipset, hence enable the scan alarm 1592 // gicing us RTC_WAKEUP of backgroundScan is NOT supported 1593 enabled = true; 1594 } 1595 1596 if (enabled == mAlarmEnabled) return; 1597 if (enabled) { 1598 /* Set RTC_WAKEUP alarms if PNO is not supported - because no one is */ 1599 /* going to wake up the host processor to look for access points */ 1600 mAlarmManager.set(AlarmManager.RTC_WAKEUP, 1601 System.currentTimeMillis() + mDefaultFrameworkScanIntervalMs, 1602 mScanIntent); 1603 mAlarmEnabled = true; 1604 } else { 1605 mAlarmManager.cancel(mScanIntent); 1606 mAlarmEnabled = false; 1607 } 1608 } 1609 1610 private void cancelDelayedScan() { 1611 mDelayedScanCounter.incrementAndGet(); 1612 } 1613 1614 private boolean checkAndRestartDelayedScan(int counter, boolean restart, int milli, 1615 ScanSettings settings, WorkSource workSource) { 1616 1617 if (counter != mDelayedScanCounter.get()) { 1618 return false; 1619 } 1620 if (restart) 1621 startDelayedScan(milli, settings, workSource); 1622 return true; 1623 } 1624 1625 private void startDelayedScan(int milli, ScanSettings settings, WorkSource workSource) { 1626 if (milli <= 0) return; 1627 /** 1628 * The cases where the scan alarm should be run are : 1629 * - DisconnectedState && screenOn => used delayed timer 1630 * - DisconnectedState && !screenOn && mBackgroundScanSupported => PNO 1631 * - DisconnectedState && !screenOn && !mBackgroundScanSupported => used RTC_WAKEUP Alarm 1632 * - ConnectedState && screenOn => used delayed timer 1633 */ 1634 1635 mDelayedScanCounter.incrementAndGet(); 1636 if (mScreenOn && 1637 (getCurrentState() == mDisconnectedState 1638 || getCurrentState() == mConnectedState)) { 1639 Bundle bundle = new Bundle(); 1640 bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, settings); 1641 bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource); 1642 bundle.putLong(SCAN_REQUEST_TIME, System.currentTimeMillis()); 1643 sendMessageDelayed(CMD_START_SCAN, SCAN_ALARM_SOURCE, 1644 mDelayedScanCounter.get(), bundle, milli); 1645 if (DBG) logd("startDelayedScan send -> " + mDelayedScanCounter + " milli " + milli); 1646 } else if (mBackgroundScanSupported == false 1647 && !mScreenOn && getCurrentState() == mDisconnectedState) { 1648 setScanAlarm(true); 1649 if (DBG) logd("startDelayedScan start scan alarm -> " 1650 + mDelayedScanCounter + " milli " + milli); 1651 } else { 1652 if (DBG) logd("startDelayedScan unhandled -> " 1653 + mDelayedScanCounter + " milli " + milli); 1654 } 1655 } 1656 1657 private boolean setRandomMacOui() { 1658 String oui = mContext.getResources().getString(R.string.config_wifi_random_mac_oui); 1659 if (TextUtils.isEmpty(oui)) { 1660 oui = GOOGLE_OUI; 1661 } 1662 String[] ouiParts = oui.split("-"); 1663 byte[] ouiBytes = new byte[3]; 1664 ouiBytes[0] = (byte) (Integer.parseInt(ouiParts[0], 16) & 0xFF); 1665 ouiBytes[1] = (byte) (Integer.parseInt(ouiParts[1], 16) & 0xFF); 1666 ouiBytes[2] = (byte) (Integer.parseInt(ouiParts[2], 16) & 0xFF); 1667 1668 logd("Setting OUI to " + oui); 1669 return mWifiNative.setScanningMacOui(ouiBytes); 1670 } 1671 1672 /** 1673 * ****************************************************** 1674 * Methods exposed for public use 1675 * ****************************************************** 1676 */ 1677 1678 public Messenger getMessenger() { 1679 return new Messenger(getHandler()); 1680 } 1681 1682 /** 1683 * TODO: doc 1684 */ 1685 public boolean syncPingSupplicant(AsyncChannel channel) { 1686 Message resultMsg = channel.sendMessageSynchronously(CMD_PING_SUPPLICANT); 1687 boolean result = (resultMsg.arg1 != FAILURE); 1688 resultMsg.recycle(); 1689 return result; 1690 } 1691 1692 /** 1693 * When settings allowing making use of untrusted networks change, trigger a scan 1694 * so as to kick of autojoin. 1695 */ 1696 public void startScanForUntrustedSettingChange() { 1697 startScan(SET_ALLOW_UNTRUSTED_SOURCE, 0, null, null); 1698 } 1699 1700 /** 1701 * Initiate a wifi scan. If workSource is not null, blame is given to it, otherwise blame is 1702 * given to callingUid. 1703 * 1704 * @param callingUid The uid initiating the wifi scan. Blame will be given here unless 1705 * workSource is specified. 1706 * @param workSource If not null, blame is given to workSource. 1707 * @param settings Scan settings, see {@link ScanSettings}. 1708 */ 1709 public void startScan(int callingUid, int scanCounter, 1710 ScanSettings settings, WorkSource workSource) { 1711 Bundle bundle = new Bundle(); 1712 bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, settings); 1713 bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource); 1714 bundle.putLong(SCAN_REQUEST_TIME, System.currentTimeMillis()); 1715 sendMessage(CMD_START_SCAN, callingUid, scanCounter, bundle); 1716 } 1717 1718 // called from BroadcastListener 1719 1720 /** 1721 * Start reading new scan data 1722 * Data comes in as: 1723 * "scancount=5\n" 1724 * "nextcount=5\n" 1725 * "apcount=3\n" 1726 * "trunc\n" (optional) 1727 * "bssid=...\n" 1728 * "ssid=...\n" 1729 * "freq=...\n" (in Mhz) 1730 * "level=...\n" 1731 * "dist=...\n" (in cm) 1732 * "distsd=...\n" (standard deviation, in cm) 1733 * "====" 1734 * "bssid=...\n" 1735 * etc 1736 * "====" 1737 * "bssid=...\n" 1738 * etc 1739 * "%%%%" 1740 * "apcount=2\n" 1741 * "bssid=...\n" 1742 * etc 1743 * "%%%% 1744 * etc 1745 * "----" 1746 */ 1747 private final static boolean DEBUG_PARSE = false; 1748 1749 private long mDisconnectedTimeStamp = 0; 1750 1751 public long getDisconnectedTimeMilli() { 1752 if (getCurrentState() == mDisconnectedState 1753 && mDisconnectedTimeStamp != 0) { 1754 long now_ms = System.currentTimeMillis(); 1755 return now_ms - mDisconnectedTimeStamp; 1756 } 1757 return 0; 1758 } 1759 1760 // Keeping track of scan requests 1761 private long lastStartScanTimeStamp = 0; 1762 private long lastScanDuration = 0; 1763 // Last connect attempt is used to prevent scan requests: 1764 // - for a period of 10 seconds after attempting to connect 1765 private long lastConnectAttemptTimestamp = 0; 1766 private Set<Integer> lastScanFreqs = null; 1767 1768 // For debugging, keep track of last message status handling 1769 // TODO, find an equivalent mechanism as part of parent class 1770 private static int MESSAGE_HANDLING_STATUS_PROCESSED = 2; 1771 private static int MESSAGE_HANDLING_STATUS_OK = 1; 1772 private static int MESSAGE_HANDLING_STATUS_UNKNOWN = 0; 1773 private static int MESSAGE_HANDLING_STATUS_REFUSED = -1; 1774 private static int MESSAGE_HANDLING_STATUS_FAIL = -2; 1775 private static int MESSAGE_HANDLING_STATUS_OBSOLETE = -3; 1776 private static int MESSAGE_HANDLING_STATUS_DEFERRED = -4; 1777 private static int MESSAGE_HANDLING_STATUS_DISCARD = -5; 1778 private static int MESSAGE_HANDLING_STATUS_LOOPED = -6; 1779 private static int MESSAGE_HANDLING_STATUS_HANDLING_ERROR = -7; 1780 1781 private int messageHandlingStatus = 0; 1782 1783 //TODO: this is used only to track connection attempts, however the link state and packet per 1784 //TODO: second logic should be folded into that 1785 private boolean checkOrDeferScanAllowed(Message msg) { 1786 long now = System.currentTimeMillis(); 1787 if (lastConnectAttemptTimestamp != 0 && (now - lastConnectAttemptTimestamp) < 10000) { 1788 Message dmsg = Message.obtain(msg); 1789 sendMessageDelayed(dmsg, 11000 - (now - lastConnectAttemptTimestamp)); 1790 return false; 1791 } 1792 return true; 1793 } 1794 1795 private int mOnTime = 0; 1796 private int mTxTime = 0; 1797 private int mRxTime = 0; 1798 private int mOnTimeStartScan = 0; 1799 private int mTxTimeStartScan = 0; 1800 private int mRxTimeStartScan = 0; 1801 private int mOnTimeScan = 0; 1802 private int mTxTimeScan = 0; 1803 private int mRxTimeScan = 0; 1804 private int mOnTimeThisScan = 0; 1805 private int mTxTimeThisScan = 0; 1806 private int mRxTimeThisScan = 0; 1807 1808 private int mOnTimeScreenStateChange = 0; 1809 private long lastOntimeReportTimeStamp = 0; 1810 private long lastScreenStateChangeTimeStamp = 0; 1811 private int mOnTimeLastReport = 0; 1812 private int mTxTimeLastReport = 0; 1813 private int mRxTimeLastReport = 0; 1814 1815 private long lastLinkLayerStatsUpdate = 0; 1816 1817 String reportOnTime() { 1818 long now = System.currentTimeMillis(); 1819 StringBuilder sb = new StringBuilder(); 1820 // Report stats since last report 1821 int on = mOnTime - mOnTimeLastReport; 1822 mOnTimeLastReport = mOnTime; 1823 int tx = mTxTime - mTxTimeLastReport; 1824 mTxTimeLastReport = mTxTime; 1825 int rx = mRxTime - mRxTimeLastReport; 1826 mRxTimeLastReport = mRxTime; 1827 int period = (int) (now - lastOntimeReportTimeStamp); 1828 lastOntimeReportTimeStamp = now; 1829 sb.append(String.format("[on:%d tx:%d rx:%d period:%d]", on, tx, rx, period)); 1830 // Report stats since Screen State Changed 1831 on = mOnTime - mOnTimeScreenStateChange; 1832 period = (int) (now - lastScreenStateChangeTimeStamp); 1833 sb.append(String.format(" from screen [on:%d period:%d]", on, period)); 1834 return sb.toString(); 1835 } 1836 1837 WifiLinkLayerStats getWifiLinkLayerStats(boolean dbg) { 1838 WifiLinkLayerStats stats = null; 1839 if (mWifiLinkLayerStatsSupported > 0) { 1840 String name = "wlan0"; 1841 stats = mWifiNative.getWifiLinkLayerStats(name); 1842 if (name != null && stats == null && mWifiLinkLayerStatsSupported > 0) { 1843 mWifiLinkLayerStatsSupported -= 1; 1844 } else if (stats != null) { 1845 lastLinkLayerStatsUpdate = System.currentTimeMillis(); 1846 mOnTime = stats.on_time; 1847 mTxTime = stats.tx_time; 1848 mRxTime = stats.rx_time; 1849 mRunningBeaconCount = stats.beacon_rx; 1850 } 1851 } 1852 if (stats == null || mWifiLinkLayerStatsSupported <= 0) { 1853 long mTxPkts = mFacade.getTxPackets(mInterfaceName); 1854 long mRxPkts = mFacade.getRxPackets(mInterfaceName); 1855 mWifiInfo.updatePacketRates(mTxPkts, mRxPkts); 1856 } else { 1857 mWifiInfo.updatePacketRates(stats); 1858 } 1859 if (useHalBasedAutoJoinOffload()) { 1860 sendMessage(CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION); 1861 } 1862 return stats; 1863 } 1864 1865 void startRadioScanStats() { 1866 WifiLinkLayerStats stats = getWifiLinkLayerStats(false); 1867 if (stats != null) { 1868 mOnTimeStartScan = stats.on_time; 1869 mTxTimeStartScan = stats.tx_time; 1870 mRxTimeStartScan = stats.rx_time; 1871 mOnTime = stats.on_time; 1872 mTxTime = stats.tx_time; 1873 mRxTime = stats.rx_time; 1874 } 1875 } 1876 1877 void closeRadioScanStats() { 1878 WifiLinkLayerStats stats = getWifiLinkLayerStats(false); 1879 if (stats != null) { 1880 mOnTimeThisScan = stats.on_time - mOnTimeStartScan; 1881 mTxTimeThisScan = stats.tx_time - mTxTimeStartScan; 1882 mRxTimeThisScan = stats.rx_time - mRxTimeStartScan; 1883 mOnTimeScan += mOnTimeThisScan; 1884 mTxTimeScan += mTxTimeThisScan; 1885 mRxTimeScan += mRxTimeThisScan; 1886 } 1887 } 1888 1889 int startWifiIPPacketOffload(int slot, KeepalivePacketData packetData, int intervalSeconds) { 1890 int ret = mWifiNative.startSendingOffloadedPacket(slot, packetData, intervalSeconds * 1000); 1891 if (ret != 0) { 1892 loge("startWifiIPPacketOffload(" + slot + ", " + intervalSeconds + 1893 "): hardware error " + ret); 1894 return ConnectivityManager.PacketKeepalive.ERROR_HARDWARE_ERROR; 1895 } else { 1896 return ConnectivityManager.PacketKeepalive.SUCCESS; 1897 } 1898 } 1899 1900 int stopWifiIPPacketOffload(int slot) { 1901 int ret = mWifiNative.stopSendingOffloadedPacket(slot); 1902 if (ret != 0) { 1903 loge("stopWifiIPPacketOffload(" + slot + "): hardware error " + ret); 1904 return ConnectivityManager.PacketKeepalive.ERROR_HARDWARE_ERROR; 1905 } else { 1906 return ConnectivityManager.PacketKeepalive.SUCCESS; 1907 } 1908 } 1909 1910 int startRssiMonitoringOffload(byte maxRssi, byte minRssi) { 1911 return mWifiNative.startRssiMonitoring(maxRssi, minRssi, WifiStateMachine.this); 1912 } 1913 1914 int stopRssiMonitoringOffload() { 1915 return mWifiNative.stopRssiMonitoring(); 1916 } 1917 1918 // If workSource is not null, blame is given to it, otherwise blame is given to callingUid. 1919 private void noteScanStart(int callingUid, WorkSource workSource) { 1920 if (lastStartScanTimeStamp != 0) { 1921 noteScanEnd(); 1922 } 1923 long now = System.currentTimeMillis(); 1924 lastStartScanTimeStamp = now; 1925 lastScanDuration = 0; 1926 if (DBG) { 1927 String ts = String.format("[%,d ms]", now); 1928 if (workSource != null) { 1929 if (DBG) logd(ts + " noteScanStart" + workSource.toString() 1930 + " uid " + Integer.toString(callingUid)); 1931 } else { 1932 if (DBG) logd(ts + " noteScanstart no scan source" 1933 + " uid " + Integer.toString(callingUid)); 1934 } 1935 } 1936 startRadioScanStats(); 1937 if (mScanWorkSource == null && ((callingUid != UNKNOWN_SCAN_SOURCE 1938 && callingUid != SCAN_ALARM_SOURCE) 1939 || workSource != null)) { 1940 mScanWorkSource = workSource != null ? workSource : new WorkSource(callingUid); 1941 1942 if (mScanWorkSource.size() == 1 && mScanWorkSource.get(0) < 0) { 1943 // WiFi uses negative UIDs to mean special things. BatteryStats don't care! 1944 mScanWorkSource = new WorkSource(Process.WIFI_UID); 1945 } 1946 1947 try { 1948 mBatteryStats.noteWifiScanStartedFromSource(mScanWorkSource); 1949 } catch (RemoteException e) { 1950 log(e.toString()); 1951 } 1952 } 1953 } 1954 1955 private void noteScanEnd() { 1956 closeRadioScanStats(); 1957 long now = System.currentTimeMillis(); 1958 if (lastStartScanTimeStamp != 0) { 1959 lastScanDuration = now - lastStartScanTimeStamp; 1960 } 1961 lastStartScanTimeStamp = 0; 1962 if (DBG) { 1963 String ts = String.format("[%,d ms]", now); 1964 if (mScanWorkSource != null) 1965 logd(ts + " noteScanEnd " + mScanWorkSource.toString() 1966 + " onTime=" + mOnTimeThisScan); 1967 else 1968 logd(ts + " noteScanEnd no scan source" 1969 + " onTime=" + mOnTimeThisScan); 1970 } 1971 if (mScanWorkSource != null) { 1972 try { 1973 mBatteryStats.noteWifiScanStoppedFromSource(mScanWorkSource); 1974 } catch (RemoteException e) { 1975 log(e.toString()); 1976 } finally { 1977 mScanWorkSource = null; 1978 } 1979 } 1980 } 1981 1982 private void handleScanRequest(Message message) { 1983 ScanSettings settings = null; 1984 WorkSource workSource = null; 1985 1986 // unbundle parameters 1987 Bundle bundle = (Bundle) message.obj; 1988 1989 if (bundle != null) { 1990 settings = bundle.getParcelable(CUSTOMIZED_SCAN_SETTING); 1991 workSource = bundle.getParcelable(CUSTOMIZED_SCAN_WORKSOURCE); 1992 } 1993 1994 Set<Integer> freqs = null; 1995 if (settings != null && settings.channelSet != null) { 1996 freqs = new HashSet<Integer>(); 1997 for (WifiChannel channel : settings.channelSet) { 1998 freqs.add(channel.freqMHz); 1999 } 2000 } 2001 2002 // Retrieve the list of hidden networkId's to scan for. 2003 Set<Integer> hiddenNetworkIds = mWifiConfigManager.getHiddenConfiguredNetworkIds(); 2004 2005 // call wifi native to start the scan 2006 if (startScanNative(freqs, hiddenNetworkIds, workSource)) { 2007 // only count battery consumption if scan request is accepted 2008 noteScanStart(message.arg1, workSource); 2009 // a full scan covers everything, clearing scan request buffer 2010 if (freqs == null) 2011 mBufferedScanMsg.clear(); 2012 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; 2013 if (workSource != null) { 2014 // External worksource was passed along the scan request, 2015 // hence always send a broadcast 2016 mSendScanResultsBroadcast = true; 2017 } 2018 return; 2019 } 2020 2021 // if reach here, scan request is rejected 2022 2023 if (!mIsScanOngoing) { 2024 // if rejection is NOT due to ongoing scan (e.g. bad scan parameters), 2025 2026 // discard this request and pop up the next one 2027 if (mBufferedScanMsg.size() > 0) { 2028 sendMessage(mBufferedScanMsg.remove()); 2029 } 2030 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 2031 } else if (!mIsFullScanOngoing) { 2032 // if rejection is due to an ongoing scan, and the ongoing one is NOT a full scan, 2033 // buffer the scan request to make sure specified channels will be scanned eventually 2034 if (freqs == null) 2035 mBufferedScanMsg.clear(); 2036 if (mBufferedScanMsg.size() < SCAN_REQUEST_BUFFER_MAX_SIZE) { 2037 Message msg = obtainMessage(CMD_START_SCAN, 2038 message.arg1, message.arg2, bundle); 2039 mBufferedScanMsg.add(msg); 2040 } else { 2041 // if too many requests in buffer, combine them into a single full scan 2042 bundle = new Bundle(); 2043 bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, null); 2044 bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource); 2045 Message msg = obtainMessage(CMD_START_SCAN, message.arg1, message.arg2, bundle); 2046 mBufferedScanMsg.clear(); 2047 mBufferedScanMsg.add(msg); 2048 } 2049 messageHandlingStatus = MESSAGE_HANDLING_STATUS_LOOPED; 2050 } else { 2051 // mIsScanOngoing and mIsFullScanOngoing 2052 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 2053 } 2054 } 2055 2056 2057 // TODO this is a temporary measure to bridge between WifiScanner and WifiStateMachine until 2058 // scan functionality is refactored out of WifiStateMachine. 2059 /** 2060 * return true iff scan request is accepted 2061 */ 2062 private boolean startScanNative(final Set<Integer> freqs, Set<Integer> hiddenNetworkIds, 2063 WorkSource workSource) { 2064 WifiScanner.ScanSettings settings = new WifiScanner.ScanSettings(); 2065 if (freqs == null) { 2066 settings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS; 2067 } else { 2068 settings.band = WifiScanner.WIFI_BAND_UNSPECIFIED; 2069 int index = 0; 2070 settings.channels = new WifiScanner.ChannelSpec[freqs.size()]; 2071 for (Integer freq : freqs) { 2072 settings.channels[index++] = new WifiScanner.ChannelSpec(freq); 2073 } 2074 } 2075 settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 2076 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT; 2077 if (hiddenNetworkIds != null && hiddenNetworkIds.size() > 0) { 2078 int i = 0; 2079 settings.hiddenNetworkIds = new int[hiddenNetworkIds.size()]; 2080 for (Integer netId : hiddenNetworkIds) { 2081 settings.hiddenNetworkIds[i++] = netId; 2082 } 2083 } 2084 WifiScanner.ScanListener nativeScanListener = new WifiScanner.ScanListener() { 2085 // ignore all events since WifiStateMachine is registered for the supplicant events 2086 public void onSuccess() { 2087 } 2088 public void onFailure(int reason, String description) { 2089 mIsScanOngoing = false; 2090 mIsFullScanOngoing = false; 2091 } 2092 public void onResults(WifiScanner.ScanData[] results) { 2093 } 2094 public void onFullResult(ScanResult fullScanResult) { 2095 } 2096 public void onPeriodChanged(int periodInMs) { 2097 } 2098 }; 2099 mWifiScanner.startScan(settings, nativeScanListener, workSource); 2100 mIsScanOngoing = true; 2101 mIsFullScanOngoing = (freqs == null); 2102 lastScanFreqs = freqs; 2103 return true; 2104 } 2105 2106 /** 2107 * TODO: doc 2108 */ 2109 public void setSupplicantRunning(boolean enable) { 2110 if (enable) { 2111 sendMessage(CMD_START_SUPPLICANT); 2112 } else { 2113 sendMessage(CMD_STOP_SUPPLICANT); 2114 } 2115 } 2116 2117 /** 2118 * TODO: doc 2119 */ 2120 public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) { 2121 if (enable) { 2122 sendMessage(CMD_START_AP, wifiConfig); 2123 } else { 2124 sendMessage(CMD_STOP_AP); 2125 } 2126 } 2127 2128 public void setWifiApConfiguration(WifiConfiguration config) { 2129 mWifiApConfigStore.setApConfiguration(config); 2130 } 2131 2132 public WifiConfiguration syncGetWifiApConfiguration() { 2133 return mWifiApConfigStore.getApConfiguration(); 2134 } 2135 2136 /** 2137 * TODO: doc 2138 */ 2139 public int syncGetWifiState() { 2140 return mWifiState.get(); 2141 } 2142 2143 /** 2144 * TODO: doc 2145 */ 2146 public String syncGetWifiStateByName() { 2147 switch (mWifiState.get()) { 2148 case WIFI_STATE_DISABLING: 2149 return "disabling"; 2150 case WIFI_STATE_DISABLED: 2151 return "disabled"; 2152 case WIFI_STATE_ENABLING: 2153 return "enabling"; 2154 case WIFI_STATE_ENABLED: 2155 return "enabled"; 2156 case WIFI_STATE_UNKNOWN: 2157 return "unknown state"; 2158 default: 2159 return "[invalid state]"; 2160 } 2161 } 2162 2163 /** 2164 * TODO: doc 2165 */ 2166 public int syncGetWifiApState() { 2167 return mWifiApState.get(); 2168 } 2169 2170 /** 2171 * TODO: doc 2172 */ 2173 public String syncGetWifiApStateByName() { 2174 switch (mWifiApState.get()) { 2175 case WIFI_AP_STATE_DISABLING: 2176 return "disabling"; 2177 case WIFI_AP_STATE_DISABLED: 2178 return "disabled"; 2179 case WIFI_AP_STATE_ENABLING: 2180 return "enabling"; 2181 case WIFI_AP_STATE_ENABLED: 2182 return "enabled"; 2183 case WIFI_AP_STATE_FAILED: 2184 return "failed"; 2185 default: 2186 return "[invalid state]"; 2187 } 2188 } 2189 2190 public boolean isConnected() { 2191 return getCurrentState() == mConnectedState; 2192 } 2193 2194 public boolean isDisconnected() { 2195 return getCurrentState() == mDisconnectedState; 2196 } 2197 2198 public boolean isSupplicantTransientState() { 2199 SupplicantState SupplicantState = mWifiInfo.getSupplicantState(); 2200 if (SupplicantState == SupplicantState.ASSOCIATING 2201 || SupplicantState == SupplicantState.AUTHENTICATING 2202 || SupplicantState == SupplicantState.FOUR_WAY_HANDSHAKE 2203 || SupplicantState == SupplicantState.GROUP_HANDSHAKE) { 2204 2205 if (DBG) { 2206 Log.d(TAG, "Supplicant is under transient state: " + SupplicantState); 2207 } 2208 return true; 2209 } else { 2210 if (DBG) { 2211 Log.d(TAG, "Supplicant is under steady state: " + SupplicantState); 2212 } 2213 } 2214 2215 return false; 2216 } 2217 2218 /** 2219 * Get status information for the current connection, if any. 2220 * 2221 * @return a {@link WifiInfo} object containing information about the current connection 2222 */ 2223 public WifiInfo syncRequestConnectionInfo() { 2224 return getWiFiInfoForUid(Binder.getCallingUid()); 2225 } 2226 2227 public WifiInfo getWifiInfo() { 2228 return mWifiInfo; 2229 } 2230 2231 public DhcpResults syncGetDhcpResults() { 2232 synchronized (mDhcpResultsLock) { 2233 return new DhcpResults(mDhcpResults); 2234 } 2235 } 2236 2237 /** 2238 * TODO: doc 2239 */ 2240 public void setDriverStart(boolean enable) { 2241 if (enable) { 2242 sendMessage(CMD_START_DRIVER); 2243 } else { 2244 sendMessage(CMD_STOP_DRIVER); 2245 } 2246 } 2247 2248 /** 2249 * TODO: doc 2250 */ 2251 public void setOperationalMode(int mode) { 2252 if (DBG) log("setting operational mode to " + String.valueOf(mode)); 2253 sendMessage(CMD_SET_OPERATIONAL_MODE, mode, 0); 2254 } 2255 2256 /** 2257 * TODO: doc 2258 */ 2259 public List<ScanResult> syncGetScanResultsList() { 2260 synchronized (mScanResultsLock) { 2261 List<ScanResult> scanList = new ArrayList<ScanResult>(); 2262 for (ScanDetail result : mScanResults) { 2263 scanList.add(new ScanResult(result.getScanResult())); 2264 } 2265 return scanList; 2266 } 2267 } 2268 2269 public int syncAddPasspointManagementObject(AsyncChannel channel, String managementObject) { 2270 Message resultMsg = 2271 channel.sendMessageSynchronously(CMD_ADD_PASSPOINT_MO, managementObject); 2272 int result = resultMsg.arg1; 2273 resultMsg.recycle(); 2274 return result; 2275 } 2276 2277 public int syncModifyPasspointManagementObject(AsyncChannel channel, String fqdn, 2278 List<PasspointManagementObjectDefinition> 2279 managementObjectDefinitions) { 2280 Bundle bundle = new Bundle(); 2281 bundle.putString("FQDN", fqdn); 2282 bundle.putParcelableList("MOS", managementObjectDefinitions); 2283 Message resultMsg = channel.sendMessageSynchronously(CMD_MODIFY_PASSPOINT_MO, bundle); 2284 int result = resultMsg.arg1; 2285 resultMsg.recycle(); 2286 return result; 2287 } 2288 2289 public boolean syncQueryPasspointIcon(AsyncChannel channel, long bssid, String fileName) { 2290 Bundle bundle = new Bundle(); 2291 bundle.putLong("BSSID", bssid); 2292 bundle.putString("FILENAME", fileName); 2293 Message resultMsg = channel.sendMessageSynchronously(CMD_QUERY_OSU_ICON, bundle); 2294 int result = resultMsg.arg1; 2295 resultMsg.recycle(); 2296 return result == 1; 2297 } 2298 2299 public int matchProviderWithCurrentNetwork(AsyncChannel channel, String fqdn) { 2300 Message resultMsg = channel.sendMessageSynchronously(CMD_MATCH_PROVIDER_NETWORK, fqdn); 2301 int result = resultMsg.arg1; 2302 resultMsg.recycle(); 2303 return result; 2304 } 2305 2306 /** 2307 * Deauthenticate and set the re-authentication hold off time for the current network 2308 * @param holdoff hold off time in milliseconds 2309 * @param ess set if the hold off pertains to an ESS rather than a BSS 2310 */ 2311 public void deauthenticateNetwork(AsyncChannel channel, long holdoff, boolean ess) { 2312 // TODO: This needs an implementation 2313 } 2314 2315 public void disableEphemeralNetwork(String SSID) { 2316 if (SSID != null) { 2317 sendMessage(CMD_DISABLE_EPHEMERAL_NETWORK, SSID); 2318 } 2319 } 2320 2321 /** 2322 * Get unsynchronized pointer to scan result list 2323 * Can be called only from AutoJoinController which runs in the WifiStateMachine context 2324 */ 2325 public List<ScanDetail> getScanResultsListNoCopyUnsync() { 2326 return mScanResults; 2327 } 2328 2329 /** 2330 * Disconnect from Access Point 2331 */ 2332 public void disconnectCommand() { 2333 sendMessage(CMD_DISCONNECT); 2334 } 2335 2336 public void disconnectCommand(int uid, int reason) { 2337 sendMessage(CMD_DISCONNECT, uid, reason); 2338 } 2339 2340 /** 2341 * Initiate a reconnection to AP 2342 */ 2343 public void reconnectCommand() { 2344 sendMessage(CMD_RECONNECT); 2345 } 2346 2347 /** 2348 * Initiate a re-association to AP 2349 */ 2350 public void reassociateCommand() { 2351 sendMessage(CMD_REASSOCIATE); 2352 } 2353 2354 /** 2355 * Reload networks and then reconnect; helps load correct data for TLS networks 2356 */ 2357 2358 public void reloadTlsNetworksAndReconnect() { 2359 sendMessage(CMD_RELOAD_TLS_AND_RECONNECT); 2360 } 2361 2362 /** 2363 * Add a network synchronously 2364 * 2365 * @return network id of the new network 2366 */ 2367 public int syncAddOrUpdateNetwork(AsyncChannel channel, WifiConfiguration config) { 2368 Message resultMsg = channel.sendMessageSynchronously(CMD_ADD_OR_UPDATE_NETWORK, config); 2369 int result = resultMsg.arg1; 2370 resultMsg.recycle(); 2371 return result; 2372 } 2373 2374 /** 2375 * Get configured networks synchronously 2376 * 2377 * @param channel 2378 * @return 2379 */ 2380 2381 public List<WifiConfiguration> syncGetConfiguredNetworks(int uuid, AsyncChannel channel) { 2382 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONFIGURED_NETWORKS, uuid); 2383 List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj; 2384 resultMsg.recycle(); 2385 return result; 2386 } 2387 2388 public List<WifiConfiguration> syncGetPrivilegedConfiguredNetwork(AsyncChannel channel) { 2389 Message resultMsg = channel.sendMessageSynchronously( 2390 CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS); 2391 List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj; 2392 resultMsg.recycle(); 2393 return result; 2394 } 2395 2396 public WifiConfiguration syncGetMatchingWifiConfig(ScanResult scanResult, AsyncChannel channel) { 2397 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_MATCHING_CONFIG, scanResult); 2398 return (WifiConfiguration) resultMsg.obj; 2399 } 2400 2401 /** 2402 * Get connection statistics synchronously 2403 * 2404 * @param channel 2405 * @return 2406 */ 2407 2408 public WifiConnectionStatistics syncGetConnectionStatistics(AsyncChannel channel) { 2409 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONNECTION_STATISTICS); 2410 WifiConnectionStatistics result = (WifiConnectionStatistics) resultMsg.obj; 2411 resultMsg.recycle(); 2412 return result; 2413 } 2414 2415 /** 2416 * Get adaptors synchronously 2417 */ 2418 2419 public int syncGetSupportedFeatures(AsyncChannel channel) { 2420 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_SUPPORTED_FEATURES); 2421 int supportedFeatureSet = resultMsg.arg1; 2422 resultMsg.recycle(); 2423 return supportedFeatureSet; 2424 } 2425 2426 /** 2427 * Get link layers stats for adapter synchronously 2428 */ 2429 public WifiLinkLayerStats syncGetLinkLayerStats(AsyncChannel channel) { 2430 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_LINK_LAYER_STATS); 2431 WifiLinkLayerStats result = (WifiLinkLayerStats) resultMsg.obj; 2432 resultMsg.recycle(); 2433 return result; 2434 } 2435 2436 /** 2437 * Delete a network 2438 * 2439 * @param networkId id of the network to be removed 2440 */ 2441 public boolean syncRemoveNetwork(AsyncChannel channel, int networkId) { 2442 Message resultMsg = channel.sendMessageSynchronously(CMD_REMOVE_NETWORK, networkId); 2443 boolean result = (resultMsg.arg1 != FAILURE); 2444 resultMsg.recycle(); 2445 return result; 2446 } 2447 2448 /** 2449 * Enable a network 2450 * 2451 * @param netId network id of the network 2452 * @param disableOthers true, if all other networks have to be disabled 2453 * @return {@code true} if the operation succeeds, {@code false} otherwise 2454 */ 2455 public boolean syncEnableNetwork(AsyncChannel channel, int netId, boolean disableOthers) { 2456 Message resultMsg = channel.sendMessageSynchronously(CMD_ENABLE_NETWORK, netId, 2457 disableOthers ? 1 : 0); 2458 boolean result = (resultMsg.arg1 != FAILURE); 2459 resultMsg.recycle(); 2460 return result; 2461 } 2462 2463 /** 2464 * Disable a network 2465 * 2466 * @param netId network id of the network 2467 * @return {@code true} if the operation succeeds, {@code false} otherwise 2468 */ 2469 public boolean syncDisableNetwork(AsyncChannel channel, int netId) { 2470 Message resultMsg = channel.sendMessageSynchronously(WifiManager.DISABLE_NETWORK, netId); 2471 boolean result = (resultMsg.arg1 != WifiManager.DISABLE_NETWORK_FAILED); 2472 resultMsg.recycle(); 2473 return result; 2474 } 2475 2476 /** 2477 * Retrieves a WPS-NFC configuration token for the specified network 2478 * 2479 * @return a hex string representation of the WPS-NFC configuration token 2480 */ 2481 public String syncGetWpsNfcConfigurationToken(int netId) { 2482 return mWifiNative.getNfcWpsConfigurationToken(netId); 2483 } 2484 2485 /** 2486 * Convert WifiScanner.PnoNetwork List to WifiNative.PnoNetwork List 2487 * TODO(rpius): Remove this once WifiScanner starts PNO scanning. 2488 */ 2489 private List<WifiNative.PnoNetwork> convertPnoNetworkListToNative( 2490 List<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList) { 2491 List<WifiNative.PnoNetwork> nativePnoNetworkList = new ArrayList<>(); 2492 for (WifiScanner.PnoSettings.PnoNetwork pnoNetwork : pnoNetworkList) { 2493 WifiNative.PnoNetwork nativePnoNetwork = new WifiNative.PnoNetwork(); 2494 nativePnoNetwork.ssid = pnoNetwork.ssid; 2495 nativePnoNetwork.networkId = pnoNetwork.networkId; 2496 nativePnoNetwork.priority = pnoNetwork.priority; 2497 nativePnoNetwork.flags = pnoNetwork.flags; 2498 nativePnoNetwork.auth_bit_field = pnoNetwork.authBitField; 2499 nativePnoNetworkList.add(nativePnoNetwork); 2500 } 2501 return nativePnoNetworkList; 2502 } 2503 2504 void enableBackgroundScan(boolean enable) { 2505 if (enable) { 2506 mWifiConfigManager.enableAllNetworks(); 2507 // Now enable all the networks in wpa_supplicant. These will be 2508 // disabled when we connect to a network after PNO. 2509 mWifiConfigManager.enableAllNetworksNative(); 2510 } 2511 List<WifiScanner.PnoSettings.PnoNetwork> pnoList = 2512 mWifiConfigManager.retrieveDisconnectedPnoNetworkList(enable); 2513 boolean ret = 2514 mWifiNative.enableBackgroundScan(enable, convertPnoNetworkListToNative(pnoList)); 2515 if (ret) { 2516 mLegacyPnoEnabled = enable; 2517 } else { 2518 Log.e(TAG, " Fail to set up pno, want " + enable + " now " + mLegacyPnoEnabled); 2519 } 2520 } 2521 2522 /** 2523 * Blacklist a BSSID. This will avoid the AP if there are 2524 * alternate APs to connect 2525 * 2526 * @param bssid BSSID of the network 2527 */ 2528 public void addToBlacklist(String bssid) { 2529 sendMessage(CMD_BLACKLIST_NETWORK, bssid); 2530 } 2531 2532 /** 2533 * Clear the blacklist list 2534 */ 2535 public void clearBlacklist() { 2536 sendMessage(CMD_CLEAR_BLACKLIST); 2537 } 2538 2539 public void enableRssiPolling(boolean enabled) { 2540 sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0); 2541 } 2542 2543 public void enableAllNetworks() { 2544 sendMessage(CMD_ENABLE_ALL_NETWORKS); 2545 } 2546 2547 /** 2548 * Start filtering Multicast v4 packets 2549 */ 2550 public void startFilteringMulticastV4Packets() { 2551 mFilteringMulticastV4Packets.set(true); 2552 sendMessage(CMD_START_PACKET_FILTERING, MULTICAST_V4, 0); 2553 } 2554 2555 /** 2556 * Stop filtering Multicast v4 packets 2557 */ 2558 public void stopFilteringMulticastV4Packets() { 2559 mFilteringMulticastV4Packets.set(false); 2560 sendMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V4, 0); 2561 } 2562 2563 /** 2564 * Start filtering Multicast v4 packets 2565 */ 2566 public void startFilteringMulticastV6Packets() { 2567 sendMessage(CMD_START_PACKET_FILTERING, MULTICAST_V6, 0); 2568 } 2569 2570 /** 2571 * Stop filtering Multicast v4 packets 2572 */ 2573 public void stopFilteringMulticastV6Packets() { 2574 sendMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V6, 0); 2575 } 2576 2577 /** 2578 * Set high performance mode of operation. 2579 * Enabling would set active power mode and disable suspend optimizations; 2580 * disabling would set auto power mode and enable suspend optimizations 2581 * 2582 * @param enable true if enable, false otherwise 2583 */ 2584 public void setHighPerfModeEnabled(boolean enable) { 2585 sendMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0); 2586 } 2587 2588 2589 /** 2590 * reset cached SIM credential data 2591 */ 2592 public synchronized void resetSimAuthNetworks() { 2593 sendMessage(CMD_RESET_SIM_NETWORKS); 2594 } 2595 2596 /** 2597 * Get Network object of current wifi network 2598 * @return Network object of current wifi network 2599 */ 2600 public Network getCurrentNetwork() { 2601 if (mNetworkAgent != null) { 2602 return new Network(mNetworkAgent.netId); 2603 } else { 2604 return null; 2605 } 2606 } 2607 2608 2609 /** 2610 * Set the operational frequency band 2611 * 2612 * @param band 2613 * @param persist {@code true} if the setting should be remembered. 2614 */ 2615 public void setFrequencyBand(int band, boolean persist) { 2616 if (persist) { 2617 Settings.Global.putInt(mContext.getContentResolver(), 2618 Settings.Global.WIFI_FREQUENCY_BAND, 2619 band); 2620 } 2621 sendMessage(CMD_SET_FREQUENCY_BAND, band, 0); 2622 } 2623 2624 /** 2625 * Enable TDLS for a specific MAC address 2626 */ 2627 public void enableTdls(String remoteMacAddress, boolean enable) { 2628 int enabler = enable ? 1 : 0; 2629 sendMessage(CMD_ENABLE_TDLS, enabler, 0, remoteMacAddress); 2630 } 2631 2632 /** 2633 * Returns the operational frequency band 2634 */ 2635 public int getFrequencyBand() { 2636 return mFrequencyBand.get(); 2637 } 2638 2639 /** 2640 * Returns the wifi configuration file 2641 */ 2642 public String getConfigFile() { 2643 return mWifiConfigManager.getConfigFile(); 2644 } 2645 2646 /** 2647 * Send a message indicating bluetooth adapter connection state changed 2648 */ 2649 public void sendBluetoothAdapterStateChange(int state) { 2650 sendMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0); 2651 } 2652 2653 /** 2654 * Send a message indicating a package has been uninstalled. 2655 */ 2656 public void removeAppConfigs(String packageName, int uid) { 2657 // Build partial AppInfo manually - package may not exist in database any more 2658 ApplicationInfo ai = new ApplicationInfo(); 2659 ai.packageName = packageName; 2660 ai.uid = uid; 2661 sendMessage(CMD_REMOVE_APP_CONFIGURATIONS, ai); 2662 } 2663 2664 /** 2665 * Send a message indicating a user has been removed. 2666 */ 2667 public void removeUserConfigs(int userId) { 2668 sendMessage(CMD_REMOVE_USER_CONFIGURATIONS, userId); 2669 } 2670 2671 /** 2672 * Save configuration on supplicant 2673 * 2674 * @return {@code true} if the operation succeeds, {@code false} otherwise 2675 * <p/> 2676 * TODO: deprecate this 2677 */ 2678 public boolean syncSaveConfig(AsyncChannel channel) { 2679 Message resultMsg = channel.sendMessageSynchronously(CMD_SAVE_CONFIG); 2680 boolean result = (resultMsg.arg1 != FAILURE); 2681 resultMsg.recycle(); 2682 return result; 2683 } 2684 2685 public void updateBatteryWorkSource(WorkSource newSource) { 2686 synchronized (mRunningWifiUids) { 2687 try { 2688 if (newSource != null) { 2689 mRunningWifiUids.set(newSource); 2690 } 2691 if (mIsRunning) { 2692 if (mReportedRunning) { 2693 // If the work source has changed since last time, need 2694 // to remove old work from battery stats. 2695 if (mLastRunningWifiUids.diff(mRunningWifiUids)) { 2696 mBatteryStats.noteWifiRunningChanged(mLastRunningWifiUids, 2697 mRunningWifiUids); 2698 mLastRunningWifiUids.set(mRunningWifiUids); 2699 } 2700 } else { 2701 // Now being started, report it. 2702 mBatteryStats.noteWifiRunning(mRunningWifiUids); 2703 mLastRunningWifiUids.set(mRunningWifiUids); 2704 mReportedRunning = true; 2705 } 2706 } else { 2707 if (mReportedRunning) { 2708 // Last reported we were running, time to stop. 2709 mBatteryStats.noteWifiStopped(mLastRunningWifiUids); 2710 mLastRunningWifiUids.clear(); 2711 mReportedRunning = false; 2712 } 2713 } 2714 mWakeLock.setWorkSource(newSource); 2715 } catch (RemoteException ignore) { 2716 } 2717 } 2718 } 2719 2720 @Override 2721 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2722 super.dump(fd, pw, args); 2723 if (args.length == 1 && "apf".equals(args[0])) { 2724 mIpManager.dumpApf(pw); 2725 return; 2726 } 2727 mSupplicantStateTracker.dump(fd, pw, args); 2728 pw.println("mLinkProperties " + mLinkProperties); 2729 pw.println("mWifiInfo " + mWifiInfo); 2730 pw.println("mDhcpResults " + mDhcpResults); 2731 pw.println("mNetworkInfo " + mNetworkInfo); 2732 pw.println("mLastSignalLevel " + mLastSignalLevel); 2733 pw.println("mLastBssid " + mLastBssid); 2734 pw.println("mLastNetworkId " + mLastNetworkId); 2735 pw.println("mOperationalMode " + mOperationalMode); 2736 pw.println("mUserWantsSuspendOpt " + mUserWantsSuspendOpt); 2737 pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 2738 pw.println("Supplicant status " + mWifiNative.status(true)); 2739 pw.println("mLegacyPnoEnabled " + mLegacyPnoEnabled); 2740 if (mCountryCode.getCurrentCountryCode() != null) { 2741 pw.println("CurrentCountryCode " + mCountryCode.getCurrentCountryCode()); 2742 } else { 2743 pw.println("CurrentCountryCode is not initialized"); 2744 } 2745 pw.println("mConnectedModeGScanOffloadStarted " + mConnectedModeGScanOffloadStarted); 2746 pw.println("mGScanPeriodMilli " + mGScanPeriodMilli); 2747 if (mWhiteListedSsids != null && mWhiteListedSsids.length > 0) { 2748 pw.println("SSID whitelist :" ); 2749 for (int i=0; i < mWhiteListedSsids.length; i++) { 2750 pw.println(" " + mWhiteListedSsids[i]); 2751 } 2752 } 2753 if (mNetworkFactory != null) { 2754 mNetworkFactory.dump(fd, pw, args); 2755 } else { 2756 pw.println("mNetworkFactory is not initialized"); 2757 } 2758 2759 if (mUntrustedNetworkFactory != null) { 2760 mUntrustedNetworkFactory.dump(fd, pw, args); 2761 } else { 2762 pw.println("mUntrustedNetworkFactory is not initialized"); 2763 } 2764 pw.println("Wlan Wake Reasons:" + mWifiNative.getWlanWakeReasonCount()); 2765 pw.println(); 2766 updateWifiMetrics(); 2767 mWifiMetrics.dump(fd, pw, args); 2768 pw.println(); 2769 mNetworkFactory.dump(fd, pw, args); 2770 mUntrustedNetworkFactory.dump(fd, pw, args); 2771 pw.println(); 2772 2773 mWifiConfigManager.dump(fd, pw, args); 2774 pw.println(); 2775 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_USER_ACTION); 2776 mWifiLogger.dump(fd, pw, args); 2777 mWifiQualifiedNetworkSelector.dump(fd, pw, args); 2778 mIpManager.dumpApf(pw); 2779 } 2780 2781 public void handleUserSwitch(int userId) { 2782 sendMessage(CMD_USER_SWITCH, userId); 2783 } 2784 2785 /** 2786 * ****************************************************** 2787 * Internal private functions 2788 * ****************************************************** 2789 */ 2790 2791 private void logStateAndMessage(Message message, State state) { 2792 messageHandlingStatus = 0; 2793 if (DBG) { 2794 logd(" " + state.getClass().getSimpleName() + " " + getLogRecString(message)); 2795 } 2796 } 2797 2798 /** 2799 * helper, prints the milli time since boot wi and w/o suspended time 2800 */ 2801 String printTime() { 2802 StringBuilder sb = new StringBuilder(); 2803 sb.append(" rt=").append(SystemClock.uptimeMillis()); 2804 sb.append("/").append(SystemClock.elapsedRealtime()); 2805 return sb.toString(); 2806 } 2807 2808 /** 2809 * Return the additional string to be logged by LogRec, default 2810 * 2811 * @param msg that was processed 2812 * @return information to be logged as a String 2813 */ 2814 protected String getLogRecString(Message msg) { 2815 WifiConfiguration config; 2816 Long now; 2817 String report; 2818 String key; 2819 StringBuilder sb = new StringBuilder(); 2820 if (mScreenOn) { 2821 sb.append("!"); 2822 } 2823 if (messageHandlingStatus != MESSAGE_HANDLING_STATUS_UNKNOWN) { 2824 sb.append("(").append(messageHandlingStatus).append(")"); 2825 } 2826 sb.append(smToString(msg)); 2827 if (msg.sendingUid > 0 && msg.sendingUid != Process.WIFI_UID) { 2828 sb.append(" uid=" + msg.sendingUid); 2829 } 2830 sb.append(" ").append(printTime()); 2831 switch (msg.what) { 2832 case CMD_STARTED_GSCAN_DBG: 2833 case CMD_STARTED_PNO_DBG: 2834 sb.append(" "); 2835 sb.append(Integer.toString(msg.arg1)); 2836 sb.append(" "); 2837 sb.append(Integer.toString(msg.arg2)); 2838 if (msg.obj != null) { 2839 sb.append(" " + (String)msg.obj); 2840 } 2841 break; 2842 case CMD_RESTART_AUTOJOIN_OFFLOAD: 2843 sb.append(" "); 2844 sb.append(Integer.toString(msg.arg1)); 2845 sb.append(" "); 2846 sb.append(Integer.toString(msg.arg2)); 2847 sb.append("/").append(Integer.toString(mRestartAutoJoinOffloadCounter)); 2848 if (msg.obj != null) { 2849 sb.append(" " + (String)msg.obj); 2850 } 2851 break; 2852 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 2853 sb.append(" "); 2854 sb.append(Integer.toString(msg.arg1)); 2855 sb.append(" "); 2856 sb.append(Integer.toString(msg.arg2)); 2857 sb.append(" halAllowed=").append(useHalBasedAutoJoinOffload()); 2858 sb.append(" scanAllowed=").append(allowFullBandScanAndAssociated()); 2859 sb.append(" autojoinAllowed="); 2860 sb.append(mWifiConfigManager.enableAutoJoinWhenAssociated.get()); 2861 sb.append(" withTraffic=").append(getAllowScansWithTraffic()); 2862 sb.append(" tx=").append(mWifiInfo.txSuccessRate); 2863 sb.append("/").append(mWifiConfigManager.maxTxPacketForFullScans); 2864 sb.append(" rx=").append(mWifiInfo.rxSuccessRate); 2865 sb.append("/").append(mWifiConfigManager.maxRxPacketForFullScans); 2866 sb.append(" -> ").append(mConnectedModeGScanOffloadStarted); 2867 break; 2868 case CMD_PNO_NETWORK_FOUND: 2869 sb.append(" "); 2870 sb.append(Integer.toString(msg.arg1)); 2871 sb.append(" "); 2872 sb.append(Integer.toString(msg.arg2)); 2873 if (msg.obj != null) { 2874 ScanResult[] results = (ScanResult[])msg.obj; 2875 for (int i = 0; i < results.length; i++) { 2876 sb.append(" ").append(results[i].SSID).append(" "); 2877 sb.append(results[i].frequency); 2878 sb.append(" ").append(results[i].level); 2879 } 2880 } 2881 break; 2882 case CMD_START_SCAN: 2883 now = System.currentTimeMillis(); 2884 sb.append(" "); 2885 sb.append(Integer.toString(msg.arg1)); 2886 sb.append(" "); 2887 sb.append(Integer.toString(msg.arg2)); 2888 sb.append(" ic="); 2889 sb.append(Integer.toString(sScanAlarmIntentCount)); 2890 if (msg.obj != null) { 2891 Bundle bundle = (Bundle) msg.obj; 2892 Long request = bundle.getLong(SCAN_REQUEST_TIME, 0); 2893 if (request != 0) { 2894 sb.append(" proc(ms):").append(now - request); 2895 } 2896 } 2897 if (mIsScanOngoing) sb.append(" onGoing"); 2898 if (mIsFullScanOngoing) sb.append(" full"); 2899 if (lastStartScanTimeStamp != 0) { 2900 sb.append(" started:").append(lastStartScanTimeStamp); 2901 sb.append(",").append(now - lastStartScanTimeStamp); 2902 } 2903 if (lastScanDuration != 0) { 2904 sb.append(" dur:").append(lastScanDuration); 2905 } 2906 sb.append(" cnt=").append(mDelayedScanCounter); 2907 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2908 sb.append(" f=").append(mWifiInfo.getFrequency()); 2909 sb.append(" sc=").append(mWifiInfo.score); 2910 sb.append(" link=").append(mWifiInfo.getLinkSpeed()); 2911 sb.append(String.format(" tx=%.1f,", mWifiInfo.txSuccessRate)); 2912 sb.append(String.format(" %.1f,", mWifiInfo.txRetriesRate)); 2913 sb.append(String.format(" %.1f ", mWifiInfo.txBadRate)); 2914 sb.append(String.format(" rx=%.1f", mWifiInfo.rxSuccessRate)); 2915 if (lastScanFreqs != null) { 2916 sb.append(" list="); 2917 for(int freq : lastScanFreqs) { 2918 sb.append(freq).append(","); 2919 } 2920 } else { 2921 sb.append(" fiv=").append(fullBandConnectedTimeIntervalMilli); 2922 } 2923 report = reportOnTime(); 2924 if (report != null) { 2925 sb.append(" ").append(report); 2926 } 2927 break; 2928 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 2929 sb.append(" "); 2930 sb.append(Integer.toString(msg.arg1)); 2931 sb.append(" "); 2932 sb.append(Integer.toString(msg.arg2)); 2933 StateChangeResult stateChangeResult = (StateChangeResult) msg.obj; 2934 if (stateChangeResult != null) { 2935 sb.append(stateChangeResult.toString()); 2936 } 2937 break; 2938 case WifiManager.SAVE_NETWORK: 2939 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 2940 sb.append(" "); 2941 sb.append(Integer.toString(msg.arg1)); 2942 sb.append(" "); 2943 sb.append(Integer.toString(msg.arg2)); 2944 if (lastSavedConfigurationAttempt != null) { 2945 sb.append(" ").append(lastSavedConfigurationAttempt.configKey()); 2946 sb.append(" nid=").append(lastSavedConfigurationAttempt.networkId); 2947 if (lastSavedConfigurationAttempt.hiddenSSID) { 2948 sb.append(" hidden"); 2949 } 2950 if (lastSavedConfigurationAttempt.preSharedKey != null 2951 && !lastSavedConfigurationAttempt.preSharedKey.equals("*")) { 2952 sb.append(" hasPSK"); 2953 } 2954 if (lastSavedConfigurationAttempt.ephemeral) { 2955 sb.append(" ephemeral"); 2956 } 2957 if (lastSavedConfigurationAttempt.selfAdded) { 2958 sb.append(" selfAdded"); 2959 } 2960 sb.append(" cuid=").append(lastSavedConfigurationAttempt.creatorUid); 2961 sb.append(" suid=").append(lastSavedConfigurationAttempt.lastUpdateUid); 2962 } 2963 break; 2964 case WifiManager.FORGET_NETWORK: 2965 sb.append(" "); 2966 sb.append(Integer.toString(msg.arg1)); 2967 sb.append(" "); 2968 sb.append(Integer.toString(msg.arg2)); 2969 if (lastForgetConfigurationAttempt != null) { 2970 sb.append(" ").append(lastForgetConfigurationAttempt.configKey()); 2971 sb.append(" nid=").append(lastForgetConfigurationAttempt.networkId); 2972 if (lastForgetConfigurationAttempt.hiddenSSID) { 2973 sb.append(" hidden"); 2974 } 2975 if (lastForgetConfigurationAttempt.preSharedKey != null) { 2976 sb.append(" hasPSK"); 2977 } 2978 if (lastForgetConfigurationAttempt.ephemeral) { 2979 sb.append(" ephemeral"); 2980 } 2981 if (lastForgetConfigurationAttempt.selfAdded) { 2982 sb.append(" selfAdded"); 2983 } 2984 sb.append(" cuid=").append(lastForgetConfigurationAttempt.creatorUid); 2985 sb.append(" suid=").append(lastForgetConfigurationAttempt.lastUpdateUid); 2986 WifiConfiguration.NetworkSelectionStatus netWorkSelectionStatus = 2987 lastForgetConfigurationAttempt.getNetworkSelectionStatus(); 2988 sb.append(" ajst=").append( 2989 netWorkSelectionStatus.getNetworkStatusString()); 2990 } 2991 break; 2992 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 2993 sb.append(" "); 2994 sb.append(Integer.toString(msg.arg1)); 2995 sb.append(" "); 2996 sb.append(Integer.toString(msg.arg2)); 2997 String bssid = (String) msg.obj; 2998 if (bssid != null && bssid.length() > 0) { 2999 sb.append(" "); 3000 sb.append(bssid); 3001 } 3002 sb.append(" blacklist=" + Boolean.toString(didBlackListBSSID)); 3003 break; 3004 case WifiMonitor.SCAN_RESULTS_EVENT: 3005 sb.append(" "); 3006 sb.append(Integer.toString(msg.arg1)); 3007 sb.append(" "); 3008 sb.append(Integer.toString(msg.arg2)); 3009 if (mScanResults != null) { 3010 sb.append(" found="); 3011 sb.append(mScanResults.size()); 3012 } 3013 sb.append(" known=").append(mNumScanResultsKnown); 3014 sb.append(" got=").append(mNumScanResultsReturned); 3015 if (lastScanDuration != 0) { 3016 sb.append(" dur:").append(lastScanDuration); 3017 } 3018 if (mOnTime != 0) { 3019 sb.append(" on:").append(mOnTimeThisScan).append(",").append(mOnTimeScan); 3020 sb.append(",").append(mOnTime); 3021 } 3022 if (mTxTime != 0) { 3023 sb.append(" tx:").append(mTxTimeThisScan).append(",").append(mTxTimeScan); 3024 sb.append(",").append(mTxTime); 3025 } 3026 if (mRxTime != 0) { 3027 sb.append(" rx:").append(mRxTimeThisScan).append(",").append(mRxTimeScan); 3028 sb.append(",").append(mRxTime); 3029 } 3030 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 3031 sb.append(String.format(" con=%d", mConnectionRequests)); 3032 key = mWifiConfigManager.getLastSelectedConfiguration(); 3033 if (key != null) { 3034 sb.append(" last=").append(key); 3035 } 3036 break; 3037 case WifiMonitor.SCAN_FAILED_EVENT: 3038 break; 3039 case WifiMonitor.NETWORK_CONNECTION_EVENT: 3040 sb.append(" "); 3041 sb.append(Integer.toString(msg.arg1)); 3042 sb.append(" "); 3043 sb.append(Integer.toString(msg.arg2)); 3044 sb.append(" ").append(mLastBssid); 3045 sb.append(" nid=").append(mLastNetworkId); 3046 config = getCurrentWifiConfiguration(); 3047 if (config != null) { 3048 sb.append(" ").append(config.configKey()); 3049 } 3050 key = mWifiConfigManager.getLastSelectedConfiguration(); 3051 if (key != null) { 3052 sb.append(" last=").append(key); 3053 } 3054 break; 3055 case CMD_TARGET_BSSID: 3056 case CMD_ASSOCIATED_BSSID: 3057 sb.append(" "); 3058 sb.append(Integer.toString(msg.arg1)); 3059 sb.append(" "); 3060 sb.append(Integer.toString(msg.arg2)); 3061 if (msg.obj != null) { 3062 sb.append(" BSSID=").append((String) msg.obj); 3063 } 3064 if (mTargetRoamBSSID != null) { 3065 sb.append(" Target=").append(mTargetRoamBSSID); 3066 } 3067 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 3068 break; 3069 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 3070 if (msg.obj != null) { 3071 sb.append(" ").append((String) msg.obj); 3072 } 3073 sb.append(" nid=").append(msg.arg1); 3074 sb.append(" reason=").append(msg.arg2); 3075 if (mLastBssid != null) { 3076 sb.append(" lastbssid=").append(mLastBssid); 3077 } 3078 if (mWifiInfo.getFrequency() != -1) { 3079 sb.append(" freq=").append(mWifiInfo.getFrequency()); 3080 sb.append(" rssi=").append(mWifiInfo.getRssi()); 3081 } 3082 if (linkDebouncing) { 3083 sb.append(" debounce"); 3084 } 3085 break; 3086 case WifiMonitor.SSID_TEMP_DISABLED: 3087 case WifiMonitor.SSID_REENABLED: 3088 sb.append(" nid=").append(msg.arg1); 3089 if (msg.obj != null) { 3090 sb.append(" ").append((String) msg.obj); 3091 } 3092 config = getCurrentWifiConfiguration(); 3093 if (config != null) { 3094 WifiConfiguration.NetworkSelectionStatus netWorkSelectionStatus = 3095 config.getNetworkSelectionStatus(); 3096 sb.append(" cur=").append(config.configKey()); 3097 sb.append(" ajst=").append(netWorkSelectionStatus.getNetworkStatusString()); 3098 if (config.selfAdded) { 3099 sb.append(" selfAdded"); 3100 } 3101 if (config.status != 0) { 3102 sb.append(" st=").append(config.status); 3103 sb.append(" rs=").append( 3104 netWorkSelectionStatus.getNetworkDisableReasonString()); 3105 } 3106 if (config.lastConnected != 0) { 3107 now = System.currentTimeMillis(); 3108 sb.append(" lastconn=").append(now - config.lastConnected).append("(ms)"); 3109 } 3110 if (mLastBssid != null) { 3111 sb.append(" lastbssid=").append(mLastBssid); 3112 } 3113 if (mWifiInfo.getFrequency() != -1) { 3114 sb.append(" freq=").append(mWifiInfo.getFrequency()); 3115 sb.append(" rssi=").append(mWifiInfo.getRssi()); 3116 sb.append(" bssid=").append(mWifiInfo.getBSSID()); 3117 } 3118 } 3119 break; 3120 case CMD_RSSI_POLL: 3121 case CMD_UNWANTED_NETWORK: 3122 case WifiManager.RSSI_PKTCNT_FETCH: 3123 sb.append(" "); 3124 sb.append(Integer.toString(msg.arg1)); 3125 sb.append(" "); 3126 sb.append(Integer.toString(msg.arg2)); 3127 if (mWifiInfo.getSSID() != null) 3128 if (mWifiInfo.getSSID() != null) 3129 sb.append(" ").append(mWifiInfo.getSSID()); 3130 if (mWifiInfo.getBSSID() != null) 3131 sb.append(" ").append(mWifiInfo.getBSSID()); 3132 sb.append(" rssi=").append(mWifiInfo.getRssi()); 3133 sb.append(" f=").append(mWifiInfo.getFrequency()); 3134 sb.append(" sc=").append(mWifiInfo.score); 3135 sb.append(" link=").append(mWifiInfo.getLinkSpeed()); 3136 sb.append(String.format(" tx=%.1f,", mWifiInfo.txSuccessRate)); 3137 sb.append(String.format(" %.1f,", mWifiInfo.txRetriesRate)); 3138 sb.append(String.format(" %.1f ", mWifiInfo.txBadRate)); 3139 sb.append(String.format(" rx=%.1f", mWifiInfo.rxSuccessRate)); 3140 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 3141 report = reportOnTime(); 3142 if (report != null) { 3143 sb.append(" ").append(report); 3144 } 3145 if (mWifiScoreReport != null) { 3146 sb.append(mWifiScoreReport.getReport()); 3147 } 3148 if (mConnectedModeGScanOffloadStarted) { 3149 sb.append(" offload-started periodMilli " + mGScanPeriodMilli); 3150 } else { 3151 sb.append(" offload-stopped"); 3152 } 3153 break; 3154 case CMD_AUTO_CONNECT: 3155 case WifiManager.CONNECT_NETWORK: 3156 sb.append(" "); 3157 sb.append(Integer.toString(msg.arg1)); 3158 sb.append(" "); 3159 sb.append(Integer.toString(msg.arg2)); 3160 config = mWifiConfigManager.getWifiConfiguration(msg.arg1); 3161 if (config != null) { 3162 sb.append(" ").append(config.configKey()); 3163 if (config.visibility != null) { 3164 sb.append(" ").append(config.visibility.toString()); 3165 } 3166 } 3167 if (mTargetRoamBSSID != null) { 3168 sb.append(" ").append(mTargetRoamBSSID); 3169 } 3170 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 3171 config = getCurrentWifiConfiguration(); 3172 if (config != null) { 3173 sb.append(config.configKey()); 3174 if (config.visibility != null) { 3175 sb.append(" ").append(config.visibility.toString()); 3176 } 3177 } 3178 break; 3179 case CMD_AUTO_ROAM: 3180 sb.append(" "); 3181 sb.append(Integer.toString(msg.arg1)); 3182 sb.append(" "); 3183 sb.append(Integer.toString(msg.arg2)); 3184 ScanResult result = (ScanResult) msg.obj; 3185 if (result != null) { 3186 now = System.currentTimeMillis(); 3187 sb.append(" bssid=").append(result.BSSID); 3188 sb.append(" rssi=").append(result.level); 3189 sb.append(" freq=").append(result.frequency); 3190 if (result.seen > 0 && result.seen < now) { 3191 sb.append(" seen=").append(now - result.seen); 3192 } else { 3193 // Somehow the timestamp for this scan result is inconsistent 3194 sb.append(" !seen=").append(result.seen); 3195 } 3196 } 3197 if (mTargetRoamBSSID != null) { 3198 sb.append(" ").append(mTargetRoamBSSID); 3199 } 3200 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 3201 sb.append(" fail count=").append(Integer.toString(mRoamFailCount)); 3202 break; 3203 case CMD_ADD_OR_UPDATE_NETWORK: 3204 sb.append(" "); 3205 sb.append(Integer.toString(msg.arg1)); 3206 sb.append(" "); 3207 sb.append(Integer.toString(msg.arg2)); 3208 if (msg.obj != null) { 3209 config = (WifiConfiguration) msg.obj; 3210 sb.append(" ").append(config.configKey()); 3211 sb.append(" prio=").append(config.priority); 3212 sb.append(" status=").append(config.status); 3213 if (config.BSSID != null) { 3214 sb.append(" ").append(config.BSSID); 3215 } 3216 WifiConfiguration curConfig = getCurrentWifiConfiguration(); 3217 if (curConfig != null) { 3218 if (curConfig.configKey().equals(config.configKey())) { 3219 sb.append(" is current"); 3220 } else { 3221 sb.append(" current=").append(curConfig.configKey()); 3222 sb.append(" prio=").append(curConfig.priority); 3223 sb.append(" status=").append(curConfig.status); 3224 } 3225 } 3226 } 3227 break; 3228 case WifiManager.DISABLE_NETWORK: 3229 case CMD_ENABLE_NETWORK: 3230 sb.append(" "); 3231 sb.append(Integer.toString(msg.arg1)); 3232 sb.append(" "); 3233 sb.append(Integer.toString(msg.arg2)); 3234 key = mWifiConfigManager.getLastSelectedConfiguration(); 3235 if (key != null) { 3236 sb.append(" last=").append(key); 3237 } 3238 config = mWifiConfigManager.getWifiConfiguration(msg.arg1); 3239 if (config != null && (key == null || !config.configKey().equals(key))) { 3240 sb.append(" target=").append(key); 3241 } 3242 break; 3243 case CMD_GET_CONFIGURED_NETWORKS: 3244 sb.append(" "); 3245 sb.append(Integer.toString(msg.arg1)); 3246 sb.append(" "); 3247 sb.append(Integer.toString(msg.arg2)); 3248 sb.append(" num=").append(mWifiConfigManager.getConfiguredNetworksSize()); 3249 break; 3250 case DhcpClient.CMD_PRE_DHCP_ACTION: 3251 sb.append(" "); 3252 sb.append(Integer.toString(msg.arg1)); 3253 sb.append(" "); 3254 sb.append(Integer.toString(msg.arg2)); 3255 sb.append(" txpkts=").append(mWifiInfo.txSuccess); 3256 sb.append(",").append(mWifiInfo.txBad); 3257 sb.append(",").append(mWifiInfo.txRetries); 3258 break; 3259 case DhcpClient.CMD_POST_DHCP_ACTION: 3260 sb.append(" "); 3261 sb.append(Integer.toString(msg.arg1)); 3262 sb.append(" "); 3263 sb.append(Integer.toString(msg.arg2)); 3264 if (msg.arg1 == DhcpClient.DHCP_SUCCESS) { 3265 sb.append(" OK "); 3266 } else if (msg.arg1 == DhcpClient.DHCP_FAILURE) { 3267 sb.append(" FAIL "); 3268 } 3269 if (mLinkProperties != null) { 3270 sb.append(" "); 3271 sb.append(getLinkPropertiesSummary(mLinkProperties)); 3272 } 3273 break; 3274 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 3275 sb.append(" "); 3276 sb.append(Integer.toString(msg.arg1)); 3277 sb.append(" "); 3278 sb.append(Integer.toString(msg.arg2)); 3279 if (msg.obj != null) { 3280 NetworkInfo info = (NetworkInfo) msg.obj; 3281 NetworkInfo.State state = info.getState(); 3282 NetworkInfo.DetailedState detailedState = info.getDetailedState(); 3283 if (state != null) { 3284 sb.append(" st=").append(state); 3285 } 3286 if (detailedState != null) { 3287 sb.append("/").append(detailedState); 3288 } 3289 } 3290 break; 3291 case CMD_IP_CONFIGURATION_LOST: 3292 int count = -1; 3293 WifiConfiguration c = getCurrentWifiConfiguration(); 3294 if (c != null) { 3295 count = c.getNetworkSelectionStatus().getDisableReasonCounter( 3296 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3297 } 3298 sb.append(" "); 3299 sb.append(Integer.toString(msg.arg1)); 3300 sb.append(" "); 3301 sb.append(Integer.toString(msg.arg2)); 3302 sb.append(" failures: "); 3303 sb.append(Integer.toString(count)); 3304 sb.append("/"); 3305 sb.append(Integer.toString(mWifiConfigManager.getMaxDhcpRetries())); 3306 if (mWifiInfo.getBSSID() != null) { 3307 sb.append(" ").append(mWifiInfo.getBSSID()); 3308 } 3309 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 3310 break; 3311 case CMD_UPDATE_LINKPROPERTIES: 3312 sb.append(" "); 3313 sb.append(Integer.toString(msg.arg1)); 3314 sb.append(" "); 3315 sb.append(Integer.toString(msg.arg2)); 3316 if (mLinkProperties != null) { 3317 sb.append(" "); 3318 sb.append(getLinkPropertiesSummary(mLinkProperties)); 3319 } 3320 break; 3321 case CMD_IP_REACHABILITY_LOST: 3322 if (msg.obj != null) { 3323 sb.append(" ").append((String) msg.obj); 3324 } 3325 break; 3326 case CMD_INSTALL_PACKET_FILTER: 3327 sb.append(" len=" + ((byte[])msg.obj).length); 3328 break; 3329 case CMD_ROAM_WATCHDOG_TIMER: 3330 sb.append(" "); 3331 sb.append(Integer.toString(msg.arg1)); 3332 sb.append(" "); 3333 sb.append(Integer.toString(msg.arg2)); 3334 sb.append(" cur=").append(roamWatchdogCount); 3335 break; 3336 case CMD_DISCONNECTING_WATCHDOG_TIMER: 3337 sb.append(" "); 3338 sb.append(Integer.toString(msg.arg1)); 3339 sb.append(" "); 3340 sb.append(Integer.toString(msg.arg2)); 3341 sb.append(" cur=").append(disconnectingWatchdogCount); 3342 break; 3343 case CMD_START_RSSI_MONITORING_OFFLOAD: 3344 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 3345 case CMD_RSSI_THRESHOLD_BREACH: 3346 sb.append(" rssi="); 3347 sb.append(Integer.toString(msg.arg1)); 3348 sb.append(" thresholds="); 3349 sb.append(Arrays.toString(mRssiRanges)); 3350 break; 3351 case CMD_USER_SWITCH: 3352 sb.append(" userId="); 3353 sb.append(Integer.toString(msg.arg1)); 3354 break; 3355 case CMD_IPV4_PROVISIONING_SUCCESS: 3356 sb.append(" "); 3357 if (msg.arg1 == DhcpClient.DHCP_SUCCESS) { 3358 sb.append("DHCP_OK"); 3359 } else if (msg.arg1 == CMD_STATIC_IP_SUCCESS) { 3360 sb.append("STATIC_OK"); 3361 } else { 3362 sb.append(Integer.toString(msg.arg1)); 3363 } 3364 break; 3365 case CMD_IPV4_PROVISIONING_FAILURE: 3366 sb.append(" "); 3367 if (msg.arg1 == DhcpClient.DHCP_FAILURE) { 3368 sb.append("DHCP_FAIL"); 3369 } else if (msg.arg1 == CMD_STATIC_IP_FAILURE) { 3370 sb.append("STATIC_FAIL"); 3371 } else { 3372 sb.append(Integer.toString(msg.arg1)); 3373 } 3374 break; 3375 default: 3376 sb.append(" "); 3377 sb.append(Integer.toString(msg.arg1)); 3378 sb.append(" "); 3379 sb.append(Integer.toString(msg.arg2)); 3380 break; 3381 } 3382 3383 return sb.toString(); 3384 } 3385 3386 private void stopPnoOffload() { 3387 3388 // clear the PNO list 3389 if (!mWifiNative.resetPnoList()) { 3390 Log.e(TAG, "Failed to stop pno"); 3391 } 3392 3393 } 3394 3395 private boolean startGScanConnectedModeOffload(String reason) { 3396 if (DBG) { 3397 if (reason == null) { 3398 reason = ""; 3399 } 3400 logd("startGScanConnectedModeOffload " + reason); 3401 } 3402 stopGScan("startGScanConnectedModeOffload " + reason); 3403 if (!mScreenOn) return false; 3404 3405 if (USE_PAUSE_SCANS) { 3406 mWifiNative.pauseScan(); 3407 } 3408 mPnoEnabled = configurePno(); 3409 if (mPnoEnabled == false) { 3410 if (USE_PAUSE_SCANS) { 3411 mWifiNative.restartScan(); 3412 } 3413 return false; 3414 } 3415 if (!startConnectedGScan(reason)) { 3416 if (USE_PAUSE_SCANS) { 3417 mWifiNative.restartScan(); 3418 } 3419 return false; 3420 } 3421 if (USE_PAUSE_SCANS) { 3422 mWifiNative.restartScan(); 3423 } 3424 mConnectedModeGScanOffloadStarted = true; 3425 if (DBG) { 3426 logd("startGScanConnectedModeOffload success"); 3427 } 3428 return true; 3429 } 3430 3431 private boolean startGScanDisconnectedModeOffload(String reason) { 3432 if (DBG) { 3433 logd("startGScanDisconnectedModeOffload " + reason); 3434 } 3435 stopGScan("startGScanDisconnectedModeOffload " + reason); 3436 if (USE_PAUSE_SCANS) { 3437 mWifiNative.pauseScan(); 3438 } 3439 mPnoEnabled = configurePno(); 3440 if (mPnoEnabled == false) { 3441 if (USE_PAUSE_SCANS) { 3442 mWifiNative.restartScan(); 3443 } 3444 return false; 3445 } 3446 if (!startDisconnectedGScan(reason)) { 3447 if (USE_PAUSE_SCANS) { 3448 mWifiNative.restartScan(); 3449 } 3450 return false; 3451 } 3452 if (USE_PAUSE_SCANS) { 3453 mWifiNative.restartScan(); 3454 } 3455 return true; 3456 } 3457 3458 private boolean configurePno() { 3459 if (!useHalBasedAutoJoinOffload()) return false; 3460 3461 if (mWifiScanner == null) { 3462 log("configurePno: mWifiScanner is null "); 3463 return true; 3464 } 3465 3466 List<WifiNative.PnoNetwork> llist = null; 3467 //TODO: add getPnoList in WifiQualifiedNetworkSelector 3468 //mWifiAutoJoinController.getPnoList(getCurrentWifiConfiguration()); 3469 if (llist == null || llist.size() == 0) { 3470 stopPnoOffload(); 3471 log("configurePno: empty PNO list "); 3472 return true; 3473 } 3474 if (DBG) { 3475 log("configurePno: got llist size " + llist.size()); 3476 } 3477 3478 // first program the network we want to look for thru the pno API 3479 WifiNative.PnoNetwork[] list = 3480 (WifiNative.PnoNetwork[]) llist.toArray(new WifiNative.PnoNetwork[0]); 3481 3482 if (!mWifiNative.setPnoList(list, WifiStateMachine.this)) { 3483 Log.e(TAG, "Failed to set pno, length = " + list.length); 3484 return false; 3485 } 3486 3487 if (true) { 3488 StringBuilder sb = new StringBuilder(); 3489 for (WifiNative.PnoNetwork network : list) { 3490 sb.append("[").append(network.ssid).append(" auth=").append(network.auth_bit_field); 3491 sb.append(" flags="); 3492 sb.append(network.flags); 3493 sb.append("] "); 3494 3495 } 3496 sendMessage(CMD_STARTED_PNO_DBG, 1, (int)mGScanPeriodMilli, sb.toString()); 3497 } 3498 return true; 3499 } 3500 3501 final static int DISCONNECTED_SHORT_SCANS_DURATION_MILLI = 2 * 60 * 1000; 3502 final static int CONNECTED_SHORT_SCANS_DURATION_MILLI = 2 * 60 * 1000; 3503 3504 private boolean startConnectedGScan(String reason) { 3505 // send a scan background request so as to kick firmware 3506 // 5GHz roaming and autojoin 3507 // We do this only if screen is on 3508 WifiScanner.ScanSettings settings; 3509 3510 if (mPnoEnabled) { 3511 settings = new WifiScanner.ScanSettings(); 3512 settings.band = WifiScanner.WIFI_BAND_BOTH; 3513 long now = System.currentTimeMillis(); 3514 3515 if (!mScreenOn || (mGScanStartTimeMilli!= 0 && now > mGScanStartTimeMilli 3516 && ((now - mGScanStartTimeMilli) > CONNECTED_SHORT_SCANS_DURATION_MILLI))) { 3517 settings.periodInMs = mWifiConfigManager.wifiAssociatedLongScanIntervalMilli.get(); 3518 } else { 3519 mGScanStartTimeMilli = now; 3520 settings.periodInMs = mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get(); 3521 // if we start offload with short interval, then reconfigure it after a given 3522 // duration of time so as to reduce the scan frequency 3523 int delay = 30 * 1000 + CONNECTED_SHORT_SCANS_DURATION_MILLI; 3524 sendMessageDelayed(CMD_RESTART_AUTOJOIN_OFFLOAD, delay, 3525 mRestartAutoJoinOffloadCounter, " startConnectedGScan " + reason, 3526 (long)delay); 3527 mRestartAutoJoinOffloadCounter++; 3528 } 3529 mGScanPeriodMilli = settings.periodInMs; 3530 settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL; 3531 if (DBG) { 3532 log("startConnectedScan: settings band="+ settings.band 3533 + " period=" + settings.periodInMs); 3534 } 3535 3536 mWifiScanner.startBackgroundScan(settings, mWifiScanListener); 3537 if (true) { 3538 sendMessage(CMD_STARTED_GSCAN_DBG, 1, (int)mGScanPeriodMilli, reason); 3539 } 3540 } 3541 return true; 3542 } 3543 3544 private boolean startDisconnectedGScan(String reason) { 3545 // send a scan background request so as to kick firmware 3546 // PNO 3547 // This is done in both screen On and screen Off modes 3548 WifiScanner.ScanSettings settings; 3549 3550 if (mWifiScanner == null) { 3551 log("startDisconnectedGScan: no wifi scanner"); 3552 return false; 3553 } 3554 3555 if (mPnoEnabled) { 3556 settings = new WifiScanner.ScanSettings(); 3557 settings.band = WifiScanner.WIFI_BAND_BOTH; 3558 long now = System.currentTimeMillis(); 3559 3560 3561 if (!mScreenOn || (mGScanStartTimeMilli != 0 && now > mGScanStartTimeMilli 3562 && ((now - mGScanStartTimeMilli) > DISCONNECTED_SHORT_SCANS_DURATION_MILLI))) { 3563 settings.periodInMs = 3564 mWifiConfigManager.wifiDisconnectedLongScanIntervalMilli.get(); 3565 } else { 3566 settings.periodInMs = 3567 mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get(); 3568 mGScanStartTimeMilli = now; 3569 // if we start offload with short interval, then reconfigure it after a given 3570 // duration of time so as to reduce the scan frequency 3571 int delay = 30 * 1000 + DISCONNECTED_SHORT_SCANS_DURATION_MILLI; 3572 sendMessageDelayed(CMD_RESTART_AUTOJOIN_OFFLOAD, delay, 3573 mRestartAutoJoinOffloadCounter, " startDisconnectedGScan " + reason, 3574 (long)delay); 3575 mRestartAutoJoinOffloadCounter++; 3576 } 3577 mGScanPeriodMilli = settings.periodInMs; 3578 settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL; 3579 if (DBG) { 3580 log("startDisconnectedScan: settings band="+ settings.band 3581 + " period=" + settings.periodInMs); 3582 } 3583 mWifiScanner.startBackgroundScan(settings, mWifiScanListener); 3584 if (true) { 3585 sendMessage(CMD_STARTED_GSCAN_DBG, 1, (int)mGScanPeriodMilli, reason); 3586 } 3587 } 3588 return true; 3589 } 3590 3591 private boolean stopGScan(String reason) { 3592 mGScanStartTimeMilli = 0; 3593 mGScanPeriodMilli = 0; 3594 if (mWifiScanner != null) { 3595 mWifiScanner.stopBackgroundScan(mWifiScanListener); 3596 } 3597 mConnectedModeGScanOffloadStarted = false; 3598 if (true) { 3599 sendMessage(CMD_STARTED_GSCAN_DBG, 0, 0, reason); 3600 } 3601 return true; 3602 } 3603 3604 private void handleScreenStateChanged(boolean screenOn) { 3605 mScreenOn = screenOn; 3606 if (DBG) { 3607 logd(" handleScreenStateChanged Enter: screenOn=" + screenOn 3608 + " mUserWantsSuspendOpt=" + mUserWantsSuspendOpt 3609 + " state " + getCurrentState().getName() 3610 + " suppState:" + mSupplicantStateTracker.getSupplicantStateName()); 3611 } 3612 enableRssiPolling(screenOn); 3613 if (mUserWantsSuspendOpt.get()) { 3614 if (screenOn) { 3615 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, 0); 3616 } else { 3617 // Allow 2s for suspend optimizations to be set 3618 mSuspendWakeLock.acquire(2000); 3619 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, 0); 3620 } 3621 } 3622 mScreenBroadcastReceived.set(true); 3623 3624 getWifiLinkLayerStats(false); 3625 mOnTimeScreenStateChange = mOnTime; 3626 lastScreenStateChangeTimeStamp = lastLinkLayerStatsUpdate; 3627 3628 cancelDelayedScan(); 3629 3630 mWifiMetrics.setScreenState(screenOn); 3631 3632 if (screenOn) { 3633 enableBackgroundScan(false); 3634 setScanAlarm(false); 3635 clearBlacklist(); 3636 3637 fullBandConnectedTimeIntervalMilli 3638 = mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get(); 3639 // In either Disconnectedstate or ConnectedState, 3640 // start the scan alarm so as to enable autojoin 3641 if (getCurrentState() == mConnectedState 3642 && allowFullBandScanAndAssociated()) { 3643 if (useHalBasedAutoJoinOffload()) { 3644 startGScanConnectedModeOffload("screenOnConnected"); 3645 } else { 3646 // Scan after 500ms 3647 startDelayedScan(500, null, null); 3648 } 3649 } else if (getCurrentState() == mDisconnectedState) { 3650 if (useHalBasedAutoJoinOffload()) { 3651 startGScanDisconnectedModeOffload("screenOnDisconnected"); 3652 } else { 3653 // Scan after 500ms 3654 startDelayedScan(500, null, null); 3655 } 3656 } 3657 } else { 3658 if (getCurrentState() == mDisconnectedState) { 3659 // Screen Off and Disconnected and chipset doesn't support scan offload 3660 // => start scan alarm 3661 // Screen Off and Disconnected and chipset does support scan offload 3662 // => will use scan offload (i.e. background scan) 3663 if (useHalBasedAutoJoinOffload()) { 3664 startGScanDisconnectedModeOffload("screenOffDisconnected"); 3665 } else { 3666 if (!mBackgroundScanSupported) { 3667 setScanAlarm(true); 3668 } else { 3669 if (!mIsScanOngoing) { 3670 enableBackgroundScan(true); 3671 } 3672 } 3673 } 3674 } else { 3675 enableBackgroundScan(false); 3676 if (useHalBasedAutoJoinOffload()) { 3677 // don't try stop Gscan if it is not enabled 3678 stopGScan("ScreenOffStop(enableBackground=" + mLegacyPnoEnabled + ") "); 3679 } 3680 } 3681 } 3682 if (DBG) logd("backgroundScan enabled=" + mLegacyPnoEnabled); 3683 3684 if (DBG) log("handleScreenStateChanged Exit: " + screenOn); 3685 } 3686 3687 private void checkAndSetConnectivityInstance() { 3688 if (mCm == null) { 3689 mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 3690 } 3691 } 3692 3693 3694 /** 3695 * Set the frequency band from the system setting value, if any. 3696 */ 3697 private void setFrequencyBand() { 3698 int band = mFacade.getIntegerSetting(mContext, 3699 Settings.Global.WIFI_FREQUENCY_BAND, WifiManager.WIFI_FREQUENCY_BAND_AUTO); 3700 3701 if (mWifiNative.setBand(band)) { 3702 mFrequencyBand.set(band); 3703 mWifiQualifiedNetworkSelector.setUserPreferredBand(band); 3704 if (DBG) { 3705 logd("done set frequency band " + band); 3706 } 3707 } else { 3708 loge("Failed to set frequency band " + band); 3709 } 3710 } 3711 3712 private void setSuspendOptimizationsNative(int reason, boolean enabled) { 3713 if (DBG) { 3714 log("setSuspendOptimizationsNative: " + reason + " " + enabled 3715 + " -want " + mUserWantsSuspendOpt.get() 3716 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 3717 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 3718 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 3719 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 3720 } 3721 //mWifiNative.setSuspendOptimizations(enabled); 3722 3723 if (enabled) { 3724 mSuspendOptNeedsDisabled &= ~reason; 3725 /* None of dhcp, screen or highperf need it disabled and user wants it enabled */ 3726 if (mSuspendOptNeedsDisabled == 0 && mUserWantsSuspendOpt.get()) { 3727 if (DBG) { 3728 log("setSuspendOptimizationsNative do it " + reason + " " + enabled 3729 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 3730 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 3731 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 3732 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 3733 } 3734 mWifiNative.setSuspendOptimizations(true); 3735 } 3736 } else { 3737 mSuspendOptNeedsDisabled |= reason; 3738 mWifiNative.setSuspendOptimizations(false); 3739 } 3740 } 3741 3742 private void setSuspendOptimizations(int reason, boolean enabled) { 3743 if (DBG) log("setSuspendOptimizations: " + reason + " " + enabled); 3744 if (enabled) { 3745 mSuspendOptNeedsDisabled &= ~reason; 3746 } else { 3747 mSuspendOptNeedsDisabled |= reason; 3748 } 3749 if (DBG) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 3750 } 3751 3752 private void setWifiState(int wifiState) { 3753 final int previousWifiState = mWifiState.get(); 3754 3755 try { 3756 if (wifiState == WIFI_STATE_ENABLED) { 3757 mBatteryStats.noteWifiOn(); 3758 } else if (wifiState == WIFI_STATE_DISABLED) { 3759 mBatteryStats.noteWifiOff(); 3760 } 3761 } catch (RemoteException e) { 3762 loge("Failed to note battery stats in wifi"); 3763 } 3764 3765 mWifiState.set(wifiState); 3766 3767 if (DBG) log("setWifiState: " + syncGetWifiStateByName()); 3768 3769 final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); 3770 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3771 intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState); 3772 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState); 3773 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3774 } 3775 3776 private void setWifiApState(int wifiApState, int reason) { 3777 final int previousWifiApState = mWifiApState.get(); 3778 3779 try { 3780 if (wifiApState == WIFI_AP_STATE_ENABLED) { 3781 mBatteryStats.noteWifiOn(); 3782 } else if (wifiApState == WIFI_AP_STATE_DISABLED) { 3783 mBatteryStats.noteWifiOff(); 3784 } 3785 } catch (RemoteException e) { 3786 loge("Failed to note battery stats in wifi"); 3787 } 3788 3789 // Update state 3790 mWifiApState.set(wifiApState); 3791 3792 if (DBG) log("setWifiApState: " + syncGetWifiApStateByName()); 3793 3794 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 3795 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3796 intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState); 3797 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState); 3798 if (wifiApState == WifiManager.WIFI_AP_STATE_FAILED) { 3799 //only set reason number when softAP start failed 3800 intent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, reason); 3801 } 3802 3803 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3804 } 3805 3806 private void setScanResults() { 3807 mNumScanResultsKnown = 0; 3808 mNumScanResultsReturned = 0; 3809 3810 ArrayList<ScanDetail> scanResults = mWifiNative.getScanResults(); 3811 3812 if (scanResults.isEmpty()) { 3813 mScanResults = new ArrayList<>(); 3814 return; 3815 } 3816 3817 mWifiConfigManager.trimANQPCache(false); 3818 3819 boolean connected = mLastBssid != null; 3820 long activeBssid = 0L; 3821 if (connected) { 3822 try { 3823 activeBssid = Utils.parseMac(mLastBssid); 3824 } catch (IllegalArgumentException iae) { 3825 connected = false; 3826 } 3827 } 3828 3829 synchronized (mScanResultsLock) { 3830 ScanDetail activeScanDetail = null; 3831 mScanResults = scanResults; 3832 mNumScanResultsReturned = mScanResults.size(); 3833 for (ScanDetail resultDetail : mScanResults) { 3834 if (connected && resultDetail.getNetworkDetail().getBSSID() == activeBssid) { 3835 if (activeScanDetail == null 3836 || activeScanDetail.getNetworkDetail().getBSSID() != activeBssid 3837 || activeScanDetail.getNetworkDetail().getANQPElements() == null) { 3838 activeScanDetail = resultDetail; 3839 } 3840 } 3841 // Cache DTIM values parsed from the beacon frame Traffic Indication Map (TIM) 3842 // Information Element (IE), into the associated WifiConfigurations. Most of the 3843 // time there is no TIM IE in the scan result (Probe Response instead of Beacon 3844 // Frame), these scanResult DTIM's are negative and ignored. 3845 // <TODO> Cache these per BSSID, since dtim can change vary 3846 NetworkDetail networkDetail = resultDetail.getNetworkDetail(); 3847 if (networkDetail != null && networkDetail.getDtimInterval() > 0) { 3848 List<WifiConfiguration> associatedWifiConfigurations = 3849 mWifiConfigManager.updateSavedNetworkWithNewScanDetail(resultDetail); 3850 if (associatedWifiConfigurations != null) { 3851 for (WifiConfiguration associatedConf : associatedWifiConfigurations) { 3852 if (associatedConf != null) { 3853 associatedConf.dtimInterval = networkDetail.getDtimInterval(); 3854 } 3855 } 3856 } 3857 } 3858 } 3859 mActiveScanDetail = activeScanDetail; 3860 } 3861 3862 if (linkDebouncing) { 3863 // If debouncing, we dont re-select a SSID or BSSID hence 3864 // there is no need to call the network selection code 3865 // in WifiAutoJoinController, instead, 3866 // just try to reconnect to the same SSID by triggering a roam 3867 // The third parameter 1 means roam not from network selection but debouncing 3868 sendMessage(CMD_AUTO_ROAM, mLastNetworkId, 1, null); 3869 } else { 3870 WifiConfiguration candidate = 3871 mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, 3872 mAllowUntrustedConnections, mScanResults, linkDebouncing, isConnected(), 3873 isDisconnected(), isSupplicantTransientState()); 3874 tryToConnectToNetwork(candidate); 3875 } 3876 } 3877 3878 /** 3879 * Set whether connections to untrusted connections are allowed. 3880 */ 3881 void setAllowUntrustedConnections(boolean allow) { 3882 boolean changed = (mAllowUntrustedConnections != allow); 3883 mAllowUntrustedConnections = allow; 3884 if (changed) { 3885 // Trigger a scan so as to reattempt autojoin 3886 startScanForUntrustedSettingChange(); 3887 } 3888 } 3889 3890 public ScanDetail getActiveScanDetail() { 3891 synchronized (mScanResultsLock) { 3892 return mActiveScanDetail; 3893 } 3894 } 3895 3896 /* 3897 * Fetch RSSI, linkspeed, and frequency on current connection 3898 */ 3899 private void fetchRssiLinkSpeedAndFrequencyNative() { 3900 Integer newRssi = null; 3901 Integer newLinkSpeed = null; 3902 Integer newFrequency = null; 3903 3904 String signalPoll = mWifiNative.signalPoll(); 3905 3906 if (signalPoll != null) { 3907 String[] lines = signalPoll.split("\n"); 3908 for (String line : lines) { 3909 String[] prop = line.split("="); 3910 if (prop.length < 2) continue; 3911 try { 3912 if (prop[0].equals("RSSI")) { 3913 newRssi = Integer.parseInt(prop[1]); 3914 } else if (prop[0].equals("LINKSPEED")) { 3915 newLinkSpeed = Integer.parseInt(prop[1]); 3916 } else if (prop[0].equals("FREQUENCY")) { 3917 newFrequency = Integer.parseInt(prop[1]); 3918 } 3919 } catch (NumberFormatException e) { 3920 //Ignore, defaults on rssi and linkspeed are assigned 3921 } 3922 } 3923 } 3924 3925 if (DBG) { 3926 logd("fetchRssiLinkSpeedAndFrequencyNative rssi=" + newRssi + 3927 " linkspeed=" + newLinkSpeed + " freq=" + newFrequency); 3928 } 3929 3930 if (newRssi != null && newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) { 3931 // screen out invalid values 3932 /* some implementations avoid negative values by adding 256 3933 * so we need to adjust for that here. 3934 */ 3935 if (newRssi > 0) newRssi -= 256; 3936 mWifiInfo.setRssi(newRssi); 3937 /* 3938 * Rather then sending the raw RSSI out every time it 3939 * changes, we precalculate the signal level that would 3940 * be displayed in the status bar, and only send the 3941 * broadcast if that much more coarse-grained number 3942 * changes. This cuts down greatly on the number of 3943 * broadcasts, at the cost of not informing others 3944 * interested in RSSI of all the changes in signal 3945 * level. 3946 */ 3947 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, WifiManager.RSSI_LEVELS); 3948 if (newSignalLevel != mLastSignalLevel) { 3949 updateCapabilities(getCurrentWifiConfiguration()); 3950 sendRssiChangeBroadcast(newRssi); 3951 } 3952 mLastSignalLevel = newSignalLevel; 3953 } else { 3954 mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); 3955 updateCapabilities(getCurrentWifiConfiguration()); 3956 } 3957 3958 if (newLinkSpeed != null) { 3959 mWifiInfo.setLinkSpeed(newLinkSpeed); 3960 } 3961 if (newFrequency != null && newFrequency > 0) { 3962 if (ScanResult.is5GHz(newFrequency)) { 3963 mWifiConnectionStatistics.num5GhzConnected++; 3964 } 3965 if (ScanResult.is24GHz(newFrequency)) { 3966 mWifiConnectionStatistics.num24GhzConnected++; 3967 } 3968 mWifiInfo.setFrequency(newFrequency); 3969 } 3970 mWifiConfigManager.updateConfiguration(mWifiInfo); 3971 } 3972 3973 /** 3974 * Determine if we need to switch network: 3975 * - the delta determine the urgency to switch and/or or the expected evilness of the disruption 3976 * - match the uregncy of the switch versus the packet usage at the interface 3977 */ 3978 boolean shouldSwitchNetwork(int networkDelta) { 3979 int delta; 3980 if (networkDelta <= 0) { 3981 return false; 3982 } 3983 delta = networkDelta; 3984 if (!getEnableAutoJoinWhenAssociated() 3985 && mWifiInfo.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) { 3986 // If AutoJoin while associated is not enabled, 3987 // we should never switch network when already associated 3988 delta = -1000; 3989 } else { 3990 // TODO: Look at per AC packet count, do not switch if VO/VI traffic is present 3991 // TODO: at the interface. We should also discriminate between ucast and mcast, 3992 // TODO: since the rxSuccessRate include all the bonjour and Ipv6 3993 // TODO: broadcasts 3994 if ((mWifiInfo.txSuccessRate > 20) || (mWifiInfo.rxSuccessRate > 80)) { 3995 delta -= 999; 3996 } else if ((mWifiInfo.txSuccessRate > 5) || (mWifiInfo.rxSuccessRate > 30)) { 3997 delta -= 6; 3998 } 3999 logd("shouldSwitchNetwork " 4000 + " txSuccessRate=" + String.format("%.2f", mWifiInfo.txSuccessRate) 4001 + " rxSuccessRate=" + String.format("%.2f", mWifiInfo.rxSuccessRate) 4002 + " delta " + networkDelta + " -> " + delta); 4003 } 4004 if (delta > 0) { 4005 return true; 4006 } 4007 return false; 4008 } 4009 4010 // Polling has completed, hence we wont have a score anymore 4011 private void cleanWifiScore() { 4012 mWifiInfo.txBadRate = 0; 4013 mWifiInfo.txSuccessRate = 0; 4014 mWifiInfo.txRetriesRate = 0; 4015 mWifiInfo.rxSuccessRate = 0; 4016 mWifiScoreReport = null; 4017 } 4018 4019 // Object holding most recent wifi score report and bad Linkspeed count 4020 WifiScoreReport mWifiScoreReport = null; 4021 4022 public double getTxPacketRate() { 4023 return mWifiInfo.txSuccessRate; 4024 } 4025 4026 public double getRxPacketRate() { 4027 return mWifiInfo.rxSuccessRate; 4028 } 4029 4030 /** 4031 * Fetch TX packet counters on current connection 4032 */ 4033 private void fetchPktcntNative(RssiPacketCountInfo info) { 4034 String pktcntPoll = mWifiNative.pktcntPoll(); 4035 4036 if (pktcntPoll != null) { 4037 String[] lines = pktcntPoll.split("\n"); 4038 for (String line : lines) { 4039 String[] prop = line.split("="); 4040 if (prop.length < 2) continue; 4041 try { 4042 if (prop[0].equals("TXGOOD")) { 4043 info.txgood = Integer.parseInt(prop[1]); 4044 } else if (prop[0].equals("TXBAD")) { 4045 info.txbad = Integer.parseInt(prop[1]); 4046 } 4047 } catch (NumberFormatException e) { 4048 // Ignore 4049 } 4050 } 4051 } 4052 } 4053 4054 private void updateLinkProperties(LinkProperties newLp) { 4055 if (DBG) { 4056 log("Link configuration changed for netId: " + mLastNetworkId 4057 + " old: " + mLinkProperties + " new: " + newLp); 4058 } 4059 // We own this instance of LinkProperties because IpManager passes us a copy. 4060 mLinkProperties = newLp; 4061 if (mNetworkAgent != null) { 4062 mNetworkAgent.sendLinkProperties(mLinkProperties); 4063 } 4064 4065 if (getNetworkDetailedState() == DetailedState.CONNECTED) { 4066 // If anything has changed and we're already connected, send out a notification. 4067 // TODO: Update all callers to use NetworkCallbacks and delete this. 4068 sendLinkConfigurationChangedBroadcast(); 4069 } 4070 4071 if (DBG) { 4072 StringBuilder sb = new StringBuilder(); 4073 sb.append("updateLinkProperties nid: " + mLastNetworkId); 4074 sb.append(" state: " + getNetworkDetailedState()); 4075 4076 if (mLinkProperties != null) { 4077 sb.append(" "); 4078 sb.append(getLinkPropertiesSummary(mLinkProperties)); 4079 } 4080 logd(sb.toString()); 4081 } 4082 } 4083 4084 /** 4085 * Clears all our link properties. 4086 */ 4087 private void clearLinkProperties() { 4088 // Clear the link properties obtained from DHCP. The only caller of this 4089 // function has already called IpManager#stop(), which clears its state. 4090 synchronized (mDhcpResultsLock) { 4091 if (mDhcpResults != null) { 4092 mDhcpResults.clear(); 4093 } 4094 } 4095 4096 // Now clear the merged link properties. 4097 mLinkProperties.clear(); 4098 if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties); 4099 } 4100 4101 /** 4102 * try to update default route MAC address. 4103 */ 4104 private String updateDefaultRouteMacAddress(int timeout) { 4105 String address = null; 4106 for (RouteInfo route : mLinkProperties.getRoutes()) { 4107 if (route.isDefaultRoute() && route.hasGateway()) { 4108 InetAddress gateway = route.getGateway(); 4109 if (gateway instanceof Inet4Address) { 4110 if (DBG) { 4111 logd("updateDefaultRouteMacAddress found Ipv4 default :" 4112 + gateway.getHostAddress()); 4113 } 4114 address = macAddressFromRoute(gateway.getHostAddress()); 4115 /* The gateway's MAC address is known */ 4116 if ((address == null) && (timeout > 0)) { 4117 boolean reachable = false; 4118 try { 4119 reachable = gateway.isReachable(timeout); 4120 } catch (Exception e) { 4121 loge("updateDefaultRouteMacAddress exception reaching :" 4122 + gateway.getHostAddress()); 4123 4124 } finally { 4125 if (reachable == true) { 4126 4127 address = macAddressFromRoute(gateway.getHostAddress()); 4128 if (DBG) { 4129 logd("updateDefaultRouteMacAddress reachable (tried again) :" 4130 + gateway.getHostAddress() + " found " + address); 4131 } 4132 } 4133 } 4134 } 4135 if (address != null) { 4136 mWifiConfigManager.setDefaultGwMacAddress(mLastNetworkId, address); 4137 } 4138 } 4139 } 4140 } 4141 return address; 4142 } 4143 4144 void sendScanResultsAvailableBroadcast(boolean scanSucceeded) { 4145 Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 4146 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4147 intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, scanSucceeded); 4148 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 4149 } 4150 4151 private void sendRssiChangeBroadcast(final int newRssi) { 4152 try { 4153 mBatteryStats.noteWifiRssiChanged(newRssi); 4154 } catch (RemoteException e) { 4155 // Won't happen. 4156 } 4157 Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION); 4158 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4159 intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi); 4160 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4161 } 4162 4163 private void sendNetworkStateChangeBroadcast(String bssid) { 4164 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); 4165 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4166 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo)); 4167 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties)); 4168 if (bssid != null) 4169 intent.putExtra(WifiManager.EXTRA_BSSID, bssid); 4170 if (mNetworkInfo.getDetailedState() == DetailedState.VERIFYING_POOR_LINK || 4171 mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) { 4172 // We no longer report MAC address to third-parties and our code does 4173 // not rely on this broadcast, so just send the default MAC address. 4174 fetchRssiLinkSpeedAndFrequencyNative(); 4175 WifiInfo sentWifiInfo = new WifiInfo(mWifiInfo); 4176 sentWifiInfo.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS); 4177 intent.putExtra(WifiManager.EXTRA_WIFI_INFO, sentWifiInfo); 4178 } 4179 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4180 } 4181 4182 private WifiInfo getWiFiInfoForUid(int uid) { 4183 if (Binder.getCallingUid() == Process.myUid()) { 4184 return mWifiInfo; 4185 } 4186 4187 WifiInfo result = new WifiInfo(mWifiInfo); 4188 result.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS); 4189 4190 IBinder binder = mFacade.getService("package"); 4191 IPackageManager packageManager = IPackageManager.Stub.asInterface(binder); 4192 4193 try { 4194 if (packageManager.checkUidPermission(Manifest.permission.LOCAL_MAC_ADDRESS, 4195 uid) == PackageManager.PERMISSION_GRANTED) { 4196 result.setMacAddress(mWifiInfo.getMacAddress()); 4197 } 4198 } catch (RemoteException e) { 4199 Log.e(TAG, "Error checking receiver permission", e); 4200 } 4201 4202 return result; 4203 } 4204 4205 private void sendLinkConfigurationChangedBroadcast() { 4206 Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); 4207 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4208 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties)); 4209 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 4210 } 4211 4212 private void sendSupplicantConnectionChangedBroadcast(boolean connected) { 4213 Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 4214 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4215 intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected); 4216 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 4217 } 4218 4219 /** 4220 * Record the detailed state of a network. 4221 * 4222 * @param state the new {@code DetailedState} 4223 */ 4224 private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) { 4225 boolean hidden = false; 4226 4227 if (linkDebouncing || isRoaming()) { 4228 // There is generally a confusion in the system about colluding 4229 // WiFi Layer 2 state (as reported by supplicant) and the Network state 4230 // which leads to multiple confusion. 4231 // 4232 // If link is de-bouncing or roaming, we already have an IP address 4233 // as well we were connected and are doing L2 cycles of 4234 // reconnecting or renewing IP address to check that we still have it 4235 // This L2 link flapping should ne be reflected into the Network state 4236 // which is the state of the WiFi Network visible to Layer 3 and applications 4237 // Note that once debouncing and roaming are completed, we will 4238 // set the Network state to where it should be, or leave it as unchanged 4239 // 4240 hidden = true; 4241 } 4242 if (DBG) { 4243 log("setDetailed state, old =" 4244 + mNetworkInfo.getDetailedState() + " and new state=" + state 4245 + " hidden=" + hidden); 4246 } 4247 if (mNetworkInfo.getExtraInfo() != null && mWifiInfo.getSSID() != null 4248 && !mWifiInfo.getSSID().equals(WifiSsid.NONE)) { 4249 // Always indicate that SSID has changed 4250 if (!mNetworkInfo.getExtraInfo().equals(mWifiInfo.getSSID())) { 4251 if (DBG) { 4252 log("setDetailed state send new extra info" + mWifiInfo.getSSID()); 4253 } 4254 mNetworkInfo.setExtraInfo(mWifiInfo.getSSID()); 4255 sendNetworkStateChangeBroadcast(null); 4256 } 4257 } 4258 if (hidden == true) { 4259 return false; 4260 } 4261 4262 if (state != mNetworkInfo.getDetailedState()) { 4263 mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID()); 4264 if (mNetworkAgent != null) { 4265 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4266 } 4267 sendNetworkStateChangeBroadcast(null); 4268 return true; 4269 } 4270 return false; 4271 } 4272 4273 private DetailedState getNetworkDetailedState() { 4274 return mNetworkInfo.getDetailedState(); 4275 } 4276 4277 private SupplicantState handleSupplicantStateChange(Message message) { 4278 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 4279 SupplicantState state = stateChangeResult.state; 4280 // Supplicant state change 4281 // [31-13] Reserved for future use 4282 // [8 - 0] Supplicant state (as defined in SupplicantState.java) 4283 // 50023 supplicant_state_changed (custom|1|5) 4284 mWifiInfo.setSupplicantState(state); 4285 // If we receive a supplicant state change with an empty SSID, 4286 // this implies that wpa_supplicant is already disconnected. 4287 // We should pretend we are still connected when linkDebouncing is on. 4288 if ((stateChangeResult.wifiSsid == null 4289 || stateChangeResult.wifiSsid.toString().isEmpty()) && linkDebouncing) { 4290 return state; 4291 } 4292 // Network id is only valid when we start connecting 4293 if (SupplicantState.isConnecting(state)) { 4294 mWifiInfo.setNetworkId(stateChangeResult.networkId); 4295 } else { 4296 mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); 4297 } 4298 4299 mWifiInfo.setBSSID(stateChangeResult.BSSID); 4300 4301 if (mWhiteListedSsids != null 4302 && mWhiteListedSsids.length > 0 4303 && stateChangeResult.wifiSsid != null) { 4304 String SSID = stateChangeResult.wifiSsid.toString(); 4305 String currentSSID = mWifiInfo.getSSID(); 4306 if (SSID != null && currentSSID != null && !SSID.equals(WifiSsid.NONE)) { 4307 // Remove quote before comparing 4308 if (SSID.length() >= 2 && SSID.charAt(0) == '"' 4309 && SSID.charAt(SSID.length() - 1) == '"') { 4310 SSID = SSID.substring(1, SSID.length() - 1); 4311 } 4312 if (currentSSID.length() >= 2 && currentSSID.charAt(0) == '"' 4313 && currentSSID.charAt(currentSSID.length() - 1) == '"') { 4314 currentSSID = currentSSID.substring(1, currentSSID.length() - 1); 4315 } 4316 if ((!SSID.equals(currentSSID)) && (getCurrentState() == mConnectedState)) { 4317 lastConnectAttemptTimestamp = System.currentTimeMillis(); 4318 targetWificonfiguration = 4319 mWifiConfigManager.getWifiConfiguration(mWifiInfo.getNetworkId()); 4320 transitionTo(mRoamingState); 4321 } 4322 } 4323 } 4324 4325 mWifiInfo.setSSID(stateChangeResult.wifiSsid); 4326 mWifiInfo.setEphemeral(mWifiConfigManager.isEphemeral(mWifiInfo.getNetworkId())); 4327 if (!mWifiInfo.getMeteredHint()) { // don't override the value if already set. 4328 mWifiInfo.setMeteredHint(mWifiConfigManager.getMeteredHint(mWifiInfo.getNetworkId())); 4329 } 4330 4331 mSupplicantStateTracker.sendMessage(Message.obtain(message)); 4332 4333 return state; 4334 } 4335 4336 /** 4337 * Resets the Wi-Fi Connections by clearing any state, resetting any sockets 4338 * using the interface, stopping DHCP & disabling interface 4339 */ 4340 private void handleNetworkDisconnect() { 4341 if (DBG) log("handleNetworkDisconnect: Stopping DHCP and clearing IP" 4342 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 4343 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 4344 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 4345 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 4346 4347 stopRssiMonitoringOffload(); 4348 4349 clearCurrentConfigBSSID("handleNetworkDisconnect"); 4350 4351 stopIpManager(); 4352 4353 /* Reset data structures */ 4354 mWifiScoreReport = null; 4355 mWifiInfo.reset(); 4356 linkDebouncing = false; 4357 /* Reset roaming parameters */ 4358 mAutoRoaming = false; 4359 4360 /** 4361 * fullBandConnectedTimeIntervalMilli: 4362 * - start scans at mWifiConfigManager.wifiAssociatedShortScanIntervalMilli seconds 4363 * interval 4364 * - exponentially increase to mWifiConfigManager.associatedFullScanMaxIntervalMilli 4365 * Initialize to sane value = 20 seconds 4366 */ 4367 fullBandConnectedTimeIntervalMilli = 20 * 1000; 4368 4369 setNetworkDetailedState(DetailedState.DISCONNECTED); 4370 if (mNetworkAgent != null) { 4371 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4372 mNetworkAgent = null; 4373 } 4374 mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED); 4375 4376 /* Clear network properties */ 4377 clearLinkProperties(); 4378 4379 /* Cend event to CM & network change broadcast */ 4380 sendNetworkStateChangeBroadcast(mLastBssid); 4381 4382 /* Cancel auto roam requests */ 4383 autoRoamSetBSSID(mLastNetworkId, "any"); 4384 mLastBssid = null; 4385 registerDisconnected(); 4386 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 4387 } 4388 4389 private void handleSupplicantConnectionLoss(boolean killSupplicant) { 4390 /* Socket connection can be lost when we do a graceful shutdown 4391 * or when the driver is hung. Ensure supplicant is stopped here. 4392 */ 4393 if (killSupplicant) { 4394 mWifiMonitor.killSupplicant(mP2pSupported); 4395 } 4396 mWifiNative.closeSupplicantConnection(); 4397 sendSupplicantConnectionChangedBroadcast(false); 4398 setWifiState(WIFI_STATE_DISABLED); 4399 } 4400 4401 void handlePreDhcpSetup() { 4402 if (!mBluetoothConnectionActive) { 4403 /* 4404 * There are problems setting the Wi-Fi driver's power 4405 * mode to active when bluetooth coexistence mode is 4406 * enabled or sense. 4407 * <p> 4408 * We set Wi-Fi to active mode when 4409 * obtaining an IP address because we've found 4410 * compatibility issues with some routers with low power 4411 * mode. 4412 * <p> 4413 * In order for this active power mode to properly be set, 4414 * we disable coexistence mode until we're done with 4415 * obtaining an IP address. One exception is if we 4416 * are currently connected to a headset, since disabling 4417 * coexistence would interrupt that connection. 4418 */ 4419 // Disable the coexistence mode 4420 mWifiNative.setBluetoothCoexistenceMode( 4421 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); 4422 } 4423 4424 // Disable power save and suspend optimizations during DHCP 4425 // Note: The order here is important for now. Brcm driver changes 4426 // power settings when we control suspend mode optimizations. 4427 // TODO: Remove this comment when the driver is fixed. 4428 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false); 4429 mWifiNative.setPowerSave(false); 4430 4431 // Update link layer stats 4432 getWifiLinkLayerStats(false); 4433 4434 /* P2p discovery breaks dhcp, shut it down in order to get through this */ 4435 Message msg = new Message(); 4436 msg.what = WifiP2pServiceImpl.BLOCK_DISCOVERY; 4437 msg.arg1 = WifiP2pServiceImpl.ENABLED; 4438 msg.arg2 = DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE; 4439 msg.obj = WifiStateMachine.this; 4440 mWifiP2pChannel.sendMessage(msg); 4441 } 4442 4443 void handlePostDhcpSetup() { 4444 /* Restore power save and suspend optimizations */ 4445 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true); 4446 mWifiNative.setPowerSave(true); 4447 4448 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.BLOCK_DISCOVERY, 4449 WifiP2pServiceImpl.DISABLED); 4450 4451 // Set the coexistence mode back to its default value 4452 mWifiNative.setBluetoothCoexistenceMode( 4453 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); 4454 } 4455 4456 private void handleIPv4Success(DhcpResults dhcpResults) { 4457 if (DBG) { 4458 logd("handleIPv4Success <" + dhcpResults.toString() + ">"); 4459 logd("link address " + dhcpResults.ipAddress); 4460 } 4461 4462 Inet4Address addr; 4463 synchronized (mDhcpResultsLock) { 4464 mDhcpResults = dhcpResults; 4465 addr = (Inet4Address) dhcpResults.ipAddress.getAddress(); 4466 } 4467 4468 if (isRoaming()) { 4469 int previousAddress = mWifiInfo.getIpAddress(); 4470 int newAddress = NetworkUtils.inetAddressToInt(addr); 4471 if (previousAddress != newAddress) { 4472 logd("handleIPv4Success, roaming and address changed" + 4473 mWifiInfo + " got: " + addr); 4474 } 4475 } 4476 mWifiInfo.setInetAddress(addr); 4477 if (!mWifiInfo.getMeteredHint()) { // don't override the value if already set. 4478 mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint()); 4479 updateCapabilities(getCurrentWifiConfiguration()); 4480 } 4481 } 4482 4483 private void handleSuccessfulIpConfiguration() { 4484 mLastSignalLevel = -1; // Force update of signal strength 4485 WifiConfiguration c = getCurrentWifiConfiguration(); 4486 if (c != null) { 4487 // Reset IP failure tracking 4488 c.getNetworkSelectionStatus().clearDisableReasonCounter( 4489 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 4490 4491 // Tell the framework whether the newly connected network is trusted or untrusted. 4492 updateCapabilities(c); 4493 } 4494 if (c != null) { 4495 ScanResult result = getCurrentScanResult(); 4496 if (result == null) { 4497 logd("WifiStateMachine: handleSuccessfulIpConfiguration and no scan results" + 4498 c.configKey()); 4499 } else { 4500 // Clear the per BSSID failure count 4501 result.numIpConfigFailures = 0; 4502 // Clear the WHOLE BSSID blacklist, which means supplicant is free to retry 4503 // any BSSID, even though it may already have a non zero ip failure count, 4504 // this will typically happen if the user walks away and come back to his arrea 4505 // TODO: implement blacklisting based on a timer, i.e. keep BSSID blacklisted 4506 // in supplicant for a couple of hours or a day 4507 mWifiConfigManager.clearBssidBlacklist(); 4508 } 4509 } 4510 } 4511 4512 private void handleIPv4Failure() { 4513 // TODO: Move this to provisioning failure, not DHCP failure. 4514 // DHCPv4 failure is expected on an IPv6-only network. 4515 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_DHCP_FAILURE); 4516 if (DBG) { 4517 int count = -1; 4518 WifiConfiguration config = getCurrentWifiConfiguration(); 4519 if (config != null) { 4520 count = config.getNetworkSelectionStatus().getDisableReasonCounter( 4521 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 4522 } 4523 log("DHCP failure count=" + count); 4524 } 4525 mWifiMetrics.endConnectionEvent( 4526 WifiMetrics.ConnectionEvent.FAILURE_DHCP, 4527 WifiMetricsProto.ConnectionEvent.HLF_DHCP); 4528 synchronized(mDhcpResultsLock) { 4529 if (mDhcpResults != null) { 4530 mDhcpResults.clear(); 4531 } 4532 } 4533 if (DBG) { 4534 logd("handleIPv4Failure"); 4535 } 4536 } 4537 4538 private void handleIpConfigurationLost() { 4539 mWifiInfo.setInetAddress(null); 4540 mWifiInfo.setMeteredHint(false); 4541 4542 mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId, 4543 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 4544 4545 /* DHCP times out after about 30 seconds, we do a 4546 * disconnect thru supplicant, we will let autojoin retry connecting to the network 4547 */ 4548 mWifiNative.disconnect(); 4549 } 4550 4551 // TODO: De-duplicated this and handleIpConfigurationLost(). 4552 private void handleIpReachabilityLost() { 4553 mWifiInfo.setInetAddress(null); 4554 mWifiInfo.setMeteredHint(false); 4555 4556 // TODO: Determine whether to call some form of mWifiConfigManager.handleSSIDStateChange(). 4557 4558 // Disconnect via supplicant, and let autojoin retry connecting to the network. 4559 mWifiNative.disconnect(); 4560 } 4561 4562 private int convertFrequencyToChannelNumber(int frequency) { 4563 if (frequency >= 2412 && frequency <= 2484) { 4564 return (frequency -2412) / 5 + 1; 4565 } else if (frequency >= 5170 && frequency <=5825) { 4566 //DFS is included 4567 return (frequency -5170) / 5 + 34; 4568 } else { 4569 return 0; 4570 } 4571 } 4572 4573 private int chooseApChannel(int apBand) { 4574 int apChannel; 4575 int[] channel; 4576 4577 if (apBand == 0) { 4578 ArrayList<Integer> allowed2GChannel = 4579 mWifiApConfigStore.getAllowed2GChannel(); 4580 if (allowed2GChannel == null || allowed2GChannel.size() == 0) { 4581 //most safe channel to use 4582 if (DBG) { 4583 Log.d(TAG, "No specified 2G allowed channel list"); 4584 } 4585 apChannel = 6; 4586 } else { 4587 int index = mRandom.nextInt(allowed2GChannel.size()); 4588 apChannel = allowed2GChannel.get(index).intValue(); 4589 } 4590 } else { 4591 //5G without DFS 4592 channel = mWifiNative.getChannelsForBand(2); 4593 if (channel != null && channel.length > 0) { 4594 apChannel = channel[mRandom.nextInt(channel.length)]; 4595 apChannel = convertFrequencyToChannelNumber(apChannel); 4596 } else { 4597 Log.e(TAG, "SoftAp do not get available channel list"); 4598 apChannel = 0; 4599 } 4600 } 4601 4602 if (DBG) { 4603 Log.d(TAG, "SoftAp set on channel " + apChannel); 4604 } 4605 4606 return apChannel; 4607 } 4608 4609 /* Driver/firmware setup for soft AP. */ 4610 private boolean setupDriverForSoftAp() { 4611 if (!mWifiNative.loadDriver()) { 4612 Log.e(TAG, "Failed to load driver for softap"); 4613 return false; 4614 } 4615 4616 int index = mWifiNative.queryInterfaceIndex(mInterfaceName); 4617 if (index != -1) { 4618 if (!mWifiNative.setInterfaceUp(false)) { 4619 Log.e(TAG, "toggleInterface failed"); 4620 return false; 4621 } 4622 } else { 4623 if (DBG) Log.d(TAG, "No interfaces to bring down"); 4624 } 4625 4626 try { 4627 mNwService.wifiFirmwareReload(mInterfaceName, "AP"); 4628 if (DBG) Log.d(TAG, "Firmware reloaded in AP mode"); 4629 } catch (Exception e) { 4630 Log.e(TAG, "Failed to reload AP firmware " + e); 4631 } 4632 4633 if (!mWifiNative.startHal()) { 4634 /* starting HAL is optional */ 4635 Log.e(TAG, "Failed to start HAL"); 4636 } 4637 return true; 4638 } 4639 4640 private byte[] macAddressFromString(String macString) { 4641 String[] macBytes = macString.split(":"); 4642 if (macBytes.length != 6) { 4643 throw new IllegalArgumentException("MAC address should be 6 bytes long!"); 4644 } 4645 byte[] mac = new byte[6]; 4646 for (int i = 0; i < macBytes.length; i++) { 4647 Integer hexVal = Integer.parseInt(macBytes[i], 16); 4648 mac[i] = hexVal.byteValue(); 4649 } 4650 return mac; 4651 } 4652 4653 /* 4654 * Read a MAC address in /proc/arp/table, used by WifistateMachine 4655 * so as to record MAC address of default gateway. 4656 **/ 4657 private String macAddressFromRoute(String ipAddress) { 4658 String macAddress = null; 4659 BufferedReader reader = null; 4660 try { 4661 reader = new BufferedReader(new FileReader("/proc/net/arp")); 4662 4663 // Skip over the line bearing colum titles 4664 String line = reader.readLine(); 4665 4666 while ((line = reader.readLine()) != null) { 4667 String[] tokens = line.split("[ ]+"); 4668 if (tokens.length < 6) { 4669 continue; 4670 } 4671 4672 // ARP column format is 4673 // Address HWType HWAddress Flags Mask IFace 4674 String ip = tokens[0]; 4675 String mac = tokens[3]; 4676 4677 if (ipAddress.equals(ip)) { 4678 macAddress = mac; 4679 break; 4680 } 4681 } 4682 4683 if (macAddress == null) { 4684 loge("Did not find remoteAddress {" + ipAddress + "} in " + 4685 "/proc/net/arp"); 4686 } 4687 4688 } catch (FileNotFoundException e) { 4689 loge("Could not open /proc/net/arp to lookup mac address"); 4690 } catch (IOException e) { 4691 loge("Could not read /proc/net/arp to lookup mac address"); 4692 } finally { 4693 try { 4694 if (reader != null) { 4695 reader.close(); 4696 } 4697 } catch (IOException e) { 4698 // Do nothing 4699 } 4700 } 4701 return macAddress; 4702 4703 } 4704 4705 private class WifiNetworkFactory extends NetworkFactory { 4706 public WifiNetworkFactory(Looper l, Context c, String TAG, NetworkCapabilities f) { 4707 super(l, c, TAG, f); 4708 } 4709 4710 @Override 4711 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 4712 ++mConnectionRequests; 4713 } 4714 4715 @Override 4716 protected void releaseNetworkFor(NetworkRequest networkRequest) { 4717 --mConnectionRequests; 4718 } 4719 4720 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4721 pw.println("mConnectionRequests " + mConnectionRequests); 4722 } 4723 4724 } 4725 4726 private class UntrustedWifiNetworkFactory extends NetworkFactory { 4727 private int mUntrustedReqCount; 4728 4729 public UntrustedWifiNetworkFactory(Looper l, Context c, String tag, NetworkCapabilities f) { 4730 super(l, c, tag, f); 4731 } 4732 4733 @Override 4734 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 4735 if (!networkRequest.networkCapabilities.hasCapability( 4736 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 4737 if (++mUntrustedReqCount == 1) { 4738 setAllowUntrustedConnections(true); 4739 } 4740 } 4741 } 4742 4743 @Override 4744 protected void releaseNetworkFor(NetworkRequest networkRequest) { 4745 if (!networkRequest.networkCapabilities.hasCapability( 4746 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 4747 if (--mUntrustedReqCount == 0) { 4748 setAllowUntrustedConnections(false); 4749 } 4750 } 4751 } 4752 4753 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4754 pw.println("mUntrustedReqCount " + mUntrustedReqCount); 4755 } 4756 } 4757 4758 void maybeRegisterNetworkFactory() { 4759 if (mNetworkFactory == null) { 4760 checkAndSetConnectivityInstance(); 4761 if (mCm != null) { 4762 mNetworkFactory = new WifiNetworkFactory(getHandler().getLooper(), mContext, 4763 NETWORKTYPE, mNetworkCapabilitiesFilter); 4764 mNetworkFactory.setScoreFilter(60); 4765 mNetworkFactory.register(); 4766 4767 // We can't filter untrusted network in the capabilities filter because a trusted 4768 // network would still satisfy a request that accepts untrusted ones. 4769 mUntrustedNetworkFactory = new UntrustedWifiNetworkFactory(getHandler().getLooper(), 4770 mContext, NETWORKTYPE_UNTRUSTED, mNetworkCapabilitiesFilter); 4771 mUntrustedNetworkFactory.setScoreFilter(Integer.MAX_VALUE); 4772 mUntrustedNetworkFactory.register(); 4773 } 4774 } 4775 } 4776 4777 /******************************************************** 4778 * HSM states 4779 *******************************************************/ 4780 4781 class DefaultState extends State { 4782 @Override 4783 public boolean processMessage(Message message) { 4784 logStateAndMessage(message, this); 4785 4786 switch (message.what) { 4787 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 4788 AsyncChannel ac = (AsyncChannel) message.obj; 4789 if (ac == mWifiP2pChannel) { 4790 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 4791 mWifiP2pChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 4792 } else { 4793 loge("WifiP2pService connection failure, error=" + message.arg1); 4794 } 4795 } else { 4796 loge("got HALF_CONNECTED for unknown channel"); 4797 } 4798 break; 4799 } 4800 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 4801 AsyncChannel ac = (AsyncChannel) message.obj; 4802 if (ac == mWifiP2pChannel) { 4803 loge("WifiP2pService channel lost, message.arg1 =" + message.arg1); 4804 //TODO: Re-establish connection to state machine after a delay 4805 // mWifiP2pChannel.connect(mContext, getHandler(), 4806 // mWifiP2pManager.getMessenger()); 4807 } 4808 break; 4809 } 4810 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 4811 mBluetoothConnectionActive = (message.arg1 != 4812 BluetoothAdapter.STATE_DISCONNECTED); 4813 break; 4814 /* Synchronous call returns */ 4815 case CMD_PING_SUPPLICANT: 4816 case CMD_ENABLE_NETWORK: 4817 case CMD_ADD_OR_UPDATE_NETWORK: 4818 case CMD_REMOVE_NETWORK: 4819 case CMD_SAVE_CONFIG: 4820 replyToMessage(message, message.what, FAILURE); 4821 break; 4822 case CMD_GET_CAPABILITY_FREQ: 4823 replyToMessage(message, message.what, null); 4824 break; 4825 case CMD_GET_CONFIGURED_NETWORKS: 4826 replyToMessage(message, message.what, (List<WifiConfiguration>) null); 4827 break; 4828 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 4829 replyToMessage(message, message.what, (List<WifiConfiguration>) null); 4830 break; 4831 case CMD_ENABLE_RSSI_POLL: 4832 mEnableRssiPolling = (message.arg1 == 1); 4833 break; 4834 case CMD_SET_HIGH_PERF_MODE: 4835 if (message.arg1 == 1) { 4836 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false); 4837 } else { 4838 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true); 4839 } 4840 break; 4841 case CMD_BOOT_COMPLETED: 4842 maybeRegisterNetworkFactory(); 4843 break; 4844 case CMD_SCREEN_STATE_CHANGED: 4845 handleScreenStateChanged(message.arg1 != 0); 4846 break; 4847 /* Discard */ 4848 case CMD_START_SCAN: 4849 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4850 break; 4851 case CMD_START_SUPPLICANT: 4852 case CMD_STOP_SUPPLICANT: 4853 case CMD_STOP_SUPPLICANT_FAILED: 4854 case CMD_START_DRIVER: 4855 case CMD_STOP_DRIVER: 4856 case CMD_DRIVER_START_TIMED_OUT: 4857 case CMD_START_AP: 4858 case CMD_START_AP_FAILURE: 4859 case CMD_STOP_AP: 4860 case CMD_AP_STOPPED: 4861 case CMD_DISCONNECT: 4862 case CMD_RECONNECT: 4863 case CMD_REASSOCIATE: 4864 case CMD_RELOAD_TLS_AND_RECONNECT: 4865 case WifiMonitor.SUP_CONNECTION_EVENT: 4866 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4867 case WifiMonitor.NETWORK_CONNECTION_EVENT: 4868 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 4869 case WifiMonitor.SCAN_RESULTS_EVENT: 4870 case WifiMonitor.SCAN_FAILED_EVENT: 4871 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4872 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 4873 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 4874 case WifiMonitor.WPS_OVERLAP_EVENT: 4875 case CMD_BLACKLIST_NETWORK: 4876 case CMD_CLEAR_BLACKLIST: 4877 case CMD_SET_OPERATIONAL_MODE: 4878 case CMD_SET_FREQUENCY_BAND: 4879 case CMD_RSSI_POLL: 4880 case CMD_ENABLE_ALL_NETWORKS: 4881 case DhcpClient.CMD_PRE_DHCP_ACTION: 4882 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 4883 case DhcpClient.CMD_POST_DHCP_ACTION: 4884 case CMD_NO_NETWORKS_PERIODIC_SCAN: 4885 case CMD_DISABLE_P2P_RSP: 4886 case WifiMonitor.SUP_REQUEST_IDENTITY: 4887 case CMD_TEST_NETWORK_DISCONNECT: 4888 case CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER: 4889 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 4890 case CMD_TARGET_BSSID: 4891 case CMD_AUTO_CONNECT: 4892 case CMD_AUTO_ROAM: 4893 case CMD_AUTO_SAVE_NETWORK: 4894 case CMD_ASSOCIATED_BSSID: 4895 case CMD_UNWANTED_NETWORK: 4896 case CMD_DISCONNECTING_WATCHDOG_TIMER: 4897 case CMD_ROAM_WATCHDOG_TIMER: 4898 case CMD_DISABLE_EPHEMERAL_NETWORK: 4899 case CMD_RESTART_AUTOJOIN_OFFLOAD: 4900 case CMD_STARTED_PNO_DBG: 4901 case CMD_STARTED_GSCAN_DBG: 4902 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 4903 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4904 break; 4905 case CMD_SET_SUSPEND_OPT_ENABLED: 4906 if (message.arg1 == 1) { 4907 mSuspendWakeLock.release(); 4908 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true); 4909 } else { 4910 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false); 4911 } 4912 break; 4913 case WifiMonitor.DRIVER_HUNG_EVENT: 4914 setSupplicantRunning(false); 4915 setSupplicantRunning(true); 4916 break; 4917 case WifiManager.CONNECT_NETWORK: 4918 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 4919 WifiManager.BUSY); 4920 break; 4921 case WifiManager.FORGET_NETWORK: 4922 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 4923 WifiManager.BUSY); 4924 break; 4925 case WifiManager.SAVE_NETWORK: 4926 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 4927 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 4928 WifiManager.BUSY); 4929 break; 4930 case WifiManager.START_WPS: 4931 replyToMessage(message, WifiManager.WPS_FAILED, 4932 WifiManager.BUSY); 4933 break; 4934 case WifiManager.CANCEL_WPS: 4935 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, 4936 WifiManager.BUSY); 4937 break; 4938 case WifiManager.DISABLE_NETWORK: 4939 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 4940 WifiManager.BUSY); 4941 break; 4942 case WifiManager.RSSI_PKTCNT_FETCH: 4943 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED, 4944 WifiManager.BUSY); 4945 break; 4946 case CMD_GET_SUPPORTED_FEATURES: 4947 int featureSet = mWifiNative.getSupportedFeatureSet(); 4948 replyToMessage(message, message.what, featureSet); 4949 break; 4950 case CMD_FIRMWARE_ALERT: 4951 if (mWifiLogger != null) { 4952 byte[] buffer = (byte[])message.obj; 4953 mWifiLogger.captureAlertData(message.arg1, buffer); 4954 } 4955 break; 4956 case CMD_GET_LINK_LAYER_STATS: 4957 // Not supported hence reply with error message 4958 replyToMessage(message, message.what, null); 4959 break; 4960 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 4961 NetworkInfo info = (NetworkInfo) message.obj; 4962 mP2pConnected.set(info.isConnected()); 4963 break; 4964 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 4965 mTemporarilyDisconnectWifi = (message.arg1 == 1); 4966 replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 4967 break; 4968 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 4969 case CMD_UPDATE_LINKPROPERTIES: 4970 updateLinkProperties((LinkProperties) message.obj); 4971 break; 4972 case CMD_GET_MATCHING_CONFIG: 4973 replyToMessage(message, message.what); 4974 break; 4975 case CMD_IP_CONFIGURATION_SUCCESSFUL: 4976 case CMD_IP_CONFIGURATION_LOST: 4977 case CMD_IP_REACHABILITY_LOST: 4978 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4979 break; 4980 case CMD_GET_CONNECTION_STATISTICS: 4981 replyToMessage(message, message.what, mWifiConnectionStatistics); 4982 break; 4983 case CMD_REMOVE_APP_CONFIGURATIONS: 4984 deferMessage(message); 4985 break; 4986 case CMD_REMOVE_USER_CONFIGURATIONS: 4987 deferMessage(message); 4988 break; 4989 case CMD_START_IP_PACKET_OFFLOAD: 4990 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 4991 message.arg1, 4992 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 4993 break; 4994 case CMD_STOP_IP_PACKET_OFFLOAD: 4995 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 4996 message.arg1, 4997 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 4998 break; 4999 case CMD_START_RSSI_MONITORING_OFFLOAD: 5000 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5001 break; 5002 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 5003 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5004 break; 5005 case CMD_USER_SWITCH: 5006 mCurrentUserId = message.arg1; 5007 mWifiConfigManager.handleUserSwitch(); 5008 break; 5009 case CMD_ADD_PASSPOINT_MO: 5010 case CMD_MODIFY_PASSPOINT_MO: 5011 case CMD_QUERY_OSU_ICON: 5012 case CMD_MATCH_PROVIDER_NETWORK: 5013 /* reply with arg1 = 0 - it returns API failure to the calling app 5014 * (message.what is not looked at) 5015 */ 5016 replyToMessage(message, message.what); 5017 break; 5018 case CMD_RESET_SIM_NETWORKS: 5019 /* Defer this message until supplicant is started. */ 5020 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5021 deferMessage(message); 5022 break; 5023 case CMD_INSTALL_PACKET_FILTER: 5024 mWifiNative.installPacketFilter((byte[]) message.obj); 5025 break; 5026 default: 5027 loge("Error! unhandled message" + message); 5028 break; 5029 } 5030 return HANDLED; 5031 } 5032 } 5033 5034 class InitialState extends State { 5035 @Override 5036 public void enter() { 5037 mWifiNative.stopHal(); 5038 mWifiNative.unloadDriver(); 5039 if (mWifiP2pChannel == null) { 5040 mWifiP2pChannel = new AsyncChannel(); 5041 mWifiP2pChannel.connect(mContext, getHandler(), 5042 mWifiP2pServiceImpl.getP2pStateMachineMessenger()); 5043 } 5044 5045 if (mWifiApConfigStore == null) { 5046 mWifiApConfigStore = 5047 mFacade.makeApConfigStore(mContext, mBackupManagerProxy); 5048 } 5049 5050 if (mWifiConfigManager.enableHalBasedPno.get()) { 5051 // make sure developer Settings are in sync with the config option 5052 mHalBasedPnoEnableInDevSettings = true; 5053 } 5054 } 5055 @Override 5056 public boolean processMessage(Message message) { 5057 logStateAndMessage(message, this); 5058 switch (message.what) { 5059 case CMD_START_SUPPLICANT: 5060 if (mWifiNative.loadDriver()) { 5061 try { 5062 mNwService.wifiFirmwareReload(mInterfaceName, "STA"); 5063 } catch (Exception e) { 5064 loge("Failed to reload STA firmware " + e); 5065 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 5066 return HANDLED; 5067 } 5068 5069 try { 5070 // A runtime crash can leave the interface up and 5071 // IP addresses configured, and this affects 5072 // connectivity when supplicant starts up. 5073 // Ensure interface is down and we have no IP 5074 // addresses before a supplicant start. 5075 mNwService.setInterfaceDown(mInterfaceName); 5076 mNwService.clearInterfaceAddresses(mInterfaceName); 5077 5078 // Set privacy extensions 5079 mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true); 5080 5081 // IPv6 is enabled only as long as access point is connected since: 5082 // - IPv6 addresses and routes stick around after disconnection 5083 // - kernel is unaware when connected and fails to start IPv6 negotiation 5084 // - kernel can start autoconfiguration when 802.1x is not complete 5085 mNwService.disableIpv6(mInterfaceName); 5086 } catch (RemoteException re) { 5087 loge("Unable to change interface settings: " + re); 5088 } catch (IllegalStateException ie) { 5089 loge("Unable to change interface settings: " + ie); 5090 } 5091 5092 /* Stop a running supplicant after a runtime restart 5093 * Avoids issues with drivers that do not handle interface down 5094 * on a running supplicant properly. 5095 */ 5096 mWifiMonitor.killSupplicant(mP2pSupported); 5097 5098 if (mWifiNative.startHal() == false) { 5099 /* starting HAL is optional */ 5100 loge("Failed to start HAL"); 5101 } 5102 5103 if (mWifiNative.startSupplicant(mP2pSupported)) { 5104 setWifiState(WIFI_STATE_ENABLING); 5105 if (DBG) log("Supplicant start successful"); 5106 mWifiMonitor.startMonitoring(mInterfaceName); 5107 transitionTo(mSupplicantStartingState); 5108 } else { 5109 loge("Failed to start supplicant!"); 5110 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 5111 } 5112 } else { 5113 loge("Failed to load driver"); 5114 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 5115 } 5116 break; 5117 case CMD_START_AP: 5118 if (setupDriverForSoftAp()) { 5119 transitionTo(mSoftApState); 5120 } else { 5121 setWifiApState(WIFI_AP_STATE_FAILED, 5122 WifiManager.SAP_START_FAILURE_GENERAL); 5123 /** 5124 * Transition to InitialState (current state) to reset the 5125 * driver/HAL back to the initial state. 5126 */ 5127 transitionTo(mInitialState); 5128 } 5129 break; 5130 default: 5131 return NOT_HANDLED; 5132 } 5133 return HANDLED; 5134 } 5135 } 5136 5137 class SupplicantStartingState extends State { 5138 private void initializeWpsDetails() { 5139 String detail; 5140 detail = SystemProperties.get("ro.product.name", ""); 5141 if (!mWifiNative.setDeviceName(detail)) { 5142 loge("Failed to set device name " + detail); 5143 } 5144 detail = SystemProperties.get("ro.product.manufacturer", ""); 5145 if (!mWifiNative.setManufacturer(detail)) { 5146 loge("Failed to set manufacturer " + detail); 5147 } 5148 detail = SystemProperties.get("ro.product.model", ""); 5149 if (!mWifiNative.setModelName(detail)) { 5150 loge("Failed to set model name " + detail); 5151 } 5152 detail = SystemProperties.get("ro.product.model", ""); 5153 if (!mWifiNative.setModelNumber(detail)) { 5154 loge("Failed to set model number " + detail); 5155 } 5156 detail = SystemProperties.get("ro.serialno", ""); 5157 if (!mWifiNative.setSerialNumber(detail)) { 5158 loge("Failed to set serial number " + detail); 5159 } 5160 if (!mWifiNative.setConfigMethods("physical_display virtual_push_button")) { 5161 loge("Failed to set WPS config methods"); 5162 } 5163 if (!mWifiNative.setDeviceType(mPrimaryDeviceType)) { 5164 loge("Failed to set primary device type " + mPrimaryDeviceType); 5165 } 5166 } 5167 5168 @Override 5169 public boolean processMessage(Message message) { 5170 logStateAndMessage(message, this); 5171 5172 switch(message.what) { 5173 case WifiMonitor.SUP_CONNECTION_EVENT: 5174 if (DBG) log("Supplicant connection established"); 5175 setWifiState(WIFI_STATE_ENABLED); 5176 mSupplicantRestartCount = 0; 5177 /* Reset the supplicant state to indicate the supplicant 5178 * state is not known at this time */ 5179 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 5180 /* Initialize data structures */ 5181 mLastBssid = null; 5182 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 5183 mLastSignalLevel = -1; 5184 5185 mWifiInfo.setMacAddress(mWifiNative.getMacAddress()); 5186 /* set frequency band of operation */ 5187 setFrequencyBand(); 5188 mWifiNative.enableSaveConfig(); 5189 mWifiConfigManager.loadAndEnableAllNetworks(); 5190 if (mWifiConfigManager.enableVerboseLogging.get() > 0) { 5191 enableVerboseLogging(mWifiConfigManager.enableVerboseLogging.get()); 5192 } 5193 initializeWpsDetails(); 5194 5195 sendSupplicantConnectionChangedBroadcast(true); 5196 transitionTo(mDriverStartedState); 5197 break; 5198 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5199 if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { 5200 loge("Failed to setup control channel, restart supplicant"); 5201 mWifiMonitor.killSupplicant(mP2pSupported); 5202 transitionTo(mInitialState); 5203 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 5204 } else { 5205 loge("Failed " + mSupplicantRestartCount + 5206 " times to start supplicant, unload driver"); 5207 mSupplicantRestartCount = 0; 5208 setWifiState(WIFI_STATE_UNKNOWN); 5209 transitionTo(mInitialState); 5210 } 5211 break; 5212 case CMD_START_SUPPLICANT: 5213 case CMD_STOP_SUPPLICANT: 5214 case CMD_START_AP: 5215 case CMD_STOP_AP: 5216 case CMD_START_DRIVER: 5217 case CMD_STOP_DRIVER: 5218 case CMD_SET_OPERATIONAL_MODE: 5219 case CMD_SET_FREQUENCY_BAND: 5220 case CMD_START_PACKET_FILTERING: 5221 case CMD_STOP_PACKET_FILTERING: 5222 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5223 deferMessage(message); 5224 break; 5225 default: 5226 return NOT_HANDLED; 5227 } 5228 return HANDLED; 5229 } 5230 } 5231 5232 class SupplicantStartedState extends State { 5233 @Override 5234 public void enter() { 5235 /* Wifi is available as long as we have a connection to supplicant */ 5236 mNetworkInfo.setIsAvailable(true); 5237 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 5238 5239 int defaultInterval = mContext.getResources().getInteger( 5240 R.integer.config_wifi_supplicant_scan_interval); 5241 5242 mSupplicantScanIntervalMs = mFacade.getLongSetting(mContext, 5243 Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS, 5244 defaultInterval); 5245 5246 mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000); 5247 mWifiNative.setExternalSim(true); 5248 5249 /* turn on use of DFS channels */ 5250 mWifiNative.setDfsFlag(true); 5251 5252 setRandomMacOui(); 5253 mWifiNative.enableAutoConnect(false); 5254 mCountryCode.setReadyForChange(true); 5255 } 5256 5257 @Override 5258 public boolean processMessage(Message message) { 5259 logStateAndMessage(message, this); 5260 5261 switch(message.what) { 5262 case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */ 5263 if (mP2pSupported) { 5264 transitionTo(mWaitForP2pDisableState); 5265 } else { 5266 transitionTo(mSupplicantStoppingState); 5267 } 5268 break; 5269 case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ 5270 loge("Connection lost, restart supplicant"); 5271 handleSupplicantConnectionLoss(true); 5272 handleNetworkDisconnect(); 5273 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 5274 if (mP2pSupported) { 5275 transitionTo(mWaitForP2pDisableState); 5276 } else { 5277 transitionTo(mInitialState); 5278 } 5279 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 5280 break; 5281 case WifiMonitor.SCAN_RESULTS_EVENT: 5282 case WifiMonitor.SCAN_FAILED_EVENT: 5283 maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered 5284 noteScanEnd(); 5285 setScanResults(); 5286 if (mIsFullScanOngoing || mSendScanResultsBroadcast) { 5287 /* Just updated results from full scan, let apps know about this */ 5288 boolean scanSucceeded = message.what == WifiMonitor.SCAN_RESULTS_EVENT; 5289 sendScanResultsAvailableBroadcast(scanSucceeded); 5290 } 5291 mSendScanResultsBroadcast = false; 5292 mIsScanOngoing = false; 5293 mIsFullScanOngoing = false; 5294 if (mBufferedScanMsg.size() > 0) 5295 sendMessage(mBufferedScanMsg.remove()); 5296 break; 5297 case CMD_PING_SUPPLICANT: 5298 boolean ok = mWifiNative.ping(); 5299 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 5300 break; 5301 case CMD_GET_CAPABILITY_FREQ: 5302 String freqs = mWifiNative.getFreqCapability(); 5303 replyToMessage(message, message.what, freqs); 5304 break; 5305 case CMD_START_AP: 5306 /* Cannot start soft AP while in client mode */ 5307 loge("Failed to start soft AP with a running supplicant"); 5308 setWifiApState(WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL); 5309 break; 5310 case CMD_SET_OPERATIONAL_MODE: 5311 mOperationalMode = message.arg1; 5312 mWifiConfigManager. 5313 setAndEnableLastSelectedConfiguration( 5314 WifiConfiguration.INVALID_NETWORK_ID); 5315 break; 5316 case CMD_TARGET_BSSID: 5317 // Trying to associate to this BSSID 5318 if (message.obj != null) { 5319 mTargetRoamBSSID = (String) message.obj; 5320 } 5321 break; 5322 case CMD_GET_LINK_LAYER_STATS: 5323 WifiLinkLayerStats stats = getWifiLinkLayerStats(DBG); 5324 if (stats == null) { 5325 // When firmware doesnt support link layer stats, return an empty object 5326 stats = new WifiLinkLayerStats(); 5327 } 5328 replyToMessage(message, message.what, stats); 5329 break; 5330 case CMD_RESET_SIM_NETWORKS: 5331 log("resetting EAP-SIM/AKA/AKA' networks since SIM was removed"); 5332 mWifiConfigManager.resetSimNetworks(); 5333 break; 5334 default: 5335 return NOT_HANDLED; 5336 } 5337 return HANDLED; 5338 } 5339 5340 @Override 5341 public void exit() { 5342 mNetworkInfo.setIsAvailable(false); 5343 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 5344 mCountryCode.setReadyForChange(false); 5345 } 5346 } 5347 5348 class SupplicantStoppingState extends State { 5349 @Override 5350 public void enter() { 5351 /* Send any reset commands to supplicant before shutting it down */ 5352 handleNetworkDisconnect(); 5353 5354 String suppState = System.getProperty("init.svc.wpa_supplicant"); 5355 if (suppState == null) suppState = "unknown"; 5356 String p2pSuppState = System.getProperty("init.svc.p2p_supplicant"); 5357 if (p2pSuppState == null) p2pSuppState = "unknown"; 5358 5359 logd("SupplicantStoppingState: stopSupplicant " 5360 + " init.svc.wpa_supplicant=" + suppState 5361 + " init.svc.p2p_supplicant=" + p2pSuppState); 5362 mWifiMonitor.stopSupplicant(); 5363 5364 /* Send ourselves a delayed message to indicate failure after a wait time */ 5365 sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED, 5366 ++mSupplicantStopFailureToken, 0), SUPPLICANT_RESTART_INTERVAL_MSECS); 5367 setWifiState(WIFI_STATE_DISABLING); 5368 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 5369 } 5370 @Override 5371 public boolean processMessage(Message message) { 5372 logStateAndMessage(message, this); 5373 5374 switch(message.what) { 5375 case WifiMonitor.SUP_CONNECTION_EVENT: 5376 loge("Supplicant connection received while stopping"); 5377 break; 5378 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5379 if (DBG) log("Supplicant connection lost"); 5380 handleSupplicantConnectionLoss(false); 5381 transitionTo(mInitialState); 5382 break; 5383 case CMD_STOP_SUPPLICANT_FAILED: 5384 if (message.arg1 == mSupplicantStopFailureToken) { 5385 loge("Timed out on a supplicant stop, kill and proceed"); 5386 handleSupplicantConnectionLoss(true); 5387 transitionTo(mInitialState); 5388 } 5389 break; 5390 case CMD_START_SUPPLICANT: 5391 case CMD_STOP_SUPPLICANT: 5392 case CMD_START_AP: 5393 case CMD_STOP_AP: 5394 case CMD_START_DRIVER: 5395 case CMD_STOP_DRIVER: 5396 case CMD_SET_OPERATIONAL_MODE: 5397 case CMD_SET_FREQUENCY_BAND: 5398 case CMD_START_PACKET_FILTERING: 5399 case CMD_STOP_PACKET_FILTERING: 5400 deferMessage(message); 5401 break; 5402 default: 5403 return NOT_HANDLED; 5404 } 5405 return HANDLED; 5406 } 5407 } 5408 5409 class DriverStartingState extends State { 5410 private int mTries; 5411 @Override 5412 public void enter() { 5413 mTries = 1; 5414 /* Send ourselves a delayed message to start driver a second time */ 5415 sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT, 5416 ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS); 5417 } 5418 @Override 5419 public boolean processMessage(Message message) { 5420 logStateAndMessage(message, this); 5421 5422 switch(message.what) { 5423 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5424 SupplicantState state = handleSupplicantStateChange(message); 5425 /* If suplicant is exiting out of INTERFACE_DISABLED state into 5426 * a state that indicates driver has started, it is ready to 5427 * receive driver commands 5428 */ 5429 if (SupplicantState.isDriverActive(state)) { 5430 transitionTo(mDriverStartedState); 5431 } 5432 break; 5433 case CMD_DRIVER_START_TIMED_OUT: 5434 if (message.arg1 == mDriverStartToken) { 5435 if (mTries >= 2) { 5436 loge("Failed to start driver after " + mTries); 5437 setSupplicantRunning(false); 5438 setSupplicantRunning(true); 5439 } else { 5440 loge("Driver start failed, retrying"); 5441 mWakeLock.acquire(); 5442 mWifiNative.startDriver(); 5443 mWakeLock.release(); 5444 5445 ++mTries; 5446 /* Send ourselves a delayed message to start driver again */ 5447 sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT, 5448 ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS); 5449 } 5450 } 5451 break; 5452 /* Queue driver commands & connection events */ 5453 case CMD_START_DRIVER: 5454 case CMD_STOP_DRIVER: 5455 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5456 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5457 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 5458 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 5459 case WifiMonitor.WPS_OVERLAP_EVENT: 5460 case CMD_SET_FREQUENCY_BAND: 5461 case CMD_START_PACKET_FILTERING: 5462 case CMD_STOP_PACKET_FILTERING: 5463 case CMD_START_SCAN: 5464 case CMD_DISCONNECT: 5465 case CMD_REASSOCIATE: 5466 case CMD_RECONNECT: 5467 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5468 deferMessage(message); 5469 break; 5470 case WifiMonitor.SCAN_RESULTS_EVENT: 5471 case WifiMonitor.SCAN_FAILED_EVENT: 5472 // Loose scan results obtained in Driver Starting state, they can only confuse 5473 // the state machine 5474 break; 5475 default: 5476 return NOT_HANDLED; 5477 } 5478 return HANDLED; 5479 } 5480 } 5481 5482 class DriverStartedState extends State { 5483 @Override 5484 public void enter() { 5485 if (DBG) { 5486 logd("DriverStartedState enter"); 5487 } 5488 5489 // We can't do this in the constructor because WifiStateMachine is created before the 5490 // wifi scanning service is initialized 5491 if (mWifiScanner == null) { 5492 mWifiScanner = 5493 (WifiScanner) mContext.getSystemService(Context.WIFI_SCANNING_SERVICE); 5494 } 5495 5496 mWifiLogger.startLogging(DBG); 5497 mIsRunning = true; 5498 updateBatteryWorkSource(null); 5499 /** 5500 * Enable bluetooth coexistence scan mode when bluetooth connection is active. 5501 * When this mode is on, some of the low-level scan parameters used by the 5502 * driver are changed to reduce interference with bluetooth 5503 */ 5504 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 5505 /* initialize network state */ 5506 setNetworkDetailedState(DetailedState.DISCONNECTED); 5507 5508 /* Remove any filtering on Multicast v6 at start */ 5509 mWifiNative.stopFilteringMulticastV6Packets(); 5510 5511 /* Reset Multicast v4 filtering state */ 5512 if (mFilteringMulticastV4Packets.get()) { 5513 mWifiNative.startFilteringMulticastV4Packets(); 5514 } else { 5515 mWifiNative.stopFilteringMulticastV4Packets(); 5516 } 5517 5518 if (mOperationalMode != CONNECT_MODE) { 5519 mWifiNative.disconnect(); 5520 mWifiConfigManager.disableAllNetworksNative(); 5521 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 5522 setWifiState(WIFI_STATE_DISABLED); 5523 } 5524 transitionTo(mScanModeState); 5525 } else { 5526 5527 // Status pulls in the current supplicant state and network connection state 5528 // events over the monitor connection. This helps framework sync up with 5529 // current supplicant state 5530 // TODO: actually check th supplicant status string and make sure the supplicant 5531 // is in disconnecte4d state. 5532 mWifiNative.status(); 5533 // Transitioning to Disconnected state will trigger a scan and subsequently AutoJoin 5534 transitionTo(mDisconnectedState); 5535 transitionTo(mDisconnectedState); 5536 } 5537 5538 // We may have missed screen update at boot 5539 if (mScreenBroadcastReceived.get() == false) { 5540 PowerManager powerManager = (PowerManager)mContext.getSystemService( 5541 Context.POWER_SERVICE); 5542 handleScreenStateChanged(powerManager.isScreenOn()); 5543 } else { 5544 // Set the right suspend mode settings 5545 mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0 5546 && mUserWantsSuspendOpt.get()); 5547 } 5548 mWifiNative.setPowerSave(true); 5549 5550 if (mP2pSupported) { 5551 if (mOperationalMode == CONNECT_MODE) { 5552 mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P); 5553 } else { 5554 // P2P statemachine starts in disabled state, and is not enabled until 5555 // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to 5556 // keep it disabled. 5557 } 5558 } 5559 5560 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 5561 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5562 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED); 5563 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5564 5565 mHalFeatureSet = mWifiNative.getSupportedFeatureSet(); 5566 if ((mHalFeatureSet & WifiManager.WIFI_FEATURE_HAL_EPNO) 5567 == WifiManager.WIFI_FEATURE_HAL_EPNO) { 5568 mHalBasedPnoDriverSupported = true; 5569 } 5570 5571 // Enable link layer stats gathering 5572 mWifiNative.setWifiLinkLayerStats("wlan0", 1); 5573 5574 if (DBG) { 5575 logd("Driverstarted State enter done, epno=" + mHalBasedPnoDriverSupported 5576 + " feature=" + mHalFeatureSet); 5577 } 5578 } 5579 5580 @Override 5581 public boolean processMessage(Message message) { 5582 logStateAndMessage(message, this); 5583 5584 switch(message.what) { 5585 case CMD_START_SCAN: 5586 handleScanRequest(message); 5587 break; 5588 case CMD_SET_FREQUENCY_BAND: 5589 int band = message.arg1; 5590 if (DBG) log("set frequency band " + band); 5591 if (mWifiNative.setBand(band)) { 5592 5593 if (DBG) logd("did set frequency band " + band); 5594 5595 mFrequencyBand.set(band); 5596 // Flush old data - like scan results 5597 mWifiNative.bssFlush(); 5598 5599 if (DBG) logd("done set frequency band " + band); 5600 5601 } else { 5602 loge("Failed to set frequency band " + band); 5603 } 5604 break; 5605 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 5606 mBluetoothConnectionActive = (message.arg1 != 5607 BluetoothAdapter.STATE_DISCONNECTED); 5608 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 5609 break; 5610 case CMD_STOP_DRIVER: 5611 int mode = message.arg1; 5612 5613 log("stop driver"); 5614 mWifiConfigManager.disableAllNetworksNative(); 5615 5616 if (getCurrentState() != mDisconnectedState) { 5617 mWifiNative.disconnect(); 5618 handleNetworkDisconnect(); 5619 } 5620 mWakeLock.acquire(); 5621 mWifiNative.stopDriver(); 5622 mWakeLock.release(); 5623 if (mP2pSupported) { 5624 transitionTo(mWaitForP2pDisableState); 5625 } else { 5626 transitionTo(mDriverStoppingState); 5627 } 5628 break; 5629 case CMD_START_DRIVER: 5630 if (mOperationalMode == CONNECT_MODE) { 5631 mWifiConfigManager.enableAllNetworks(); 5632 } 5633 break; 5634 case CMD_START_PACKET_FILTERING: 5635 if (message.arg1 == MULTICAST_V6) { 5636 mWifiNative.startFilteringMulticastV6Packets(); 5637 } else if (message.arg1 == MULTICAST_V4) { 5638 mWifiNative.startFilteringMulticastV4Packets(); 5639 } else { 5640 loge("Illegal arugments to CMD_START_PACKET_FILTERING"); 5641 } 5642 break; 5643 case CMD_STOP_PACKET_FILTERING: 5644 if (message.arg1 == MULTICAST_V6) { 5645 mWifiNative.stopFilteringMulticastV6Packets(); 5646 } else if (message.arg1 == MULTICAST_V4) { 5647 mWifiNative.stopFilteringMulticastV4Packets(); 5648 } else { 5649 loge("Illegal arugments to CMD_STOP_PACKET_FILTERING"); 5650 } 5651 break; 5652 case CMD_SET_SUSPEND_OPT_ENABLED: 5653 if (message.arg1 == 1) { 5654 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); 5655 mSuspendWakeLock.release(); 5656 } else { 5657 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); 5658 } 5659 break; 5660 case CMD_SET_HIGH_PERF_MODE: 5661 if (message.arg1 == 1) { 5662 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); 5663 } else { 5664 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); 5665 } 5666 break; 5667 case CMD_ENABLE_TDLS: 5668 if (message.obj != null) { 5669 String remoteAddress = (String) message.obj; 5670 boolean enable = (message.arg1 == 1); 5671 mWifiNative.startTdls(remoteAddress, enable); 5672 } 5673 break; 5674 case WifiMonitor.ANQP_DONE_EVENT: 5675 mWifiConfigManager.notifyANQPDone((Long) message.obj, message.arg1 != 0); 5676 break; 5677 case CMD_STOP_IP_PACKET_OFFLOAD: { 5678 int slot = message.arg1; 5679 int ret = stopWifiIPPacketOffload(slot); 5680 if (mNetworkAgent != null) { 5681 mNetworkAgent.onPacketKeepaliveEvent(slot, ret); 5682 } 5683 break; 5684 } 5685 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 5686 mWifiConfigManager.notifyIconReceived((IconEvent) message.obj); 5687 break; 5688 case WifiMonitor.HS20_REMEDIATION_EVENT: 5689 mWifiConfigManager.wnmFrameReceived((WnmData) message.obj); 5690 break; 5691 default: 5692 return NOT_HANDLED; 5693 } 5694 return HANDLED; 5695 } 5696 @Override 5697 public void exit() { 5698 5699 mWifiLogger.stopLogging(); 5700 5701 mIsRunning = false; 5702 updateBatteryWorkSource(null); 5703 mScanResults = new ArrayList<>(); 5704 5705 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 5706 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5707 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); 5708 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5709 noteScanEnd(); // wrap up any pending request. 5710 mBufferedScanMsg.clear(); 5711 } 5712 } 5713 5714 class WaitForP2pDisableState extends State { 5715 private State mTransitionToState; 5716 @Override 5717 public void enter() { 5718 switch (getCurrentMessage().what) { 5719 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5720 mTransitionToState = mInitialState; 5721 break; 5722 case CMD_STOP_DRIVER: 5723 mTransitionToState = mDriverStoppingState; 5724 break; 5725 case CMD_STOP_SUPPLICANT: 5726 mTransitionToState = mSupplicantStoppingState; 5727 break; 5728 default: 5729 mTransitionToState = mDriverStoppingState; 5730 break; 5731 } 5732 mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ); 5733 } 5734 @Override 5735 public boolean processMessage(Message message) { 5736 logStateAndMessage(message, this); 5737 5738 switch(message.what) { 5739 case WifiStateMachine.CMD_DISABLE_P2P_RSP: 5740 transitionTo(mTransitionToState); 5741 break; 5742 /* Defer wifi start/shut and driver commands */ 5743 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5744 case CMD_START_SUPPLICANT: 5745 case CMD_STOP_SUPPLICANT: 5746 case CMD_START_AP: 5747 case CMD_STOP_AP: 5748 case CMD_START_DRIVER: 5749 case CMD_STOP_DRIVER: 5750 case CMD_SET_OPERATIONAL_MODE: 5751 case CMD_SET_FREQUENCY_BAND: 5752 case CMD_START_PACKET_FILTERING: 5753 case CMD_STOP_PACKET_FILTERING: 5754 case CMD_START_SCAN: 5755 case CMD_DISCONNECT: 5756 case CMD_REASSOCIATE: 5757 case CMD_RECONNECT: 5758 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5759 deferMessage(message); 5760 break; 5761 default: 5762 return NOT_HANDLED; 5763 } 5764 return HANDLED; 5765 } 5766 } 5767 5768 class DriverStoppingState extends State { 5769 @Override 5770 public boolean processMessage(Message message) { 5771 logStateAndMessage(message, this); 5772 5773 switch(message.what) { 5774 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5775 SupplicantState state = handleSupplicantStateChange(message); 5776 if (state == SupplicantState.INTERFACE_DISABLED) { 5777 transitionTo(mDriverStoppedState); 5778 } 5779 break; 5780 /* Queue driver commands */ 5781 case CMD_START_DRIVER: 5782 case CMD_STOP_DRIVER: 5783 case CMD_SET_FREQUENCY_BAND: 5784 case CMD_START_PACKET_FILTERING: 5785 case CMD_STOP_PACKET_FILTERING: 5786 case CMD_START_SCAN: 5787 case CMD_DISCONNECT: 5788 case CMD_REASSOCIATE: 5789 case CMD_RECONNECT: 5790 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5791 deferMessage(message); 5792 break; 5793 default: 5794 return NOT_HANDLED; 5795 } 5796 return HANDLED; 5797 } 5798 } 5799 5800 class DriverStoppedState extends State { 5801 @Override 5802 public boolean processMessage(Message message) { 5803 logStateAndMessage(message, this); 5804 switch (message.what) { 5805 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5806 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 5807 SupplicantState state = stateChangeResult.state; 5808 // A WEXT bug means that we can be back to driver started state 5809 // unexpectedly 5810 if (SupplicantState.isDriverActive(state)) { 5811 transitionTo(mDriverStartedState); 5812 } 5813 break; 5814 case CMD_START_DRIVER: 5815 mWakeLock.acquire(); 5816 mWifiNative.startDriver(); 5817 mWakeLock.release(); 5818 transitionTo(mDriverStartingState); 5819 break; 5820 default: 5821 return NOT_HANDLED; 5822 } 5823 return HANDLED; 5824 } 5825 } 5826 5827 class ScanModeState extends State { 5828 private int mLastOperationMode; 5829 @Override 5830 public void enter() { 5831 mLastOperationMode = mOperationalMode; 5832 } 5833 @Override 5834 public boolean processMessage(Message message) { 5835 logStateAndMessage(message, this); 5836 5837 switch(message.what) { 5838 case CMD_SET_OPERATIONAL_MODE: 5839 if (message.arg1 == CONNECT_MODE) { 5840 5841 if (mLastOperationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 5842 setWifiState(WIFI_STATE_ENABLED); 5843 // Load and re-enable networks when going back to enabled state 5844 // This is essential for networks to show up after restore 5845 mWifiConfigManager.loadAndEnableAllNetworks(); 5846 mWifiP2pChannel.sendMessage(CMD_ENABLE_P2P); 5847 } else { 5848 mWifiConfigManager.enableAllNetworks(); 5849 } 5850 // start a scan to trigger Quality network selection 5851 startScan(ENABLE_WIFI, 0, null, null); 5852 5853 // Loose last selection choice since user toggled WiFi 5854 mWifiConfigManager. 5855 setAndEnableLastSelectedConfiguration( 5856 WifiConfiguration.INVALID_NETWORK_ID); 5857 5858 mOperationalMode = CONNECT_MODE; 5859 transitionTo(mDisconnectedState); 5860 } else { 5861 // Nothing to do 5862 return HANDLED; 5863 } 5864 break; 5865 // Handle scan. All the connection related commands are 5866 // handled only in ConnectModeState 5867 case CMD_START_SCAN: 5868 handleScanRequest(message); 5869 break; 5870 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5871 SupplicantState state = handleSupplicantStateChange(message); 5872 if (DBG) log("SupplicantState= " + state); 5873 break; 5874 default: 5875 return NOT_HANDLED; 5876 } 5877 return HANDLED; 5878 } 5879 } 5880 5881 5882 String smToString(Message message) { 5883 return smToString(message.what); 5884 } 5885 5886 String smToString(int what) { 5887 String s = sSmToString.get(what); 5888 if (s != null) { 5889 return s; 5890 } 5891 switch (what) { 5892 case WifiMonitor.DRIVER_HUNG_EVENT: 5893 s = "DRIVER_HUNG_EVENT"; 5894 break; 5895 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 5896 s = "AsyncChannel.CMD_CHANNEL_HALF_CONNECTED"; 5897 break; 5898 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 5899 s = "AsyncChannel.CMD_CHANNEL_DISCONNECTED"; 5900 break; 5901 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 5902 s = "WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST"; 5903 break; 5904 case WifiManager.DISABLE_NETWORK: 5905 s = "WifiManager.DISABLE_NETWORK"; 5906 break; 5907 case WifiManager.CONNECT_NETWORK: 5908 s = "CONNECT_NETWORK"; 5909 break; 5910 case WifiManager.SAVE_NETWORK: 5911 s = "SAVE_NETWORK"; 5912 break; 5913 case WifiManager.FORGET_NETWORK: 5914 s = "FORGET_NETWORK"; 5915 break; 5916 case WifiMonitor.SUP_CONNECTION_EVENT: 5917 s = "SUP_CONNECTION_EVENT"; 5918 break; 5919 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5920 s = "SUP_DISCONNECTION_EVENT"; 5921 break; 5922 case WifiMonitor.SCAN_RESULTS_EVENT: 5923 s = "SCAN_RESULTS_EVENT"; 5924 break; 5925 case WifiMonitor.SCAN_FAILED_EVENT: 5926 s = "SCAN_FAILED_EVENT"; 5927 break; 5928 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5929 s = "SUPPLICANT_STATE_CHANGE_EVENT"; 5930 break; 5931 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 5932 s = "AUTHENTICATION_FAILURE_EVENT"; 5933 break; 5934 case WifiMonitor.SSID_TEMP_DISABLED: 5935 s = "SSID_TEMP_DISABLED"; 5936 break; 5937 case WifiMonitor.SSID_REENABLED: 5938 s = "SSID_REENABLED"; 5939 break; 5940 case WifiMonitor.WPS_SUCCESS_EVENT: 5941 s = "WPS_SUCCESS_EVENT"; 5942 break; 5943 case WifiMonitor.WPS_FAIL_EVENT: 5944 s = "WPS_FAIL_EVENT"; 5945 break; 5946 case WifiMonitor.SUP_REQUEST_IDENTITY: 5947 s = "SUP_REQUEST_IDENTITY"; 5948 break; 5949 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5950 s = "NETWORK_CONNECTION_EVENT"; 5951 break; 5952 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5953 s = "NETWORK_DISCONNECTION_EVENT"; 5954 break; 5955 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 5956 s = "ASSOCIATION_REJECTION_EVENT"; 5957 break; 5958 case WifiMonitor.ANQP_DONE_EVENT: 5959 s = "WifiMonitor.ANQP_DONE_EVENT"; 5960 break; 5961 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 5962 s = "WifiMonitor.RX_HS20_ANQP_ICON_EVENT"; 5963 break; 5964 case WifiMonitor.GAS_QUERY_DONE_EVENT: 5965 s = "WifiMonitor.GAS_QUERY_DONE_EVENT"; 5966 break; 5967 case WifiMonitor.HS20_REMEDIATION_EVENT: 5968 s = "WifiMonitor.HS20_REMEDIATION_EVENT"; 5969 break; 5970 case WifiMonitor.GAS_QUERY_START_EVENT: 5971 s = "WifiMonitor.GAS_QUERY_START_EVENT"; 5972 break; 5973 case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT: 5974 s = "GROUP_CREATING_TIMED_OUT"; 5975 break; 5976 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 5977 s = "P2P_CONNECTION_CHANGED"; 5978 break; 5979 case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE: 5980 s = "P2P.DISCONNECT_WIFI_RESPONSE"; 5981 break; 5982 case WifiP2pServiceImpl.SET_MIRACAST_MODE: 5983 s = "P2P.SET_MIRACAST_MODE"; 5984 break; 5985 case WifiP2pServiceImpl.BLOCK_DISCOVERY: 5986 s = "P2P.BLOCK_DISCOVERY"; 5987 break; 5988 case WifiManager.CANCEL_WPS: 5989 s = "CANCEL_WPS"; 5990 break; 5991 case WifiManager.CANCEL_WPS_FAILED: 5992 s = "CANCEL_WPS_FAILED"; 5993 break; 5994 case WifiManager.CANCEL_WPS_SUCCEDED: 5995 s = "CANCEL_WPS_SUCCEDED"; 5996 break; 5997 case WifiManager.START_WPS: 5998 s = "START_WPS"; 5999 break; 6000 case WifiManager.START_WPS_SUCCEEDED: 6001 s = "START_WPS_SUCCEEDED"; 6002 break; 6003 case WifiManager.WPS_FAILED: 6004 s = "WPS_FAILED"; 6005 break; 6006 case WifiManager.WPS_COMPLETED: 6007 s = "WPS_COMPLETED"; 6008 break; 6009 case WifiManager.RSSI_PKTCNT_FETCH: 6010 s = "RSSI_PKTCNT_FETCH"; 6011 break; 6012 default: 6013 s = "what:" + Integer.toString(what); 6014 break; 6015 } 6016 return s; 6017 } 6018 6019 void registerConnected() { 6020 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6021 WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 6022 if (config != null) { 6023 //Here we will clear all disable counters once a network is connected 6024 //records how long this network is connected in future 6025 config.lastConnected = System.currentTimeMillis(); 6026 config.getNetworkSelectionStatus().clearDisableReasonCounter(); 6027 config.numAssociation++; 6028 } 6029 // On connect, reset wifiScoreReport 6030 mWifiScoreReport = null; 6031 } 6032 } 6033 6034 void registerDisconnected() { 6035 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6036 // We are switching away from this configuration, 6037 // hence record the time we were connected last 6038 WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 6039 if (config != null) { 6040 config.lastDisconnected = System.currentTimeMillis(); 6041 if (config.ephemeral) { 6042 // Remove ephemeral WifiConfigurations from file 6043 mWifiConfigManager.forgetNetwork(mLastNetworkId); 6044 } 6045 } 6046 } 6047 } 6048 6049 void noteWifiDisabledWhileAssociated() { 6050 // We got disabled by user while we were associated, make note of it 6051 int rssi = mWifiInfo.getRssi(); 6052 WifiConfiguration config = getCurrentWifiConfiguration(); 6053 if (getCurrentState() == mConnectedState 6054 && rssi != WifiInfo.INVALID_RSSI 6055 && config != null) { 6056 boolean is24GHz = mWifiInfo.is24GHz(); 6057 boolean isBadRSSI = (is24GHz && rssi < mWifiConfigManager.thresholdMinimumRssi24.get()) 6058 || (!is24GHz && rssi < mWifiConfigManager.thresholdMinimumRssi5.get()); 6059 boolean isLowRSSI = 6060 (is24GHz && rssi < mWifiConfigManager.thresholdQualifiedRssi24.get()) 6061 || (!is24GHz && mWifiInfo.getRssi() < 6062 mWifiConfigManager.thresholdQualifiedRssi5.get()); 6063 boolean isHighRSSI = (is24GHz && rssi 6064 >= mWifiConfigManager.thresholdSaturatedRssi24.get()) 6065 || (!is24GHz && mWifiInfo.getRssi() 6066 >= mWifiConfigManager.thresholdSaturatedRssi5.get()); 6067 if (isBadRSSI) { 6068 // Take note that we got disabled while RSSI was Bad 6069 config.numUserTriggeredWifiDisableLowRSSI++; 6070 } else if (isLowRSSI) { 6071 // Take note that we got disabled while RSSI was Low 6072 config.numUserTriggeredWifiDisableBadRSSI++; 6073 } else if (!isHighRSSI) { 6074 // Take note that we got disabled while RSSI was Not high 6075 config.numUserTriggeredWifiDisableNotHighRSSI++; 6076 } 6077 } 6078 } 6079 6080 WifiConfiguration getCurrentWifiConfiguration() { 6081 if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 6082 return null; 6083 } 6084 return mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 6085 } 6086 6087 ScanResult getCurrentScanResult() { 6088 WifiConfiguration config = getCurrentWifiConfiguration(); 6089 if (config == null) { 6090 return null; 6091 } 6092 String BSSID = mWifiInfo.getBSSID(); 6093 if (BSSID == null) { 6094 BSSID = mTargetRoamBSSID; 6095 } 6096 ScanDetailCache scanDetailCache = 6097 mWifiConfigManager.getScanDetailCache(config); 6098 6099 if (scanDetailCache == null) { 6100 return null; 6101 } 6102 6103 return scanDetailCache.get(BSSID); 6104 } 6105 6106 String getCurrentBSSID() { 6107 if (linkDebouncing) { 6108 return null; 6109 } 6110 return mLastBssid; 6111 } 6112 6113 class ConnectModeState extends State { 6114 6115 @Override 6116 public void enter() { 6117 // Inform metrics that Wifi is Enabled (but not yet connected) 6118 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 6119 } 6120 6121 @Override 6122 public void exit() { 6123 // Inform metrics that Wifi is being disabled (Toggled, airplane enabled, etc) 6124 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISABLED); 6125 } 6126 6127 @Override 6128 public boolean processMessage(Message message) { 6129 WifiConfiguration config; 6130 int netId; 6131 boolean ok; 6132 boolean didDisconnect; 6133 String bssid; 6134 String ssid; 6135 NetworkUpdateResult result; 6136 logStateAndMessage(message, this); 6137 6138 switch (message.what) { 6139 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 6140 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_ASSOC_FAILURE); 6141 didBlackListBSSID = false; 6142 bssid = (String) message.obj; 6143 if (bssid == null || TextUtils.isEmpty(bssid)) { 6144 // If BSSID is null, use the target roam BSSID 6145 bssid = mTargetRoamBSSID; 6146 } 6147 if (bssid != null) { 6148 // If we have a BSSID, tell configStore to black list it 6149 didBlackListBSSID = mWifiQualifiedNetworkSelector 6150 .enableBssidForQualityNetworkSelection(bssid, false); 6151 } 6152 6153 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 6154 WifiConfiguration.NetworkSelectionStatus 6155 .DISABLED_ASSOCIATION_REJECTION); 6156 6157 mSupplicantStateTracker.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT); 6158 //If rejection occurred while Metrics is tracking a ConnnectionEvent, end it. 6159 mWifiMetrics.endConnectionEvent( 6160 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, 6161 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6162 break; 6163 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 6164 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_AUTH_FAILURE); 6165 mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); 6166 if (mTargetNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6167 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 6168 WifiConfiguration.NetworkSelectionStatus 6169 .DISABLED_AUTHENTICATION_FAILURE); 6170 } 6171 //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. 6172 mWifiMetrics.endConnectionEvent( 6173 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, 6174 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6175 break; 6176 case WifiMonitor.SSID_TEMP_DISABLED: 6177 Log.e(TAG, "Supplicant SSID temporary disabled:" 6178 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 6179 mWifiConfigManager.updateNetworkSelectionStatus( 6180 message.arg1, 6181 WifiConfiguration.NetworkSelectionStatus 6182 .DISABLED_AUTHENTICATION_FAILURE); 6183 mWifiMetrics.endConnectionEvent( 6184 WifiMetrics.ConnectionEvent.FAILURE_SSID_TEMP_DISABLED, 6185 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6186 break; 6187 case WifiMonitor.SSID_REENABLED: 6188 Log.d(TAG, "Supplicant SSID reenable:" 6189 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 6190 // Do not re-enable it in Quality Network Selection since framework has its own 6191 // Algorithm of disable/enable 6192 break; 6193 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6194 SupplicantState state = handleSupplicantStateChange(message); 6195 // A driver/firmware hang can now put the interface in a down state. 6196 // We detect the interface going down and recover from it 6197 if (!SupplicantState.isDriverActive(state)) { 6198 if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 6199 handleNetworkDisconnect(); 6200 } 6201 log("Detected an interface down, restart driver"); 6202 transitionTo(mDriverStoppedState); 6203 sendMessage(CMD_START_DRIVER); 6204 break; 6205 } 6206 6207 // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT 6208 // when authentication times out after a successful connection, 6209 // we can figure this from the supplicant state. If supplicant 6210 // state is DISCONNECTED, but the mNetworkInfo says we are not 6211 // disconnected, we need to handle a disconnection 6212 if (!linkDebouncing && state == SupplicantState.DISCONNECTED && 6213 mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 6214 if (DBG) log("Missed CTRL-EVENT-DISCONNECTED, disconnect"); 6215 handleNetworkDisconnect(); 6216 transitionTo(mDisconnectedState); 6217 } 6218 6219 // If we have COMPLETED a connection to a BSSID, start doing 6220 // DNAv4/DNAv6 -style probing for on-link neighbors of 6221 // interest (e.g. routers); harmless if none are configured. 6222 if (state == SupplicantState.COMPLETED) { 6223 mIpManager.confirmConfiguration(); 6224 } 6225 break; 6226 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 6227 if (message.arg1 == 1) { 6228 mWifiNative.disconnect(); 6229 mTemporarilyDisconnectWifi = true; 6230 } else { 6231 mWifiNative.reconnect(); 6232 mTemporarilyDisconnectWifi = false; 6233 } 6234 break; 6235 case CMD_ADD_OR_UPDATE_NETWORK: 6236 // Only the current foreground user can modify networks. 6237 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6238 loge("Only the current foreground user can modify networks " 6239 + " currentUserId=" + mCurrentUserId 6240 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6241 replyToMessage(message, message.what, FAILURE); 6242 break; 6243 } 6244 6245 config = (WifiConfiguration) message.obj; 6246 6247 if (!recordUidIfAuthorized(config, message.sendingUid, 6248 /* onlyAnnotate */ false)) { 6249 logw("Not authorized to update network " 6250 + " config=" + config.SSID 6251 + " cnid=" + config.networkId 6252 + " uid=" + message.sendingUid); 6253 replyToMessage(message, message.what, FAILURE); 6254 break; 6255 } 6256 6257 int res = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 6258 if (res < 0) { 6259 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6260 } else { 6261 WifiConfiguration curConfig = getCurrentWifiConfiguration(); 6262 if (curConfig != null && config != null) { 6263 WifiConfiguration.NetworkSelectionStatus networkStatus = 6264 config.getNetworkSelectionStatus(); 6265 if (curConfig.priority < config.priority && networkStatus != null 6266 && !networkStatus.isNetworkPermanentlyDisabled()) { 6267 // Interpret this as a connect attempt 6268 // Set the last selected configuration so as to allow the system to 6269 // stick the last user choice without persisting the choice 6270 mWifiConfigManager.setAndEnableLastSelectedConfiguration(res); 6271 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 6272 boolean persist = mWifiConfigManager 6273 .checkConfigOverridePermission(message.sendingUid); 6274 mWifiQualifiedNetworkSelector 6275 .userSelectNetwork(res, persist); 6276 6277 // Remember time of last connection attempt 6278 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6279 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6280 6281 // As a courtesy to the caller, trigger a scan now 6282 startScan(ADD_OR_UPDATE_SOURCE, 0, null, null); 6283 } 6284 } 6285 } 6286 replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK, res); 6287 break; 6288 case CMD_REMOVE_NETWORK: 6289 // Only the current foreground user can modify networks. 6290 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6291 loge("Only the current foreground user can modify networks " 6292 + " currentUserId=" + mCurrentUserId 6293 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6294 replyToMessage(message, message.what, FAILURE); 6295 break; 6296 } 6297 netId = message.arg1; 6298 6299 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 6300 /* onlyAnnotate */ false)) { 6301 logw("Not authorized to remove network " 6302 + " cnid=" + netId 6303 + " uid=" + message.sendingUid); 6304 replyToMessage(message, message.what, FAILURE); 6305 break; 6306 } 6307 6308 ok = mWifiConfigManager.removeNetwork(message.arg1); 6309 if (!ok) { 6310 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6311 } 6312 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 6313 break; 6314 case CMD_ENABLE_NETWORK: 6315 // Only the current foreground user can modify networks. 6316 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6317 loge("Only the current foreground user can modify networks " 6318 + " currentUserId=" + mCurrentUserId 6319 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6320 replyToMessage(message, message.what, FAILURE); 6321 break; 6322 } 6323 6324 boolean disableOthers = message.arg2 == 1; 6325 netId = message.arg1; 6326 config = mWifiConfigManager.getWifiConfiguration(netId); 6327 if (config == null) { 6328 loge("No network with id = " + netId); 6329 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6330 replyToMessage(message, message.what, FAILURE); 6331 break; 6332 } 6333 6334 // disable other only means select this network, does not mean all other 6335 // networks need to be disabled 6336 if (disableOthers) { 6337 mWifiQualifiedNetworkSelector.enableNetworkByUser(config); 6338 // Remember time of last connection attempt 6339 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6340 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6341 } 6342 // Cancel auto roam requests 6343 autoRoamSetBSSID(netId, "any"); 6344 6345 int uid = message.sendingUid; 6346 mWifiQualifiedNetworkSelector.enableNetworkByUser(config); 6347 ok = mWifiConfigManager.enableNetwork(netId, disableOthers, uid); 6348 if (!ok) { 6349 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6350 } else if (disableOthers) { 6351 mTargetNetworkId = netId; 6352 } 6353 6354 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 6355 break; 6356 case CMD_ENABLE_ALL_NETWORKS: 6357 long time = android.os.SystemClock.elapsedRealtime(); 6358 if (time - mLastEnableAllNetworksTime > MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS) { 6359 mWifiConfigManager.enableAllNetworks(); 6360 mLastEnableAllNetworksTime = time; 6361 } 6362 break; 6363 case WifiManager.DISABLE_NETWORK: 6364 if (mWifiConfigManager.updateNetworkSelectionStatus(message.arg1, 6365 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER)) { 6366 replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED); 6367 } else { 6368 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6369 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 6370 WifiManager.ERROR); 6371 } 6372 break; 6373 case CMD_DISABLE_EPHEMERAL_NETWORK: 6374 config = mWifiConfigManager.disableEphemeralNetwork((String)message.obj); 6375 if (config != null) { 6376 if (config.networkId == mLastNetworkId) { 6377 // Disconnect and let autojoin reselect a new network 6378 sendMessage(CMD_DISCONNECT); 6379 } 6380 } 6381 break; 6382 case CMD_BLACKLIST_NETWORK: 6383 mWifiConfigManager.blackListBssid((String) message.obj); 6384 break; 6385 case CMD_CLEAR_BLACKLIST: 6386 mWifiConfigManager.clearBssidBlacklist(); 6387 break; 6388 case CMD_SAVE_CONFIG: 6389 ok = mWifiConfigManager.saveConfig(); 6390 6391 if (DBG) logd("did save config " + ok); 6392 replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); 6393 6394 // Inform the backup manager about a data change 6395 mBackupManagerProxy.notifyDataChanged(); 6396 break; 6397 case CMD_GET_CONFIGURED_NETWORKS: 6398 replyToMessage(message, message.what, 6399 mWifiConfigManager.getConfiguredNetworks()); 6400 break; 6401 case WifiMonitor.SUP_REQUEST_IDENTITY: 6402 int networkId = message.arg2; 6403 boolean identitySent = false; 6404 int eapMethod = WifiEnterpriseConfig.Eap.NONE; 6405 6406 if (targetWificonfiguration != null 6407 && targetWificonfiguration.enterpriseConfig != null) { 6408 eapMethod = targetWificonfiguration.enterpriseConfig.getEapMethod(); 6409 } 6410 6411 // For SIM & AKA/AKA' EAP method Only, get identity from ICC 6412 if (targetWificonfiguration != null 6413 && targetWificonfiguration.networkId == networkId 6414 && targetWificonfiguration.allowedKeyManagement 6415 .get(WifiConfiguration.KeyMgmt.IEEE8021X) 6416 && (eapMethod == WifiEnterpriseConfig.Eap.SIM 6417 || eapMethod == WifiEnterpriseConfig.Eap.AKA 6418 || eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME)) { 6419 TelephonyManager tm = (TelephonyManager) 6420 mContext.getSystemService(Context.TELEPHONY_SERVICE); 6421 if (tm != null) { 6422 String imsi = tm.getSubscriberId(); 6423 String mccMnc = ""; 6424 6425 if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) 6426 mccMnc = tm.getSimOperator(); 6427 6428 String identity = buildIdentity(eapMethod, imsi, mccMnc); 6429 6430 if (!identity.isEmpty()) { 6431 mWifiNative.simIdentityResponse(networkId, identity); 6432 identitySent = true; 6433 } 6434 } 6435 } 6436 if (!identitySent) { 6437 // Supplicant lacks credentials to connect to that network, hence black list 6438 ssid = (String) message.obj; 6439 if (targetWificonfiguration != null && ssid != null 6440 && targetWificonfiguration.SSID != null 6441 && targetWificonfiguration.SSID.equals("\"" + ssid + "\"")) { 6442 mWifiConfigManager.updateNetworkSelectionStatus(targetWificonfiguration, 6443 WifiConfiguration.NetworkSelectionStatus 6444 .DISABLED_AUTHENTICATION_NO_CREDENTIALS); 6445 } 6446 // Disconnect now, as we don't have any way to fullfill 6447 // the supplicant request. 6448 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 6449 WifiConfiguration.INVALID_NETWORK_ID); 6450 mWifiNative.disconnect(); 6451 } 6452 break; 6453 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 6454 logd("Received SUP_REQUEST_SIM_AUTH"); 6455 SimAuthRequestData requestData = (SimAuthRequestData) message.obj; 6456 if (requestData != null) { 6457 if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) { 6458 handleGsmAuthRequest(requestData); 6459 } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA 6460 || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) { 6461 handle3GAuthRequest(requestData); 6462 } 6463 } else { 6464 loge("Invalid sim auth request"); 6465 } 6466 break; 6467 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 6468 replyToMessage(message, message.what, 6469 mWifiConfigManager.getPrivilegedConfiguredNetworks()); 6470 break; 6471 case CMD_GET_MATCHING_CONFIG: 6472 replyToMessage(message, message.what, 6473 mWifiConfigManager.getMatchingConfig((ScanResult)message.obj)); 6474 break; 6475 /* Do a redundant disconnect without transition */ 6476 case CMD_DISCONNECT: 6477 mWifiConfigManager.setAndEnableLastSelectedConfiguration 6478 (WifiConfiguration.INVALID_NETWORK_ID); 6479 mWifiNative.disconnect(); 6480 break; 6481 case CMD_RECONNECT: 6482 WifiConfiguration candidate = 6483 mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true, 6484 mAllowUntrustedConnections, mScanResults, linkDebouncing, 6485 isConnected(), isDisconnected(), isSupplicantTransientState()); 6486 tryToConnectToNetwork(candidate); 6487 break; 6488 case CMD_REASSOCIATE: 6489 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6490 mWifiNative.reassociate(); 6491 break; 6492 case CMD_RELOAD_TLS_AND_RECONNECT: 6493 if (mWifiConfigManager.needsUnlockedKeyStore()) { 6494 logd("Reconnecting to give a chance to un-connected TLS networks"); 6495 mWifiNative.disconnect(); 6496 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6497 mWifiNative.reconnect(); 6498 } 6499 break; 6500 case CMD_AUTO_ROAM: 6501 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6502 return HANDLED; 6503 case CMD_AUTO_CONNECT: 6504 /* Work Around: wpa_supplicant can get in a bad state where it returns a non 6505 * associated status to the STATUS command but somehow-someplace still thinks 6506 * it is associated and thus will ignore select/reconnect command with 6507 * following message: 6508 * "Already associated with the selected network - do nothing" 6509 * 6510 * Hence, sends a disconnect to supplicant first. 6511 */ 6512 didDisconnect = false; 6513 if (getCurrentState() != mDisconnectedState) { 6514 /** Supplicant will ignore the reconnect if we are currently associated, 6515 * hence trigger a disconnect 6516 */ 6517 didDisconnect = true; 6518 mWifiNative.disconnect(); 6519 } 6520 6521 /* connect command coming from auto-join */ 6522 netId = message.arg1; 6523 mTargetNetworkId = netId; 6524 mTargetRoamBSSID = (String) message.obj; 6525 config = mWifiConfigManager.getWifiConfiguration(netId); 6526 logd("CMD_AUTO_CONNECT sup state " 6527 + mSupplicantStateTracker.getSupplicantStateName() 6528 + " my state " + getCurrentState().getName() 6529 + " nid=" + Integer.toString(netId) 6530 + " roam=" + Boolean.toString(mAutoRoaming)); 6531 if (config == null) { 6532 loge("AUTO_CONNECT and no config, bail out..."); 6533 break; 6534 } 6535 6536 /* Make sure we cancel any previous roam request */ 6537 setTargetBssid(config, mTargetRoamBSSID); 6538 6539 /* Save the network config */ 6540 logd("CMD_AUTO_CONNECT will save config -> " + config.SSID 6541 + " nid=" + Integer.toString(netId)); 6542 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 6543 netId = result.getNetworkId(); 6544 logd("CMD_AUTO_CONNECT did save config -> " 6545 + " nid=" + Integer.toString(netId)); 6546 6547 // Since we updated the config,read it back from config store: 6548 config = mWifiConfigManager.getWifiConfiguration(netId); 6549 if (config == null) { 6550 loge("CMD_AUTO_CONNECT couldn't update the config, got null config"); 6551 break; 6552 } 6553 if (netId != config.networkId) { 6554 loge("CMD_AUTO_CONNECT couldn't update the config, want" 6555 + " nid=" + Integer.toString(netId) + " but got" + config.networkId); 6556 break; 6557 } 6558 6559 if (deferForUserInput(message, netId, false)) { 6560 break; 6561 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 6562 WifiConfiguration.USER_BANNED) { 6563 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6564 WifiManager.NOT_AUTHORIZED); 6565 break; 6566 } 6567 6568 // If we're autojoining a network that the user or an app explicitly selected, 6569 // keep track of the UID that selected it. 6570 // TODO(b/26786318): Keep track of the lastSelectedConfiguration and the 6571 // lastConnectUid on a per-user basis. 6572 int lastConnectUid = WifiConfiguration.UNKNOWN_UID; 6573 6574 //Start a new ConnectionEvent due to auto_connect, assume we are connecting 6575 //between different networks due to QNS, setting ROAM_UNRELATED 6576 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 6577 WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); 6578 if (!didDisconnect) { 6579 //If we were originally disconnected, then this was not any kind of ROAM 6580 mWifiMetrics.setConnectionEventRoamType( 6581 WifiMetricsProto.ConnectionEvent.ROAM_NONE); 6582 } 6583 //Determine if this CONNECTION is for a user selection 6584 if (mWifiConfigManager.isLastSelectedConfiguration(config) 6585 && isCurrentUserProfile(UserHandle.getUserId(config.lastConnectUid))) { 6586 lastConnectUid = config.lastConnectUid; 6587 mWifiMetrics.setConnectionEventRoamType( 6588 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED); 6589 } 6590 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 6591 lastConnectUid) && mWifiNative.reconnect()) { 6592 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6593 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 6594 config = mWifiConfigManager.getWifiConfiguration(netId); 6595 if (config != null 6596 && !mWifiConfigManager.isLastSelectedConfiguration(config)) { 6597 // If we autojoined a different config than the user selected one, 6598 // it means we could not see the last user selection, 6599 // or that the last user selection was faulty and ended up blacklisted 6600 // for some reason (in which case the user is notified with an error 6601 // message in the Wifi picker), and thus we managed to auto-join away 6602 // from the selected config. -> in that case we need to forget 6603 // the selection because we don't want to abruptly switch back to it. 6604 // 6605 // Note that the user selection is also forgotten after a period of time 6606 // during which the device has been disconnected. 6607 // The default value is 30 minutes : see the code path at bottom of 6608 // setScanResults() function. 6609 mWifiConfigManager. 6610 setAndEnableLastSelectedConfiguration( 6611 WifiConfiguration.INVALID_NETWORK_ID); 6612 } 6613 mAutoRoaming = false; 6614 if (isRoaming() || linkDebouncing) { 6615 transitionTo(mRoamingState); 6616 } else if (didDisconnect) { 6617 transitionTo(mDisconnectingState); 6618 } else { 6619 /* Already in disconnected state, nothing to change */ 6620 if (!mScreenOn && mLegacyPnoEnabled && mBackgroundScanSupported) { 6621 int delay = 60 * 1000; 6622 if (DBG) { 6623 logd("Starting PNO alarm: " + delay); 6624 } 6625 mAlarmManager.set(AlarmManager.RTC_WAKEUP, 6626 System.currentTimeMillis() + delay, 6627 mPnoIntent); 6628 } 6629 mRestartAutoJoinOffloadCounter++; 6630 } 6631 } else { 6632 loge("Failed to connect config: " + config + " netId: " + netId); 6633 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6634 WifiManager.ERROR); 6635 mWifiMetrics.endConnectionEvent( 6636 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 6637 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6638 break; 6639 } 6640 break; 6641 case CMD_REMOVE_APP_CONFIGURATIONS: 6642 mWifiConfigManager.removeNetworksForApp((ApplicationInfo) message.obj); 6643 break; 6644 case CMD_REMOVE_USER_CONFIGURATIONS: 6645 mWifiConfigManager.removeNetworksForUser(message.arg1); 6646 break; 6647 case WifiManager.CONNECT_NETWORK: 6648 // Only the current foreground user can modify networks. 6649 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6650 loge("Only the current foreground user can modify networks " 6651 + " currentUserId=" + mCurrentUserId 6652 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6653 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6654 WifiManager.NOT_AUTHORIZED); 6655 break; 6656 } 6657 6658 /** 6659 * The connect message can contain a network id passed as arg1 on message or 6660 * or a config passed as obj on message. 6661 * For a new network, a config is passed to create and connect. 6662 * For an existing network, a network id is passed 6663 */ 6664 netId = message.arg1; 6665 config = (WifiConfiguration) message.obj; 6666 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6667 boolean updatedExisting = false; 6668 6669 /* Save the network config */ 6670 if (config != null) { 6671 // When connecting to an access point, WifiStateMachine wants to update the 6672 // relevant config with administrative data. This update should not be 6673 // considered a 'real' update, therefore lockdown by Device Owner must be 6674 // disregarded. 6675 if (!recordUidIfAuthorized(config, message.sendingUid, 6676 /* onlyAnnotate */ true)) { 6677 logw("Not authorized to update network " 6678 + " config=" + config.SSID 6679 + " cnid=" + config.networkId 6680 + " uid=" + message.sendingUid); 6681 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6682 WifiManager.NOT_AUTHORIZED); 6683 break; 6684 } 6685 String configKey = config.configKey(true /* allowCached */); 6686 WifiConfiguration savedConfig = 6687 mWifiConfigManager.getWifiConfiguration(configKey); 6688 if (savedConfig != null) { 6689 // There is an existing config with this netId, but it wasn't exposed 6690 // (either AUTO_JOIN_DELETED or ephemeral; see WifiConfigManager# 6691 // getConfiguredNetworks). Remove those bits and update the config. 6692 config = savedConfig; 6693 logd("CONNECT_NETWORK updating existing config with id=" + 6694 config.networkId + " configKey=" + configKey); 6695 config.ephemeral = false; 6696 mWifiConfigManager.updateNetworkSelectionStatus(config, 6697 WifiConfiguration.NetworkSelectionStatus 6698 .NETWORK_SELECTION_ENABLE); 6699 updatedExisting = true; 6700 } 6701 6702 result = mWifiConfigManager.saveNetwork(config, message.sendingUid); 6703 netId = result.getNetworkId(); 6704 } 6705 config = mWifiConfigManager.getWifiConfiguration(netId); 6706 if (config == null) { 6707 logd("CONNECT_NETWORK no config for id=" + Integer.toString(netId) + " " 6708 + mSupplicantStateTracker.getSupplicantStateName() + " my state " 6709 + getCurrentState().getName()); 6710 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6711 WifiManager.ERROR); 6712 break; 6713 } 6714 mTargetNetworkId = netId; 6715 autoRoamSetBSSID(netId, "any"); 6716 if (message.sendingUid == Process.WIFI_UID 6717 || message.sendingUid == Process.SYSTEM_UID) { 6718 // As a sanity measure, clear the BSSID in the supplicant network block. 6719 // If system or Wifi Settings want to connect, they will not 6720 // specify the BSSID. 6721 // If an app however had added a BSSID to this configuration, and the BSSID 6722 // was wrong, Then we would forever fail to connect until that BSSID 6723 // is cleaned up. 6724 clearConfigBSSID(config, "CONNECT_NETWORK"); 6725 } 6726 6727 if (deferForUserInput(message, netId, true)) { 6728 break; 6729 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 6730 WifiConfiguration.USER_BANNED) { 6731 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6732 WifiManager.NOT_AUTHORIZED); 6733 break; 6734 } 6735 6736 mAutoRoaming = false; 6737 6738 /* Tell network selection the user did try to connect to that network if from 6739 settings */ 6740 boolean persist = 6741 mWifiConfigManager.checkConfigOverridePermission(message.sendingUid); 6742 6743 6744 mWifiConfigManager.setAndEnableLastSelectedConfiguration(netId); 6745 mWifiQualifiedNetworkSelector.userSelectNetwork(netId, persist); 6746 didDisconnect = false; 6747 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 6748 && mLastNetworkId != netId) { 6749 /** Supplicant will ignore the reconnect if we are currently associated, 6750 * hence trigger a disconnect 6751 */ 6752 didDisconnect = true; 6753 mWifiNative.disconnect(); 6754 } 6755 6756 //Start a new ConnectionEvent due to connect_network, this is always user 6757 //selected 6758 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 6759 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED); 6760 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ true, 6761 message.sendingUid) && mWifiNative.reconnect()) { 6762 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6763 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 6764 6765 /* The state tracker handles enabling networks upon completion/failure */ 6766 mSupplicantStateTracker.sendMessage(WifiManager.CONNECT_NETWORK); 6767 replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 6768 if (didDisconnect) { 6769 /* Expect a disconnection from the old connection */ 6770 transitionTo(mDisconnectingState); 6771 } else if (updatedExisting && getCurrentState() == mConnectedState && 6772 getCurrentWifiConfiguration().networkId == netId) { 6773 // Update the current set of network capabilities, but stay in the 6774 // current state. 6775 updateCapabilities(config); 6776 } else { 6777 /** 6778 * Directly go to disconnected state where we 6779 * process the connection events from supplicant 6780 */ 6781 transitionTo(mDisconnectedState); 6782 } 6783 } else { 6784 loge("Failed to connect config: " + config + " netId: " + netId); 6785 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6786 WifiManager.ERROR); 6787 mWifiMetrics.endConnectionEvent( 6788 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 6789 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6790 break; 6791 } 6792 break; 6793 case WifiManager.SAVE_NETWORK: 6794 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6795 // Fall thru 6796 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 6797 // Only the current foreground user can modify networks. 6798 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6799 loge("Only the current foreground user can modify networks " 6800 + " currentUserId=" + mCurrentUserId 6801 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6802 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6803 WifiManager.NOT_AUTHORIZED); 6804 break; 6805 } 6806 6807 lastSavedConfigurationAttempt = null; // Used for debug 6808 config = (WifiConfiguration) message.obj; 6809 if (config == null) { 6810 loge("ERROR: SAVE_NETWORK with null configuration" 6811 + mSupplicantStateTracker.getSupplicantStateName() 6812 + " my state " + getCurrentState().getName()); 6813 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6814 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6815 WifiManager.ERROR); 6816 break; 6817 } 6818 lastSavedConfigurationAttempt = new WifiConfiguration(config); 6819 int nid = config.networkId; 6820 logd("SAVE_NETWORK id=" + Integer.toString(nid) 6821 + " config=" + config.SSID 6822 + " nid=" + config.networkId 6823 + " supstate=" + mSupplicantStateTracker.getSupplicantStateName() 6824 + " my state " + getCurrentState().getName()); 6825 6826 // Only record the uid if this is user initiated 6827 boolean checkUid = (message.what == WifiManager.SAVE_NETWORK); 6828 if (checkUid && !recordUidIfAuthorized(config, message.sendingUid, 6829 /* onlyAnnotate */ false)) { 6830 logw("Not authorized to update network " 6831 + " config=" + config.SSID 6832 + " cnid=" + config.networkId 6833 + " uid=" + message.sendingUid); 6834 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6835 WifiManager.NOT_AUTHORIZED); 6836 break; 6837 } 6838 6839 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 6840 if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) { 6841 if (mWifiInfo.getNetworkId() == result.getNetworkId()) { 6842 if (result.hasIpChanged()) { 6843 // The currently connection configuration was changed 6844 // We switched from DHCP to static or from static to DHCP, or the 6845 // static IP address has changed. 6846 log("Reconfiguring IP on connection"); 6847 // TODO: clear addresses and disable IPv6 6848 // to simplify obtainingIpState. 6849 transitionTo(mObtainingIpState); 6850 } 6851 if (result.hasProxyChanged()) { 6852 log("Reconfiguring proxy on connection"); 6853 mIpManager.setHttpProxy( 6854 mWifiConfigManager.getProxyProperties(mLastNetworkId)); 6855 } 6856 } 6857 replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED); 6858 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 6859 6860 if (DBG) { 6861 logd("Success save network nid=" 6862 + Integer.toString(result.getNetworkId())); 6863 } 6864 6865 /** 6866 * If the command comes from WifiManager, then 6867 * tell autojoin the user did try to modify and save that network, 6868 * and interpret the SAVE_NETWORK as a request to connect 6869 */ 6870 boolean user = message.what == WifiManager.SAVE_NETWORK; 6871 6872 // Did this connect come from settings 6873 boolean persistConnect = 6874 mWifiConfigManager.checkConfigOverridePermission( 6875 message.sendingUid); 6876 6877 if (user) { 6878 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 6879 mWifiConfigManager.writeKnownNetworkHistory(); 6880 } 6881 //Fixme, CMD_AUTO_SAVE_NETWORK can be cleaned 6882 mWifiQualifiedNetworkSelector.userSelectNetwork( 6883 result.getNetworkId(), persistConnect); 6884 candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true, 6885 mAllowUntrustedConnections, mScanResults, linkDebouncing, 6886 isConnected(), isDisconnected(), isSupplicantTransientState()); 6887 tryToConnectToNetwork(candidate); 6888 } else { 6889 loge("Failed to save network"); 6890 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6891 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6892 WifiManager.ERROR); 6893 } 6894 break; 6895 case WifiManager.FORGET_NETWORK: 6896 // Only the current foreground user can modify networks. 6897 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6898 loge("Only the current foreground user can modify networks " 6899 + " currentUserId=" + mCurrentUserId 6900 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6901 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 6902 WifiManager.NOT_AUTHORIZED); 6903 break; 6904 } 6905 6906 // Debug only, remember last configuration that was forgotten 6907 WifiConfiguration toRemove 6908 = mWifiConfigManager.getWifiConfiguration(message.arg1); 6909 if (toRemove == null) { 6910 lastForgetConfigurationAttempt = null; 6911 } else { 6912 lastForgetConfigurationAttempt = new WifiConfiguration(toRemove); 6913 } 6914 // check that the caller owns this network 6915 netId = message.arg1; 6916 6917 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 6918 /* onlyAnnotate */ false)) { 6919 logw("Not authorized to forget network " 6920 + " cnid=" + netId 6921 + " uid=" + message.sendingUid); 6922 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 6923 WifiManager.NOT_AUTHORIZED); 6924 break; 6925 } 6926 6927 if (mWifiConfigManager.forgetNetwork(message.arg1)) { 6928 replyToMessage(message, WifiManager.FORGET_NETWORK_SUCCEEDED); 6929 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, 6930 (WifiConfiguration) message.obj); 6931 } else { 6932 loge("Failed to forget network"); 6933 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 6934 WifiManager.ERROR); 6935 } 6936 break; 6937 case WifiManager.START_WPS: 6938 WpsInfo wpsInfo = (WpsInfo) message.obj; 6939 WpsResult wpsResult; 6940 switch (wpsInfo.setup) { 6941 case WpsInfo.PBC: 6942 wpsResult = mWifiConfigManager.startWpsPbc(wpsInfo); 6943 break; 6944 case WpsInfo.KEYPAD: 6945 wpsResult = mWifiConfigManager.startWpsWithPinFromAccessPoint(wpsInfo); 6946 break; 6947 case WpsInfo.DISPLAY: 6948 wpsResult = mWifiConfigManager.startWpsWithPinFromDevice(wpsInfo); 6949 break; 6950 default: 6951 wpsResult = new WpsResult(Status.FAILURE); 6952 loge("Invalid setup for WPS"); 6953 break; 6954 } 6955 mWifiConfigManager.setAndEnableLastSelectedConfiguration 6956 (WifiConfiguration.INVALID_NETWORK_ID); 6957 if (wpsResult.status == Status.SUCCESS) { 6958 replyToMessage(message, WifiManager.START_WPS_SUCCEEDED, wpsResult); 6959 transitionTo(mWpsRunningState); 6960 } else { 6961 loge("Failed to start WPS with config " + wpsInfo.toString()); 6962 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR); 6963 } 6964 break; 6965 case CMD_ASSOCIATED_BSSID: 6966 // This is where we can confirm the connection BSSID. Use it to find the 6967 // right ScanDetail to populate metrics. 6968 String someBssid = (String) message.obj; 6969 if (someBssid != null) { 6970 //Get the config associated with this connection attempt 6971 WifiConfiguration someConf = 6972 mWifiConfigManager.getWifiConfiguration(mTargetNetworkId); 6973 // Get the ScanDetail associated with this BSSID 6974 ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCache( 6975 someConf); 6976 if (scanDetailCache != null) { 6977 mWifiMetrics.setConnectionScanDetail(scanDetailCache.getScanDetail( 6978 someBssid)); 6979 } 6980 } 6981 return NOT_HANDLED; 6982 case WifiMonitor.NETWORK_CONNECTION_EVENT: 6983 if (DBG) log("Network connection established"); 6984 mLastNetworkId = message.arg1; 6985 mLastBssid = (String) message.obj; 6986 6987 mWifiInfo.setBSSID(mLastBssid); 6988 mWifiInfo.setNetworkId(mLastNetworkId); 6989 mWifiQualifiedNetworkSelector 6990 .enableBssidForQualityNetworkSelection(mLastBssid, true); 6991 sendNetworkStateChangeBroadcast(mLastBssid); 6992 transitionTo(mObtainingIpState); 6993 break; 6994 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6995 // Calling handleNetworkDisconnect here is redundant because we might already 6996 // have called it when leaving L2ConnectedState to go to disconnecting state 6997 // or thru other path 6998 // We should normally check the mWifiInfo or mLastNetworkId so as to check 6999 // if they are valid, and only in this case call handleNEtworkDisconnect, 7000 // TODO: this should be fixed for a L MR release 7001 // The side effect of calling handleNetworkDisconnect twice is that a bunch of 7002 // idempotent commands are executed twice (stopping Dhcp, enabling the SPS mode 7003 // at the chip etc... 7004 if (DBG) log("ConnectModeState: Network connection lost "); 7005 handleNetworkDisconnect(); 7006 transitionTo(mDisconnectedState); 7007 break; 7008 case CMD_PNO_NETWORK_FOUND: 7009 processPnoNetworkFound((ScanResult[]) message.obj); 7010 break; 7011 case CMD_ADD_PASSPOINT_MO: 7012 res = mWifiConfigManager.addPasspointManagementObject((String) message.obj); 7013 replyToMessage(message, message.what, res); 7014 break; 7015 case CMD_MODIFY_PASSPOINT_MO: 7016 if (message.obj != null) { 7017 Bundle bundle = (Bundle) message.obj; 7018 ArrayList<PasspointManagementObjectDefinition> mos = 7019 bundle.getParcelableArrayList("MOS"); 7020 res = mWifiConfigManager.modifyPasspointMo(bundle.getString("FQDN"), mos); 7021 } else { 7022 res = 0; 7023 } 7024 replyToMessage(message, message.what, res); 7025 7026 break; 7027 case CMD_QUERY_OSU_ICON: 7028 if (mWifiConfigManager.queryPasspointIcon( 7029 ((Bundle) message.obj).getLong("BSSID"), 7030 ((Bundle) message.obj).getString("FILENAME"))) { 7031 res = 1; 7032 } else { 7033 res = 0; 7034 } 7035 replyToMessage(message, message.what, res); 7036 break; 7037 case CMD_MATCH_PROVIDER_NETWORK: 7038 res = mWifiConfigManager.matchProviderWithCurrentNetwork((String) message.obj); 7039 replyToMessage(message, message.what, res); 7040 break; 7041 default: 7042 return NOT_HANDLED; 7043 } 7044 return HANDLED; 7045 } 7046 } 7047 7048 private void updateCapabilities(WifiConfiguration config) { 7049 NetworkCapabilities networkCapabilities = new NetworkCapabilities(mDfltNetworkCapabilities); 7050 if (config != null) { 7051 if (config.ephemeral) { 7052 networkCapabilities.removeCapability( 7053 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 7054 } else { 7055 networkCapabilities.addCapability( 7056 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 7057 } 7058 7059 networkCapabilities.setSignalStrength( 7060 (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI) 7061 ? mWifiInfo.getRssi() 7062 : NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED); 7063 } 7064 7065 if (mWifiInfo.getMeteredHint()) { 7066 networkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 7067 } 7068 7069 mNetworkAgent.sendNetworkCapabilities(networkCapabilities); 7070 } 7071 7072 private class WifiNetworkAgent extends NetworkAgent { 7073 public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, 7074 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { 7075 super(l, c, TAG, ni, nc, lp, score, misc); 7076 } 7077 protected void unwanted() { 7078 // Ignore if we're not the current networkAgent. 7079 if (this != mNetworkAgent) return; 7080 if (DBG) log("WifiNetworkAgent -> Wifi unwanted score " 7081 + Integer.toString(mWifiInfo.score)); 7082 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT); 7083 } 7084 7085 @Override 7086 protected void networkStatus(int status) { 7087 if (this != mNetworkAgent) return; 7088 if (status == NetworkAgent.INVALID_NETWORK) { 7089 if (DBG) log("WifiNetworkAgent -> Wifi networkStatus invalid, score=" 7090 + Integer.toString(mWifiInfo.score)); 7091 unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED); 7092 } else if (status == NetworkAgent.VALID_NETWORK) { 7093 if (DBG) { 7094 log("WifiNetworkAgent -> Wifi networkStatus valid, score= " 7095 + Integer.toString(mWifiInfo.score)); 7096 } 7097 doNetworkStatus(status); 7098 } 7099 } 7100 7101 @Override 7102 protected void saveAcceptUnvalidated(boolean accept) { 7103 if (this != mNetworkAgent) return; 7104 WifiStateMachine.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0); 7105 } 7106 7107 @Override 7108 protected void startPacketKeepalive(Message msg) { 7109 WifiStateMachine.this.sendMessage( 7110 CMD_START_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 7111 } 7112 7113 @Override 7114 protected void stopPacketKeepalive(Message msg) { 7115 WifiStateMachine.this.sendMessage( 7116 CMD_STOP_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 7117 } 7118 7119 @Override 7120 protected void setSignalStrengthThresholds(int[] thresholds) { 7121 // 0. If there are no thresholds, or if the thresholds are invalid, stop RSSI monitoring. 7122 // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and 7123 // MAX_VALUE at the start/end of the thresholds array if necessary. 7124 // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware 7125 // event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then 7126 // re-arm the hardware event. This needs to be done on the state machine thread to 7127 // avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one 7128 // sent in the NetworkCapabilities) must be the one received from the hardware event 7129 // received, or we might skip callbacks. 7130 // 3. Ensure that when we disconnect, RSSI monitoring is stopped. 7131 log("Received signal strength thresholds: " + Arrays.toString(thresholds)); 7132 if (thresholds.length == 0) { 7133 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 7134 mWifiInfo.getRssi()); 7135 return; 7136 } 7137 int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2); 7138 rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE; 7139 rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE; 7140 Arrays.sort(rssiVals); 7141 byte[] rssiRange = new byte[rssiVals.length]; 7142 for (int i = 0; i < rssiVals.length; i++) { 7143 int val = rssiVals[i]; 7144 if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) { 7145 rssiRange[i] = (byte) val; 7146 } else { 7147 Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: " 7148 + Arrays.toString(rssiVals)); 7149 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 7150 mWifiInfo.getRssi()); 7151 return; 7152 } 7153 } 7154 // TODO: Do we quash rssi values in this sorted array which are very close? 7155 mRssiRanges = rssiRange; 7156 WifiStateMachine.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD, 7157 mWifiInfo.getRssi()); 7158 } 7159 7160 @Override 7161 protected void preventAutomaticReconnect() { 7162 if (this != mNetworkAgent) return; 7163 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN); 7164 } 7165 } 7166 7167 void unwantedNetwork(int reason) { 7168 sendMessage(CMD_UNWANTED_NETWORK, reason); 7169 } 7170 7171 void doNetworkStatus(int status) { 7172 sendMessage(CMD_NETWORK_STATUS, status); 7173 } 7174 7175 // rfc4186 & rfc4187: 7176 // create Permanent Identity base on IMSI, 7177 // identity = usernam@realm 7178 // with username = prefix | IMSI 7179 // and realm is derived MMC/MNC tuple according 3GGP spec(TS23.003) 7180 private String buildIdentity(int eapMethod, String imsi, String mccMnc) { 7181 String mcc; 7182 String mnc; 7183 String prefix; 7184 7185 if (imsi == null || imsi.isEmpty()) 7186 return ""; 7187 7188 if (eapMethod == WifiEnterpriseConfig.Eap.SIM) 7189 prefix = "1"; 7190 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA) 7191 prefix = "0"; 7192 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME) 7193 prefix = "6"; 7194 else // not a valide EapMethod 7195 return ""; 7196 7197 /* extract mcc & mnc from mccMnc */ 7198 if (mccMnc != null && !mccMnc.isEmpty()) { 7199 mcc = mccMnc.substring(0, 3); 7200 mnc = mccMnc.substring(3); 7201 if (mnc.length() == 2) 7202 mnc = "0" + mnc; 7203 } else { 7204 // extract mcc & mnc from IMSI, assume mnc size is 3 7205 mcc = imsi.substring(0, 3); 7206 mnc = imsi.substring(3, 6); 7207 } 7208 7209 return prefix + imsi + "@wlan.mnc" + mnc + ".mcc" + mcc + ".3gppnetwork.org"; 7210 } 7211 7212 boolean startScanForConfiguration(WifiConfiguration config, boolean restrictChannelList) { 7213 if (config == null) 7214 return false; 7215 7216 // We are still seeing a fairly high power consumption triggered by autojoin scans 7217 // Hence do partial scans only for PSK configuration that are roamable since the 7218 // primary purpose of the partial scans is roaming. 7219 // Full badn scans with exponential backoff for the purpose or extended roaming and 7220 // network switching are performed unconditionally. 7221 ScanDetailCache scanDetailCache = 7222 mWifiConfigManager.getScanDetailCache(config); 7223 if (scanDetailCache == null 7224 || !config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) 7225 || scanDetailCache.size() > 6) { 7226 //return true but to not trigger the scan 7227 return true; 7228 } 7229 HashSet<Integer> freqs = mWifiConfigManager.makeChannelList(config, 7230 ONE_HOUR_MILLI, restrictChannelList); 7231 if (freqs != null && freqs.size() != 0) { 7232 //if (DBG) { 7233 logd("starting scan for " + config.configKey() + " with " + freqs); 7234 //} 7235 Set<Integer> hiddenNetworkIds = new HashSet<>(); 7236 if (config.hiddenSSID) { 7237 hiddenNetworkIds.add(config.networkId); 7238 } 7239 // Call wifi native to start the scan 7240 if (startScanNative(freqs, hiddenNetworkIds, null)) { 7241 // Only count battery consumption if scan request is accepted 7242 noteScanStart(SCAN_ALARM_SOURCE, null); 7243 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; 7244 } else { 7245 // used for debug only, mark scan as failed 7246 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 7247 } 7248 return true; 7249 } else { 7250 if (DBG) logd("no channels for " + config.configKey()); 7251 return false; 7252 } 7253 } 7254 7255 void clearCurrentConfigBSSID(String dbg) { 7256 // Clear the bssid in the current config's network block 7257 WifiConfiguration config = getCurrentWifiConfiguration(); 7258 if (config == null) 7259 return; 7260 clearConfigBSSID(config, dbg); 7261 } 7262 void clearConfigBSSID(WifiConfiguration config, String dbg) { 7263 if (config == null) 7264 return; 7265 if (DBG) { 7266 logd(dbg + " " + mTargetRoamBSSID + " config " + config.configKey() 7267 + " config.NetworkSelectionStatus.mNetworkSelectionBSSID " 7268 + config.getNetworkSelectionStatus().getNetworkSelectionBSSID()); 7269 } 7270 if (DBG) { 7271 logd(dbg + " " + config.SSID 7272 + " nid=" + Integer.toString(config.networkId)); 7273 } 7274 mWifiConfigManager.saveWifiConfigBSSID(config, "any"); 7275 } 7276 7277 class L2ConnectedState extends State { 7278 @Override 7279 public void enter() { 7280 mRssiPollToken++; 7281 if (mEnableRssiPolling) { 7282 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0); 7283 } 7284 if (mNetworkAgent != null) { 7285 loge("Have NetworkAgent when entering L2Connected"); 7286 setNetworkDetailedState(DetailedState.DISCONNECTED); 7287 } 7288 setNetworkDetailedState(DetailedState.CONNECTING); 7289 7290 mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, 7291 "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter, 7292 mLinkProperties, 60, mNetworkMisc); 7293 7294 // We must clear the config BSSID, as the wifi chipset may decide to roam 7295 // from this point on and having the BSSID specified in the network block would 7296 // cause the roam to faile and the device to disconnect 7297 clearCurrentConfigBSSID("L2ConnectedState"); 7298 mCountryCode.setReadyForChange(false); 7299 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); 7300 } 7301 7302 @Override 7303 public void exit() { 7304 mIpManager.stop(); 7305 7306 // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState 7307 // Bug: 15347363 7308 // For paranoia's sake, call handleNetworkDisconnect 7309 // only if BSSID is null or last networkId 7310 // is not invalid. 7311 if (DBG) { 7312 StringBuilder sb = new StringBuilder(); 7313 sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId)); 7314 if (mLastBssid !=null) { 7315 sb.append(" ").append(mLastBssid); 7316 } 7317 } 7318 if (mLastBssid != null || mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 7319 handleNetworkDisconnect(); 7320 } 7321 mCountryCode.setReadyForChange(true); 7322 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 7323 } 7324 7325 @Override 7326 public boolean processMessage(Message message) { 7327 logStateAndMessage(message, this); 7328 7329 switch (message.what) { 7330 case DhcpClient.CMD_PRE_DHCP_ACTION: 7331 handlePreDhcpSetup(); 7332 break; 7333 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 7334 mIpManager.completedPreDhcpAction(); 7335 break; 7336 case DhcpClient.CMD_POST_DHCP_ACTION: 7337 handlePostDhcpSetup(); 7338 // We advance to mConnectedState because IpManager will also send a 7339 // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(), 7340 // which calls updateLinkProperties, which then sends 7341 // CMD_IP_CONFIGURATION_SUCCESSFUL. 7342 // 7343 // In the event of failure, we transition to mDisconnectingState 7344 // similarly--via messages sent back from IpManager. 7345 break; 7346 case CMD_IPV4_PROVISIONING_SUCCESS: { 7347 handleIPv4Success((DhcpResults) message.obj); 7348 sendNetworkStateChangeBroadcast(mLastBssid); 7349 break; 7350 } 7351 case CMD_IPV4_PROVISIONING_FAILURE: { 7352 handleIPv4Failure(); 7353 break; 7354 } 7355 case CMD_IP_CONFIGURATION_SUCCESSFUL: 7356 handleSuccessfulIpConfiguration(); 7357 mWifiMetrics.endConnectionEvent( 7358 WifiMetrics.ConnectionEvent.FAILURE_NONE, 7359 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7360 sendConnectedState(); 7361 transitionTo(mConnectedState); 7362 break; 7363 case CMD_IP_CONFIGURATION_LOST: 7364 // Get Link layer stats so that we get fresh tx packet counters. 7365 getWifiLinkLayerStats(true); 7366 handleIpConfigurationLost(); 7367 transitionTo(mDisconnectingState); 7368 break; 7369 case CMD_IP_REACHABILITY_LOST: 7370 if (DBG && message.obj != null) log((String) message.obj); 7371 handleIpReachabilityLost(); 7372 transitionTo(mDisconnectingState); 7373 break; 7374 case CMD_DISCONNECT: 7375 mWifiNative.disconnect(); 7376 transitionTo(mDisconnectingState); 7377 break; 7378 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 7379 if (message.arg1 == 1) { 7380 mWifiNative.disconnect(); 7381 mTemporarilyDisconnectWifi = true; 7382 transitionTo(mDisconnectingState); 7383 } 7384 break; 7385 case CMD_SET_OPERATIONAL_MODE: 7386 if (message.arg1 != CONNECT_MODE) { 7387 sendMessage(CMD_DISCONNECT); 7388 deferMessage(message); 7389 if (message.arg1 == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 7390 noteWifiDisabledWhileAssociated(); 7391 } 7392 } 7393 mWifiConfigManager. 7394 setAndEnableLastSelectedConfiguration( 7395 WifiConfiguration.INVALID_NETWORK_ID); 7396 break; 7397 case CMD_START_SCAN: 7398 if (DBG) { 7399 logd("CMD_START_SCAN source " + message.arg1 7400 + " txSuccessRate="+String.format( "%.2f", mWifiInfo.txSuccessRate) 7401 + " rxSuccessRate="+String.format( "%.2f", mWifiInfo.rxSuccessRate) 7402 + " targetRoamBSSID=" + mTargetRoamBSSID 7403 + " RSSI=" + mWifiInfo.getRssi()); 7404 } 7405 if (message.arg1 == SCAN_ALARM_SOURCE) { 7406 // Check if the CMD_START_SCAN message is obsolete (and thus if it should 7407 // not be processed) and restart the scan if neede 7408 if (!getEnableAutoJoinWhenAssociated()) { 7409 return HANDLED; 7410 } 7411 boolean shouldScan = mScreenOn; 7412 7413 if (!checkAndRestartDelayedScan(message.arg2, 7414 shouldScan, 7415 mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get(), 7416 null, null)) { 7417 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 7418 logd("L2Connected CMD_START_SCAN source " 7419 + message.arg1 7420 + " " + message.arg2 + ", " + mDelayedScanCounter 7421 + " -> obsolete"); 7422 return HANDLED; 7423 } 7424 if (mP2pConnected.get()) { 7425 logd("L2Connected CMD_START_SCAN source " 7426 + message.arg1 7427 + " " + message.arg2 + ", " + mDelayedScanCounter 7428 + " ignore because P2P is connected"); 7429 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7430 return HANDLED; 7431 } 7432 boolean tryFullBandScan = false; 7433 boolean restrictChannelList = false; 7434 long now_ms = System.currentTimeMillis(); 7435 if (DBG) { 7436 logd("CMD_START_SCAN with age=" 7437 + Long.toString(now_ms - lastFullBandConnectedTimeMilli) 7438 + " interval=" + fullBandConnectedTimeIntervalMilli 7439 + " maxinterval=" + maxFullBandConnectedTimeIntervalMilli); 7440 } 7441 7442 if (mWifiConfigManager.enableFullBandScanWhenAssociated.get() 7443 && (now_ms - lastFullBandConnectedTimeMilli) 7444 > fullBandConnectedTimeIntervalMilli) { 7445 if (DBG) { 7446 logd("CMD_START_SCAN try full band scan age=" 7447 + Long.toString(now_ms - lastFullBandConnectedTimeMilli) 7448 + " interval=" + fullBandConnectedTimeIntervalMilli 7449 + " maxinterval=" + maxFullBandConnectedTimeIntervalMilli); 7450 } 7451 tryFullBandScan = true; 7452 } 7453 7454 if (mWifiInfo.txSuccessRate > mWifiConfigManager.maxTxPacketForFullScans 7455 || mWifiInfo.rxSuccessRate 7456 > mWifiConfigManager.maxRxPacketForFullScans) { 7457 // Too much traffic at the interface, hence no full band scan 7458 if (DBG) { 7459 logd("CMD_START_SCAN prevent full band scan due to pkt rate"); 7460 } 7461 tryFullBandScan = false; 7462 } 7463 7464 if (mWifiInfo.txSuccessRate > mWifiConfigManager.maxTxPacketForPartialScans 7465 || mWifiInfo.rxSuccessRate 7466 > mWifiConfigManager.maxRxPacketForPartialScans) { 7467 // Don't scan if lots of packets are being sent 7468 restrictChannelList = true; 7469 if (mWifiConfigManager.alwaysEnableScansWhileAssociated.get() == 0) { 7470 if (DBG) { 7471 logd("CMD_START_SCAN source " + message.arg1 7472 + " ...and ignore scans" 7473 + " tx=" 7474 + String.format("%.2f", mWifiInfo.txSuccessRate) 7475 + " rx=" 7476 + String.format("%.2f", mWifiInfo.rxSuccessRate)); 7477 } 7478 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 7479 return HANDLED; 7480 } 7481 } 7482 7483 WifiConfiguration currentConfiguration = getCurrentWifiConfiguration(); 7484 if (DBG) { 7485 logd("CMD_START_SCAN full=" + 7486 tryFullBandScan); 7487 } 7488 if (currentConfiguration != null) { 7489 if (fullBandConnectedTimeIntervalMilli < 7490 mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get()) { 7491 // Sanity 7492 fullBandConnectedTimeIntervalMilli = 7493 mWifiConfigManager 7494 .wifiAssociatedShortScanIntervalMilli.get(); 7495 } 7496 if (tryFullBandScan) { 7497 lastFullBandConnectedTimeMilli = now_ms; 7498 if (fullBandConnectedTimeIntervalMilli 7499 < mWifiConfigManager.associatedFullScanMaxIntervalMilli) { 7500 // Increase the interval 7501 fullBandConnectedTimeIntervalMilli = 7502 fullBandConnectedTimeIntervalMilli * 7503 mWifiConfigManager 7504 .associatedFullScanBackoff.get() / 8; 7505 7506 if (DBG) { 7507 logd("CMD_START_SCAN bump interval =" 7508 + fullBandConnectedTimeIntervalMilli); 7509 } 7510 } 7511 handleScanRequest(message); 7512 } else { 7513 if (!startScanForConfiguration( 7514 currentConfiguration, restrictChannelList)) { 7515 if (DBG) { 7516 logd("starting scan, " + 7517 " did not find channels -> full"); 7518 } 7519 lastFullBandConnectedTimeMilli = now_ms; 7520 if (fullBandConnectedTimeIntervalMilli 7521 < mWifiConfigManager 7522 .associatedFullScanMaxIntervalMilli) { 7523 // Increase the interval 7524 fullBandConnectedTimeIntervalMilli = 7525 fullBandConnectedTimeIntervalMilli * 7526 mWifiConfigManager 7527 .associatedFullScanBackoff.get() / 8; 7528 7529 if (DBG) { 7530 logd("CMD_START_SCAN bump interval =" 7531 + fullBandConnectedTimeIntervalMilli); 7532 } 7533 } 7534 handleScanRequest(message); 7535 } 7536 } 7537 7538 } else { 7539 logd("CMD_START_SCAN : connected mode and no configuration"); 7540 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 7541 } 7542 } else { 7543 // Not scan alarm source 7544 return NOT_HANDLED; 7545 } 7546 break; 7547 /* Ignore connection to same network */ 7548 case WifiManager.CONNECT_NETWORK: 7549 int netId = message.arg1; 7550 if (mWifiInfo.getNetworkId() == netId) { 7551 break; 7552 } 7553 return NOT_HANDLED; 7554 case WifiMonitor.NETWORK_CONNECTION_EVENT: 7555 mWifiInfo.setBSSID((String) message.obj); 7556 mLastNetworkId = message.arg1; 7557 mWifiInfo.setNetworkId(mLastNetworkId); 7558 if(!mLastBssid.equals((String) message.obj)) { 7559 mLastBssid = (String) message.obj; 7560 sendNetworkStateChangeBroadcast(mLastBssid); 7561 } 7562 break; 7563 case CMD_RSSI_POLL: 7564 if (message.arg1 == mRssiPollToken) { 7565 if (mWifiConfigManager.enableChipWakeUpWhenAssociated.get()) { 7566 if (DBG) log(" get link layer stats " + mWifiLinkLayerStatsSupported); 7567 WifiLinkLayerStats stats = getWifiLinkLayerStats(DBG); 7568 if (stats != null) { 7569 // Sanity check the results provided by driver 7570 if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI 7571 && (stats.rssi_mgmt == 0 7572 || stats.beacon_rx == 0)) { 7573 stats = null; 7574 } 7575 } 7576 // Get Info and continue polling 7577 fetchRssiLinkSpeedAndFrequencyNative(); 7578 mWifiScoreReport = 7579 WifiScoreReport.calculateScore(mWifiInfo, 7580 getCurrentWifiConfiguration(), 7581 mWifiConfigManager, 7582 mNetworkAgent, 7583 mWifiScoreReport, 7584 mAggressiveHandover); 7585 } 7586 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 7587 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 7588 if (DBG) sendRssiChangeBroadcast(mWifiInfo.getRssi()); 7589 } else { 7590 // Polling has completed 7591 } 7592 break; 7593 case CMD_ENABLE_RSSI_POLL: 7594 cleanWifiScore(); 7595 if (mWifiConfigManager.enableRssiPollWhenAssociated.get()) { 7596 mEnableRssiPolling = (message.arg1 == 1); 7597 } else { 7598 mEnableRssiPolling = false; 7599 } 7600 mRssiPollToken++; 7601 if (mEnableRssiPolling) { 7602 // First poll 7603 fetchRssiLinkSpeedAndFrequencyNative(); 7604 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 7605 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 7606 } 7607 break; 7608 case WifiManager.RSSI_PKTCNT_FETCH: 7609 RssiPacketCountInfo info = new RssiPacketCountInfo(); 7610 fetchRssiLinkSpeedAndFrequencyNative(); 7611 info.rssi = mWifiInfo.getRssi(); 7612 fetchPktcntNative(info); 7613 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED, info); 7614 break; 7615 case CMD_DELAYED_NETWORK_DISCONNECT: 7616 if (!linkDebouncing && mWifiConfigManager.enableLinkDebouncing) { 7617 7618 // Ignore if we are not debouncing 7619 logd("CMD_DELAYED_NETWORK_DISCONNECT and not debouncing - ignore " 7620 + message.arg1); 7621 return HANDLED; 7622 } else { 7623 logd("CMD_DELAYED_NETWORK_DISCONNECT and debouncing - disconnect " 7624 + message.arg1); 7625 7626 linkDebouncing = false; 7627 // If we are still debouncing while this message comes, 7628 // it means we were not able to reconnect within the alloted time 7629 // = LINK_FLAPPING_DEBOUNCE_MSEC 7630 // and thus, trigger a real disconnect 7631 handleNetworkDisconnect(); 7632 transitionTo(mDisconnectedState); 7633 } 7634 break; 7635 case CMD_ASSOCIATED_BSSID: 7636 if ((String) message.obj == null) { 7637 logw("Associated command w/o BSSID"); 7638 break; 7639 } 7640 mLastBssid = (String) message.obj; 7641 if (mLastBssid != null && (mWifiInfo.getBSSID() == null 7642 || !mLastBssid.equals(mWifiInfo.getBSSID()))) { 7643 mWifiInfo.setBSSID((String) message.obj); 7644 sendNetworkStateChangeBroadcast(mLastBssid); 7645 } 7646 break; 7647 case CMD_START_RSSI_MONITORING_OFFLOAD: 7648 case CMD_RSSI_THRESHOLD_BREACH: 7649 byte currRssi = (byte) message.arg1; 7650 processRssiThreshold(currRssi, message.what); 7651 break; 7652 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 7653 stopRssiMonitoringOffload(); 7654 break; 7655 case CMD_RESET_SIM_NETWORKS: 7656 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 7657 WifiConfiguration config = 7658 mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 7659 if (mWifiConfigManager.isSimConfig(config)) { 7660 mWifiNative.disconnect(); 7661 transitionTo(mDisconnectingState); 7662 } 7663 } 7664 /* allow parent state to reset data for other networks */ 7665 return NOT_HANDLED; 7666 default: 7667 return NOT_HANDLED; 7668 } 7669 7670 return HANDLED; 7671 } 7672 } 7673 7674 class ObtainingIpState extends State { 7675 @Override 7676 public void enter() { 7677 if (DBG) { 7678 String key = ""; 7679 if (getCurrentWifiConfiguration() != null) { 7680 key = getCurrentWifiConfiguration().configKey(); 7681 } 7682 log("enter ObtainingIpState netId=" + Integer.toString(mLastNetworkId) 7683 + " " + key + " " 7684 + " roam=" + mAutoRoaming 7685 + " static=" + mWifiConfigManager.isUsingStaticIp(mLastNetworkId) 7686 + " watchdog= " + obtainingIpWatchdogCount); 7687 } 7688 7689 // Reset link Debouncing, indicating we have successfully re-connected to the AP 7690 // We might still be roaming 7691 linkDebouncing = false; 7692 7693 // Send event to CM & network change broadcast 7694 setNetworkDetailedState(DetailedState.OBTAINING_IPADDR); 7695 7696 // We must clear the config BSSID, as the wifi chipset may decide to roam 7697 // from this point on and having the BSSID specified in the network block would 7698 // cause the roam to fail and the device to disconnect. 7699 clearCurrentConfigBSSID("ObtainingIpAddress"); 7700 7701 // Stop IpManager in case we're switching from DHCP to static 7702 // configuration or vice versa. 7703 // 7704 // TODO: Only ever enter this state the first time we connect to a 7705 // network, never on switching between static configuration and 7706 // DHCP. When we transition from static configuration to DHCP in 7707 // particular, we must tell ConnectivityService that we're 7708 // disconnected, because DHCP might take a long time during which 7709 // connectivity APIs such as getActiveNetworkInfo should not return 7710 // CONNECTED. 7711 stopIpManager(); 7712 7713 mIpManager.setHttpProxy(mWifiConfigManager.getProxyProperties(mLastNetworkId)); 7714 if (!TextUtils.isEmpty(mTcpBufferSizes)) { 7715 mIpManager.setTcpBufferSizes(mTcpBufferSizes); 7716 } 7717 7718 if (!mWifiConfigManager.isUsingStaticIp(mLastNetworkId)) { 7719 final IpManager.ProvisioningConfiguration prov = 7720 mIpManager.buildProvisioningConfiguration() 7721 .withPreDhcpAction() 7722 .withApfCapabilities(mWifiNative.getApfCapabilities()) 7723 .build(); 7724 mIpManager.startProvisioning(prov); 7725 obtainingIpWatchdogCount++; 7726 logd("Start Dhcp Watchdog " + obtainingIpWatchdogCount); 7727 // Get Link layer stats so as we get fresh tx packet counters 7728 getWifiLinkLayerStats(true); 7729 sendMessageDelayed(obtainMessage(CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER, 7730 obtainingIpWatchdogCount, 0), OBTAINING_IP_ADDRESS_GUARD_TIMER_MSEC); 7731 } else { 7732 StaticIpConfiguration config = mWifiConfigManager.getStaticIpConfiguration( 7733 mLastNetworkId); 7734 if (config.ipAddress == null) { 7735 logd("Static IP lacks address"); 7736 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 7737 } else { 7738 final IpManager.ProvisioningConfiguration prov = 7739 mIpManager.buildProvisioningConfiguration() 7740 .withStaticConfiguration(config) 7741 .withApfCapabilities(mWifiNative.getApfCapabilities()) 7742 .build(); 7743 mIpManager.startProvisioning(prov); 7744 } 7745 } 7746 } 7747 7748 @Override 7749 public boolean processMessage(Message message) { 7750 logStateAndMessage(message, this); 7751 7752 switch(message.what) { 7753 case CMD_AUTO_CONNECT: 7754 case CMD_AUTO_ROAM: 7755 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7756 break; 7757 case WifiManager.SAVE_NETWORK: 7758 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 7759 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 7760 deferMessage(message); 7761 break; 7762 /* Defer any power mode changes since we must keep active power mode at DHCP */ 7763 7764 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7765 mWifiMetrics.endConnectionEvent( 7766 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 7767 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7768 return NOT_HANDLED; 7769 case CMD_SET_HIGH_PERF_MODE: 7770 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 7771 deferMessage(message); 7772 break; 7773 /* Defer scan request since we should not switch to other channels at DHCP */ 7774 case CMD_START_SCAN: 7775 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 7776 deferMessage(message); 7777 break; 7778 case CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER: 7779 if (message.arg1 == obtainingIpWatchdogCount) { 7780 logd("ObtainingIpAddress: Watchdog Triggered, count=" 7781 + obtainingIpWatchdogCount); 7782 handleIpConfigurationLost(); 7783 transitionTo(mDisconnectingState); 7784 break; 7785 } 7786 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7787 break; 7788 default: 7789 return NOT_HANDLED; 7790 } 7791 return HANDLED; 7792 } 7793 } 7794 7795 private void sendConnectedState() { 7796 // If this network was explicitly selected by the user, evaluate whether to call 7797 // explicitlySelected() so the system can treat it appropriately. 7798 WifiConfiguration config = getCurrentWifiConfiguration(); 7799 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 7800 boolean prompt = 7801 mWifiConfigManager.checkConfigOverridePermission(config.lastConnectUid); 7802 if (DBG) { 7803 log("Network selected by UID " + config.lastConnectUid + " prompt=" + prompt); 7804 } 7805 if (prompt) { 7806 // Selected by the user via Settings or QuickSettings. If this network has Internet 7807 // access, switch to it. Otherwise, switch to it only if the user confirms that they 7808 // really want to switch, or has already confirmed and selected "Don't ask again". 7809 if (DBG) { 7810 log("explictlySelected acceptUnvalidated=" + config.noInternetAccessExpected); 7811 } 7812 mNetworkAgent.explicitlySelected(config.noInternetAccessExpected); 7813 } 7814 } 7815 7816 setNetworkDetailedState(DetailedState.CONNECTED); 7817 mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.CONNECTED); 7818 sendNetworkStateChangeBroadcast(mLastBssid); 7819 } 7820 7821 class RoamingState extends State { 7822 boolean mAssociated; 7823 @Override 7824 public void enter() { 7825 if (DBG) { 7826 log("RoamingState Enter" 7827 + " mScreenOn=" + mScreenOn ); 7828 } 7829 setScanAlarm(false); 7830 7831 // Make sure we disconnect if roaming fails 7832 roamWatchdogCount++; 7833 logd("Start Roam Watchdog " + roamWatchdogCount); 7834 sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER, 7835 roamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); 7836 mAssociated = false; 7837 } 7838 @Override 7839 public boolean processMessage(Message message) { 7840 logStateAndMessage(message, this); 7841 WifiConfiguration config; 7842 switch (message.what) { 7843 case CMD_IP_CONFIGURATION_LOST: 7844 config = getCurrentWifiConfiguration(); 7845 if (config != null) { 7846 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_AUTOROAM_FAILURE); 7847 mWifiConfigManager.noteRoamingFailure(config, 7848 WifiConfiguration.ROAMING_FAILURE_IP_CONFIG); 7849 } 7850 return NOT_HANDLED; 7851 case CMD_UNWANTED_NETWORK: 7852 if (DBG) log("Roaming and CS doesnt want the network -> ignore"); 7853 return HANDLED; 7854 case CMD_SET_OPERATIONAL_MODE: 7855 if (message.arg1 != CONNECT_MODE) { 7856 deferMessage(message); 7857 } 7858 break; 7859 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 7860 /** 7861 * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT 7862 * before NETWORK_DISCONNECTION_EVENT 7863 * And there is an associated BSSID corresponding to our target BSSID, then 7864 * we have missed the network disconnection, transition to mDisconnectedState 7865 * and handle the rest of the events there. 7866 */ 7867 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 7868 if (stateChangeResult.state == SupplicantState.DISCONNECTED 7869 || stateChangeResult.state == SupplicantState.INACTIVE 7870 || stateChangeResult.state == SupplicantState.INTERFACE_DISABLED) { 7871 if (DBG) { 7872 log("STATE_CHANGE_EVENT in roaming state " 7873 + stateChangeResult.toString() ); 7874 } 7875 if (stateChangeResult.BSSID != null 7876 && stateChangeResult.BSSID.equals(mTargetRoamBSSID)) { 7877 handleNetworkDisconnect(); 7878 transitionTo(mDisconnectedState); 7879 } 7880 } 7881 if (stateChangeResult.state == SupplicantState.ASSOCIATED) { 7882 // We completed the layer2 roaming part 7883 mAssociated = true; 7884 if (stateChangeResult.BSSID != null) { 7885 mTargetRoamBSSID = (String) stateChangeResult.BSSID; 7886 } 7887 } 7888 break; 7889 case CMD_ROAM_WATCHDOG_TIMER: 7890 if (roamWatchdogCount == message.arg1) { 7891 if (DBG) log("roaming watchdog! -> disconnect"); 7892 mWifiMetrics.endConnectionEvent( 7893 WifiMetrics.ConnectionEvent.FAILURE_ROAM_TIMEOUT, 7894 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7895 mRoamFailCount++; 7896 handleNetworkDisconnect(); 7897 mWifiNative.disconnect(); 7898 transitionTo(mDisconnectedState); 7899 } 7900 break; 7901 case WifiMonitor.NETWORK_CONNECTION_EVENT: 7902 if (mAssociated) { 7903 if (DBG) log("roaming and Network connection established"); 7904 mLastNetworkId = message.arg1; 7905 mLastBssid = (String) message.obj; 7906 mWifiInfo.setBSSID(mLastBssid); 7907 mWifiInfo.setNetworkId(mLastNetworkId); 7908 mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection( 7909 mLastBssid, true); 7910 sendNetworkStateChangeBroadcast(mLastBssid); 7911 7912 // Successful framework roam! (probably) 7913 mWifiMetrics.endConnectionEvent( 7914 WifiMetrics.ConnectionEvent.FAILURE_NONE, 7915 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7916 // We used to transition to ObtainingIpState in an 7917 // attempt to do DHCPv4 RENEWs on framework roams. 7918 // DHCP can take too long to time out, and we now rely 7919 // upon IpManager's use of IpReachabilityMonitor to 7920 // confirm our current network configuration. 7921 // 7922 // mIpManager.confirmConfiguration() is called within 7923 // the handling of SupplicantState.COMPLETED. 7924 transitionTo(mConnectedState); 7925 } else { 7926 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7927 } 7928 break; 7929 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7930 // Throw away but only if it corresponds to the network we're roaming to 7931 String bssid = (String) message.obj; 7932 if (true) { 7933 String target = ""; 7934 if (mTargetRoamBSSID != null) target = mTargetRoamBSSID; 7935 log("NETWORK_DISCONNECTION_EVENT in roaming state" 7936 + " BSSID=" + bssid 7937 + " target=" + target); 7938 } 7939 if (bssid != null && bssid.equals(mTargetRoamBSSID)) { 7940 handleNetworkDisconnect(); 7941 transitionTo(mDisconnectedState); 7942 } 7943 break; 7944 case WifiMonitor.SSID_TEMP_DISABLED: 7945 // Auth error while roaming 7946 logd("SSID_TEMP_DISABLED nid=" + Integer.toString(mLastNetworkId) 7947 + " id=" + Integer.toString(message.arg1) 7948 + " isRoaming=" + isRoaming() 7949 + " roam=" + mAutoRoaming); 7950 if (message.arg1 == mLastNetworkId) { 7951 config = getCurrentWifiConfiguration(); 7952 if (config != null) { 7953 mWifiLogger.captureBugReportData( 7954 WifiLogger.REPORT_REASON_AUTOROAM_FAILURE); 7955 mWifiConfigManager.noteRoamingFailure(config, 7956 WifiConfiguration.ROAMING_FAILURE_AUTH_FAILURE); 7957 } 7958 handleNetworkDisconnect(); 7959 transitionTo(mDisconnectingState); 7960 } 7961 return NOT_HANDLED; 7962 case CMD_START_SCAN: 7963 deferMessage(message); 7964 break; 7965 default: 7966 return NOT_HANDLED; 7967 } 7968 return HANDLED; 7969 } 7970 7971 @Override 7972 public void exit() { 7973 logd("WifiStateMachine: Leaving Roaming state"); 7974 } 7975 } 7976 7977 class ConnectedState extends State { 7978 @Override 7979 public void enter() { 7980 String address; 7981 updateDefaultRouteMacAddress(1000); 7982 if (DBG) { 7983 log("Enter ConnectedState " 7984 + " mScreenOn=" + mScreenOn 7985 + " scanperiod=" 7986 + Integer.toString( 7987 mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get()) 7988 + " useGscan=" + mHalBasedPnoDriverSupported + "/" 7989 + mWifiConfigManager.enableHalBasedPno.get() 7990 + " mHalBasedPnoEnableInDevSettings " + mHalBasedPnoEnableInDevSettings); 7991 } 7992 if (mScreenOn 7993 && getEnableAutoJoinWhenAssociated()) { 7994 if (useHalBasedAutoJoinOffload()) { 7995 startGScanConnectedModeOffload("connectedEnter"); 7996 } else { 7997 // restart scan alarm 7998 startDelayedScan(mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get(), 7999 null, null); 8000 } 8001 } 8002 registerConnected(); 8003 lastConnectAttemptTimestamp = 0; 8004 targetWificonfiguration = null; 8005 // Paranoia 8006 linkDebouncing = false; 8007 8008 // Not roaming anymore 8009 mAutoRoaming = false; 8010 8011 if (testNetworkDisconnect) { 8012 testNetworkDisconnectCounter++; 8013 logd("ConnectedState Enter start disconnect test " + 8014 testNetworkDisconnectCounter); 8015 sendMessageDelayed(obtainMessage(CMD_TEST_NETWORK_DISCONNECT, 8016 testNetworkDisconnectCounter, 0), 15000); 8017 } 8018 8019 // Reenable all networks, allow for hidden networks to be scanned 8020 mWifiConfigManager.enableAllNetworks(); 8021 8022 mLastDriverRoamAttempt = 0; 8023 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 8024 } 8025 @Override 8026 public boolean processMessage(Message message) { 8027 WifiConfiguration config = null; 8028 logStateAndMessage(message, this); 8029 8030 switch (message.what) { 8031 case CMD_RESTART_AUTOJOIN_OFFLOAD: 8032 if ( (int)message.arg2 < mRestartAutoJoinOffloadCounter ) { 8033 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 8034 return HANDLED; 8035 } 8036 /* If we are still in Disconnected state after having discovered a valid 8037 * network this means autojoin didnt managed to associate to the network, 8038 * then restart PNO so as we will try associating to it again. 8039 */ 8040 if (useHalBasedAutoJoinOffload()) { 8041 if (mGScanStartTimeMilli == 0) { 8042 // If offload is not started, then start it... 8043 startGScanConnectedModeOffload("connectedRestart"); 8044 } else { 8045 // If offload is already started, then check if we need to increase 8046 // the scan period and restart the Gscan 8047 long now = System.currentTimeMillis(); 8048 if (mGScanStartTimeMilli != 0 && now > mGScanStartTimeMilli 8049 && ((now - mGScanStartTimeMilli) 8050 > DISCONNECTED_SHORT_SCANS_DURATION_MILLI) 8051 && (mGScanPeriodMilli 8052 < mWifiConfigManager 8053 .wifiDisconnectedLongScanIntervalMilli.get())) 8054 { 8055 startConnectedGScan("Connected restart gscan"); 8056 } 8057 } 8058 } 8059 break; 8060 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 8061 updateAssociatedScanPermission(); 8062 break; 8063 case CMD_UNWANTED_NETWORK: 8064 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { 8065 mWifiConfigManager.handleBadNetworkDisconnectReport( 8066 mLastNetworkId, mWifiInfo); 8067 mWifiNative.disconnect(); 8068 transitionTo(mDisconnectingState); 8069 } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN || 8070 message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { 8071 Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 8072 ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN" 8073 : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED")); 8074 config = getCurrentWifiConfiguration(); 8075 if (config != null) { 8076 // Disable autojoin 8077 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) { 8078 config.validatedInternetAccess = false; 8079 // Clear last-selected status, as being last-selected also avoids 8080 // disabling auto-join. 8081 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 8082 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 8083 WifiConfiguration.INVALID_NETWORK_ID); 8084 } 8085 mWifiConfigManager.updateNetworkSelectionStatus(config, 8086 WifiConfiguration.NetworkSelectionStatus 8087 .DISABLED_NO_INTERNET); 8088 } 8089 config.numNoInternetAccessReports += 1; 8090 mWifiConfigManager.writeKnownNetworkHistory(); 8091 } 8092 } 8093 return HANDLED; 8094 case CMD_NETWORK_STATUS: 8095 if (message.arg1 == NetworkAgent.VALID_NETWORK) { 8096 config = getCurrentWifiConfiguration(); 8097 if (config != null) { 8098 // re-enable autojoin 8099 config.numNoInternetAccessReports = 0; 8100 config.validatedInternetAccess = true; 8101 mWifiConfigManager.writeKnownNetworkHistory(); 8102 } 8103 } 8104 return HANDLED; 8105 case CMD_ACCEPT_UNVALIDATED: 8106 boolean accept = (message.arg1 != 0); 8107 config = getCurrentWifiConfiguration(); 8108 if (config != null) { 8109 config.noInternetAccessExpected = accept; 8110 } 8111 return HANDLED; 8112 case CMD_TEST_NETWORK_DISCONNECT: 8113 // Force a disconnect 8114 if (message.arg1 == testNetworkDisconnectCounter) { 8115 mWifiNative.disconnect(); 8116 } 8117 break; 8118 case CMD_ASSOCIATED_BSSID: 8119 // ASSOCIATING to a new BSSID while already connected, indicates 8120 // that driver is roaming 8121 mLastDriverRoamAttempt = System.currentTimeMillis(); 8122 return NOT_HANDLED; 8123 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8124 long lastRoam = 0; 8125 mWifiMetrics.endConnectionEvent( 8126 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 8127 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8128 if (mLastDriverRoamAttempt != 0) { 8129 // Calculate time since last driver roam attempt 8130 lastRoam = System.currentTimeMillis() - mLastDriverRoamAttempt; 8131 mLastDriverRoamAttempt = 0; 8132 } 8133 if (unexpectedDisconnectedReason(message.arg2)) { 8134 mWifiLogger.captureBugReportData( 8135 WifiLogger.REPORT_REASON_UNEXPECTED_DISCONNECT); 8136 } 8137 config = getCurrentWifiConfiguration(); 8138 if (mScreenOn 8139 && !linkDebouncing 8140 && config != null 8141 && config.getNetworkSelectionStatus().isNetworkEnabled() 8142 && !mWifiConfigManager.isLastSelectedConfiguration(config) 8143 && (message.arg2 != 3 /* reason cannot be 3, i.e. locally generated */ 8144 || (lastRoam > 0 && lastRoam < 2000) /* unless driver is roaming */) 8145 && ((ScanResult.is24GHz(mWifiInfo.getFrequency()) 8146 && mWifiInfo.getRssi() > 8147 WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND) 8148 || (ScanResult.is5GHz(mWifiInfo.getFrequency()) 8149 && mWifiInfo.getRssi() > 8150 mWifiConfigManager.thresholdQualifiedRssi5.get()))) { 8151 // Start de-bouncing the L2 disconnection: 8152 // this L2 disconnection might be spurious. 8153 // Hence we allow 4 seconds for the state machine to try 8154 // to reconnect, go thru the 8155 // roaming cycle and enter Obtaining IP address 8156 // before signalling the disconnect to ConnectivityService and L3 8157 startScanForConfiguration(getCurrentWifiConfiguration(), false); 8158 linkDebouncing = true; 8159 8160 sendMessageDelayed(obtainMessage(CMD_DELAYED_NETWORK_DISCONNECT, 8161 0, mLastNetworkId), LINK_FLAPPING_DEBOUNCE_MSEC); 8162 if (DBG) { 8163 log("NETWORK_DISCONNECTION_EVENT in connected state" 8164 + " BSSID=" + mWifiInfo.getBSSID() 8165 + " RSSI=" + mWifiInfo.getRssi() 8166 + " freq=" + mWifiInfo.getFrequency() 8167 + " reason=" + message.arg2 8168 + " -> debounce"); 8169 } 8170 return HANDLED; 8171 } else { 8172 if (DBG) { 8173 log("NETWORK_DISCONNECTION_EVENT in connected state" 8174 + " BSSID=" + mWifiInfo.getBSSID() 8175 + " RSSI=" + mWifiInfo.getRssi() 8176 + " freq=" + mWifiInfo.getFrequency() 8177 + " was debouncing=" + linkDebouncing 8178 + " reason=" + message.arg2 8179 + " Network Selection Status=" + (config == null ? "Unavailable" 8180 : config.getNetworkSelectionStatus().getNetworkStatusString())); 8181 } 8182 } 8183 break; 8184 case CMD_AUTO_ROAM: 8185 // Clear the driver roam indication since we are attempting a framework roam 8186 mLastDriverRoamAttempt = 0; 8187 8188 /*<TODO> 2016-02-24 8189 Fix CMD_AUTO_ROAM to use the candidate (message.arg1) networkID, rather than 8190 the old networkID. 8191 The current code only handles roaming between BSSIDs on the same networkID, 8192 and will break for roams between different (but linked) networkIDs. This 8193 case occurs for DBDC roaming, and the CMD_AUTO_ROAM sent due to it will 8194 fail. 8195 */ 8196 /* Connect command coming from auto-join */ 8197 ScanResult candidate = (ScanResult)message.obj; 8198 String bssid = "any"; 8199 if (candidate != null) { 8200 bssid = candidate.BSSID; 8201 } 8202 int netId = message.arg1; 8203 if (netId == WifiConfiguration.INVALID_NETWORK_ID) { 8204 loge("AUTO_ROAM and no config, bail out..."); 8205 break; 8206 } else { 8207 config = mWifiConfigManager.getWifiConfiguration(netId); 8208 } 8209 8210 logd("CMD_AUTO_ROAM sup state " 8211 + mSupplicantStateTracker.getSupplicantStateName() 8212 + " my state " + getCurrentState().getName() 8213 + " nid=" + Integer.toString(netId) 8214 + " config " + config.configKey() 8215 + " roam=" + Integer.toString(message.arg2) 8216 + " to " + bssid 8217 + " targetRoamBSSID " + mTargetRoamBSSID); 8218 8219 setTargetBssid(config, bssid); 8220 mTargetNetworkId = netId; 8221 8222 /* Determine if this is a regular roam (between BSSIDs sharing the same SSID), 8223 or a DBDC roam (between 2.4 & 5GHz networks on different SSID's, but with 8224 matching 16 byte BSSID prefixes): 8225 */ 8226 WifiConfiguration currentConfig = getCurrentWifiConfiguration(); 8227 if (currentConfig != null && currentConfig.isLinked(config)) { 8228 // This is dual band roaming 8229 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 8230 WifiMetricsProto.ConnectionEvent.ROAM_DBDC); 8231 } else { 8232 // This is regular roaming 8233 mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID, 8234 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 8235 } 8236 8237 if (deferForUserInput(message, netId, false)) { 8238 mWifiMetrics.endConnectionEvent( 8239 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 8240 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8241 break; 8242 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 8243 WifiConfiguration.USER_BANNED) { 8244 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 8245 WifiManager.NOT_AUTHORIZED); 8246 mWifiMetrics.endConnectionEvent( 8247 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 8248 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8249 break; 8250 } 8251 8252 boolean ret = false; 8253 if (mLastNetworkId != netId) { 8254 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 8255 WifiConfiguration.UNKNOWN_UID) && mWifiNative.reconnect()) { 8256 ret = true; 8257 } 8258 } else { 8259 ret = mWifiNative.reassociate(); 8260 } 8261 if (ret) { 8262 lastConnectAttemptTimestamp = System.currentTimeMillis(); 8263 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 8264 8265 // replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 8266 mAutoRoaming = true; 8267 transitionTo(mRoamingState); 8268 8269 } else { 8270 loge("Failed to connect config: " + config + " netId: " + netId); 8271 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 8272 WifiManager.ERROR); 8273 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 8274 mWifiMetrics.endConnectionEvent( 8275 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 8276 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8277 break; 8278 } 8279 break; 8280 case CMD_START_IP_PACKET_OFFLOAD: { 8281 int slot = message.arg1; 8282 int intervalSeconds = message.arg2; 8283 KeepalivePacketData pkt = (KeepalivePacketData) message.obj; 8284 byte[] dstMac; 8285 try { 8286 InetAddress gateway = RouteInfo.selectBestRoute( 8287 mLinkProperties.getRoutes(), pkt.dstAddress).getGateway(); 8288 String dstMacStr = macAddressFromRoute(gateway.getHostAddress()); 8289 dstMac = macAddressFromString(dstMacStr); 8290 } catch (NullPointerException|IllegalArgumentException e) { 8291 loge("Can't find MAC address for next hop to " + pkt.dstAddress); 8292 mNetworkAgent.onPacketKeepaliveEvent(slot, 8293 ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 8294 break; 8295 } 8296 pkt.dstMac = dstMac; 8297 int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds); 8298 mNetworkAgent.onPacketKeepaliveEvent(slot, result); 8299 break; 8300 } 8301 default: 8302 return NOT_HANDLED; 8303 } 8304 return HANDLED; 8305 } 8306 8307 @Override 8308 public void exit() { 8309 logd("WifiStateMachine: Leaving Connected state"); 8310 setScanAlarm(false); 8311 mLastDriverRoamAttempt = 0; 8312 mWhiteListedSsids = null; 8313 } 8314 } 8315 8316 class DisconnectingState extends State { 8317 8318 @Override 8319 public void enter() { 8320 8321 if (DBG) { 8322 logd(" Enter DisconnectingState State scan interval " 8323 + mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get() 8324 + " mLegacyPnoEnabled= " + mLegacyPnoEnabled 8325 + " screenOn=" + mScreenOn); 8326 } 8327 8328 // Make sure we disconnect: we enter this state prior to connecting to a new 8329 // network, waiting for either a DISCONNECT event or a SUPPLICANT_STATE_CHANGE 8330 // event which in this case will be indicating that supplicant started to associate. 8331 // In some cases supplicant doesn't ignore the connect requests (it might not 8332 // find the target SSID in its cache), 8333 // Therefore we end up stuck that state, hence the need for the watchdog. 8334 disconnectingWatchdogCount++; 8335 logd("Start Disconnecting Watchdog " + disconnectingWatchdogCount); 8336 sendMessageDelayed(obtainMessage(CMD_DISCONNECTING_WATCHDOG_TIMER, 8337 disconnectingWatchdogCount, 0), DISCONNECTING_GUARD_TIMER_MSEC); 8338 } 8339 8340 @Override 8341 public boolean processMessage(Message message) { 8342 logStateAndMessage(message, this); 8343 switch (message.what) { 8344 case CMD_SET_OPERATIONAL_MODE: 8345 if (message.arg1 != CONNECT_MODE) { 8346 deferMessage(message); 8347 } 8348 break; 8349 case CMD_START_SCAN: 8350 deferMessage(message); 8351 return HANDLED; 8352 case CMD_DISCONNECTING_WATCHDOG_TIMER: 8353 if (disconnectingWatchdogCount == message.arg1) { 8354 if (DBG) log("disconnecting watchdog! -> disconnect"); 8355 handleNetworkDisconnect(); 8356 transitionTo(mDisconnectedState); 8357 } 8358 break; 8359 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 8360 /** 8361 * If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT 8362 * we have missed the network disconnection, transition to mDisconnectedState 8363 * and handle the rest of the events there 8364 */ 8365 deferMessage(message); 8366 handleNetworkDisconnect(); 8367 transitionTo(mDisconnectedState); 8368 break; 8369 default: 8370 return NOT_HANDLED; 8371 } 8372 return HANDLED; 8373 } 8374 } 8375 8376 class DisconnectedState extends State { 8377 @Override 8378 public void enter() { 8379 // We dont scan frequently if this is a temporary disconnect 8380 // due to p2p 8381 if (mTemporarilyDisconnectWifi) { 8382 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 8383 return; 8384 } 8385 8386 if (DBG) { 8387 logd(" Enter DisconnectedState scan interval " 8388 + mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get() 8389 + " mLegacyPnoEnabled= " + mLegacyPnoEnabled 8390 + " screenOn=" + mScreenOn 8391 + " useGscan=" + mHalBasedPnoDriverSupported + "/" 8392 + mWifiConfigManager.enableHalBasedPno.get()); 8393 } 8394 8395 /** clear the roaming state, if we were roaming, we failed */ 8396 mAutoRoaming = false; 8397 8398 if (useHalBasedAutoJoinOffload()) { 8399 startGScanDisconnectedModeOffload("disconnectedEnter"); 8400 } else { 8401 if (mScreenOn) { 8402 /** 8403 * screen lit and => start scan immediately 8404 */ 8405 startScan(UNKNOWN_SCAN_SOURCE, 0, null, null); 8406 } else { 8407 /** 8408 * screen dark and PNO supported => scan alarm disabled 8409 */ 8410 if (mBackgroundScanSupported) { 8411 /* If a regular scan result is pending, do not initiate background 8412 * scan until the scan results are returned. This is needed because 8413 * initiating a background scan will cancel the regular scan and 8414 * scan results will not be returned until background scanning is 8415 * cleared 8416 */ 8417 if (!mIsScanOngoing) { 8418 enableBackgroundScan(true); 8419 } 8420 } else { 8421 setScanAlarm(true); 8422 } 8423 } 8424 } 8425 8426 /** 8427 * If we have no networks saved, the supplicant stops doing the periodic scan. 8428 * The scans are useful to notify the user of the presence of an open network. 8429 * Note that these are not wake up scans. 8430 */ 8431 if (mNoNetworksPeriodicScan != 0 && !mP2pConnected.get() 8432 && mWifiConfigManager.getConfiguredNetworks().size() == 0) { 8433 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8434 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8435 } 8436 8437 mDisconnectedTimeStamp = System.currentTimeMillis(); 8438 mDisconnectedPnoAlarmCount = 0; 8439 } 8440 @Override 8441 public boolean processMessage(Message message) { 8442 boolean ret = HANDLED; 8443 8444 logStateAndMessage(message, this); 8445 8446 switch (message.what) { 8447 case CMD_NO_NETWORKS_PERIODIC_SCAN: 8448 if (mP2pConnected.get()) break; 8449 if (mNoNetworksPeriodicScan != 0 && message.arg1 == mPeriodicScanToken && 8450 mWifiConfigManager.getConfiguredNetworks().size() == 0) { 8451 startScan(UNKNOWN_SCAN_SOURCE, -1, null, null); 8452 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8453 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8454 } 8455 break; 8456 case WifiManager.FORGET_NETWORK: 8457 case CMD_REMOVE_NETWORK: 8458 case CMD_REMOVE_APP_CONFIGURATIONS: 8459 case CMD_REMOVE_USER_CONFIGURATIONS: 8460 // Set up a delayed message here. After the forget/remove is handled 8461 // the handled delayed message will determine if there is a need to 8462 // scan and continue 8463 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8464 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8465 ret = NOT_HANDLED; 8466 break; 8467 case CMD_SET_OPERATIONAL_MODE: 8468 if (message.arg1 != CONNECT_MODE) { 8469 mOperationalMode = message.arg1; 8470 mWifiConfigManager.disableAllNetworksNative(); 8471 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 8472 mWifiP2pChannel.sendMessage(CMD_DISABLE_P2P_REQ); 8473 setWifiState(WIFI_STATE_DISABLED); 8474 } 8475 transitionTo(mScanModeState); 8476 } 8477 mWifiConfigManager. 8478 setAndEnableLastSelectedConfiguration( 8479 WifiConfiguration.INVALID_NETWORK_ID); 8480 break; 8481 /* Ignore network disconnect */ 8482 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8483 // Interpret this as an L2 connection failure 8484 break; 8485 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 8486 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 8487 if (DBG) { 8488 logd("SUPPLICANT_STATE_CHANGE_EVENT state=" + stateChangeResult.state + 8489 " -> state= " + WifiInfo.getDetailedStateOf(stateChangeResult.state) 8490 + " debouncing=" + linkDebouncing); 8491 } 8492 setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state)); 8493 /* ConnectModeState does the rest of the handling */ 8494 ret = NOT_HANDLED; 8495 break; 8496 case CMD_START_SCAN: 8497 if (!checkOrDeferScanAllowed(message)) { 8498 // The scan request was rescheduled 8499 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 8500 return HANDLED; 8501 } 8502 if (message.arg1 == SCAN_ALARM_SOURCE) { 8503 // Check if the CMD_START_SCAN message is obsolete (and thus if it should 8504 // not be processed) and restart the scan 8505 int period = 8506 mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get(); 8507 if (mP2pConnected.get()) { 8508 period = (int) mFacade.getLongSetting(mContext, 8509 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, 8510 period); 8511 } 8512 if (!checkAndRestartDelayedScan(message.arg2, 8513 true, period, null, null)) { 8514 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 8515 logd("Disconnected CMD_START_SCAN source " 8516 + message.arg1 8517 + " " + message.arg2 + ", " + mDelayedScanCounter 8518 + " -> obsolete"); 8519 return HANDLED; 8520 } 8521 /* Disable background scan temporarily during a regular scan */ 8522 enableBackgroundScan(false); 8523 handleScanRequest(message); 8524 ret = HANDLED; 8525 } else { 8526 8527 /* 8528 * The SCAN request is not handled in this state and 8529 * would eventually might/will get handled in the 8530 * parent's state. The PNO, if already enabled had to 8531 * get disabled before the SCAN trigger. Hence, stop 8532 * the PNO if already enabled in this state, though the 8533 * SCAN request is not handled(PNO disable before the 8534 * SCAN trigger in any other state is not the right 8535 * place to issue). 8536 */ 8537 8538 enableBackgroundScan(false); 8539 ret = NOT_HANDLED; 8540 } 8541 break; 8542 case CMD_RESTART_AUTOJOIN_OFFLOAD: 8543 if ( (int)message.arg2 < mRestartAutoJoinOffloadCounter ) { 8544 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 8545 return HANDLED; 8546 } 8547 /* If we are still in Disconnected state after having discovered a valid 8548 * network this means autojoin didnt managed to associate to the network, 8549 * then restart PNO so as we will try associating to it again. 8550 */ 8551 if (useHalBasedAutoJoinOffload()) { 8552 if (mGScanStartTimeMilli == 0) { 8553 // If offload is not started, then start it... 8554 startGScanDisconnectedModeOffload("disconnectedRestart"); 8555 } else { 8556 // If offload is already started, then check if we need to increase 8557 // the scan period and restart the Gscan 8558 long now = System.currentTimeMillis(); 8559 if (mGScanStartTimeMilli != 0 && now > mGScanStartTimeMilli 8560 && ((now - mGScanStartTimeMilli) 8561 > DISCONNECTED_SHORT_SCANS_DURATION_MILLI) 8562 && (mGScanPeriodMilli 8563 < mWifiConfigManager 8564 .wifiDisconnectedLongScanIntervalMilli.get())) 8565 { 8566 startDisconnectedGScan("disconnected restart gscan"); 8567 } 8568 } 8569 } else { 8570 // If we are still disconnected for a short while after having found a 8571 // network thru PNO, then something went wrong, and for some reason we 8572 // couldn't join this network. 8573 // It might be due to a SW bug in supplicant or the wifi stack, or an 8574 // interoperability issue, or we try to join a bad bss and failed 8575 // In that case we want to restart pno so as to make sure that we will 8576 // attempt again to join that network. 8577 if (!mScreenOn && !mIsScanOngoing && mBackgroundScanSupported) { 8578 enableBackgroundScan(false); 8579 enableBackgroundScan(true); 8580 } 8581 return HANDLED; 8582 } 8583 break; 8584 case WifiMonitor.SCAN_RESULTS_EVENT: 8585 case WifiMonitor.SCAN_FAILED_EVENT: 8586 /* Re-enable background scan when a pending scan result is received */ 8587 if (!mScreenOn && mIsScanOngoing 8588 && mBackgroundScanSupported 8589 && !useHalBasedAutoJoinOffload()) { 8590 enableBackgroundScan(true); 8591 } else if (!mScreenOn 8592 && !mIsScanOngoing 8593 && mBackgroundScanSupported 8594 && !useHalBasedAutoJoinOffload()) { 8595 // We receive scan results from legacy PNO, hence restart the PNO alarm 8596 int delay; 8597 if (mDisconnectedPnoAlarmCount < 1) { 8598 delay = 30 * 1000; 8599 } else if (mDisconnectedPnoAlarmCount < 3) { 8600 delay = 60 * 1000; 8601 } else { 8602 delay = 360 * 1000; 8603 } 8604 mDisconnectedPnoAlarmCount++; 8605 if (DBG) { 8606 logd("Starting PNO alarm " + delay); 8607 } 8608 mAlarmManager.set(AlarmManager.RTC_WAKEUP, 8609 System.currentTimeMillis() + delay, 8610 mPnoIntent); 8611 } 8612 /* Handled in parent state */ 8613 ret = NOT_HANDLED; 8614 break; 8615 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 8616 NetworkInfo info = (NetworkInfo) message.obj; 8617 mP2pConnected.set(info.isConnected()); 8618 if (mP2pConnected.get()) { 8619 int defaultInterval = mContext.getResources().getInteger( 8620 R.integer.config_wifi_scan_interval_p2p_connected); 8621 long scanIntervalMs = mFacade.getLongSetting(mContext, 8622 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, 8623 defaultInterval); 8624 mWifiNative.setScanInterval((int) scanIntervalMs/1000); 8625 } else if (mWifiConfigManager.getConfiguredNetworks().size() == 0) { 8626 if (DBG) log("Turn on scanning after p2p disconnected"); 8627 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8628 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8629 } else { 8630 // If P2P is not connected and there are saved networks, then restart 8631 // scanning at the normal period. This is necessary because scanning might 8632 // have been disabled altogether if WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS 8633 // was set to zero. 8634 if (useHalBasedAutoJoinOffload()) { 8635 startGScanDisconnectedModeOffload("p2pRestart"); 8636 } else { 8637 startDelayedScan( 8638 mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get(), 8639 null, null); 8640 } 8641 } 8642 break; 8643 case CMD_RECONNECT: 8644 case CMD_REASSOCIATE: 8645 if (mTemporarilyDisconnectWifi) { 8646 // Drop a third party reconnect/reassociate if STA is 8647 // temporarily disconnected for p2p 8648 break; 8649 } else { 8650 // ConnectModeState handles it 8651 ret = NOT_HANDLED; 8652 } 8653 break; 8654 case CMD_SCREEN_STATE_CHANGED: 8655 handleScreenStateChanged(message.arg1 != 0); 8656 break; 8657 default: 8658 ret = NOT_HANDLED; 8659 } 8660 return ret; 8661 } 8662 8663 @Override 8664 public void exit() { 8665 mDisconnectedPnoAlarmCount = 0; 8666 /* No need for a background scan upon exit from a disconnected state */ 8667 enableBackgroundScan(false); 8668 setScanAlarm(false); 8669 mAlarmManager.cancel(mPnoIntent); 8670 } 8671 } 8672 8673 class WpsRunningState extends State { 8674 // Tracks the source to provide a reply 8675 private Message mSourceMessage; 8676 @Override 8677 public void enter() { 8678 mSourceMessage = Message.obtain(getCurrentMessage()); 8679 } 8680 @Override 8681 public boolean processMessage(Message message) { 8682 logStateAndMessage(message, this); 8683 8684 switch (message.what) { 8685 case WifiMonitor.WPS_SUCCESS_EVENT: 8686 // Ignore intermediate success, wait for full connection 8687 break; 8688 case WifiMonitor.NETWORK_CONNECTION_EVENT: 8689 replyToMessage(mSourceMessage, WifiManager.WPS_COMPLETED); 8690 mSourceMessage.recycle(); 8691 mSourceMessage = null; 8692 deferMessage(message); 8693 transitionTo(mDisconnectedState); 8694 break; 8695 case WifiMonitor.WPS_OVERLAP_EVENT: 8696 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 8697 WifiManager.WPS_OVERLAP_ERROR); 8698 mSourceMessage.recycle(); 8699 mSourceMessage = null; 8700 transitionTo(mDisconnectedState); 8701 break; 8702 case WifiMonitor.WPS_FAIL_EVENT: 8703 // Arg1 has the reason for the failure 8704 if ((message.arg1 != WifiManager.ERROR) || (message.arg2 != 0)) { 8705 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1); 8706 mSourceMessage.recycle(); 8707 mSourceMessage = null; 8708 transitionTo(mDisconnectedState); 8709 } else { 8710 if (DBG) log("Ignore unspecified fail event during WPS connection"); 8711 } 8712 break; 8713 case WifiMonitor.WPS_TIMEOUT_EVENT: 8714 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 8715 WifiManager.WPS_TIMED_OUT); 8716 mSourceMessage.recycle(); 8717 mSourceMessage = null; 8718 transitionTo(mDisconnectedState); 8719 break; 8720 case WifiManager.START_WPS: 8721 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS); 8722 break; 8723 case WifiManager.CANCEL_WPS: 8724 if (mWifiNative.cancelWps()) { 8725 replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED); 8726 } else { 8727 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR); 8728 } 8729 transitionTo(mDisconnectedState); 8730 break; 8731 /** 8732 * Defer all commands that can cause connections to a different network 8733 * or put the state machine out of connect mode 8734 */ 8735 case CMD_STOP_DRIVER: 8736 case CMD_SET_OPERATIONAL_MODE: 8737 case WifiManager.CONNECT_NETWORK: 8738 case CMD_ENABLE_NETWORK: 8739 case CMD_RECONNECT: 8740 case CMD_REASSOCIATE: 8741 case CMD_ENABLE_ALL_NETWORKS: 8742 deferMessage(message); 8743 break; 8744 case CMD_AUTO_CONNECT: 8745 case CMD_AUTO_ROAM: 8746 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 8747 return HANDLED; 8748 case CMD_START_SCAN: 8749 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 8750 return HANDLED; 8751 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8752 if (DBG) log("Network connection lost"); 8753 handleNetworkDisconnect(); 8754 break; 8755 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 8756 if (DBG) log("Ignore Assoc reject event during WPS Connection"); 8757 break; 8758 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 8759 // Disregard auth failure events during WPS connection. The 8760 // EAP sequence is retried several times, and there might be 8761 // failures (especially for wps pin). We will get a WPS_XXX 8762 // event at the end of the sequence anyway. 8763 if (DBG) log("Ignore auth failure during WPS connection"); 8764 break; 8765 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 8766 // Throw away supplicant state changes when WPS is running. 8767 // We will start getting supplicant state changes once we get 8768 // a WPS success or failure 8769 break; 8770 default: 8771 return NOT_HANDLED; 8772 } 8773 return HANDLED; 8774 } 8775 8776 @Override 8777 public void exit() { 8778 mWifiConfigManager.enableAllNetworks(); 8779 mWifiConfigManager.loadConfiguredNetworks(); 8780 } 8781 } 8782 8783 class SoftApState extends State { 8784 private SoftApManager mSoftApManager; 8785 8786 private class SoftApListener implements SoftApManager.Listener { 8787 @Override 8788 public void onStateChanged(int state, int reason) { 8789 if (state == WIFI_AP_STATE_DISABLED) { 8790 sendMessage(CMD_AP_STOPPED); 8791 } else if (state == WIFI_AP_STATE_FAILED) { 8792 sendMessage(CMD_START_AP_FAILURE); 8793 } 8794 8795 setWifiApState(state, reason); 8796 } 8797 } 8798 8799 @Override 8800 public void enter() { 8801 final Message message = getCurrentMessage(); 8802 if (message.what == CMD_START_AP) { 8803 WifiConfiguration config = (WifiConfiguration) message.obj; 8804 8805 if (config == null) { 8806 /** 8807 * Configuration not provided in the command, fallback to use the current 8808 * configuration. 8809 */ 8810 config = mWifiApConfigStore.getApConfiguration(); 8811 } else { 8812 /* Update AP configuration. */ 8813 mWifiApConfigStore.setApConfiguration(config); 8814 } 8815 8816 checkAndSetConnectivityInstance(); 8817 mSoftApManager = mFacade.makeSoftApManager( 8818 mContext, getHandler().getLooper(), mWifiNative, mNwService, 8819 mCm, mCountryCode.getCurrentCountryCode(), 8820 mWifiApConfigStore.getAllowed2GChannel(), 8821 new SoftApListener()); 8822 mSoftApManager.start(config); 8823 } else { 8824 throw new RuntimeException("Illegal transition to SoftApState: " + message); 8825 } 8826 } 8827 8828 @Override 8829 public void exit() { 8830 mSoftApManager = null; 8831 } 8832 8833 @Override 8834 public boolean processMessage(Message message) { 8835 logStateAndMessage(message, this); 8836 8837 switch(message.what) { 8838 case CMD_START_AP: 8839 /* Ignore start command when it is starting/started. */ 8840 break; 8841 case CMD_STOP_AP: 8842 mSoftApManager.stop(); 8843 break; 8844 case CMD_START_AP_FAILURE: 8845 transitionTo(mInitialState); 8846 break; 8847 case CMD_AP_STOPPED: 8848 transitionTo(mInitialState); 8849 break; 8850 default: 8851 return NOT_HANDLED; 8852 } 8853 return HANDLED; 8854 } 8855 } 8856 8857 /** 8858 * State machine initiated requests can have replyTo set to null indicating 8859 * there are no recepients, we ignore those reply actions. 8860 */ 8861 private void replyToMessage(Message msg, int what) { 8862 if (msg.replyTo == null) return; 8863 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 8864 mReplyChannel.replyToMessage(msg, dstMsg); 8865 } 8866 8867 private void replyToMessage(Message msg, int what, int arg1) { 8868 if (msg.replyTo == null) return; 8869 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 8870 dstMsg.arg1 = arg1; 8871 mReplyChannel.replyToMessage(msg, dstMsg); 8872 } 8873 8874 private void replyToMessage(Message msg, int what, Object obj) { 8875 if (msg.replyTo == null) return; 8876 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 8877 dstMsg.obj = obj; 8878 mReplyChannel.replyToMessage(msg, dstMsg); 8879 } 8880 8881 /** 8882 * arg2 on the source message has a unique id that needs to be retained in replies 8883 * to match the request 8884 * <p>see WifiManager for details 8885 */ 8886 private Message obtainMessageWithWhatAndArg2(Message srcMsg, int what) { 8887 Message msg = Message.obtain(); 8888 msg.what = what; 8889 msg.arg2 = srcMsg.arg2; 8890 return msg; 8891 } 8892 8893 /** 8894 * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT 8895 * @param msg Must have a WifiConfiguration obj to succeed 8896 */ 8897 private void broadcastWifiCredentialChanged(int wifiCredentialEventType, 8898 WifiConfiguration config) { 8899 if (config != null && config.preSharedKey != null) { 8900 Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); 8901 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); 8902 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, 8903 wifiCredentialEventType); 8904 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT, 8905 android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE); 8906 } 8907 } 8908 8909 private static int parseHex(char ch) { 8910 if ('0' <= ch && ch <= '9') { 8911 return ch - '0'; 8912 } else if ('a' <= ch && ch <= 'f') { 8913 return ch - 'a' + 10; 8914 } else if ('A' <= ch && ch <= 'F') { 8915 return ch - 'A' + 10; 8916 } else { 8917 throw new NumberFormatException("" + ch + " is not a valid hex digit"); 8918 } 8919 } 8920 8921 private byte[] parseHex(String hex) { 8922 /* This only works for good input; don't throw bad data at it */ 8923 if (hex == null) { 8924 return new byte[0]; 8925 } 8926 8927 if (hex.length() % 2 != 0) { 8928 throw new NumberFormatException(hex + " is not a valid hex string"); 8929 } 8930 8931 byte[] result = new byte[(hex.length())/2 + 1]; 8932 result[0] = (byte) ((hex.length())/2); 8933 for (int i = 0, j = 1; i < hex.length(); i += 2, j++) { 8934 int val = parseHex(hex.charAt(i)) * 16 + parseHex(hex.charAt(i+1)); 8935 byte b = (byte) (val & 0xFF); 8936 result[j] = b; 8937 } 8938 8939 return result; 8940 } 8941 8942 private static String makeHex(byte[] bytes) { 8943 StringBuilder sb = new StringBuilder(); 8944 for (byte b : bytes) { 8945 sb.append(String.format("%02x", b)); 8946 } 8947 return sb.toString(); 8948 } 8949 8950 private static String makeHex(byte[] bytes, int from, int len) { 8951 StringBuilder sb = new StringBuilder(); 8952 for (int i = 0; i < len; i++) { 8953 sb.append(String.format("%02x", bytes[from+i])); 8954 } 8955 return sb.toString(); 8956 } 8957 8958 private static byte[] concat(byte[] array1, byte[] array2, byte[] array3) { 8959 8960 int len = array1.length + array2.length + array3.length; 8961 8962 if (array1.length != 0) { 8963 len++; /* add another byte for size */ 8964 } 8965 8966 if (array2.length != 0) { 8967 len++; /* add another byte for size */ 8968 } 8969 8970 if (array3.length != 0) { 8971 len++; /* add another byte for size */ 8972 } 8973 8974 byte[] result = new byte[len]; 8975 8976 int index = 0; 8977 if (array1.length != 0) { 8978 result[index] = (byte) (array1.length & 0xFF); 8979 index++; 8980 for (byte b : array1) { 8981 result[index] = b; 8982 index++; 8983 } 8984 } 8985 8986 if (array2.length != 0) { 8987 result[index] = (byte) (array2.length & 0xFF); 8988 index++; 8989 for (byte b : array2) { 8990 result[index] = b; 8991 index++; 8992 } 8993 } 8994 8995 if (array3.length != 0) { 8996 result[index] = (byte) (array3.length & 0xFF); 8997 index++; 8998 for (byte b : array3) { 8999 result[index] = b; 9000 index++; 9001 } 9002 } 9003 return result; 9004 } 9005 9006 private static byte[] concatHex(byte[] array1, byte[] array2) { 9007 9008 int len = array1.length + array2.length; 9009 9010 byte[] result = new byte[len]; 9011 9012 int index = 0; 9013 if (array1.length != 0) { 9014 for (byte b : array1) { 9015 result[index] = b; 9016 index++; 9017 } 9018 } 9019 9020 if (array2.length != 0) { 9021 for (byte b : array2) { 9022 result[index] = b; 9023 index++; 9024 } 9025 } 9026 9027 return result; 9028 } 9029 9030 String getGsmSimAuthResponse(String[] requestData, TelephonyManager tm) { 9031 StringBuilder sb = new StringBuilder(); 9032 for (String challenge : requestData) { 9033 if (challenge == null || challenge.isEmpty()) { 9034 continue; 9035 } 9036 logd("RAND = " + challenge); 9037 9038 byte[] rand = null; 9039 try { 9040 rand = parseHex(challenge); 9041 } catch (NumberFormatException e) { 9042 loge("malformed challenge"); 9043 continue; 9044 } 9045 9046 String base64Challenge = android.util.Base64.encodeToString( 9047 rand, android.util.Base64.NO_WRAP); 9048 /* 9049 * First, try with appType = 2 => USIM according to 9050 * com.android.internal.telephony.PhoneConstants#APPTYPE_xxx 9051 */ 9052 int appType = 2; 9053 String tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge); 9054 if (tmResponse == null) { 9055 /* Then, in case of failure, issue may be due to sim type, retry as a simple sim 9056 * appType = 1 => SIM 9057 */ 9058 appType = 1; 9059 tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge); 9060 } 9061 logv("Raw Response - " + tmResponse); 9062 9063 if (tmResponse == null || tmResponse.length() <= 4) { 9064 loge("bad response - " + tmResponse); 9065 return null; 9066 } 9067 9068 byte[] result = android.util.Base64.decode(tmResponse, android.util.Base64.DEFAULT); 9069 logv("Hex Response -" + makeHex(result)); 9070 int sres_len = result[0]; 9071 if (sres_len >= result.length) { 9072 loge("malfomed response - " + tmResponse); 9073 return null; 9074 } 9075 String sres = makeHex(result, 1, sres_len); 9076 int kc_offset = 1 + sres_len; 9077 if (kc_offset >= result.length) { 9078 loge("malfomed response - " + tmResponse); 9079 return null; 9080 } 9081 int kc_len = result[kc_offset]; 9082 if (kc_offset + kc_len > result.length) { 9083 loge("malfomed response - " + tmResponse); 9084 return null; 9085 } 9086 String kc = makeHex(result, 1 + kc_offset, kc_len); 9087 sb.append(":" + kc + ":" + sres); 9088 logv("kc:" + kc + " sres:" + sres); 9089 } 9090 9091 return sb.toString(); 9092 } 9093 9094 void handleGsmAuthRequest(SimAuthRequestData requestData) { 9095 if (targetWificonfiguration == null 9096 || targetWificonfiguration.networkId == requestData.networkId) { 9097 logd("id matches targetWifiConfiguration"); 9098 } else { 9099 logd("id does not match targetWifiConfiguration"); 9100 return; 9101 } 9102 9103 TelephonyManager tm = (TelephonyManager) 9104 mContext.getSystemService(Context.TELEPHONY_SERVICE); 9105 9106 if (tm == null) { 9107 loge("could not get telephony manager"); 9108 mWifiNative.simAuthFailedResponse(requestData.networkId); 9109 return; 9110 } 9111 9112 String response = getGsmSimAuthResponse(requestData.data, tm); 9113 if (response == null) { 9114 mWifiNative.simAuthFailedResponse(requestData.networkId); 9115 } else { 9116 logv("Supplicant Response -" + response); 9117 mWifiNative.simAuthResponse(requestData.networkId, "GSM-AUTH", response); 9118 } 9119 } 9120 9121 void handle3GAuthRequest(SimAuthRequestData requestData) { 9122 StringBuilder sb = new StringBuilder(); 9123 byte[] rand = null; 9124 byte[] authn = null; 9125 String res_type = "UMTS-AUTH"; 9126 9127 if (targetWificonfiguration == null 9128 || targetWificonfiguration.networkId == requestData.networkId) { 9129 logd("id matches targetWifiConfiguration"); 9130 } else { 9131 logd("id does not match targetWifiConfiguration"); 9132 return; 9133 } 9134 if (requestData.data.length == 2) { 9135 try { 9136 rand = parseHex(requestData.data[0]); 9137 authn = parseHex(requestData.data[1]); 9138 } catch (NumberFormatException e) { 9139 loge("malformed challenge"); 9140 } 9141 } else { 9142 loge("malformed challenge"); 9143 } 9144 9145 String tmResponse = ""; 9146 if (rand != null && authn != null) { 9147 String base64Challenge = android.util.Base64.encodeToString( 9148 concatHex(rand,authn), android.util.Base64.NO_WRAP); 9149 9150 TelephonyManager tm = (TelephonyManager) 9151 mContext.getSystemService(Context.TELEPHONY_SERVICE); 9152 if (tm != null) { 9153 int appType = 2; // 2 => USIM 9154 tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge); 9155 logv("Raw Response - " + tmResponse); 9156 } else { 9157 loge("could not get telephony manager"); 9158 } 9159 } 9160 9161 boolean good_response = false; 9162 if (tmResponse != null && tmResponse.length() > 4) { 9163 byte[] result = android.util.Base64.decode(tmResponse, 9164 android.util.Base64.DEFAULT); 9165 loge("Hex Response - " + makeHex(result)); 9166 byte tag = result[0]; 9167 if (tag == (byte) 0xdb) { 9168 logv("successful 3G authentication "); 9169 int res_len = result[1]; 9170 String res = makeHex(result, 2, res_len); 9171 int ck_len = result[res_len + 2]; 9172 String ck = makeHex(result, res_len + 3, ck_len); 9173 int ik_len = result[res_len + ck_len + 3]; 9174 String ik = makeHex(result, res_len + ck_len + 4, ik_len); 9175 sb.append(":" + ik + ":" + ck + ":" + res); 9176 logv("ik:" + ik + "ck:" + ck + " res:" + res); 9177 good_response = true; 9178 } else if (tag == (byte) 0xdc) { 9179 loge("synchronisation failure"); 9180 int auts_len = result[1]; 9181 String auts = makeHex(result, 2, auts_len); 9182 res_type = "UMTS-AUTS"; 9183 sb.append(":" + auts); 9184 logv("auts:" + auts); 9185 good_response = true; 9186 } else { 9187 loge("bad response - unknown tag = " + tag); 9188 } 9189 } else { 9190 loge("bad response - " + tmResponse); 9191 } 9192 9193 if (good_response) { 9194 String response = sb.toString(); 9195 logv("Supplicant Response -" + response); 9196 mWifiNative.simAuthResponse(requestData.networkId, res_type, response); 9197 } else { 9198 mWifiNative.umtsAuthFailedResponse(requestData.networkId); 9199 } 9200 } 9201 9202 public int getCurrentUserId() { 9203 return mCurrentUserId; 9204 } 9205 9206 private boolean isCurrentUserProfile(int userId) { 9207 if (userId == mCurrentUserId) { 9208 return true; 9209 } 9210 final UserInfo parent = mUserManager.getProfileParent(userId); 9211 return parent != null && parent.id == mCurrentUserId; 9212 } 9213 9214 public List<UserInfo> getCurrentUserProfiles() { 9215 return mUserManager.getProfiles(mCurrentUserId); 9216 } 9217 9218 /** 9219 * @param reason reason code from supplicant on network disconnected event 9220 * @return true if this is a suspicious disconnect 9221 */ 9222 static boolean unexpectedDisconnectedReason(int reason) { 9223 return reason == 2 // PREV_AUTH_NOT_VALID 9224 || reason == 6 // CLASS2_FRAME_FROM_NONAUTH_STA 9225 || reason == 7 // FRAME_FROM_NONASSOC_STA 9226 || reason == 8 // STA_HAS_LEFT 9227 || reason == 9 // STA_REQ_ASSOC_WITHOUT_AUTH 9228 || reason == 14 // MICHAEL_MIC_FAILURE 9229 || reason == 15 // 4WAY_HANDSHAKE_TIMEOUT 9230 || reason == 16 // GROUP_KEY_UPDATE_TIMEOUT 9231 || reason == 18 // GROUP_CIPHER_NOT_VALID 9232 || reason == 19 // PAIRWISE_CIPHER_NOT_VALID 9233 || reason == 23 // IEEE_802_1X_AUTH_FAILED 9234 || reason == 34; // DISASSOC_LOW_ACK 9235 } 9236 9237 /** 9238 * Update WifiMetrics before dumping 9239 */ 9240 void updateWifiMetrics() { 9241 int numSavedNetworks = mWifiConfigManager.getConfiguredNetworksSize(); 9242 int numOpenNetworks = 0; 9243 int numPersonalNetworks = 0; 9244 int numEnterpriseNetworks = 0; 9245 int numNetworksAddedByUser = 0; 9246 int numNetworksAddedByApps = 0; 9247 for (WifiConfiguration config : mWifiConfigManager.getConfiguredNetworks()) { 9248 if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { 9249 numOpenNetworks++; 9250 } else if (config.isEnterprise()) { 9251 numEnterpriseNetworks++; 9252 } else { 9253 numPersonalNetworks++; 9254 } 9255 if (config.selfAdded) { 9256 numNetworksAddedByUser++; 9257 } else { 9258 numNetworksAddedByApps++; 9259 } 9260 } 9261 mWifiMetrics.setNumSavedNetworks(numSavedNetworks); 9262 mWifiMetrics.setNumOpenNetworks(numOpenNetworks); 9263 mWifiMetrics.setNumPersonalNetworks(numPersonalNetworks); 9264 mWifiMetrics.setNumEnterpriseNetworks(numEnterpriseNetworks); 9265 mWifiMetrics.setNumNetworksAddedByUser(numNetworksAddedByUser); 9266 mWifiMetrics.setNumNetworksAddedByApps(numNetworksAddedByApps); 9267 9268 /* <TODO> decide how to access WifiServiecImpl.isLocationEnabled() or if to do it manually 9269 mWifiMetrics.setIsLocationEnabled(Settings.Secure.getInt( 9270 mContext.getContentResolver(), 9271 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) 9272 != Settings.Secure.LOCATION_MODE_OFF); 9273 */ 9274 9275 /* <TODO> decide how statemachine will access WifiSettingsStore 9276 mWifiMetrics.setIsScanningAlwaysEnabled(mSettingsStore.isScanningAlwaysAvailable()); 9277 */ 9278 } 9279 9280 private static String getLinkPropertiesSummary(LinkProperties lp) { 9281 List<String> attributes = new ArrayList(6); 9282 if (lp.hasIPv4Address()) { 9283 attributes.add("v4"); 9284 } 9285 if (lp.hasIPv4DefaultRoute()) { 9286 attributes.add("v4r"); 9287 } 9288 if (lp.hasIPv4DnsServer()) { 9289 attributes.add("v4dns"); 9290 } 9291 if (lp.hasGlobalIPv6Address()) { 9292 attributes.add("v6"); 9293 } 9294 if (lp.hasIPv6DefaultRoute()) { 9295 attributes.add("v6r"); 9296 } 9297 if (lp.hasIPv6DnsServer()) { 9298 attributes.add("v6dns"); 9299 } 9300 9301 return TextUtils.join(" ", attributes); 9302 } 9303 9304 /** 9305 * Try to connect to the network of candidate. According to the current connected network, this 9306 * API determines whether no action, disconnect and connect, or roaming. 9307 * 9308 * @param candidate the candidate network to connect to 9309 */ 9310 private void tryToConnectToNetwork(WifiConfiguration candidate) { 9311 if (candidate == null) { 9312 if (DBG) { 9313 Log.d(TAG, "Try to connect to null, give up"); 9314 } 9315 return; 9316 } 9317 9318 ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate(); 9319 if (scanResultCandidate == null) { 9320 Log.e(TAG, "tryToConnectToNetwork: bad candidate. Network:" + candidate 9321 + " scanresult: " + scanResultCandidate); 9322 return; 9323 } 9324 9325 String targetBssid = scanResultCandidate.BSSID; 9326 String targetAssociationId = candidate.SSID + " : " + targetBssid; 9327 if (targetBssid != null && targetBssid.equals(mWifiInfo.getBSSID())) { 9328 if (DBG) { 9329 Log.d(TAG, "tryToConnectToNetwork: Already connect to" + targetAssociationId); 9330 } 9331 return; 9332 } 9333 9334 WifiConfiguration currentConnectedNetwork = mWifiConfigManager 9335 .getWifiConfiguration(mWifiInfo.getNetworkId()); 9336 String currentAssociationId = (currentConnectedNetwork == null) ? "Disconnected" : 9337 (mWifiInfo.getSSID() + " : " + mWifiInfo.getBSSID()); 9338 9339 if (currentConnectedNetwork != null 9340 && (currentConnectedNetwork.networkId == candidate.networkId 9341 || currentConnectedNetwork.isLinked(candidate))) { 9342 if (DBG) { 9343 Log.d(TAG, "tryToConnectToNetwork: Roaming from " + currentAssociationId + " to " 9344 + targetAssociationId); 9345 } 9346 sendMessage(CMD_AUTO_ROAM, candidate.networkId, 0, scanResultCandidate); 9347 } else { 9348 if (DBG) { 9349 Log.d(TAG, "tryToConnectToNetwork: Reconnect from " + currentAssociationId + " to " 9350 + targetAssociationId); 9351 } 9352 9353 sendMessage(CMD_AUTO_CONNECT, candidate.networkId, 0, scanResultCandidate.BSSID); 9354 } 9355 } 9356} 9357