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