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