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