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