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