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