WifiStateMachine.java revision bcbc449d47124ec8f73a38ffe228b97bd9b493bf
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 } 2489 List<WifiNative.WifiPnoNetwork> pnoList = 2490 mWifiConfigManager.retrieveDisconnectedWifiPnoNetworkList(enable); 2491 boolean ret = mWifiNative.enableBackgroundScan(enable, pnoList); 2492 if (ret) { 2493 mLegacyPnoEnabled = enable; 2494 } else { 2495 Log.e(TAG, " Fail to set up pno, want " + enable + " now " + mLegacyPnoEnabled); 2496 } 2497 } 2498 2499 /** 2500 * Blacklist a BSSID. This will avoid the AP if there are 2501 * alternate APs to connect 2502 * 2503 * @param bssid BSSID of the network 2504 */ 2505 public void addToBlacklist(String bssid) { 2506 sendMessage(CMD_BLACKLIST_NETWORK, bssid); 2507 } 2508 2509 /** 2510 * Clear the blacklist list 2511 */ 2512 public void clearBlacklist() { 2513 sendMessage(CMD_CLEAR_BLACKLIST); 2514 } 2515 2516 public void enableRssiPolling(boolean enabled) { 2517 sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0); 2518 } 2519 2520 public void enableAllNetworks() { 2521 sendMessage(CMD_ENABLE_ALL_NETWORKS); 2522 } 2523 2524 /** 2525 * Start filtering Multicast v4 packets 2526 */ 2527 public void startFilteringMulticastV4Packets() { 2528 mFilteringMulticastV4Packets.set(true); 2529 sendMessage(CMD_START_PACKET_FILTERING, MULTICAST_V4, 0); 2530 } 2531 2532 /** 2533 * Stop filtering Multicast v4 packets 2534 */ 2535 public void stopFilteringMulticastV4Packets() { 2536 mFilteringMulticastV4Packets.set(false); 2537 sendMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V4, 0); 2538 } 2539 2540 /** 2541 * Start filtering Multicast v4 packets 2542 */ 2543 public void startFilteringMulticastV6Packets() { 2544 sendMessage(CMD_START_PACKET_FILTERING, MULTICAST_V6, 0); 2545 } 2546 2547 /** 2548 * Stop filtering Multicast v4 packets 2549 */ 2550 public void stopFilteringMulticastV6Packets() { 2551 sendMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V6, 0); 2552 } 2553 2554 /** 2555 * Set high performance mode of operation. 2556 * Enabling would set active power mode and disable suspend optimizations; 2557 * disabling would set auto power mode and enable suspend optimizations 2558 * 2559 * @param enable true if enable, false otherwise 2560 */ 2561 public void setHighPerfModeEnabled(boolean enable) { 2562 sendMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0); 2563 } 2564 2565 /** 2566 * Set the country code 2567 * 2568 * @param countryCode following ISO 3166 format 2569 * @param persist {@code true} if the setting should be remembered. 2570 */ 2571 public synchronized void setCountryCode(String countryCode, boolean persist) { 2572 // If it's a good country code, apply after the current 2573 // wifi connection is terminated; ignore resetting of code 2574 // for now (it is unclear what the chipset should do when 2575 // country code is reset) 2576 2577 // if mCountryCodeSequence == 0, it is the first time to set country code, always set 2578 // else only when the new country code is different from the current one to set 2579 2580 if (TextUtils.isEmpty(countryCode)) { 2581 if (DBG) log("Ignoring resetting of country code"); 2582 } else { 2583 int countryCodeSequence = mCountryCodeSequence.get(); 2584 String currentCountryCode = getCurrentCountryCode(); 2585 if (countryCodeSequence == 0 2586 || TextUtils.equals(countryCode, currentCountryCode) == false) { 2587 2588 countryCodeSequence = mCountryCodeSequence.incrementAndGet(); 2589 sendMessage(CMD_SET_COUNTRY_CODE, countryCodeSequence, persist ? 1 : 0, 2590 countryCode); 2591 } 2592 } 2593 } 2594 2595 /** 2596 * reset the country code to default 2597 */ 2598 public synchronized void resetCountryCode() { 2599 if (mRevertCountryCodeOnCellularLoss && TextUtils.isEmpty(mDefaultCountryCode) == false) { 2600 logd("resetting country code to " + mDefaultCountryCode); 2601 setCountryCode(mDefaultCountryCode, /* persist = */ true); 2602 } 2603 } 2604 2605 /** 2606 * reset cached SIM credential data 2607 */ 2608 public synchronized void resetSimAuthNetworks() { 2609 sendMessage(CMD_RESET_SIM_NETWORKS); 2610 } 2611 2612 2613 /** 2614 * Get Network object of current wifi network 2615 * @return Network object of current wifi network 2616 */ 2617 public Network getCurrentNetwork() { 2618 if (mNetworkAgent != null) { 2619 return new Network(mNetworkAgent.netId); 2620 } else { 2621 return null; 2622 } 2623 } 2624 2625 /** 2626 * Get the country code 2627 * 2628 * @return countryCode following ISO 3166 format 2629 */ 2630 public String getCurrentCountryCode() { 2631 return mFacade.getStringSetting(mContext, Settings.Global.WIFI_COUNTRY_CODE); 2632 } 2633 2634 /** 2635 * Set the operational frequency band 2636 * 2637 * @param band 2638 * @param persist {@code true} if the setting should be remembered. 2639 */ 2640 public void setFrequencyBand(int band, boolean persist) { 2641 if (persist) { 2642 Settings.Global.putInt(mContext.getContentResolver(), 2643 Settings.Global.WIFI_FREQUENCY_BAND, 2644 band); 2645 } 2646 sendMessage(CMD_SET_FREQUENCY_BAND, band, 0); 2647 } 2648 2649 /** 2650 * Enable TDLS for a specific MAC address 2651 */ 2652 public void enableTdls(String remoteMacAddress, boolean enable) { 2653 int enabler = enable ? 1 : 0; 2654 sendMessage(CMD_ENABLE_TDLS, enabler, 0, remoteMacAddress); 2655 } 2656 2657 /** 2658 * Returns the operational frequency band 2659 */ 2660 public int getFrequencyBand() { 2661 return mFrequencyBand.get(); 2662 } 2663 2664 /** 2665 * Returns the wifi configuration file 2666 */ 2667 public String getConfigFile() { 2668 return mWifiConfigManager.getConfigFile(); 2669 } 2670 2671 /** 2672 * Send a message indicating bluetooth adapter connection state changed 2673 */ 2674 public void sendBluetoothAdapterStateChange(int state) { 2675 sendMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0); 2676 } 2677 2678 /** 2679 * Send a message indicating a package has been uninstalled. 2680 */ 2681 public void removeAppConfigs(String packageName, int uid) { 2682 // Build partial AppInfo manually - package may not exist in database any more 2683 ApplicationInfo ai = new ApplicationInfo(); 2684 ai.packageName = packageName; 2685 ai.uid = uid; 2686 sendMessage(CMD_REMOVE_APP_CONFIGURATIONS, ai); 2687 } 2688 2689 /** 2690 * Send a message indicating a user has been removed. 2691 */ 2692 public void removeUserConfigs(int userId) { 2693 sendMessage(CMD_REMOVE_USER_CONFIGURATIONS, userId); 2694 } 2695 2696 /** 2697 * Save configuration on supplicant 2698 * 2699 * @return {@code true} if the operation succeeds, {@code false} otherwise 2700 * <p/> 2701 * TODO: deprecate this 2702 */ 2703 public boolean syncSaveConfig(AsyncChannel channel) { 2704 Message resultMsg = channel.sendMessageSynchronously(CMD_SAVE_CONFIG); 2705 boolean result = (resultMsg.arg1 != FAILURE); 2706 resultMsg.recycle(); 2707 return result; 2708 } 2709 2710 public void updateBatteryWorkSource(WorkSource newSource) { 2711 synchronized (mRunningWifiUids) { 2712 try { 2713 if (newSource != null) { 2714 mRunningWifiUids.set(newSource); 2715 } 2716 if (mIsRunning) { 2717 if (mReportedRunning) { 2718 // If the work source has changed since last time, need 2719 // to remove old work from battery stats. 2720 if (mLastRunningWifiUids.diff(mRunningWifiUids)) { 2721 mBatteryStats.noteWifiRunningChanged(mLastRunningWifiUids, 2722 mRunningWifiUids); 2723 mLastRunningWifiUids.set(mRunningWifiUids); 2724 } 2725 } else { 2726 // Now being started, report it. 2727 mBatteryStats.noteWifiRunning(mRunningWifiUids); 2728 mLastRunningWifiUids.set(mRunningWifiUids); 2729 mReportedRunning = true; 2730 } 2731 } else { 2732 if (mReportedRunning) { 2733 // Last reported we were running, time to stop. 2734 mBatteryStats.noteWifiStopped(mLastRunningWifiUids); 2735 mLastRunningWifiUids.clear(); 2736 mReportedRunning = false; 2737 } 2738 } 2739 mWakeLock.setWorkSource(newSource); 2740 } catch (RemoteException ignore) { 2741 } 2742 } 2743 } 2744 2745 @Override 2746 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2747 super.dump(fd, pw, args); 2748 mSupplicantStateTracker.dump(fd, pw, args); 2749 pw.println("mLinkProperties " + mLinkProperties); 2750 pw.println("mWifiInfo " + mWifiInfo); 2751 pw.println("mDhcpResults " + mDhcpResults); 2752 pw.println("mNetworkInfo " + mNetworkInfo); 2753 pw.println("mLastSignalLevel " + mLastSignalLevel); 2754 pw.println("mLastBssid " + mLastBssid); 2755 pw.println("mLastNetworkId " + mLastNetworkId); 2756 pw.println("mOperationalMode " + mOperationalMode); 2757 pw.println("mUserWantsSuspendOpt " + mUserWantsSuspendOpt); 2758 pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 2759 pw.println("Supplicant status " + mWifiNative.status(true)); 2760 pw.println("mLegacyPnoEnabled " + mLegacyPnoEnabled); 2761 pw.println("mDriverSetCountryCode " + mDriverSetCountryCode); 2762 pw.println("mConnectedModeGScanOffloadStarted " + mConnectedModeGScanOffloadStarted); 2763 pw.println("mGScanPeriodMilli " + mGScanPeriodMilli); 2764 if (mWhiteListedSsids != null && mWhiteListedSsids.length > 0) { 2765 pw.println("SSID whitelist :" ); 2766 for (int i=0; i < mWhiteListedSsids.length; i++) { 2767 pw.println(" " + mWhiteListedSsids[i]); 2768 } 2769 } 2770 if (mNetworkFactory != null) { 2771 mNetworkFactory.dump(fd, pw, args); 2772 } else { 2773 pw.println("mNetworkFactory is not initialized"); 2774 } 2775 2776 if (mUntrustedNetworkFactory != null) { 2777 mUntrustedNetworkFactory.dump(fd, pw, args); 2778 } else { 2779 pw.println("mUntrustedNetworkFactory is not initialized"); 2780 } 2781 pw.println(); 2782 updateWifiMetrics(); 2783 mWifiMetrics.dump(fd, pw, args); 2784 pw.println(); 2785 mNetworkFactory.dump(fd, pw, args); 2786 mUntrustedNetworkFactory.dump(fd, pw, args); 2787 pw.println(); 2788 2789 mWifiConfigManager.dump(fd, pw, args); 2790 pw.println(); 2791 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_USER_ACTION); 2792 mWifiLogger.dump(fd, pw, args); 2793 mWifiQualifiedNetworkSelector.dump(fd, pw, args); 2794 } 2795 2796 public void handleUserSwitch(int userId) { 2797 sendMessage(CMD_USER_SWITCH, userId); 2798 } 2799 2800 /** 2801 * ****************************************************** 2802 * Internal private functions 2803 * ****************************************************** 2804 */ 2805 2806 private void logStateAndMessage(Message message, State state) { 2807 messageHandlingStatus = 0; 2808 if (mLogMessages) { 2809 logd(" " + state.getClass().getSimpleName() + " " + getLogRecString(message)); 2810 } 2811 } 2812 2813 /** 2814 * helper, prints the milli time since boot wi and w/o suspended time 2815 */ 2816 String printTime() { 2817 StringBuilder sb = new StringBuilder(); 2818 sb.append(" rt=").append(SystemClock.uptimeMillis()); 2819 sb.append("/").append(SystemClock.elapsedRealtime()); 2820 return sb.toString(); 2821 } 2822 2823 /** 2824 * Return the additional string to be logged by LogRec, default 2825 * 2826 * @param msg that was processed 2827 * @return information to be logged as a String 2828 */ 2829 protected String getLogRecString(Message msg) { 2830 WifiConfiguration config; 2831 Long now; 2832 String report; 2833 String key; 2834 StringBuilder sb = new StringBuilder(); 2835 if (mScreenOn) { 2836 sb.append("!"); 2837 } 2838 if (messageHandlingStatus != MESSAGE_HANDLING_STATUS_UNKNOWN) { 2839 sb.append("(").append(messageHandlingStatus).append(")"); 2840 } 2841 sb.append(smToString(msg)); 2842 if (msg.sendingUid > 0 && msg.sendingUid != Process.WIFI_UID) { 2843 sb.append(" uid=" + msg.sendingUid); 2844 } 2845 sb.append(" ").append(printTime()); 2846 switch (msg.what) { 2847 case CMD_STARTED_GSCAN_DBG: 2848 case CMD_STARTED_PNO_DBG: 2849 sb.append(" "); 2850 sb.append(Integer.toString(msg.arg1)); 2851 sb.append(" "); 2852 sb.append(Integer.toString(msg.arg2)); 2853 if (msg.obj != null) { 2854 sb.append(" " + (String)msg.obj); 2855 } 2856 break; 2857 case CMD_RESTART_AUTOJOIN_OFFLOAD: 2858 sb.append(" "); 2859 sb.append(Integer.toString(msg.arg1)); 2860 sb.append(" "); 2861 sb.append(Integer.toString(msg.arg2)); 2862 sb.append("/").append(Integer.toString(mRestartAutoJoinOffloadCounter)); 2863 if (msg.obj != null) { 2864 sb.append(" " + (String)msg.obj); 2865 } 2866 break; 2867 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 2868 sb.append(" "); 2869 sb.append(Integer.toString(msg.arg1)); 2870 sb.append(" "); 2871 sb.append(Integer.toString(msg.arg2)); 2872 sb.append(" halAllowed=").append(useHalBasedAutoJoinOffload()); 2873 sb.append(" scanAllowed=").append(allowFullBandScanAndAssociated()); 2874 sb.append(" autojoinAllowed="); 2875 sb.append(mWifiConfigManager.enableAutoJoinWhenAssociated.get()); 2876 sb.append(" withTraffic=").append(getAllowScansWithTraffic()); 2877 sb.append(" tx=").append(mWifiInfo.txSuccessRate); 2878 sb.append("/").append(mWifiConfigManager.maxTxPacketForFullScans); 2879 sb.append(" rx=").append(mWifiInfo.rxSuccessRate); 2880 sb.append("/").append(mWifiConfigManager.maxRxPacketForFullScans); 2881 sb.append(" -> ").append(mConnectedModeGScanOffloadStarted); 2882 break; 2883 case CMD_PNO_NETWORK_FOUND: 2884 sb.append(" "); 2885 sb.append(Integer.toString(msg.arg1)); 2886 sb.append(" "); 2887 sb.append(Integer.toString(msg.arg2)); 2888 if (msg.obj != null) { 2889 ScanResult[] results = (ScanResult[])msg.obj; 2890 for (int i = 0; i < results.length; i++) { 2891 sb.append(" ").append(results[i].SSID).append(" "); 2892 sb.append(results[i].frequency); 2893 sb.append(" ").append(results[i].level); 2894 } 2895 } 2896 break; 2897 case CMD_START_SCAN: 2898 now = System.currentTimeMillis(); 2899 sb.append(" "); 2900 sb.append(Integer.toString(msg.arg1)); 2901 sb.append(" "); 2902 sb.append(Integer.toString(msg.arg2)); 2903 sb.append(" ic="); 2904 sb.append(Integer.toString(sScanAlarmIntentCount)); 2905 if (msg.obj != null) { 2906 Bundle bundle = (Bundle) msg.obj; 2907 Long request = bundle.getLong(SCAN_REQUEST_TIME, 0); 2908 if (request != 0) { 2909 sb.append(" proc(ms):").append(now - request); 2910 } 2911 } 2912 if (mIsScanOngoing) sb.append(" onGoing"); 2913 if (mIsFullScanOngoing) sb.append(" full"); 2914 if (lastStartScanTimeStamp != 0) { 2915 sb.append(" started:").append(lastStartScanTimeStamp); 2916 sb.append(",").append(now - lastStartScanTimeStamp); 2917 } 2918 if (lastScanDuration != 0) { 2919 sb.append(" dur:").append(lastScanDuration); 2920 } 2921 sb.append(" cnt=").append(mDelayedScanCounter); 2922 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2923 sb.append(" f=").append(mWifiInfo.getFrequency()); 2924 sb.append(" sc=").append(mWifiInfo.score); 2925 sb.append(" link=").append(mWifiInfo.getLinkSpeed()); 2926 sb.append(String.format(" tx=%.1f,", mWifiInfo.txSuccessRate)); 2927 sb.append(String.format(" %.1f,", mWifiInfo.txRetriesRate)); 2928 sb.append(String.format(" %.1f ", mWifiInfo.txBadRate)); 2929 sb.append(String.format(" rx=%.1f", mWifiInfo.rxSuccessRate)); 2930 if (lastScanFreqs != null) { 2931 sb.append(" list="); 2932 for(int freq : lastScanFreqs) { 2933 sb.append(freq).append(","); 2934 } 2935 } else { 2936 sb.append(" fiv=").append(fullBandConnectedTimeIntervalMilli); 2937 } 2938 report = reportOnTime(); 2939 if (report != null) { 2940 sb.append(" ").append(report); 2941 } 2942 break; 2943 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 2944 sb.append(" "); 2945 sb.append(Integer.toString(msg.arg1)); 2946 sb.append(" "); 2947 sb.append(Integer.toString(msg.arg2)); 2948 StateChangeResult stateChangeResult = (StateChangeResult) msg.obj; 2949 if (stateChangeResult != null) { 2950 sb.append(stateChangeResult.toString()); 2951 } 2952 break; 2953 case WifiManager.SAVE_NETWORK: 2954 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 2955 sb.append(" "); 2956 sb.append(Integer.toString(msg.arg1)); 2957 sb.append(" "); 2958 sb.append(Integer.toString(msg.arg2)); 2959 if (lastSavedConfigurationAttempt != null) { 2960 sb.append(" ").append(lastSavedConfigurationAttempt.configKey()); 2961 sb.append(" nid=").append(lastSavedConfigurationAttempt.networkId); 2962 if (lastSavedConfigurationAttempt.hiddenSSID) { 2963 sb.append(" hidden"); 2964 } 2965 if (lastSavedConfigurationAttempt.preSharedKey != null 2966 && !lastSavedConfigurationAttempt.preSharedKey.equals("*")) { 2967 sb.append(" hasPSK"); 2968 } 2969 if (lastSavedConfigurationAttempt.ephemeral) { 2970 sb.append(" ephemeral"); 2971 } 2972 if (lastSavedConfigurationAttempt.selfAdded) { 2973 sb.append(" selfAdded"); 2974 } 2975 sb.append(" cuid=").append(lastSavedConfigurationAttempt.creatorUid); 2976 sb.append(" suid=").append(lastSavedConfigurationAttempt.lastUpdateUid); 2977 } 2978 break; 2979 case WifiManager.FORGET_NETWORK: 2980 sb.append(" "); 2981 sb.append(Integer.toString(msg.arg1)); 2982 sb.append(" "); 2983 sb.append(Integer.toString(msg.arg2)); 2984 if (lastForgetConfigurationAttempt != null) { 2985 sb.append(" ").append(lastForgetConfigurationAttempt.configKey()); 2986 sb.append(" nid=").append(lastForgetConfigurationAttempt.networkId); 2987 if (lastForgetConfigurationAttempt.hiddenSSID) { 2988 sb.append(" hidden"); 2989 } 2990 if (lastForgetConfigurationAttempt.preSharedKey != null) { 2991 sb.append(" hasPSK"); 2992 } 2993 if (lastForgetConfigurationAttempt.ephemeral) { 2994 sb.append(" ephemeral"); 2995 } 2996 if (lastForgetConfigurationAttempt.selfAdded) { 2997 sb.append(" selfAdded"); 2998 } 2999 sb.append(" cuid=").append(lastForgetConfigurationAttempt.creatorUid); 3000 sb.append(" suid=").append(lastForgetConfigurationAttempt.lastUpdateUid); 3001 WifiConfiguration.NetworkSelectionStatus netWorkSelectionStatus = 3002 lastForgetConfigurationAttempt.getNetworkSelectionStatus(); 3003 sb.append(" ajst=").append( 3004 netWorkSelectionStatus.getNetworkStatusString()); 3005 } 3006 break; 3007 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 3008 sb.append(" "); 3009 sb.append(Integer.toString(msg.arg1)); 3010 sb.append(" "); 3011 sb.append(Integer.toString(msg.arg2)); 3012 String bssid = (String) msg.obj; 3013 if (bssid != null && bssid.length() > 0) { 3014 sb.append(" "); 3015 sb.append(bssid); 3016 } 3017 sb.append(" blacklist=" + Boolean.toString(didBlackListBSSID)); 3018 break; 3019 case WifiMonitor.SCAN_RESULTS_EVENT: 3020 sb.append(" "); 3021 sb.append(Integer.toString(msg.arg1)); 3022 sb.append(" "); 3023 sb.append(Integer.toString(msg.arg2)); 3024 if (mScanResults != null) { 3025 sb.append(" found="); 3026 sb.append(mScanResults.size()); 3027 } 3028 sb.append(" known=").append(mNumScanResultsKnown); 3029 sb.append(" got=").append(mNumScanResultsReturned); 3030 if (lastScanDuration != 0) { 3031 sb.append(" dur:").append(lastScanDuration); 3032 } 3033 if (mOnTime != 0) { 3034 sb.append(" on:").append(mOnTimeThisScan).append(",").append(mOnTimeScan); 3035 sb.append(",").append(mOnTime); 3036 } 3037 if (mTxTime != 0) { 3038 sb.append(" tx:").append(mTxTimeThisScan).append(",").append(mTxTimeScan); 3039 sb.append(",").append(mTxTime); 3040 } 3041 if (mRxTime != 0) { 3042 sb.append(" rx:").append(mRxTimeThisScan).append(",").append(mRxTimeScan); 3043 sb.append(",").append(mRxTime); 3044 } 3045 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 3046 sb.append(String.format(" con=%d", mConnectionRequests)); 3047 key = mWifiConfigManager.getLastSelectedConfiguration(); 3048 if (key != null) { 3049 sb.append(" last=").append(key); 3050 } 3051 break; 3052 case WifiMonitor.SCAN_FAILED_EVENT: 3053 break; 3054 case WifiMonitor.NETWORK_CONNECTION_EVENT: 3055 sb.append(" "); 3056 sb.append(Integer.toString(msg.arg1)); 3057 sb.append(" "); 3058 sb.append(Integer.toString(msg.arg2)); 3059 sb.append(" ").append(mLastBssid); 3060 sb.append(" nid=").append(mLastNetworkId); 3061 config = getCurrentWifiConfiguration(); 3062 if (config != null) { 3063 sb.append(" ").append(config.configKey()); 3064 } 3065 key = mWifiConfigManager.getLastSelectedConfiguration(); 3066 if (key != null) { 3067 sb.append(" last=").append(key); 3068 } 3069 break; 3070 case CMD_TARGET_BSSID: 3071 case CMD_ASSOCIATED_BSSID: 3072 sb.append(" "); 3073 sb.append(Integer.toString(msg.arg1)); 3074 sb.append(" "); 3075 sb.append(Integer.toString(msg.arg2)); 3076 if (msg.obj != null) { 3077 sb.append(" BSSID=").append((String) msg.obj); 3078 } 3079 if (mTargetRoamBSSID != null) { 3080 sb.append(" Target=").append(mTargetRoamBSSID); 3081 } 3082 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 3083 break; 3084 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 3085 if (msg.obj != null) { 3086 sb.append(" ").append((String) msg.obj); 3087 } 3088 sb.append(" nid=").append(msg.arg1); 3089 sb.append(" reason=").append(msg.arg2); 3090 if (mLastBssid != null) { 3091 sb.append(" lastbssid=").append(mLastBssid); 3092 } 3093 if (mWifiInfo.getFrequency() != -1) { 3094 sb.append(" freq=").append(mWifiInfo.getFrequency()); 3095 sb.append(" rssi=").append(mWifiInfo.getRssi()); 3096 } 3097 if (linkDebouncing) { 3098 sb.append(" debounce"); 3099 } 3100 break; 3101 case WifiMonitor.SSID_TEMP_DISABLED: 3102 case WifiMonitor.SSID_REENABLED: 3103 sb.append(" nid=").append(msg.arg1); 3104 if (msg.obj != null) { 3105 sb.append(" ").append((String) msg.obj); 3106 } 3107 config = getCurrentWifiConfiguration(); 3108 if (config != null) { 3109 WifiConfiguration.NetworkSelectionStatus netWorkSelectionStatus = 3110 config.getNetworkSelectionStatus(); 3111 sb.append(" cur=").append(config.configKey()); 3112 sb.append(" ajst=").append(netWorkSelectionStatus.getNetworkStatusString()); 3113 if (config.selfAdded) { 3114 sb.append(" selfAdded"); 3115 } 3116 if (config.status != 0) { 3117 sb.append(" st=").append(config.status); 3118 sb.append(" rs=").append( 3119 netWorkSelectionStatus.getNetworkDisableReasonString()); 3120 } 3121 if (config.lastConnected != 0) { 3122 now = System.currentTimeMillis(); 3123 sb.append(" lastconn=").append(now - config.lastConnected).append("(ms)"); 3124 } 3125 if (mLastBssid != null) { 3126 sb.append(" lastbssid=").append(mLastBssid); 3127 } 3128 if (mWifiInfo.getFrequency() != -1) { 3129 sb.append(" freq=").append(mWifiInfo.getFrequency()); 3130 sb.append(" rssi=").append(mWifiInfo.getRssi()); 3131 sb.append(" bssid=").append(mWifiInfo.getBSSID()); 3132 } 3133 } 3134 break; 3135 case CMD_RSSI_POLL: 3136 case CMD_UNWANTED_NETWORK: 3137 case WifiManager.RSSI_PKTCNT_FETCH: 3138 sb.append(" "); 3139 sb.append(Integer.toString(msg.arg1)); 3140 sb.append(" "); 3141 sb.append(Integer.toString(msg.arg2)); 3142 if (mWifiInfo.getSSID() != null) 3143 if (mWifiInfo.getSSID() != null) 3144 sb.append(" ").append(mWifiInfo.getSSID()); 3145 if (mWifiInfo.getBSSID() != null) 3146 sb.append(" ").append(mWifiInfo.getBSSID()); 3147 sb.append(" rssi=").append(mWifiInfo.getRssi()); 3148 sb.append(" f=").append(mWifiInfo.getFrequency()); 3149 sb.append(" sc=").append(mWifiInfo.score); 3150 sb.append(" link=").append(mWifiInfo.getLinkSpeed()); 3151 sb.append(String.format(" tx=%.1f,", mWifiInfo.txSuccessRate)); 3152 sb.append(String.format(" %.1f,", mWifiInfo.txRetriesRate)); 3153 sb.append(String.format(" %.1f ", mWifiInfo.txBadRate)); 3154 sb.append(String.format(" rx=%.1f", mWifiInfo.rxSuccessRate)); 3155 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 3156 report = reportOnTime(); 3157 if (report != null) { 3158 sb.append(" ").append(report); 3159 } 3160 if (wifiScoringReport != null) { 3161 sb.append(wifiScoringReport); 3162 } 3163 if (mConnectedModeGScanOffloadStarted) { 3164 sb.append(" offload-started periodMilli " + mGScanPeriodMilli); 3165 } else { 3166 sb.append(" offload-stopped"); 3167 } 3168 break; 3169 case CMD_AUTO_CONNECT: 3170 case WifiManager.CONNECT_NETWORK: 3171 sb.append(" "); 3172 sb.append(Integer.toString(msg.arg1)); 3173 sb.append(" "); 3174 sb.append(Integer.toString(msg.arg2)); 3175 config = mWifiConfigManager.getWifiConfiguration(msg.arg1); 3176 if (config != null) { 3177 sb.append(" ").append(config.configKey()); 3178 if (config.visibility != null) { 3179 sb.append(" ").append(config.visibility.toString()); 3180 } 3181 } 3182 if (mTargetRoamBSSID != null) { 3183 sb.append(" ").append(mTargetRoamBSSID); 3184 } 3185 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 3186 config = getCurrentWifiConfiguration(); 3187 if (config != null) { 3188 sb.append(config.configKey()); 3189 if (config.visibility != null) { 3190 sb.append(" ").append(config.visibility.toString()); 3191 } 3192 } 3193 break; 3194 case CMD_AUTO_ROAM: 3195 sb.append(" "); 3196 sb.append(Integer.toString(msg.arg1)); 3197 sb.append(" "); 3198 sb.append(Integer.toString(msg.arg2)); 3199 ScanResult result = (ScanResult) msg.obj; 3200 if (result != null) { 3201 now = System.currentTimeMillis(); 3202 sb.append(" bssid=").append(result.BSSID); 3203 sb.append(" rssi=").append(result.level); 3204 sb.append(" freq=").append(result.frequency); 3205 if (result.seen > 0 && result.seen < now) { 3206 sb.append(" seen=").append(now - result.seen); 3207 } else { 3208 // Somehow the timestamp for this scan result is inconsistent 3209 sb.append(" !seen=").append(result.seen); 3210 } 3211 } 3212 if (mTargetRoamBSSID != null) { 3213 sb.append(" ").append(mTargetRoamBSSID); 3214 } 3215 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 3216 sb.append(" fail count=").append(Integer.toString(mRoamFailCount)); 3217 break; 3218 case CMD_ADD_OR_UPDATE_NETWORK: 3219 sb.append(" "); 3220 sb.append(Integer.toString(msg.arg1)); 3221 sb.append(" "); 3222 sb.append(Integer.toString(msg.arg2)); 3223 if (msg.obj != null) { 3224 config = (WifiConfiguration) msg.obj; 3225 sb.append(" ").append(config.configKey()); 3226 sb.append(" prio=").append(config.priority); 3227 sb.append(" status=").append(config.status); 3228 if (config.BSSID != null) { 3229 sb.append(" ").append(config.BSSID); 3230 } 3231 WifiConfiguration curConfig = getCurrentWifiConfiguration(); 3232 if (curConfig != null) { 3233 if (curConfig.configKey().equals(config.configKey())) { 3234 sb.append(" is current"); 3235 } else { 3236 sb.append(" current=").append(curConfig.configKey()); 3237 sb.append(" prio=").append(curConfig.priority); 3238 sb.append(" status=").append(curConfig.status); 3239 } 3240 } 3241 } 3242 break; 3243 case WifiManager.DISABLE_NETWORK: 3244 case CMD_ENABLE_NETWORK: 3245 sb.append(" "); 3246 sb.append(Integer.toString(msg.arg1)); 3247 sb.append(" "); 3248 sb.append(Integer.toString(msg.arg2)); 3249 key = mWifiConfigManager.getLastSelectedConfiguration(); 3250 if (key != null) { 3251 sb.append(" last=").append(key); 3252 } 3253 config = mWifiConfigManager.getWifiConfiguration(msg.arg1); 3254 if (config != null && (key == null || !config.configKey().equals(key))) { 3255 sb.append(" target=").append(key); 3256 } 3257 break; 3258 case CMD_GET_CONFIGURED_NETWORKS: 3259 sb.append(" "); 3260 sb.append(Integer.toString(msg.arg1)); 3261 sb.append(" "); 3262 sb.append(Integer.toString(msg.arg2)); 3263 sb.append(" num=").append(mWifiConfigManager.getConfiguredNetworksSize()); 3264 break; 3265 case DhcpClient.CMD_PRE_DHCP_ACTION: 3266 sb.append(" "); 3267 sb.append(Integer.toString(msg.arg1)); 3268 sb.append(" "); 3269 sb.append(Integer.toString(msg.arg2)); 3270 sb.append(" txpkts=").append(mWifiInfo.txSuccess); 3271 sb.append(",").append(mWifiInfo.txBad); 3272 sb.append(",").append(mWifiInfo.txRetries); 3273 break; 3274 case DhcpClient.CMD_POST_DHCP_ACTION: 3275 sb.append(" "); 3276 sb.append(Integer.toString(msg.arg1)); 3277 sb.append(" "); 3278 sb.append(Integer.toString(msg.arg2)); 3279 if (msg.arg1 == DhcpClient.DHCP_SUCCESS) { 3280 sb.append(" OK "); 3281 } else if (msg.arg1 == DhcpClient.DHCP_FAILURE) { 3282 sb.append(" FAIL "); 3283 } 3284 if (mLinkProperties != null) { 3285 sb.append(" "); 3286 sb.append(getLinkPropertiesSummary(mLinkProperties)); 3287 } 3288 break; 3289 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 3290 sb.append(" "); 3291 sb.append(Integer.toString(msg.arg1)); 3292 sb.append(" "); 3293 sb.append(Integer.toString(msg.arg2)); 3294 if (msg.obj != null) { 3295 NetworkInfo info = (NetworkInfo) msg.obj; 3296 NetworkInfo.State state = info.getState(); 3297 NetworkInfo.DetailedState detailedState = info.getDetailedState(); 3298 if (state != null) { 3299 sb.append(" st=").append(state); 3300 } 3301 if (detailedState != null) { 3302 sb.append("/").append(detailedState); 3303 } 3304 } 3305 break; 3306 case CMD_IP_CONFIGURATION_LOST: 3307 int count = -1; 3308 WifiConfiguration c = getCurrentWifiConfiguration(); 3309 if (c != null) { 3310 count = c.getNetworkSelectionStatus().getDisableReasonCounter( 3311 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3312 } 3313 sb.append(" "); 3314 sb.append(Integer.toString(msg.arg1)); 3315 sb.append(" "); 3316 sb.append(Integer.toString(msg.arg2)); 3317 sb.append(" failures: "); 3318 sb.append(Integer.toString(count)); 3319 sb.append("/"); 3320 sb.append(Integer.toString(mWifiConfigManager.getMaxDhcpRetries())); 3321 if (mWifiInfo.getBSSID() != null) { 3322 sb.append(" ").append(mWifiInfo.getBSSID()); 3323 } 3324 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 3325 break; 3326 case CMD_UPDATE_LINKPROPERTIES: 3327 sb.append(" "); 3328 sb.append(Integer.toString(msg.arg1)); 3329 sb.append(" "); 3330 sb.append(Integer.toString(msg.arg2)); 3331 if (mLinkProperties != null) { 3332 sb.append(" "); 3333 sb.append(getLinkPropertiesSummary(mLinkProperties)); 3334 } 3335 break; 3336 case CMD_IP_REACHABILITY_LOST: 3337 if (msg.obj != null) { 3338 sb.append(" ").append((String) msg.obj); 3339 } 3340 break; 3341 case CMD_SET_COUNTRY_CODE: 3342 sb.append(" "); 3343 sb.append(Integer.toString(msg.arg1)); 3344 sb.append(" "); 3345 sb.append(Integer.toString(msg.arg2)); 3346 if (msg.obj != null) { 3347 sb.append(" ").append((String) msg.obj); 3348 } 3349 break; 3350 case CMD_ROAM_WATCHDOG_TIMER: 3351 sb.append(" "); 3352 sb.append(Integer.toString(msg.arg1)); 3353 sb.append(" "); 3354 sb.append(Integer.toString(msg.arg2)); 3355 sb.append(" cur=").append(roamWatchdogCount); 3356 break; 3357 case CMD_DISCONNECTING_WATCHDOG_TIMER: 3358 sb.append(" "); 3359 sb.append(Integer.toString(msg.arg1)); 3360 sb.append(" "); 3361 sb.append(Integer.toString(msg.arg2)); 3362 sb.append(" cur=").append(disconnectingWatchdogCount); 3363 break; 3364 case CMD_START_RSSI_MONITORING_OFFLOAD: 3365 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 3366 case CMD_RSSI_THRESHOLD_BREACH: 3367 sb.append(" rssi="); 3368 sb.append(Integer.toString(msg.arg1)); 3369 sb.append(" thresholds="); 3370 sb.append(Arrays.toString(mRssiRanges)); 3371 break; 3372 case CMD_USER_SWITCH: 3373 sb.append(" userId="); 3374 sb.append(Integer.toString(msg.arg1)); 3375 break; 3376 case CMD_IPV4_PROVISIONING_SUCCESS: 3377 sb.append(" "); 3378 if (msg.arg1 == DhcpClient.DHCP_SUCCESS) { 3379 sb.append("DHCP_OK"); 3380 } else if (msg.arg1 == CMD_STATIC_IP_SUCCESS) { 3381 sb.append("STATIC_OK"); 3382 } else { 3383 sb.append(Integer.toString(msg.arg1)); 3384 } 3385 break; 3386 case CMD_IPV4_PROVISIONING_FAILURE: 3387 sb.append(" "); 3388 if (msg.arg1 == DhcpClient.DHCP_FAILURE) { 3389 sb.append("DHCP_FAIL"); 3390 } else if (msg.arg1 == CMD_STATIC_IP_FAILURE) { 3391 sb.append("STATIC_FAIL"); 3392 } else { 3393 sb.append(Integer.toString(msg.arg1)); 3394 } 3395 break; 3396 default: 3397 sb.append(" "); 3398 sb.append(Integer.toString(msg.arg1)); 3399 sb.append(" "); 3400 sb.append(Integer.toString(msg.arg2)); 3401 break; 3402 } 3403 3404 return sb.toString(); 3405 } 3406 3407 private void stopPnoOffload() { 3408 3409 // clear the PNO list 3410 if (!mWifiNative.setPnoList(null, WifiStateMachine.this)) { 3411 Log.e(TAG, "Failed to stop pno"); 3412 } 3413 3414 } 3415 3416 3417 private boolean configureSsidWhiteList() { 3418 3419 mWhiteListedSsids = mWifiConfigManager.getWhiteListedSsids(getCurrentWifiConfiguration()); 3420 if (mWhiteListedSsids == null || mWhiteListedSsids.length == 0) { 3421 return true; 3422 } 3423 3424 if (!mWifiNative.setSsidWhitelist(mWhiteListedSsids)) { 3425 loge("configureSsidWhiteList couldnt program SSID list, size " 3426 + mWhiteListedSsids.length); 3427 return false; 3428 } 3429 3430 logd("configureSsidWhiteList success"); 3431 return true; 3432 } 3433 3434 // In associated more, lazy roam will be looking for 5GHz roam candidate 3435 //Fixme: This is for network selection offload , whole function need to be re-written according 3436 // to the new design 3437 private boolean configureLazyRoam() { 3438 /*boolean status; 3439 if (!useHalBasedAutoJoinOffload()) return false; 3440 3441 WifiNative.WifiLazyRoamParams params = new WifiNative.WifiLazyRoamParams(); 3442 //params.A_band_boost_threshold = mWifiConfigManager.bandPreferenceBoostThreshold5.get(); 3443 //params.A_band_penalty_threshold = 3444 mWifiConfigManager.bandPreferencePenaltyThreshold5.get(); 3445 params.A_band_boost_factor = mWifiConfigManager.bandPreferenceBoostFactor5; 3446 params.A_band_penalty_factor = mWifiConfigManager.bandPreferencePenaltyFactor5; 3447 params.A_band_max_boost = 65; 3448 params.lazy_roam_hysteresis = 25; 3449 params.alert_roam_rssi_trigger = -75; 3450 3451 if (DBG) { 3452 Log.e(TAG, "configureLazyRoam " + params.toString()); 3453 } 3454 3455 if (!mWifiNative.setLazyRoam(true, params)) { 3456 3457 Log.e(TAG, "configureLazyRoam couldnt program params"); 3458 3459 return false; 3460 } 3461 if (DBG) { 3462 Log.e(TAG, "configureLazyRoam success"); 3463 }*/ 3464 return true; 3465 } 3466 3467 // In associated more, lazy roam will be looking for 5GHz roam candidate 3468 private boolean stopLazyRoam() { 3469 boolean status; 3470 if (!useHalBasedAutoJoinOffload()) return false; 3471 if (DBG) { 3472 Log.e(TAG, "stopLazyRoam"); 3473 } 3474 return mWifiNative.setLazyRoam(false, null); 3475 } 3476 3477 private boolean startGScanConnectedModeOffload(String reason) { 3478 if (DBG) { 3479 if (reason == null) { 3480 reason = ""; 3481 } 3482 logd("startGScanConnectedModeOffload " + reason); 3483 } 3484 stopGScan("startGScanConnectedModeOffload " + reason); 3485 if (!mScreenOn) return false; 3486 3487 if (USE_PAUSE_SCANS) { 3488 mWifiNative.pauseScan(); 3489 } 3490 mPnoEnabled = configurePno(); 3491 if (mPnoEnabled == false) { 3492 if (USE_PAUSE_SCANS) { 3493 mWifiNative.restartScan(); 3494 } 3495 return false; 3496 } 3497 mLazyRoamEnabled = configureLazyRoam(); 3498 if (mLazyRoamEnabled == false) { 3499 if (USE_PAUSE_SCANS) { 3500 mWifiNative.restartScan(); 3501 } 3502 return false; 3503 } 3504 if (mWifiConfigManager.getLastSelectedConfiguration() == null) { 3505 configureSsidWhiteList(); 3506 } 3507 if (!startConnectedGScan(reason)) { 3508 if (USE_PAUSE_SCANS) { 3509 mWifiNative.restartScan(); 3510 } 3511 return false; 3512 } 3513 if (USE_PAUSE_SCANS) { 3514 mWifiNative.restartScan(); 3515 } 3516 mConnectedModeGScanOffloadStarted = true; 3517 if (DBG) { 3518 logd("startGScanConnectedModeOffload success"); 3519 } 3520 return true; 3521 } 3522 3523 private boolean startGScanDisconnectedModeOffload(String reason) { 3524 if (DBG) { 3525 logd("startGScanDisconnectedModeOffload " + reason); 3526 } 3527 stopGScan("startGScanDisconnectedModeOffload " + reason); 3528 if (USE_PAUSE_SCANS) { 3529 mWifiNative.pauseScan(); 3530 } 3531 mPnoEnabled = configurePno(); 3532 if (mPnoEnabled == false) { 3533 if (USE_PAUSE_SCANS) { 3534 mWifiNative.restartScan(); 3535 } 3536 return false; 3537 } 3538 if (!startDisconnectedGScan(reason)) { 3539 if (USE_PAUSE_SCANS) { 3540 mWifiNative.restartScan(); 3541 } 3542 return false; 3543 } 3544 if (USE_PAUSE_SCANS) { 3545 mWifiNative.restartScan(); 3546 } 3547 return true; 3548 } 3549 3550 private boolean configurePno() { 3551 if (!useHalBasedAutoJoinOffload()) return false; 3552 3553 if (mWifiScanner == null) { 3554 log("configurePno: mWifiScanner is null "); 3555 return true; 3556 } 3557 3558 List<WifiNative.WifiPnoNetwork> llist = null; 3559 //TODO: add getPnoList in WifiQualifiedNetworkSelector 3560 //mWifiAutoJoinController.getPnoList(getCurrentWifiConfiguration()); 3561 if (llist == null || llist.size() == 0) { 3562 stopPnoOffload(); 3563 log("configurePno: empty PNO list "); 3564 return true; 3565 } 3566 if (DBG) { 3567 log("configurePno: got llist size " + llist.size()); 3568 } 3569 3570 // first program the network we want to look for thru the pno API 3571 WifiNative.WifiPnoNetwork list[] 3572 = (WifiNative.WifiPnoNetwork[]) llist.toArray(new WifiNative.WifiPnoNetwork[0]); 3573 3574 if (!mWifiNative.setPnoList(list, WifiStateMachine.this)) { 3575 Log.e(TAG, "Failed to set pno, length = " + list.length); 3576 return false; 3577 } 3578 3579 if (true) { 3580 StringBuilder sb = new StringBuilder(); 3581 for (WifiNative.WifiPnoNetwork network : list) { 3582 sb.append("[").append(network.SSID).append(" auth=").append(network.auth); 3583 sb.append(" flags="); 3584 sb.append(network.flags).append(" rssi").append(network.rssi_threshold); 3585 sb.append("] "); 3586 3587 } 3588 sendMessage(CMD_STARTED_PNO_DBG, 1, (int)mGScanPeriodMilli, sb.toString()); 3589 } 3590 return true; 3591 } 3592 3593 final static int DISCONNECTED_SHORT_SCANS_DURATION_MILLI = 2 * 60 * 1000; 3594 final static int CONNECTED_SHORT_SCANS_DURATION_MILLI = 2 * 60 * 1000; 3595 3596 private boolean startConnectedGScan(String reason) { 3597 // send a scan background request so as to kick firmware 3598 // 5GHz roaming and autojoin 3599 // We do this only if screen is on 3600 WifiScanner.ScanSettings settings; 3601 3602 if (mPnoEnabled || mLazyRoamEnabled) { 3603 settings = new WifiScanner.ScanSettings(); 3604 settings.band = WifiScanner.WIFI_BAND_BOTH; 3605 long now = System.currentTimeMillis(); 3606 3607 if (!mScreenOn || (mGScanStartTimeMilli!= 0 && now > mGScanStartTimeMilli 3608 && ((now - mGScanStartTimeMilli) > CONNECTED_SHORT_SCANS_DURATION_MILLI))) { 3609 settings.periodInMs = mWifiConfigManager.wifiAssociatedLongScanIntervalMilli.get(); 3610 } else { 3611 mGScanStartTimeMilli = now; 3612 settings.periodInMs = mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get(); 3613 // if we start offload with short interval, then reconfigure it after a given 3614 // duration of time so as to reduce the scan frequency 3615 int delay = 30 * 1000 + CONNECTED_SHORT_SCANS_DURATION_MILLI; 3616 sendMessageDelayed(CMD_RESTART_AUTOJOIN_OFFLOAD, delay, 3617 mRestartAutoJoinOffloadCounter, " startConnectedGScan " + reason, 3618 (long)delay); 3619 mRestartAutoJoinOffloadCounter++; 3620 } 3621 mGScanPeriodMilli = settings.periodInMs; 3622 settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL; 3623 if (DBG) { 3624 log("startConnectedScan: settings band="+ settings.band 3625 + " period=" + settings.periodInMs); 3626 } 3627 3628 mWifiScanner.startBackgroundScan(settings, mWifiScanListener); 3629 if (true) { 3630 sendMessage(CMD_STARTED_GSCAN_DBG, 1, (int)mGScanPeriodMilli, reason); 3631 } 3632 } 3633 return true; 3634 } 3635 3636 private boolean startDisconnectedGScan(String reason) { 3637 // send a scan background request so as to kick firmware 3638 // PNO 3639 // This is done in both screen On and screen Off modes 3640 WifiScanner.ScanSettings settings; 3641 3642 if (mWifiScanner == null) { 3643 log("startDisconnectedGScan: no wifi scanner"); 3644 return false; 3645 } 3646 3647 if (mPnoEnabled || mLazyRoamEnabled) { 3648 settings = new WifiScanner.ScanSettings(); 3649 settings.band = WifiScanner.WIFI_BAND_BOTH; 3650 long now = System.currentTimeMillis(); 3651 3652 3653 if (!mScreenOn || (mGScanStartTimeMilli != 0 && now > mGScanStartTimeMilli 3654 && ((now - mGScanStartTimeMilli) > DISCONNECTED_SHORT_SCANS_DURATION_MILLI))) { 3655 settings.periodInMs = 3656 mWifiConfigManager.wifiDisconnectedLongScanIntervalMilli.get(); 3657 } else { 3658 settings.periodInMs = 3659 mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get(); 3660 mGScanStartTimeMilli = now; 3661 // if we start offload with short interval, then reconfigure it after a given 3662 // duration of time so as to reduce the scan frequency 3663 int delay = 30 * 1000 + DISCONNECTED_SHORT_SCANS_DURATION_MILLI; 3664 sendMessageDelayed(CMD_RESTART_AUTOJOIN_OFFLOAD, delay, 3665 mRestartAutoJoinOffloadCounter, " startDisconnectedGScan " + reason, 3666 (long)delay); 3667 mRestartAutoJoinOffloadCounter++; 3668 } 3669 mGScanPeriodMilli = settings.periodInMs; 3670 settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL; 3671 if (DBG) { 3672 log("startDisconnectedScan: settings band="+ settings.band 3673 + " period=" + settings.periodInMs); 3674 } 3675 mWifiScanner.startBackgroundScan(settings, mWifiScanListener); 3676 if (true) { 3677 sendMessage(CMD_STARTED_GSCAN_DBG, 1, (int)mGScanPeriodMilli, reason); 3678 } 3679 } 3680 return true; 3681 } 3682 3683 private boolean stopGScan(String reason) { 3684 mGScanStartTimeMilli = 0; 3685 mGScanPeriodMilli = 0; 3686 if (mWifiScanner != null) { 3687 mWifiScanner.stopBackgroundScan(mWifiScanListener); 3688 } 3689 mConnectedModeGScanOffloadStarted = false; 3690 if (true) { 3691 sendMessage(CMD_STARTED_GSCAN_DBG, 0, 0, reason); 3692 } 3693 return true; 3694 } 3695 3696 private void handleScreenStateChanged(boolean screenOn) { 3697 mScreenOn = screenOn; 3698 if (PDBG) { 3699 logd(" handleScreenStateChanged Enter: screenOn=" + screenOn 3700 + " mUserWantsSuspendOpt=" + mUserWantsSuspendOpt 3701 + " state " + getCurrentState().getName() 3702 + " suppState:" + mSupplicantStateTracker.getSupplicantStateName()); 3703 } 3704 enableRssiPolling(screenOn); 3705 if (mUserWantsSuspendOpt.get()) { 3706 if (screenOn) { 3707 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, 0); 3708 } else { 3709 // Allow 2s for suspend optimizations to be set 3710 mSuspendWakeLock.acquire(2000); 3711 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, 0); 3712 } 3713 } 3714 mScreenBroadcastReceived.set(true); 3715 3716 getWifiLinkLayerStats(false); 3717 mOnTimeScreenStateChange = mOnTime; 3718 lastScreenStateChangeTimeStamp = lastLinkLayerStatsUpdate; 3719 3720 cancelDelayedScan(); 3721 3722 if (screenOn) { 3723 enableBackgroundScan(false); 3724 setScanAlarm(false); 3725 clearBlacklist(); 3726 3727 fullBandConnectedTimeIntervalMilli 3728 = mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get(); 3729 // In either Disconnectedstate or ConnectedState, 3730 // start the scan alarm so as to enable autojoin 3731 if (getCurrentState() == mConnectedState 3732 && allowFullBandScanAndAssociated()) { 3733 if (useHalBasedAutoJoinOffload()) { 3734 startGScanConnectedModeOffload("screenOnConnected"); 3735 } else { 3736 // Scan after 500ms 3737 startDelayedScan(500, null, null); 3738 } 3739 } else if (getCurrentState() == mDisconnectedState) { 3740 if (useHalBasedAutoJoinOffload()) { 3741 startGScanDisconnectedModeOffload("screenOnDisconnected"); 3742 } else { 3743 // Scan after 500ms 3744 startDelayedScan(500, null, null); 3745 } 3746 } 3747 } else { 3748 if (getCurrentState() == mDisconnectedState) { 3749 // Screen Off and Disconnected and chipset doesn't support scan offload 3750 // => start scan alarm 3751 // Screen Off and Disconnected and chipset does support scan offload 3752 // => will use scan offload (i.e. background scan) 3753 if (useHalBasedAutoJoinOffload()) { 3754 startGScanDisconnectedModeOffload("screenOffDisconnected"); 3755 } else { 3756 if (!mBackgroundScanSupported) { 3757 setScanAlarm(true); 3758 } else { 3759 if (!mIsScanOngoing) { 3760 enableBackgroundScan(true); 3761 } 3762 } 3763 } 3764 } else { 3765 enableBackgroundScan(false); 3766 if (useHalBasedAutoJoinOffload()) { 3767 // don't try stop Gscan if it is not enabled 3768 stopGScan("ScreenOffStop(enableBackground=" + mLegacyPnoEnabled + ") "); 3769 } 3770 } 3771 } 3772 if (DBG) logd("backgroundScan enabled=" + mLegacyPnoEnabled); 3773 3774 if (DBG) log("handleScreenStateChanged Exit: " + screenOn); 3775 } 3776 3777 private void checkAndSetConnectivityInstance() { 3778 if (mCm == null) { 3779 mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 3780 } 3781 } 3782 3783 /** 3784 * Set the country code from the system setting value, if any. 3785 */ 3786 private void initializeCountryCode() { 3787 String countryCode = getCurrentCountryCode(); 3788 if (countryCode != null && !countryCode.isEmpty()) { 3789 setCountryCode(countryCode, false); 3790 } else { 3791 //use driver default 3792 } 3793 } 3794 3795 /** 3796 * Set the frequency band from the system setting value, if any. 3797 */ 3798 private void setFrequencyBand() { 3799 int band = mFacade.getIntegerSetting(mContext, 3800 Settings.Global.WIFI_FREQUENCY_BAND, WifiManager.WIFI_FREQUENCY_BAND_AUTO); 3801 3802 if (mWifiNative.setBand(band)) { 3803 mFrequencyBand.set(band); 3804 if (PDBG) { 3805 logd("done set frequency band " + band); 3806 mWifiQualifiedNetworkSelector.setUserPreferredBand(band); 3807 } 3808 } else { 3809 loge("Failed to set frequency band " + band); 3810 } 3811 } 3812 3813 private void setSuspendOptimizationsNative(int reason, boolean enabled) { 3814 if (DBG) { 3815 log("setSuspendOptimizationsNative: " + reason + " " + enabled 3816 + " -want " + mUserWantsSuspendOpt.get() 3817 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 3818 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 3819 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 3820 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 3821 } 3822 //mWifiNative.setSuspendOptimizations(enabled); 3823 3824 if (enabled) { 3825 mSuspendOptNeedsDisabled &= ~reason; 3826 /* None of dhcp, screen or highperf need it disabled and user wants it enabled */ 3827 if (mSuspendOptNeedsDisabled == 0 && mUserWantsSuspendOpt.get()) { 3828 if (DBG) { 3829 log("setSuspendOptimizationsNative do it " + reason + " " + enabled 3830 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 3831 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 3832 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 3833 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 3834 } 3835 mWifiNative.setSuspendOptimizations(true); 3836 } 3837 } else { 3838 mSuspendOptNeedsDisabled |= reason; 3839 mWifiNative.setSuspendOptimizations(false); 3840 } 3841 } 3842 3843 private void setSuspendOptimizations(int reason, boolean enabled) { 3844 if (DBG) log("setSuspendOptimizations: " + reason + " " + enabled); 3845 if (enabled) { 3846 mSuspendOptNeedsDisabled &= ~reason; 3847 } else { 3848 mSuspendOptNeedsDisabled |= reason; 3849 } 3850 if (DBG) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 3851 } 3852 3853 private void setWifiState(int wifiState) { 3854 final int previousWifiState = mWifiState.get(); 3855 3856 try { 3857 if (wifiState == WIFI_STATE_ENABLED) { 3858 mBatteryStats.noteWifiOn(); 3859 } else if (wifiState == WIFI_STATE_DISABLED) { 3860 mBatteryStats.noteWifiOff(); 3861 } 3862 } catch (RemoteException e) { 3863 loge("Failed to note battery stats in wifi"); 3864 } 3865 3866 mWifiState.set(wifiState); 3867 3868 if (DBG) log("setWifiState: " + syncGetWifiStateByName()); 3869 3870 final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); 3871 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3872 intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState); 3873 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState); 3874 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3875 } 3876 3877 private void setWifiApState(int wifiApState, int reason) { 3878 final int previousWifiApState = mWifiApState.get(); 3879 3880 try { 3881 if (wifiApState == WIFI_AP_STATE_ENABLED) { 3882 mBatteryStats.noteWifiOn(); 3883 } else if (wifiApState == WIFI_AP_STATE_DISABLED) { 3884 mBatteryStats.noteWifiOff(); 3885 } 3886 } catch (RemoteException e) { 3887 loge("Failed to note battery stats in wifi"); 3888 } 3889 3890 // Update state 3891 mWifiApState.set(wifiApState); 3892 3893 if (DBG) log("setWifiApState: " + syncGetWifiApStateByName()); 3894 3895 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 3896 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3897 intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState); 3898 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState); 3899 if (wifiApState == WifiManager.WIFI_AP_STATE_FAILED) { 3900 //only set reason number when softAP start failed 3901 intent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, reason); 3902 } 3903 3904 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3905 } 3906 3907 private void setScanResults() { 3908 mNumScanResultsKnown = 0; 3909 mNumScanResultsReturned = 0; 3910 3911 ArrayList<ScanDetail> scanResults = mWifiNative.getScanResults(); 3912 3913 if (scanResults.isEmpty()) { 3914 mScanResults = new ArrayList<>(); 3915 return; 3916 } 3917 3918 mWifiConfigManager.trimANQPCache(false); 3919 3920 boolean connected = mLastBssid != null; 3921 long activeBssid = 0L; 3922 if (connected) { 3923 try { 3924 activeBssid = Utils.parseMac(mLastBssid); 3925 } catch (IllegalArgumentException iae) { 3926 connected = false; 3927 } 3928 } 3929 3930 synchronized (mScanResultCache) { 3931 ScanDetail activeScanDetail = null; 3932 mScanResults = scanResults; 3933 mNumScanResultsReturned = mScanResults.size(); 3934 for (ScanDetail resultDetail : mScanResults) { 3935 mScanResultCache.put(resultDetail.getNetworkDetail(), resultDetail); 3936 if (connected && resultDetail.getNetworkDetail().getBSSID() == activeBssid) { 3937 if (activeScanDetail == null 3938 || activeScanDetail.getNetworkDetail().getBSSID() != activeBssid 3939 || activeScanDetail.getNetworkDetail().getANQPElements() == null) { 3940 activeScanDetail = resultDetail; 3941 } 3942 } 3943 // Cache DTIM values parsed from the beacon frame Traffic Indication Map (TIM) 3944 // Information Element (IE), into the associated WifiConfigurations. Most of the 3945 // time there is no TIM IE in the scan result (Probe Response instead of Beacon 3946 // Frame), these scanResult DTIM's are negative and ignored. 3947 NetworkDetail networkDetail = resultDetail.getNetworkDetail(); 3948 if (networkDetail != null && networkDetail.getDtimInterval() > 0) { 3949 List<WifiConfiguration> associatedWifiConfigurations = 3950 mWifiConfigManager.updateSavedNetworkWithNewScanDetail(resultDetail); 3951 if (associatedWifiConfigurations != null) { 3952 for (WifiConfiguration associatedConf : associatedWifiConfigurations) { 3953 if (associatedConf != null) { 3954 associatedConf.dtimInterval = networkDetail.getDtimInterval(); 3955 } 3956 } 3957 } 3958 } 3959 } 3960 mActiveScanDetail = activeScanDetail; 3961 } 3962 if (mNumScanResultsReturned > 0) { 3963 mWifiMetrics.incrementNonEmptyScanResultCount(); 3964 } else { 3965 mWifiMetrics.incrementEmptyScanResultCount(); 3966 } 3967 3968 if (linkDebouncing) { 3969 // If debouncing, we dont re-select a SSID or BSSID hence 3970 // there is no need to call the network selection code 3971 // in WifiAutoJoinController, instead, 3972 // just try to reconnect to the same SSID by triggering a roam 3973 // The third parameter 1 means roam not from network selection but debouncing 3974 sendMessage(CMD_AUTO_ROAM, mLastNetworkId, 1, null); 3975 } else { 3976 WifiConfiguration candidate = 3977 mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, 3978 mAllowUntrustedConnections, mScanResults, linkDebouncing, isConnected(), 3979 isDisconnected(), isSupplicantTransientState()); 3980 tryToConnectToNetwork(candidate); 3981 } 3982 } 3983 3984 /** 3985 * Set whether connections to untrusted connections are allowed. 3986 */ 3987 void setAllowUntrustedConnections(boolean allow) { 3988 boolean changed = (mAllowUntrustedConnections != allow); 3989 mAllowUntrustedConnections = allow; 3990 if (changed) { 3991 // Trigger a scan so as to reattempt autojoin 3992 startScanForUntrustedSettingChange(); 3993 } 3994 } 3995 3996 public ScanDetail getActiveScanDetail() { 3997 synchronized (mScanResultCache) { 3998 return mActiveScanDetail; 3999 } 4000 } 4001 4002 /* 4003 * Fetch RSSI, linkspeed, and frequency on current connection 4004 */ 4005 private void fetchRssiLinkSpeedAndFrequencyNative() { 4006 Integer newRssi = null; 4007 Integer newLinkSpeed = null; 4008 Integer newFrequency = null; 4009 4010 String signalPoll = mWifiNative.signalPoll(); 4011 4012 if (signalPoll != null) { 4013 String[] lines = signalPoll.split("\n"); 4014 for (String line : lines) { 4015 String[] prop = line.split("="); 4016 if (prop.length < 2) continue; 4017 try { 4018 if (prop[0].equals("RSSI")) { 4019 newRssi = Integer.parseInt(prop[1]); 4020 } else if (prop[0].equals("LINKSPEED")) { 4021 newLinkSpeed = Integer.parseInt(prop[1]); 4022 } else if (prop[0].equals("FREQUENCY")) { 4023 newFrequency = Integer.parseInt(prop[1]); 4024 } 4025 } catch (NumberFormatException e) { 4026 //Ignore, defaults on rssi and linkspeed are assigned 4027 } 4028 } 4029 } 4030 4031 if (PDBG) { 4032 logd("fetchRssiLinkSpeedAndFrequencyNative rssi=" + newRssi + 4033 " linkspeed=" + newLinkSpeed + " freq=" + newFrequency); 4034 } 4035 4036 if (newRssi != null && newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) { 4037 // screen out invalid values 4038 /* some implementations avoid negative values by adding 256 4039 * so we need to adjust for that here. 4040 */ 4041 if (newRssi > 0) newRssi -= 256; 4042 mWifiInfo.setRssi(newRssi); 4043 /* 4044 * Rather then sending the raw RSSI out every time it 4045 * changes, we precalculate the signal level that would 4046 * be displayed in the status bar, and only send the 4047 * broadcast if that much more coarse-grained number 4048 * changes. This cuts down greatly on the number of 4049 * broadcasts, at the cost of not informing others 4050 * interested in RSSI of all the changes in signal 4051 * level. 4052 */ 4053 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, WifiManager.RSSI_LEVELS); 4054 if (newSignalLevel != mLastSignalLevel) { 4055 updateCapabilities(getCurrentWifiConfiguration()); 4056 sendRssiChangeBroadcast(newRssi); 4057 } 4058 mLastSignalLevel = newSignalLevel; 4059 } else { 4060 mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); 4061 updateCapabilities(getCurrentWifiConfiguration()); 4062 } 4063 4064 if (newLinkSpeed != null) { 4065 mWifiInfo.setLinkSpeed(newLinkSpeed); 4066 } 4067 if (newFrequency != null && newFrequency > 0) { 4068 if (ScanResult.is5GHz(newFrequency)) { 4069 mWifiConnectionStatistics.num5GhzConnected++; 4070 } 4071 if (ScanResult.is24GHz(newFrequency)) { 4072 mWifiConnectionStatistics.num24GhzConnected++; 4073 } 4074 mWifiInfo.setFrequency(newFrequency); 4075 } 4076 mWifiConfigManager.updateConfiguration(mWifiInfo); 4077 } 4078 4079 /** 4080 * Determine if we need to switch network: 4081 * - the delta determine the urgency to switch and/or or the expected evilness of the disruption 4082 * - match the uregncy of the switch versus the packet usage at the interface 4083 */ 4084 boolean shouldSwitchNetwork(int networkDelta) { 4085 int delta; 4086 if (networkDelta <= 0) { 4087 return false; 4088 } 4089 delta = networkDelta; 4090 if (mWifiInfo != null) { 4091 if (!getEnableAutoJoinWhenAssociated() 4092 && mWifiInfo.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) { 4093 // If AutoJoin while associated is not enabled, 4094 // we should never switch network when already associated 4095 delta = -1000; 4096 } else { 4097 // TODO: Look at per AC packet count, do not switch if VO/VI traffic is present 4098 // TODO: at the interface. We should also discriminate between ucast and mcast, 4099 // TODO: since the rxSuccessRate include all the bonjour and Ipv6 4100 // TODO: broadcasts 4101 if ((mWifiInfo.txSuccessRate > 20) || (mWifiInfo.rxSuccessRate > 80)) { 4102 delta -= 999; 4103 } else if ((mWifiInfo.txSuccessRate > 5) || (mWifiInfo.rxSuccessRate > 30)) { 4104 delta -= 6; 4105 } 4106 logd("shouldSwitchNetwork " 4107 + " txSuccessRate=" + String.format("%.2f", mWifiInfo.txSuccessRate) 4108 + " rxSuccessRate=" + String.format("%.2f", mWifiInfo.rxSuccessRate) 4109 + " delta " + networkDelta + " -> " + delta); 4110 } 4111 } else { 4112 logd("shouldSwitchNetwork " 4113 + " delta " + networkDelta + " -> " + delta); 4114 } 4115 if (delta > 0) { 4116 return true; 4117 } 4118 return false; 4119 } 4120 4121 // Polling has completed, hence we wont have a score anymore 4122 private void cleanWifiScore() { 4123 mWifiInfo.txBadRate = 0; 4124 mWifiInfo.txSuccessRate = 0; 4125 mWifiInfo.txRetriesRate = 0; 4126 mWifiInfo.rxSuccessRate = 0; 4127 } 4128 4129 int mBadLinkspeedcount = 0; 4130 4131 // For debug, provide information about the last scoring operation 4132 String wifiScoringReport = null; 4133 4134 private void calculateWifiScore(WifiLinkLayerStats stats) { 4135 StringBuilder sb = new StringBuilder(); 4136 4137 int score = 56; // Starting score, temporarily hardcoded in between 50 and 60 4138 boolean isBadLinkspeed = (mWifiInfo.is24GHz() 4139 && mWifiInfo.getLinkSpeed() < mWifiConfigManager.badLinkSpeed24) 4140 || (mWifiInfo.is5GHz() && mWifiInfo.getLinkSpeed() 4141 < mWifiConfigManager.badLinkSpeed5); 4142 boolean isGoodLinkspeed = (mWifiInfo.is24GHz() 4143 && mWifiInfo.getLinkSpeed() >= mWifiConfigManager.goodLinkSpeed24) 4144 || (mWifiInfo.is5GHz() && mWifiInfo.getLinkSpeed() 4145 >= mWifiConfigManager.goodLinkSpeed5); 4146 4147 if (isBadLinkspeed) { 4148 if (mBadLinkspeedcount < 6) 4149 mBadLinkspeedcount++; 4150 } else { 4151 if (mBadLinkspeedcount > 0) 4152 mBadLinkspeedcount--; 4153 } 4154 4155 if (isBadLinkspeed) sb.append(" bl(").append(mBadLinkspeedcount).append(")"); 4156 if (isGoodLinkspeed) sb.append(" gl"); 4157 4158 /** 4159 * We want to make sure that we use the 24GHz RSSI thresholds if 4160 * there are 2.4GHz scan results 4161 * otherwise we end up lowering the score based on 5GHz values 4162 * which may cause a switch to LTE before roaming has a chance to try 2.4GHz 4163 * We also might unblacklist the configuation based on 2.4GHz 4164 * thresholds but joining 5GHz anyhow, and failing over to 2.4GHz because 5GHz is not good 4165 */ 4166 boolean use24Thresholds = false; 4167 boolean homeNetworkBoost = false; 4168 WifiConfiguration currentConfiguration = getCurrentWifiConfiguration(); 4169 ScanDetailCache scanDetailCache = 4170 mWifiConfigManager.getScanDetailCache(currentConfiguration); 4171 if (currentConfiguration != null && scanDetailCache != null) { 4172 currentConfiguration.setVisibility(scanDetailCache.getVisibility(12000)); 4173 if (currentConfiguration.visibility != null) { 4174 if (currentConfiguration.visibility.rssi24 != WifiConfiguration.INVALID_RSSI 4175 && currentConfiguration.visibility.rssi24 4176 >= (currentConfiguration.visibility.rssi5 - 2)) { 4177 use24Thresholds = true; 4178 } 4179 } 4180 if (scanDetailCache.size() <= 6 4181 && currentConfiguration.allowedKeyManagement.cardinality() == 1 4182 && currentConfiguration.allowedKeyManagement. 4183 get(WifiConfiguration.KeyMgmt.WPA_PSK) == true) { 4184 // A PSK network with less than 6 known BSSIDs 4185 // This is most likely a home network and thus we want to stick to wifi more 4186 homeNetworkBoost = true; 4187 } 4188 } 4189 if (homeNetworkBoost) sb.append(" hn"); 4190 if (use24Thresholds) sb.append(" u24"); 4191 4192 int rssi = mWifiInfo.getRssi() - 6 * mAggressiveHandover 4193 + (homeNetworkBoost ? WifiConfiguration.HOME_NETWORK_RSSI_BOOST : 0); 4194 sb.append(String.format(" rssi=%d ag=%d", rssi, mAggressiveHandover)); 4195 4196 boolean is24GHz = use24Thresholds || mWifiInfo.is24GHz(); 4197 4198 boolean isBadRSSI = (is24GHz && rssi < mWifiConfigManager.thresholdMinimumRssi24.get()) 4199 || (!is24GHz && rssi < mWifiConfigManager.thresholdMinimumRssi5.get()); 4200 boolean isLowRSSI = (is24GHz && rssi < mWifiConfigManager.thresholdQualifiedRssi24.get()) 4201 || (!is24GHz && 4202 mWifiInfo.getRssi() < mWifiConfigManager.thresholdMinimumRssi5.get()); 4203 boolean isHighRSSI = (is24GHz && rssi >= mWifiConfigManager.thresholdSaturatedRssi24.get()) 4204 || (!is24GHz && mWifiInfo.getRssi() 4205 >= mWifiConfigManager.thresholdSaturatedRssi5.get()); 4206 4207 if (isBadRSSI) sb.append(" br"); 4208 if (isLowRSSI) sb.append(" lr"); 4209 if (isHighRSSI) sb.append(" hr"); 4210 4211 int penalizedDueToUserTriggeredDisconnect = 0; // For debug information 4212 if (currentConfiguration != null && 4213 (mWifiInfo.txSuccessRate > 5 || mWifiInfo.rxSuccessRate > 5)) { 4214 if (isBadRSSI) { 4215 currentConfiguration.numTicksAtBadRSSI++; 4216 if (currentConfiguration.numTicksAtBadRSSI > 1000) { 4217 // We remained associated for a compound amount of time while passing 4218 // traffic, hence loose the corresponding user triggered disabled stats 4219 if (currentConfiguration.numUserTriggeredWifiDisableBadRSSI > 0) { 4220 currentConfiguration.numUserTriggeredWifiDisableBadRSSI--; 4221 } 4222 if (currentConfiguration.numUserTriggeredWifiDisableLowRSSI > 0) { 4223 currentConfiguration.numUserTriggeredWifiDisableLowRSSI--; 4224 } 4225 if (currentConfiguration.numUserTriggeredWifiDisableNotHighRSSI > 0) { 4226 currentConfiguration.numUserTriggeredWifiDisableNotHighRSSI--; 4227 } 4228 currentConfiguration.numTicksAtBadRSSI = 0; 4229 } 4230 if (mWifiConfigManager.enableWifiCellularHandoverUserTriggeredAdjustment && 4231 (currentConfiguration.numUserTriggeredWifiDisableBadRSSI > 0 4232 || currentConfiguration.numUserTriggeredWifiDisableLowRSSI > 0 4233 || currentConfiguration.numUserTriggeredWifiDisableNotHighRSSI > 0)) { 4234 score = score - 5; 4235 penalizedDueToUserTriggeredDisconnect = 1; 4236 sb.append(" p1"); 4237 } 4238 } else if (isLowRSSI) { 4239 currentConfiguration.numTicksAtLowRSSI++; 4240 if (currentConfiguration.numTicksAtLowRSSI > 1000) { 4241 // We remained associated for a compound amount of time while passing 4242 // traffic, hence loose the corresponding user triggered disabled stats 4243 if (currentConfiguration.numUserTriggeredWifiDisableLowRSSI > 0) { 4244 currentConfiguration.numUserTriggeredWifiDisableLowRSSI--; 4245 } 4246 if (currentConfiguration.numUserTriggeredWifiDisableNotHighRSSI > 0) { 4247 currentConfiguration.numUserTriggeredWifiDisableNotHighRSSI--; 4248 } 4249 currentConfiguration.numTicksAtLowRSSI = 0; 4250 } 4251 if (mWifiConfigManager.enableWifiCellularHandoverUserTriggeredAdjustment && 4252 (currentConfiguration.numUserTriggeredWifiDisableLowRSSI > 0 4253 || currentConfiguration.numUserTriggeredWifiDisableNotHighRSSI > 0)) { 4254 score = score - 5; 4255 penalizedDueToUserTriggeredDisconnect = 2; 4256 sb.append(" p2"); 4257 } 4258 } else if (!isHighRSSI) { 4259 currentConfiguration.numTicksAtNotHighRSSI++; 4260 if (currentConfiguration.numTicksAtNotHighRSSI > 1000) { 4261 // We remained associated for a compound amount of time while passing 4262 // traffic, hence loose the corresponding user triggered disabled stats 4263 if (currentConfiguration.numUserTriggeredWifiDisableNotHighRSSI > 0) { 4264 currentConfiguration.numUserTriggeredWifiDisableNotHighRSSI--; 4265 } 4266 currentConfiguration.numTicksAtNotHighRSSI = 0; 4267 } 4268 if (mWifiConfigManager.enableWifiCellularHandoverUserTriggeredAdjustment && 4269 currentConfiguration.numUserTriggeredWifiDisableNotHighRSSI > 0) { 4270 score = score - 5; 4271 penalizedDueToUserTriggeredDisconnect = 3; 4272 sb.append(" p3"); 4273 } 4274 } 4275 sb.append(String.format(" ticks %d,%d,%d", currentConfiguration.numTicksAtBadRSSI, 4276 currentConfiguration.numTicksAtLowRSSI, 4277 currentConfiguration.numTicksAtNotHighRSSI)); 4278 } 4279 4280 if (PDBG) { 4281 String rssiStatus = ""; 4282 if (isBadRSSI) rssiStatus += " badRSSI "; 4283 else if (isHighRSSI) rssiStatus += " highRSSI "; 4284 else if (isLowRSSI) rssiStatus += " lowRSSI "; 4285 if (isBadLinkspeed) rssiStatus += " lowSpeed "; 4286 logd("calculateWifiScore freq=" + Integer.toString(mWifiInfo.getFrequency()) 4287 + " speed=" + Integer.toString(mWifiInfo.getLinkSpeed()) 4288 + " score=" + Integer.toString(mWifiInfo.score) 4289 + rssiStatus 4290 + " -> txbadrate=" + String.format("%.2f", mWifiInfo.txBadRate) 4291 + " txgoodrate=" + String.format("%.2f", mWifiInfo.txSuccessRate) 4292 + " txretriesrate=" + String.format("%.2f", mWifiInfo.txRetriesRate) 4293 + " rxrate=" + String.format("%.2f", mWifiInfo.rxSuccessRate) 4294 + " userTriggerdPenalty" + penalizedDueToUserTriggeredDisconnect); 4295 } 4296 4297 if ((mWifiInfo.txBadRate >= 1) && (mWifiInfo.txSuccessRate < 3) 4298 && (isBadRSSI || isLowRSSI)) { 4299 // Link is stuck 4300 if (mWifiInfo.linkStuckCount < 5) 4301 mWifiInfo.linkStuckCount += 1; 4302 sb.append(String.format(" ls+=%d", mWifiInfo.linkStuckCount)); 4303 if (PDBG) logd(" bad link -> stuck count =" 4304 + Integer.toString(mWifiInfo.linkStuckCount)); 4305 } else if (mWifiInfo.txBadRate < 0.3) { 4306 if (mWifiInfo.linkStuckCount > 0) 4307 mWifiInfo.linkStuckCount -= 1; 4308 sb.append(String.format(" ls-=%d", mWifiInfo.linkStuckCount)); 4309 if (PDBG) logd(" good link -> stuck count =" 4310 + Integer.toString(mWifiInfo.linkStuckCount)); 4311 } 4312 4313 sb.append(String.format(" [%d", score)); 4314 4315 if (mWifiInfo.linkStuckCount > 1) { 4316 // Once link gets stuck for more than 3 seconds, start reducing the score 4317 score = score - 2 * (mWifiInfo.linkStuckCount - 1); 4318 } 4319 sb.append(String.format(",%d", score)); 4320 4321 if (isBadLinkspeed) { 4322 score -= 4; 4323 if (PDBG) { 4324 logd(" isBadLinkspeed ---> count=" + mBadLinkspeedcount 4325 + " score=" + Integer.toString(score)); 4326 } 4327 } else if ((isGoodLinkspeed) && (mWifiInfo.txSuccessRate > 5)) { 4328 score += 4; // So as bad rssi alone dont kill us 4329 } 4330 sb.append(String.format(",%d", score)); 4331 4332 if (isBadRSSI) { 4333 if (mWifiInfo.badRssiCount < 7) 4334 mWifiInfo.badRssiCount += 1; 4335 } else if (isLowRSSI) { 4336 mWifiInfo.lowRssiCount = 1; // Dont increment the lowRssi count above 1 4337 if (mWifiInfo.badRssiCount > 0) { 4338 // Decrement bad Rssi count 4339 mWifiInfo.badRssiCount -= 1; 4340 } 4341 } else { 4342 mWifiInfo.badRssiCount = 0; 4343 mWifiInfo.lowRssiCount = 0; 4344 } 4345 4346 score -= mWifiInfo.badRssiCount * 2 + mWifiInfo.lowRssiCount; 4347 sb.append(String.format(",%d", score)); 4348 4349 if (PDBG) logd(" badRSSI count" + Integer.toString(mWifiInfo.badRssiCount) 4350 + " lowRSSI count" + Integer.toString(mWifiInfo.lowRssiCount) 4351 + " --> score " + Integer.toString(score)); 4352 4353 4354 if (isHighRSSI) { 4355 score += 5; 4356 if (PDBG) logd(" isHighRSSI ---> score=" + Integer.toString(score)); 4357 } 4358 sb.append(String.format(",%d]", score)); 4359 4360 sb.append(String.format(" brc=%d lrc=%d", mWifiInfo.badRssiCount, mWifiInfo.lowRssiCount)); 4361 4362 //sanitize boundaries 4363 if (score > NetworkAgent.WIFI_BASE_SCORE) 4364 score = NetworkAgent.WIFI_BASE_SCORE; 4365 if (score < 0) 4366 score = 0; 4367 4368 //report score 4369 if (score != mWifiInfo.score) { 4370 if (DBG) { 4371 logd("calculateWifiScore() report new score " + Integer.toString(score)); 4372 } 4373 mWifiInfo.score = score; 4374 if (mNetworkAgent != null) { 4375 mNetworkAgent.sendNetworkScore(score); 4376 } 4377 } 4378 wifiScoringReport = sb.toString(); 4379 } 4380 4381 public double getTxPacketRate() { 4382 if (mWifiInfo != null) { 4383 return mWifiInfo.txSuccessRate; 4384 } 4385 return -1; 4386 } 4387 4388 public double getRxPacketRate() { 4389 if (mWifiInfo != null) { 4390 return mWifiInfo.rxSuccessRate; 4391 } 4392 return -1; 4393 } 4394 4395 /** 4396 * Fetch TX packet counters on current connection 4397 */ 4398 private void fetchPktcntNative(RssiPacketCountInfo info) { 4399 String pktcntPoll = mWifiNative.pktcntPoll(); 4400 4401 if (pktcntPoll != null) { 4402 String[] lines = pktcntPoll.split("\n"); 4403 for (String line : lines) { 4404 String[] prop = line.split("="); 4405 if (prop.length < 2) continue; 4406 try { 4407 if (prop[0].equals("TXGOOD")) { 4408 info.txgood = Integer.parseInt(prop[1]); 4409 } else if (prop[0].equals("TXBAD")) { 4410 info.txbad = Integer.parseInt(prop[1]); 4411 } 4412 } catch (NumberFormatException e) { 4413 // Ignore 4414 } 4415 } 4416 } 4417 } 4418 4419 private void notifyLinkProperties() { 4420 // TODO: Add setters for TCP buffer sizes and HTTP proxy to IpManager. 4421 // Once that is done delete this. 4422 updateLinkProperties(new LinkProperties(mLinkProperties)); 4423 } 4424 4425 private void updateLinkProperties(LinkProperties newLp) { 4426 // HTTP proxy and TCP buffer sizes are locally configured. 4427 newLp.setHttpProxy(mWifiConfigManager.getProxyProperties(mLastNetworkId)); 4428 if (!TextUtils.isEmpty(mTcpBufferSizes)) { 4429 newLp.setTcpBufferSizes(mTcpBufferSizes); 4430 } 4431 4432 if (!newLp.equals(mLinkProperties)) { 4433 if (DBG) { 4434 log("Link configuration changed for netId: " + mLastNetworkId 4435 + " old: " + mLinkProperties + " new: " + newLp); 4436 } 4437 // We own this instance of LinkProperties because IpManager passes us a copy. 4438 mLinkProperties = newLp; 4439 if (mNetworkAgent != null) { 4440 mNetworkAgent.sendLinkProperties(mLinkProperties); 4441 } 4442 4443 if (getNetworkDetailedState() == DetailedState.CONNECTED) { 4444 // If anything has changed and we're already connected, send out a notification. 4445 // TODO: Update all callers to use NetworkCallbacks and delete this. 4446 sendLinkConfigurationChangedBroadcast(); 4447 } 4448 } 4449 4450 if (DBG) { 4451 StringBuilder sb = new StringBuilder(); 4452 sb.append("updateLinkProperties nid: " + mLastNetworkId); 4453 sb.append(" state: " + getNetworkDetailedState()); 4454 4455 if (mLinkProperties != null) { 4456 sb.append(" "); 4457 sb.append(getLinkPropertiesSummary(mLinkProperties)); 4458 } 4459 logd(sb.toString()); 4460 } 4461 } 4462 4463 /** 4464 * Clears all our link properties. 4465 */ 4466 private void clearLinkProperties() { 4467 // Clear the link properties obtained from DHCP. The only caller of this 4468 // function has already called IpManager#stop(), which clears its state. 4469 synchronized (mDhcpResultsLock) { 4470 if (mDhcpResults != null) { 4471 mDhcpResults.clear(); 4472 } 4473 } 4474 4475 // Now clear the merged link properties. 4476 mLinkProperties.clear(); 4477 if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties); 4478 } 4479 4480 /** 4481 * try to update default route MAC address. 4482 */ 4483 private String updateDefaultRouteMacAddress(int timeout) { 4484 String address = null; 4485 for (RouteInfo route : mLinkProperties.getRoutes()) { 4486 if (route.isDefaultRoute() && route.hasGateway()) { 4487 InetAddress gateway = route.getGateway(); 4488 if (gateway instanceof Inet4Address) { 4489 if (PDBG) { 4490 logd("updateDefaultRouteMacAddress found Ipv4 default :" 4491 + gateway.getHostAddress()); 4492 } 4493 address = macAddressFromRoute(gateway.getHostAddress()); 4494 /* The gateway's MAC address is known */ 4495 if ((address == null) && (timeout > 0)) { 4496 boolean reachable = false; 4497 try { 4498 reachable = gateway.isReachable(timeout); 4499 } catch (Exception e) { 4500 loge("updateDefaultRouteMacAddress exception reaching :" 4501 + gateway.getHostAddress()); 4502 4503 } finally { 4504 if (reachable == true) { 4505 4506 address = macAddressFromRoute(gateway.getHostAddress()); 4507 if (PDBG) { 4508 logd("updateDefaultRouteMacAddress reachable (tried again) :" 4509 + gateway.getHostAddress() + " found " + address); 4510 } 4511 } 4512 } 4513 } 4514 if (address != null) { 4515 mWifiConfigManager.setDefaultGwMacAddress(mLastNetworkId, address); 4516 } 4517 } 4518 } 4519 } 4520 return address; 4521 } 4522 4523 void sendScanResultsAvailableBroadcast(boolean scanSucceeded) { 4524 Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 4525 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4526 intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, scanSucceeded); 4527 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 4528 } 4529 4530 private void sendRssiChangeBroadcast(final int newRssi) { 4531 try { 4532 mBatteryStats.noteWifiRssiChanged(newRssi); 4533 } catch (RemoteException e) { 4534 // Won't happen. 4535 } 4536 Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION); 4537 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4538 intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi); 4539 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4540 } 4541 4542 private void sendNetworkStateChangeBroadcast(String bssid) { 4543 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); 4544 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4545 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo)); 4546 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties)); 4547 if (bssid != null) 4548 intent.putExtra(WifiManager.EXTRA_BSSID, bssid); 4549 if (mNetworkInfo.getDetailedState() == DetailedState.VERIFYING_POOR_LINK || 4550 mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) { 4551 // We no longer report MAC address to third-parties and our code does 4552 // not rely on this broadcast, so just send the default MAC address. 4553 WifiInfo sentWifiInfo = new WifiInfo(mWifiInfo); 4554 sentWifiInfo.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS); 4555 intent.putExtra(WifiManager.EXTRA_WIFI_INFO, sentWifiInfo); 4556 } 4557 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4558 } 4559 4560 private WifiInfo getWiFiInfoForUid(int uid) { 4561 if (Binder.getCallingUid() == Process.myUid()) { 4562 return mWifiInfo; 4563 } 4564 4565 WifiInfo result = new WifiInfo(mWifiInfo); 4566 result.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS); 4567 4568 IBinder binder = mFacade.getService("package"); 4569 IPackageManager packageManager = IPackageManager.Stub.asInterface(binder); 4570 4571 try { 4572 if (packageManager.checkUidPermission(Manifest.permission.LOCAL_MAC_ADDRESS, 4573 uid) == PackageManager.PERMISSION_GRANTED) { 4574 result.setMacAddress(mWifiInfo.getMacAddress()); 4575 } 4576 } catch (RemoteException e) { 4577 Log.e(TAG, "Error checking receiver permission", e); 4578 } 4579 4580 return result; 4581 } 4582 4583 private void sendLinkConfigurationChangedBroadcast() { 4584 Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); 4585 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4586 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties)); 4587 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 4588 } 4589 4590 private void sendSupplicantConnectionChangedBroadcast(boolean connected) { 4591 Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 4592 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4593 intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected); 4594 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 4595 } 4596 4597 /** 4598 * Record the detailed state of a network. 4599 * 4600 * @param state the new {@code DetailedState} 4601 */ 4602 private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) { 4603 boolean hidden = false; 4604 4605 if (linkDebouncing || isRoaming()) { 4606 // There is generally a confusion in the system about colluding 4607 // WiFi Layer 2 state (as reported by supplicant) and the Network state 4608 // which leads to multiple confusion. 4609 // 4610 // If link is de-bouncing or roaming, we already have an IP address 4611 // as well we were connected and are doing L2 cycles of 4612 // reconnecting or renewing IP address to check that we still have it 4613 // This L2 link flapping should ne be reflected into the Network state 4614 // which is the state of the WiFi Network visible to Layer 3 and applications 4615 // Note that once debouncing and roaming are completed, we will 4616 // set the Network state to where it should be, or leave it as unchanged 4617 // 4618 hidden = true; 4619 } 4620 if (DBG) { 4621 log("setDetailed state, old =" 4622 + mNetworkInfo.getDetailedState() + " and new state=" + state 4623 + " hidden=" + hidden); 4624 } 4625 if (mNetworkInfo.getExtraInfo() != null && mWifiInfo.getSSID() != null 4626 && !mWifiInfo.getSSID().equals(WifiSsid.NONE)) { 4627 // Always indicate that SSID has changed 4628 if (!mNetworkInfo.getExtraInfo().equals(mWifiInfo.getSSID())) { 4629 if (DBG) { 4630 log("setDetailed state send new extra info" + mWifiInfo.getSSID()); 4631 } 4632 mNetworkInfo.setExtraInfo(mWifiInfo.getSSID()); 4633 sendNetworkStateChangeBroadcast(null); 4634 } 4635 } 4636 if (hidden == true) { 4637 return false; 4638 } 4639 4640 if (state != mNetworkInfo.getDetailedState()) { 4641 mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID()); 4642 if (mNetworkAgent != null) { 4643 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4644 } 4645 sendNetworkStateChangeBroadcast(null); 4646 return true; 4647 } 4648 return false; 4649 } 4650 4651 private DetailedState getNetworkDetailedState() { 4652 return mNetworkInfo.getDetailedState(); 4653 } 4654 4655 private SupplicantState handleSupplicantStateChange(Message message) { 4656 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 4657 SupplicantState state = stateChangeResult.state; 4658 // Supplicant state change 4659 // [31-13] Reserved for future use 4660 // [8 - 0] Supplicant state (as defined in SupplicantState.java) 4661 // 50023 supplicant_state_changed (custom|1|5) 4662 mWifiInfo.setSupplicantState(state); 4663 // Network id is only valid when we start connecting 4664 if (SupplicantState.isConnecting(state)) { 4665 mWifiInfo.setNetworkId(stateChangeResult.networkId); 4666 } else { 4667 mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); 4668 } 4669 4670 mWifiInfo.setBSSID(stateChangeResult.BSSID); 4671 4672 if (mWhiteListedSsids != null 4673 && mWhiteListedSsids.length > 0 4674 && stateChangeResult.wifiSsid != null) { 4675 String SSID = stateChangeResult.wifiSsid.toString(); 4676 String currentSSID = mWifiInfo.getSSID(); 4677 if (SSID != null && currentSSID != null && !SSID.equals(WifiSsid.NONE)) { 4678 // Remove quote before comparing 4679 if (SSID.length() >= 2 && SSID.charAt(0) == '"' 4680 && SSID.charAt(SSID.length() - 1) == '"') { 4681 SSID = SSID.substring(1, SSID.length() - 1); 4682 } 4683 if (currentSSID.length() >= 2 && currentSSID.charAt(0) == '"' 4684 && currentSSID.charAt(currentSSID.length() - 1) == '"') { 4685 currentSSID = currentSSID.substring(1, currentSSID.length() - 1); 4686 } 4687 if ((!SSID.equals(currentSSID)) && (getCurrentState() == mConnectedState)) { 4688 lastConnectAttemptTimestamp = System.currentTimeMillis(); 4689 targetWificonfiguration = 4690 mWifiConfigManager.getWifiConfiguration(mWifiInfo.getNetworkId()); 4691 transitionTo(mRoamingState); 4692 } 4693 } 4694 } 4695 4696 mWifiInfo.setSSID(stateChangeResult.wifiSsid); 4697 mWifiInfo.setEphemeral(mWifiConfigManager.isEphemeral(mWifiInfo.getNetworkId())); 4698 4699 mSupplicantStateTracker.sendMessage(Message.obtain(message)); 4700 4701 return state; 4702 } 4703 4704 /** 4705 * Resets the Wi-Fi Connections by clearing any state, resetting any sockets 4706 * using the interface, stopping DHCP & disabling interface 4707 */ 4708 private void handleNetworkDisconnect() { 4709 if (DBG) log("handleNetworkDisconnect: Stopping DHCP and clearing IP" 4710 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 4711 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 4712 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 4713 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 4714 4715 stopRssiMonitoringOffload(); 4716 4717 clearCurrentConfigBSSID("handleNetworkDisconnect"); 4718 4719 stopIpManager(); 4720 4721 /* Reset data structures */ 4722 mBadLinkspeedcount = 0; 4723 mWifiInfo.reset(); 4724 linkDebouncing = false; 4725 /* Reset roaming parameters */ 4726 mAutoRoaming = false; 4727 4728 /** 4729 * fullBandConnectedTimeIntervalMilli: 4730 * - start scans at mWifiConfigManager.wifiAssociatedShortScanIntervalMilli seconds 4731 * interval 4732 * - exponentially increase to mWifiConfigManager.associatedFullScanMaxIntervalMilli 4733 * Initialize to sane value = 20 seconds 4734 */ 4735 fullBandConnectedTimeIntervalMilli = 20 * 1000; 4736 4737 setNetworkDetailedState(DetailedState.DISCONNECTED); 4738 if (mNetworkAgent != null) { 4739 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4740 mNetworkAgent = null; 4741 } 4742 mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED); 4743 4744 /* Clear network properties */ 4745 clearLinkProperties(); 4746 4747 /* Cend event to CM & network change broadcast */ 4748 sendNetworkStateChangeBroadcast(mLastBssid); 4749 4750 /* Cancel auto roam requests */ 4751 autoRoamSetBSSID(mLastNetworkId, "any"); 4752 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 4753 mLastBssid = null; 4754 registerDisconnected(); 4755 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 4756 } 4757 4758 private void handleSupplicantConnectionLoss(boolean killSupplicant) { 4759 /* Socket connection can be lost when we do a graceful shutdown 4760 * or when the driver is hung. Ensure supplicant is stopped here. 4761 */ 4762 if (killSupplicant) { 4763 mWifiMonitor.killSupplicant(mP2pSupported); 4764 } 4765 mWifiNative.closeSupplicantConnection(); 4766 sendSupplicantConnectionChangedBroadcast(false); 4767 setWifiState(WIFI_STATE_DISABLED); 4768 } 4769 4770 void handlePreDhcpSetup() { 4771 if (!mBluetoothConnectionActive) { 4772 /* 4773 * There are problems setting the Wi-Fi driver's power 4774 * mode to active when bluetooth coexistence mode is 4775 * enabled or sense. 4776 * <p> 4777 * We set Wi-Fi to active mode when 4778 * obtaining an IP address because we've found 4779 * compatibility issues with some routers with low power 4780 * mode. 4781 * <p> 4782 * In order for this active power mode to properly be set, 4783 * we disable coexistence mode until we're done with 4784 * obtaining an IP address. One exception is if we 4785 * are currently connected to a headset, since disabling 4786 * coexistence would interrupt that connection. 4787 */ 4788 // Disable the coexistence mode 4789 mWifiNative.setBluetoothCoexistenceMode( 4790 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); 4791 } 4792 4793 // Disable power save and suspend optimizations during DHCP 4794 // Note: The order here is important for now. Brcm driver changes 4795 // power settings when we control suspend mode optimizations. 4796 // TODO: Remove this comment when the driver is fixed. 4797 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false); 4798 mWifiNative.setPowerSave(false); 4799 4800 // Update link layer stats 4801 getWifiLinkLayerStats(false); 4802 4803 /* P2p discovery breaks dhcp, shut it down in order to get through this */ 4804 Message msg = new Message(); 4805 msg.what = WifiP2pServiceImpl.BLOCK_DISCOVERY; 4806 msg.arg1 = WifiP2pServiceImpl.ENABLED; 4807 msg.arg2 = DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE; 4808 msg.obj = WifiStateMachine.this; 4809 mWifiP2pChannel.sendMessage(msg); 4810 } 4811 4812 void handlePostDhcpSetup() { 4813 /* Restore power save and suspend optimizations */ 4814 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true); 4815 mWifiNative.setPowerSave(true); 4816 4817 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.BLOCK_DISCOVERY, 4818 WifiP2pServiceImpl.DISABLED); 4819 4820 // Set the coexistence mode back to its default value 4821 mWifiNative.setBluetoothCoexistenceMode( 4822 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); 4823 } 4824 4825 void connectScanningService() { 4826 if (mWifiScanner == null) { 4827 mWifiScanner = (WifiScanner) mContext.getSystemService(Context.WIFI_SCANNING_SERVICE); 4828 } 4829 } 4830 4831 private void handleIPv4Success(DhcpResults dhcpResults) { 4832 if (PDBG) { 4833 logd("handleIPv4Success <" + dhcpResults.toString() + ">"); 4834 logd("link address " + dhcpResults.ipAddress); 4835 } 4836 4837 Inet4Address addr; 4838 synchronized (mDhcpResultsLock) { 4839 mDhcpResults = dhcpResults; 4840 addr = (Inet4Address) dhcpResults.ipAddress.getAddress(); 4841 } 4842 4843 if (isRoaming()) { 4844 int previousAddress = mWifiInfo.getIpAddress(); 4845 int newAddress = NetworkUtils.inetAddressToInt(addr); 4846 if (previousAddress != newAddress) { 4847 logd("handleIPv4Success, roaming and address changed" + 4848 mWifiInfo + " got: " + addr); 4849 } 4850 } 4851 mWifiInfo.setInetAddress(addr); 4852 mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint()); 4853 } 4854 4855 private void handleSuccessfulIpConfiguration() { 4856 mLastSignalLevel = -1; // Force update of signal strength 4857 WifiConfiguration c = getCurrentWifiConfiguration(); 4858 if (c != null) { 4859 // Reset IP failure tracking 4860 c.getNetworkSelectionStatus().clearDisableReasonCounter( 4861 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 4862 4863 // Tell the framework whether the newly connected network is trusted or untrusted. 4864 updateCapabilities(c); 4865 } 4866 if (c != null) { 4867 ScanResult result = getCurrentScanResult(); 4868 if (result == null) { 4869 logd("WifiStateMachine: handleSuccessfulIpConfiguration and no scan results" + 4870 c.configKey()); 4871 } else { 4872 // Clear the per BSSID failure count 4873 result.numIpConfigFailures = 0; 4874 // Clear the WHOLE BSSID blacklist, which means supplicant is free to retry 4875 // any BSSID, even though it may already have a non zero ip failure count, 4876 // this will typically happen if the user walks away and come back to his arrea 4877 // TODO: implement blacklisting based on a timer, i.e. keep BSSID blacklisted 4878 // in supplicant for a couple of hours or a day 4879 mWifiConfigManager.clearBssidBlacklist(); 4880 } 4881 } 4882 } 4883 4884 private void handleIPv4Failure() { 4885 // TODO: Move this to provisioning failure, not DHCP failure. 4886 // DHCPv4 failure is expected on an IPv6-only network. 4887 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_DHCP_FAILURE); 4888 if (DBG) { 4889 int count = -1; 4890 WifiConfiguration config = getCurrentWifiConfiguration(); 4891 if (config != null) { 4892 count = config.getNetworkSelectionStatus().getDisableReasonCounter( 4893 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 4894 } 4895 log("DHCP failure count=" + count); 4896 } 4897 mWifiMetrics.endConnectionEvent( 4898 WifiMetrics.ConnectionEvent.LLF_NONE, 4899 WifiMetricsProto.ConnectionEvent.HLF_DHCP); 4900 synchronized(mDhcpResultsLock) { 4901 if (mDhcpResults != null) { 4902 mDhcpResults.clear(); 4903 } 4904 } 4905 if (PDBG) { 4906 logd("handleIPv4Failure"); 4907 } 4908 } 4909 4910 private void handleIpConfigurationLost() { 4911 mWifiInfo.setInetAddress(null); 4912 mWifiInfo.setMeteredHint(false); 4913 4914 mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId, 4915 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 4916 4917 /* DHCP times out after about 30 seconds, we do a 4918 * disconnect thru supplicant, we will let autojoin retry connecting to the network 4919 */ 4920 mWifiNative.disconnect(); 4921 } 4922 4923 // TODO: De-duplicated this and handleIpConfigurationLost(). 4924 private void handleIpReachabilityLost() { 4925 mWifiInfo.setInetAddress(null); 4926 mWifiInfo.setMeteredHint(false); 4927 4928 // TODO: Determine whether to call some form of mWifiConfigManager.handleSSIDStateChange(). 4929 4930 // Disconnect via supplicant, and let autojoin retry connecting to the network. 4931 mWifiNative.disconnect(); 4932 } 4933 4934 private int convertFrequencyToChannelNumber(int frequency) { 4935 if (frequency >= 2412 && frequency <= 2484) { 4936 return (frequency -2412) / 5 + 1; 4937 } else if (frequency >= 5170 && frequency <=5825) { 4938 //DFS is included 4939 return (frequency -5170) / 5 + 34; 4940 } else { 4941 return 0; 4942 } 4943 } 4944 4945 private int chooseApChannel(int apBand) { 4946 int apChannel; 4947 int[] channel; 4948 4949 if (apBand == 0) { 4950 ArrayList<Integer> allowed2GChannel = 4951 mWifiApConfigStore.getAllowed2GChannel(); 4952 if (allowed2GChannel == null || allowed2GChannel.size() == 0) { 4953 //most safe channel to use 4954 if(DBG) { 4955 Log.d(TAG, "No specified 2G allowed channel list"); 4956 } 4957 apChannel = 6; 4958 } else { 4959 int index = mRandom.nextInt(allowed2GChannel.size()); 4960 apChannel = allowed2GChannel.get(index).intValue(); 4961 } 4962 } else { 4963 //5G without DFS 4964 channel = mWifiNative.getChannelsForBand(2); 4965 if (channel != null && channel.length > 0) { 4966 apChannel = channel[mRandom.nextInt(channel.length)]; 4967 apChannel = convertFrequencyToChannelNumber(apChannel); 4968 } else { 4969 Log.e(TAG, "SoftAp do not get available channel list"); 4970 apChannel = 0; 4971 } 4972 } 4973 4974 if(DBG) { 4975 Log.d(TAG, "SoftAp set on channel " + apChannel); 4976 } 4977 4978 return apChannel; 4979 } 4980 4981 /* Driver/firmware setup for soft AP. */ 4982 private boolean setupDriverForSoftAp() { 4983 if (!mWifiNative.loadDriver()) { 4984 Log.e(TAG, "Failed to load driver for softap"); 4985 return false; 4986 } 4987 4988 if (mWifiNative.getInterfaces() != 0) { 4989 if (!mWifiNative.toggleInterface(0)) { 4990 Log.e(TAG, "toggleInterface failed"); 4991 return false; 4992 } 4993 } else { 4994 if (DBG) Log.d(TAG, "No interfaces to toggle"); 4995 } 4996 4997 try { 4998 mNwService.wifiFirmwareReload(mInterfaceName, "AP"); 4999 if (DBG) Log.d(TAG, "Firmware reloaded in AP mode"); 5000 } catch (Exception e) { 5001 Log.e(TAG, "Failed to reload AP firmware " + e); 5002 } 5003 5004 if (!mWifiNative.startHal()) { 5005 /* starting HAL is optional */ 5006 Log.e(TAG, "Failed to start HAL"); 5007 } 5008 return true; 5009 } 5010 5011 private byte[] macAddressFromString(String macString) { 5012 String[] macBytes = macString.split(":"); 5013 if (macBytes.length != 6) { 5014 throw new IllegalArgumentException("MAC address should be 6 bytes long!"); 5015 } 5016 byte[] mac = new byte[6]; 5017 for (int i = 0; i < macBytes.length; i++) { 5018 Integer hexVal = Integer.parseInt(macBytes[i], 16); 5019 mac[i] = hexVal.byteValue(); 5020 } 5021 return mac; 5022 } 5023 5024 /* 5025 * Read a MAC address in /proc/arp/table, used by WifistateMachine 5026 * so as to record MAC address of default gateway. 5027 **/ 5028 private String macAddressFromRoute(String ipAddress) { 5029 String macAddress = null; 5030 BufferedReader reader = null; 5031 try { 5032 reader = new BufferedReader(new FileReader("/proc/net/arp")); 5033 5034 // Skip over the line bearing colum titles 5035 String line = reader.readLine(); 5036 5037 while ((line = reader.readLine()) != null) { 5038 String[] tokens = line.split("[ ]+"); 5039 if (tokens.length < 6) { 5040 continue; 5041 } 5042 5043 // ARP column format is 5044 // Address HWType HWAddress Flags Mask IFace 5045 String ip = tokens[0]; 5046 String mac = tokens[3]; 5047 5048 if (ipAddress.equals(ip)) { 5049 macAddress = mac; 5050 break; 5051 } 5052 } 5053 5054 if (macAddress == null) { 5055 loge("Did not find remoteAddress {" + ipAddress + "} in " + 5056 "/proc/net/arp"); 5057 } 5058 5059 } catch (FileNotFoundException e) { 5060 loge("Could not open /proc/net/arp to lookup mac address"); 5061 } catch (IOException e) { 5062 loge("Could not read /proc/net/arp to lookup mac address"); 5063 } finally { 5064 try { 5065 if (reader != null) { 5066 reader.close(); 5067 } 5068 } catch (IOException e) { 5069 // Do nothing 5070 } 5071 } 5072 return macAddress; 5073 5074 } 5075 5076 private class WifiNetworkFactory extends NetworkFactory { 5077 public WifiNetworkFactory(Looper l, Context c, String TAG, NetworkCapabilities f) { 5078 super(l, c, TAG, f); 5079 } 5080 5081 @Override 5082 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 5083 ++mConnectionRequests; 5084 } 5085 5086 @Override 5087 protected void releaseNetworkFor(NetworkRequest networkRequest) { 5088 --mConnectionRequests; 5089 } 5090 5091 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 5092 pw.println("mConnectionRequests " + mConnectionRequests); 5093 } 5094 5095 } 5096 5097 private class UntrustedWifiNetworkFactory extends NetworkFactory { 5098 private int mUntrustedReqCount; 5099 5100 public UntrustedWifiNetworkFactory(Looper l, Context c, String tag, NetworkCapabilities f) { 5101 super(l, c, tag, f); 5102 } 5103 5104 @Override 5105 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 5106 if (!networkRequest.networkCapabilities.hasCapability( 5107 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 5108 if (++mUntrustedReqCount == 1) { 5109 setAllowUntrustedConnections(true); 5110 } 5111 } 5112 } 5113 5114 @Override 5115 protected void releaseNetworkFor(NetworkRequest networkRequest) { 5116 if (!networkRequest.networkCapabilities.hasCapability( 5117 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 5118 if (--mUntrustedReqCount == 0) { 5119 setAllowUntrustedConnections(false); 5120 } 5121 } 5122 } 5123 5124 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 5125 pw.println("mUntrustedReqCount " + mUntrustedReqCount); 5126 } 5127 } 5128 5129 void maybeRegisterNetworkFactory() { 5130 if (mNetworkFactory == null) { 5131 checkAndSetConnectivityInstance(); 5132 if (mCm != null) { 5133 mNetworkFactory = new WifiNetworkFactory(getHandler().getLooper(), mContext, 5134 NETWORKTYPE, mNetworkCapabilitiesFilter); 5135 mNetworkFactory.setScoreFilter(60); 5136 mNetworkFactory.register(); 5137 5138 // We can't filter untrusted network in the capabilities filter because a trusted 5139 // network would still satisfy a request that accepts untrusted ones. 5140 mUntrustedNetworkFactory = new UntrustedWifiNetworkFactory(getHandler().getLooper(), 5141 mContext, NETWORKTYPE_UNTRUSTED, mNetworkCapabilitiesFilter); 5142 mUntrustedNetworkFactory.setScoreFilter(Integer.MAX_VALUE); 5143 mUntrustedNetworkFactory.register(); 5144 } 5145 } 5146 } 5147 5148 /******************************************************** 5149 * HSM states 5150 *******************************************************/ 5151 5152 class DefaultState extends State { 5153 @Override 5154 public boolean processMessage(Message message) { 5155 logStateAndMessage(message, this); 5156 5157 switch (message.what) { 5158 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 5159 AsyncChannel ac = (AsyncChannel) message.obj; 5160 if (ac == mWifiP2pChannel) { 5161 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 5162 mWifiP2pChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 5163 } else { 5164 loge("WifiP2pService connection failure, error=" + message.arg1); 5165 } 5166 } else { 5167 loge("got HALF_CONNECTED for unknown channel"); 5168 } 5169 break; 5170 } 5171 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 5172 AsyncChannel ac = (AsyncChannel) message.obj; 5173 if (ac == mWifiP2pChannel) { 5174 loge("WifiP2pService channel lost, message.arg1 =" + message.arg1); 5175 //TODO: Re-establish connection to state machine after a delay 5176 // mWifiP2pChannel.connect(mContext, getHandler(), 5177 // mWifiP2pManager.getMessenger()); 5178 } 5179 break; 5180 } 5181 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 5182 mBluetoothConnectionActive = (message.arg1 != 5183 BluetoothAdapter.STATE_DISCONNECTED); 5184 break; 5185 /* Synchronous call returns */ 5186 case CMD_PING_SUPPLICANT: 5187 case CMD_ENABLE_NETWORK: 5188 case CMD_ADD_OR_UPDATE_NETWORK: 5189 case CMD_REMOVE_NETWORK: 5190 case CMD_SAVE_CONFIG: 5191 replyToMessage(message, message.what, FAILURE); 5192 break; 5193 case CMD_GET_CAPABILITY_FREQ: 5194 replyToMessage(message, message.what, null); 5195 break; 5196 case CMD_GET_CONFIGURED_NETWORKS: 5197 replyToMessage(message, message.what, (List<WifiConfiguration>) null); 5198 break; 5199 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 5200 replyToMessage(message, message.what, (List<WifiConfiguration>) null); 5201 break; 5202 case CMD_ENABLE_RSSI_POLL: 5203 mEnableRssiPolling = (message.arg1 == 1); 5204 break; 5205 case CMD_SET_HIGH_PERF_MODE: 5206 if (message.arg1 == 1) { 5207 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false); 5208 } else { 5209 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true); 5210 } 5211 break; 5212 case CMD_BOOT_COMPLETED: 5213 maybeRegisterNetworkFactory(); 5214 break; 5215 case CMD_SCREEN_STATE_CHANGED: 5216 handleScreenStateChanged(message.arg1 != 0); 5217 break; 5218 /* Discard */ 5219 case CMD_START_SCAN: 5220 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5221 break; 5222 case CMD_START_SUPPLICANT: 5223 case CMD_STOP_SUPPLICANT: 5224 case CMD_STOP_SUPPLICANT_FAILED: 5225 case CMD_START_DRIVER: 5226 case CMD_STOP_DRIVER: 5227 case CMD_DRIVER_START_TIMED_OUT: 5228 case CMD_START_AP: 5229 case CMD_START_AP_FAILURE: 5230 case CMD_STOP_AP: 5231 case CMD_AP_STOPPED: 5232 case CMD_DISCONNECT: 5233 case CMD_RECONNECT: 5234 case CMD_REASSOCIATE: 5235 case CMD_RELOAD_TLS_AND_RECONNECT: 5236 case WifiMonitor.SUP_CONNECTION_EVENT: 5237 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5238 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5239 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5240 case WifiMonitor.SCAN_RESULTS_EVENT: 5241 case WifiMonitor.SCAN_FAILED_EVENT: 5242 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5243 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 5244 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 5245 case WifiMonitor.WPS_OVERLAP_EVENT: 5246 case CMD_BLACKLIST_NETWORK: 5247 case CMD_CLEAR_BLACKLIST: 5248 case CMD_SET_OPERATIONAL_MODE: 5249 case CMD_SET_FREQUENCY_BAND: 5250 case CMD_RSSI_POLL: 5251 case CMD_ENABLE_ALL_NETWORKS: 5252 case DhcpClient.CMD_PRE_DHCP_ACTION: 5253 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 5254 case DhcpClient.CMD_POST_DHCP_ACTION: 5255 case CMD_NO_NETWORKS_PERIODIC_SCAN: 5256 case CMD_DISABLE_P2P_RSP: 5257 case WifiMonitor.SUP_REQUEST_IDENTITY: 5258 case CMD_TEST_NETWORK_DISCONNECT: 5259 case CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER: 5260 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 5261 case CMD_TARGET_BSSID: 5262 case CMD_AUTO_CONNECT: 5263 case CMD_AUTO_ROAM: 5264 case CMD_AUTO_SAVE_NETWORK: 5265 case CMD_ASSOCIATED_BSSID: 5266 case CMD_UNWANTED_NETWORK: 5267 case CMD_DISCONNECTING_WATCHDOG_TIMER: 5268 case CMD_ROAM_WATCHDOG_TIMER: 5269 case CMD_DISABLE_EPHEMERAL_NETWORK: 5270 case CMD_RESTART_AUTOJOIN_OFFLOAD: 5271 case CMD_STARTED_PNO_DBG: 5272 case CMD_STARTED_GSCAN_DBG: 5273 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 5274 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5275 break; 5276 case CMD_SET_COUNTRY_CODE: 5277 String country = (String) message.obj; 5278 final boolean persist = (message.arg2 == 1); 5279 final int sequence = message.arg1; 5280 if (sequence != mCountryCodeSequence.get()) { 5281 if (DBG) log("set country code ignored due to sequnce num"); 5282 break; 5283 } 5284 5285 if (persist) { 5286 country = country.toUpperCase(Locale.ROOT); 5287 if (DBG) log("set country code " + (country == null ? "(null)" : country)); 5288 Settings.Global.putString(mContext.getContentResolver(), 5289 Settings.Global.WIFI_COUNTRY_CODE, 5290 country == null ? "" : country); 5291 } 5292 5293 break; 5294 case CMD_SET_SUSPEND_OPT_ENABLED: 5295 if (message.arg1 == 1) { 5296 mSuspendWakeLock.release(); 5297 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true); 5298 } else { 5299 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false); 5300 } 5301 break; 5302 case WifiMonitor.DRIVER_HUNG_EVENT: 5303 setSupplicantRunning(false); 5304 setSupplicantRunning(true); 5305 break; 5306 case WifiManager.CONNECT_NETWORK: 5307 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5308 WifiManager.BUSY); 5309 break; 5310 case WifiManager.FORGET_NETWORK: 5311 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 5312 WifiManager.BUSY); 5313 break; 5314 case WifiManager.SAVE_NETWORK: 5315 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5316 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5317 WifiManager.BUSY); 5318 break; 5319 case WifiManager.START_WPS: 5320 replyToMessage(message, WifiManager.WPS_FAILED, 5321 WifiManager.BUSY); 5322 break; 5323 case WifiManager.CANCEL_WPS: 5324 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, 5325 WifiManager.BUSY); 5326 break; 5327 case WifiManager.DISABLE_NETWORK: 5328 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 5329 WifiManager.BUSY); 5330 break; 5331 case WifiManager.RSSI_PKTCNT_FETCH: 5332 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED, 5333 WifiManager.BUSY); 5334 break; 5335 case CMD_GET_SUPPORTED_FEATURES: 5336 int featureSet = mWifiNative.getSupportedFeatureSet(); 5337 replyToMessage(message, message.what, featureSet); 5338 break; 5339 case CMD_FIRMWARE_ALERT: 5340 if (mWifiLogger != null) { 5341 byte[] buffer = (byte[])message.obj; 5342 mWifiLogger.captureAlertData(message.arg1, buffer); 5343 } 5344 break; 5345 case CMD_GET_LINK_LAYER_STATS: 5346 // Not supported hence reply with error message 5347 replyToMessage(message, message.what, null); 5348 break; 5349 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 5350 NetworkInfo info = (NetworkInfo) message.obj; 5351 mP2pConnected.set(info.isConnected()); 5352 break; 5353 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 5354 mTemporarilyDisconnectWifi = (message.arg1 == 1); 5355 replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 5356 break; 5357 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 5358 case CMD_UPDATE_LINKPROPERTIES: 5359 updateLinkProperties((LinkProperties) message.obj); 5360 break; 5361 case CMD_GET_MATCHING_CONFIG: 5362 replyToMessage(message, message.what); 5363 break; 5364 case CMD_IP_CONFIGURATION_SUCCESSFUL: 5365 case CMD_IP_CONFIGURATION_LOST: 5366 case CMD_IP_REACHABILITY_LOST: 5367 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5368 break; 5369 case CMD_GET_CONNECTION_STATISTICS: 5370 replyToMessage(message, message.what, mWifiConnectionStatistics); 5371 break; 5372 case CMD_REMOVE_APP_CONFIGURATIONS: 5373 deferMessage(message); 5374 break; 5375 case CMD_REMOVE_USER_CONFIGURATIONS: 5376 deferMessage(message); 5377 break; 5378 case CMD_START_IP_PACKET_OFFLOAD: 5379 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 5380 message.arg1, 5381 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 5382 break; 5383 case CMD_STOP_IP_PACKET_OFFLOAD: 5384 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 5385 message.arg1, 5386 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 5387 break; 5388 case CMD_START_RSSI_MONITORING_OFFLOAD: 5389 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5390 break; 5391 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 5392 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5393 break; 5394 case CMD_USER_SWITCH: 5395 mCurrentUserId = message.arg1; 5396 mWifiConfigManager.handleUserSwitch(); 5397 break; 5398 case CMD_ADD_PASSPOINT_MO: 5399 case CMD_MODIFY_PASSPOINT_MO: 5400 case CMD_QUERY_OSU_ICON: 5401 case CMD_MATCH_PROVIDER_NETWORK: 5402 /* reply with arg1 = 0 - it returns API failure to the calling app 5403 * (message.what is not looked at) 5404 */ 5405 replyToMessage(message, message.what); 5406 break; 5407 default: 5408 loge("Error! unhandled message" + message); 5409 break; 5410 } 5411 return HANDLED; 5412 } 5413 } 5414 5415 class InitialState extends State { 5416 @Override 5417 public void enter() { 5418 mWifiNative.stopHal(); 5419 mWifiNative.unloadDriver(); 5420 if (mWifiP2pChannel == null) { 5421 mWifiP2pChannel = new AsyncChannel(); 5422 mWifiP2pChannel.connect(mContext, getHandler(), 5423 mWifiP2pServiceImpl.getP2pStateMachineMessenger()); 5424 } 5425 5426 if (mWifiApConfigStore == null) { 5427 mWifiApConfigStore = mFacade.makeApConfigStore(mContext); 5428 } 5429 5430 if (mWifiConfigManager.enableHalBasedPno.get()) { 5431 // make sure developer Settings are in sync with the config option 5432 mHalBasedPnoEnableInDevSettings = true; 5433 } 5434 } 5435 @Override 5436 public boolean processMessage(Message message) { 5437 logStateAndMessage(message, this); 5438 switch (message.what) { 5439 case CMD_START_SUPPLICANT: 5440 if (mWifiNative.loadDriver()) { 5441 try { 5442 mNwService.wifiFirmwareReload(mInterfaceName, "STA"); 5443 } catch (Exception e) { 5444 loge("Failed to reload STA firmware " + e); 5445 // Continue 5446 } 5447 5448 try { 5449 // A runtime crash can leave the interface up and 5450 // IP addresses configured, and this affects 5451 // connectivity when supplicant starts up. 5452 // Ensure interface is down and we have no IP 5453 // addresses before a supplicant start. 5454 mNwService.setInterfaceDown(mInterfaceName); 5455 mNwService.clearInterfaceAddresses(mInterfaceName); 5456 5457 // Set privacy extensions 5458 mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true); 5459 5460 // IPv6 is enabled only as long as access point is connected since: 5461 // - IPv6 addresses and routes stick around after disconnection 5462 // - kernel is unaware when connected and fails to start IPv6 negotiation 5463 // - kernel can start autoconfiguration when 802.1x is not complete 5464 mNwService.disableIpv6(mInterfaceName); 5465 } catch (RemoteException re) { 5466 loge("Unable to change interface settings: " + re); 5467 } catch (IllegalStateException ie) { 5468 loge("Unable to change interface settings: " + ie); 5469 } 5470 5471 /* Stop a running supplicant after a runtime restart 5472 * Avoids issues with drivers that do not handle interface down 5473 * on a running supplicant properly. 5474 */ 5475 mWifiMonitor.killSupplicant(mP2pSupported); 5476 5477 if (mWifiNative.startHal() == false) { 5478 /* starting HAL is optional */ 5479 loge("Failed to start HAL"); 5480 } 5481 5482 if (mWifiNative.startSupplicant(mP2pSupported)) { 5483 setWifiState(WIFI_STATE_ENABLING); 5484 if (DBG) log("Supplicant start successful"); 5485 mWifiMonitor.startMonitoring(mInterfaceName); 5486 transitionTo(mSupplicantStartingState); 5487 } else { 5488 loge("Failed to start supplicant!"); 5489 } 5490 } else { 5491 loge("Failed to load driver"); 5492 } 5493 break; 5494 case CMD_START_AP: 5495 if (setupDriverForSoftAp()) { 5496 transitionTo(mSoftApState); 5497 } else { 5498 setWifiApState(WIFI_AP_STATE_FAILED, 5499 WifiManager.SAP_START_FAILURE_GENERAL); 5500 /** 5501 * Transition to InitialState (current state) to reset the 5502 * driver/HAL back to the initial state. 5503 */ 5504 transitionTo(mInitialState); 5505 } 5506 break; 5507 default: 5508 return NOT_HANDLED; 5509 } 5510 return HANDLED; 5511 } 5512 } 5513 5514 class SupplicantStartingState extends State { 5515 private void initializeWpsDetails() { 5516 String detail; 5517 detail = SystemProperties.get("ro.product.name", ""); 5518 if (!mWifiNative.setDeviceName(detail)) { 5519 loge("Failed to set device name " + detail); 5520 } 5521 detail = SystemProperties.get("ro.product.manufacturer", ""); 5522 if (!mWifiNative.setManufacturer(detail)) { 5523 loge("Failed to set manufacturer " + detail); 5524 } 5525 detail = SystemProperties.get("ro.product.model", ""); 5526 if (!mWifiNative.setModelName(detail)) { 5527 loge("Failed to set model name " + detail); 5528 } 5529 detail = SystemProperties.get("ro.product.model", ""); 5530 if (!mWifiNative.setModelNumber(detail)) { 5531 loge("Failed to set model number " + detail); 5532 } 5533 detail = SystemProperties.get("ro.serialno", ""); 5534 if (!mWifiNative.setSerialNumber(detail)) { 5535 loge("Failed to set serial number " + detail); 5536 } 5537 if (!mWifiNative.setConfigMethods("physical_display virtual_push_button")) { 5538 loge("Failed to set WPS config methods"); 5539 } 5540 if (!mWifiNative.setDeviceType(mPrimaryDeviceType)) { 5541 loge("Failed to set primary device type " + mPrimaryDeviceType); 5542 } 5543 } 5544 5545 @Override 5546 public boolean processMessage(Message message) { 5547 logStateAndMessage(message, this); 5548 5549 switch(message.what) { 5550 case WifiMonitor.SUP_CONNECTION_EVENT: 5551 if (DBG) log("Supplicant connection established"); 5552 setWifiState(WIFI_STATE_ENABLED); 5553 mSupplicantRestartCount = 0; 5554 /* Reset the supplicant state to indicate the supplicant 5555 * state is not known at this time */ 5556 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 5557 /* Initialize data structures */ 5558 mLastBssid = null; 5559 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 5560 mLastSignalLevel = -1; 5561 5562 mWifiInfo.setMacAddress(mWifiNative.getMacAddress()); 5563 /* set frequency band of operation */ 5564 setFrequencyBand(); 5565 mWifiNative.enableSaveConfig(); 5566 mWifiConfigManager.loadAndEnableAllNetworks(); 5567 if (mWifiConfigManager.enableVerboseLogging.get() > 0) { 5568 enableVerboseLogging(mWifiConfigManager.enableVerboseLogging.get()); 5569 } 5570 initializeWpsDetails(); 5571 5572 sendSupplicantConnectionChangedBroadcast(true); 5573 transitionTo(mDriverStartedState); 5574 break; 5575 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5576 if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { 5577 loge("Failed to setup control channel, restart supplicant"); 5578 mWifiMonitor.killSupplicant(mP2pSupported); 5579 transitionTo(mInitialState); 5580 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 5581 } else { 5582 loge("Failed " + mSupplicantRestartCount + 5583 " times to start supplicant, unload driver"); 5584 mSupplicantRestartCount = 0; 5585 setWifiState(WIFI_STATE_UNKNOWN); 5586 transitionTo(mInitialState); 5587 } 5588 break; 5589 case CMD_START_SUPPLICANT: 5590 case CMD_STOP_SUPPLICANT: 5591 case CMD_START_AP: 5592 case CMD_STOP_AP: 5593 case CMD_START_DRIVER: 5594 case CMD_STOP_DRIVER: 5595 case CMD_SET_OPERATIONAL_MODE: 5596 case CMD_SET_COUNTRY_CODE: 5597 case CMD_SET_FREQUENCY_BAND: 5598 case CMD_START_PACKET_FILTERING: 5599 case CMD_STOP_PACKET_FILTERING: 5600 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5601 deferMessage(message); 5602 break; 5603 default: 5604 return NOT_HANDLED; 5605 } 5606 return HANDLED; 5607 } 5608 } 5609 5610 class SupplicantStartedState extends State { 5611 @Override 5612 public void enter() { 5613 /* Wifi is available as long as we have a connection to supplicant */ 5614 mNetworkInfo.setIsAvailable(true); 5615 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 5616 5617 int defaultInterval = mContext.getResources().getInteger( 5618 R.integer.config_wifi_supplicant_scan_interval); 5619 5620 mSupplicantScanIntervalMs = mFacade.getLongSetting(mContext, 5621 Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS, 5622 defaultInterval); 5623 5624 mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000); 5625 mWifiNative.setExternalSim(true); 5626 5627 /* turn on use of DFS channels */ 5628 mWifiNative.setDfsFlag(true); 5629 5630 /* set country code */ 5631 initializeCountryCode(); 5632 5633 setRandomMacOui(); 5634 mWifiNative.enableAutoConnect(false); 5635 } 5636 5637 @Override 5638 public boolean processMessage(Message message) { 5639 logStateAndMessage(message, this); 5640 5641 switch(message.what) { 5642 case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */ 5643 if (mP2pSupported) { 5644 transitionTo(mWaitForP2pDisableState); 5645 } else { 5646 transitionTo(mSupplicantStoppingState); 5647 } 5648 break; 5649 case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ 5650 loge("Connection lost, restart supplicant"); 5651 handleSupplicantConnectionLoss(true); 5652 handleNetworkDisconnect(); 5653 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 5654 if (mP2pSupported) { 5655 transitionTo(mWaitForP2pDisableState); 5656 } else { 5657 transitionTo(mInitialState); 5658 } 5659 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 5660 break; 5661 case WifiMonitor.SCAN_RESULTS_EVENT: 5662 case WifiMonitor.SCAN_FAILED_EVENT: 5663 maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered 5664 noteScanEnd(); 5665 setScanResults(); 5666 if (mIsFullScanOngoing || mSendScanResultsBroadcast) { 5667 /* Just updated results from full scan, let apps know about this */ 5668 boolean scanSucceeded = message.what == WifiMonitor.SCAN_RESULTS_EVENT; 5669 sendScanResultsAvailableBroadcast(scanSucceeded); 5670 } 5671 mSendScanResultsBroadcast = false; 5672 mIsScanOngoing = false; 5673 mIsFullScanOngoing = false; 5674 if (mBufferedScanMsg.size() > 0) 5675 sendMessage(mBufferedScanMsg.remove()); 5676 break; 5677 case CMD_PING_SUPPLICANT: 5678 boolean ok = mWifiNative.ping(); 5679 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 5680 break; 5681 case CMD_GET_CAPABILITY_FREQ: 5682 String freqs = mWifiNative.getFreqCapability(); 5683 replyToMessage(message, message.what, freqs); 5684 break; 5685 case CMD_START_AP: 5686 /* Cannot start soft AP while in client mode */ 5687 loge("Failed to start soft AP with a running supplicant"); 5688 setWifiApState(WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL); 5689 break; 5690 case CMD_SET_OPERATIONAL_MODE: 5691 mOperationalMode = message.arg1; 5692 mWifiConfigManager. 5693 setAndEnableLastSelectedConfiguration( 5694 WifiConfiguration.INVALID_NETWORK_ID); 5695 break; 5696 case CMD_TARGET_BSSID: 5697 // Trying to associate to this BSSID 5698 if (message.obj != null) { 5699 mTargetRoamBSSID = (String) message.obj; 5700 } 5701 break; 5702 case CMD_GET_LINK_LAYER_STATS: 5703 WifiLinkLayerStats stats = getWifiLinkLayerStats(DBG); 5704 if (stats == null) { 5705 // When firmware doesnt support link layer stats, return an empty object 5706 stats = new WifiLinkLayerStats(); 5707 } 5708 replyToMessage(message, message.what, stats); 5709 break; 5710 case CMD_SET_COUNTRY_CODE: 5711 String country = (String) message.obj; 5712 final boolean persist = (message.arg2 == 1); 5713 final int sequence = message.arg1; 5714 if (sequence != mCountryCodeSequence.get()) { 5715 if (DBG) log("set country code ignored due to sequnce num"); 5716 break; 5717 } 5718 5719 country = country.toUpperCase(Locale.ROOT); 5720 5721 if (DBG) log("set country code " + (country == null ? "(null)" : country)); 5722 5723 if (!TextUtils.equals(mDriverSetCountryCode, country)) { 5724 if (mWifiNative.setCountryCode(country)) { 5725 mDriverSetCountryCode = country; 5726 } else { 5727 loge("Failed to set country code " + country); 5728 } 5729 } 5730 5731 if (persist) { 5732 Settings.Global.putString(mContext.getContentResolver(), 5733 Settings.Global.WIFI_COUNTRY_CODE, 5734 country == null ? "" : country); 5735 } 5736 5737 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.SET_COUNTRY_CODE, country); 5738 break; 5739 case CMD_RESET_SIM_NETWORKS: 5740 log("resetting EAP-SIM/AKA/AKA' networks since SIM was removed"); 5741 mWifiConfigManager.resetSimNetworks(); 5742 break; 5743 default: 5744 return NOT_HANDLED; 5745 } 5746 return HANDLED; 5747 } 5748 5749 @Override 5750 public void exit() { 5751 mNetworkInfo.setIsAvailable(false); 5752 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 5753 } 5754 } 5755 5756 class SupplicantStoppingState extends State { 5757 @Override 5758 public void enter() { 5759 /* Send any reset commands to supplicant before shutting it down */ 5760 handleNetworkDisconnect(); 5761 5762 String suppState = System.getProperty("init.svc.wpa_supplicant"); 5763 if (suppState == null) suppState = "unknown"; 5764 String p2pSuppState = System.getProperty("init.svc.p2p_supplicant"); 5765 if (p2pSuppState == null) p2pSuppState = "unknown"; 5766 5767 logd("SupplicantStoppingState: stopSupplicant " 5768 + " init.svc.wpa_supplicant=" + suppState 5769 + " init.svc.p2p_supplicant=" + p2pSuppState); 5770 mWifiMonitor.stopSupplicant(); 5771 5772 /* Send ourselves a delayed message to indicate failure after a wait time */ 5773 sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED, 5774 ++mSupplicantStopFailureToken, 0), SUPPLICANT_RESTART_INTERVAL_MSECS); 5775 setWifiState(WIFI_STATE_DISABLING); 5776 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 5777 } 5778 @Override 5779 public boolean processMessage(Message message) { 5780 logStateAndMessage(message, this); 5781 5782 switch(message.what) { 5783 case WifiMonitor.SUP_CONNECTION_EVENT: 5784 loge("Supplicant connection received while stopping"); 5785 break; 5786 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5787 if (DBG) log("Supplicant connection lost"); 5788 handleSupplicantConnectionLoss(false); 5789 transitionTo(mInitialState); 5790 break; 5791 case CMD_STOP_SUPPLICANT_FAILED: 5792 if (message.arg1 == mSupplicantStopFailureToken) { 5793 loge("Timed out on a supplicant stop, kill and proceed"); 5794 handleSupplicantConnectionLoss(true); 5795 transitionTo(mInitialState); 5796 } 5797 break; 5798 case CMD_START_SUPPLICANT: 5799 case CMD_STOP_SUPPLICANT: 5800 case CMD_START_AP: 5801 case CMD_STOP_AP: 5802 case CMD_START_DRIVER: 5803 case CMD_STOP_DRIVER: 5804 case CMD_SET_OPERATIONAL_MODE: 5805 case CMD_SET_COUNTRY_CODE: 5806 case CMD_SET_FREQUENCY_BAND: 5807 case CMD_START_PACKET_FILTERING: 5808 case CMD_STOP_PACKET_FILTERING: 5809 deferMessage(message); 5810 break; 5811 default: 5812 return NOT_HANDLED; 5813 } 5814 return HANDLED; 5815 } 5816 } 5817 5818 class DriverStartingState extends State { 5819 private int mTries; 5820 @Override 5821 public void enter() { 5822 mTries = 1; 5823 /* Send ourselves a delayed message to start driver a second time */ 5824 sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT, 5825 ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS); 5826 } 5827 @Override 5828 public boolean processMessage(Message message) { 5829 logStateAndMessage(message, this); 5830 5831 switch(message.what) { 5832 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5833 SupplicantState state = handleSupplicantStateChange(message); 5834 /* If suplicant is exiting out of INTERFACE_DISABLED state into 5835 * a state that indicates driver has started, it is ready to 5836 * receive driver commands 5837 */ 5838 if (SupplicantState.isDriverActive(state)) { 5839 transitionTo(mDriverStartedState); 5840 } 5841 break; 5842 case CMD_DRIVER_START_TIMED_OUT: 5843 if (message.arg1 == mDriverStartToken) { 5844 if (mTries >= 2) { 5845 loge("Failed to start driver after " + mTries); 5846 transitionTo(mDriverStoppedState); 5847 } else { 5848 loge("Driver start failed, retrying"); 5849 mWakeLock.acquire(); 5850 mWifiNative.startDriver(); 5851 mWakeLock.release(); 5852 5853 ++mTries; 5854 /* Send ourselves a delayed message to start driver again */ 5855 sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT, 5856 ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS); 5857 } 5858 } 5859 break; 5860 /* Queue driver commands & connection events */ 5861 case CMD_START_DRIVER: 5862 case CMD_STOP_DRIVER: 5863 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5864 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5865 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 5866 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 5867 case WifiMonitor.WPS_OVERLAP_EVENT: 5868 case CMD_SET_COUNTRY_CODE: 5869 case CMD_SET_FREQUENCY_BAND: 5870 case CMD_START_PACKET_FILTERING: 5871 case CMD_STOP_PACKET_FILTERING: 5872 case CMD_START_SCAN: 5873 case CMD_DISCONNECT: 5874 case CMD_REASSOCIATE: 5875 case CMD_RECONNECT: 5876 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5877 deferMessage(message); 5878 break; 5879 case WifiMonitor.SCAN_RESULTS_EVENT: 5880 case WifiMonitor.SCAN_FAILED_EVENT: 5881 // Loose scan results obtained in Driver Starting state, they can only confuse 5882 // the state machine 5883 break; 5884 default: 5885 return NOT_HANDLED; 5886 } 5887 return HANDLED; 5888 } 5889 } 5890 5891 class DriverStartedState extends State { 5892 @Override 5893 public void enter() { 5894 5895 if (PDBG) { 5896 logd("DriverStartedState enter"); 5897 } 5898 5899 mWifiLogger.startLogging(mVerboseLoggingLevel > 0); 5900 mIsRunning = true; 5901 updateBatteryWorkSource(null); 5902 /** 5903 * Enable bluetooth coexistence scan mode when bluetooth connection is active. 5904 * When this mode is on, some of the low-level scan parameters used by the 5905 * driver are changed to reduce interference with bluetooth 5906 */ 5907 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 5908 /* initialize network state */ 5909 setNetworkDetailedState(DetailedState.DISCONNECTED); 5910 5911 /* Remove any filtering on Multicast v6 at start */ 5912 mWifiNative.stopFilteringMulticastV6Packets(); 5913 5914 /* Reset Multicast v4 filtering state */ 5915 if (mFilteringMulticastV4Packets.get()) { 5916 mWifiNative.startFilteringMulticastV4Packets(); 5917 } else { 5918 mWifiNative.stopFilteringMulticastV4Packets(); 5919 } 5920 5921 if (mOperationalMode != CONNECT_MODE) { 5922 mWifiNative.disconnect(); 5923 mWifiConfigManager.disableAllNetworks(); 5924 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 5925 setWifiState(WIFI_STATE_DISABLED); 5926 } 5927 transitionTo(mScanModeState); 5928 } else { 5929 5930 // Status pulls in the current supplicant state and network connection state 5931 // events over the monitor connection. This helps framework sync up with 5932 // current supplicant state 5933 // TODO: actually check th supplicant status string and make sure the supplicant 5934 // is in disconnecte4d state. 5935 mWifiNative.status(); 5936 // Transitioning to Disconnected state will trigger a scan and subsequently AutoJoin 5937 transitionTo(mDisconnectedState); 5938 transitionTo(mDisconnectedState); 5939 } 5940 5941 // We may have missed screen update at boot 5942 if (mScreenBroadcastReceived.get() == false) { 5943 PowerManager powerManager = (PowerManager)mContext.getSystemService( 5944 Context.POWER_SERVICE); 5945 handleScreenStateChanged(powerManager.isScreenOn()); 5946 } else { 5947 // Set the right suspend mode settings 5948 mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0 5949 && mUserWantsSuspendOpt.get()); 5950 } 5951 mWifiNative.setPowerSave(true); 5952 5953 if (mP2pSupported) { 5954 if (mOperationalMode == CONNECT_MODE) { 5955 mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P); 5956 } else { 5957 // P2P statemachine starts in disabled state, and is not enabled until 5958 // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to 5959 // keep it disabled. 5960 } 5961 } 5962 5963 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 5964 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5965 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED); 5966 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5967 5968 mHalFeatureSet = mWifiNative.getSupportedFeatureSet(); 5969 if ((mHalFeatureSet & WifiManager.WIFI_FEATURE_HAL_EPNO) 5970 == WifiManager.WIFI_FEATURE_HAL_EPNO) { 5971 mHalBasedPnoDriverSupported = true; 5972 } 5973 5974 // Enable link layer stats gathering 5975 mWifiNative.setWifiLinkLayerStats("wlan0", 1); 5976 5977 if (PDBG) { 5978 logd("Driverstarted State enter done, epno=" + mHalBasedPnoDriverSupported 5979 + " feature=" + mHalFeatureSet); 5980 } 5981 } 5982 5983 @Override 5984 public boolean processMessage(Message message) { 5985 logStateAndMessage(message, this); 5986 5987 switch(message.what) { 5988 case CMD_START_SCAN: 5989 handleScanRequest(message); 5990 break; 5991 case CMD_SET_FREQUENCY_BAND: 5992 int band = message.arg1; 5993 if (DBG) log("set frequency band " + band); 5994 if (mWifiNative.setBand(band)) { 5995 5996 if (PDBG) logd("did set frequency band " + band); 5997 5998 mFrequencyBand.set(band); 5999 // Flush old data - like scan results 6000 mWifiNative.bssFlush(); 6001 6002 if (PDBG) logd("done set frequency band " + band); 6003 6004 } else { 6005 loge("Failed to set frequency band " + band); 6006 } 6007 break; 6008 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 6009 mBluetoothConnectionActive = (message.arg1 != 6010 BluetoothAdapter.STATE_DISCONNECTED); 6011 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 6012 break; 6013 case CMD_STOP_DRIVER: 6014 int mode = message.arg1; 6015 6016 log("stop driver"); 6017 mWifiConfigManager.disableAllNetworks(); 6018 6019 if (getCurrentState() != mDisconnectedState) { 6020 mWifiNative.disconnect(); 6021 handleNetworkDisconnect(); 6022 } 6023 mWakeLock.acquire(); 6024 mWifiNative.stopDriver(); 6025 mWakeLock.release(); 6026 if (mP2pSupported) { 6027 transitionTo(mWaitForP2pDisableState); 6028 } else { 6029 transitionTo(mDriverStoppingState); 6030 } 6031 break; 6032 case CMD_START_DRIVER: 6033 if (mOperationalMode == CONNECT_MODE) { 6034 mWifiConfigManager.enableAllNetworks(); 6035 } 6036 break; 6037 case CMD_START_PACKET_FILTERING: 6038 if (message.arg1 == MULTICAST_V6) { 6039 mWifiNative.startFilteringMulticastV6Packets(); 6040 } else if (message.arg1 == MULTICAST_V4) { 6041 mWifiNative.startFilteringMulticastV4Packets(); 6042 } else { 6043 loge("Illegal arugments to CMD_START_PACKET_FILTERING"); 6044 } 6045 break; 6046 case CMD_STOP_PACKET_FILTERING: 6047 if (message.arg1 == MULTICAST_V6) { 6048 mWifiNative.stopFilteringMulticastV6Packets(); 6049 } else if (message.arg1 == MULTICAST_V4) { 6050 mWifiNative.stopFilteringMulticastV4Packets(); 6051 } else { 6052 loge("Illegal arugments to CMD_STOP_PACKET_FILTERING"); 6053 } 6054 break; 6055 case CMD_SET_SUSPEND_OPT_ENABLED: 6056 if (message.arg1 == 1) { 6057 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); 6058 mSuspendWakeLock.release(); 6059 } else { 6060 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); 6061 } 6062 break; 6063 case CMD_SET_HIGH_PERF_MODE: 6064 if (message.arg1 == 1) { 6065 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); 6066 } else { 6067 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); 6068 } 6069 break; 6070 case CMD_ENABLE_TDLS: 6071 if (message.obj != null) { 6072 String remoteAddress = (String) message.obj; 6073 boolean enable = (message.arg1 == 1); 6074 mWifiNative.startTdls(remoteAddress, enable); 6075 } 6076 break; 6077 case WifiMonitor.ANQP_DONE_EVENT: 6078 mWifiConfigManager.notifyANQPDone((Long) message.obj, message.arg1 != 0); 6079 break; 6080 case CMD_STOP_IP_PACKET_OFFLOAD: { 6081 int slot = message.arg1; 6082 int ret = stopWifiIPPacketOffload(slot); 6083 if (mNetworkAgent != null) { 6084 mNetworkAgent.onPacketKeepaliveEvent(slot, ret); 6085 } 6086 break; 6087 } 6088 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 6089 mWifiConfigManager.notifyIconReceived((IconEvent) message.obj); 6090 break; 6091 case WifiMonitor.HS20_REMEDIATION_EVENT: 6092 mWifiConfigManager.wnmFrameReceived((WnmData) message.obj); 6093 break; 6094 default: 6095 return NOT_HANDLED; 6096 } 6097 return HANDLED; 6098 } 6099 @Override 6100 public void exit() { 6101 6102 mWifiLogger.stopLogging(); 6103 6104 mIsRunning = false; 6105 updateBatteryWorkSource(null); 6106 mScanResults = new ArrayList<>(); 6107 6108 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 6109 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 6110 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); 6111 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 6112 noteScanEnd(); // wrap up any pending request. 6113 mBufferedScanMsg.clear(); 6114 } 6115 } 6116 6117 class WaitForP2pDisableState extends State { 6118 private State mTransitionToState; 6119 @Override 6120 public void enter() { 6121 switch (getCurrentMessage().what) { 6122 case WifiMonitor.SUP_DISCONNECTION_EVENT: 6123 mTransitionToState = mInitialState; 6124 break; 6125 case CMD_STOP_DRIVER: 6126 mTransitionToState = mDriverStoppingState; 6127 break; 6128 case CMD_STOP_SUPPLICANT: 6129 mTransitionToState = mSupplicantStoppingState; 6130 break; 6131 default: 6132 mTransitionToState = mDriverStoppingState; 6133 break; 6134 } 6135 mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ); 6136 } 6137 @Override 6138 public boolean processMessage(Message message) { 6139 logStateAndMessage(message, this); 6140 6141 switch(message.what) { 6142 case WifiStateMachine.CMD_DISABLE_P2P_RSP: 6143 transitionTo(mTransitionToState); 6144 break; 6145 /* Defer wifi start/shut and driver commands */ 6146 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6147 case CMD_START_SUPPLICANT: 6148 case CMD_STOP_SUPPLICANT: 6149 case CMD_START_AP: 6150 case CMD_STOP_AP: 6151 case CMD_START_DRIVER: 6152 case CMD_STOP_DRIVER: 6153 case CMD_SET_OPERATIONAL_MODE: 6154 case CMD_SET_COUNTRY_CODE: 6155 case CMD_SET_FREQUENCY_BAND: 6156 case CMD_START_PACKET_FILTERING: 6157 case CMD_STOP_PACKET_FILTERING: 6158 case CMD_START_SCAN: 6159 case CMD_DISCONNECT: 6160 case CMD_REASSOCIATE: 6161 case CMD_RECONNECT: 6162 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 6163 deferMessage(message); 6164 break; 6165 default: 6166 return NOT_HANDLED; 6167 } 6168 return HANDLED; 6169 } 6170 } 6171 6172 class DriverStoppingState extends State { 6173 @Override 6174 public boolean processMessage(Message message) { 6175 logStateAndMessage(message, this); 6176 6177 switch(message.what) { 6178 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6179 SupplicantState state = handleSupplicantStateChange(message); 6180 if (state == SupplicantState.INTERFACE_DISABLED) { 6181 transitionTo(mDriverStoppedState); 6182 } 6183 break; 6184 /* Queue driver commands */ 6185 case CMD_START_DRIVER: 6186 case CMD_STOP_DRIVER: 6187 case CMD_SET_COUNTRY_CODE: 6188 case CMD_SET_FREQUENCY_BAND: 6189 case CMD_START_PACKET_FILTERING: 6190 case CMD_STOP_PACKET_FILTERING: 6191 case CMD_START_SCAN: 6192 case CMD_DISCONNECT: 6193 case CMD_REASSOCIATE: 6194 case CMD_RECONNECT: 6195 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 6196 deferMessage(message); 6197 break; 6198 default: 6199 return NOT_HANDLED; 6200 } 6201 return HANDLED; 6202 } 6203 } 6204 6205 class DriverStoppedState extends State { 6206 @Override 6207 public boolean processMessage(Message message) { 6208 logStateAndMessage(message, this); 6209 switch (message.what) { 6210 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6211 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 6212 SupplicantState state = stateChangeResult.state; 6213 // A WEXT bug means that we can be back to driver started state 6214 // unexpectedly 6215 if (SupplicantState.isDriverActive(state)) { 6216 transitionTo(mDriverStartedState); 6217 } 6218 break; 6219 case CMD_START_DRIVER: 6220 mWakeLock.acquire(); 6221 mWifiNative.startDriver(); 6222 mWakeLock.release(); 6223 transitionTo(mDriverStartingState); 6224 break; 6225 default: 6226 return NOT_HANDLED; 6227 } 6228 return HANDLED; 6229 } 6230 } 6231 6232 class ScanModeState extends State { 6233 private int mLastOperationMode; 6234 @Override 6235 public void enter() { 6236 mLastOperationMode = mOperationalMode; 6237 } 6238 @Override 6239 public boolean processMessage(Message message) { 6240 logStateAndMessage(message, this); 6241 6242 switch(message.what) { 6243 case CMD_SET_OPERATIONAL_MODE: 6244 if (message.arg1 == CONNECT_MODE) { 6245 6246 if (mLastOperationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 6247 setWifiState(WIFI_STATE_ENABLED); 6248 // Load and re-enable networks when going back to enabled state 6249 // This is essential for networks to show up after restore 6250 mWifiConfigManager.loadAndEnableAllNetworks(); 6251 mWifiP2pChannel.sendMessage(CMD_ENABLE_P2P); 6252 } else { 6253 mWifiConfigManager.enableAllNetworks(); 6254 } 6255 // start a scan to trigger Quality network selection 6256 startScan(ENABLE_WIFI, 0, null, null); 6257 6258 // Loose last selection choice since user toggled WiFi 6259 mWifiConfigManager. 6260 setAndEnableLastSelectedConfiguration( 6261 WifiConfiguration.INVALID_NETWORK_ID); 6262 6263 mOperationalMode = CONNECT_MODE; 6264 transitionTo(mDisconnectedState); 6265 } else { 6266 // Nothing to do 6267 return HANDLED; 6268 } 6269 break; 6270 // Handle scan. All the connection related commands are 6271 // handled only in ConnectModeState 6272 case CMD_START_SCAN: 6273 handleScanRequest(message); 6274 break; 6275 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6276 SupplicantState state = handleSupplicantStateChange(message); 6277 if(DBG) log("SupplicantState= " + state); 6278 break; 6279 default: 6280 return NOT_HANDLED; 6281 } 6282 return HANDLED; 6283 } 6284 } 6285 6286 6287 String smToString(Message message) { 6288 return smToString(message.what); 6289 } 6290 6291 String smToString(int what) { 6292 String s = sSmToString.get(what); 6293 if (s != null) { 6294 return s; 6295 } 6296 switch (what) { 6297 case WifiMonitor.DRIVER_HUNG_EVENT: 6298 s = "DRIVER_HUNG_EVENT"; 6299 break; 6300 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 6301 s = "AsyncChannel.CMD_CHANNEL_HALF_CONNECTED"; 6302 break; 6303 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 6304 s = "AsyncChannel.CMD_CHANNEL_DISCONNECTED"; 6305 break; 6306 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 6307 s = "WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST"; 6308 break; 6309 case WifiManager.DISABLE_NETWORK: 6310 s = "WifiManager.DISABLE_NETWORK"; 6311 break; 6312 case WifiManager.CONNECT_NETWORK: 6313 s = "CONNECT_NETWORK"; 6314 break; 6315 case WifiManager.SAVE_NETWORK: 6316 s = "SAVE_NETWORK"; 6317 break; 6318 case WifiManager.FORGET_NETWORK: 6319 s = "FORGET_NETWORK"; 6320 break; 6321 case WifiMonitor.SUP_CONNECTION_EVENT: 6322 s = "SUP_CONNECTION_EVENT"; 6323 break; 6324 case WifiMonitor.SUP_DISCONNECTION_EVENT: 6325 s = "SUP_DISCONNECTION_EVENT"; 6326 break; 6327 case WifiMonitor.SCAN_RESULTS_EVENT: 6328 s = "SCAN_RESULTS_EVENT"; 6329 break; 6330 case WifiMonitor.SCAN_FAILED_EVENT: 6331 s = "SCAN_FAILED_EVENT"; 6332 break; 6333 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6334 s = "SUPPLICANT_STATE_CHANGE_EVENT"; 6335 break; 6336 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 6337 s = "AUTHENTICATION_FAILURE_EVENT"; 6338 break; 6339 case WifiMonitor.SSID_TEMP_DISABLED: 6340 s = "SSID_TEMP_DISABLED"; 6341 break; 6342 case WifiMonitor.SSID_REENABLED: 6343 s = "SSID_REENABLED"; 6344 break; 6345 case WifiMonitor.WPS_SUCCESS_EVENT: 6346 s = "WPS_SUCCESS_EVENT"; 6347 break; 6348 case WifiMonitor.WPS_FAIL_EVENT: 6349 s = "WPS_FAIL_EVENT"; 6350 break; 6351 case WifiMonitor.SUP_REQUEST_IDENTITY: 6352 s = "SUP_REQUEST_IDENTITY"; 6353 break; 6354 case WifiMonitor.NETWORK_CONNECTION_EVENT: 6355 s = "NETWORK_CONNECTION_EVENT"; 6356 break; 6357 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6358 s = "NETWORK_DISCONNECTION_EVENT"; 6359 break; 6360 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 6361 s = "ASSOCIATION_REJECTION_EVENT"; 6362 break; 6363 case WifiMonitor.ANQP_DONE_EVENT: 6364 s = "WifiMonitor.ANQP_DONE_EVENT"; 6365 break; 6366 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 6367 s = "WifiMonitor.RX_HS20_ANQP_ICON_EVENT"; 6368 break; 6369 case WifiMonitor.GAS_QUERY_DONE_EVENT: 6370 s = "WifiMonitor.GAS_QUERY_DONE_EVENT"; 6371 break; 6372 case WifiMonitor.HS20_REMEDIATION_EVENT: 6373 s = "WifiMonitor.HS20_REMEDIATION_EVENT"; 6374 break; 6375 case WifiMonitor.GAS_QUERY_START_EVENT: 6376 s = "WifiMonitor.GAS_QUERY_START_EVENT"; 6377 break; 6378 case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT: 6379 s = "GROUP_CREATING_TIMED_OUT"; 6380 break; 6381 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 6382 s = "P2P_CONNECTION_CHANGED"; 6383 break; 6384 case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE: 6385 s = "P2P.DISCONNECT_WIFI_RESPONSE"; 6386 break; 6387 case WifiP2pServiceImpl.SET_MIRACAST_MODE: 6388 s = "P2P.SET_MIRACAST_MODE"; 6389 break; 6390 case WifiP2pServiceImpl.BLOCK_DISCOVERY: 6391 s = "P2P.BLOCK_DISCOVERY"; 6392 break; 6393 case WifiP2pServiceImpl.SET_COUNTRY_CODE: 6394 s = "P2P.SET_COUNTRY_CODE"; 6395 break; 6396 case WifiManager.CANCEL_WPS: 6397 s = "CANCEL_WPS"; 6398 break; 6399 case WifiManager.CANCEL_WPS_FAILED: 6400 s = "CANCEL_WPS_FAILED"; 6401 break; 6402 case WifiManager.CANCEL_WPS_SUCCEDED: 6403 s = "CANCEL_WPS_SUCCEDED"; 6404 break; 6405 case WifiManager.START_WPS: 6406 s = "START_WPS"; 6407 break; 6408 case WifiManager.START_WPS_SUCCEEDED: 6409 s = "START_WPS_SUCCEEDED"; 6410 break; 6411 case WifiManager.WPS_FAILED: 6412 s = "WPS_FAILED"; 6413 break; 6414 case WifiManager.WPS_COMPLETED: 6415 s = "WPS_COMPLETED"; 6416 break; 6417 case WifiManager.RSSI_PKTCNT_FETCH: 6418 s = "RSSI_PKTCNT_FETCH"; 6419 break; 6420 default: 6421 s = "what:" + Integer.toString(what); 6422 break; 6423 } 6424 return s; 6425 } 6426 6427 void registerConnected() { 6428 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6429 WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 6430 if (config != null) { 6431 //Here we will clear all disable counters once a network is connected 6432 //records how long this network is connected in future 6433 config.lastConnected = System.currentTimeMillis(); 6434 config.getNetworkSelectionStatus().clearDisableReasonCounter(); 6435 config.numAssociation++; 6436 } 6437 mBadLinkspeedcount = 0; 6438 } 6439 } 6440 6441 void registerDisconnected() { 6442 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6443 long now_ms = System.currentTimeMillis(); 6444 // We are switching away from this configuration, 6445 // hence record the time we were connected last 6446 WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 6447 if (config != null) { 6448 config.lastDisconnected = System.currentTimeMillis(); 6449 if (config.ephemeral) { 6450 // Remove ephemeral WifiConfigurations from file 6451 mWifiConfigManager.forgetNetwork(mLastNetworkId); 6452 } 6453 } 6454 } 6455 } 6456 6457 void noteWifiDisabledWhileAssociated() { 6458 // We got disabled by user while we were associated, make note of it 6459 int rssi = mWifiInfo.getRssi(); 6460 WifiConfiguration config = getCurrentWifiConfiguration(); 6461 if (getCurrentState() == mConnectedState 6462 && rssi != WifiInfo.INVALID_RSSI 6463 && config != null) { 6464 boolean is24GHz = mWifiInfo.is24GHz(); 6465 boolean isBadRSSI = (is24GHz && rssi < mWifiConfigManager.thresholdMinimumRssi24.get()) 6466 || (!is24GHz && rssi < mWifiConfigManager.thresholdMinimumRssi5.get()); 6467 boolean isLowRSSI = 6468 (is24GHz && rssi < mWifiConfigManager.thresholdQualifiedRssi24.get()) 6469 || (!is24GHz && mWifiInfo.getRssi() < 6470 mWifiConfigManager.thresholdQualifiedRssi5.get()); 6471 boolean isHighRSSI = (is24GHz && rssi 6472 >= mWifiConfigManager.thresholdSaturatedRssi24.get()) 6473 || (!is24GHz && mWifiInfo.getRssi() 6474 >= mWifiConfigManager.thresholdSaturatedRssi5.get()); 6475 if (isBadRSSI) { 6476 // Take note that we got disabled while RSSI was Bad 6477 config.numUserTriggeredWifiDisableLowRSSI++; 6478 } else if (isLowRSSI) { 6479 // Take note that we got disabled while RSSI was Low 6480 config.numUserTriggeredWifiDisableBadRSSI++; 6481 } else if (!isHighRSSI) { 6482 // Take note that we got disabled while RSSI was Not high 6483 config.numUserTriggeredWifiDisableNotHighRSSI++; 6484 } 6485 } 6486 } 6487 6488 WifiConfiguration getCurrentWifiConfiguration() { 6489 if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 6490 return null; 6491 } 6492 return mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 6493 } 6494 6495 ScanResult getCurrentScanResult() { 6496 WifiConfiguration config = getCurrentWifiConfiguration(); 6497 if (config == null) { 6498 return null; 6499 } 6500 String BSSID = mWifiInfo.getBSSID(); 6501 if (BSSID == null) { 6502 BSSID = mTargetRoamBSSID; 6503 } 6504 ScanDetailCache scanDetailCache = 6505 mWifiConfigManager.getScanDetailCache(config); 6506 6507 if (scanDetailCache == null) { 6508 return null; 6509 } 6510 6511 return scanDetailCache.get(BSSID); 6512 } 6513 6514 String getCurrentBSSID() { 6515 if (linkDebouncing) { 6516 return null; 6517 } 6518 return mLastBssid; 6519 } 6520 6521 class ConnectModeState extends State { 6522 6523 @Override 6524 public void enter() { 6525 connectScanningService(); 6526 } 6527 6528 @Override 6529 public boolean processMessage(Message message) { 6530 WifiConfiguration config; 6531 int netId; 6532 boolean ok; 6533 boolean didDisconnect; 6534 String bssid; 6535 String ssid; 6536 NetworkUpdateResult result; 6537 logStateAndMessage(message, this); 6538 6539 switch (message.what) { 6540 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 6541 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_ASSOC_FAILURE); 6542 didBlackListBSSID = false; 6543 bssid = (String) message.obj; 6544 if (bssid == null || TextUtils.isEmpty(bssid)) { 6545 // If BSSID is null, use the target roam BSSID 6546 bssid = mTargetRoamBSSID; 6547 } 6548 if (bssid != null) { 6549 // If we have a BSSID, tell configStore to black list it 6550 synchronized(mScanResultCache) { 6551 didBlackListBSSID = mWifiQualifiedNetworkSelector 6552 .enableBssidForQualityNetworkSelection(bssid, false); 6553 } 6554 } 6555 6556 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 6557 WifiConfiguration.NetworkSelectionStatus 6558 .DISABLED_ASSOCIATION_REJECTION); 6559 6560 mSupplicantStateTracker.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT); 6561 //If rejection occurred while Metrics is tracking a ConnnectionEvent, end it. 6562 mWifiMetrics.endConnectionEvent( 6563 WifiMetrics.ConnectionEvent.LLF_ASSOCIATION_REJECTION, 6564 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6565 break; 6566 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 6567 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_AUTH_FAILURE); 6568 mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); 6569 if (mTargetNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6570 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 6571 WifiConfiguration.NetworkSelectionStatus 6572 .DISABLED_AUTHENTICATION_FAILURE); 6573 } 6574 //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. 6575 mWifiMetrics.endConnectionEvent( 6576 WifiMetrics.ConnectionEvent.LLF_AUTHENTICATION_FAILURE, 6577 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6578 break; 6579 case WifiMonitor.SSID_TEMP_DISABLED: 6580 Log.e(TAG, "Supplicant SSID temporary disabled:" 6581 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 6582 mWifiConfigManager.updateNetworkSelectionStatus( 6583 message.arg1, 6584 WifiConfiguration.NetworkSelectionStatus 6585 .DISABLED_AUTHENTICATION_FAILURE); 6586 mWifiMetrics.endConnectionEvent( 6587 WifiMetrics.ConnectionEvent.LLF_SSID_TEMP_DISABLED, 6588 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6589 break; 6590 case WifiMonitor.SSID_REENABLED: 6591 Log.d(TAG, "Supplicant SSID reenable:" 6592 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 6593 // Do not re-enable it in Quality Network Selection since framework has its own 6594 // Algorithm of disable/enable 6595 break; 6596 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6597 SupplicantState state = handleSupplicantStateChange(message); 6598 // A driver/firmware hang can now put the interface in a down state. 6599 // We detect the interface going down and recover from it 6600 if (!SupplicantState.isDriverActive(state)) { 6601 if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 6602 handleNetworkDisconnect(); 6603 } 6604 log("Detected an interface down, restart driver"); 6605 transitionTo(mDriverStoppedState); 6606 sendMessage(CMD_START_DRIVER); 6607 break; 6608 } 6609 6610 // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT 6611 // when authentication times out after a successful connection, 6612 // we can figure this from the supplicant state. If supplicant 6613 // state is DISCONNECTED, but the mNetworkInfo says we are not 6614 // disconnected, we need to handle a disconnection 6615 if (!linkDebouncing && state == SupplicantState.DISCONNECTED && 6616 mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 6617 if (DBG) log("Missed CTRL-EVENT-DISCONNECTED, disconnect"); 6618 handleNetworkDisconnect(); 6619 transitionTo(mDisconnectedState); 6620 } 6621 6622 // If we have COMPLETED a connection to a BSSID, start doing 6623 // DNAv4/DNAv6 -style probing for on-link neighbors of 6624 // interest (e.g. routers); harmless if none are configured. 6625 if (state == SupplicantState.COMPLETED) { 6626 mIpManager.confirmConfiguration(); 6627 } 6628 break; 6629 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 6630 if (message.arg1 == 1) { 6631 mWifiNative.disconnect(); 6632 mTemporarilyDisconnectWifi = true; 6633 } else { 6634 mWifiNative.reconnect(); 6635 mTemporarilyDisconnectWifi = false; 6636 } 6637 break; 6638 case CMD_ADD_OR_UPDATE_NETWORK: 6639 // Only the current foreground user can modify networks. 6640 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6641 loge("Only the current foreground user can modify networks " 6642 + " currentUserId=" + mCurrentUserId 6643 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6644 replyToMessage(message, message.what, FAILURE); 6645 break; 6646 } 6647 6648 config = (WifiConfiguration) message.obj; 6649 6650 if (!recordUidIfAuthorized(config, message.sendingUid, 6651 /* onlyAnnotate */ false)) { 6652 logw("Not authorized to update network " 6653 + " config=" + config.SSID 6654 + " cnid=" + config.networkId 6655 + " uid=" + message.sendingUid); 6656 replyToMessage(message, message.what, FAILURE); 6657 break; 6658 } 6659 6660 int res = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 6661 if (res < 0) { 6662 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6663 } else { 6664 WifiConfiguration curConfig = getCurrentWifiConfiguration(); 6665 if (curConfig != null && config != null) { 6666 if (curConfig.priority < config.priority 6667 && config.status == WifiConfiguration.Status.ENABLED) { 6668 // Interpret this as a connect attempt 6669 // Set the last selected configuration so as to allow the system to 6670 // stick the last user choice without persisting the choice 6671 mWifiConfigManager.setAndEnableLastSelectedConfiguration(res); 6672 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 6673 boolean persist = mWifiConfigManager 6674 .checkConfigOverridePermission(message.sendingUid); 6675 mWifiQualifiedNetworkSelector 6676 .userSelectNetwork(res, persist); 6677 6678 // Remember time of last connection attempt 6679 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6680 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6681 6682 // As a courtesy to the caller, trigger a scan now 6683 startScan(ADD_OR_UPDATE_SOURCE, 0, null, null); 6684 } 6685 } 6686 } 6687 replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK, res); 6688 break; 6689 case CMD_REMOVE_NETWORK: 6690 // Only the current foreground user can modify networks. 6691 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6692 loge("Only the current foreground user can modify networks " 6693 + " currentUserId=" + mCurrentUserId 6694 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6695 replyToMessage(message, message.what, FAILURE); 6696 break; 6697 } 6698 netId = message.arg1; 6699 6700 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 6701 /* onlyAnnotate */ false)) { 6702 logw("Not authorized to remove network " 6703 + " cnid=" + netId 6704 + " uid=" + message.sendingUid); 6705 replyToMessage(message, message.what, FAILURE); 6706 break; 6707 } 6708 6709 ok = mWifiConfigManager.removeNetwork(message.arg1); 6710 if (!ok) { 6711 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6712 } 6713 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 6714 break; 6715 case CMD_ENABLE_NETWORK: 6716 // Only the current foreground user can modify networks. 6717 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6718 loge("Only the current foreground user can modify networks " 6719 + " currentUserId=" + mCurrentUserId 6720 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6721 replyToMessage(message, message.what, FAILURE); 6722 break; 6723 } 6724 6725 boolean disableOthers = message.arg2 == 1; 6726 netId = message.arg1; 6727 config = mWifiConfigManager.getWifiConfiguration(netId); 6728 if (config == null) { 6729 loge("No network with id = " + netId); 6730 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6731 replyToMessage(message, message.what, FAILURE); 6732 break; 6733 } 6734 6735 // disable other only means select this network, does not mean all other 6736 // networks need to be disabled 6737 if (disableOthers) { 6738 mWifiQualifiedNetworkSelector.enableNetworkByUser(config); 6739 // Remember time of last connection attempt 6740 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6741 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6742 } 6743 // Cancel auto roam requests 6744 autoRoamSetBSSID(netId, "any"); 6745 6746 int uid = message.sendingUid; 6747 mWifiQualifiedNetworkSelector.enableNetworkByUser(config); 6748 ok = mWifiConfigManager.enableNetwork(netId, disableOthers, uid); 6749 if (!ok) { 6750 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6751 } else if (disableOthers) { 6752 mTargetNetworkId = netId; 6753 } 6754 6755 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 6756 break; 6757 case CMD_ENABLE_ALL_NETWORKS: 6758 long time = android.os.SystemClock.elapsedRealtime(); 6759 if (time - mLastEnableAllNetworksTime > MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS) { 6760 mWifiConfigManager.enableAllNetworks(); 6761 mLastEnableAllNetworksTime = time; 6762 } 6763 break; 6764 case WifiManager.DISABLE_NETWORK: 6765 if (mWifiConfigManager.updateNetworkSelectionStatus(message.arg1, 6766 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER)) { 6767 replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED); 6768 } else { 6769 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6770 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 6771 WifiManager.ERROR); 6772 } 6773 break; 6774 case CMD_DISABLE_EPHEMERAL_NETWORK: 6775 config = mWifiConfigManager.disableEphemeralNetwork((String)message.obj); 6776 if (config != null) { 6777 if (config.networkId == mLastNetworkId) { 6778 // Disconnect and let autojoin reselect a new network 6779 sendMessage(CMD_DISCONNECT); 6780 } 6781 } 6782 break; 6783 case CMD_BLACKLIST_NETWORK: 6784 mWifiConfigManager.blackListBssid((String) message.obj); 6785 break; 6786 case CMD_CLEAR_BLACKLIST: 6787 mWifiConfigManager.clearBssidBlacklist(); 6788 break; 6789 case CMD_SAVE_CONFIG: 6790 ok = mWifiConfigManager.saveConfig(); 6791 6792 if (DBG) logd("did save config " + ok); 6793 replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); 6794 6795 // Inform the backup manager about a data change 6796 IBackupManager ibm = IBackupManager.Stub.asInterface( 6797 mFacade.getService(Context.BACKUP_SERVICE)); 6798 if (ibm != null) { 6799 try { 6800 ibm.dataChanged("com.android.providers.settings"); 6801 } catch (Exception e) { 6802 // Try again later 6803 } 6804 } 6805 break; 6806 case CMD_GET_CONFIGURED_NETWORKS: 6807 replyToMessage(message, message.what, 6808 mWifiConfigManager.getConfiguredNetworks()); 6809 break; 6810 case WifiMonitor.SUP_REQUEST_IDENTITY: 6811 int networkId = message.arg2; 6812 boolean identitySent = false; 6813 int eapMethod = WifiEnterpriseConfig.Eap.NONE; 6814 6815 if (targetWificonfiguration != null 6816 && targetWificonfiguration.enterpriseConfig != null) { 6817 eapMethod = targetWificonfiguration.enterpriseConfig.getEapMethod(); 6818 } 6819 6820 // For SIM & AKA/AKA' EAP method Only, get identity from ICC 6821 if (targetWificonfiguration != null 6822 && targetWificonfiguration.networkId == networkId 6823 && targetWificonfiguration.allowedKeyManagement 6824 .get(WifiConfiguration.KeyMgmt.IEEE8021X) 6825 && (eapMethod == WifiEnterpriseConfig.Eap.SIM 6826 || eapMethod == WifiEnterpriseConfig.Eap.AKA 6827 || eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME)) { 6828 TelephonyManager tm = (TelephonyManager) 6829 mContext.getSystemService(Context.TELEPHONY_SERVICE); 6830 if (tm != null) { 6831 String imsi = tm.getSubscriberId(); 6832 String mccMnc = ""; 6833 6834 if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) 6835 mccMnc = tm.getSimOperator(); 6836 6837 String identity = buildIdentity(eapMethod, imsi, mccMnc); 6838 6839 if (!identity.isEmpty()) { 6840 mWifiNative.simIdentityResponse(networkId, identity); 6841 identitySent = true; 6842 } 6843 } 6844 } 6845 if (!identitySent) { 6846 // Supplicant lacks credentials to connect to that network, hence black list 6847 ssid = (String) message.obj; 6848 if (targetWificonfiguration != null && ssid != null 6849 && targetWificonfiguration.SSID != null 6850 && targetWificonfiguration.SSID.equals("\"" + ssid + "\"")) { 6851 mWifiConfigManager.updateNetworkSelectionStatus(targetWificonfiguration, 6852 WifiConfiguration.NetworkSelectionStatus 6853 .DISABLED_AUTHENTICATION_NO_CREDENTIALS); 6854 } 6855 // Disconnect now, as we don't have any way to fullfill 6856 // the supplicant request. 6857 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 6858 WifiConfiguration.INVALID_NETWORK_ID); 6859 mWifiNative.disconnect(); 6860 } 6861 break; 6862 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 6863 logd("Received SUP_REQUEST_SIM_AUTH"); 6864 SimAuthRequestData requestData = (SimAuthRequestData) message.obj; 6865 if (requestData != null) { 6866 if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) { 6867 handleGsmAuthRequest(requestData); 6868 } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA 6869 || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) { 6870 handle3GAuthRequest(requestData); 6871 } 6872 } else { 6873 loge("Invalid sim auth request"); 6874 } 6875 break; 6876 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 6877 replyToMessage(message, message.what, 6878 mWifiConfigManager.getPrivilegedConfiguredNetworks()); 6879 break; 6880 case CMD_GET_MATCHING_CONFIG: 6881 replyToMessage(message, message.what, 6882 mWifiConfigManager.getMatchingConfig((ScanResult)message.obj)); 6883 break; 6884 /* Do a redundant disconnect without transition */ 6885 case CMD_DISCONNECT: 6886 mWifiConfigManager.setAndEnableLastSelectedConfiguration 6887 (WifiConfiguration.INVALID_NETWORK_ID); 6888 mWifiNative.disconnect(); 6889 break; 6890 case CMD_RECONNECT: 6891 WifiConfiguration candidate = 6892 mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true, 6893 mAllowUntrustedConnections, mScanResults, linkDebouncing, 6894 isConnected(), isDisconnected(), isSupplicantTransientState()); 6895 tryToConnectToNetwork(candidate); 6896 break; 6897 case CMD_REASSOCIATE: 6898 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6899 mWifiNative.reassociate(); 6900 break; 6901 case CMD_RELOAD_TLS_AND_RECONNECT: 6902 if (mWifiConfigManager.needsUnlockedKeyStore()) { 6903 logd("Reconnecting to give a chance to un-connected TLS networks"); 6904 mWifiNative.disconnect(); 6905 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6906 mWifiNative.reconnect(); 6907 } 6908 break; 6909 case CMD_AUTO_ROAM: 6910 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6911 return HANDLED; 6912 case CMD_AUTO_CONNECT: 6913 /* Work Around: wpa_supplicant can get in a bad state where it returns a non 6914 * associated status to the STATUS command but somehow-someplace still thinks 6915 * it is associated and thus will ignore select/reconnect command with 6916 * following message: 6917 * "Already associated with the selected network - do nothing" 6918 * 6919 * Hence, sends a disconnect to supplicant first. 6920 */ 6921 didDisconnect = false; 6922 if (getCurrentState() != mDisconnectedState) { 6923 /** Supplicant will ignore the reconnect if we are currently associated, 6924 * hence trigger a disconnect 6925 */ 6926 didDisconnect = true; 6927 mWifiNative.disconnect(); 6928 } 6929 6930 /* connect command coming from auto-join */ 6931 netId = message.arg1; 6932 mTargetNetworkId = netId; 6933 mTargetRoamBSSID = (String) message.obj; 6934 config = mWifiConfigManager.getWifiConfiguration(netId); 6935 logd("CMD_AUTO_CONNECT sup state " 6936 + mSupplicantStateTracker.getSupplicantStateName() 6937 + " my state " + getCurrentState().getName() 6938 + " nid=" + Integer.toString(netId) 6939 + " roam=" + Boolean.toString(mAutoRoaming)); 6940 if (config == null) { 6941 loge("AUTO_CONNECT and no config, bail out..."); 6942 break; 6943 } 6944 6945 /* Make sure we cancel any previous roam request */ 6946 setTargetBssid(config, mTargetRoamBSSID); 6947 6948 /* Save the network config */ 6949 logd("CMD_AUTO_CONNECT will save config -> " + config.SSID 6950 + " nid=" + Integer.toString(netId)); 6951 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 6952 netId = result.getNetworkId(); 6953 logd("CMD_AUTO_CONNECT did save config -> " 6954 + " nid=" + Integer.toString(netId)); 6955 6956 // Since we updated the config,read it back from config store: 6957 config = mWifiConfigManager.getWifiConfiguration(netId); 6958 if (config == null) { 6959 loge("CMD_AUTO_CONNECT couldn't update the config, got null config"); 6960 break; 6961 } 6962 if (netId != config.networkId) { 6963 loge("CMD_AUTO_CONNECT couldn't update the config, want" 6964 + " nid=" + Integer.toString(netId) + " but got" + config.networkId); 6965 break; 6966 } 6967 6968 if (deferForUserInput(message, netId, false)) { 6969 break; 6970 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 6971 WifiConfiguration.USER_BANNED) { 6972 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6973 WifiManager.NOT_AUTHORIZED); 6974 break; 6975 } 6976 6977 // Make sure the network is enabled, since supplicant will not reenable it 6978 mWifiConfigManager.enableNetworkWithoutBroadcast(netId, false); 6979 6980 // If we're autojoining a network that the user or an app explicitly selected, 6981 // keep track of the UID that selected it. 6982 // TODO(b/26786318): Keep track of the lastSelectedConfiguration and the 6983 // lastConnectUid on a per-user basis. 6984 int lastConnectUid = WifiConfiguration.UNKNOWN_UID; 6985 mWifiMetrics.startConnectionEvent(mWifiInfo, config, 6986 WifiMetricsProto.ConnectionEvent.ROAM_NONE); 6987 if (mWifiConfigManager.isLastSelectedConfiguration(config) 6988 && isCurrentUserProfile(UserHandle.getUserId(config.lastConnectUid))) { 6989 lastConnectUid = config.lastConnectUid; 6990 mWifiMetrics.setConnectionEventRoamType( 6991 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED); 6992 } 6993 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 6994 lastConnectUid) && mWifiNative.reconnect()) { 6995 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6996 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 6997 config = mWifiConfigManager.getWifiConfiguration(netId); 6998 if (config != null 6999 && !mWifiConfigManager.isLastSelectedConfiguration(config)) { 7000 // If we autojoined a different config than the user selected one, 7001 // it means we could not see the last user selection, 7002 // or that the last user selection was faulty and ended up blacklisted 7003 // for some reason (in which case the user is notified with an error 7004 // message in the Wifi picker), and thus we managed to auto-join away 7005 // from the selected config. -> in that case we need to forget 7006 // the selection because we don't want to abruptly switch back to it. 7007 // 7008 // Note that the user selection is also forgotten after a period of time 7009 // during which the device has been disconnected. 7010 // The default value is 30 minutes : see the code path at bottom of 7011 // setScanResults() function. 7012 mWifiConfigManager. 7013 setAndEnableLastSelectedConfiguration( 7014 WifiConfiguration.INVALID_NETWORK_ID); 7015 } 7016 mAutoRoaming = false; 7017 if (isRoaming() || linkDebouncing) { 7018 transitionTo(mRoamingState); 7019 } else if (didDisconnect) { 7020 transitionTo(mDisconnectingState); 7021 } else { 7022 /* Already in disconnected state, nothing to change */ 7023 if (!mScreenOn && mLegacyPnoEnabled && mBackgroundScanSupported) { 7024 int delay = 60 * 1000; 7025 if (VDBG) { 7026 logd("Starting PNO alarm: " + delay); 7027 } 7028 mAlarmManager.set(AlarmManager.RTC_WAKEUP, 7029 System.currentTimeMillis() + delay, 7030 mPnoIntent); 7031 } 7032 mRestartAutoJoinOffloadCounter++; 7033 } 7034 } else { 7035 loge("Failed to connect config: " + config + " netId: " + netId); 7036 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 7037 WifiManager.ERROR); 7038 mWifiMetrics.endConnectionEvent( 7039 WifiMetrics.ConnectionEvent.LLF_CONNECT_NETWORK_FAILED, 7040 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7041 break; 7042 } 7043 break; 7044 case CMD_REMOVE_APP_CONFIGURATIONS: 7045 mWifiConfigManager.removeNetworksForApp((ApplicationInfo) message.obj); 7046 break; 7047 case CMD_REMOVE_USER_CONFIGURATIONS: 7048 mWifiConfigManager.removeNetworksForUser(message.arg1); 7049 break; 7050 case WifiManager.CONNECT_NETWORK: 7051 // Only the current foreground user can modify networks. 7052 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 7053 loge("Only the current foreground user can modify networks " 7054 + " currentUserId=" + mCurrentUserId 7055 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 7056 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 7057 WifiManager.NOT_AUTHORIZED); 7058 break; 7059 } 7060 7061 /** 7062 * The connect message can contain a network id passed as arg1 on message or 7063 * or a config passed as obj on message. 7064 * For a new network, a config is passed to create and connect. 7065 * For an existing network, a network id is passed 7066 */ 7067 netId = message.arg1; 7068 config = (WifiConfiguration) message.obj; 7069 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 7070 boolean updatedExisting = false; 7071 7072 /* Save the network config */ 7073 if (config != null) { 7074 // When connecting to an access point, WifiStateMachine wants to update the 7075 // relevant config with administrative data. This update should not be 7076 // considered a 'real' update, therefore lockdown by Device Owner must be 7077 // disregarded. 7078 if (!recordUidIfAuthorized(config, message.sendingUid, 7079 /* onlyAnnotate */ true)) { 7080 logw("Not authorized to update network " 7081 + " config=" + config.SSID 7082 + " cnid=" + config.networkId 7083 + " uid=" + message.sendingUid); 7084 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 7085 WifiManager.NOT_AUTHORIZED); 7086 break; 7087 } 7088 7089 String configKey = config.configKey(true /* allowCached */); 7090 WifiConfiguration savedConfig = 7091 mWifiConfigManager.getWifiConfiguration(configKey); 7092 if (savedConfig != null) { 7093 // There is an existing config with this netId, but it wasn't exposed 7094 // (either AUTO_JOIN_DELETED or ephemeral; see WifiConfigManager# 7095 // getConfiguredNetworks). Remove those bits and update the config. 7096 config = savedConfig; 7097 logd("CONNECT_NETWORK updating existing config with id=" + 7098 config.networkId + " configKey=" + configKey); 7099 config.ephemeral = false; 7100 mWifiConfigManager.updateNetworkSelectionStatus(config, 7101 WifiConfiguration.NetworkSelectionStatus 7102 .NETWORK_SELECTION_ENABLE); 7103 updatedExisting = true; 7104 } 7105 7106 result = mWifiConfigManager.saveNetwork(config, message.sendingUid); 7107 netId = result.getNetworkId(); 7108 } 7109 config = mWifiConfigManager.getWifiConfiguration(netId); 7110 7111 if (config == null) { 7112 logd("CONNECT_NETWORK no config for id=" + Integer.toString(netId) + " " 7113 + mSupplicantStateTracker.getSupplicantStateName() + " my state " 7114 + getCurrentState().getName()); 7115 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 7116 WifiManager.ERROR); 7117 break; 7118 } 7119 mTargetNetworkId = netId; 7120 autoRoamSetBSSID(netId, "any"); 7121 7122 if (message.sendingUid == Process.WIFI_UID 7123 || message.sendingUid == Process.SYSTEM_UID) { 7124 // As a sanity measure, clear the BSSID in the supplicant network block. 7125 // If system or Wifi Settings want to connect, they will not 7126 // specify the BSSID. 7127 // If an app however had added a BSSID to this configuration, and the BSSID 7128 // was wrong, Then we would forever fail to connect until that BSSID 7129 // is cleaned up. 7130 clearConfigBSSID(config, "CONNECT_NETWORK"); 7131 } 7132 7133 if (deferForUserInput(message, netId, true)) { 7134 break; 7135 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 7136 WifiConfiguration.USER_BANNED) { 7137 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 7138 WifiManager.NOT_AUTHORIZED); 7139 break; 7140 } 7141 7142 mAutoRoaming = false; 7143 7144 /* Tell network selection the user did try to connect to that network if from 7145 settings */ 7146 boolean persist = 7147 mWifiConfigManager.checkConfigOverridePermission(message.sendingUid); 7148 7149 7150 mWifiConfigManager.setAndEnableLastSelectedConfiguration(netId); 7151 mWifiQualifiedNetworkSelector.userSelectNetwork(netId, persist); 7152 didDisconnect = false; 7153 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 7154 && mLastNetworkId != netId) { 7155 /** Supplicant will ignore the reconnect if we are currently associated, 7156 * hence trigger a disconnect 7157 */ 7158 didDisconnect = true; 7159 mWifiNative.disconnect(); 7160 } 7161 7162 // Make sure the network is enabled, since supplicant will not reenable it 7163 mWifiConfigManager.enableNetworkWithoutBroadcast(netId, false); 7164 7165 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ true, 7166 message.sendingUid) && mWifiNative.reconnect()) { 7167 lastConnectAttemptTimestamp = System.currentTimeMillis(); 7168 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 7169 7170 /* The state tracker handles enabling networks upon completion/failure */ 7171 mSupplicantStateTracker.sendMessage(WifiManager.CONNECT_NETWORK); 7172 replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 7173 if (didDisconnect) { 7174 /* Expect a disconnection from the old connection */ 7175 transitionTo(mDisconnectingState); 7176 } else if (updatedExisting && getCurrentState() == mConnectedState && 7177 getCurrentWifiConfiguration().networkId == netId) { 7178 // Update the current set of network capabilities, but stay in the 7179 // current state. 7180 updateCapabilities(config); 7181 } else { 7182 /** 7183 * Directly go to disconnected state where we 7184 * process the connection events from supplicant 7185 */ 7186 transitionTo(mDisconnectedState); 7187 } 7188 } else { 7189 loge("Failed to connect config: " + config + " netId: " + netId); 7190 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 7191 WifiManager.ERROR); 7192 break; 7193 } 7194 break; 7195 case WifiManager.SAVE_NETWORK: 7196 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 7197 // Fall thru 7198 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 7199 // Only the current foreground user can modify networks. 7200 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 7201 loge("Only the current foreground user can modify networks " 7202 + " currentUserId=" + mCurrentUserId 7203 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 7204 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 7205 WifiManager.NOT_AUTHORIZED); 7206 break; 7207 } 7208 7209 lastSavedConfigurationAttempt = null; // Used for debug 7210 config = (WifiConfiguration) message.obj; 7211 if (config == null) { 7212 loge("ERROR: SAVE_NETWORK with null configuration" 7213 + mSupplicantStateTracker.getSupplicantStateName() 7214 + " my state " + getCurrentState().getName()); 7215 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 7216 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 7217 WifiManager.ERROR); 7218 break; 7219 } 7220 lastSavedConfigurationAttempt = new WifiConfiguration(config); 7221 int nid = config.networkId; 7222 logd("SAVE_NETWORK id=" + Integer.toString(nid) 7223 + " config=" + config.SSID 7224 + " nid=" + config.networkId 7225 + " supstate=" + mSupplicantStateTracker.getSupplicantStateName() 7226 + " my state " + getCurrentState().getName()); 7227 7228 // Only record the uid if this is user initiated 7229 boolean checkUid = (message.what == WifiManager.SAVE_NETWORK); 7230 if (checkUid && !recordUidIfAuthorized(config, message.sendingUid, 7231 /* onlyAnnotate */ false)) { 7232 logw("Not authorized to update network " 7233 + " config=" + config.SSID 7234 + " cnid=" + config.networkId 7235 + " uid=" + message.sendingUid); 7236 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 7237 WifiManager.NOT_AUTHORIZED); 7238 break; 7239 } 7240 7241 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 7242 if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) { 7243 if (mWifiInfo.getNetworkId() == result.getNetworkId()) { 7244 if (result.hasIpChanged()) { 7245 // The currently connection configuration was changed 7246 // We switched from DHCP to static or from static to DHCP, or the 7247 // static IP address has changed. 7248 log("Reconfiguring IP on connection"); 7249 // TODO: clear addresses and disable IPv6 7250 // to simplify obtainingIpState. 7251 transitionTo(mObtainingIpState); 7252 } 7253 if (result.hasProxyChanged()) { 7254 log("Reconfiguring proxy on connection"); 7255 notifyLinkProperties(); 7256 } 7257 } 7258 replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED); 7259 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 7260 7261 if (VDBG) { 7262 logd("Success save network nid=" 7263 + Integer.toString(result.getNetworkId())); 7264 } 7265 7266 synchronized(mScanResultCache) { 7267 /** 7268 * If the command comes from WifiManager, then 7269 * tell autojoin the user did try to modify and save that network, 7270 * and interpret the SAVE_NETWORK as a request to connect 7271 */ 7272 boolean user = message.what == WifiManager.SAVE_NETWORK; 7273 7274 // Did this connect come from settings 7275 boolean persistConnect = 7276 mWifiConfigManager.checkConfigOverridePermission( 7277 message.sendingUid); 7278 7279 if (user) { 7280 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 7281 mWifiConfigManager.writeKnownNetworkHistory(); 7282 } 7283 //Fixme, CMD_AUTO_SAVE_NETWORK can be cleaned 7284 mWifiQualifiedNetworkSelector.userSelectNetwork( 7285 result.getNetworkId(), persistConnect); 7286 candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true, 7287 mAllowUntrustedConnections, mScanResults, linkDebouncing, 7288 isConnected(), isDisconnected(), isSupplicantTransientState()); 7289 tryToConnectToNetwork(candidate); 7290 } 7291 } else { 7292 loge("Failed to save network"); 7293 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 7294 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 7295 WifiManager.ERROR); 7296 } 7297 break; 7298 case WifiManager.FORGET_NETWORK: 7299 // Only the current foreground user can modify networks. 7300 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 7301 loge("Only the current foreground user can modify networks " 7302 + " currentUserId=" + mCurrentUserId 7303 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 7304 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 7305 WifiManager.NOT_AUTHORIZED); 7306 break; 7307 } 7308 7309 // Debug only, remember last configuration that was forgotten 7310 WifiConfiguration toRemove 7311 = mWifiConfigManager.getWifiConfiguration(message.arg1); 7312 if (toRemove == null) { 7313 lastForgetConfigurationAttempt = null; 7314 } else { 7315 lastForgetConfigurationAttempt = new WifiConfiguration(toRemove); 7316 } 7317 // check that the caller owns this network 7318 netId = message.arg1; 7319 7320 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 7321 /* onlyAnnotate */ false)) { 7322 logw("Not authorized to forget network " 7323 + " cnid=" + netId 7324 + " uid=" + message.sendingUid); 7325 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 7326 WifiManager.NOT_AUTHORIZED); 7327 break; 7328 } 7329 7330 if (mWifiConfigManager.forgetNetwork(message.arg1)) { 7331 replyToMessage(message, WifiManager.FORGET_NETWORK_SUCCEEDED); 7332 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, 7333 (WifiConfiguration) message.obj); 7334 } else { 7335 loge("Failed to forget network"); 7336 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 7337 WifiManager.ERROR); 7338 } 7339 break; 7340 case WifiManager.START_WPS: 7341 WpsInfo wpsInfo = (WpsInfo) message.obj; 7342 WpsResult wpsResult; 7343 switch (wpsInfo.setup) { 7344 case WpsInfo.PBC: 7345 wpsResult = mWifiConfigManager.startWpsPbc(wpsInfo); 7346 break; 7347 case WpsInfo.KEYPAD: 7348 wpsResult = mWifiConfigManager.startWpsWithPinFromAccessPoint(wpsInfo); 7349 break; 7350 case WpsInfo.DISPLAY: 7351 wpsResult = mWifiConfigManager.startWpsWithPinFromDevice(wpsInfo); 7352 break; 7353 default: 7354 wpsResult = new WpsResult(Status.FAILURE); 7355 loge("Invalid setup for WPS"); 7356 break; 7357 } 7358 mWifiConfigManager.setAndEnableLastSelectedConfiguration 7359 (WifiConfiguration.INVALID_NETWORK_ID); 7360 if (wpsResult.status == Status.SUCCESS) { 7361 replyToMessage(message, WifiManager.START_WPS_SUCCEEDED, wpsResult); 7362 transitionTo(mWpsRunningState); 7363 } else { 7364 loge("Failed to start WPS with config " + wpsInfo.toString()); 7365 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR); 7366 } 7367 break; 7368 case WifiMonitor.NETWORK_CONNECTION_EVENT: 7369 if (DBG) log("Network connection established"); 7370 mLastNetworkId = message.arg1; 7371 mLastBssid = (String) message.obj; 7372 7373 mWifiInfo.setBSSID(mLastBssid); 7374 mWifiInfo.setNetworkId(mLastNetworkId); 7375 mWifiQualifiedNetworkSelector 7376 .enableBssidForQualityNetworkSelection(mLastBssid, true); 7377 sendNetworkStateChangeBroadcast(mLastBssid); 7378 transitionTo(mObtainingIpState); 7379 break; 7380 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7381 // Calling handleNetworkDisconnect here is redundant because we might already 7382 // have called it when leaving L2ConnectedState to go to disconnecting state 7383 // or thru other path 7384 // We should normally check the mWifiInfo or mLastNetworkId so as to check 7385 // if they are valid, and only in this case call handleNEtworkDisconnect, 7386 // TODO: this should be fixed for a L MR release 7387 // The side effect of calling handleNetworkDisconnect twice is that a bunch of 7388 // idempotent commands are executed twice (stopping Dhcp, enabling the SPS mode 7389 // at the chip etc... 7390 if (DBG) log("ConnectModeState: Network connection lost "); 7391 handleNetworkDisconnect(); 7392 transitionTo(mDisconnectedState); 7393 break; 7394 case CMD_PNO_NETWORK_FOUND: 7395 processPnoNetworkFound((ScanResult[]) message.obj); 7396 break; 7397 case CMD_ADD_PASSPOINT_MO: 7398 res = mWifiConfigManager.addPasspointManagementObject((String) message.obj); 7399 replyToMessage(message, message.what, res); 7400 break; 7401 case CMD_MODIFY_PASSPOINT_MO: 7402 if (message.obj != null) { 7403 Bundle bundle = (Bundle) message.obj; 7404 ArrayList<PasspointManagementObjectDefinition> mos = 7405 bundle.getParcelableArrayList("MOS"); 7406 res = mWifiConfigManager.modifyPasspointMo(bundle.getString("FQDN"), mos); 7407 } else { 7408 res = 0; 7409 } 7410 replyToMessage(message, message.what, res); 7411 7412 break; 7413 case CMD_QUERY_OSU_ICON: 7414 if (mWifiConfigManager.queryPasspointIcon( 7415 ((Bundle) message.obj).getLong("BSSID"), 7416 ((Bundle) message.obj).getString("FILENAME"))) { 7417 res = 1; 7418 } else { 7419 res = 0; 7420 } 7421 replyToMessage(message, message.what, res); 7422 break; 7423 case CMD_MATCH_PROVIDER_NETWORK: 7424 res = mWifiConfigManager.matchProviderWithCurrentNetwork((String) message.obj); 7425 replyToMessage(message, message.what, res); 7426 break; 7427 default: 7428 return NOT_HANDLED; 7429 } 7430 return HANDLED; 7431 } 7432 } 7433 7434 private void updateCapabilities(WifiConfiguration config) { 7435 NetworkCapabilities networkCapabilities = new NetworkCapabilities(mDfltNetworkCapabilities); 7436 if (config != null) { 7437 if (config.ephemeral) { 7438 networkCapabilities.removeCapability( 7439 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 7440 } else { 7441 networkCapabilities.addCapability( 7442 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 7443 } 7444 networkCapabilities.setSignalStrength(mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI ? 7445 mWifiInfo.getRssi() : NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED); 7446 } 7447 mNetworkAgent.sendNetworkCapabilities(networkCapabilities); 7448 } 7449 7450 private class WifiNetworkAgent extends NetworkAgent { 7451 public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, 7452 NetworkCapabilities nc, LinkProperties lp, int score) { 7453 super(l, c, TAG, ni, nc, lp, score); 7454 } 7455 protected void unwanted() { 7456 // Ignore if we're not the current networkAgent. 7457 if (this != mNetworkAgent) return; 7458 if (DBG) log("WifiNetworkAgent -> Wifi unwanted score " 7459 + Integer.toString(mWifiInfo.score)); 7460 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT); 7461 } 7462 7463 @Override 7464 protected void networkStatus(int status) { 7465 if (this != mNetworkAgent) return; 7466 if (status == NetworkAgent.INVALID_NETWORK) { 7467 if (DBG) log("WifiNetworkAgent -> Wifi networkStatus invalid, score=" 7468 + Integer.toString(mWifiInfo.score)); 7469 unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED); 7470 } else if (status == NetworkAgent.VALID_NETWORK) { 7471 if (DBG && mWifiInfo != null) log("WifiNetworkAgent -> Wifi networkStatus valid, score= " 7472 + Integer.toString(mWifiInfo.score)); 7473 doNetworkStatus(status); 7474 } 7475 } 7476 7477 @Override 7478 protected void saveAcceptUnvalidated(boolean accept) { 7479 if (this != mNetworkAgent) return; 7480 WifiStateMachine.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0); 7481 } 7482 7483 @Override 7484 protected void startPacketKeepalive(Message msg) { 7485 WifiStateMachine.this.sendMessage( 7486 CMD_START_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 7487 } 7488 7489 @Override 7490 protected void stopPacketKeepalive(Message msg) { 7491 WifiStateMachine.this.sendMessage( 7492 CMD_STOP_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 7493 } 7494 7495 @Override 7496 protected void setSignalStrengthThresholds(int[] thresholds) { 7497 // 0. If there are no thresholds, or if the thresholds are invalid, stop RSSI monitoring. 7498 // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and 7499 // MAX_VALUE at the start/end of the thresholds array if necessary. 7500 // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware 7501 // event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then 7502 // re-arm the hardware event. This needs to be done on the state machine thread to 7503 // avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one 7504 // sent in the NetworkCapabilities) must be the one received from the hardware event 7505 // received, or we might skip callbacks. 7506 // 3. Ensure that when we disconnect, RSSI monitoring is stopped. 7507 log("Received signal strength thresholds: " + Arrays.toString(thresholds)); 7508 if (thresholds.length == 0) { 7509 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 7510 mWifiInfo.getRssi()); 7511 return; 7512 } 7513 int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2); 7514 rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE; 7515 rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE; 7516 Arrays.sort(rssiVals); 7517 byte[] rssiRange = new byte[rssiVals.length]; 7518 for (int i = 0; i < rssiVals.length; i++) { 7519 int val = rssiVals[i]; 7520 if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) { 7521 rssiRange[i] = (byte) val; 7522 } else { 7523 Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: " 7524 + Arrays.toString(rssiVals)); 7525 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 7526 mWifiInfo.getRssi()); 7527 return; 7528 } 7529 } 7530 // TODO: Do we quash rssi values in this sorted array which are very close? 7531 mRssiRanges = rssiRange; 7532 WifiStateMachine.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD, 7533 mWifiInfo.getRssi()); 7534 } 7535 7536 @Override 7537 protected void preventAutomaticReconnect() { 7538 if (this != mNetworkAgent) return; 7539 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN); 7540 } 7541 } 7542 7543 void unwantedNetwork(int reason) { 7544 sendMessage(CMD_UNWANTED_NETWORK, reason); 7545 } 7546 7547 void doNetworkStatus(int status) { 7548 sendMessage(CMD_NETWORK_STATUS, status); 7549 } 7550 7551 // rfc4186 & rfc4187: 7552 // create Permanent Identity base on IMSI, 7553 // identity = usernam@realm 7554 // with username = prefix | IMSI 7555 // and realm is derived MMC/MNC tuple according 3GGP spec(TS23.003) 7556 private String buildIdentity(int eapMethod, String imsi, String mccMnc) { 7557 String mcc; 7558 String mnc; 7559 String prefix; 7560 7561 if (imsi == null || imsi.isEmpty()) 7562 return ""; 7563 7564 if (eapMethod == WifiEnterpriseConfig.Eap.SIM) 7565 prefix = "1"; 7566 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA) 7567 prefix = "0"; 7568 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME) 7569 prefix = "6"; 7570 else // not a valide EapMethod 7571 return ""; 7572 7573 /* extract mcc & mnc from mccMnc */ 7574 if (mccMnc != null && !mccMnc.isEmpty()) { 7575 mcc = mccMnc.substring(0, 3); 7576 mnc = mccMnc.substring(3); 7577 if (mnc.length() == 2) 7578 mnc = "0" + mnc; 7579 } else { 7580 // extract mcc & mnc from IMSI, assume mnc size is 3 7581 mcc = imsi.substring(0, 3); 7582 mnc = imsi.substring(3, 6); 7583 } 7584 7585 return prefix + imsi + "@wlan.mnc" + mnc + ".mcc" + mcc + ".3gppnetwork.org"; 7586 } 7587 7588 boolean startScanForConfiguration(WifiConfiguration config, boolean restrictChannelList) { 7589 if (config == null) 7590 return false; 7591 7592 // We are still seeing a fairly high power consumption triggered by autojoin scans 7593 // Hence do partial scans only for PSK configuration that are roamable since the 7594 // primary purpose of the partial scans is roaming. 7595 // Full badn scans with exponential backoff for the purpose or extended roaming and 7596 // network switching are performed unconditionally. 7597 ScanDetailCache scanDetailCache = 7598 mWifiConfigManager.getScanDetailCache(config); 7599 if (scanDetailCache == null 7600 || !config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) 7601 || scanDetailCache.size() > 6) { 7602 //return true but to not trigger the scan 7603 return true; 7604 } 7605 HashSet<Integer> freqs = mWifiConfigManager.makeChannelList(config, 7606 ONE_HOUR_MILLI, restrictChannelList); 7607 if (freqs != null && freqs.size() != 0) { 7608 //if (DBG) { 7609 logd("starting scan for " + config.configKey() + " with " + freqs); 7610 //} 7611 // Call wifi native to start the scan 7612 if (startScanNative(freqs)) { 7613 // Only count battery consumption if scan request is accepted 7614 noteScanStart(SCAN_ALARM_SOURCE, null); 7615 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; 7616 } else { 7617 // used for debug only, mark scan as failed 7618 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 7619 } 7620 return true; 7621 } else { 7622 if (DBG) logd("no channels for " + config.configKey()); 7623 return false; 7624 } 7625 } 7626 7627 void clearCurrentConfigBSSID(String dbg) { 7628 // Clear the bssid in the current config's network block 7629 WifiConfiguration config = getCurrentWifiConfiguration(); 7630 if (config == null) 7631 return; 7632 clearConfigBSSID(config, dbg); 7633 } 7634 void clearConfigBSSID(WifiConfiguration config, String dbg) { 7635 if (config == null) 7636 return; 7637 if (DBG) { 7638 logd(dbg + " " + mTargetRoamBSSID + " config " + config.configKey() 7639 + " config.NetworkSelectionStatus.mNetworkSelectionBSSID " 7640 + config.getNetworkSelectionStatus().getNetworkSelectionBSSID()); 7641 } 7642 config.getNetworkSelectionStatus().setNetworkSelectionBSSID("any"); 7643 if (DBG) { 7644 logd(dbg + " " + config.SSID 7645 + " nid=" + Integer.toString(config.networkId)); 7646 } 7647 mWifiConfigManager.saveWifiConfigBSSID(config); 7648 } 7649 7650 class L2ConnectedState extends State { 7651 @Override 7652 public void enter() { 7653 mRssiPollToken++; 7654 if (mEnableRssiPolling) { 7655 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0); 7656 } 7657 if (mNetworkAgent != null) { 7658 loge("Have NetworkAgent when entering L2Connected"); 7659 setNetworkDetailedState(DetailedState.DISCONNECTED); 7660 } 7661 setNetworkDetailedState(DetailedState.CONNECTING); 7662 7663 if (!TextUtils.isEmpty(mTcpBufferSizes)) { 7664 mLinkProperties.setTcpBufferSizes(mTcpBufferSizes); 7665 } 7666 mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, 7667 "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter, 7668 mLinkProperties, 60); 7669 7670 // We must clear the config BSSID, as the wifi chipset may decide to roam 7671 // from this point on and having the BSSID specified in the network block would 7672 // cause the roam to faile and the device to disconnect 7673 clearCurrentConfigBSSID("L2ConnectedState"); 7674 } 7675 7676 @Override 7677 public void exit() { 7678 mIpManager.stop(); 7679 7680 // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState 7681 // Bug: 15347363 7682 // For paranoia's sake, call handleNetworkDisconnect 7683 // only if BSSID is null or last networkId 7684 // is not invalid. 7685 if (DBG) { 7686 StringBuilder sb = new StringBuilder(); 7687 sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId)); 7688 if (mLastBssid !=null) { 7689 sb.append(" ").append(mLastBssid); 7690 } 7691 } 7692 if (mLastBssid != null || mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 7693 handleNetworkDisconnect(); 7694 } 7695 } 7696 7697 @Override 7698 public boolean processMessage(Message message) { 7699 logStateAndMessage(message, this); 7700 7701 switch (message.what) { 7702 case DhcpClient.CMD_PRE_DHCP_ACTION: 7703 handlePreDhcpSetup(); 7704 break; 7705 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 7706 mIpManager.completedPreDhcpAction(); 7707 break; 7708 case DhcpClient.CMD_POST_DHCP_ACTION: 7709 handlePostDhcpSetup(); 7710 // We advance to mConnectedState because IpManager will also send a 7711 // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(), 7712 // which calls updateLinkProperties, which then sends 7713 // CMD_IP_CONFIGURATION_SUCCESSFUL. 7714 // 7715 // In the event of failure, we transition to mDisconnectingState 7716 // similarly--via messages sent back from IpManager. 7717 break; 7718 case CMD_IPV4_PROVISIONING_SUCCESS: { 7719 handleIPv4Success((DhcpResults) message.obj); 7720 break; 7721 } 7722 case CMD_IPV4_PROVISIONING_FAILURE: { 7723 handleIPv4Failure(); 7724 break; 7725 } 7726 case CMD_IP_CONFIGURATION_SUCCESSFUL: 7727 handleSuccessfulIpConfiguration(); 7728 mWifiMetrics.endConnectionEvent( 7729 WifiMetrics.ConnectionEvent.LLF_NONE, 7730 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7731 sendConnectedState(); 7732 transitionTo(mConnectedState); 7733 break; 7734 case CMD_IP_CONFIGURATION_LOST: 7735 // Get Link layer stats so that we get fresh tx packet counters. 7736 getWifiLinkLayerStats(true); 7737 handleIpConfigurationLost(); 7738 transitionTo(mDisconnectingState); 7739 break; 7740 case CMD_IP_REACHABILITY_LOST: 7741 if (DBG && message.obj != null) log((String) message.obj); 7742 handleIpReachabilityLost(); 7743 transitionTo(mDisconnectingState); 7744 break; 7745 case CMD_DISCONNECT: 7746 mWifiNative.disconnect(); 7747 transitionTo(mDisconnectingState); 7748 break; 7749 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 7750 if (message.arg1 == 1) { 7751 mWifiNative.disconnect(); 7752 mTemporarilyDisconnectWifi = true; 7753 transitionTo(mDisconnectingState); 7754 } 7755 break; 7756 case CMD_SET_OPERATIONAL_MODE: 7757 if (message.arg1 != CONNECT_MODE) { 7758 sendMessage(CMD_DISCONNECT); 7759 deferMessage(message); 7760 if (message.arg1 == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 7761 noteWifiDisabledWhileAssociated(); 7762 } 7763 } 7764 mWifiConfigManager. 7765 setAndEnableLastSelectedConfiguration( 7766 WifiConfiguration.INVALID_NETWORK_ID); 7767 break; 7768 case CMD_SET_COUNTRY_CODE: 7769 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 7770 deferMessage(message); 7771 break; 7772 case CMD_START_SCAN: 7773 if (DBG) { 7774 logd("CMD_START_SCAN source " + message.arg1 7775 + " txSuccessRate="+String.format( "%.2f", mWifiInfo.txSuccessRate) 7776 + " rxSuccessRate="+String.format( "%.2f", mWifiInfo.rxSuccessRate) 7777 + " targetRoamBSSID=" + mTargetRoamBSSID 7778 + " RSSI=" + mWifiInfo.getRssi()); 7779 } 7780 if (message.arg1 == SCAN_ALARM_SOURCE) { 7781 // Check if the CMD_START_SCAN message is obsolete (and thus if it should 7782 // not be processed) and restart the scan if neede 7783 if (!getEnableAutoJoinWhenAssociated()) { 7784 return HANDLED; 7785 } 7786 boolean shouldScan = mScreenOn; 7787 7788 if (!checkAndRestartDelayedScan(message.arg2, 7789 shouldScan, 7790 mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get(), 7791 null, null)) { 7792 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 7793 logd("L2Connected CMD_START_SCAN source " 7794 + message.arg1 7795 + " " + message.arg2 + ", " + mDelayedScanCounter 7796 + " -> obsolete"); 7797 return HANDLED; 7798 } 7799 if (mP2pConnected.get()) { 7800 logd("L2Connected CMD_START_SCAN source " 7801 + message.arg1 7802 + " " + message.arg2 + ", " + mDelayedScanCounter 7803 + " ignore because P2P is connected"); 7804 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7805 return HANDLED; 7806 } 7807 boolean tryFullBandScan = false; 7808 boolean restrictChannelList = false; 7809 long now_ms = System.currentTimeMillis(); 7810 if (DBG) { 7811 logd("CMD_START_SCAN with age=" 7812 + Long.toString(now_ms - lastFullBandConnectedTimeMilli) 7813 + " interval=" + fullBandConnectedTimeIntervalMilli 7814 + " maxinterval=" + maxFullBandConnectedTimeIntervalMilli); 7815 } 7816 if (mWifiInfo != null) { 7817 if (mWifiConfigManager.enableFullBandScanWhenAssociated.get() && 7818 (now_ms - lastFullBandConnectedTimeMilli) 7819 > fullBandConnectedTimeIntervalMilli) { 7820 if (DBG) { 7821 logd("CMD_START_SCAN try full band scan age=" 7822 + Long.toString(now_ms - lastFullBandConnectedTimeMilli) 7823 + " interval=" + fullBandConnectedTimeIntervalMilli 7824 + " maxinterval=" + maxFullBandConnectedTimeIntervalMilli); 7825 } 7826 tryFullBandScan = true; 7827 } 7828 7829 if (mWifiInfo.txSuccessRate > 7830 mWifiConfigManager.maxTxPacketForFullScans 7831 || mWifiInfo.rxSuccessRate > 7832 mWifiConfigManager.maxRxPacketForFullScans) { 7833 // Too much traffic at the interface, hence no full band scan 7834 if (DBG) { 7835 logd("CMD_START_SCAN " + 7836 "prevent full band scan due to pkt rate"); 7837 } 7838 tryFullBandScan = false; 7839 } 7840 7841 if (mWifiInfo.txSuccessRate > 7842 mWifiConfigManager.maxTxPacketForPartialScans 7843 || mWifiInfo.rxSuccessRate > 7844 mWifiConfigManager.maxRxPacketForPartialScans) { 7845 // Don't scan if lots of packets are being sent 7846 restrictChannelList = true; 7847 if (mWifiConfigManager.alwaysEnableScansWhileAssociated.get() == 7848 0) { 7849 if (DBG) { 7850 logd("CMD_START_SCAN source " + message.arg1 7851 + " ...and ignore scans" 7852 + " tx=" + String.format("%.2f", mWifiInfo.txSuccessRate) 7853 + " rx=" + String.format("%.2f", mWifiInfo.rxSuccessRate)); 7854 } 7855 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 7856 return HANDLED; 7857 } 7858 } 7859 } 7860 7861 WifiConfiguration currentConfiguration = getCurrentWifiConfiguration(); 7862 if (DBG) { 7863 logd("CMD_START_SCAN full=" + 7864 tryFullBandScan); 7865 } 7866 if (currentConfiguration != null) { 7867 if (fullBandConnectedTimeIntervalMilli < 7868 mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get()) { 7869 // Sanity 7870 fullBandConnectedTimeIntervalMilli = 7871 mWifiConfigManager 7872 .wifiAssociatedShortScanIntervalMilli.get(); 7873 } 7874 if (tryFullBandScan) { 7875 lastFullBandConnectedTimeMilli = now_ms; 7876 if (fullBandConnectedTimeIntervalMilli 7877 < mWifiConfigManager.associatedFullScanMaxIntervalMilli) { 7878 // Increase the interval 7879 fullBandConnectedTimeIntervalMilli = 7880 fullBandConnectedTimeIntervalMilli * 7881 mWifiConfigManager 7882 .associatedFullScanBackoff.get() / 8; 7883 7884 if (DBG) { 7885 logd("CMD_START_SCAN bump interval =" 7886 + fullBandConnectedTimeIntervalMilli); 7887 } 7888 } 7889 handleScanRequest(message); 7890 } else { 7891 if (!startScanForConfiguration( 7892 currentConfiguration, restrictChannelList)) { 7893 if (DBG) { 7894 logd("starting scan, " + 7895 " did not find channels -> full"); 7896 } 7897 lastFullBandConnectedTimeMilli = now_ms; 7898 if (fullBandConnectedTimeIntervalMilli 7899 < mWifiConfigManager 7900 .associatedFullScanMaxIntervalMilli) { 7901 // Increase the interval 7902 fullBandConnectedTimeIntervalMilli = 7903 fullBandConnectedTimeIntervalMilli * 7904 mWifiConfigManager 7905 .associatedFullScanBackoff.get() / 8; 7906 7907 if (DBG) { 7908 logd("CMD_START_SCAN bump interval =" 7909 + fullBandConnectedTimeIntervalMilli); 7910 } 7911 } 7912 handleScanRequest(message); 7913 } 7914 } 7915 7916 } else { 7917 logd("CMD_START_SCAN : connected mode and no configuration"); 7918 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 7919 } 7920 } else { 7921 // Not scan alarm source 7922 return NOT_HANDLED; 7923 } 7924 break; 7925 /* Ignore connection to same network */ 7926 case WifiManager.CONNECT_NETWORK: 7927 int netId = message.arg1; 7928 if (mWifiInfo.getNetworkId() == netId) { 7929 break; 7930 } 7931 return NOT_HANDLED; 7932 case WifiMonitor.NETWORK_CONNECTION_EVENT: 7933 mWifiInfo.setBSSID((String) message.obj); 7934 mLastNetworkId = message.arg1; 7935 mWifiInfo.setNetworkId(mLastNetworkId); 7936 if(!mLastBssid.equals((String) message.obj)) { 7937 mLastBssid = (String) message.obj; 7938 sendNetworkStateChangeBroadcast(mLastBssid); 7939 } 7940 break; 7941 case CMD_RSSI_POLL: 7942 if (message.arg1 == mRssiPollToken) { 7943 if (mWifiConfigManager.enableChipWakeUpWhenAssociated.get()) { 7944 if (VVDBG) log(" get link layer stats " + mWifiLinkLayerStatsSupported); 7945 WifiLinkLayerStats stats = getWifiLinkLayerStats(VDBG); 7946 if (stats != null) { 7947 // Sanity check the results provided by driver 7948 if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI 7949 && (stats.rssi_mgmt == 0 7950 || stats.beacon_rx == 0)) { 7951 stats = null; 7952 } 7953 } 7954 // Get Info and continue polling 7955 fetchRssiLinkSpeedAndFrequencyNative(); 7956 calculateWifiScore(stats); 7957 } 7958 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 7959 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 7960 if (DBG) sendRssiChangeBroadcast(mWifiInfo.getRssi()); 7961 } else { 7962 // Polling has completed 7963 } 7964 break; 7965 case CMD_ENABLE_RSSI_POLL: 7966 cleanWifiScore(); 7967 if (mWifiConfigManager.enableRssiPollWhenAssociated.get()) { 7968 mEnableRssiPolling = (message.arg1 == 1); 7969 } else { 7970 mEnableRssiPolling = false; 7971 } 7972 mRssiPollToken++; 7973 if (mEnableRssiPolling) { 7974 // First poll 7975 fetchRssiLinkSpeedAndFrequencyNative(); 7976 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 7977 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 7978 } 7979 break; 7980 case WifiManager.RSSI_PKTCNT_FETCH: 7981 RssiPacketCountInfo info = new RssiPacketCountInfo(); 7982 fetchRssiLinkSpeedAndFrequencyNative(); 7983 info.rssi = mWifiInfo.getRssi(); 7984 fetchPktcntNative(info); 7985 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED, info); 7986 break; 7987 case CMD_DELAYED_NETWORK_DISCONNECT: 7988 if (!linkDebouncing && mWifiConfigManager.enableLinkDebouncing) { 7989 7990 // Ignore if we are not debouncing 7991 logd("CMD_DELAYED_NETWORK_DISCONNECT and not debouncing - ignore " 7992 + message.arg1); 7993 return HANDLED; 7994 } else { 7995 logd("CMD_DELAYED_NETWORK_DISCONNECT and debouncing - disconnect " 7996 + message.arg1); 7997 7998 linkDebouncing = false; 7999 // If we are still debouncing while this message comes, 8000 // it means we were not able to reconnect within the alloted time 8001 // = LINK_FLAPPING_DEBOUNCE_MSEC 8002 // and thus, trigger a real disconnect 8003 handleNetworkDisconnect(); 8004 transitionTo(mDisconnectedState); 8005 } 8006 break; 8007 case CMD_ASSOCIATED_BSSID: 8008 if ((String) message.obj == null) { 8009 logw("Associated command w/o BSSID"); 8010 break; 8011 } 8012 mLastBssid = (String) message.obj; 8013 if (mLastBssid != null 8014 && (mWifiInfo.getBSSID() == null 8015 || !mLastBssid.equals(mWifiInfo.getBSSID()))) { 8016 mWifiInfo.setBSSID((String) message.obj); 8017 sendNetworkStateChangeBroadcast(mLastBssid); 8018 } 8019 break; 8020 case CMD_START_RSSI_MONITORING_OFFLOAD: 8021 case CMD_RSSI_THRESHOLD_BREACH: 8022 byte currRssi = (byte) message.arg1; 8023 processRssiThreshold(currRssi, message.what); 8024 break; 8025 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 8026 stopRssiMonitoringOffload(); 8027 break; 8028 case CMD_RESET_SIM_NETWORKS: 8029 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 8030 WifiConfiguration config = 8031 mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 8032 if (mWifiConfigManager.isSimConfig(config)) { 8033 mWifiNative.disconnect(); 8034 transitionTo(mDisconnectingState); 8035 } 8036 } 8037 /* allow parent state to reset data for other networks */ 8038 return NOT_HANDLED; 8039 default: 8040 return NOT_HANDLED; 8041 } 8042 8043 return HANDLED; 8044 } 8045 } 8046 8047 class ObtainingIpState extends State { 8048 @Override 8049 public void enter() { 8050 if (DBG) { 8051 String key = ""; 8052 if (getCurrentWifiConfiguration() != null) { 8053 key = getCurrentWifiConfiguration().configKey(); 8054 } 8055 log("enter ObtainingIpState netId=" + Integer.toString(mLastNetworkId) 8056 + " " + key + " " 8057 + " roam=" + mAutoRoaming 8058 + " static=" + mWifiConfigManager.isUsingStaticIp(mLastNetworkId) 8059 + " watchdog= " + obtainingIpWatchdogCount); 8060 } 8061 8062 // Reset link Debouncing, indicating we have successfully re-connected to the AP 8063 // We might still be roaming 8064 linkDebouncing = false; 8065 8066 // Send event to CM & network change broadcast 8067 setNetworkDetailedState(DetailedState.OBTAINING_IPADDR); 8068 8069 // We must clear the config BSSID, as the wifi chipset may decide to roam 8070 // from this point on and having the BSSID specified in the network block would 8071 // cause the roam to fail and the device to disconnect. 8072 clearCurrentConfigBSSID("ObtainingIpAddress"); 8073 8074 // Stop IpManager in case we're switching from DHCP to static 8075 // configuration or vice versa. 8076 // 8077 // TODO: Only ever enter this state the first time we connect to a 8078 // network, never on switching between static configuration and 8079 // DHCP. When we transition from static configuration to DHCP in 8080 // particular, we must tell ConnectivityService that we're 8081 // disconnected, because DHCP might take a long time during which 8082 // connectivity APIs such as getActiveNetworkInfo should not return 8083 // CONNECTED. 8084 stopIpManager(); 8085 8086 if (!mWifiConfigManager.isUsingStaticIp(mLastNetworkId)) { 8087 final IpManager.ProvisioningConfiguration prov = 8088 mIpManager.buildProvisioningConfiguration() 8089 .withPreDhcpAction() 8090 .build(); 8091 mIpManager.startProvisioning(prov); 8092 obtainingIpWatchdogCount++; 8093 logd("Start Dhcp Watchdog " + obtainingIpWatchdogCount); 8094 // Get Link layer stats so as we get fresh tx packet counters 8095 getWifiLinkLayerStats(true); 8096 sendMessageDelayed(obtainMessage(CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER, 8097 obtainingIpWatchdogCount, 0), OBTAINING_IP_ADDRESS_GUARD_TIMER_MSEC); 8098 } else { 8099 StaticIpConfiguration config = mWifiConfigManager.getStaticIpConfiguration( 8100 mLastNetworkId); 8101 if (config.ipAddress == null) { 8102 logd("Static IP lacks address"); 8103 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 8104 } else { 8105 final IpManager.ProvisioningConfiguration prov = 8106 mIpManager.buildProvisioningConfiguration() 8107 .withStaticConfiguration(config) 8108 .build(); 8109 mIpManager.startProvisioning(prov); 8110 } 8111 } 8112 } 8113 8114 @Override 8115 public boolean processMessage(Message message) { 8116 logStateAndMessage(message, this); 8117 8118 switch(message.what) { 8119 case CMD_AUTO_CONNECT: 8120 case CMD_AUTO_ROAM: 8121 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 8122 break; 8123 case WifiManager.SAVE_NETWORK: 8124 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 8125 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 8126 deferMessage(message); 8127 break; 8128 /* Defer any power mode changes since we must keep active power mode at DHCP */ 8129 8130 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8131 mWifiMetrics.endConnectionEvent( 8132 WifiMetrics.ConnectionEvent.LLF_NETWORK_DISCONNECTION, 8133 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8134 return NOT_HANDLED; 8135 case CMD_SET_HIGH_PERF_MODE: 8136 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 8137 deferMessage(message); 8138 break; 8139 /* Defer scan request since we should not switch to other channels at DHCP */ 8140 case CMD_START_SCAN: 8141 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 8142 deferMessage(message); 8143 break; 8144 case CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER: 8145 if (message.arg1 == obtainingIpWatchdogCount) { 8146 logd("ObtainingIpAddress: Watchdog Triggered, count=" 8147 + obtainingIpWatchdogCount); 8148 handleIpConfigurationLost(); 8149 transitionTo(mDisconnectingState); 8150 break; 8151 } 8152 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 8153 break; 8154 default: 8155 return NOT_HANDLED; 8156 } 8157 return HANDLED; 8158 } 8159 } 8160 8161 private void sendConnectedState() { 8162 // If this network was explicitly selected by the user, evaluate whether to call 8163 // explicitlySelected() so the system can treat it appropriately. 8164 WifiConfiguration config = getCurrentWifiConfiguration(); 8165 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 8166 boolean prompt = 8167 mWifiConfigManager.checkConfigOverridePermission(config.lastConnectUid); 8168 if (DBG) { 8169 log("Network selected by UID " + config.lastConnectUid + " prompt=" + prompt); 8170 } 8171 if (prompt) { 8172 // Selected by the user via Settings or QuickSettings. If this network has Internet 8173 // access, switch to it. Otherwise, switch to it only if the user confirms that they 8174 // really want to switch, or has already confirmed and selected "Don't ask again". 8175 if (DBG) { 8176 log("explictlySelected acceptUnvalidated=" + config.noInternetAccessExpected); 8177 } 8178 mNetworkAgent.explicitlySelected(config.noInternetAccessExpected); 8179 } 8180 } 8181 8182 setNetworkDetailedState(DetailedState.CONNECTED); 8183 mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.CONNECTED); 8184 sendNetworkStateChangeBroadcast(mLastBssid); 8185 } 8186 8187 class RoamingState extends State { 8188 boolean mAssociated; 8189 @Override 8190 public void enter() { 8191 if (DBG) { 8192 log("RoamingState Enter" 8193 + " mScreenOn=" + mScreenOn ); 8194 } 8195 setScanAlarm(false); 8196 8197 // Make sure we disconnect if roaming fails 8198 roamWatchdogCount++; 8199 logd("Start Roam Watchdog " + roamWatchdogCount); 8200 sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER, 8201 roamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); 8202 mAssociated = false; 8203 } 8204 @Override 8205 public boolean processMessage(Message message) { 8206 logStateAndMessage(message, this); 8207 WifiConfiguration config; 8208 switch (message.what) { 8209 case CMD_IP_CONFIGURATION_LOST: 8210 config = getCurrentWifiConfiguration(); 8211 if (config != null) { 8212 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_AUTOROAM_FAILURE); 8213 mWifiConfigManager.noteRoamingFailure(config, 8214 WifiConfiguration.ROAMING_FAILURE_IP_CONFIG); 8215 } 8216 return NOT_HANDLED; 8217 case CMD_UNWANTED_NETWORK: 8218 if (DBG) log("Roaming and CS doesnt want the network -> ignore"); 8219 return HANDLED; 8220 case CMD_SET_OPERATIONAL_MODE: 8221 if (message.arg1 != CONNECT_MODE) { 8222 deferMessage(message); 8223 } 8224 break; 8225 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 8226 /** 8227 * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT 8228 * before NETWORK_DISCONNECTION_EVENT 8229 * And there is an associated BSSID corresponding to our target BSSID, then 8230 * we have missed the network disconnection, transition to mDisconnectedState 8231 * and handle the rest of the events there. 8232 */ 8233 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 8234 if (stateChangeResult.state == SupplicantState.DISCONNECTED 8235 || stateChangeResult.state == SupplicantState.INACTIVE 8236 || stateChangeResult.state == SupplicantState.INTERFACE_DISABLED) { 8237 if (DBG) { 8238 log("STATE_CHANGE_EVENT in roaming state " 8239 + stateChangeResult.toString() ); 8240 } 8241 if (stateChangeResult.BSSID != null 8242 && stateChangeResult.BSSID.equals(mTargetRoamBSSID)) { 8243 handleNetworkDisconnect(); 8244 transitionTo(mDisconnectedState); 8245 } 8246 } 8247 if (stateChangeResult.state == SupplicantState.ASSOCIATED) { 8248 // We completed the layer2 roaming part 8249 mAssociated = true; 8250 if (stateChangeResult.BSSID != null) { 8251 mTargetRoamBSSID = (String) stateChangeResult.BSSID; 8252 } 8253 } 8254 break; 8255 case CMD_ROAM_WATCHDOG_TIMER: 8256 if (roamWatchdogCount == message.arg1) { 8257 if (DBG) log("roaming watchdog! -> disconnect"); 8258 mRoamFailCount++; 8259 handleNetworkDisconnect(); 8260 mWifiNative.disconnect(); 8261 transitionTo(mDisconnectedState); 8262 } 8263 break; 8264 case WifiMonitor.NETWORK_CONNECTION_EVENT: 8265 if (mAssociated) { 8266 if (DBG) log("roaming and Network connection established"); 8267 mLastNetworkId = message.arg1; 8268 mLastBssid = (String) message.obj; 8269 mWifiInfo.setBSSID(mLastBssid); 8270 mWifiInfo.setNetworkId(mLastNetworkId); 8271 mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection( 8272 mLastBssid, true); 8273 sendNetworkStateChangeBroadcast(mLastBssid); 8274 8275 // We used to transition to ObtainingIpState in an 8276 // attempt to do DHCPv4 RENEWs on framework roams. 8277 // DHCP can take too long to time out, and we now rely 8278 // upon IpManager's use of IpReachabilityMonitor to 8279 // confirm our current network configuration. 8280 // 8281 // mIpManager.confirmConfiguration() is called within 8282 // the handling of SupplicantState.COMPLETED. 8283 transitionTo(mConnectedState); 8284 } else { 8285 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 8286 } 8287 break; 8288 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8289 // Throw away but only if it corresponds to the network we're roaming to 8290 String bssid = (String) message.obj; 8291 if (true) { 8292 String target = ""; 8293 if (mTargetRoamBSSID != null) target = mTargetRoamBSSID; 8294 log("NETWORK_DISCONNECTION_EVENT in roaming state" 8295 + " BSSID=" + bssid 8296 + " target=" + target); 8297 } 8298 if (bssid != null && bssid.equals(mTargetRoamBSSID)) { 8299 handleNetworkDisconnect(); 8300 transitionTo(mDisconnectedState); 8301 } 8302 break; 8303 case WifiMonitor.SSID_TEMP_DISABLED: 8304 // Auth error while roaming 8305 logd("SSID_TEMP_DISABLED nid=" + Integer.toString(mLastNetworkId) 8306 + " id=" + Integer.toString(message.arg1) 8307 + " isRoaming=" + isRoaming() 8308 + " roam=" + mAutoRoaming); 8309 if (message.arg1 == mLastNetworkId) { 8310 config = getCurrentWifiConfiguration(); 8311 if (config != null) { 8312 mWifiLogger.captureBugReportData( 8313 WifiLogger.REPORT_REASON_AUTOROAM_FAILURE); 8314 mWifiConfigManager.noteRoamingFailure(config, 8315 WifiConfiguration.ROAMING_FAILURE_AUTH_FAILURE); 8316 } 8317 handleNetworkDisconnect(); 8318 transitionTo(mDisconnectingState); 8319 } 8320 return NOT_HANDLED; 8321 case CMD_START_SCAN: 8322 deferMessage(message); 8323 break; 8324 default: 8325 return NOT_HANDLED; 8326 } 8327 return HANDLED; 8328 } 8329 8330 @Override 8331 public void exit() { 8332 logd("WifiStateMachine: Leaving Roaming state"); 8333 } 8334 } 8335 8336 class ConnectedState extends State { 8337 @Override 8338 public void enter() { 8339 String address; 8340 updateDefaultRouteMacAddress(1000); 8341 if (DBG) { 8342 log("Enter ConnectedState " 8343 + " mScreenOn=" + mScreenOn 8344 + " scanperiod=" 8345 + Integer.toString( 8346 mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get()) 8347 + " useGscan=" + mHalBasedPnoDriverSupported + "/" 8348 + mWifiConfigManager.enableHalBasedPno.get() 8349 + " mHalBasedPnoEnableInDevSettings " + mHalBasedPnoEnableInDevSettings); 8350 } 8351 if (mScreenOn 8352 && getEnableAutoJoinWhenAssociated()) { 8353 if (useHalBasedAutoJoinOffload()) { 8354 startGScanConnectedModeOffload("connectedEnter"); 8355 } else { 8356 // restart scan alarm 8357 startDelayedScan(mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get(), 8358 null, null); 8359 } 8360 } 8361 registerConnected(); 8362 lastConnectAttemptTimestamp = 0; 8363 targetWificonfiguration = null; 8364 // Paranoia 8365 linkDebouncing = false; 8366 8367 // Not roaming anymore 8368 mAutoRoaming = false; 8369 8370 if (testNetworkDisconnect) { 8371 testNetworkDisconnectCounter++; 8372 logd("ConnectedState Enter start disconnect test " + 8373 testNetworkDisconnectCounter); 8374 sendMessageDelayed(obtainMessage(CMD_TEST_NETWORK_DISCONNECT, 8375 testNetworkDisconnectCounter, 0), 15000); 8376 } 8377 8378 // Reenable all networks, allow for hidden networks to be scanned 8379 mWifiConfigManager.enableAllNetworks(); 8380 8381 mLastDriverRoamAttempt = 0; 8382 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 8383 //startLazyRoam(); 8384 } 8385 @Override 8386 public boolean processMessage(Message message) { 8387 WifiConfiguration config = null; 8388 logStateAndMessage(message, this); 8389 8390 switch (message.what) { 8391 case CMD_RESTART_AUTOJOIN_OFFLOAD: 8392 if ( (int)message.arg2 < mRestartAutoJoinOffloadCounter ) { 8393 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 8394 return HANDLED; 8395 } 8396 /* If we are still in Disconnected state after having discovered a valid 8397 * network this means autojoin didnt managed to associate to the network, 8398 * then restart PNO so as we will try associating to it again. 8399 */ 8400 if (useHalBasedAutoJoinOffload()) { 8401 if (mGScanStartTimeMilli == 0) { 8402 // If offload is not started, then start it... 8403 startGScanConnectedModeOffload("connectedRestart"); 8404 } else { 8405 // If offload is already started, then check if we need to increase 8406 // the scan period and restart the Gscan 8407 long now = System.currentTimeMillis(); 8408 if (mGScanStartTimeMilli != 0 && now > mGScanStartTimeMilli 8409 && ((now - mGScanStartTimeMilli) 8410 > DISCONNECTED_SHORT_SCANS_DURATION_MILLI) 8411 && (mGScanPeriodMilli 8412 < mWifiConfigManager 8413 .wifiDisconnectedLongScanIntervalMilli.get())) 8414 { 8415 startConnectedGScan("Connected restart gscan"); 8416 } 8417 } 8418 } 8419 break; 8420 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 8421 updateAssociatedScanPermission(); 8422 break; 8423 case CMD_UNWANTED_NETWORK: 8424 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { 8425 mWifiConfigManager.handleBadNetworkDisconnectReport( 8426 mLastNetworkId, mWifiInfo); 8427 mWifiNative.disconnect(); 8428 transitionTo(mDisconnectingState); 8429 } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN || 8430 message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { 8431 Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 8432 ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN" 8433 : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED")); 8434 config = getCurrentWifiConfiguration(); 8435 if (config != null) { 8436 // Disable autojoin 8437 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) { 8438 config.validatedInternetAccess = false; 8439 // Clear last-selected status, as being last-selected also avoids 8440 // disabling auto-join. 8441 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 8442 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 8443 WifiConfiguration.INVALID_NETWORK_ID); 8444 } 8445 mWifiConfigManager.updateNetworkSelectionStatus(config, 8446 WifiConfiguration.NetworkSelectionStatus 8447 .DISABLED_NO_INTERNET); 8448 } 8449 config.numNoInternetAccessReports += 1; 8450 mWifiConfigManager.writeKnownNetworkHistory(); 8451 } 8452 } 8453 return HANDLED; 8454 case CMD_NETWORK_STATUS: 8455 if (message.arg1 == NetworkAgent.VALID_NETWORK) { 8456 config = getCurrentWifiConfiguration(); 8457 if (config != null) { 8458 // re-enable autojoin 8459 config.numNoInternetAccessReports = 0; 8460 config.validatedInternetAccess = true; 8461 mWifiConfigManager.writeKnownNetworkHistory(); 8462 } 8463 } 8464 return HANDLED; 8465 case CMD_ACCEPT_UNVALIDATED: 8466 boolean accept = (message.arg1 != 0); 8467 config = getCurrentWifiConfiguration(); 8468 if (config != null) { 8469 config.noInternetAccessExpected = accept; 8470 } 8471 return HANDLED; 8472 case CMD_TEST_NETWORK_DISCONNECT: 8473 // Force a disconnect 8474 if (message.arg1 == testNetworkDisconnectCounter) { 8475 mWifiNative.disconnect(); 8476 } 8477 break; 8478 case CMD_ASSOCIATED_BSSID: 8479 // ASSOCIATING to a new BSSID while already connected, indicates 8480 // that driver is roaming 8481 mLastDriverRoamAttempt = System.currentTimeMillis(); 8482 String toBSSID = (String)message.obj; 8483 if (toBSSID != null && !toBSSID.equals(mWifiInfo.getBSSID())) { 8484 mWifiConfigManager.driverRoamedFrom(mWifiInfo); 8485 } 8486 return NOT_HANDLED; 8487 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8488 long lastRoam = 0; 8489 mWifiMetrics.endConnectionEvent( 8490 WifiMetrics.ConnectionEvent.LLF_NETWORK_DISCONNECTION, 8491 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8492 if (mLastDriverRoamAttempt != 0) { 8493 // Calculate time since last driver roam attempt 8494 lastRoam = System.currentTimeMillis() - mLastDriverRoamAttempt; 8495 mLastDriverRoamAttempt = 0; 8496 } 8497 if (unexpectedDisconnectedReason(message.arg2)) { 8498 mWifiLogger.captureBugReportData( 8499 WifiLogger.REPORT_REASON_UNEXPECTED_DISCONNECT); 8500 } 8501 config = getCurrentWifiConfiguration(); 8502 if (mScreenOn 8503 && !linkDebouncing 8504 && config != null 8505 && config.getNetworkSelectionStatus().isNetworkEnabled() 8506 && !mWifiConfigManager.isLastSelectedConfiguration(config) 8507 && (message.arg2 != 3 /* reason cannot be 3, i.e. locally generated */ 8508 || (lastRoam > 0 && lastRoam < 2000) /* unless driver is roaming */) 8509 && ((ScanResult.is24GHz(mWifiInfo.getFrequency()) 8510 && mWifiInfo.getRssi() > 8511 WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND) 8512 || (ScanResult.is5GHz(mWifiInfo.getFrequency()) 8513 && mWifiInfo.getRssi() > 8514 mWifiConfigManager.thresholdQualifiedRssi5.get()))) { 8515 // Start de-bouncing the L2 disconnection: 8516 // this L2 disconnection might be spurious. 8517 // Hence we allow 7 seconds for the state machine to try 8518 // to reconnect, go thru the 8519 // roaming cycle and enter Obtaining IP address 8520 // before signalling the disconnect to ConnectivityService and L3 8521 startScanForConfiguration(getCurrentWifiConfiguration(), false); 8522 linkDebouncing = true; 8523 8524 sendMessageDelayed(obtainMessage(CMD_DELAYED_NETWORK_DISCONNECT, 8525 0, mLastNetworkId), LINK_FLAPPING_DEBOUNCE_MSEC); 8526 if (DBG) { 8527 log("NETWORK_DISCONNECTION_EVENT in connected state" 8528 + " BSSID=" + mWifiInfo.getBSSID() 8529 + " RSSI=" + mWifiInfo.getRssi() 8530 + " freq=" + mWifiInfo.getFrequency() 8531 + " reason=" + message.arg2 8532 + " -> debounce"); 8533 } 8534 return HANDLED; 8535 } else { 8536 if (DBG) { 8537 log("NETWORK_DISCONNECTION_EVENT in connected state" 8538 + " BSSID=" + mWifiInfo.getBSSID() 8539 + " RSSI=" + mWifiInfo.getRssi() 8540 + " freq=" + mWifiInfo.getFrequency() 8541 + " was debouncing=" + linkDebouncing 8542 + " reason=" + message.arg2 8543 + " Network Selection Status=" + (config == null ? "Unavailable" 8544 : config.getNetworkSelectionStatus().getNetworkStatusString())); 8545 } 8546 } 8547 break; 8548 case CMD_AUTO_ROAM: 8549 // Clear the driver roam indication since we are attempting a framework roam 8550 mLastDriverRoamAttempt = 0; 8551 8552 /* Connect command coming from auto-join */ 8553 ScanResult candidate = (ScanResult)message.obj; 8554 String bssid = "any"; 8555 if (candidate != null) { 8556 bssid = candidate.BSSID; 8557 } 8558 int netId = mLastNetworkId; 8559 config = getCurrentWifiConfiguration(); 8560 8561 8562 if (config == null) { 8563 loge("AUTO_ROAM and no config, bail out..."); 8564 break; 8565 } 8566 8567 logd("CMD_AUTO_ROAM sup state " 8568 + mSupplicantStateTracker.getSupplicantStateName() 8569 + " my state " + getCurrentState().getName() 8570 + " nid=" + Integer.toString(netId) 8571 + " config " + config.configKey() 8572 + " roam=" + Integer.toString(message.arg2) 8573 + " to " + bssid 8574 + " targetRoamBSSID " + mTargetRoamBSSID); 8575 8576 setTargetBssid(config, bssid); 8577 mTargetNetworkId = netId; 8578 // Make sure the network is enabled, since supplicant will not re-enable it 8579 mWifiConfigManager.enableNetworkWithoutBroadcast(netId, false); 8580 8581 if (deferForUserInput(message, netId, false)) { 8582 break; 8583 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 8584 WifiConfiguration.USER_BANNED) { 8585 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 8586 WifiManager.NOT_AUTHORIZED); 8587 break; 8588 } 8589 8590 boolean ret = false; 8591 if (mLastNetworkId != netId) { 8592 mWifiMetrics.startConnectionEvent(mWifiInfo, config, 8593 WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); 8594 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 8595 WifiConfiguration.UNKNOWN_UID) && mWifiNative.reconnect()) { 8596 ret = true; 8597 } 8598 } else { 8599 mWifiMetrics.startConnectionEvent(mWifiInfo, config, 8600 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 8601 ret = mWifiNative.reassociate(); 8602 } 8603 if (ret) { 8604 lastConnectAttemptTimestamp = System.currentTimeMillis(); 8605 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 8606 8607 // replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 8608 mAutoRoaming = true; 8609 transitionTo(mRoamingState); 8610 8611 } else { 8612 loge("Failed to connect config: " + config + " netId: " + netId); 8613 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 8614 WifiManager.ERROR); 8615 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 8616 mWifiMetrics.endConnectionEvent( 8617 WifiMetrics.ConnectionEvent.LLF_CONNECT_NETWORK_FAILED, 8618 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8619 break; 8620 } 8621 break; 8622 case CMD_START_IP_PACKET_OFFLOAD: { 8623 int slot = message.arg1; 8624 int intervalSeconds = message.arg2; 8625 KeepalivePacketData pkt = (KeepalivePacketData) message.obj; 8626 byte[] dstMac; 8627 try { 8628 InetAddress gateway = RouteInfo.selectBestRoute( 8629 mLinkProperties.getRoutes(), pkt.dstAddress).getGateway(); 8630 String dstMacStr = macAddressFromRoute(gateway.getHostAddress()); 8631 dstMac = macAddressFromString(dstMacStr); 8632 } catch (NullPointerException|IllegalArgumentException e) { 8633 loge("Can't find MAC address for next hop to " + pkt.dstAddress); 8634 mNetworkAgent.onPacketKeepaliveEvent(slot, 8635 ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 8636 break; 8637 } 8638 pkt.dstMac = dstMac; 8639 int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds); 8640 mNetworkAgent.onPacketKeepaliveEvent(slot, result); 8641 break; 8642 } 8643 default: 8644 return NOT_HANDLED; 8645 } 8646 return HANDLED; 8647 } 8648 8649 @Override 8650 public void exit() { 8651 logd("WifiStateMachine: Leaving Connected state"); 8652 setScanAlarm(false); 8653 mLastDriverRoamAttempt = 0; 8654 8655 stopLazyRoam(); 8656 8657 mWhiteListedSsids = null; 8658 } 8659 } 8660 8661 class DisconnectingState extends State { 8662 8663 @Override 8664 public void enter() { 8665 8666 if (PDBG) { 8667 logd(" Enter DisconnectingState State scan interval " 8668 + mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get() 8669 + " mLegacyPnoEnabled= " + mLegacyPnoEnabled 8670 + " screenOn=" + mScreenOn); 8671 } 8672 8673 // Make sure we disconnect: we enter this state prior to connecting to a new 8674 // network, waiting for either a DISCONNECT event or a SUPPLICANT_STATE_CHANGE 8675 // event which in this case will be indicating that supplicant started to associate. 8676 // In some cases supplicant doesn't ignore the connect requests (it might not 8677 // find the target SSID in its cache), 8678 // Therefore we end up stuck that state, hence the need for the watchdog. 8679 disconnectingWatchdogCount++; 8680 logd("Start Disconnecting Watchdog " + disconnectingWatchdogCount); 8681 sendMessageDelayed(obtainMessage(CMD_DISCONNECTING_WATCHDOG_TIMER, 8682 disconnectingWatchdogCount, 0), DISCONNECTING_GUARD_TIMER_MSEC); 8683 } 8684 8685 @Override 8686 public boolean processMessage(Message message) { 8687 logStateAndMessage(message, this); 8688 switch (message.what) { 8689 case CMD_SET_OPERATIONAL_MODE: 8690 if (message.arg1 != CONNECT_MODE) { 8691 deferMessage(message); 8692 } 8693 break; 8694 case CMD_START_SCAN: 8695 deferMessage(message); 8696 return HANDLED; 8697 case CMD_DISCONNECTING_WATCHDOG_TIMER: 8698 if (disconnectingWatchdogCount == message.arg1) { 8699 if (DBG) log("disconnecting watchdog! -> disconnect"); 8700 handleNetworkDisconnect(); 8701 transitionTo(mDisconnectedState); 8702 } 8703 break; 8704 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 8705 /** 8706 * If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT 8707 * we have missed the network disconnection, transition to mDisconnectedState 8708 * and handle the rest of the events there 8709 */ 8710 deferMessage(message); 8711 handleNetworkDisconnect(); 8712 transitionTo(mDisconnectedState); 8713 break; 8714 default: 8715 return NOT_HANDLED; 8716 } 8717 return HANDLED; 8718 } 8719 } 8720 8721 class DisconnectedState extends State { 8722 @Override 8723 public void enter() { 8724 // We dont scan frequently if this is a temporary disconnect 8725 // due to p2p 8726 if (mTemporarilyDisconnectWifi) { 8727 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 8728 return; 8729 } 8730 8731 if (PDBG) { 8732 logd(" Enter DisconnectedState scan interval " 8733 + mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get() 8734 + " mLegacyPnoEnabled= " + mLegacyPnoEnabled 8735 + " screenOn=" + mScreenOn 8736 + " useGscan=" + mHalBasedPnoDriverSupported + "/" 8737 + mWifiConfigManager.enableHalBasedPno.get()); 8738 } 8739 8740 /** clear the roaming state, if we were roaming, we failed */ 8741 mAutoRoaming = false; 8742 8743 if (useHalBasedAutoJoinOffload()) { 8744 startGScanDisconnectedModeOffload("disconnectedEnter"); 8745 } else { 8746 if (mScreenOn) { 8747 /** 8748 * screen lit and => start scan immediately 8749 */ 8750 startScan(UNKNOWN_SCAN_SOURCE, 0, null, null); 8751 } else { 8752 /** 8753 * screen dark and PNO supported => scan alarm disabled 8754 */ 8755 if (mBackgroundScanSupported) { 8756 /* If a regular scan result is pending, do not initiate background 8757 * scan until the scan results are returned. This is needed because 8758 * initiating a background scan will cancel the regular scan and 8759 * scan results will not be returned until background scanning is 8760 * cleared 8761 */ 8762 if (!mIsScanOngoing) { 8763 enableBackgroundScan(true); 8764 } 8765 } else { 8766 setScanAlarm(true); 8767 } 8768 } 8769 } 8770 8771 /** 8772 * If we have no networks saved, the supplicant stops doing the periodic scan. 8773 * The scans are useful to notify the user of the presence of an open network. 8774 * Note that these are not wake up scans. 8775 */ 8776 if (mNoNetworksPeriodicScan != 0 && !mP2pConnected.get() 8777 && mWifiConfigManager.getConfiguredNetworks().size() == 0) { 8778 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8779 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8780 } 8781 8782 mDisconnectedTimeStamp = System.currentTimeMillis(); 8783 mDisconnectedPnoAlarmCount = 0; 8784 } 8785 @Override 8786 public boolean processMessage(Message message) { 8787 boolean ret = HANDLED; 8788 8789 logStateAndMessage(message, this); 8790 8791 switch (message.what) { 8792 case CMD_NO_NETWORKS_PERIODIC_SCAN: 8793 if (mP2pConnected.get()) break; 8794 if (mNoNetworksPeriodicScan != 0 && message.arg1 == mPeriodicScanToken && 8795 mWifiConfigManager.getConfiguredNetworks().size() == 0) { 8796 startScan(UNKNOWN_SCAN_SOURCE, -1, null, null); 8797 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8798 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8799 } 8800 break; 8801 case WifiManager.FORGET_NETWORK: 8802 case CMD_REMOVE_NETWORK: 8803 case CMD_REMOVE_APP_CONFIGURATIONS: 8804 case CMD_REMOVE_USER_CONFIGURATIONS: 8805 // Set up a delayed message here. After the forget/remove is handled 8806 // the handled delayed message will determine if there is a need to 8807 // scan and continue 8808 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8809 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8810 ret = NOT_HANDLED; 8811 break; 8812 case CMD_SET_OPERATIONAL_MODE: 8813 if (message.arg1 != CONNECT_MODE) { 8814 mOperationalMode = message.arg1; 8815 8816 mWifiConfigManager.disableAllNetworks(); 8817 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 8818 mWifiP2pChannel.sendMessage(CMD_DISABLE_P2P_REQ); 8819 setWifiState(WIFI_STATE_DISABLED); 8820 } 8821 transitionTo(mScanModeState); 8822 } 8823 mWifiConfigManager. 8824 setAndEnableLastSelectedConfiguration( 8825 WifiConfiguration.INVALID_NETWORK_ID); 8826 break; 8827 /* Ignore network disconnect */ 8828 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8829 // Interpret this as an L2 connection failure 8830 break; 8831 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 8832 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 8833 if (DBG) { 8834 logd("SUPPLICANT_STATE_CHANGE_EVENT state=" + stateChangeResult.state + 8835 " -> state= " + WifiInfo.getDetailedStateOf(stateChangeResult.state) 8836 + " debouncing=" + linkDebouncing); 8837 } 8838 setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state)); 8839 /* ConnectModeState does the rest of the handling */ 8840 ret = NOT_HANDLED; 8841 break; 8842 case CMD_START_SCAN: 8843 if (!checkOrDeferScanAllowed(message)) { 8844 // The scan request was rescheduled 8845 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 8846 return HANDLED; 8847 } 8848 if (message.arg1 == SCAN_ALARM_SOURCE) { 8849 // Check if the CMD_START_SCAN message is obsolete (and thus if it should 8850 // not be processed) and restart the scan 8851 int period = 8852 mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get(); 8853 if (mP2pConnected.get()) { 8854 period = (int) mFacade.getLongSetting(mContext, 8855 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, 8856 period); 8857 } 8858 if (!checkAndRestartDelayedScan(message.arg2, 8859 true, period, null, null)) { 8860 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 8861 logd("Disconnected CMD_START_SCAN source " 8862 + message.arg1 8863 + " " + message.arg2 + ", " + mDelayedScanCounter 8864 + " -> obsolete"); 8865 return HANDLED; 8866 } 8867 /* Disable background scan temporarily during a regular scan */ 8868 enableBackgroundScan(false); 8869 handleScanRequest(message); 8870 ret = HANDLED; 8871 } else { 8872 8873 /* 8874 * The SCAN request is not handled in this state and 8875 * would eventually might/will get handled in the 8876 * parent's state. The PNO, if already enabled had to 8877 * get disabled before the SCAN trigger. Hence, stop 8878 * the PNO if already enabled in this state, though the 8879 * SCAN request is not handled(PNO disable before the 8880 * SCAN trigger in any other state is not the right 8881 * place to issue). 8882 */ 8883 8884 enableBackgroundScan(false); 8885 ret = NOT_HANDLED; 8886 } 8887 break; 8888 case CMD_RESTART_AUTOJOIN_OFFLOAD: 8889 if ( (int)message.arg2 < mRestartAutoJoinOffloadCounter ) { 8890 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 8891 return HANDLED; 8892 } 8893 /* If we are still in Disconnected state after having discovered a valid 8894 * network this means autojoin didnt managed to associate to the network, 8895 * then restart PNO so as we will try associating to it again. 8896 */ 8897 if (useHalBasedAutoJoinOffload()) { 8898 if (mGScanStartTimeMilli == 0) { 8899 // If offload is not started, then start it... 8900 startGScanDisconnectedModeOffload("disconnectedRestart"); 8901 } else { 8902 // If offload is already started, then check if we need to increase 8903 // the scan period and restart the Gscan 8904 long now = System.currentTimeMillis(); 8905 if (mGScanStartTimeMilli != 0 && now > mGScanStartTimeMilli 8906 && ((now - mGScanStartTimeMilli) 8907 > DISCONNECTED_SHORT_SCANS_DURATION_MILLI) 8908 && (mGScanPeriodMilli 8909 < mWifiConfigManager 8910 .wifiDisconnectedLongScanIntervalMilli.get())) 8911 { 8912 startDisconnectedGScan("disconnected restart gscan"); 8913 } 8914 } 8915 } else { 8916 // If we are still disconnected for a short while after having found a 8917 // network thru PNO, then something went wrong, and for some reason we 8918 // couldn't join this network. 8919 // It might be due to a SW bug in supplicant or the wifi stack, or an 8920 // interoperability issue, or we try to join a bad bss and failed 8921 // In that case we want to restart pno so as to make sure that we will 8922 // attempt again to join that network. 8923 if (!mScreenOn && !mIsScanOngoing && mBackgroundScanSupported) { 8924 enableBackgroundScan(false); 8925 enableBackgroundScan(true); 8926 } 8927 return HANDLED; 8928 } 8929 break; 8930 case WifiMonitor.SCAN_RESULTS_EVENT: 8931 case WifiMonitor.SCAN_FAILED_EVENT: 8932 /* Re-enable background scan when a pending scan result is received */ 8933 if (!mScreenOn && mIsScanOngoing 8934 && mBackgroundScanSupported 8935 && !useHalBasedAutoJoinOffload()) { 8936 enableBackgroundScan(true); 8937 } else if (!mScreenOn 8938 && !mIsScanOngoing 8939 && mBackgroundScanSupported 8940 && !useHalBasedAutoJoinOffload()) { 8941 // We receive scan results from legacy PNO, hence restart the PNO alarm 8942 int delay; 8943 if (mDisconnectedPnoAlarmCount < 1) { 8944 delay = 30 * 1000; 8945 } else if (mDisconnectedPnoAlarmCount < 3) { 8946 delay = 60 * 1000; 8947 } else { 8948 delay = 360 * 1000; 8949 } 8950 mDisconnectedPnoAlarmCount++; 8951 if (VDBG) { 8952 logd("Starting PNO alarm " + delay); 8953 } 8954 mAlarmManager.set(AlarmManager.RTC_WAKEUP, 8955 System.currentTimeMillis() + delay, 8956 mPnoIntent); 8957 } 8958 /* Handled in parent state */ 8959 ret = NOT_HANDLED; 8960 break; 8961 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 8962 NetworkInfo info = (NetworkInfo) message.obj; 8963 mP2pConnected.set(info.isConnected()); 8964 if (mP2pConnected.get()) { 8965 int defaultInterval = mContext.getResources().getInteger( 8966 R.integer.config_wifi_scan_interval_p2p_connected); 8967 long scanIntervalMs = mFacade.getLongSetting(mContext, 8968 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, 8969 defaultInterval); 8970 mWifiNative.setScanInterval((int) scanIntervalMs/1000); 8971 } else if (mWifiConfigManager.getConfiguredNetworks().size() == 0) { 8972 if (DBG) log("Turn on scanning after p2p disconnected"); 8973 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8974 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8975 } else { 8976 // If P2P is not connected and there are saved networks, then restart 8977 // scanning at the normal period. This is necessary because scanning might 8978 // have been disabled altogether if WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS 8979 // was set to zero. 8980 if (useHalBasedAutoJoinOffload()) { 8981 startGScanDisconnectedModeOffload("p2pRestart"); 8982 } else { 8983 startDelayedScan( 8984 mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get(), 8985 null, null); 8986 } 8987 } 8988 break; 8989 case CMD_RECONNECT: 8990 case CMD_REASSOCIATE: 8991 if (mTemporarilyDisconnectWifi) { 8992 // Drop a third party reconnect/reassociate if STA is 8993 // temporarily disconnected for p2p 8994 break; 8995 } else { 8996 // ConnectModeState handles it 8997 ret = NOT_HANDLED; 8998 } 8999 break; 9000 case CMD_SCREEN_STATE_CHANGED: 9001 handleScreenStateChanged(message.arg1 != 0); 9002 break; 9003 default: 9004 ret = NOT_HANDLED; 9005 } 9006 return ret; 9007 } 9008 9009 @Override 9010 public void exit() { 9011 mDisconnectedPnoAlarmCount = 0; 9012 /* No need for a background scan upon exit from a disconnected state */ 9013 enableBackgroundScan(false); 9014 setScanAlarm(false); 9015 mAlarmManager.cancel(mPnoIntent); 9016 } 9017 } 9018 9019 class WpsRunningState extends State { 9020 // Tracks the source to provide a reply 9021 private Message mSourceMessage; 9022 @Override 9023 public void enter() { 9024 mSourceMessage = Message.obtain(getCurrentMessage()); 9025 } 9026 @Override 9027 public boolean processMessage(Message message) { 9028 logStateAndMessage(message, this); 9029 9030 switch (message.what) { 9031 case WifiMonitor.WPS_SUCCESS_EVENT: 9032 // Ignore intermediate success, wait for full connection 9033 break; 9034 case WifiMonitor.NETWORK_CONNECTION_EVENT: 9035 replyToMessage(mSourceMessage, WifiManager.WPS_COMPLETED); 9036 mSourceMessage.recycle(); 9037 mSourceMessage = null; 9038 deferMessage(message); 9039 transitionTo(mDisconnectedState); 9040 break; 9041 case WifiMonitor.WPS_OVERLAP_EVENT: 9042 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 9043 WifiManager.WPS_OVERLAP_ERROR); 9044 mSourceMessage.recycle(); 9045 mSourceMessage = null; 9046 transitionTo(mDisconnectedState); 9047 break; 9048 case WifiMonitor.WPS_FAIL_EVENT: 9049 // Arg1 has the reason for the failure 9050 if ((message.arg1 != WifiManager.ERROR) || (message.arg2 != 0)) { 9051 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1); 9052 mSourceMessage.recycle(); 9053 mSourceMessage = null; 9054 transitionTo(mDisconnectedState); 9055 } else { 9056 if (DBG) log("Ignore unspecified fail event during WPS connection"); 9057 } 9058 break; 9059 case WifiMonitor.WPS_TIMEOUT_EVENT: 9060 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 9061 WifiManager.WPS_TIMED_OUT); 9062 mSourceMessage.recycle(); 9063 mSourceMessage = null; 9064 transitionTo(mDisconnectedState); 9065 break; 9066 case WifiManager.START_WPS: 9067 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS); 9068 break; 9069 case WifiManager.CANCEL_WPS: 9070 if (mWifiNative.cancelWps()) { 9071 replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED); 9072 } else { 9073 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR); 9074 } 9075 transitionTo(mDisconnectedState); 9076 break; 9077 /** 9078 * Defer all commands that can cause connections to a different network 9079 * or put the state machine out of connect mode 9080 */ 9081 case CMD_STOP_DRIVER: 9082 case CMD_SET_OPERATIONAL_MODE: 9083 case WifiManager.CONNECT_NETWORK: 9084 case CMD_ENABLE_NETWORK: 9085 case CMD_RECONNECT: 9086 case CMD_REASSOCIATE: 9087 case CMD_ENABLE_ALL_NETWORKS: 9088 deferMessage(message); 9089 break; 9090 case CMD_AUTO_CONNECT: 9091 case CMD_AUTO_ROAM: 9092 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 9093 return HANDLED; 9094 case CMD_START_SCAN: 9095 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 9096 return HANDLED; 9097 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 9098 if (DBG) log("Network connection lost"); 9099 handleNetworkDisconnect(); 9100 break; 9101 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 9102 if (DBG) log("Ignore Assoc reject event during WPS Connection"); 9103 break; 9104 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 9105 // Disregard auth failure events during WPS connection. The 9106 // EAP sequence is retried several times, and there might be 9107 // failures (especially for wps pin). We will get a WPS_XXX 9108 // event at the end of the sequence anyway. 9109 if (DBG) log("Ignore auth failure during WPS connection"); 9110 break; 9111 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 9112 // Throw away supplicant state changes when WPS is running. 9113 // We will start getting supplicant state changes once we get 9114 // a WPS success or failure 9115 break; 9116 default: 9117 return NOT_HANDLED; 9118 } 9119 return HANDLED; 9120 } 9121 9122 @Override 9123 public void exit() { 9124 mWifiConfigManager.enableAllNetworks(); 9125 mWifiConfigManager.loadConfiguredNetworks(); 9126 } 9127 } 9128 9129 class SoftApState extends State { 9130 private SoftApManager mSoftApManager; 9131 9132 private class SoftApListener implements SoftApManager.Listener { 9133 @Override 9134 public void onStateChanged(int state, int reason) { 9135 if (state == WIFI_AP_STATE_DISABLED) { 9136 sendMessage(CMD_AP_STOPPED); 9137 } else if (state == WIFI_AP_STATE_FAILED) { 9138 sendMessage(CMD_START_AP_FAILURE); 9139 } 9140 9141 setWifiApState(state, reason); 9142 } 9143 } 9144 9145 @Override 9146 public void enter() { 9147 final Message message = getCurrentMessage(); 9148 if (message.what == CMD_START_AP) { 9149 WifiConfiguration config = (WifiConfiguration) message.obj; 9150 9151 if (config == null) { 9152 /** 9153 * Configuration not provided in the command, fallback to use the current 9154 * configuration. 9155 */ 9156 config = mWifiApConfigStore.getApConfiguration(); 9157 } else { 9158 /* Update AP configuration. */ 9159 mWifiApConfigStore.setApConfiguration(config); 9160 } 9161 9162 checkAndSetConnectivityInstance(); 9163 mSoftApManager = mFacade.makeSoftApManager( 9164 mContext, getHandler().getLooper(), mWifiNative, mNwService, 9165 mCm, getCurrentCountryCode(), 9166 mWifiApConfigStore.getAllowed2GChannel(), 9167 new SoftApListener()); 9168 mSoftApManager.start(config); 9169 } else { 9170 throw new RuntimeException("Illegal transition to SoftApState: " + message); 9171 } 9172 } 9173 9174 @Override 9175 public void exit() { 9176 mSoftApManager = null; 9177 } 9178 9179 @Override 9180 public boolean processMessage(Message message) { 9181 logStateAndMessage(message, this); 9182 9183 switch(message.what) { 9184 case CMD_START_AP: 9185 /* Ignore start command when it is starting/started. */ 9186 break; 9187 case CMD_STOP_AP: 9188 mSoftApManager.stop(); 9189 break; 9190 case CMD_START_AP_FAILURE: 9191 transitionTo(mInitialState); 9192 break; 9193 case CMD_AP_STOPPED: 9194 transitionTo(mInitialState); 9195 break; 9196 default: 9197 return NOT_HANDLED; 9198 } 9199 return HANDLED; 9200 } 9201 } 9202 9203 /** 9204 * State machine initiated requests can have replyTo set to null indicating 9205 * there are no recepients, we ignore those reply actions. 9206 */ 9207 private void replyToMessage(Message msg, int what) { 9208 if (msg.replyTo == null) return; 9209 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 9210 mReplyChannel.replyToMessage(msg, dstMsg); 9211 } 9212 9213 private void replyToMessage(Message msg, int what, int arg1) { 9214 if (msg.replyTo == null) return; 9215 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 9216 dstMsg.arg1 = arg1; 9217 mReplyChannel.replyToMessage(msg, dstMsg); 9218 } 9219 9220 private void replyToMessage(Message msg, int what, Object obj) { 9221 if (msg.replyTo == null) return; 9222 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 9223 dstMsg.obj = obj; 9224 mReplyChannel.replyToMessage(msg, dstMsg); 9225 } 9226 9227 /** 9228 * arg2 on the source message has a unique id that needs to be retained in replies 9229 * to match the request 9230 * <p>see WifiManager for details 9231 */ 9232 private Message obtainMessageWithWhatAndArg2(Message srcMsg, int what) { 9233 Message msg = Message.obtain(); 9234 msg.what = what; 9235 msg.arg2 = srcMsg.arg2; 9236 return msg; 9237 } 9238 9239 /** 9240 * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT 9241 * @param msg Must have a WifiConfiguration obj to succeed 9242 */ 9243 private void broadcastWifiCredentialChanged(int wifiCredentialEventType, 9244 WifiConfiguration config) { 9245 if (config != null && config.preSharedKey != null) { 9246 Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); 9247 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); 9248 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, 9249 wifiCredentialEventType); 9250 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT, 9251 android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE); 9252 } 9253 } 9254 9255 private static int parseHex(char ch) { 9256 if ('0' <= ch && ch <= '9') { 9257 return ch - '0'; 9258 } else if ('a' <= ch && ch <= 'f') { 9259 return ch - 'a' + 10; 9260 } else if ('A' <= ch && ch <= 'F') { 9261 return ch - 'A' + 10; 9262 } else { 9263 throw new NumberFormatException("" + ch + " is not a valid hex digit"); 9264 } 9265 } 9266 9267 private byte[] parseHex(String hex) { 9268 /* This only works for good input; don't throw bad data at it */ 9269 if (hex == null) { 9270 return new byte[0]; 9271 } 9272 9273 if (hex.length() % 2 != 0) { 9274 throw new NumberFormatException(hex + " is not a valid hex string"); 9275 } 9276 9277 byte[] result = new byte[(hex.length())/2 + 1]; 9278 result[0] = (byte) ((hex.length())/2); 9279 for (int i = 0, j = 1; i < hex.length(); i += 2, j++) { 9280 int val = parseHex(hex.charAt(i)) * 16 + parseHex(hex.charAt(i+1)); 9281 byte b = (byte) (val & 0xFF); 9282 result[j] = b; 9283 } 9284 9285 return result; 9286 } 9287 9288 private static String makeHex(byte[] bytes) { 9289 StringBuilder sb = new StringBuilder(); 9290 for (byte b : bytes) { 9291 sb.append(String.format("%02x", b)); 9292 } 9293 return sb.toString(); 9294 } 9295 9296 private static String makeHex(byte[] bytes, int from, int len) { 9297 StringBuilder sb = new StringBuilder(); 9298 for (int i = 0; i < len; i++) { 9299 sb.append(String.format("%02x", bytes[from+i])); 9300 } 9301 return sb.toString(); 9302 } 9303 9304 private static byte[] concat(byte[] array1, byte[] array2, byte[] array3) { 9305 9306 int len = array1.length + array2.length + array3.length; 9307 9308 if (array1.length != 0) { 9309 len++; /* add another byte for size */ 9310 } 9311 9312 if (array2.length != 0) { 9313 len++; /* add another byte for size */ 9314 } 9315 9316 if (array3.length != 0) { 9317 len++; /* add another byte for size */ 9318 } 9319 9320 byte[] result = new byte[len]; 9321 9322 int index = 0; 9323 if (array1.length != 0) { 9324 result[index] = (byte) (array1.length & 0xFF); 9325 index++; 9326 for (byte b : array1) { 9327 result[index] = b; 9328 index++; 9329 } 9330 } 9331 9332 if (array2.length != 0) { 9333 result[index] = (byte) (array2.length & 0xFF); 9334 index++; 9335 for (byte b : array2) { 9336 result[index] = b; 9337 index++; 9338 } 9339 } 9340 9341 if (array3.length != 0) { 9342 result[index] = (byte) (array3.length & 0xFF); 9343 index++; 9344 for (byte b : array3) { 9345 result[index] = b; 9346 index++; 9347 } 9348 } 9349 return result; 9350 } 9351 9352 private static byte[] concatHex(byte[] array1, byte[] array2) { 9353 9354 int len = array1.length + array2.length; 9355 9356 byte[] result = new byte[len]; 9357 9358 int index = 0; 9359 if (array1.length != 0) { 9360 for (byte b : array1) { 9361 result[index] = b; 9362 index++; 9363 } 9364 } 9365 9366 if (array2.length != 0) { 9367 for (byte b : array2) { 9368 result[index] = b; 9369 index++; 9370 } 9371 } 9372 9373 return result; 9374 } 9375 9376 void handleGsmAuthRequest(SimAuthRequestData requestData) { 9377 if (targetWificonfiguration == null 9378 || targetWificonfiguration.networkId == requestData.networkId) { 9379 logd("id matches targetWifiConfiguration"); 9380 } else { 9381 logd("id does not match targetWifiConfiguration"); 9382 return; 9383 } 9384 9385 TelephonyManager tm = (TelephonyManager) 9386 mContext.getSystemService(Context.TELEPHONY_SERVICE); 9387 9388 if (tm != null) { 9389 StringBuilder sb = new StringBuilder(); 9390 for (String challenge : requestData.data) { 9391 9392 if (challenge == null || challenge.isEmpty()) 9393 continue; 9394 logd("RAND = " + challenge); 9395 9396 byte[] rand = null; 9397 try { 9398 rand = parseHex(challenge); 9399 } catch (NumberFormatException e) { 9400 loge("malformed challenge"); 9401 continue; 9402 } 9403 9404 String base64Challenge = android.util.Base64.encodeToString( 9405 rand, android.util.Base64.NO_WRAP); 9406 /* 9407 * First, try with appType = 2 => USIM according to 9408 * com.android.internal.telephony.PhoneConstants#APPTYPE_xxx 9409 */ 9410 int appType = 2; 9411 String tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge); 9412 if (tmResponse == null) { 9413 /* Then, in case of failure, issue may be due to sim type, retry as a simple sim 9414 * appType = 1 => SIM 9415 */ 9416 appType = 1; 9417 tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge); 9418 } 9419 logv("Raw Response - " + tmResponse); 9420 9421 if (tmResponse != null && tmResponse.length() > 4) { 9422 byte[] result = android.util.Base64.decode(tmResponse, 9423 android.util.Base64.DEFAULT); 9424 logv("Hex Response -" + makeHex(result)); 9425 int sres_len = result[0]; 9426 String sres = makeHex(result, 1, sres_len); 9427 int kc_offset = 1+sres_len; 9428 int kc_len = result[kc_offset]; 9429 String kc = makeHex(result, 1 + kc_offset, kc_len); 9430 sb.append(":" + kc + ":" + sres); 9431 logv("kc:" + kc + " sres:" + sres); 9432 9433 String response = sb.toString(); 9434 logv("Supplicant Response -" + response); 9435 mWifiNative.simAuthResponse(requestData.networkId, "GSM-AUTH", response); 9436 } else { 9437 loge("bad response - " + tmResponse); 9438 mWifiNative.simAuthFailedResponse(requestData.networkId); 9439 } 9440 } 9441 9442 } else { 9443 loge("could not get telephony manager"); 9444 mWifiNative.simAuthFailedResponse(requestData.networkId); 9445 } 9446 } 9447 9448 void handle3GAuthRequest(SimAuthRequestData requestData) { 9449 StringBuilder sb = new StringBuilder(); 9450 byte[] rand = null; 9451 byte[] authn = null; 9452 String res_type = "UMTS-AUTH"; 9453 9454 if (targetWificonfiguration == null 9455 || targetWificonfiguration.networkId == requestData.networkId) { 9456 logd("id matches targetWifiConfiguration"); 9457 } else { 9458 logd("id does not match targetWifiConfiguration"); 9459 return; 9460 } 9461 if (requestData.data.length == 2) { 9462 try { 9463 rand = parseHex(requestData.data[0]); 9464 authn = parseHex(requestData.data[1]); 9465 } catch (NumberFormatException e) { 9466 loge("malformed challenge"); 9467 } 9468 } else { 9469 loge("malformed challenge"); 9470 } 9471 9472 String tmResponse = ""; 9473 if (rand != null && authn != null) { 9474 String base64Challenge = android.util.Base64.encodeToString( 9475 concatHex(rand,authn), android.util.Base64.NO_WRAP); 9476 9477 TelephonyManager tm = (TelephonyManager) 9478 mContext.getSystemService(Context.TELEPHONY_SERVICE); 9479 if (tm != null) { 9480 int appType = 2; // 2 => USIM 9481 tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge); 9482 logv("Raw Response - " + tmResponse); 9483 } else { 9484 loge("could not get telephony manager"); 9485 } 9486 } 9487 9488 boolean good_response = false; 9489 if (tmResponse != null && tmResponse.length() > 4) { 9490 byte[] result = android.util.Base64.decode(tmResponse, 9491 android.util.Base64.DEFAULT); 9492 loge("Hex Response - " + makeHex(result)); 9493 byte tag = result[0]; 9494 if (tag == (byte) 0xdb) { 9495 logv("successful 3G authentication "); 9496 int res_len = result[1]; 9497 String res = makeHex(result, 2, res_len); 9498 int ck_len = result[res_len + 2]; 9499 String ck = makeHex(result, res_len + 3, ck_len); 9500 int ik_len = result[res_len + ck_len + 3]; 9501 String ik = makeHex(result, res_len + ck_len + 4, ik_len); 9502 sb.append(":" + ik + ":" + ck + ":" + res); 9503 logv("ik:" + ik + "ck:" + ck + " res:" + res); 9504 good_response = true; 9505 } else if (tag == (byte) 0xdc) { 9506 loge("synchronisation failure"); 9507 int auts_len = result[1]; 9508 String auts = makeHex(result, 2, auts_len); 9509 res_type = "UMTS-AUTS"; 9510 sb.append(":" + auts); 9511 logv("auts:" + auts); 9512 good_response = true; 9513 } else { 9514 loge("bad response - unknown tag = " + tag); 9515 } 9516 } else { 9517 loge("bad response - " + tmResponse); 9518 } 9519 9520 if (good_response) { 9521 String response = sb.toString(); 9522 logv("Supplicant Response -" + response); 9523 mWifiNative.simAuthResponse(requestData.networkId, res_type, response); 9524 } else { 9525 mWifiNative.umtsAuthFailedResponse(requestData.networkId); 9526 } 9527 } 9528 9529 public int getCurrentUserId() { 9530 return mCurrentUserId; 9531 } 9532 9533 private boolean isCurrentUserProfile(int userId) { 9534 if (userId == mCurrentUserId) { 9535 return true; 9536 } 9537 final UserInfo parent = mUserManager.getProfileParent(userId); 9538 return parent != null && parent.id == mCurrentUserId; 9539 } 9540 9541 public List<UserInfo> getCurrentUserProfiles() { 9542 return mUserManager.getProfiles(mCurrentUserId); 9543 } 9544 9545 /** 9546 * @param reason reason code from supplicant on network disconnected event 9547 * @return true if this is a suspicious disconnect 9548 */ 9549 static boolean unexpectedDisconnectedReason(int reason) { 9550 return reason == 2 // PREV_AUTH_NOT_VALID 9551 || reason == 6 // CLASS2_FRAME_FROM_NONAUTH_STA 9552 || reason == 7 // FRAME_FROM_NONASSOC_STA 9553 || reason == 8 // STA_HAS_LEFT 9554 || reason == 9 // STA_REQ_ASSOC_WITHOUT_AUTH 9555 || reason == 14 // MICHAEL_MIC_FAILURE 9556 || reason == 15 // 4WAY_HANDSHAKE_TIMEOUT 9557 || reason == 16 // GROUP_KEY_UPDATE_TIMEOUT 9558 || reason == 18 // GROUP_CIPHER_NOT_VALID 9559 || reason == 19 // PAIRWISE_CIPHER_NOT_VALID 9560 || reason == 23 // IEEE_802_1X_AUTH_FAILED 9561 || reason == 34; // DISASSOC_LOW_ACK 9562 } 9563 9564 /** 9565 * Update WifiMetrics before dumping 9566 */ 9567 void updateWifiMetrics() { 9568 int numSavedNetworks = mWifiConfigManager.getConfiguredNetworksSize(); 9569 int numOpenNetworks = 0; 9570 int numPersonalNetworks = 0; 9571 int numEnterpriseNetworks = 0; 9572 int numNetworksAddedByUser = 0; 9573 int numNetworksAddedByApps = 0; 9574 for (WifiConfiguration config : mWifiConfigManager.getConfiguredNetworks()) { 9575 if (config.allowedAuthAlgorithms.get(WifiConfiguration.AuthAlgorithm.OPEN)) { 9576 numOpenNetworks++; 9577 } else if (config.isEnterprise()) { 9578 numEnterpriseNetworks++; 9579 } else { 9580 numPersonalNetworks++; 9581 } 9582 if (config.selfAdded) { 9583 numNetworksAddedByUser++; 9584 } else { 9585 numNetworksAddedByApps++; 9586 } 9587 } 9588 mWifiMetrics.setNumSavedNetworks(numSavedNetworks); 9589 mWifiMetrics.setNumOpenNetworks(numOpenNetworks); 9590 mWifiMetrics.setNumPersonalNetworks(numPersonalNetworks); 9591 mWifiMetrics.setNumEnterpriseNetworks(numEnterpriseNetworks); 9592 mWifiMetrics.setNumNetworksAddedByUser(numNetworksAddedByUser); 9593 mWifiMetrics.setNumNetworksAddedByApps(numNetworksAddedByApps); 9594 9595 /* <TODO> decide how to access WifiServiecImpl.isLocationEnabled() or if to do it manually 9596 mWifiMetrics.setIsLocationEnabled(Settings.Secure.getInt( 9597 mContext.getContentResolver(), 9598 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) 9599 != Settings.Secure.LOCATION_MODE_OFF); 9600 */ 9601 9602 /* <TODO> decide how statemachine will access WifiSettingsStore 9603 mWifiMetrics.setIsScanningAlwaysEnabled(mSettingsStore.isScanningAlwaysAvailable()); 9604 */ 9605 } 9606 9607 private static String getLinkPropertiesSummary(LinkProperties lp) { 9608 List<String> attributes = new ArrayList(6); 9609 if (lp.hasIPv4Address()) { 9610 attributes.add("v4"); 9611 } 9612 if (lp.hasIPv4DefaultRoute()) { 9613 attributes.add("v4r"); 9614 } 9615 if (lp.hasIPv4DnsServer()) { 9616 attributes.add("v4dns"); 9617 } 9618 if (lp.hasGlobalIPv6Address()) { 9619 attributes.add("v6"); 9620 } 9621 if (lp.hasIPv6DefaultRoute()) { 9622 attributes.add("v6r"); 9623 } 9624 if (lp.hasIPv6DnsServer()) { 9625 attributes.add("v6dns"); 9626 } 9627 9628 // TODO: Replace with String.join(" ", attributes) once we're fully on JDK 8. 9629 StringBuilder sb = new StringBuilder(); 9630 boolean first = true; 9631 for (String attr : attributes) { 9632 if (!first) { 9633 sb.append(" "); 9634 } else { 9635 first = false; 9636 } 9637 sb.append(attr); 9638 } 9639 return sb.toString(); 9640 } 9641 9642 /** 9643 * Try to connect to the network of candidate. According to the current connected network, this 9644 * API determines whether no action, disconnect and connect, or roaming. 9645 * 9646 * @param candidate the candidate network to connect to 9647 */ 9648 private void tryToConnectToNetwork(WifiConfiguration candidate) { 9649 if (candidate == null) { 9650 if (DBG) { 9651 Log.d(TAG, "Try to connect to null, give up"); 9652 } 9653 return; 9654 } 9655 9656 ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate(); 9657 if (scanResultCandidate == null) { 9658 Log.e(TAG, "tryToConnectToNetwork: bad candidate. Network:" + candidate 9659 + " scanresult: " + scanResultCandidate); 9660 return; 9661 } 9662 9663 String targetBssid = scanResultCandidate.BSSID; 9664 String targetAssociationId = candidate.SSID + " : " + targetBssid; 9665 if (targetBssid != null && targetBssid.equals(mWifiInfo.getBSSID())) { 9666 if (DBG) { 9667 Log.d(TAG, "tryToConnectToNetwork: Already connect to" + targetAssociationId); 9668 } 9669 return; 9670 } 9671 9672 WifiConfiguration currentConnectedNetwork = mWifiConfigManager 9673 .getWifiConfiguration(mWifiInfo.getNetworkId()); 9674 String currentAssociationId = (currentConnectedNetwork == null) ? "Disconnected" : 9675 (mWifiInfo.getSSID() + " : " + mWifiInfo.getBSSID()); 9676 9677 if (currentConnectedNetwork != null 9678 && (currentConnectedNetwork.networkId == candidate.networkId 9679 || currentConnectedNetwork.isLinked(candidate))) { 9680 if (DBG) { 9681 Log.d(TAG, "tryToConnectToNetwork: Roaming from " + currentAssociationId + " to " 9682 + targetAssociationId); 9683 } 9684 sendMessage(CMD_AUTO_ROAM, candidate.networkId, 0, scanResultCandidate); 9685 } else { 9686 if (DBG) { 9687 Log.d(TAG, "tryToConnectToNetwork: Reconnect from " + currentAssociationId + " to " 9688 + targetAssociationId); 9689 } 9690 9691 sendMessage(CMD_AUTO_CONNECT, candidate.networkId, 0, scanResultCandidate.BSSID); 9692 } 9693 } 9694} 9695