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