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