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