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