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