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