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