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