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