WifiStateMachine.java revision 5818c1320387ec7a14eb8b7e2710667800319fae
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 // If we receive a supplicant state change with an empty SSID, 4373 // this implies that wpa_supplicant is already disconnected. 4374 // We should pretend we are still connected when linkDebouncing is on. 4375 if ((stateChangeResult.wifiSsid == null 4376 || stateChangeResult.wifiSsid.toString().isEmpty()) && linkDebouncing) { 4377 return state; 4378 } 4379 // Network id is only valid when we start connecting 4380 if (SupplicantState.isConnecting(state)) { 4381 mWifiInfo.setNetworkId(stateChangeResult.networkId); 4382 } else { 4383 mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); 4384 } 4385 4386 mWifiInfo.setBSSID(stateChangeResult.BSSID); 4387 4388 if (mWhiteListedSsids != null 4389 && mWhiteListedSsids.length > 0 4390 && stateChangeResult.wifiSsid != null) { 4391 String SSID = stateChangeResult.wifiSsid.toString(); 4392 String currentSSID = mWifiInfo.getSSID(); 4393 if (SSID != null && currentSSID != null && !SSID.equals(WifiSsid.NONE)) { 4394 // Remove quote before comparing 4395 if (SSID.length() >= 2 && SSID.charAt(0) == '"' 4396 && SSID.charAt(SSID.length() - 1) == '"') { 4397 SSID = SSID.substring(1, SSID.length() - 1); 4398 } 4399 if (currentSSID.length() >= 2 && currentSSID.charAt(0) == '"' 4400 && currentSSID.charAt(currentSSID.length() - 1) == '"') { 4401 currentSSID = currentSSID.substring(1, currentSSID.length() - 1); 4402 } 4403 if ((!SSID.equals(currentSSID)) && (getCurrentState() == mConnectedState)) { 4404 lastConnectAttemptTimestamp = System.currentTimeMillis(); 4405 targetWificonfiguration = 4406 mWifiConfigManager.getWifiConfiguration(mWifiInfo.getNetworkId()); 4407 transitionTo(mRoamingState); 4408 } 4409 } 4410 } 4411 4412 mWifiInfo.setSSID(stateChangeResult.wifiSsid); 4413 mWifiInfo.setEphemeral(mWifiConfigManager.isEphemeral(mWifiInfo.getNetworkId())); 4414 4415 mSupplicantStateTracker.sendMessage(Message.obtain(message)); 4416 4417 return state; 4418 } 4419 4420 /** 4421 * Resets the Wi-Fi Connections by clearing any state, resetting any sockets 4422 * using the interface, stopping DHCP & disabling interface 4423 */ 4424 private void handleNetworkDisconnect() { 4425 if (DBG) log("handleNetworkDisconnect: Stopping DHCP and clearing IP" 4426 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 4427 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 4428 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 4429 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 4430 4431 stopRssiMonitoringOffload(); 4432 4433 clearCurrentConfigBSSID("handleNetworkDisconnect"); 4434 4435 stopIpManager(); 4436 4437 /* Reset data structures */ 4438 mWifiScoreReport = null; 4439 mWifiInfo.reset(); 4440 linkDebouncing = false; 4441 /* Reset roaming parameters */ 4442 mAutoRoaming = false; 4443 4444 /** 4445 * fullBandConnectedTimeIntervalMilli: 4446 * - start scans at mWifiConfigManager.wifiAssociatedShortScanIntervalMilli seconds 4447 * interval 4448 * - exponentially increase to mWifiConfigManager.associatedFullScanMaxIntervalMilli 4449 * Initialize to sane value = 20 seconds 4450 */ 4451 fullBandConnectedTimeIntervalMilli = 20 * 1000; 4452 4453 setNetworkDetailedState(DetailedState.DISCONNECTED); 4454 if (mNetworkAgent != null) { 4455 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4456 mNetworkAgent = null; 4457 } 4458 mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED); 4459 4460 /* Clear network properties */ 4461 clearLinkProperties(); 4462 4463 /* Cend event to CM & network change broadcast */ 4464 sendNetworkStateChangeBroadcast(mLastBssid); 4465 4466 /* Cancel auto roam requests */ 4467 autoRoamSetBSSID(mLastNetworkId, "any"); 4468 mLastBssid = null; 4469 registerDisconnected(); 4470 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 4471 } 4472 4473 private void handleSupplicantConnectionLoss(boolean killSupplicant) { 4474 /* Socket connection can be lost when we do a graceful shutdown 4475 * or when the driver is hung. Ensure supplicant is stopped here. 4476 */ 4477 if (killSupplicant) { 4478 mWifiMonitor.killSupplicant(mP2pSupported); 4479 } 4480 mWifiNative.closeSupplicantConnection(); 4481 sendSupplicantConnectionChangedBroadcast(false); 4482 setWifiState(WIFI_STATE_DISABLED); 4483 } 4484 4485 void handlePreDhcpSetup() { 4486 if (!mBluetoothConnectionActive) { 4487 /* 4488 * There are problems setting the Wi-Fi driver's power 4489 * mode to active when bluetooth coexistence mode is 4490 * enabled or sense. 4491 * <p> 4492 * We set Wi-Fi to active mode when 4493 * obtaining an IP address because we've found 4494 * compatibility issues with some routers with low power 4495 * mode. 4496 * <p> 4497 * In order for this active power mode to properly be set, 4498 * we disable coexistence mode until we're done with 4499 * obtaining an IP address. One exception is if we 4500 * are currently connected to a headset, since disabling 4501 * coexistence would interrupt that connection. 4502 */ 4503 // Disable the coexistence mode 4504 mWifiNative.setBluetoothCoexistenceMode( 4505 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); 4506 } 4507 4508 // Disable power save and suspend optimizations during DHCP 4509 // Note: The order here is important for now. Brcm driver changes 4510 // power settings when we control suspend mode optimizations. 4511 // TODO: Remove this comment when the driver is fixed. 4512 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false); 4513 mWifiNative.setPowerSave(false); 4514 4515 // Update link layer stats 4516 getWifiLinkLayerStats(false); 4517 4518 /* P2p discovery breaks dhcp, shut it down in order to get through this */ 4519 Message msg = new Message(); 4520 msg.what = WifiP2pServiceImpl.BLOCK_DISCOVERY; 4521 msg.arg1 = WifiP2pServiceImpl.ENABLED; 4522 msg.arg2 = DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE; 4523 msg.obj = WifiStateMachine.this; 4524 mWifiP2pChannel.sendMessage(msg); 4525 } 4526 4527 void handlePostDhcpSetup() { 4528 /* Restore power save and suspend optimizations */ 4529 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true); 4530 mWifiNative.setPowerSave(true); 4531 4532 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.BLOCK_DISCOVERY, 4533 WifiP2pServiceImpl.DISABLED); 4534 4535 // Set the coexistence mode back to its default value 4536 mWifiNative.setBluetoothCoexistenceMode( 4537 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); 4538 } 4539 4540 private void handleIPv4Success(DhcpResults dhcpResults) { 4541 if (DBG) { 4542 logd("handleIPv4Success <" + dhcpResults.toString() + ">"); 4543 logd("link address " + dhcpResults.ipAddress); 4544 } 4545 4546 Inet4Address addr; 4547 synchronized (mDhcpResultsLock) { 4548 mDhcpResults = dhcpResults; 4549 addr = (Inet4Address) dhcpResults.ipAddress.getAddress(); 4550 } 4551 4552 if (isRoaming()) { 4553 int previousAddress = mWifiInfo.getIpAddress(); 4554 int newAddress = NetworkUtils.inetAddressToInt(addr); 4555 if (previousAddress != newAddress) { 4556 logd("handleIPv4Success, roaming and address changed" + 4557 mWifiInfo + " got: " + addr); 4558 } 4559 } 4560 mWifiInfo.setInetAddress(addr); 4561 mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint()); 4562 } 4563 4564 private void handleSuccessfulIpConfiguration() { 4565 mLastSignalLevel = -1; // Force update of signal strength 4566 WifiConfiguration c = getCurrentWifiConfiguration(); 4567 if (c != null) { 4568 // Reset IP failure tracking 4569 c.getNetworkSelectionStatus().clearDisableReasonCounter( 4570 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 4571 4572 // Tell the framework whether the newly connected network is trusted or untrusted. 4573 updateCapabilities(c); 4574 } 4575 if (c != null) { 4576 ScanResult result = getCurrentScanResult(); 4577 if (result == null) { 4578 logd("WifiStateMachine: handleSuccessfulIpConfiguration and no scan results" + 4579 c.configKey()); 4580 } else { 4581 // Clear the per BSSID failure count 4582 result.numIpConfigFailures = 0; 4583 // Clear the WHOLE BSSID blacklist, which means supplicant is free to retry 4584 // any BSSID, even though it may already have a non zero ip failure count, 4585 // this will typically happen if the user walks away and come back to his arrea 4586 // TODO: implement blacklisting based on a timer, i.e. keep BSSID blacklisted 4587 // in supplicant for a couple of hours or a day 4588 mWifiConfigManager.clearBssidBlacklist(); 4589 } 4590 } 4591 } 4592 4593 private void handleIPv4Failure() { 4594 // TODO: Move this to provisioning failure, not DHCP failure. 4595 // DHCPv4 failure is expected on an IPv6-only network. 4596 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_DHCP_FAILURE); 4597 if (DBG) { 4598 int count = -1; 4599 WifiConfiguration config = getCurrentWifiConfiguration(); 4600 if (config != null) { 4601 count = config.getNetworkSelectionStatus().getDisableReasonCounter( 4602 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 4603 } 4604 log("DHCP failure count=" + count); 4605 } 4606 mWifiMetrics.endConnectionEvent( 4607 WifiMetrics.ConnectionEvent.LLF_NONE, 4608 WifiMetricsProto.ConnectionEvent.HLF_DHCP); 4609 synchronized(mDhcpResultsLock) { 4610 if (mDhcpResults != null) { 4611 mDhcpResults.clear(); 4612 } 4613 } 4614 if (DBG) { 4615 logd("handleIPv4Failure"); 4616 } 4617 } 4618 4619 private void handleIpConfigurationLost() { 4620 mWifiInfo.setInetAddress(null); 4621 mWifiInfo.setMeteredHint(false); 4622 4623 mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId, 4624 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 4625 4626 /* DHCP times out after about 30 seconds, we do a 4627 * disconnect thru supplicant, we will let autojoin retry connecting to the network 4628 */ 4629 mWifiNative.disconnect(); 4630 } 4631 4632 // TODO: De-duplicated this and handleIpConfigurationLost(). 4633 private void handleIpReachabilityLost() { 4634 mWifiInfo.setInetAddress(null); 4635 mWifiInfo.setMeteredHint(false); 4636 4637 // TODO: Determine whether to call some form of mWifiConfigManager.handleSSIDStateChange(). 4638 4639 // Disconnect via supplicant, and let autojoin retry connecting to the network. 4640 mWifiNative.disconnect(); 4641 } 4642 4643 private int convertFrequencyToChannelNumber(int frequency) { 4644 if (frequency >= 2412 && frequency <= 2484) { 4645 return (frequency -2412) / 5 + 1; 4646 } else if (frequency >= 5170 && frequency <=5825) { 4647 //DFS is included 4648 return (frequency -5170) / 5 + 34; 4649 } else { 4650 return 0; 4651 } 4652 } 4653 4654 private int chooseApChannel(int apBand) { 4655 int apChannel; 4656 int[] channel; 4657 4658 if (apBand == 0) { 4659 ArrayList<Integer> allowed2GChannel = 4660 mWifiApConfigStore.getAllowed2GChannel(); 4661 if (allowed2GChannel == null || allowed2GChannel.size() == 0) { 4662 //most safe channel to use 4663 if (DBG) { 4664 Log.d(TAG, "No specified 2G allowed channel list"); 4665 } 4666 apChannel = 6; 4667 } else { 4668 int index = mRandom.nextInt(allowed2GChannel.size()); 4669 apChannel = allowed2GChannel.get(index).intValue(); 4670 } 4671 } else { 4672 //5G without DFS 4673 channel = mWifiNative.getChannelsForBand(2); 4674 if (channel != null && channel.length > 0) { 4675 apChannel = channel[mRandom.nextInt(channel.length)]; 4676 apChannel = convertFrequencyToChannelNumber(apChannel); 4677 } else { 4678 Log.e(TAG, "SoftAp do not get available channel list"); 4679 apChannel = 0; 4680 } 4681 } 4682 4683 if (DBG) { 4684 Log.d(TAG, "SoftAp set on channel " + apChannel); 4685 } 4686 4687 return apChannel; 4688 } 4689 4690 /* Driver/firmware setup for soft AP. */ 4691 private boolean setupDriverForSoftAp() { 4692 if (!mWifiNative.loadDriver()) { 4693 Log.e(TAG, "Failed to load driver for softap"); 4694 return false; 4695 } 4696 4697 if (mWifiNative.getInterfaces() != 0) { 4698 if (!mWifiNative.toggleInterface(0)) { 4699 Log.e(TAG, "toggleInterface failed"); 4700 return false; 4701 } 4702 } else { 4703 if (DBG) Log.d(TAG, "No interfaces to toggle"); 4704 } 4705 4706 try { 4707 mNwService.wifiFirmwareReload(mInterfaceName, "AP"); 4708 if (DBG) Log.d(TAG, "Firmware reloaded in AP mode"); 4709 } catch (Exception e) { 4710 Log.e(TAG, "Failed to reload AP firmware " + e); 4711 } 4712 4713 if (!mWifiNative.startHal()) { 4714 /* starting HAL is optional */ 4715 Log.e(TAG, "Failed to start HAL"); 4716 } 4717 return true; 4718 } 4719 4720 private byte[] macAddressFromString(String macString) { 4721 String[] macBytes = macString.split(":"); 4722 if (macBytes.length != 6) { 4723 throw new IllegalArgumentException("MAC address should be 6 bytes long!"); 4724 } 4725 byte[] mac = new byte[6]; 4726 for (int i = 0; i < macBytes.length; i++) { 4727 Integer hexVal = Integer.parseInt(macBytes[i], 16); 4728 mac[i] = hexVal.byteValue(); 4729 } 4730 return mac; 4731 } 4732 4733 /* 4734 * Read a MAC address in /proc/arp/table, used by WifistateMachine 4735 * so as to record MAC address of default gateway. 4736 **/ 4737 private String macAddressFromRoute(String ipAddress) { 4738 String macAddress = null; 4739 BufferedReader reader = null; 4740 try { 4741 reader = new BufferedReader(new FileReader("/proc/net/arp")); 4742 4743 // Skip over the line bearing colum titles 4744 String line = reader.readLine(); 4745 4746 while ((line = reader.readLine()) != null) { 4747 String[] tokens = line.split("[ ]+"); 4748 if (tokens.length < 6) { 4749 continue; 4750 } 4751 4752 // ARP column format is 4753 // Address HWType HWAddress Flags Mask IFace 4754 String ip = tokens[0]; 4755 String mac = tokens[3]; 4756 4757 if (ipAddress.equals(ip)) { 4758 macAddress = mac; 4759 break; 4760 } 4761 } 4762 4763 if (macAddress == null) { 4764 loge("Did not find remoteAddress {" + ipAddress + "} in " + 4765 "/proc/net/arp"); 4766 } 4767 4768 } catch (FileNotFoundException e) { 4769 loge("Could not open /proc/net/arp to lookup mac address"); 4770 } catch (IOException e) { 4771 loge("Could not read /proc/net/arp to lookup mac address"); 4772 } finally { 4773 try { 4774 if (reader != null) { 4775 reader.close(); 4776 } 4777 } catch (IOException e) { 4778 // Do nothing 4779 } 4780 } 4781 return macAddress; 4782 4783 } 4784 4785 private class WifiNetworkFactory extends NetworkFactory { 4786 public WifiNetworkFactory(Looper l, Context c, String TAG, NetworkCapabilities f) { 4787 super(l, c, TAG, f); 4788 } 4789 4790 @Override 4791 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 4792 ++mConnectionRequests; 4793 } 4794 4795 @Override 4796 protected void releaseNetworkFor(NetworkRequest networkRequest) { 4797 --mConnectionRequests; 4798 } 4799 4800 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4801 pw.println("mConnectionRequests " + mConnectionRequests); 4802 } 4803 4804 } 4805 4806 private class UntrustedWifiNetworkFactory extends NetworkFactory { 4807 private int mUntrustedReqCount; 4808 4809 public UntrustedWifiNetworkFactory(Looper l, Context c, String tag, NetworkCapabilities f) { 4810 super(l, c, tag, f); 4811 } 4812 4813 @Override 4814 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 4815 if (!networkRequest.networkCapabilities.hasCapability( 4816 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 4817 if (++mUntrustedReqCount == 1) { 4818 setAllowUntrustedConnections(true); 4819 } 4820 } 4821 } 4822 4823 @Override 4824 protected void releaseNetworkFor(NetworkRequest networkRequest) { 4825 if (!networkRequest.networkCapabilities.hasCapability( 4826 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 4827 if (--mUntrustedReqCount == 0) { 4828 setAllowUntrustedConnections(false); 4829 } 4830 } 4831 } 4832 4833 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4834 pw.println("mUntrustedReqCount " + mUntrustedReqCount); 4835 } 4836 } 4837 4838 void maybeRegisterNetworkFactory() { 4839 if (mNetworkFactory == null) { 4840 checkAndSetConnectivityInstance(); 4841 if (mCm != null) { 4842 mNetworkFactory = new WifiNetworkFactory(getHandler().getLooper(), mContext, 4843 NETWORKTYPE, mNetworkCapabilitiesFilter); 4844 mNetworkFactory.setScoreFilter(60); 4845 mNetworkFactory.register(); 4846 4847 // We can't filter untrusted network in the capabilities filter because a trusted 4848 // network would still satisfy a request that accepts untrusted ones. 4849 mUntrustedNetworkFactory = new UntrustedWifiNetworkFactory(getHandler().getLooper(), 4850 mContext, NETWORKTYPE_UNTRUSTED, mNetworkCapabilitiesFilter); 4851 mUntrustedNetworkFactory.setScoreFilter(Integer.MAX_VALUE); 4852 mUntrustedNetworkFactory.register(); 4853 } 4854 } 4855 } 4856 4857 /******************************************************** 4858 * HSM states 4859 *******************************************************/ 4860 4861 class DefaultState extends State { 4862 @Override 4863 public boolean processMessage(Message message) { 4864 logStateAndMessage(message, this); 4865 4866 switch (message.what) { 4867 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 4868 AsyncChannel ac = (AsyncChannel) message.obj; 4869 if (ac == mWifiP2pChannel) { 4870 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 4871 mWifiP2pChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 4872 } else { 4873 loge("WifiP2pService connection failure, error=" + message.arg1); 4874 } 4875 } else { 4876 loge("got HALF_CONNECTED for unknown channel"); 4877 } 4878 break; 4879 } 4880 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 4881 AsyncChannel ac = (AsyncChannel) message.obj; 4882 if (ac == mWifiP2pChannel) { 4883 loge("WifiP2pService channel lost, message.arg1 =" + message.arg1); 4884 //TODO: Re-establish connection to state machine after a delay 4885 // mWifiP2pChannel.connect(mContext, getHandler(), 4886 // mWifiP2pManager.getMessenger()); 4887 } 4888 break; 4889 } 4890 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 4891 mBluetoothConnectionActive = (message.arg1 != 4892 BluetoothAdapter.STATE_DISCONNECTED); 4893 break; 4894 /* Synchronous call returns */ 4895 case CMD_PING_SUPPLICANT: 4896 case CMD_ENABLE_NETWORK: 4897 case CMD_ADD_OR_UPDATE_NETWORK: 4898 case CMD_REMOVE_NETWORK: 4899 case CMD_SAVE_CONFIG: 4900 replyToMessage(message, message.what, FAILURE); 4901 break; 4902 case CMD_GET_CAPABILITY_FREQ: 4903 replyToMessage(message, message.what, null); 4904 break; 4905 case CMD_GET_CONFIGURED_NETWORKS: 4906 replyToMessage(message, message.what, (List<WifiConfiguration>) null); 4907 break; 4908 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 4909 replyToMessage(message, message.what, (List<WifiConfiguration>) null); 4910 break; 4911 case CMD_ENABLE_RSSI_POLL: 4912 mEnableRssiPolling = (message.arg1 == 1); 4913 break; 4914 case CMD_SET_HIGH_PERF_MODE: 4915 if (message.arg1 == 1) { 4916 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false); 4917 } else { 4918 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true); 4919 } 4920 break; 4921 case CMD_BOOT_COMPLETED: 4922 maybeRegisterNetworkFactory(); 4923 break; 4924 case CMD_SCREEN_STATE_CHANGED: 4925 handleScreenStateChanged(message.arg1 != 0); 4926 break; 4927 /* Discard */ 4928 case CMD_START_SCAN: 4929 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4930 break; 4931 case CMD_START_SUPPLICANT: 4932 case CMD_STOP_SUPPLICANT: 4933 case CMD_STOP_SUPPLICANT_FAILED: 4934 case CMD_START_DRIVER: 4935 case CMD_STOP_DRIVER: 4936 case CMD_DRIVER_START_TIMED_OUT: 4937 case CMD_START_AP: 4938 case CMD_START_AP_FAILURE: 4939 case CMD_STOP_AP: 4940 case CMD_AP_STOPPED: 4941 case CMD_DISCONNECT: 4942 case CMD_RECONNECT: 4943 case CMD_REASSOCIATE: 4944 case CMD_RELOAD_TLS_AND_RECONNECT: 4945 case WifiMonitor.SUP_CONNECTION_EVENT: 4946 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4947 case WifiMonitor.NETWORK_CONNECTION_EVENT: 4948 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 4949 case WifiMonitor.SCAN_RESULTS_EVENT: 4950 case WifiMonitor.SCAN_FAILED_EVENT: 4951 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4952 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 4953 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 4954 case WifiMonitor.WPS_OVERLAP_EVENT: 4955 case CMD_BLACKLIST_NETWORK: 4956 case CMD_CLEAR_BLACKLIST: 4957 case CMD_SET_OPERATIONAL_MODE: 4958 case CMD_SET_FREQUENCY_BAND: 4959 case CMD_RSSI_POLL: 4960 case CMD_ENABLE_ALL_NETWORKS: 4961 case DhcpClient.CMD_PRE_DHCP_ACTION: 4962 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 4963 case DhcpClient.CMD_POST_DHCP_ACTION: 4964 case CMD_NO_NETWORKS_PERIODIC_SCAN: 4965 case CMD_DISABLE_P2P_RSP: 4966 case WifiMonitor.SUP_REQUEST_IDENTITY: 4967 case CMD_TEST_NETWORK_DISCONNECT: 4968 case CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER: 4969 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 4970 case CMD_TARGET_BSSID: 4971 case CMD_AUTO_CONNECT: 4972 case CMD_AUTO_ROAM: 4973 case CMD_AUTO_SAVE_NETWORK: 4974 case CMD_ASSOCIATED_BSSID: 4975 case CMD_UNWANTED_NETWORK: 4976 case CMD_DISCONNECTING_WATCHDOG_TIMER: 4977 case CMD_ROAM_WATCHDOG_TIMER: 4978 case CMD_DISABLE_EPHEMERAL_NETWORK: 4979 case CMD_RESTART_AUTOJOIN_OFFLOAD: 4980 case CMD_STARTED_PNO_DBG: 4981 case CMD_STARTED_GSCAN_DBG: 4982 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 4983 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4984 break; 4985 case CMD_SET_COUNTRY_CODE: 4986 String country = (String) message.obj; 4987 final boolean persist = (message.arg2 == 1); 4988 final int sequence = message.arg1; 4989 if (sequence != mCountryCodeSequence.get()) { 4990 if (DBG) log("set country code ignored due to sequnce num"); 4991 break; 4992 } 4993 4994 if (persist) { 4995 country = country.toUpperCase(Locale.ROOT); 4996 if (DBG) log("set country code " + (country == null ? "(null)" : country)); 4997 Settings.Global.putString(mContext.getContentResolver(), 4998 Settings.Global.WIFI_COUNTRY_CODE, 4999 country == null ? "" : country); 5000 } 5001 5002 break; 5003 case CMD_SET_SUSPEND_OPT_ENABLED: 5004 if (message.arg1 == 1) { 5005 mSuspendWakeLock.release(); 5006 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true); 5007 } else { 5008 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false); 5009 } 5010 break; 5011 case WifiMonitor.DRIVER_HUNG_EVENT: 5012 setSupplicantRunning(false); 5013 setSupplicantRunning(true); 5014 break; 5015 case WifiManager.CONNECT_NETWORK: 5016 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5017 WifiManager.BUSY); 5018 break; 5019 case WifiManager.FORGET_NETWORK: 5020 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 5021 WifiManager.BUSY); 5022 break; 5023 case WifiManager.SAVE_NETWORK: 5024 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5025 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5026 WifiManager.BUSY); 5027 break; 5028 case WifiManager.START_WPS: 5029 replyToMessage(message, WifiManager.WPS_FAILED, 5030 WifiManager.BUSY); 5031 break; 5032 case WifiManager.CANCEL_WPS: 5033 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, 5034 WifiManager.BUSY); 5035 break; 5036 case WifiManager.DISABLE_NETWORK: 5037 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 5038 WifiManager.BUSY); 5039 break; 5040 case WifiManager.RSSI_PKTCNT_FETCH: 5041 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED, 5042 WifiManager.BUSY); 5043 break; 5044 case CMD_GET_SUPPORTED_FEATURES: 5045 int featureSet = mWifiNative.getSupportedFeatureSet(); 5046 replyToMessage(message, message.what, featureSet); 5047 break; 5048 case CMD_FIRMWARE_ALERT: 5049 if (mWifiLogger != null) { 5050 byte[] buffer = (byte[])message.obj; 5051 mWifiLogger.captureAlertData(message.arg1, buffer); 5052 } 5053 break; 5054 case CMD_GET_LINK_LAYER_STATS: 5055 // Not supported hence reply with error message 5056 replyToMessage(message, message.what, null); 5057 break; 5058 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 5059 NetworkInfo info = (NetworkInfo) message.obj; 5060 mP2pConnected.set(info.isConnected()); 5061 break; 5062 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 5063 mTemporarilyDisconnectWifi = (message.arg1 == 1); 5064 replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 5065 break; 5066 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 5067 case CMD_UPDATE_LINKPROPERTIES: 5068 updateLinkProperties((LinkProperties) message.obj); 5069 break; 5070 case CMD_GET_MATCHING_CONFIG: 5071 replyToMessage(message, message.what); 5072 break; 5073 case CMD_IP_CONFIGURATION_SUCCESSFUL: 5074 case CMD_IP_CONFIGURATION_LOST: 5075 case CMD_IP_REACHABILITY_LOST: 5076 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5077 break; 5078 case CMD_GET_CONNECTION_STATISTICS: 5079 replyToMessage(message, message.what, mWifiConnectionStatistics); 5080 break; 5081 case CMD_REMOVE_APP_CONFIGURATIONS: 5082 deferMessage(message); 5083 break; 5084 case CMD_REMOVE_USER_CONFIGURATIONS: 5085 deferMessage(message); 5086 break; 5087 case CMD_START_IP_PACKET_OFFLOAD: 5088 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 5089 message.arg1, 5090 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 5091 break; 5092 case CMD_STOP_IP_PACKET_OFFLOAD: 5093 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 5094 message.arg1, 5095 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 5096 break; 5097 case CMD_START_RSSI_MONITORING_OFFLOAD: 5098 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5099 break; 5100 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 5101 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5102 break; 5103 case CMD_USER_SWITCH: 5104 mCurrentUserId = message.arg1; 5105 mWifiConfigManager.handleUserSwitch(); 5106 break; 5107 case CMD_ADD_PASSPOINT_MO: 5108 case CMD_MODIFY_PASSPOINT_MO: 5109 case CMD_QUERY_OSU_ICON: 5110 case CMD_MATCH_PROVIDER_NETWORK: 5111 /* reply with arg1 = 0 - it returns API failure to the calling app 5112 * (message.what is not looked at) 5113 */ 5114 replyToMessage(message, message.what); 5115 break; 5116 default: 5117 loge("Error! unhandled message" + message); 5118 break; 5119 } 5120 return HANDLED; 5121 } 5122 } 5123 5124 class InitialState extends State { 5125 @Override 5126 public void enter() { 5127 mWifiNative.stopHal(); 5128 mWifiNative.unloadDriver(); 5129 if (mWifiP2pChannel == null) { 5130 mWifiP2pChannel = new AsyncChannel(); 5131 mWifiP2pChannel.connect(mContext, getHandler(), 5132 mWifiP2pServiceImpl.getP2pStateMachineMessenger()); 5133 } 5134 5135 if (mWifiApConfigStore == null) { 5136 mWifiApConfigStore = 5137 mFacade.makeApConfigStore(mContext, mBackupManagerProxy); 5138 } 5139 5140 if (mWifiConfigManager.enableHalBasedPno.get()) { 5141 // make sure developer Settings are in sync with the config option 5142 mHalBasedPnoEnableInDevSettings = true; 5143 } 5144 } 5145 @Override 5146 public boolean processMessage(Message message) { 5147 logStateAndMessage(message, this); 5148 switch (message.what) { 5149 case CMD_START_SUPPLICANT: 5150 if (mWifiNative.loadDriver()) { 5151 try { 5152 mNwService.wifiFirmwareReload(mInterfaceName, "STA"); 5153 } catch (Exception e) { 5154 loge("Failed to reload STA firmware " + e); 5155 // Continue 5156 } 5157 5158 try { 5159 // A runtime crash can leave the interface up and 5160 // IP addresses configured, and this affects 5161 // connectivity when supplicant starts up. 5162 // Ensure interface is down and we have no IP 5163 // addresses before a supplicant start. 5164 mNwService.setInterfaceDown(mInterfaceName); 5165 mNwService.clearInterfaceAddresses(mInterfaceName); 5166 5167 // Set privacy extensions 5168 mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true); 5169 5170 // IPv6 is enabled only as long as access point is connected since: 5171 // - IPv6 addresses and routes stick around after disconnection 5172 // - kernel is unaware when connected and fails to start IPv6 negotiation 5173 // - kernel can start autoconfiguration when 802.1x is not complete 5174 mNwService.disableIpv6(mInterfaceName); 5175 } catch (RemoteException re) { 5176 loge("Unable to change interface settings: " + re); 5177 } catch (IllegalStateException ie) { 5178 loge("Unable to change interface settings: " + ie); 5179 } 5180 5181 /* Stop a running supplicant after a runtime restart 5182 * Avoids issues with drivers that do not handle interface down 5183 * on a running supplicant properly. 5184 */ 5185 mWifiMonitor.killSupplicant(mP2pSupported); 5186 5187 if (mWifiNative.startHal() == false) { 5188 /* starting HAL is optional */ 5189 loge("Failed to start HAL"); 5190 } 5191 5192 if (mWifiNative.startSupplicant(mP2pSupported)) { 5193 setWifiState(WIFI_STATE_ENABLING); 5194 if (DBG) log("Supplicant start successful"); 5195 mWifiMonitor.startMonitoring(mInterfaceName); 5196 transitionTo(mSupplicantStartingState); 5197 } else { 5198 loge("Failed to start supplicant!"); 5199 } 5200 } else { 5201 loge("Failed to load driver"); 5202 } 5203 break; 5204 case CMD_START_AP: 5205 if (setupDriverForSoftAp()) { 5206 transitionTo(mSoftApState); 5207 } else { 5208 setWifiApState(WIFI_AP_STATE_FAILED, 5209 WifiManager.SAP_START_FAILURE_GENERAL); 5210 /** 5211 * Transition to InitialState (current state) to reset the 5212 * driver/HAL back to the initial state. 5213 */ 5214 transitionTo(mInitialState); 5215 } 5216 break; 5217 default: 5218 return NOT_HANDLED; 5219 } 5220 return HANDLED; 5221 } 5222 } 5223 5224 class SupplicantStartingState extends State { 5225 private void initializeWpsDetails() { 5226 String detail; 5227 detail = SystemProperties.get("ro.product.name", ""); 5228 if (!mWifiNative.setDeviceName(detail)) { 5229 loge("Failed to set device name " + detail); 5230 } 5231 detail = SystemProperties.get("ro.product.manufacturer", ""); 5232 if (!mWifiNative.setManufacturer(detail)) { 5233 loge("Failed to set manufacturer " + detail); 5234 } 5235 detail = SystemProperties.get("ro.product.model", ""); 5236 if (!mWifiNative.setModelName(detail)) { 5237 loge("Failed to set model name " + detail); 5238 } 5239 detail = SystemProperties.get("ro.product.model", ""); 5240 if (!mWifiNative.setModelNumber(detail)) { 5241 loge("Failed to set model number " + detail); 5242 } 5243 detail = SystemProperties.get("ro.serialno", ""); 5244 if (!mWifiNative.setSerialNumber(detail)) { 5245 loge("Failed to set serial number " + detail); 5246 } 5247 if (!mWifiNative.setConfigMethods("physical_display virtual_push_button")) { 5248 loge("Failed to set WPS config methods"); 5249 } 5250 if (!mWifiNative.setDeviceType(mPrimaryDeviceType)) { 5251 loge("Failed to set primary device type " + mPrimaryDeviceType); 5252 } 5253 } 5254 5255 @Override 5256 public boolean processMessage(Message message) { 5257 logStateAndMessage(message, this); 5258 5259 switch(message.what) { 5260 case WifiMonitor.SUP_CONNECTION_EVENT: 5261 if (DBG) log("Supplicant connection established"); 5262 setWifiState(WIFI_STATE_ENABLED); 5263 mSupplicantRestartCount = 0; 5264 /* Reset the supplicant state to indicate the supplicant 5265 * state is not known at this time */ 5266 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 5267 /* Initialize data structures */ 5268 mLastBssid = null; 5269 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 5270 mLastSignalLevel = -1; 5271 5272 mWifiInfo.setMacAddress(mWifiNative.getMacAddress()); 5273 /* set frequency band of operation */ 5274 setFrequencyBand(); 5275 mWifiNative.enableSaveConfig(); 5276 mWifiConfigManager.loadAndEnableAllNetworks(); 5277 if (mWifiConfigManager.enableVerboseLogging.get() > 0) { 5278 enableVerboseLogging(mWifiConfigManager.enableVerboseLogging.get()); 5279 } 5280 initializeWpsDetails(); 5281 5282 sendSupplicantConnectionChangedBroadcast(true); 5283 transitionTo(mDriverStartedState); 5284 break; 5285 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5286 if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { 5287 loge("Failed to setup control channel, restart supplicant"); 5288 mWifiMonitor.killSupplicant(mP2pSupported); 5289 transitionTo(mInitialState); 5290 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 5291 } else { 5292 loge("Failed " + mSupplicantRestartCount + 5293 " times to start supplicant, unload driver"); 5294 mSupplicantRestartCount = 0; 5295 setWifiState(WIFI_STATE_UNKNOWN); 5296 transitionTo(mInitialState); 5297 } 5298 break; 5299 case CMD_START_SUPPLICANT: 5300 case CMD_STOP_SUPPLICANT: 5301 case CMD_START_AP: 5302 case CMD_STOP_AP: 5303 case CMD_START_DRIVER: 5304 case CMD_STOP_DRIVER: 5305 case CMD_SET_OPERATIONAL_MODE: 5306 case CMD_SET_COUNTRY_CODE: 5307 case CMD_SET_FREQUENCY_BAND: 5308 case CMD_START_PACKET_FILTERING: 5309 case CMD_STOP_PACKET_FILTERING: 5310 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5311 deferMessage(message); 5312 break; 5313 default: 5314 return NOT_HANDLED; 5315 } 5316 return HANDLED; 5317 } 5318 } 5319 5320 class SupplicantStartedState extends State { 5321 @Override 5322 public void enter() { 5323 /* Wifi is available as long as we have a connection to supplicant */ 5324 mNetworkInfo.setIsAvailable(true); 5325 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 5326 5327 int defaultInterval = mContext.getResources().getInteger( 5328 R.integer.config_wifi_supplicant_scan_interval); 5329 5330 mSupplicantScanIntervalMs = mFacade.getLongSetting(mContext, 5331 Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS, 5332 defaultInterval); 5333 5334 mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000); 5335 mWifiNative.setExternalSim(true); 5336 5337 /* turn on use of DFS channels */ 5338 mWifiNative.setDfsFlag(true); 5339 5340 /* set country code */ 5341 initializeCountryCode(); 5342 5343 setRandomMacOui(); 5344 mWifiNative.enableAutoConnect(false); 5345 } 5346 5347 @Override 5348 public boolean processMessage(Message message) { 5349 logStateAndMessage(message, this); 5350 5351 switch(message.what) { 5352 case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */ 5353 if (mP2pSupported) { 5354 transitionTo(mWaitForP2pDisableState); 5355 } else { 5356 transitionTo(mSupplicantStoppingState); 5357 } 5358 break; 5359 case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ 5360 loge("Connection lost, restart supplicant"); 5361 handleSupplicantConnectionLoss(true); 5362 handleNetworkDisconnect(); 5363 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 5364 if (mP2pSupported) { 5365 transitionTo(mWaitForP2pDisableState); 5366 } else { 5367 transitionTo(mInitialState); 5368 } 5369 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 5370 break; 5371 case WifiMonitor.SCAN_RESULTS_EVENT: 5372 case WifiMonitor.SCAN_FAILED_EVENT: 5373 maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered 5374 noteScanEnd(); 5375 setScanResults(); 5376 if (mIsFullScanOngoing || mSendScanResultsBroadcast) { 5377 /* Just updated results from full scan, let apps know about this */ 5378 boolean scanSucceeded = message.what == WifiMonitor.SCAN_RESULTS_EVENT; 5379 sendScanResultsAvailableBroadcast(scanSucceeded); 5380 } 5381 mSendScanResultsBroadcast = false; 5382 mIsScanOngoing = false; 5383 mIsFullScanOngoing = false; 5384 if (mBufferedScanMsg.size() > 0) 5385 sendMessage(mBufferedScanMsg.remove()); 5386 break; 5387 case CMD_PING_SUPPLICANT: 5388 boolean ok = mWifiNative.ping(); 5389 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 5390 break; 5391 case CMD_GET_CAPABILITY_FREQ: 5392 String freqs = mWifiNative.getFreqCapability(); 5393 replyToMessage(message, message.what, freqs); 5394 break; 5395 case CMD_START_AP: 5396 /* Cannot start soft AP while in client mode */ 5397 loge("Failed to start soft AP with a running supplicant"); 5398 setWifiApState(WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL); 5399 break; 5400 case CMD_SET_OPERATIONAL_MODE: 5401 mOperationalMode = message.arg1; 5402 mWifiConfigManager. 5403 setAndEnableLastSelectedConfiguration( 5404 WifiConfiguration.INVALID_NETWORK_ID); 5405 break; 5406 case CMD_TARGET_BSSID: 5407 // Trying to associate to this BSSID 5408 if (message.obj != null) { 5409 mTargetRoamBSSID = (String) message.obj; 5410 } 5411 break; 5412 case CMD_GET_LINK_LAYER_STATS: 5413 WifiLinkLayerStats stats = getWifiLinkLayerStats(DBG); 5414 if (stats == null) { 5415 // When firmware doesnt support link layer stats, return an empty object 5416 stats = new WifiLinkLayerStats(); 5417 } 5418 replyToMessage(message, message.what, stats); 5419 break; 5420 case CMD_SET_COUNTRY_CODE: 5421 String country = (String) message.obj; 5422 final boolean persist = (message.arg2 == 1); 5423 final int sequence = message.arg1; 5424 if (sequence != mCountryCodeSequence.get()) { 5425 if (DBG) log("set country code ignored due to sequnce num"); 5426 break; 5427 } 5428 5429 country = country.toUpperCase(Locale.ROOT); 5430 5431 if (DBG) log("set country code " + (country == null ? "(null)" : country)); 5432 5433 if (!TextUtils.equals(mDriverSetCountryCode, country)) { 5434 if (mWifiNative.setCountryCode(country)) { 5435 mDriverSetCountryCode = country; 5436 mHasSetCountryCode.set(true); 5437 if (persist) { 5438 Settings.Global.putString(mContext.getContentResolver(), 5439 Settings.Global.WIFI_COUNTRY_CODE, 5440 country == null ? "" : country); 5441 } 5442 } else { 5443 loge("Failed to set country code " + country); 5444 } 5445 } 5446 5447 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.SET_COUNTRY_CODE, country); 5448 break; 5449 case CMD_RESET_SIM_NETWORKS: 5450 log("resetting EAP-SIM/AKA/AKA' networks since SIM was removed"); 5451 mWifiConfigManager.resetSimNetworks(); 5452 break; 5453 default: 5454 return NOT_HANDLED; 5455 } 5456 return HANDLED; 5457 } 5458 5459 @Override 5460 public void exit() { 5461 mNetworkInfo.setIsAvailable(false); 5462 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 5463 } 5464 } 5465 5466 class SupplicantStoppingState extends State { 5467 @Override 5468 public void enter() { 5469 /* Send any reset commands to supplicant before shutting it down */ 5470 handleNetworkDisconnect(); 5471 5472 String suppState = System.getProperty("init.svc.wpa_supplicant"); 5473 if (suppState == null) suppState = "unknown"; 5474 String p2pSuppState = System.getProperty("init.svc.p2p_supplicant"); 5475 if (p2pSuppState == null) p2pSuppState = "unknown"; 5476 5477 logd("SupplicantStoppingState: stopSupplicant " 5478 + " init.svc.wpa_supplicant=" + suppState 5479 + " init.svc.p2p_supplicant=" + p2pSuppState); 5480 mWifiMonitor.stopSupplicant(); 5481 5482 /* Send ourselves a delayed message to indicate failure after a wait time */ 5483 sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED, 5484 ++mSupplicantStopFailureToken, 0), SUPPLICANT_RESTART_INTERVAL_MSECS); 5485 setWifiState(WIFI_STATE_DISABLING); 5486 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 5487 } 5488 @Override 5489 public boolean processMessage(Message message) { 5490 logStateAndMessage(message, this); 5491 5492 switch(message.what) { 5493 case WifiMonitor.SUP_CONNECTION_EVENT: 5494 loge("Supplicant connection received while stopping"); 5495 break; 5496 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5497 if (DBG) log("Supplicant connection lost"); 5498 handleSupplicantConnectionLoss(false); 5499 transitionTo(mInitialState); 5500 break; 5501 case CMD_STOP_SUPPLICANT_FAILED: 5502 if (message.arg1 == mSupplicantStopFailureToken) { 5503 loge("Timed out on a supplicant stop, kill and proceed"); 5504 handleSupplicantConnectionLoss(true); 5505 transitionTo(mInitialState); 5506 } 5507 break; 5508 case CMD_START_SUPPLICANT: 5509 case CMD_STOP_SUPPLICANT: 5510 case CMD_START_AP: 5511 case CMD_STOP_AP: 5512 case CMD_START_DRIVER: 5513 case CMD_STOP_DRIVER: 5514 case CMD_SET_OPERATIONAL_MODE: 5515 case CMD_SET_COUNTRY_CODE: 5516 case CMD_SET_FREQUENCY_BAND: 5517 case CMD_START_PACKET_FILTERING: 5518 case CMD_STOP_PACKET_FILTERING: 5519 deferMessage(message); 5520 break; 5521 default: 5522 return NOT_HANDLED; 5523 } 5524 return HANDLED; 5525 } 5526 } 5527 5528 class DriverStartingState extends State { 5529 private int mTries; 5530 @Override 5531 public void enter() { 5532 mTries = 1; 5533 /* Send ourselves a delayed message to start driver a second time */ 5534 sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT, 5535 ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS); 5536 } 5537 @Override 5538 public boolean processMessage(Message message) { 5539 logStateAndMessage(message, this); 5540 5541 switch(message.what) { 5542 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5543 SupplicantState state = handleSupplicantStateChange(message); 5544 /* If suplicant is exiting out of INTERFACE_DISABLED state into 5545 * a state that indicates driver has started, it is ready to 5546 * receive driver commands 5547 */ 5548 if (SupplicantState.isDriverActive(state)) { 5549 transitionTo(mDriverStartedState); 5550 } 5551 break; 5552 case CMD_DRIVER_START_TIMED_OUT: 5553 if (message.arg1 == mDriverStartToken) { 5554 if (mTries >= 2) { 5555 loge("Failed to start driver after " + mTries); 5556 setSupplicantRunning(false); 5557 setSupplicantRunning(true); 5558 } else { 5559 loge("Driver start failed, retrying"); 5560 mWakeLock.acquire(); 5561 mWifiNative.startDriver(); 5562 mWakeLock.release(); 5563 5564 ++mTries; 5565 /* Send ourselves a delayed message to start driver again */ 5566 sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT, 5567 ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS); 5568 } 5569 } 5570 break; 5571 /* Queue driver commands & connection events */ 5572 case CMD_START_DRIVER: 5573 case CMD_STOP_DRIVER: 5574 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5575 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5576 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 5577 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 5578 case WifiMonitor.WPS_OVERLAP_EVENT: 5579 case CMD_SET_COUNTRY_CODE: 5580 case CMD_SET_FREQUENCY_BAND: 5581 case CMD_START_PACKET_FILTERING: 5582 case CMD_STOP_PACKET_FILTERING: 5583 case CMD_START_SCAN: 5584 case CMD_DISCONNECT: 5585 case CMD_REASSOCIATE: 5586 case CMD_RECONNECT: 5587 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5588 deferMessage(message); 5589 break; 5590 case WifiMonitor.SCAN_RESULTS_EVENT: 5591 case WifiMonitor.SCAN_FAILED_EVENT: 5592 // Loose scan results obtained in Driver Starting state, they can only confuse 5593 // the state machine 5594 break; 5595 default: 5596 return NOT_HANDLED; 5597 } 5598 return HANDLED; 5599 } 5600 } 5601 5602 class DriverStartedState extends State { 5603 @Override 5604 public void enter() { 5605 if (DBG) { 5606 logd("DriverStartedState enter"); 5607 } 5608 5609 // We can't do this in the constructor because WifiStateMachine is created before the 5610 // wifi scanning service is initialized 5611 if (mWifiScanner == null) { 5612 mWifiScanner = 5613 (WifiScanner) mContext.getSystemService(Context.WIFI_SCANNING_SERVICE); 5614 } 5615 5616 mWifiLogger.startLogging(DBG); 5617 mIsRunning = true; 5618 updateBatteryWorkSource(null); 5619 /** 5620 * Enable bluetooth coexistence scan mode when bluetooth connection is active. 5621 * When this mode is on, some of the low-level scan parameters used by the 5622 * driver are changed to reduce interference with bluetooth 5623 */ 5624 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 5625 /* initialize network state */ 5626 setNetworkDetailedState(DetailedState.DISCONNECTED); 5627 5628 /* Remove any filtering on Multicast v6 at start */ 5629 mWifiNative.stopFilteringMulticastV6Packets(); 5630 5631 /* Reset Multicast v4 filtering state */ 5632 if (mFilteringMulticastV4Packets.get()) { 5633 mWifiNative.startFilteringMulticastV4Packets(); 5634 } else { 5635 mWifiNative.stopFilteringMulticastV4Packets(); 5636 } 5637 5638 if (mOperationalMode != CONNECT_MODE) { 5639 mWifiNative.disconnect(); 5640 mWifiConfigManager.disableAllNetworksNative(); 5641 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 5642 setWifiState(WIFI_STATE_DISABLED); 5643 } 5644 transitionTo(mScanModeState); 5645 } else { 5646 5647 // Status pulls in the current supplicant state and network connection state 5648 // events over the monitor connection. This helps framework sync up with 5649 // current supplicant state 5650 // TODO: actually check th supplicant status string and make sure the supplicant 5651 // is in disconnecte4d state. 5652 mWifiNative.status(); 5653 // Transitioning to Disconnected state will trigger a scan and subsequently AutoJoin 5654 transitionTo(mDisconnectedState); 5655 transitionTo(mDisconnectedState); 5656 } 5657 5658 // We may have missed screen update at boot 5659 if (mScreenBroadcastReceived.get() == false) { 5660 PowerManager powerManager = (PowerManager)mContext.getSystemService( 5661 Context.POWER_SERVICE); 5662 handleScreenStateChanged(powerManager.isScreenOn()); 5663 } else { 5664 // Set the right suspend mode settings 5665 mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0 5666 && mUserWantsSuspendOpt.get()); 5667 } 5668 mWifiNative.setPowerSave(true); 5669 5670 if (mP2pSupported) { 5671 if (mOperationalMode == CONNECT_MODE) { 5672 mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P); 5673 } else { 5674 // P2P statemachine starts in disabled state, and is not enabled until 5675 // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to 5676 // keep it disabled. 5677 } 5678 } 5679 5680 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 5681 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5682 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED); 5683 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5684 5685 mHalFeatureSet = mWifiNative.getSupportedFeatureSet(); 5686 if ((mHalFeatureSet & WifiManager.WIFI_FEATURE_HAL_EPNO) 5687 == WifiManager.WIFI_FEATURE_HAL_EPNO) { 5688 mHalBasedPnoDriverSupported = true; 5689 } 5690 5691 // Enable link layer stats gathering 5692 mWifiNative.setWifiLinkLayerStats("wlan0", 1); 5693 5694 if (DBG) { 5695 logd("Driverstarted State enter done, epno=" + mHalBasedPnoDriverSupported 5696 + " feature=" + mHalFeatureSet); 5697 } 5698 } 5699 5700 @Override 5701 public boolean processMessage(Message message) { 5702 logStateAndMessage(message, this); 5703 5704 switch(message.what) { 5705 case CMD_START_SCAN: 5706 handleScanRequest(message); 5707 break; 5708 case CMD_SET_FREQUENCY_BAND: 5709 int band = message.arg1; 5710 if (DBG) log("set frequency band " + band); 5711 if (mWifiNative.setBand(band)) { 5712 5713 if (DBG) logd("did set frequency band " + band); 5714 5715 mFrequencyBand.set(band); 5716 // Flush old data - like scan results 5717 mWifiNative.bssFlush(); 5718 5719 if (DBG) logd("done set frequency band " + band); 5720 5721 } else { 5722 loge("Failed to set frequency band " + band); 5723 } 5724 break; 5725 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 5726 mBluetoothConnectionActive = (message.arg1 != 5727 BluetoothAdapter.STATE_DISCONNECTED); 5728 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 5729 break; 5730 case CMD_STOP_DRIVER: 5731 int mode = message.arg1; 5732 5733 log("stop driver"); 5734 mWifiConfigManager.disableAllNetworksNative(); 5735 5736 if (getCurrentState() != mDisconnectedState) { 5737 mWifiNative.disconnect(); 5738 handleNetworkDisconnect(); 5739 } 5740 mWakeLock.acquire(); 5741 mWifiNative.stopDriver(); 5742 mWakeLock.release(); 5743 if (mP2pSupported) { 5744 transitionTo(mWaitForP2pDisableState); 5745 } else { 5746 transitionTo(mDriverStoppingState); 5747 } 5748 break; 5749 case CMD_START_DRIVER: 5750 if (mOperationalMode == CONNECT_MODE) { 5751 mWifiConfigManager.enableAllNetworks(); 5752 } 5753 break; 5754 case CMD_START_PACKET_FILTERING: 5755 if (message.arg1 == MULTICAST_V6) { 5756 mWifiNative.startFilteringMulticastV6Packets(); 5757 } else if (message.arg1 == MULTICAST_V4) { 5758 mWifiNative.startFilteringMulticastV4Packets(); 5759 } else { 5760 loge("Illegal arugments to CMD_START_PACKET_FILTERING"); 5761 } 5762 break; 5763 case CMD_STOP_PACKET_FILTERING: 5764 if (message.arg1 == MULTICAST_V6) { 5765 mWifiNative.stopFilteringMulticastV6Packets(); 5766 } else if (message.arg1 == MULTICAST_V4) { 5767 mWifiNative.stopFilteringMulticastV4Packets(); 5768 } else { 5769 loge("Illegal arugments to CMD_STOP_PACKET_FILTERING"); 5770 } 5771 break; 5772 case CMD_SET_SUSPEND_OPT_ENABLED: 5773 if (message.arg1 == 1) { 5774 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); 5775 mSuspendWakeLock.release(); 5776 } else { 5777 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); 5778 } 5779 break; 5780 case CMD_SET_HIGH_PERF_MODE: 5781 if (message.arg1 == 1) { 5782 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); 5783 } else { 5784 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); 5785 } 5786 break; 5787 case CMD_ENABLE_TDLS: 5788 if (message.obj != null) { 5789 String remoteAddress = (String) message.obj; 5790 boolean enable = (message.arg1 == 1); 5791 mWifiNative.startTdls(remoteAddress, enable); 5792 } 5793 break; 5794 case WifiMonitor.ANQP_DONE_EVENT: 5795 mWifiConfigManager.notifyANQPDone((Long) message.obj, message.arg1 != 0); 5796 break; 5797 case CMD_STOP_IP_PACKET_OFFLOAD: { 5798 int slot = message.arg1; 5799 int ret = stopWifiIPPacketOffload(slot); 5800 if (mNetworkAgent != null) { 5801 mNetworkAgent.onPacketKeepaliveEvent(slot, ret); 5802 } 5803 break; 5804 } 5805 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 5806 mWifiConfigManager.notifyIconReceived((IconEvent) message.obj); 5807 break; 5808 case WifiMonitor.HS20_REMEDIATION_EVENT: 5809 mWifiConfigManager.wnmFrameReceived((WnmData) message.obj); 5810 break; 5811 default: 5812 return NOT_HANDLED; 5813 } 5814 return HANDLED; 5815 } 5816 @Override 5817 public void exit() { 5818 5819 mWifiLogger.stopLogging(); 5820 5821 mIsRunning = false; 5822 updateBatteryWorkSource(null); 5823 mScanResults = new ArrayList<>(); 5824 5825 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 5826 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5827 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); 5828 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5829 noteScanEnd(); // wrap up any pending request. 5830 mBufferedScanMsg.clear(); 5831 } 5832 } 5833 5834 class WaitForP2pDisableState extends State { 5835 private State mTransitionToState; 5836 @Override 5837 public void enter() { 5838 switch (getCurrentMessage().what) { 5839 case WifiMonitor.SUP_DISCONNECTION_EVENT: 5840 mTransitionToState = mInitialState; 5841 break; 5842 case CMD_STOP_DRIVER: 5843 mTransitionToState = mDriverStoppingState; 5844 break; 5845 case CMD_STOP_SUPPLICANT: 5846 mTransitionToState = mSupplicantStoppingState; 5847 break; 5848 default: 5849 mTransitionToState = mDriverStoppingState; 5850 break; 5851 } 5852 mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ); 5853 } 5854 @Override 5855 public boolean processMessage(Message message) { 5856 logStateAndMessage(message, this); 5857 5858 switch(message.what) { 5859 case WifiStateMachine.CMD_DISABLE_P2P_RSP: 5860 transitionTo(mTransitionToState); 5861 break; 5862 /* Defer wifi start/shut and driver commands */ 5863 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5864 case CMD_START_SUPPLICANT: 5865 case CMD_STOP_SUPPLICANT: 5866 case CMD_START_AP: 5867 case CMD_STOP_AP: 5868 case CMD_START_DRIVER: 5869 case CMD_STOP_DRIVER: 5870 case CMD_SET_OPERATIONAL_MODE: 5871 case CMD_SET_COUNTRY_CODE: 5872 case CMD_SET_FREQUENCY_BAND: 5873 case CMD_START_PACKET_FILTERING: 5874 case CMD_STOP_PACKET_FILTERING: 5875 case CMD_START_SCAN: 5876 case CMD_DISCONNECT: 5877 case CMD_REASSOCIATE: 5878 case CMD_RECONNECT: 5879 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5880 deferMessage(message); 5881 break; 5882 default: 5883 return NOT_HANDLED; 5884 } 5885 return HANDLED; 5886 } 5887 } 5888 5889 class DriverStoppingState extends State { 5890 @Override 5891 public boolean processMessage(Message message) { 5892 logStateAndMessage(message, this); 5893 5894 switch(message.what) { 5895 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5896 SupplicantState state = handleSupplicantStateChange(message); 5897 if (state == SupplicantState.INTERFACE_DISABLED) { 5898 transitionTo(mDriverStoppedState); 5899 } 5900 break; 5901 /* Queue driver commands */ 5902 case CMD_START_DRIVER: 5903 case CMD_STOP_DRIVER: 5904 case CMD_SET_COUNTRY_CODE: 5905 case CMD_SET_FREQUENCY_BAND: 5906 case CMD_START_PACKET_FILTERING: 5907 case CMD_STOP_PACKET_FILTERING: 5908 case CMD_START_SCAN: 5909 case CMD_DISCONNECT: 5910 case CMD_REASSOCIATE: 5911 case CMD_RECONNECT: 5912 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5913 deferMessage(message); 5914 break; 5915 default: 5916 return NOT_HANDLED; 5917 } 5918 return HANDLED; 5919 } 5920 } 5921 5922 class DriverStoppedState extends State { 5923 @Override 5924 public boolean processMessage(Message message) { 5925 logStateAndMessage(message, this); 5926 switch (message.what) { 5927 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5928 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 5929 SupplicantState state = stateChangeResult.state; 5930 // A WEXT bug means that we can be back to driver started state 5931 // unexpectedly 5932 if (SupplicantState.isDriverActive(state)) { 5933 transitionTo(mDriverStartedState); 5934 } 5935 break; 5936 case CMD_START_DRIVER: 5937 mWakeLock.acquire(); 5938 mWifiNative.startDriver(); 5939 mWakeLock.release(); 5940 transitionTo(mDriverStartingState); 5941 break; 5942 default: 5943 return NOT_HANDLED; 5944 } 5945 return HANDLED; 5946 } 5947 } 5948 5949 class ScanModeState extends State { 5950 private int mLastOperationMode; 5951 @Override 5952 public void enter() { 5953 mLastOperationMode = mOperationalMode; 5954 } 5955 @Override 5956 public boolean processMessage(Message message) { 5957 logStateAndMessage(message, this); 5958 5959 switch(message.what) { 5960 case CMD_SET_OPERATIONAL_MODE: 5961 if (message.arg1 == CONNECT_MODE) { 5962 5963 if (mLastOperationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 5964 setWifiState(WIFI_STATE_ENABLED); 5965 // Load and re-enable networks when going back to enabled state 5966 // This is essential for networks to show up after restore 5967 mWifiConfigManager.loadAndEnableAllNetworks(); 5968 mWifiP2pChannel.sendMessage(CMD_ENABLE_P2P); 5969 } else { 5970 mWifiConfigManager.enableAllNetworks(); 5971 } 5972 // start a scan to trigger Quality network selection 5973 startScan(ENABLE_WIFI, 0, null, null); 5974 5975 // Loose last selection choice since user toggled WiFi 5976 mWifiConfigManager. 5977 setAndEnableLastSelectedConfiguration( 5978 WifiConfiguration.INVALID_NETWORK_ID); 5979 5980 mOperationalMode = CONNECT_MODE; 5981 transitionTo(mDisconnectedState); 5982 } else { 5983 // Nothing to do 5984 return HANDLED; 5985 } 5986 break; 5987 // Handle scan. All the connection related commands are 5988 // handled only in ConnectModeState 5989 case CMD_START_SCAN: 5990 handleScanRequest(message); 5991 break; 5992 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5993 SupplicantState state = handleSupplicantStateChange(message); 5994 if (DBG) log("SupplicantState= " + state); 5995 break; 5996 default: 5997 return NOT_HANDLED; 5998 } 5999 return HANDLED; 6000 } 6001 } 6002 6003 6004 String smToString(Message message) { 6005 return smToString(message.what); 6006 } 6007 6008 String smToString(int what) { 6009 String s = sSmToString.get(what); 6010 if (s != null) { 6011 return s; 6012 } 6013 switch (what) { 6014 case WifiMonitor.DRIVER_HUNG_EVENT: 6015 s = "DRIVER_HUNG_EVENT"; 6016 break; 6017 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 6018 s = "AsyncChannel.CMD_CHANNEL_HALF_CONNECTED"; 6019 break; 6020 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 6021 s = "AsyncChannel.CMD_CHANNEL_DISCONNECTED"; 6022 break; 6023 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 6024 s = "WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST"; 6025 break; 6026 case WifiManager.DISABLE_NETWORK: 6027 s = "WifiManager.DISABLE_NETWORK"; 6028 break; 6029 case WifiManager.CONNECT_NETWORK: 6030 s = "CONNECT_NETWORK"; 6031 break; 6032 case WifiManager.SAVE_NETWORK: 6033 s = "SAVE_NETWORK"; 6034 break; 6035 case WifiManager.FORGET_NETWORK: 6036 s = "FORGET_NETWORK"; 6037 break; 6038 case WifiMonitor.SUP_CONNECTION_EVENT: 6039 s = "SUP_CONNECTION_EVENT"; 6040 break; 6041 case WifiMonitor.SUP_DISCONNECTION_EVENT: 6042 s = "SUP_DISCONNECTION_EVENT"; 6043 break; 6044 case WifiMonitor.SCAN_RESULTS_EVENT: 6045 s = "SCAN_RESULTS_EVENT"; 6046 break; 6047 case WifiMonitor.SCAN_FAILED_EVENT: 6048 s = "SCAN_FAILED_EVENT"; 6049 break; 6050 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6051 s = "SUPPLICANT_STATE_CHANGE_EVENT"; 6052 break; 6053 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 6054 s = "AUTHENTICATION_FAILURE_EVENT"; 6055 break; 6056 case WifiMonitor.SSID_TEMP_DISABLED: 6057 s = "SSID_TEMP_DISABLED"; 6058 break; 6059 case WifiMonitor.SSID_REENABLED: 6060 s = "SSID_REENABLED"; 6061 break; 6062 case WifiMonitor.WPS_SUCCESS_EVENT: 6063 s = "WPS_SUCCESS_EVENT"; 6064 break; 6065 case WifiMonitor.WPS_FAIL_EVENT: 6066 s = "WPS_FAIL_EVENT"; 6067 break; 6068 case WifiMonitor.SUP_REQUEST_IDENTITY: 6069 s = "SUP_REQUEST_IDENTITY"; 6070 break; 6071 case WifiMonitor.NETWORK_CONNECTION_EVENT: 6072 s = "NETWORK_CONNECTION_EVENT"; 6073 break; 6074 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6075 s = "NETWORK_DISCONNECTION_EVENT"; 6076 break; 6077 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 6078 s = "ASSOCIATION_REJECTION_EVENT"; 6079 break; 6080 case WifiMonitor.ANQP_DONE_EVENT: 6081 s = "WifiMonitor.ANQP_DONE_EVENT"; 6082 break; 6083 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 6084 s = "WifiMonitor.RX_HS20_ANQP_ICON_EVENT"; 6085 break; 6086 case WifiMonitor.GAS_QUERY_DONE_EVENT: 6087 s = "WifiMonitor.GAS_QUERY_DONE_EVENT"; 6088 break; 6089 case WifiMonitor.HS20_REMEDIATION_EVENT: 6090 s = "WifiMonitor.HS20_REMEDIATION_EVENT"; 6091 break; 6092 case WifiMonitor.GAS_QUERY_START_EVENT: 6093 s = "WifiMonitor.GAS_QUERY_START_EVENT"; 6094 break; 6095 case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT: 6096 s = "GROUP_CREATING_TIMED_OUT"; 6097 break; 6098 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 6099 s = "P2P_CONNECTION_CHANGED"; 6100 break; 6101 case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE: 6102 s = "P2P.DISCONNECT_WIFI_RESPONSE"; 6103 break; 6104 case WifiP2pServiceImpl.SET_MIRACAST_MODE: 6105 s = "P2P.SET_MIRACAST_MODE"; 6106 break; 6107 case WifiP2pServiceImpl.BLOCK_DISCOVERY: 6108 s = "P2P.BLOCK_DISCOVERY"; 6109 break; 6110 case WifiP2pServiceImpl.SET_COUNTRY_CODE: 6111 s = "P2P.SET_COUNTRY_CODE"; 6112 break; 6113 case WifiManager.CANCEL_WPS: 6114 s = "CANCEL_WPS"; 6115 break; 6116 case WifiManager.CANCEL_WPS_FAILED: 6117 s = "CANCEL_WPS_FAILED"; 6118 break; 6119 case WifiManager.CANCEL_WPS_SUCCEDED: 6120 s = "CANCEL_WPS_SUCCEDED"; 6121 break; 6122 case WifiManager.START_WPS: 6123 s = "START_WPS"; 6124 break; 6125 case WifiManager.START_WPS_SUCCEEDED: 6126 s = "START_WPS_SUCCEEDED"; 6127 break; 6128 case WifiManager.WPS_FAILED: 6129 s = "WPS_FAILED"; 6130 break; 6131 case WifiManager.WPS_COMPLETED: 6132 s = "WPS_COMPLETED"; 6133 break; 6134 case WifiManager.RSSI_PKTCNT_FETCH: 6135 s = "RSSI_PKTCNT_FETCH"; 6136 break; 6137 default: 6138 s = "what:" + Integer.toString(what); 6139 break; 6140 } 6141 return s; 6142 } 6143 6144 void registerConnected() { 6145 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6146 WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 6147 if (config != null) { 6148 //Here we will clear all disable counters once a network is connected 6149 //records how long this network is connected in future 6150 config.lastConnected = System.currentTimeMillis(); 6151 config.getNetworkSelectionStatus().clearDisableReasonCounter(); 6152 config.numAssociation++; 6153 } 6154 // On connect, reset wifiScoreReport 6155 mWifiScoreReport = null; 6156 } 6157 } 6158 6159 void registerDisconnected() { 6160 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6161 // We are switching away from this configuration, 6162 // hence record the time we were connected last 6163 WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 6164 if (config != null) { 6165 config.lastDisconnected = System.currentTimeMillis(); 6166 if (config.ephemeral) { 6167 // Remove ephemeral WifiConfigurations from file 6168 mWifiConfigManager.forgetNetwork(mLastNetworkId); 6169 } 6170 } 6171 } 6172 } 6173 6174 void noteWifiDisabledWhileAssociated() { 6175 // We got disabled by user while we were associated, make note of it 6176 int rssi = mWifiInfo.getRssi(); 6177 WifiConfiguration config = getCurrentWifiConfiguration(); 6178 if (getCurrentState() == mConnectedState 6179 && rssi != WifiInfo.INVALID_RSSI 6180 && config != null) { 6181 boolean is24GHz = mWifiInfo.is24GHz(); 6182 boolean isBadRSSI = (is24GHz && rssi < mWifiConfigManager.thresholdMinimumRssi24.get()) 6183 || (!is24GHz && rssi < mWifiConfigManager.thresholdMinimumRssi5.get()); 6184 boolean isLowRSSI = 6185 (is24GHz && rssi < mWifiConfigManager.thresholdQualifiedRssi24.get()) 6186 || (!is24GHz && mWifiInfo.getRssi() < 6187 mWifiConfigManager.thresholdQualifiedRssi5.get()); 6188 boolean isHighRSSI = (is24GHz && rssi 6189 >= mWifiConfigManager.thresholdSaturatedRssi24.get()) 6190 || (!is24GHz && mWifiInfo.getRssi() 6191 >= mWifiConfigManager.thresholdSaturatedRssi5.get()); 6192 if (isBadRSSI) { 6193 // Take note that we got disabled while RSSI was Bad 6194 config.numUserTriggeredWifiDisableLowRSSI++; 6195 } else if (isLowRSSI) { 6196 // Take note that we got disabled while RSSI was Low 6197 config.numUserTriggeredWifiDisableBadRSSI++; 6198 } else if (!isHighRSSI) { 6199 // Take note that we got disabled while RSSI was Not high 6200 config.numUserTriggeredWifiDisableNotHighRSSI++; 6201 } 6202 } 6203 } 6204 6205 WifiConfiguration getCurrentWifiConfiguration() { 6206 if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 6207 return null; 6208 } 6209 return mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 6210 } 6211 6212 ScanResult getCurrentScanResult() { 6213 WifiConfiguration config = getCurrentWifiConfiguration(); 6214 if (config == null) { 6215 return null; 6216 } 6217 String BSSID = mWifiInfo.getBSSID(); 6218 if (BSSID == null) { 6219 BSSID = mTargetRoamBSSID; 6220 } 6221 ScanDetailCache scanDetailCache = 6222 mWifiConfigManager.getScanDetailCache(config); 6223 6224 if (scanDetailCache == null) { 6225 return null; 6226 } 6227 6228 return scanDetailCache.get(BSSID); 6229 } 6230 6231 String getCurrentBSSID() { 6232 if (linkDebouncing) { 6233 return null; 6234 } 6235 return mLastBssid; 6236 } 6237 6238 class ConnectModeState extends State { 6239 6240 @Override 6241 public boolean processMessage(Message message) { 6242 WifiConfiguration config; 6243 int netId; 6244 boolean ok; 6245 boolean didDisconnect; 6246 String bssid; 6247 String ssid; 6248 NetworkUpdateResult result; 6249 logStateAndMessage(message, this); 6250 6251 switch (message.what) { 6252 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 6253 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_ASSOC_FAILURE); 6254 didBlackListBSSID = false; 6255 bssid = (String) message.obj; 6256 if (bssid == null || TextUtils.isEmpty(bssid)) { 6257 // If BSSID is null, use the target roam BSSID 6258 bssid = mTargetRoamBSSID; 6259 } 6260 if (bssid != null) { 6261 // If we have a BSSID, tell configStore to black list it 6262 didBlackListBSSID = mWifiQualifiedNetworkSelector 6263 .enableBssidForQualityNetworkSelection(bssid, false); 6264 } 6265 6266 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 6267 WifiConfiguration.NetworkSelectionStatus 6268 .DISABLED_ASSOCIATION_REJECTION); 6269 6270 mSupplicantStateTracker.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT); 6271 //If rejection occurred while Metrics is tracking a ConnnectionEvent, end it. 6272 mWifiMetrics.endConnectionEvent( 6273 WifiMetrics.ConnectionEvent.LLF_ASSOCIATION_REJECTION, 6274 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6275 break; 6276 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 6277 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_AUTH_FAILURE); 6278 mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); 6279 if (mTargetNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 6280 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 6281 WifiConfiguration.NetworkSelectionStatus 6282 .DISABLED_AUTHENTICATION_FAILURE); 6283 } 6284 //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. 6285 mWifiMetrics.endConnectionEvent( 6286 WifiMetrics.ConnectionEvent.LLF_AUTHENTICATION_FAILURE, 6287 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6288 break; 6289 case WifiMonitor.SSID_TEMP_DISABLED: 6290 Log.e(TAG, "Supplicant SSID temporary disabled:" 6291 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 6292 mWifiConfigManager.updateNetworkSelectionStatus( 6293 message.arg1, 6294 WifiConfiguration.NetworkSelectionStatus 6295 .DISABLED_AUTHENTICATION_FAILURE); 6296 mWifiMetrics.endConnectionEvent( 6297 WifiMetrics.ConnectionEvent.LLF_SSID_TEMP_DISABLED, 6298 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6299 break; 6300 case WifiMonitor.SSID_REENABLED: 6301 Log.d(TAG, "Supplicant SSID reenable:" 6302 + mWifiConfigManager.getWifiConfiguration(message.arg1)); 6303 // Do not re-enable it in Quality Network Selection since framework has its own 6304 // Algorithm of disable/enable 6305 break; 6306 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6307 SupplicantState state = handleSupplicantStateChange(message); 6308 // A driver/firmware hang can now put the interface in a down state. 6309 // We detect the interface going down and recover from it 6310 if (!SupplicantState.isDriverActive(state)) { 6311 if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 6312 handleNetworkDisconnect(); 6313 } 6314 log("Detected an interface down, restart driver"); 6315 transitionTo(mDriverStoppedState); 6316 sendMessage(CMD_START_DRIVER); 6317 break; 6318 } 6319 6320 // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT 6321 // when authentication times out after a successful connection, 6322 // we can figure this from the supplicant state. If supplicant 6323 // state is DISCONNECTED, but the mNetworkInfo says we are not 6324 // disconnected, we need to handle a disconnection 6325 if (!linkDebouncing && state == SupplicantState.DISCONNECTED && 6326 mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 6327 if (DBG) log("Missed CTRL-EVENT-DISCONNECTED, disconnect"); 6328 handleNetworkDisconnect(); 6329 transitionTo(mDisconnectedState); 6330 } 6331 6332 // If we have COMPLETED a connection to a BSSID, start doing 6333 // DNAv4/DNAv6 -style probing for on-link neighbors of 6334 // interest (e.g. routers); harmless if none are configured. 6335 if (state == SupplicantState.COMPLETED) { 6336 mIpManager.confirmConfiguration(); 6337 } 6338 break; 6339 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 6340 if (message.arg1 == 1) { 6341 mWifiNative.disconnect(); 6342 mTemporarilyDisconnectWifi = true; 6343 } else { 6344 mWifiNative.reconnect(); 6345 mTemporarilyDisconnectWifi = false; 6346 } 6347 break; 6348 case CMD_ADD_OR_UPDATE_NETWORK: 6349 // Only the current foreground user can modify networks. 6350 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6351 loge("Only the current foreground user can modify networks " 6352 + " currentUserId=" + mCurrentUserId 6353 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6354 replyToMessage(message, message.what, FAILURE); 6355 break; 6356 } 6357 6358 config = (WifiConfiguration) message.obj; 6359 6360 if (!recordUidIfAuthorized(config, message.sendingUid, 6361 /* onlyAnnotate */ false)) { 6362 logw("Not authorized to update network " 6363 + " config=" + config.SSID 6364 + " cnid=" + config.networkId 6365 + " uid=" + message.sendingUid); 6366 replyToMessage(message, message.what, FAILURE); 6367 break; 6368 } 6369 6370 int res = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 6371 if (res < 0) { 6372 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6373 } else { 6374 WifiConfiguration curConfig = getCurrentWifiConfiguration(); 6375 if (curConfig != null && config != null) { 6376 WifiConfiguration.NetworkSelectionStatus networkStatus = 6377 config.getNetworkSelectionStatus(); 6378 if (curConfig.priority < config.priority && networkStatus != null 6379 && !networkStatus.isNetworkPermanentlyDisabled()) { 6380 // Interpret this as a connect attempt 6381 // Set the last selected configuration so as to allow the system to 6382 // stick the last user choice without persisting the choice 6383 mWifiConfigManager.setAndEnableLastSelectedConfiguration(res); 6384 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 6385 boolean persist = mWifiConfigManager 6386 .checkConfigOverridePermission(message.sendingUid); 6387 mWifiQualifiedNetworkSelector 6388 .userSelectNetwork(res, persist); 6389 6390 // Remember time of last connection attempt 6391 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6392 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6393 6394 // As a courtesy to the caller, trigger a scan now 6395 startScan(ADD_OR_UPDATE_SOURCE, 0, null, null); 6396 } 6397 } 6398 } 6399 replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK, res); 6400 break; 6401 case CMD_REMOVE_NETWORK: 6402 // Only the current foreground user can modify networks. 6403 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6404 loge("Only the current foreground user can modify networks " 6405 + " currentUserId=" + mCurrentUserId 6406 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6407 replyToMessage(message, message.what, FAILURE); 6408 break; 6409 } 6410 netId = message.arg1; 6411 6412 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 6413 /* onlyAnnotate */ false)) { 6414 logw("Not authorized to remove network " 6415 + " cnid=" + netId 6416 + " uid=" + message.sendingUid); 6417 replyToMessage(message, message.what, FAILURE); 6418 break; 6419 } 6420 6421 ok = mWifiConfigManager.removeNetwork(message.arg1); 6422 if (!ok) { 6423 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6424 } 6425 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 6426 break; 6427 case CMD_ENABLE_NETWORK: 6428 // Only the current foreground user can modify networks. 6429 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6430 loge("Only the current foreground user can modify networks " 6431 + " currentUserId=" + mCurrentUserId 6432 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6433 replyToMessage(message, message.what, FAILURE); 6434 break; 6435 } 6436 6437 boolean disableOthers = message.arg2 == 1; 6438 netId = message.arg1; 6439 config = mWifiConfigManager.getWifiConfiguration(netId); 6440 if (config == null) { 6441 loge("No network with id = " + netId); 6442 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6443 replyToMessage(message, message.what, FAILURE); 6444 break; 6445 } 6446 6447 // disable other only means select this network, does not mean all other 6448 // networks need to be disabled 6449 if (disableOthers) { 6450 mWifiQualifiedNetworkSelector.enableNetworkByUser(config); 6451 // Remember time of last connection attempt 6452 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6453 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6454 } 6455 // Cancel auto roam requests 6456 autoRoamSetBSSID(netId, "any"); 6457 6458 int uid = message.sendingUid; 6459 mWifiQualifiedNetworkSelector.enableNetworkByUser(config); 6460 ok = mWifiConfigManager.enableNetwork(netId, disableOthers, uid); 6461 if (!ok) { 6462 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6463 } else if (disableOthers) { 6464 mTargetNetworkId = netId; 6465 } 6466 6467 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 6468 break; 6469 case CMD_ENABLE_ALL_NETWORKS: 6470 long time = android.os.SystemClock.elapsedRealtime(); 6471 if (time - mLastEnableAllNetworksTime > MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS) { 6472 mWifiConfigManager.enableAllNetworks(); 6473 mLastEnableAllNetworksTime = time; 6474 } 6475 break; 6476 case WifiManager.DISABLE_NETWORK: 6477 if (mWifiConfigManager.updateNetworkSelectionStatus(message.arg1, 6478 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER)) { 6479 replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED); 6480 } else { 6481 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6482 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 6483 WifiManager.ERROR); 6484 } 6485 break; 6486 case CMD_DISABLE_EPHEMERAL_NETWORK: 6487 config = mWifiConfigManager.disableEphemeralNetwork((String)message.obj); 6488 if (config != null) { 6489 if (config.networkId == mLastNetworkId) { 6490 // Disconnect and let autojoin reselect a new network 6491 sendMessage(CMD_DISCONNECT); 6492 } 6493 } 6494 break; 6495 case CMD_BLACKLIST_NETWORK: 6496 mWifiConfigManager.blackListBssid((String) message.obj); 6497 break; 6498 case CMD_CLEAR_BLACKLIST: 6499 mWifiConfigManager.clearBssidBlacklist(); 6500 break; 6501 case CMD_SAVE_CONFIG: 6502 ok = mWifiConfigManager.saveConfig(); 6503 6504 if (DBG) logd("did save config " + ok); 6505 replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); 6506 6507 // Inform the backup manager about a data change 6508 mBackupManagerProxy.notifyDataChanged(); 6509 break; 6510 case CMD_GET_CONFIGURED_NETWORKS: 6511 replyToMessage(message, message.what, 6512 mWifiConfigManager.getConfiguredNetworks()); 6513 break; 6514 case WifiMonitor.SUP_REQUEST_IDENTITY: 6515 int networkId = message.arg2; 6516 boolean identitySent = false; 6517 int eapMethod = WifiEnterpriseConfig.Eap.NONE; 6518 6519 if (targetWificonfiguration != null 6520 && targetWificonfiguration.enterpriseConfig != null) { 6521 eapMethod = targetWificonfiguration.enterpriseConfig.getEapMethod(); 6522 } 6523 6524 // For SIM & AKA/AKA' EAP method Only, get identity from ICC 6525 if (targetWificonfiguration != null 6526 && targetWificonfiguration.networkId == networkId 6527 && targetWificonfiguration.allowedKeyManagement 6528 .get(WifiConfiguration.KeyMgmt.IEEE8021X) 6529 && (eapMethod == WifiEnterpriseConfig.Eap.SIM 6530 || eapMethod == WifiEnterpriseConfig.Eap.AKA 6531 || eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME)) { 6532 TelephonyManager tm = (TelephonyManager) 6533 mContext.getSystemService(Context.TELEPHONY_SERVICE); 6534 if (tm != null) { 6535 String imsi = tm.getSubscriberId(); 6536 String mccMnc = ""; 6537 6538 if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) 6539 mccMnc = tm.getSimOperator(); 6540 6541 String identity = buildIdentity(eapMethod, imsi, mccMnc); 6542 6543 if (!identity.isEmpty()) { 6544 mWifiNative.simIdentityResponse(networkId, identity); 6545 identitySent = true; 6546 } 6547 } 6548 } 6549 if (!identitySent) { 6550 // Supplicant lacks credentials to connect to that network, hence black list 6551 ssid = (String) message.obj; 6552 if (targetWificonfiguration != null && ssid != null 6553 && targetWificonfiguration.SSID != null 6554 && targetWificonfiguration.SSID.equals("\"" + ssid + "\"")) { 6555 mWifiConfigManager.updateNetworkSelectionStatus(targetWificonfiguration, 6556 WifiConfiguration.NetworkSelectionStatus 6557 .DISABLED_AUTHENTICATION_NO_CREDENTIALS); 6558 } 6559 // Disconnect now, as we don't have any way to fullfill 6560 // the supplicant request. 6561 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 6562 WifiConfiguration.INVALID_NETWORK_ID); 6563 mWifiNative.disconnect(); 6564 } 6565 break; 6566 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 6567 logd("Received SUP_REQUEST_SIM_AUTH"); 6568 SimAuthRequestData requestData = (SimAuthRequestData) message.obj; 6569 if (requestData != null) { 6570 if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) { 6571 handleGsmAuthRequest(requestData); 6572 } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA 6573 || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) { 6574 handle3GAuthRequest(requestData); 6575 } 6576 } else { 6577 loge("Invalid sim auth request"); 6578 } 6579 break; 6580 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 6581 replyToMessage(message, message.what, 6582 mWifiConfigManager.getPrivilegedConfiguredNetworks()); 6583 break; 6584 case CMD_GET_MATCHING_CONFIG: 6585 replyToMessage(message, message.what, 6586 mWifiConfigManager.getMatchingConfig((ScanResult)message.obj)); 6587 break; 6588 /* Do a redundant disconnect without transition */ 6589 case CMD_DISCONNECT: 6590 mWifiConfigManager.setAndEnableLastSelectedConfiguration 6591 (WifiConfiguration.INVALID_NETWORK_ID); 6592 mWifiNative.disconnect(); 6593 break; 6594 case CMD_RECONNECT: 6595 WifiConfiguration candidate = 6596 mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true, 6597 mAllowUntrustedConnections, mScanResults, linkDebouncing, 6598 isConnected(), isDisconnected(), isSupplicantTransientState()); 6599 tryToConnectToNetwork(candidate); 6600 break; 6601 case CMD_REASSOCIATE: 6602 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6603 mWifiNative.reassociate(); 6604 break; 6605 case CMD_RELOAD_TLS_AND_RECONNECT: 6606 if (mWifiConfigManager.needsUnlockedKeyStore()) { 6607 logd("Reconnecting to give a chance to un-connected TLS networks"); 6608 mWifiNative.disconnect(); 6609 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6610 mWifiNative.reconnect(); 6611 } 6612 break; 6613 case CMD_AUTO_ROAM: 6614 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6615 return HANDLED; 6616 case CMD_AUTO_CONNECT: 6617 /* Work Around: wpa_supplicant can get in a bad state where it returns a non 6618 * associated status to the STATUS command but somehow-someplace still thinks 6619 * it is associated and thus will ignore select/reconnect command with 6620 * following message: 6621 * "Already associated with the selected network - do nothing" 6622 * 6623 * Hence, sends a disconnect to supplicant first. 6624 */ 6625 didDisconnect = false; 6626 if (getCurrentState() != mDisconnectedState) { 6627 /** Supplicant will ignore the reconnect if we are currently associated, 6628 * hence trigger a disconnect 6629 */ 6630 didDisconnect = true; 6631 mWifiNative.disconnect(); 6632 } 6633 6634 /* connect command coming from auto-join */ 6635 netId = message.arg1; 6636 mTargetNetworkId = netId; 6637 mTargetRoamBSSID = (String) message.obj; 6638 config = mWifiConfigManager.getWifiConfiguration(netId); 6639 logd("CMD_AUTO_CONNECT sup state " 6640 + mSupplicantStateTracker.getSupplicantStateName() 6641 + " my state " + getCurrentState().getName() 6642 + " nid=" + Integer.toString(netId) 6643 + " roam=" + Boolean.toString(mAutoRoaming)); 6644 if (config == null) { 6645 loge("AUTO_CONNECT and no config, bail out..."); 6646 break; 6647 } 6648 6649 /* Make sure we cancel any previous roam request */ 6650 setTargetBssid(config, mTargetRoamBSSID); 6651 6652 /* Save the network config */ 6653 logd("CMD_AUTO_CONNECT will save config -> " + config.SSID 6654 + " nid=" + Integer.toString(netId)); 6655 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 6656 netId = result.getNetworkId(); 6657 logd("CMD_AUTO_CONNECT did save config -> " 6658 + " nid=" + Integer.toString(netId)); 6659 6660 // Since we updated the config,read it back from config store: 6661 config = mWifiConfigManager.getWifiConfiguration(netId); 6662 if (config == null) { 6663 loge("CMD_AUTO_CONNECT couldn't update the config, got null config"); 6664 break; 6665 } 6666 if (netId != config.networkId) { 6667 loge("CMD_AUTO_CONNECT couldn't update the config, want" 6668 + " nid=" + Integer.toString(netId) + " but got" + config.networkId); 6669 break; 6670 } 6671 6672 if (deferForUserInput(message, netId, false)) { 6673 break; 6674 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 6675 WifiConfiguration.USER_BANNED) { 6676 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6677 WifiManager.NOT_AUTHORIZED); 6678 break; 6679 } 6680 6681 // If we're autojoining a network that the user or an app explicitly selected, 6682 // keep track of the UID that selected it. 6683 // TODO(b/26786318): Keep track of the lastSelectedConfiguration and the 6684 // lastConnectUid on a per-user basis. 6685 int lastConnectUid = WifiConfiguration.UNKNOWN_UID; 6686 6687 //Start a new ConnectionEvent due to auto_connect, assume we are connecting 6688 //between different networks due to QNS, setting ROAM_UNRELATED 6689 mWifiMetrics.startConnectionEvent(config, 6690 WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); 6691 if (!didDisconnect) { 6692 //If we were originally disconnected, then this was not any kind of ROAM 6693 mWifiMetrics.setConnectionEventRoamType( 6694 WifiMetricsProto.ConnectionEvent.ROAM_NONE); 6695 } 6696 //Determine if this CONNECTION is for a user selection 6697 if (mWifiConfigManager.isLastSelectedConfiguration(config) 6698 && isCurrentUserProfile(UserHandle.getUserId(config.lastConnectUid))) { 6699 lastConnectUid = config.lastConnectUid; 6700 mWifiMetrics.setConnectionEventRoamType( 6701 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED); 6702 } 6703 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 6704 lastConnectUid) && mWifiNative.reconnect()) { 6705 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6706 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 6707 config = mWifiConfigManager.getWifiConfiguration(netId); 6708 if (config != null 6709 && !mWifiConfigManager.isLastSelectedConfiguration(config)) { 6710 // If we autojoined a different config than the user selected one, 6711 // it means we could not see the last user selection, 6712 // or that the last user selection was faulty and ended up blacklisted 6713 // for some reason (in which case the user is notified with an error 6714 // message in the Wifi picker), and thus we managed to auto-join away 6715 // from the selected config. -> in that case we need to forget 6716 // the selection because we don't want to abruptly switch back to it. 6717 // 6718 // Note that the user selection is also forgotten after a period of time 6719 // during which the device has been disconnected. 6720 // The default value is 30 minutes : see the code path at bottom of 6721 // setScanResults() function. 6722 mWifiConfigManager. 6723 setAndEnableLastSelectedConfiguration( 6724 WifiConfiguration.INVALID_NETWORK_ID); 6725 } 6726 mAutoRoaming = false; 6727 if (isRoaming() || linkDebouncing) { 6728 transitionTo(mRoamingState); 6729 } else if (didDisconnect) { 6730 transitionTo(mDisconnectingState); 6731 } else { 6732 /* Already in disconnected state, nothing to change */ 6733 if (!mScreenOn && mLegacyPnoEnabled && mBackgroundScanSupported) { 6734 int delay = 60 * 1000; 6735 if (DBG) { 6736 logd("Starting PNO alarm: " + delay); 6737 } 6738 mAlarmManager.set(AlarmManager.RTC_WAKEUP, 6739 System.currentTimeMillis() + delay, 6740 mPnoIntent); 6741 } 6742 mRestartAutoJoinOffloadCounter++; 6743 } 6744 } else { 6745 loge("Failed to connect config: " + config + " netId: " + netId); 6746 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6747 WifiManager.ERROR); 6748 mWifiMetrics.endConnectionEvent( 6749 WifiMetrics.ConnectionEvent.LLF_CONNECT_NETWORK_FAILED, 6750 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6751 break; 6752 } 6753 break; 6754 case CMD_REMOVE_APP_CONFIGURATIONS: 6755 mWifiConfigManager.removeNetworksForApp((ApplicationInfo) message.obj); 6756 break; 6757 case CMD_REMOVE_USER_CONFIGURATIONS: 6758 mWifiConfigManager.removeNetworksForUser(message.arg1); 6759 break; 6760 case WifiManager.CONNECT_NETWORK: 6761 // Only the current foreground user can modify networks. 6762 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6763 loge("Only the current foreground user can modify networks " 6764 + " currentUserId=" + mCurrentUserId 6765 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6766 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6767 WifiManager.NOT_AUTHORIZED); 6768 break; 6769 } 6770 6771 /** 6772 * The connect message can contain a network id passed as arg1 on message or 6773 * or a config passed as obj on message. 6774 * For a new network, a config is passed to create and connect. 6775 * For an existing network, a network id is passed 6776 */ 6777 netId = message.arg1; 6778 config = (WifiConfiguration) message.obj; 6779 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6780 boolean updatedExisting = false; 6781 6782 /* Save the network config */ 6783 if (config != null) { 6784 // When connecting to an access point, WifiStateMachine wants to update the 6785 // relevant config with administrative data. This update should not be 6786 // considered a 'real' update, therefore lockdown by Device Owner must be 6787 // disregarded. 6788 if (!recordUidIfAuthorized(config, message.sendingUid, 6789 /* onlyAnnotate */ true)) { 6790 logw("Not authorized to update network " 6791 + " config=" + config.SSID 6792 + " cnid=" + config.networkId 6793 + " uid=" + message.sendingUid); 6794 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6795 WifiManager.NOT_AUTHORIZED); 6796 break; 6797 } 6798 String configKey = config.configKey(true /* allowCached */); 6799 WifiConfiguration savedConfig = 6800 mWifiConfigManager.getWifiConfiguration(configKey); 6801 if (savedConfig != null) { 6802 // There is an existing config with this netId, but it wasn't exposed 6803 // (either AUTO_JOIN_DELETED or ephemeral; see WifiConfigManager# 6804 // getConfiguredNetworks). Remove those bits and update the config. 6805 config = savedConfig; 6806 logd("CONNECT_NETWORK updating existing config with id=" + 6807 config.networkId + " configKey=" + configKey); 6808 config.ephemeral = false; 6809 mWifiConfigManager.updateNetworkSelectionStatus(config, 6810 WifiConfiguration.NetworkSelectionStatus 6811 .NETWORK_SELECTION_ENABLE); 6812 updatedExisting = true; 6813 } 6814 6815 result = mWifiConfigManager.saveNetwork(config, message.sendingUid); 6816 netId = result.getNetworkId(); 6817 } 6818 config = mWifiConfigManager.getWifiConfiguration(netId); 6819 if (config == null) { 6820 logd("CONNECT_NETWORK no config for id=" + Integer.toString(netId) + " " 6821 + mSupplicantStateTracker.getSupplicantStateName() + " my state " 6822 + getCurrentState().getName()); 6823 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6824 WifiManager.ERROR); 6825 break; 6826 } 6827 mTargetNetworkId = netId; 6828 autoRoamSetBSSID(netId, "any"); 6829 if (message.sendingUid == Process.WIFI_UID 6830 || message.sendingUid == Process.SYSTEM_UID) { 6831 // As a sanity measure, clear the BSSID in the supplicant network block. 6832 // If system or Wifi Settings want to connect, they will not 6833 // specify the BSSID. 6834 // If an app however had added a BSSID to this configuration, and the BSSID 6835 // was wrong, Then we would forever fail to connect until that BSSID 6836 // is cleaned up. 6837 clearConfigBSSID(config, "CONNECT_NETWORK"); 6838 } 6839 6840 if (deferForUserInput(message, netId, true)) { 6841 break; 6842 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 6843 WifiConfiguration.USER_BANNED) { 6844 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6845 WifiManager.NOT_AUTHORIZED); 6846 break; 6847 } 6848 6849 mAutoRoaming = false; 6850 6851 /* Tell network selection the user did try to connect to that network if from 6852 settings */ 6853 boolean persist = 6854 mWifiConfigManager.checkConfigOverridePermission(message.sendingUid); 6855 6856 6857 mWifiConfigManager.setAndEnableLastSelectedConfiguration(netId); 6858 mWifiQualifiedNetworkSelector.userSelectNetwork(netId, persist); 6859 didDisconnect = false; 6860 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID 6861 && mLastNetworkId != netId) { 6862 /** Supplicant will ignore the reconnect if we are currently associated, 6863 * hence trigger a disconnect 6864 */ 6865 didDisconnect = true; 6866 mWifiNative.disconnect(); 6867 } 6868 6869 //Start a new ConnectionEvent due to connect_network, this is always user 6870 //selected 6871 mWifiMetrics.startConnectionEvent(config, 6872 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED); 6873 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ true, 6874 message.sendingUid) && mWifiNative.reconnect()) { 6875 lastConnectAttemptTimestamp = System.currentTimeMillis(); 6876 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 6877 6878 /* The state tracker handles enabling networks upon completion/failure */ 6879 mSupplicantStateTracker.sendMessage(WifiManager.CONNECT_NETWORK); 6880 replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 6881 if (didDisconnect) { 6882 /* Expect a disconnection from the old connection */ 6883 transitionTo(mDisconnectingState); 6884 } else if (updatedExisting && getCurrentState() == mConnectedState && 6885 getCurrentWifiConfiguration().networkId == netId) { 6886 // Update the current set of network capabilities, but stay in the 6887 // current state. 6888 updateCapabilities(config); 6889 } else { 6890 /** 6891 * Directly go to disconnected state where we 6892 * process the connection events from supplicant 6893 */ 6894 transitionTo(mDisconnectedState); 6895 } 6896 } else { 6897 loge("Failed to connect config: " + config + " netId: " + netId); 6898 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6899 WifiManager.ERROR); 6900 mWifiMetrics.endConnectionEvent( 6901 WifiMetrics.ConnectionEvent.LLF_CONNECT_NETWORK_FAILED, 6902 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6903 break; 6904 } 6905 break; 6906 case WifiManager.SAVE_NETWORK: 6907 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 6908 // Fall thru 6909 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 6910 // Only the current foreground user can modify networks. 6911 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 6912 loge("Only the current foreground user can modify networks " 6913 + " currentUserId=" + mCurrentUserId 6914 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 6915 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6916 WifiManager.NOT_AUTHORIZED); 6917 break; 6918 } 6919 6920 lastSavedConfigurationAttempt = null; // Used for debug 6921 config = (WifiConfiguration) message.obj; 6922 if (config == null) { 6923 loge("ERROR: SAVE_NETWORK with null configuration" 6924 + mSupplicantStateTracker.getSupplicantStateName() 6925 + " my state " + getCurrentState().getName()); 6926 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6927 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6928 WifiManager.ERROR); 6929 break; 6930 } 6931 lastSavedConfigurationAttempt = new WifiConfiguration(config); 6932 int nid = config.networkId; 6933 logd("SAVE_NETWORK id=" + Integer.toString(nid) 6934 + " config=" + config.SSID 6935 + " nid=" + config.networkId 6936 + " supstate=" + mSupplicantStateTracker.getSupplicantStateName() 6937 + " my state " + getCurrentState().getName()); 6938 6939 // Only record the uid if this is user initiated 6940 boolean checkUid = (message.what == WifiManager.SAVE_NETWORK); 6941 if (checkUid && !recordUidIfAuthorized(config, message.sendingUid, 6942 /* onlyAnnotate */ false)) { 6943 logw("Not authorized to update network " 6944 + " config=" + config.SSID 6945 + " cnid=" + config.networkId 6946 + " uid=" + message.sendingUid); 6947 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 6948 WifiManager.NOT_AUTHORIZED); 6949 break; 6950 } 6951 6952 result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID); 6953 if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) { 6954 if (mWifiInfo.getNetworkId() == result.getNetworkId()) { 6955 if (result.hasIpChanged()) { 6956 // The currently connection configuration was changed 6957 // We switched from DHCP to static or from static to DHCP, or the 6958 // static IP address has changed. 6959 log("Reconfiguring IP on connection"); 6960 // TODO: clear addresses and disable IPv6 6961 // to simplify obtainingIpState. 6962 transitionTo(mObtainingIpState); 6963 } 6964 if (result.hasProxyChanged()) { 6965 log("Reconfiguring proxy on connection"); 6966 mIpManager.setHttpProxy( 6967 mWifiConfigManager.getProxyProperties(mLastNetworkId)); 6968 } 6969 } 6970 replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED); 6971 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 6972 6973 if (DBG) { 6974 logd("Success save network nid=" 6975 + Integer.toString(result.getNetworkId())); 6976 } 6977 6978 /** 6979 * If the command comes from WifiManager, then 6980 * tell autojoin the user did try to modify and save that network, 6981 * and interpret the SAVE_NETWORK as a request to connect 6982 */ 6983 boolean user = message.what == WifiManager.SAVE_NETWORK; 6984 6985 // Did this connect come from settings 6986 boolean persistConnect = 6987 mWifiConfigManager.checkConfigOverridePermission( 6988 message.sendingUid); 6989 6990 if (user) { 6991 mWifiConfigManager.updateLastConnectUid(config, message.sendingUid); 6992 mWifiConfigManager.writeKnownNetworkHistory(); 6993 } 6994 //Fixme, CMD_AUTO_SAVE_NETWORK can be cleaned 6995 mWifiQualifiedNetworkSelector.userSelectNetwork( 6996 result.getNetworkId(), persistConnect); 6997 candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true, 6998 mAllowUntrustedConnections, mScanResults, linkDebouncing, 6999 isConnected(), isDisconnected(), isSupplicantTransientState()); 7000 tryToConnectToNetwork(candidate); 7001 } else { 7002 loge("Failed to save network"); 7003 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 7004 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 7005 WifiManager.ERROR); 7006 } 7007 break; 7008 case WifiManager.FORGET_NETWORK: 7009 // Only the current foreground user can modify networks. 7010 if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) { 7011 loge("Only the current foreground user can modify networks " 7012 + " currentUserId=" + mCurrentUserId 7013 + " sendingUserId=" + UserHandle.getUserId(message.sendingUid)); 7014 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 7015 WifiManager.NOT_AUTHORIZED); 7016 break; 7017 } 7018 7019 // Debug only, remember last configuration that was forgotten 7020 WifiConfiguration toRemove 7021 = mWifiConfigManager.getWifiConfiguration(message.arg1); 7022 if (toRemove == null) { 7023 lastForgetConfigurationAttempt = null; 7024 } else { 7025 lastForgetConfigurationAttempt = new WifiConfiguration(toRemove); 7026 } 7027 // check that the caller owns this network 7028 netId = message.arg1; 7029 7030 if (!mWifiConfigManager.canModifyNetwork(message.sendingUid, netId, 7031 /* onlyAnnotate */ false)) { 7032 logw("Not authorized to forget network " 7033 + " cnid=" + netId 7034 + " uid=" + message.sendingUid); 7035 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 7036 WifiManager.NOT_AUTHORIZED); 7037 break; 7038 } 7039 7040 if (mWifiConfigManager.forgetNetwork(message.arg1)) { 7041 replyToMessage(message, WifiManager.FORGET_NETWORK_SUCCEEDED); 7042 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, 7043 (WifiConfiguration) message.obj); 7044 } else { 7045 loge("Failed to forget network"); 7046 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 7047 WifiManager.ERROR); 7048 } 7049 break; 7050 case WifiManager.START_WPS: 7051 WpsInfo wpsInfo = (WpsInfo) message.obj; 7052 WpsResult wpsResult; 7053 switch (wpsInfo.setup) { 7054 case WpsInfo.PBC: 7055 wpsResult = mWifiConfigManager.startWpsPbc(wpsInfo); 7056 break; 7057 case WpsInfo.KEYPAD: 7058 wpsResult = mWifiConfigManager.startWpsWithPinFromAccessPoint(wpsInfo); 7059 break; 7060 case WpsInfo.DISPLAY: 7061 wpsResult = mWifiConfigManager.startWpsWithPinFromDevice(wpsInfo); 7062 break; 7063 default: 7064 wpsResult = new WpsResult(Status.FAILURE); 7065 loge("Invalid setup for WPS"); 7066 break; 7067 } 7068 mWifiConfigManager.setAndEnableLastSelectedConfiguration 7069 (WifiConfiguration.INVALID_NETWORK_ID); 7070 if (wpsResult.status == Status.SUCCESS) { 7071 replyToMessage(message, WifiManager.START_WPS_SUCCEEDED, wpsResult); 7072 transitionTo(mWpsRunningState); 7073 } else { 7074 loge("Failed to start WPS with config " + wpsInfo.toString()); 7075 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR); 7076 } 7077 break; 7078 case CMD_ASSOCIATED_BSSID: 7079 // This is where we can confirm the connection BSSID. Use it to find the 7080 // right ScanDetail to populate metrics. 7081 String someBssid = (String) message.obj; 7082 if (someBssid != null) { 7083 //Get the config associated with this connection attempt 7084 WifiConfiguration someConf = 7085 mWifiConfigManager.getWifiConfiguration(mTargetNetworkId); 7086 // Get the ScanDetail associated with this BSSID 7087 ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCache( 7088 someConf); 7089 if (scanDetailCache != null) { 7090 mWifiMetrics.setConnectionScanDetail(scanDetailCache.getScanDetail( 7091 someBssid)); 7092 } 7093 } 7094 return NOT_HANDLED; 7095 case WifiMonitor.NETWORK_CONNECTION_EVENT: 7096 if (DBG) log("Network connection established"); 7097 mLastNetworkId = message.arg1; 7098 mLastBssid = (String) message.obj; 7099 7100 mWifiInfo.setBSSID(mLastBssid); 7101 mWifiInfo.setNetworkId(mLastNetworkId); 7102 mWifiQualifiedNetworkSelector 7103 .enableBssidForQualityNetworkSelection(mLastBssid, true); 7104 sendNetworkStateChangeBroadcast(mLastBssid); 7105 transitionTo(mObtainingIpState); 7106 break; 7107 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7108 // Calling handleNetworkDisconnect here is redundant because we might already 7109 // have called it when leaving L2ConnectedState to go to disconnecting state 7110 // or thru other path 7111 // We should normally check the mWifiInfo or mLastNetworkId so as to check 7112 // if they are valid, and only in this case call handleNEtworkDisconnect, 7113 // TODO: this should be fixed for a L MR release 7114 // The side effect of calling handleNetworkDisconnect twice is that a bunch of 7115 // idempotent commands are executed twice (stopping Dhcp, enabling the SPS mode 7116 // at the chip etc... 7117 if (DBG) log("ConnectModeState: Network connection lost "); 7118 handleNetworkDisconnect(); 7119 transitionTo(mDisconnectedState); 7120 break; 7121 case CMD_PNO_NETWORK_FOUND: 7122 processPnoNetworkFound((ScanResult[]) message.obj); 7123 break; 7124 case CMD_ADD_PASSPOINT_MO: 7125 res = mWifiConfigManager.addPasspointManagementObject((String) message.obj); 7126 replyToMessage(message, message.what, res); 7127 break; 7128 case CMD_MODIFY_PASSPOINT_MO: 7129 if (message.obj != null) { 7130 Bundle bundle = (Bundle) message.obj; 7131 ArrayList<PasspointManagementObjectDefinition> mos = 7132 bundle.getParcelableArrayList("MOS"); 7133 res = mWifiConfigManager.modifyPasspointMo(bundle.getString("FQDN"), mos); 7134 } else { 7135 res = 0; 7136 } 7137 replyToMessage(message, message.what, res); 7138 7139 break; 7140 case CMD_QUERY_OSU_ICON: 7141 if (mWifiConfigManager.queryPasspointIcon( 7142 ((Bundle) message.obj).getLong("BSSID"), 7143 ((Bundle) message.obj).getString("FILENAME"))) { 7144 res = 1; 7145 } else { 7146 res = 0; 7147 } 7148 replyToMessage(message, message.what, res); 7149 break; 7150 case CMD_MATCH_PROVIDER_NETWORK: 7151 res = mWifiConfigManager.matchProviderWithCurrentNetwork((String) message.obj); 7152 replyToMessage(message, message.what, res); 7153 break; 7154 default: 7155 return NOT_HANDLED; 7156 } 7157 return HANDLED; 7158 } 7159 } 7160 7161 private void updateCapabilities(WifiConfiguration config) { 7162 NetworkCapabilities networkCapabilities = new NetworkCapabilities(mDfltNetworkCapabilities); 7163 if (config != null) { 7164 if (config.ephemeral) { 7165 networkCapabilities.removeCapability( 7166 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 7167 } else { 7168 networkCapabilities.addCapability( 7169 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 7170 } 7171 networkCapabilities.setSignalStrength(mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI ? 7172 mWifiInfo.getRssi() : NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED); 7173 } 7174 mNetworkAgent.sendNetworkCapabilities(networkCapabilities); 7175 } 7176 7177 private class WifiNetworkAgent extends NetworkAgent { 7178 public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, 7179 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { 7180 super(l, c, TAG, ni, nc, lp, score, misc); 7181 } 7182 protected void unwanted() { 7183 // Ignore if we're not the current networkAgent. 7184 if (this != mNetworkAgent) return; 7185 if (DBG) log("WifiNetworkAgent -> Wifi unwanted score " 7186 + Integer.toString(mWifiInfo.score)); 7187 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT); 7188 } 7189 7190 @Override 7191 protected void networkStatus(int status) { 7192 if (this != mNetworkAgent) return; 7193 if (status == NetworkAgent.INVALID_NETWORK) { 7194 if (DBG) log("WifiNetworkAgent -> Wifi networkStatus invalid, score=" 7195 + Integer.toString(mWifiInfo.score)); 7196 unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED); 7197 } else if (status == NetworkAgent.VALID_NETWORK) { 7198 if (DBG && mWifiInfo != null) log("WifiNetworkAgent -> Wifi networkStatus valid, score= " 7199 + Integer.toString(mWifiInfo.score)); 7200 doNetworkStatus(status); 7201 } 7202 } 7203 7204 @Override 7205 protected void saveAcceptUnvalidated(boolean accept) { 7206 if (this != mNetworkAgent) return; 7207 WifiStateMachine.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0); 7208 } 7209 7210 @Override 7211 protected void startPacketKeepalive(Message msg) { 7212 WifiStateMachine.this.sendMessage( 7213 CMD_START_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 7214 } 7215 7216 @Override 7217 protected void stopPacketKeepalive(Message msg) { 7218 WifiStateMachine.this.sendMessage( 7219 CMD_STOP_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 7220 } 7221 7222 @Override 7223 protected void setSignalStrengthThresholds(int[] thresholds) { 7224 // 0. If there are no thresholds, or if the thresholds are invalid, stop RSSI monitoring. 7225 // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and 7226 // MAX_VALUE at the start/end of the thresholds array if necessary. 7227 // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware 7228 // event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then 7229 // re-arm the hardware event. This needs to be done on the state machine thread to 7230 // avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one 7231 // sent in the NetworkCapabilities) must be the one received from the hardware event 7232 // received, or we might skip callbacks. 7233 // 3. Ensure that when we disconnect, RSSI monitoring is stopped. 7234 log("Received signal strength thresholds: " + Arrays.toString(thresholds)); 7235 if (thresholds.length == 0) { 7236 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 7237 mWifiInfo.getRssi()); 7238 return; 7239 } 7240 int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2); 7241 rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE; 7242 rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE; 7243 Arrays.sort(rssiVals); 7244 byte[] rssiRange = new byte[rssiVals.length]; 7245 for (int i = 0; i < rssiVals.length; i++) { 7246 int val = rssiVals[i]; 7247 if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) { 7248 rssiRange[i] = (byte) val; 7249 } else { 7250 Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: " 7251 + Arrays.toString(rssiVals)); 7252 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 7253 mWifiInfo.getRssi()); 7254 return; 7255 } 7256 } 7257 // TODO: Do we quash rssi values in this sorted array which are very close? 7258 mRssiRanges = rssiRange; 7259 WifiStateMachine.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD, 7260 mWifiInfo.getRssi()); 7261 } 7262 7263 @Override 7264 protected void preventAutomaticReconnect() { 7265 if (this != mNetworkAgent) return; 7266 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN); 7267 } 7268 7269 @Override 7270 protected boolean installPacketFilter(byte[] filter) { 7271 return mWifiNative.installPacketFilter(filter); 7272 } 7273 } 7274 7275 void unwantedNetwork(int reason) { 7276 sendMessage(CMD_UNWANTED_NETWORK, reason); 7277 } 7278 7279 void doNetworkStatus(int status) { 7280 sendMessage(CMD_NETWORK_STATUS, status); 7281 } 7282 7283 // rfc4186 & rfc4187: 7284 // create Permanent Identity base on IMSI, 7285 // identity = usernam@realm 7286 // with username = prefix | IMSI 7287 // and realm is derived MMC/MNC tuple according 3GGP spec(TS23.003) 7288 private String buildIdentity(int eapMethod, String imsi, String mccMnc) { 7289 String mcc; 7290 String mnc; 7291 String prefix; 7292 7293 if (imsi == null || imsi.isEmpty()) 7294 return ""; 7295 7296 if (eapMethod == WifiEnterpriseConfig.Eap.SIM) 7297 prefix = "1"; 7298 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA) 7299 prefix = "0"; 7300 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME) 7301 prefix = "6"; 7302 else // not a valide EapMethod 7303 return ""; 7304 7305 /* extract mcc & mnc from mccMnc */ 7306 if (mccMnc != null && !mccMnc.isEmpty()) { 7307 mcc = mccMnc.substring(0, 3); 7308 mnc = mccMnc.substring(3); 7309 if (mnc.length() == 2) 7310 mnc = "0" + mnc; 7311 } else { 7312 // extract mcc & mnc from IMSI, assume mnc size is 3 7313 mcc = imsi.substring(0, 3); 7314 mnc = imsi.substring(3, 6); 7315 } 7316 7317 return prefix + imsi + "@wlan.mnc" + mnc + ".mcc" + mcc + ".3gppnetwork.org"; 7318 } 7319 7320 boolean startScanForConfiguration(WifiConfiguration config, boolean restrictChannelList) { 7321 if (config == null) 7322 return false; 7323 7324 // We are still seeing a fairly high power consumption triggered by autojoin scans 7325 // Hence do partial scans only for PSK configuration that are roamable since the 7326 // primary purpose of the partial scans is roaming. 7327 // Full badn scans with exponential backoff for the purpose or extended roaming and 7328 // network switching are performed unconditionally. 7329 ScanDetailCache scanDetailCache = 7330 mWifiConfigManager.getScanDetailCache(config); 7331 if (scanDetailCache == null 7332 || !config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) 7333 || scanDetailCache.size() > 6) { 7334 //return true but to not trigger the scan 7335 return true; 7336 } 7337 HashSet<Integer> freqs = mWifiConfigManager.makeChannelList(config, 7338 ONE_HOUR_MILLI, restrictChannelList); 7339 if (freqs != null && freqs.size() != 0) { 7340 //if (DBG) { 7341 logd("starting scan for " + config.configKey() + " with " + freqs); 7342 //} 7343 Set<Integer> hiddenNetworkIds = new HashSet<>(); 7344 if (config.hiddenSSID) { 7345 hiddenNetworkIds.add(config.networkId); 7346 } 7347 // Call wifi native to start the scan 7348 if (startScanNative(freqs, hiddenNetworkIds)) { 7349 // Only count battery consumption if scan request is accepted 7350 noteScanStart(SCAN_ALARM_SOURCE, null); 7351 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; 7352 } else { 7353 // used for debug only, mark scan as failed 7354 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 7355 } 7356 return true; 7357 } else { 7358 if (DBG) logd("no channels for " + config.configKey()); 7359 return false; 7360 } 7361 } 7362 7363 void clearCurrentConfigBSSID(String dbg) { 7364 // Clear the bssid in the current config's network block 7365 WifiConfiguration config = getCurrentWifiConfiguration(); 7366 if (config == null) 7367 return; 7368 clearConfigBSSID(config, dbg); 7369 } 7370 void clearConfigBSSID(WifiConfiguration config, String dbg) { 7371 if (config == null) 7372 return; 7373 if (DBG) { 7374 logd(dbg + " " + mTargetRoamBSSID + " config " + config.configKey() 7375 + " config.NetworkSelectionStatus.mNetworkSelectionBSSID " 7376 + config.getNetworkSelectionStatus().getNetworkSelectionBSSID()); 7377 } 7378 if (DBG) { 7379 logd(dbg + " " + config.SSID 7380 + " nid=" + Integer.toString(config.networkId)); 7381 } 7382 mWifiConfigManager.saveWifiConfigBSSID(config, "any"); 7383 } 7384 7385 class L2ConnectedState extends State { 7386 @Override 7387 public void enter() { 7388 mRssiPollToken++; 7389 if (mEnableRssiPolling) { 7390 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0); 7391 } 7392 if (mNetworkAgent != null) { 7393 loge("Have NetworkAgent when entering L2Connected"); 7394 setNetworkDetailedState(DetailedState.DISCONNECTED); 7395 } 7396 setNetworkDetailedState(DetailedState.CONNECTING); 7397 7398 WifiNative.PacketFilterCapabilities packetFilterCapabilities = 7399 mWifiNative.getPacketFilterCapabilities(); 7400 if (packetFilterCapabilities != null) { 7401 mNetworkMisc.apfVersionSupported = 7402 packetFilterCapabilities.apfVersionSupported; 7403 mNetworkMisc.maximumApfProgramSize = 7404 packetFilterCapabilities.maximumApfProgramSize; 7405 mNetworkMisc.apfPacketFormat = ARPHRD_ETHER; 7406 } 7407 7408 mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, 7409 "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter, 7410 mLinkProperties, 60, mNetworkMisc); 7411 7412 // We must clear the config BSSID, as the wifi chipset may decide to roam 7413 // from this point on and having the BSSID specified in the network block would 7414 // cause the roam to faile and the device to disconnect 7415 clearCurrentConfigBSSID("L2ConnectedState"); 7416 } 7417 7418 @Override 7419 public void exit() { 7420 mIpManager.stop(); 7421 7422 // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState 7423 // Bug: 15347363 7424 // For paranoia's sake, call handleNetworkDisconnect 7425 // only if BSSID is null or last networkId 7426 // is not invalid. 7427 if (DBG) { 7428 StringBuilder sb = new StringBuilder(); 7429 sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId)); 7430 if (mLastBssid !=null) { 7431 sb.append(" ").append(mLastBssid); 7432 } 7433 } 7434 if (mLastBssid != null || mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 7435 handleNetworkDisconnect(); 7436 } 7437 } 7438 7439 @Override 7440 public boolean processMessage(Message message) { 7441 logStateAndMessage(message, this); 7442 7443 switch (message.what) { 7444 case DhcpClient.CMD_PRE_DHCP_ACTION: 7445 handlePreDhcpSetup(); 7446 break; 7447 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 7448 mIpManager.completedPreDhcpAction(); 7449 break; 7450 case DhcpClient.CMD_POST_DHCP_ACTION: 7451 handlePostDhcpSetup(); 7452 // We advance to mConnectedState because IpManager will also send a 7453 // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(), 7454 // which calls updateLinkProperties, which then sends 7455 // CMD_IP_CONFIGURATION_SUCCESSFUL. 7456 // 7457 // In the event of failure, we transition to mDisconnectingState 7458 // similarly--via messages sent back from IpManager. 7459 break; 7460 case CMD_IPV4_PROVISIONING_SUCCESS: { 7461 handleIPv4Success((DhcpResults) message.obj); 7462 break; 7463 } 7464 case CMD_IPV4_PROVISIONING_FAILURE: { 7465 handleIPv4Failure(); 7466 break; 7467 } 7468 case CMD_IP_CONFIGURATION_SUCCESSFUL: 7469 handleSuccessfulIpConfiguration(); 7470 mWifiMetrics.endConnectionEvent( 7471 WifiMetrics.ConnectionEvent.LLF_NONE, 7472 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7473 sendConnectedState(); 7474 transitionTo(mConnectedState); 7475 break; 7476 case CMD_IP_CONFIGURATION_LOST: 7477 // Get Link layer stats so that we get fresh tx packet counters. 7478 getWifiLinkLayerStats(true); 7479 handleIpConfigurationLost(); 7480 transitionTo(mDisconnectingState); 7481 break; 7482 case CMD_IP_REACHABILITY_LOST: 7483 if (DBG && message.obj != null) log((String) message.obj); 7484 handleIpReachabilityLost(); 7485 transitionTo(mDisconnectingState); 7486 break; 7487 case CMD_DISCONNECT: 7488 mWifiNative.disconnect(); 7489 transitionTo(mDisconnectingState); 7490 break; 7491 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 7492 if (message.arg1 == 1) { 7493 mWifiNative.disconnect(); 7494 mTemporarilyDisconnectWifi = true; 7495 transitionTo(mDisconnectingState); 7496 } 7497 break; 7498 case CMD_SET_OPERATIONAL_MODE: 7499 if (message.arg1 != CONNECT_MODE) { 7500 sendMessage(CMD_DISCONNECT); 7501 deferMessage(message); 7502 if (message.arg1 == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 7503 noteWifiDisabledWhileAssociated(); 7504 } 7505 } 7506 mWifiConfigManager. 7507 setAndEnableLastSelectedConfiguration( 7508 WifiConfiguration.INVALID_NETWORK_ID); 7509 break; 7510 case CMD_SET_COUNTRY_CODE: 7511 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 7512 deferMessage(message); 7513 break; 7514 case CMD_START_SCAN: 7515 if (DBG) { 7516 logd("CMD_START_SCAN source " + message.arg1 7517 + " txSuccessRate="+String.format( "%.2f", mWifiInfo.txSuccessRate) 7518 + " rxSuccessRate="+String.format( "%.2f", mWifiInfo.rxSuccessRate) 7519 + " targetRoamBSSID=" + mTargetRoamBSSID 7520 + " RSSI=" + mWifiInfo.getRssi()); 7521 } 7522 if (message.arg1 == SCAN_ALARM_SOURCE) { 7523 // Check if the CMD_START_SCAN message is obsolete (and thus if it should 7524 // not be processed) and restart the scan if neede 7525 if (!getEnableAutoJoinWhenAssociated()) { 7526 return HANDLED; 7527 } 7528 boolean shouldScan = mScreenOn; 7529 7530 if (!checkAndRestartDelayedScan(message.arg2, 7531 shouldScan, 7532 mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get(), 7533 null, null)) { 7534 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 7535 logd("L2Connected CMD_START_SCAN source " 7536 + message.arg1 7537 + " " + message.arg2 + ", " + mDelayedScanCounter 7538 + " -> obsolete"); 7539 return HANDLED; 7540 } 7541 if (mP2pConnected.get()) { 7542 logd("L2Connected CMD_START_SCAN source " 7543 + message.arg1 7544 + " " + message.arg2 + ", " + mDelayedScanCounter 7545 + " ignore because P2P is connected"); 7546 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7547 return HANDLED; 7548 } 7549 boolean tryFullBandScan = false; 7550 boolean restrictChannelList = false; 7551 long now_ms = System.currentTimeMillis(); 7552 if (DBG) { 7553 logd("CMD_START_SCAN with age=" 7554 + Long.toString(now_ms - lastFullBandConnectedTimeMilli) 7555 + " interval=" + fullBandConnectedTimeIntervalMilli 7556 + " maxinterval=" + maxFullBandConnectedTimeIntervalMilli); 7557 } 7558 if (mWifiInfo != null) { 7559 if (mWifiConfigManager.enableFullBandScanWhenAssociated.get() && 7560 (now_ms - lastFullBandConnectedTimeMilli) 7561 > fullBandConnectedTimeIntervalMilli) { 7562 if (DBG) { 7563 logd("CMD_START_SCAN try full band scan age=" 7564 + Long.toString(now_ms - lastFullBandConnectedTimeMilli) 7565 + " interval=" + fullBandConnectedTimeIntervalMilli 7566 + " maxinterval=" + maxFullBandConnectedTimeIntervalMilli); 7567 } 7568 tryFullBandScan = true; 7569 } 7570 7571 if (mWifiInfo.txSuccessRate > 7572 mWifiConfigManager.maxTxPacketForFullScans 7573 || mWifiInfo.rxSuccessRate > 7574 mWifiConfigManager.maxRxPacketForFullScans) { 7575 // Too much traffic at the interface, hence no full band scan 7576 if (DBG) { 7577 logd("CMD_START_SCAN " + 7578 "prevent full band scan due to pkt rate"); 7579 } 7580 tryFullBandScan = false; 7581 } 7582 7583 if (mWifiInfo.txSuccessRate > 7584 mWifiConfigManager.maxTxPacketForPartialScans 7585 || mWifiInfo.rxSuccessRate > 7586 mWifiConfigManager.maxRxPacketForPartialScans) { 7587 // Don't scan if lots of packets are being sent 7588 restrictChannelList = true; 7589 if (mWifiConfigManager.alwaysEnableScansWhileAssociated.get() == 7590 0) { 7591 if (DBG) { 7592 logd("CMD_START_SCAN source " + message.arg1 7593 + " ...and ignore scans" 7594 + " tx=" + String.format("%.2f", mWifiInfo.txSuccessRate) 7595 + " rx=" + String.format("%.2f", mWifiInfo.rxSuccessRate)); 7596 } 7597 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 7598 return HANDLED; 7599 } 7600 } 7601 } 7602 7603 WifiConfiguration currentConfiguration = getCurrentWifiConfiguration(); 7604 if (DBG) { 7605 logd("CMD_START_SCAN full=" + 7606 tryFullBandScan); 7607 } 7608 if (currentConfiguration != null) { 7609 if (fullBandConnectedTimeIntervalMilli < 7610 mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get()) { 7611 // Sanity 7612 fullBandConnectedTimeIntervalMilli = 7613 mWifiConfigManager 7614 .wifiAssociatedShortScanIntervalMilli.get(); 7615 } 7616 if (tryFullBandScan) { 7617 lastFullBandConnectedTimeMilli = now_ms; 7618 if (fullBandConnectedTimeIntervalMilli 7619 < mWifiConfigManager.associatedFullScanMaxIntervalMilli) { 7620 // Increase the interval 7621 fullBandConnectedTimeIntervalMilli = 7622 fullBandConnectedTimeIntervalMilli * 7623 mWifiConfigManager 7624 .associatedFullScanBackoff.get() / 8; 7625 7626 if (DBG) { 7627 logd("CMD_START_SCAN bump interval =" 7628 + fullBandConnectedTimeIntervalMilli); 7629 } 7630 } 7631 handleScanRequest(message); 7632 } else { 7633 if (!startScanForConfiguration( 7634 currentConfiguration, restrictChannelList)) { 7635 if (DBG) { 7636 logd("starting scan, " + 7637 " did not find channels -> full"); 7638 } 7639 lastFullBandConnectedTimeMilli = now_ms; 7640 if (fullBandConnectedTimeIntervalMilli 7641 < mWifiConfigManager 7642 .associatedFullScanMaxIntervalMilli) { 7643 // Increase the interval 7644 fullBandConnectedTimeIntervalMilli = 7645 fullBandConnectedTimeIntervalMilli * 7646 mWifiConfigManager 7647 .associatedFullScanBackoff.get() / 8; 7648 7649 if (DBG) { 7650 logd("CMD_START_SCAN bump interval =" 7651 + fullBandConnectedTimeIntervalMilli); 7652 } 7653 } 7654 handleScanRequest(message); 7655 } 7656 } 7657 7658 } else { 7659 logd("CMD_START_SCAN : connected mode and no configuration"); 7660 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 7661 } 7662 } else { 7663 // Not scan alarm source 7664 return NOT_HANDLED; 7665 } 7666 break; 7667 /* Ignore connection to same network */ 7668 case WifiManager.CONNECT_NETWORK: 7669 int netId = message.arg1; 7670 if (mWifiInfo.getNetworkId() == netId) { 7671 break; 7672 } 7673 return NOT_HANDLED; 7674 case WifiMonitor.NETWORK_CONNECTION_EVENT: 7675 mWifiInfo.setBSSID((String) message.obj); 7676 mLastNetworkId = message.arg1; 7677 mWifiInfo.setNetworkId(mLastNetworkId); 7678 if(!mLastBssid.equals((String) message.obj)) { 7679 mLastBssid = (String) message.obj; 7680 sendNetworkStateChangeBroadcast(mLastBssid); 7681 } 7682 break; 7683 case CMD_RSSI_POLL: 7684 if (message.arg1 == mRssiPollToken) { 7685 if (mWifiConfigManager.enableChipWakeUpWhenAssociated.get()) { 7686 if (DBG) log(" get link layer stats " + mWifiLinkLayerStatsSupported); 7687 WifiLinkLayerStats stats = getWifiLinkLayerStats(DBG); 7688 if (stats != null) { 7689 // Sanity check the results provided by driver 7690 if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI 7691 && (stats.rssi_mgmt == 0 7692 || stats.beacon_rx == 0)) { 7693 stats = null; 7694 } 7695 } 7696 // Get Info and continue polling 7697 fetchRssiLinkSpeedAndFrequencyNative(); 7698 mWifiScoreReport = 7699 WifiScoreReport.calculateScore(mWifiInfo, 7700 getCurrentWifiConfiguration(), 7701 mWifiConfigManager, 7702 mNetworkAgent, 7703 mWifiScoreReport, 7704 mAggressiveHandover); 7705 } 7706 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 7707 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 7708 if (DBG) sendRssiChangeBroadcast(mWifiInfo.getRssi()); 7709 } else { 7710 // Polling has completed 7711 } 7712 break; 7713 case CMD_ENABLE_RSSI_POLL: 7714 cleanWifiScore(); 7715 if (mWifiConfigManager.enableRssiPollWhenAssociated.get()) { 7716 mEnableRssiPolling = (message.arg1 == 1); 7717 } else { 7718 mEnableRssiPolling = false; 7719 } 7720 mRssiPollToken++; 7721 if (mEnableRssiPolling) { 7722 // First poll 7723 fetchRssiLinkSpeedAndFrequencyNative(); 7724 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 7725 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 7726 } 7727 break; 7728 case WifiManager.RSSI_PKTCNT_FETCH: 7729 RssiPacketCountInfo info = new RssiPacketCountInfo(); 7730 fetchRssiLinkSpeedAndFrequencyNative(); 7731 info.rssi = mWifiInfo.getRssi(); 7732 fetchPktcntNative(info); 7733 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED, info); 7734 break; 7735 case CMD_DELAYED_NETWORK_DISCONNECT: 7736 if (!linkDebouncing && mWifiConfigManager.enableLinkDebouncing) { 7737 7738 // Ignore if we are not debouncing 7739 logd("CMD_DELAYED_NETWORK_DISCONNECT and not debouncing - ignore " 7740 + message.arg1); 7741 return HANDLED; 7742 } else { 7743 logd("CMD_DELAYED_NETWORK_DISCONNECT and debouncing - disconnect " 7744 + message.arg1); 7745 7746 linkDebouncing = false; 7747 // If we are still debouncing while this message comes, 7748 // it means we were not able to reconnect within the alloted time 7749 // = LINK_FLAPPING_DEBOUNCE_MSEC 7750 // and thus, trigger a real disconnect 7751 handleNetworkDisconnect(); 7752 transitionTo(mDisconnectedState); 7753 } 7754 break; 7755 case CMD_ASSOCIATED_BSSID: 7756 if ((String) message.obj == null) { 7757 logw("Associated command w/o BSSID"); 7758 break; 7759 } 7760 mLastBssid = (String) message.obj; 7761 if (mLastBssid != null && (mWifiInfo.getBSSID() == null 7762 || !mLastBssid.equals(mWifiInfo.getBSSID()))) { 7763 mWifiInfo.setBSSID((String) message.obj); 7764 sendNetworkStateChangeBroadcast(mLastBssid); 7765 } 7766 break; 7767 case CMD_START_RSSI_MONITORING_OFFLOAD: 7768 case CMD_RSSI_THRESHOLD_BREACH: 7769 byte currRssi = (byte) message.arg1; 7770 processRssiThreshold(currRssi, message.what); 7771 break; 7772 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 7773 stopRssiMonitoringOffload(); 7774 break; 7775 case CMD_RESET_SIM_NETWORKS: 7776 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 7777 WifiConfiguration config = 7778 mWifiConfigManager.getWifiConfiguration(mLastNetworkId); 7779 if (mWifiConfigManager.isSimConfig(config)) { 7780 mWifiNative.disconnect(); 7781 transitionTo(mDisconnectingState); 7782 } 7783 } 7784 /* allow parent state to reset data for other networks */ 7785 return NOT_HANDLED; 7786 default: 7787 return NOT_HANDLED; 7788 } 7789 7790 return HANDLED; 7791 } 7792 } 7793 7794 class ObtainingIpState extends State { 7795 @Override 7796 public void enter() { 7797 if (DBG) { 7798 String key = ""; 7799 if (getCurrentWifiConfiguration() != null) { 7800 key = getCurrentWifiConfiguration().configKey(); 7801 } 7802 log("enter ObtainingIpState netId=" + Integer.toString(mLastNetworkId) 7803 + " " + key + " " 7804 + " roam=" + mAutoRoaming 7805 + " static=" + mWifiConfigManager.isUsingStaticIp(mLastNetworkId) 7806 + " watchdog= " + obtainingIpWatchdogCount); 7807 } 7808 7809 // Reset link Debouncing, indicating we have successfully re-connected to the AP 7810 // We might still be roaming 7811 linkDebouncing = false; 7812 7813 // Send event to CM & network change broadcast 7814 setNetworkDetailedState(DetailedState.OBTAINING_IPADDR); 7815 7816 // We must clear the config BSSID, as the wifi chipset may decide to roam 7817 // from this point on and having the BSSID specified in the network block would 7818 // cause the roam to fail and the device to disconnect. 7819 clearCurrentConfigBSSID("ObtainingIpAddress"); 7820 7821 // Stop IpManager in case we're switching from DHCP to static 7822 // configuration or vice versa. 7823 // 7824 // TODO: Only ever enter this state the first time we connect to a 7825 // network, never on switching between static configuration and 7826 // DHCP. When we transition from static configuration to DHCP in 7827 // particular, we must tell ConnectivityService that we're 7828 // disconnected, because DHCP might take a long time during which 7829 // connectivity APIs such as getActiveNetworkInfo should not return 7830 // CONNECTED. 7831 stopIpManager(); 7832 7833 mIpManager.setHttpProxy(mWifiConfigManager.getProxyProperties(mLastNetworkId)); 7834 if (!TextUtils.isEmpty(mTcpBufferSizes)) { 7835 mIpManager.setTcpBufferSizes(mTcpBufferSizes); 7836 } 7837 7838 if (!mWifiConfigManager.isUsingStaticIp(mLastNetworkId)) { 7839 final IpManager.ProvisioningConfiguration prov = 7840 mIpManager.buildProvisioningConfiguration() 7841 .withPreDhcpAction() 7842 .build(); 7843 mIpManager.startProvisioning(prov); 7844 obtainingIpWatchdogCount++; 7845 logd("Start Dhcp Watchdog " + obtainingIpWatchdogCount); 7846 // Get Link layer stats so as we get fresh tx packet counters 7847 getWifiLinkLayerStats(true); 7848 sendMessageDelayed(obtainMessage(CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER, 7849 obtainingIpWatchdogCount, 0), OBTAINING_IP_ADDRESS_GUARD_TIMER_MSEC); 7850 } else { 7851 StaticIpConfiguration config = mWifiConfigManager.getStaticIpConfiguration( 7852 mLastNetworkId); 7853 if (config.ipAddress == null) { 7854 logd("Static IP lacks address"); 7855 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 7856 } else { 7857 final IpManager.ProvisioningConfiguration prov = 7858 mIpManager.buildProvisioningConfiguration() 7859 .withStaticConfiguration(config) 7860 .build(); 7861 mIpManager.startProvisioning(prov); 7862 } 7863 } 7864 } 7865 7866 @Override 7867 public boolean processMessage(Message message) { 7868 logStateAndMessage(message, this); 7869 7870 switch(message.what) { 7871 case CMD_AUTO_CONNECT: 7872 case CMD_AUTO_ROAM: 7873 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7874 break; 7875 case WifiManager.SAVE_NETWORK: 7876 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK: 7877 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 7878 deferMessage(message); 7879 break; 7880 /* Defer any power mode changes since we must keep active power mode at DHCP */ 7881 7882 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 7883 mWifiMetrics.endConnectionEvent( 7884 WifiMetrics.ConnectionEvent.LLF_NETWORK_DISCONNECTION, 7885 WifiMetricsProto.ConnectionEvent.HLF_NONE); 7886 return NOT_HANDLED; 7887 case CMD_SET_HIGH_PERF_MODE: 7888 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 7889 deferMessage(message); 7890 break; 7891 /* Defer scan request since we should not switch to other channels at DHCP */ 7892 case CMD_START_SCAN: 7893 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 7894 deferMessage(message); 7895 break; 7896 case CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER: 7897 if (message.arg1 == obtainingIpWatchdogCount) { 7898 logd("ObtainingIpAddress: Watchdog Triggered, count=" 7899 + obtainingIpWatchdogCount); 7900 handleIpConfigurationLost(); 7901 transitionTo(mDisconnectingState); 7902 break; 7903 } 7904 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 7905 break; 7906 default: 7907 return NOT_HANDLED; 7908 } 7909 return HANDLED; 7910 } 7911 } 7912 7913 private void sendConnectedState() { 7914 // If this network was explicitly selected by the user, evaluate whether to call 7915 // explicitlySelected() so the system can treat it appropriately. 7916 WifiConfiguration config = getCurrentWifiConfiguration(); 7917 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 7918 boolean prompt = 7919 mWifiConfigManager.checkConfigOverridePermission(config.lastConnectUid); 7920 if (DBG) { 7921 log("Network selected by UID " + config.lastConnectUid + " prompt=" + prompt); 7922 } 7923 if (prompt) { 7924 // Selected by the user via Settings or QuickSettings. If this network has Internet 7925 // access, switch to it. Otherwise, switch to it only if the user confirms that they 7926 // really want to switch, or has already confirmed and selected "Don't ask again". 7927 if (DBG) { 7928 log("explictlySelected acceptUnvalidated=" + config.noInternetAccessExpected); 7929 } 7930 mNetworkAgent.explicitlySelected(config.noInternetAccessExpected); 7931 } 7932 } 7933 7934 setNetworkDetailedState(DetailedState.CONNECTED); 7935 mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.CONNECTED); 7936 sendNetworkStateChangeBroadcast(mLastBssid); 7937 } 7938 7939 class RoamingState extends State { 7940 boolean mAssociated; 7941 @Override 7942 public void enter() { 7943 if (DBG) { 7944 log("RoamingState Enter" 7945 + " mScreenOn=" + mScreenOn ); 7946 } 7947 setScanAlarm(false); 7948 7949 // Make sure we disconnect if roaming fails 7950 roamWatchdogCount++; 7951 logd("Start Roam Watchdog " + roamWatchdogCount); 7952 sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER, 7953 roamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); 7954 mAssociated = false; 7955 } 7956 @Override 7957 public boolean processMessage(Message message) { 7958 logStateAndMessage(message, this); 7959 WifiConfiguration config; 7960 switch (message.what) { 7961 case CMD_IP_CONFIGURATION_LOST: 7962 config = getCurrentWifiConfiguration(); 7963 if (config != null) { 7964 mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_AUTOROAM_FAILURE); 7965 mWifiConfigManager.noteRoamingFailure(config, 7966 WifiConfiguration.ROAMING_FAILURE_IP_CONFIG); 7967 } 7968 return NOT_HANDLED; 7969 case CMD_UNWANTED_NETWORK: 7970 if (DBG) log("Roaming and CS doesnt want the network -> ignore"); 7971 return HANDLED; 7972 case CMD_SET_OPERATIONAL_MODE: 7973 if (message.arg1 != CONNECT_MODE) { 7974 deferMessage(message); 7975 } 7976 break; 7977 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 7978 /** 7979 * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT 7980 * before NETWORK_DISCONNECTION_EVENT 7981 * And there is an associated BSSID corresponding to our target BSSID, then 7982 * we have missed the network disconnection, transition to mDisconnectedState 7983 * and handle the rest of the events there. 7984 */ 7985 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 7986 if (stateChangeResult.state == SupplicantState.DISCONNECTED 7987 || stateChangeResult.state == SupplicantState.INACTIVE 7988 || stateChangeResult.state == SupplicantState.INTERFACE_DISABLED) { 7989 if (DBG) { 7990 log("STATE_CHANGE_EVENT in roaming state " 7991 + stateChangeResult.toString() ); 7992 } 7993 if (stateChangeResult.BSSID != null 7994 && stateChangeResult.BSSID.equals(mTargetRoamBSSID)) { 7995 handleNetworkDisconnect(); 7996 transitionTo(mDisconnectedState); 7997 } 7998 } 7999 if (stateChangeResult.state == SupplicantState.ASSOCIATED) { 8000 // We completed the layer2 roaming part 8001 mAssociated = true; 8002 if (stateChangeResult.BSSID != null) { 8003 mTargetRoamBSSID = (String) stateChangeResult.BSSID; 8004 } 8005 } 8006 break; 8007 case CMD_ROAM_WATCHDOG_TIMER: 8008 if (roamWatchdogCount == message.arg1) { 8009 if (DBG) log("roaming watchdog! -> disconnect"); 8010 mRoamFailCount++; 8011 handleNetworkDisconnect(); 8012 mWifiNative.disconnect(); 8013 transitionTo(mDisconnectedState); 8014 } 8015 break; 8016 case WifiMonitor.NETWORK_CONNECTION_EVENT: 8017 if (mAssociated) { 8018 if (DBG) log("roaming and Network connection established"); 8019 mLastNetworkId = message.arg1; 8020 mLastBssid = (String) message.obj; 8021 mWifiInfo.setBSSID(mLastBssid); 8022 mWifiInfo.setNetworkId(mLastNetworkId); 8023 mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection( 8024 mLastBssid, true); 8025 sendNetworkStateChangeBroadcast(mLastBssid); 8026 8027 // Successful framework roam! (probably) 8028 mWifiMetrics.endConnectionEvent( 8029 WifiMetrics.ConnectionEvent.LLF_NONE, 8030 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8031 // We used to transition to ObtainingIpState in an 8032 // attempt to do DHCPv4 RENEWs on framework roams. 8033 // DHCP can take too long to time out, and we now rely 8034 // upon IpManager's use of IpReachabilityMonitor to 8035 // confirm our current network configuration. 8036 // 8037 // mIpManager.confirmConfiguration() is called within 8038 // the handling of SupplicantState.COMPLETED. 8039 transitionTo(mConnectedState); 8040 } else { 8041 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 8042 } 8043 break; 8044 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8045 // Throw away but only if it corresponds to the network we're roaming to 8046 String bssid = (String) message.obj; 8047 if (true) { 8048 String target = ""; 8049 if (mTargetRoamBSSID != null) target = mTargetRoamBSSID; 8050 log("NETWORK_DISCONNECTION_EVENT in roaming state" 8051 + " BSSID=" + bssid 8052 + " target=" + target); 8053 } 8054 if (bssid != null && bssid.equals(mTargetRoamBSSID)) { 8055 handleNetworkDisconnect(); 8056 transitionTo(mDisconnectedState); 8057 } 8058 break; 8059 case WifiMonitor.SSID_TEMP_DISABLED: 8060 // Auth error while roaming 8061 logd("SSID_TEMP_DISABLED nid=" + Integer.toString(mLastNetworkId) 8062 + " id=" + Integer.toString(message.arg1) 8063 + " isRoaming=" + isRoaming() 8064 + " roam=" + mAutoRoaming); 8065 if (message.arg1 == mLastNetworkId) { 8066 config = getCurrentWifiConfiguration(); 8067 if (config != null) { 8068 mWifiLogger.captureBugReportData( 8069 WifiLogger.REPORT_REASON_AUTOROAM_FAILURE); 8070 mWifiConfigManager.noteRoamingFailure(config, 8071 WifiConfiguration.ROAMING_FAILURE_AUTH_FAILURE); 8072 } 8073 handleNetworkDisconnect(); 8074 transitionTo(mDisconnectingState); 8075 } 8076 return NOT_HANDLED; 8077 case CMD_START_SCAN: 8078 deferMessage(message); 8079 break; 8080 default: 8081 return NOT_HANDLED; 8082 } 8083 return HANDLED; 8084 } 8085 8086 @Override 8087 public void exit() { 8088 logd("WifiStateMachine: Leaving Roaming state"); 8089 } 8090 } 8091 8092 class ConnectedState extends State { 8093 @Override 8094 public void enter() { 8095 String address; 8096 updateDefaultRouteMacAddress(1000); 8097 if (DBG) { 8098 log("Enter ConnectedState " 8099 + " mScreenOn=" + mScreenOn 8100 + " scanperiod=" 8101 + Integer.toString( 8102 mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get()) 8103 + " useGscan=" + mHalBasedPnoDriverSupported + "/" 8104 + mWifiConfigManager.enableHalBasedPno.get() 8105 + " mHalBasedPnoEnableInDevSettings " + mHalBasedPnoEnableInDevSettings); 8106 } 8107 if (mScreenOn 8108 && getEnableAutoJoinWhenAssociated()) { 8109 if (useHalBasedAutoJoinOffload()) { 8110 startGScanConnectedModeOffload("connectedEnter"); 8111 } else { 8112 // restart scan alarm 8113 startDelayedScan(mWifiConfigManager.wifiAssociatedShortScanIntervalMilli.get(), 8114 null, null); 8115 } 8116 } 8117 registerConnected(); 8118 lastConnectAttemptTimestamp = 0; 8119 targetWificonfiguration = null; 8120 // Paranoia 8121 linkDebouncing = false; 8122 8123 // Not roaming anymore 8124 mAutoRoaming = false; 8125 8126 if (testNetworkDisconnect) { 8127 testNetworkDisconnectCounter++; 8128 logd("ConnectedState Enter start disconnect test " + 8129 testNetworkDisconnectCounter); 8130 sendMessageDelayed(obtainMessage(CMD_TEST_NETWORK_DISCONNECT, 8131 testNetworkDisconnectCounter, 0), 15000); 8132 } 8133 8134 // Reenable all networks, allow for hidden networks to be scanned 8135 mWifiConfigManager.enableAllNetworks(); 8136 8137 mLastDriverRoamAttempt = 0; 8138 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 8139 } 8140 @Override 8141 public boolean processMessage(Message message) { 8142 WifiConfiguration config = null; 8143 logStateAndMessage(message, this); 8144 8145 switch (message.what) { 8146 case CMD_RESTART_AUTOJOIN_OFFLOAD: 8147 if ( (int)message.arg2 < mRestartAutoJoinOffloadCounter ) { 8148 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 8149 return HANDLED; 8150 } 8151 /* If we are still in Disconnected state after having discovered a valid 8152 * network this means autojoin didnt managed to associate to the network, 8153 * then restart PNO so as we will try associating to it again. 8154 */ 8155 if (useHalBasedAutoJoinOffload()) { 8156 if (mGScanStartTimeMilli == 0) { 8157 // If offload is not started, then start it... 8158 startGScanConnectedModeOffload("connectedRestart"); 8159 } else { 8160 // If offload is already started, then check if we need to increase 8161 // the scan period and restart the Gscan 8162 long now = System.currentTimeMillis(); 8163 if (mGScanStartTimeMilli != 0 && now > mGScanStartTimeMilli 8164 && ((now - mGScanStartTimeMilli) 8165 > DISCONNECTED_SHORT_SCANS_DURATION_MILLI) 8166 && (mGScanPeriodMilli 8167 < mWifiConfigManager 8168 .wifiDisconnectedLongScanIntervalMilli.get())) 8169 { 8170 startConnectedGScan("Connected restart gscan"); 8171 } 8172 } 8173 } 8174 break; 8175 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION: 8176 updateAssociatedScanPermission(); 8177 break; 8178 case CMD_UNWANTED_NETWORK: 8179 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { 8180 mWifiConfigManager.handleBadNetworkDisconnectReport( 8181 mLastNetworkId, mWifiInfo); 8182 mWifiNative.disconnect(); 8183 transitionTo(mDisconnectingState); 8184 } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN || 8185 message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { 8186 Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 8187 ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN" 8188 : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED")); 8189 config = getCurrentWifiConfiguration(); 8190 if (config != null) { 8191 // Disable autojoin 8192 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) { 8193 config.validatedInternetAccess = false; 8194 // Clear last-selected status, as being last-selected also avoids 8195 // disabling auto-join. 8196 if (mWifiConfigManager.isLastSelectedConfiguration(config)) { 8197 mWifiConfigManager.setAndEnableLastSelectedConfiguration( 8198 WifiConfiguration.INVALID_NETWORK_ID); 8199 } 8200 mWifiConfigManager.updateNetworkSelectionStatus(config, 8201 WifiConfiguration.NetworkSelectionStatus 8202 .DISABLED_NO_INTERNET); 8203 } 8204 config.numNoInternetAccessReports += 1; 8205 mWifiConfigManager.writeKnownNetworkHistory(); 8206 } 8207 } 8208 return HANDLED; 8209 case CMD_NETWORK_STATUS: 8210 if (message.arg1 == NetworkAgent.VALID_NETWORK) { 8211 config = getCurrentWifiConfiguration(); 8212 if (config != null) { 8213 // re-enable autojoin 8214 config.numNoInternetAccessReports = 0; 8215 config.validatedInternetAccess = true; 8216 mWifiConfigManager.writeKnownNetworkHistory(); 8217 } 8218 } 8219 return HANDLED; 8220 case CMD_ACCEPT_UNVALIDATED: 8221 boolean accept = (message.arg1 != 0); 8222 config = getCurrentWifiConfiguration(); 8223 if (config != null) { 8224 config.noInternetAccessExpected = accept; 8225 } 8226 return HANDLED; 8227 case CMD_TEST_NETWORK_DISCONNECT: 8228 // Force a disconnect 8229 if (message.arg1 == testNetworkDisconnectCounter) { 8230 mWifiNative.disconnect(); 8231 } 8232 break; 8233 case CMD_ASSOCIATED_BSSID: 8234 // ASSOCIATING to a new BSSID while already connected, indicates 8235 // that driver is roaming 8236 mLastDriverRoamAttempt = System.currentTimeMillis(); 8237 return NOT_HANDLED; 8238 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8239 long lastRoam = 0; 8240 mWifiMetrics.endConnectionEvent( 8241 WifiMetrics.ConnectionEvent.LLF_NETWORK_DISCONNECTION, 8242 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8243 if (mLastDriverRoamAttempt != 0) { 8244 // Calculate time since last driver roam attempt 8245 lastRoam = System.currentTimeMillis() - mLastDriverRoamAttempt; 8246 mLastDriverRoamAttempt = 0; 8247 } 8248 if (unexpectedDisconnectedReason(message.arg2)) { 8249 mWifiLogger.captureBugReportData( 8250 WifiLogger.REPORT_REASON_UNEXPECTED_DISCONNECT); 8251 } 8252 config = getCurrentWifiConfiguration(); 8253 if (mScreenOn 8254 && !linkDebouncing 8255 && config != null 8256 && config.getNetworkSelectionStatus().isNetworkEnabled() 8257 && !mWifiConfigManager.isLastSelectedConfiguration(config) 8258 && (message.arg2 != 3 /* reason cannot be 3, i.e. locally generated */ 8259 || (lastRoam > 0 && lastRoam < 2000) /* unless driver is roaming */) 8260 && ((ScanResult.is24GHz(mWifiInfo.getFrequency()) 8261 && mWifiInfo.getRssi() > 8262 WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND) 8263 || (ScanResult.is5GHz(mWifiInfo.getFrequency()) 8264 && mWifiInfo.getRssi() > 8265 mWifiConfigManager.thresholdQualifiedRssi5.get()))) { 8266 // Start de-bouncing the L2 disconnection: 8267 // this L2 disconnection might be spurious. 8268 // Hence we allow 7 seconds for the state machine to try 8269 // to reconnect, go thru the 8270 // roaming cycle and enter Obtaining IP address 8271 // before signalling the disconnect to ConnectivityService and L3 8272 startScanForConfiguration(getCurrentWifiConfiguration(), false); 8273 linkDebouncing = true; 8274 8275 sendMessageDelayed(obtainMessage(CMD_DELAYED_NETWORK_DISCONNECT, 8276 0, mLastNetworkId), LINK_FLAPPING_DEBOUNCE_MSEC); 8277 if (DBG) { 8278 log("NETWORK_DISCONNECTION_EVENT in connected state" 8279 + " BSSID=" + mWifiInfo.getBSSID() 8280 + " RSSI=" + mWifiInfo.getRssi() 8281 + " freq=" + mWifiInfo.getFrequency() 8282 + " reason=" + message.arg2 8283 + " -> debounce"); 8284 } 8285 return HANDLED; 8286 } else { 8287 if (DBG) { 8288 log("NETWORK_DISCONNECTION_EVENT in connected state" 8289 + " BSSID=" + mWifiInfo.getBSSID() 8290 + " RSSI=" + mWifiInfo.getRssi() 8291 + " freq=" + mWifiInfo.getFrequency() 8292 + " was debouncing=" + linkDebouncing 8293 + " reason=" + message.arg2 8294 + " Network Selection Status=" + (config == null ? "Unavailable" 8295 : config.getNetworkSelectionStatus().getNetworkStatusString())); 8296 } 8297 } 8298 break; 8299 case CMD_AUTO_ROAM: 8300 // Clear the driver roam indication since we are attempting a framework roam 8301 mLastDriverRoamAttempt = 0; 8302 8303 /*<TODO> 2016-02-24 8304 Fix CMD_AUTO_ROAM to use the candidate (message.arg1) networkID, rather than 8305 the old networkID. 8306 The current code only handles roaming between BSSIDs on the same networkID, 8307 and will break for roams between different (but linked) networkIDs. This 8308 case occurs for DBDC roaming, and the CMD_AUTO_ROAM sent due to it will 8309 fail. 8310 */ 8311 /* Connect command coming from auto-join */ 8312 ScanResult candidate = (ScanResult)message.obj; 8313 String bssid = "any"; 8314 if (candidate != null) { 8315 bssid = candidate.BSSID; 8316 } 8317 int netId = mLastNetworkId; 8318 config = getCurrentWifiConfiguration(); 8319 8320 8321 if (config == null) { 8322 loge("AUTO_ROAM and no config, bail out..."); 8323 break; 8324 } 8325 8326 logd("CMD_AUTO_ROAM sup state " 8327 + mSupplicantStateTracker.getSupplicantStateName() 8328 + " my state " + getCurrentState().getName() 8329 + " nid=" + Integer.toString(netId) 8330 + " config " + config.configKey() 8331 + " roam=" + Integer.toString(message.arg2) 8332 + " to " + bssid 8333 + " targetRoamBSSID " + mTargetRoamBSSID); 8334 8335 setTargetBssid(config, bssid); 8336 mTargetNetworkId = netId; 8337 mWifiMetrics.startConnectionEvent(config, 8338 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 8339 /* <TODO> 2016-02-24 8340 Detect DBDC (2.4 <-> 5Ghz, same AP) roaming events, once CMD_AUTO_ROAM 8341 has been fixed to handle them correctly: 8342 mWifiMetrics.setConnectionEventRoamType( 8343 WifiMetricsProto.ConnectionEvent.ROAM_DBDC); 8344 Handy statements: 8345 ABSSID.regionMatches(true, 0, BBSSID, 0, 16) //BSSID matching 8346 currentConfig.isLinked(config) //check the configs are linked 8347 */ 8348 if (deferForUserInput(message, netId, false)) { 8349 mWifiMetrics.endConnectionEvent( 8350 WifiMetrics.ConnectionEvent.LLF_CONNECT_NETWORK_FAILED, 8351 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8352 break; 8353 } else if (mWifiConfigManager.getWifiConfiguration(netId).userApproved == 8354 WifiConfiguration.USER_BANNED) { 8355 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 8356 WifiManager.NOT_AUTHORIZED); 8357 mWifiMetrics.endConnectionEvent( 8358 WifiMetrics.ConnectionEvent.LLF_CONNECT_NETWORK_FAILED, 8359 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8360 break; 8361 } 8362 8363 boolean ret = false; 8364 if (mLastNetworkId != netId) { 8365 if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false, 8366 WifiConfiguration.UNKNOWN_UID) && mWifiNative.reconnect()) { 8367 ret = true; 8368 } 8369 } else { 8370 ret = mWifiNative.reassociate(); 8371 } 8372 if (ret) { 8373 lastConnectAttemptTimestamp = System.currentTimeMillis(); 8374 targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId); 8375 8376 // replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 8377 mAutoRoaming = true; 8378 transitionTo(mRoamingState); 8379 8380 } else { 8381 loge("Failed to connect config: " + config + " netId: " + netId); 8382 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 8383 WifiManager.ERROR); 8384 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 8385 mWifiMetrics.endConnectionEvent( 8386 WifiMetrics.ConnectionEvent.LLF_CONNECT_NETWORK_FAILED, 8387 WifiMetricsProto.ConnectionEvent.HLF_NONE); 8388 break; 8389 } 8390 break; 8391 case CMD_START_IP_PACKET_OFFLOAD: { 8392 int slot = message.arg1; 8393 int intervalSeconds = message.arg2; 8394 KeepalivePacketData pkt = (KeepalivePacketData) message.obj; 8395 byte[] dstMac; 8396 try { 8397 InetAddress gateway = RouteInfo.selectBestRoute( 8398 mLinkProperties.getRoutes(), pkt.dstAddress).getGateway(); 8399 String dstMacStr = macAddressFromRoute(gateway.getHostAddress()); 8400 dstMac = macAddressFromString(dstMacStr); 8401 } catch (NullPointerException|IllegalArgumentException e) { 8402 loge("Can't find MAC address for next hop to " + pkt.dstAddress); 8403 mNetworkAgent.onPacketKeepaliveEvent(slot, 8404 ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 8405 break; 8406 } 8407 pkt.dstMac = dstMac; 8408 int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds); 8409 mNetworkAgent.onPacketKeepaliveEvent(slot, result); 8410 break; 8411 } 8412 default: 8413 return NOT_HANDLED; 8414 } 8415 return HANDLED; 8416 } 8417 8418 @Override 8419 public void exit() { 8420 logd("WifiStateMachine: Leaving Connected state"); 8421 setScanAlarm(false); 8422 mLastDriverRoamAttempt = 0; 8423 mWhiteListedSsids = null; 8424 } 8425 } 8426 8427 class DisconnectingState extends State { 8428 8429 @Override 8430 public void enter() { 8431 8432 if (DBG) { 8433 logd(" Enter DisconnectingState State scan interval " 8434 + mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get() 8435 + " mLegacyPnoEnabled= " + mLegacyPnoEnabled 8436 + " screenOn=" + mScreenOn); 8437 } 8438 8439 // Make sure we disconnect: we enter this state prior to connecting to a new 8440 // network, waiting for either a DISCONNECT event or a SUPPLICANT_STATE_CHANGE 8441 // event which in this case will be indicating that supplicant started to associate. 8442 // In some cases supplicant doesn't ignore the connect requests (it might not 8443 // find the target SSID in its cache), 8444 // Therefore we end up stuck that state, hence the need for the watchdog. 8445 disconnectingWatchdogCount++; 8446 logd("Start Disconnecting Watchdog " + disconnectingWatchdogCount); 8447 sendMessageDelayed(obtainMessage(CMD_DISCONNECTING_WATCHDOG_TIMER, 8448 disconnectingWatchdogCount, 0), DISCONNECTING_GUARD_TIMER_MSEC); 8449 } 8450 8451 @Override 8452 public boolean processMessage(Message message) { 8453 logStateAndMessage(message, this); 8454 switch (message.what) { 8455 case CMD_SET_OPERATIONAL_MODE: 8456 if (message.arg1 != CONNECT_MODE) { 8457 deferMessage(message); 8458 } 8459 break; 8460 case CMD_START_SCAN: 8461 deferMessage(message); 8462 return HANDLED; 8463 case CMD_DISCONNECTING_WATCHDOG_TIMER: 8464 if (disconnectingWatchdogCount == message.arg1) { 8465 if (DBG) log("disconnecting watchdog! -> disconnect"); 8466 handleNetworkDisconnect(); 8467 transitionTo(mDisconnectedState); 8468 } 8469 break; 8470 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 8471 /** 8472 * If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT 8473 * we have missed the network disconnection, transition to mDisconnectedState 8474 * and handle the rest of the events there 8475 */ 8476 deferMessage(message); 8477 handleNetworkDisconnect(); 8478 transitionTo(mDisconnectedState); 8479 break; 8480 default: 8481 return NOT_HANDLED; 8482 } 8483 return HANDLED; 8484 } 8485 } 8486 8487 class DisconnectedState extends State { 8488 @Override 8489 public void enter() { 8490 // We dont scan frequently if this is a temporary disconnect 8491 // due to p2p 8492 if (mTemporarilyDisconnectWifi) { 8493 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 8494 return; 8495 } 8496 8497 if (DBG) { 8498 logd(" Enter DisconnectedState scan interval " 8499 + mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get() 8500 + " mLegacyPnoEnabled= " + mLegacyPnoEnabled 8501 + " screenOn=" + mScreenOn 8502 + " useGscan=" + mHalBasedPnoDriverSupported + "/" 8503 + mWifiConfigManager.enableHalBasedPno.get()); 8504 } 8505 8506 /** clear the roaming state, if we were roaming, we failed */ 8507 mAutoRoaming = false; 8508 8509 if (useHalBasedAutoJoinOffload()) { 8510 startGScanDisconnectedModeOffload("disconnectedEnter"); 8511 } else { 8512 if (mScreenOn) { 8513 /** 8514 * screen lit and => start scan immediately 8515 */ 8516 startScan(UNKNOWN_SCAN_SOURCE, 0, null, null); 8517 } else { 8518 /** 8519 * screen dark and PNO supported => scan alarm disabled 8520 */ 8521 if (mBackgroundScanSupported) { 8522 /* If a regular scan result is pending, do not initiate background 8523 * scan until the scan results are returned. This is needed because 8524 * initiating a background scan will cancel the regular scan and 8525 * scan results will not be returned until background scanning is 8526 * cleared 8527 */ 8528 if (!mIsScanOngoing) { 8529 enableBackgroundScan(true); 8530 } 8531 } else { 8532 setScanAlarm(true); 8533 } 8534 } 8535 } 8536 8537 /** 8538 * If we have no networks saved, the supplicant stops doing the periodic scan. 8539 * The scans are useful to notify the user of the presence of an open network. 8540 * Note that these are not wake up scans. 8541 */ 8542 if (mNoNetworksPeriodicScan != 0 && !mP2pConnected.get() 8543 && mWifiConfigManager.getConfiguredNetworks().size() == 0) { 8544 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8545 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8546 } 8547 8548 mDisconnectedTimeStamp = System.currentTimeMillis(); 8549 mDisconnectedPnoAlarmCount = 0; 8550 } 8551 @Override 8552 public boolean processMessage(Message message) { 8553 boolean ret = HANDLED; 8554 8555 logStateAndMessage(message, this); 8556 8557 switch (message.what) { 8558 case CMD_NO_NETWORKS_PERIODIC_SCAN: 8559 if (mP2pConnected.get()) break; 8560 if (mNoNetworksPeriodicScan != 0 && message.arg1 == mPeriodicScanToken && 8561 mWifiConfigManager.getConfiguredNetworks().size() == 0) { 8562 startScan(UNKNOWN_SCAN_SOURCE, -1, null, null); 8563 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8564 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8565 } 8566 break; 8567 case WifiManager.FORGET_NETWORK: 8568 case CMD_REMOVE_NETWORK: 8569 case CMD_REMOVE_APP_CONFIGURATIONS: 8570 case CMD_REMOVE_USER_CONFIGURATIONS: 8571 // Set up a delayed message here. After the forget/remove is handled 8572 // the handled delayed message will determine if there is a need to 8573 // scan and continue 8574 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8575 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8576 ret = NOT_HANDLED; 8577 break; 8578 case CMD_SET_OPERATIONAL_MODE: 8579 if (message.arg1 != CONNECT_MODE) { 8580 mOperationalMode = message.arg1; 8581 mWifiConfigManager.disableAllNetworksNative(); 8582 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 8583 mWifiP2pChannel.sendMessage(CMD_DISABLE_P2P_REQ); 8584 setWifiState(WIFI_STATE_DISABLED); 8585 } 8586 transitionTo(mScanModeState); 8587 } 8588 mWifiConfigManager. 8589 setAndEnableLastSelectedConfiguration( 8590 WifiConfiguration.INVALID_NETWORK_ID); 8591 break; 8592 /* Ignore network disconnect */ 8593 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8594 // Interpret this as an L2 connection failure 8595 break; 8596 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 8597 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 8598 if (DBG) { 8599 logd("SUPPLICANT_STATE_CHANGE_EVENT state=" + stateChangeResult.state + 8600 " -> state= " + WifiInfo.getDetailedStateOf(stateChangeResult.state) 8601 + " debouncing=" + linkDebouncing); 8602 } 8603 setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state)); 8604 /* ConnectModeState does the rest of the handling */ 8605 ret = NOT_HANDLED; 8606 break; 8607 case CMD_START_SCAN: 8608 if (!checkOrDeferScanAllowed(message)) { 8609 // The scan request was rescheduled 8610 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 8611 return HANDLED; 8612 } 8613 if (message.arg1 == SCAN_ALARM_SOURCE) { 8614 // Check if the CMD_START_SCAN message is obsolete (and thus if it should 8615 // not be processed) and restart the scan 8616 int period = 8617 mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get(); 8618 if (mP2pConnected.get()) { 8619 period = (int) mFacade.getLongSetting(mContext, 8620 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, 8621 period); 8622 } 8623 if (!checkAndRestartDelayedScan(message.arg2, 8624 true, period, null, null)) { 8625 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 8626 logd("Disconnected CMD_START_SCAN source " 8627 + message.arg1 8628 + " " + message.arg2 + ", " + mDelayedScanCounter 8629 + " -> obsolete"); 8630 return HANDLED; 8631 } 8632 /* Disable background scan temporarily during a regular scan */ 8633 enableBackgroundScan(false); 8634 handleScanRequest(message); 8635 ret = HANDLED; 8636 } else { 8637 8638 /* 8639 * The SCAN request is not handled in this state and 8640 * would eventually might/will get handled in the 8641 * parent's state. The PNO, if already enabled had to 8642 * get disabled before the SCAN trigger. Hence, stop 8643 * the PNO if already enabled in this state, though the 8644 * SCAN request is not handled(PNO disable before the 8645 * SCAN trigger in any other state is not the right 8646 * place to issue). 8647 */ 8648 8649 enableBackgroundScan(false); 8650 ret = NOT_HANDLED; 8651 } 8652 break; 8653 case CMD_RESTART_AUTOJOIN_OFFLOAD: 8654 if ( (int)message.arg2 < mRestartAutoJoinOffloadCounter ) { 8655 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE; 8656 return HANDLED; 8657 } 8658 /* If we are still in Disconnected state after having discovered a valid 8659 * network this means autojoin didnt managed to associate to the network, 8660 * then restart PNO so as we will try associating to it again. 8661 */ 8662 if (useHalBasedAutoJoinOffload()) { 8663 if (mGScanStartTimeMilli == 0) { 8664 // If offload is not started, then start it... 8665 startGScanDisconnectedModeOffload("disconnectedRestart"); 8666 } else { 8667 // If offload is already started, then check if we need to increase 8668 // the scan period and restart the Gscan 8669 long now = System.currentTimeMillis(); 8670 if (mGScanStartTimeMilli != 0 && now > mGScanStartTimeMilli 8671 && ((now - mGScanStartTimeMilli) 8672 > DISCONNECTED_SHORT_SCANS_DURATION_MILLI) 8673 && (mGScanPeriodMilli 8674 < mWifiConfigManager 8675 .wifiDisconnectedLongScanIntervalMilli.get())) 8676 { 8677 startDisconnectedGScan("disconnected restart gscan"); 8678 } 8679 } 8680 } else { 8681 // If we are still disconnected for a short while after having found a 8682 // network thru PNO, then something went wrong, and for some reason we 8683 // couldn't join this network. 8684 // It might be due to a SW bug in supplicant or the wifi stack, or an 8685 // interoperability issue, or we try to join a bad bss and failed 8686 // In that case we want to restart pno so as to make sure that we will 8687 // attempt again to join that network. 8688 if (!mScreenOn && !mIsScanOngoing && mBackgroundScanSupported) { 8689 enableBackgroundScan(false); 8690 enableBackgroundScan(true); 8691 } 8692 return HANDLED; 8693 } 8694 break; 8695 case WifiMonitor.SCAN_RESULTS_EVENT: 8696 case WifiMonitor.SCAN_FAILED_EVENT: 8697 /* Re-enable background scan when a pending scan result is received */ 8698 if (!mScreenOn && mIsScanOngoing 8699 && mBackgroundScanSupported 8700 && !useHalBasedAutoJoinOffload()) { 8701 enableBackgroundScan(true); 8702 } else if (!mScreenOn 8703 && !mIsScanOngoing 8704 && mBackgroundScanSupported 8705 && !useHalBasedAutoJoinOffload()) { 8706 // We receive scan results from legacy PNO, hence restart the PNO alarm 8707 int delay; 8708 if (mDisconnectedPnoAlarmCount < 1) { 8709 delay = 30 * 1000; 8710 } else if (mDisconnectedPnoAlarmCount < 3) { 8711 delay = 60 * 1000; 8712 } else { 8713 delay = 360 * 1000; 8714 } 8715 mDisconnectedPnoAlarmCount++; 8716 if (DBG) { 8717 logd("Starting PNO alarm " + delay); 8718 } 8719 mAlarmManager.set(AlarmManager.RTC_WAKEUP, 8720 System.currentTimeMillis() + delay, 8721 mPnoIntent); 8722 } 8723 /* Handled in parent state */ 8724 ret = NOT_HANDLED; 8725 break; 8726 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 8727 NetworkInfo info = (NetworkInfo) message.obj; 8728 mP2pConnected.set(info.isConnected()); 8729 if (mP2pConnected.get()) { 8730 int defaultInterval = mContext.getResources().getInteger( 8731 R.integer.config_wifi_scan_interval_p2p_connected); 8732 long scanIntervalMs = mFacade.getLongSetting(mContext, 8733 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, 8734 defaultInterval); 8735 mWifiNative.setScanInterval((int) scanIntervalMs/1000); 8736 } else if (mWifiConfigManager.getConfiguredNetworks().size() == 0) { 8737 if (DBG) log("Turn on scanning after p2p disconnected"); 8738 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 8739 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 8740 } else { 8741 // If P2P is not connected and there are saved networks, then restart 8742 // scanning at the normal period. This is necessary because scanning might 8743 // have been disabled altogether if WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS 8744 // was set to zero. 8745 if (useHalBasedAutoJoinOffload()) { 8746 startGScanDisconnectedModeOffload("p2pRestart"); 8747 } else { 8748 startDelayedScan( 8749 mWifiConfigManager.wifiDisconnectedShortScanIntervalMilli.get(), 8750 null, null); 8751 } 8752 } 8753 break; 8754 case CMD_RECONNECT: 8755 case CMD_REASSOCIATE: 8756 if (mTemporarilyDisconnectWifi) { 8757 // Drop a third party reconnect/reassociate if STA is 8758 // temporarily disconnected for p2p 8759 break; 8760 } else { 8761 // ConnectModeState handles it 8762 ret = NOT_HANDLED; 8763 } 8764 break; 8765 case CMD_SCREEN_STATE_CHANGED: 8766 handleScreenStateChanged(message.arg1 != 0); 8767 break; 8768 default: 8769 ret = NOT_HANDLED; 8770 } 8771 return ret; 8772 } 8773 8774 @Override 8775 public void exit() { 8776 mDisconnectedPnoAlarmCount = 0; 8777 /* No need for a background scan upon exit from a disconnected state */ 8778 enableBackgroundScan(false); 8779 setScanAlarm(false); 8780 mAlarmManager.cancel(mPnoIntent); 8781 } 8782 } 8783 8784 class WpsRunningState extends State { 8785 // Tracks the source to provide a reply 8786 private Message mSourceMessage; 8787 @Override 8788 public void enter() { 8789 mSourceMessage = Message.obtain(getCurrentMessage()); 8790 } 8791 @Override 8792 public boolean processMessage(Message message) { 8793 logStateAndMessage(message, this); 8794 8795 switch (message.what) { 8796 case WifiMonitor.WPS_SUCCESS_EVENT: 8797 // Ignore intermediate success, wait for full connection 8798 break; 8799 case WifiMonitor.NETWORK_CONNECTION_EVENT: 8800 replyToMessage(mSourceMessage, WifiManager.WPS_COMPLETED); 8801 mSourceMessage.recycle(); 8802 mSourceMessage = null; 8803 deferMessage(message); 8804 transitionTo(mDisconnectedState); 8805 break; 8806 case WifiMonitor.WPS_OVERLAP_EVENT: 8807 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 8808 WifiManager.WPS_OVERLAP_ERROR); 8809 mSourceMessage.recycle(); 8810 mSourceMessage = null; 8811 transitionTo(mDisconnectedState); 8812 break; 8813 case WifiMonitor.WPS_FAIL_EVENT: 8814 // Arg1 has the reason for the failure 8815 if ((message.arg1 != WifiManager.ERROR) || (message.arg2 != 0)) { 8816 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1); 8817 mSourceMessage.recycle(); 8818 mSourceMessage = null; 8819 transitionTo(mDisconnectedState); 8820 } else { 8821 if (DBG) log("Ignore unspecified fail event during WPS connection"); 8822 } 8823 break; 8824 case WifiMonitor.WPS_TIMEOUT_EVENT: 8825 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 8826 WifiManager.WPS_TIMED_OUT); 8827 mSourceMessage.recycle(); 8828 mSourceMessage = null; 8829 transitionTo(mDisconnectedState); 8830 break; 8831 case WifiManager.START_WPS: 8832 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS); 8833 break; 8834 case WifiManager.CANCEL_WPS: 8835 if (mWifiNative.cancelWps()) { 8836 replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED); 8837 } else { 8838 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR); 8839 } 8840 transitionTo(mDisconnectedState); 8841 break; 8842 /** 8843 * Defer all commands that can cause connections to a different network 8844 * or put the state machine out of connect mode 8845 */ 8846 case CMD_STOP_DRIVER: 8847 case CMD_SET_OPERATIONAL_MODE: 8848 case WifiManager.CONNECT_NETWORK: 8849 case CMD_ENABLE_NETWORK: 8850 case CMD_RECONNECT: 8851 case CMD_REASSOCIATE: 8852 case CMD_ENABLE_ALL_NETWORKS: 8853 deferMessage(message); 8854 break; 8855 case CMD_AUTO_CONNECT: 8856 case CMD_AUTO_ROAM: 8857 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 8858 return HANDLED; 8859 case CMD_START_SCAN: 8860 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 8861 return HANDLED; 8862 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 8863 if (DBG) log("Network connection lost"); 8864 handleNetworkDisconnect(); 8865 break; 8866 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 8867 if (DBG) log("Ignore Assoc reject event during WPS Connection"); 8868 break; 8869 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 8870 // Disregard auth failure events during WPS connection. The 8871 // EAP sequence is retried several times, and there might be 8872 // failures (especially for wps pin). We will get a WPS_XXX 8873 // event at the end of the sequence anyway. 8874 if (DBG) log("Ignore auth failure during WPS connection"); 8875 break; 8876 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 8877 // Throw away supplicant state changes when WPS is running. 8878 // We will start getting supplicant state changes once we get 8879 // a WPS success or failure 8880 break; 8881 default: 8882 return NOT_HANDLED; 8883 } 8884 return HANDLED; 8885 } 8886 8887 @Override 8888 public void exit() { 8889 mWifiConfigManager.enableAllNetworks(); 8890 mWifiConfigManager.loadConfiguredNetworks(); 8891 } 8892 } 8893 8894 class SoftApState extends State { 8895 private SoftApManager mSoftApManager; 8896 8897 private class SoftApListener implements SoftApManager.Listener { 8898 @Override 8899 public void onStateChanged(int state, int reason) { 8900 if (state == WIFI_AP_STATE_DISABLED) { 8901 sendMessage(CMD_AP_STOPPED); 8902 } else if (state == WIFI_AP_STATE_FAILED) { 8903 sendMessage(CMD_START_AP_FAILURE); 8904 } 8905 8906 setWifiApState(state, reason); 8907 } 8908 } 8909 8910 @Override 8911 public void enter() { 8912 final Message message = getCurrentMessage(); 8913 if (message.what == CMD_START_AP) { 8914 WifiConfiguration config = (WifiConfiguration) message.obj; 8915 8916 if (config == null) { 8917 /** 8918 * Configuration not provided in the command, fallback to use the current 8919 * configuration. 8920 */ 8921 config = mWifiApConfigStore.getApConfiguration(); 8922 } else { 8923 /* Update AP configuration. */ 8924 mWifiApConfigStore.setApConfiguration(config); 8925 } 8926 8927 checkAndSetConnectivityInstance(); 8928 mSoftApManager = mFacade.makeSoftApManager( 8929 mContext, getHandler().getLooper(), mWifiNative, mNwService, 8930 mCm, getCurrentCountryCode(), 8931 mWifiApConfigStore.getAllowed2GChannel(), 8932 new SoftApListener()); 8933 mSoftApManager.start(config); 8934 } else { 8935 throw new RuntimeException("Illegal transition to SoftApState: " + message); 8936 } 8937 } 8938 8939 @Override 8940 public void exit() { 8941 mSoftApManager = null; 8942 } 8943 8944 @Override 8945 public boolean processMessage(Message message) { 8946 logStateAndMessage(message, this); 8947 8948 switch(message.what) { 8949 case CMD_START_AP: 8950 /* Ignore start command when it is starting/started. */ 8951 break; 8952 case CMD_STOP_AP: 8953 mSoftApManager.stop(); 8954 break; 8955 case CMD_START_AP_FAILURE: 8956 transitionTo(mInitialState); 8957 break; 8958 case CMD_AP_STOPPED: 8959 transitionTo(mInitialState); 8960 break; 8961 default: 8962 return NOT_HANDLED; 8963 } 8964 return HANDLED; 8965 } 8966 } 8967 8968 /** 8969 * State machine initiated requests can have replyTo set to null indicating 8970 * there are no recepients, we ignore those reply actions. 8971 */ 8972 private void replyToMessage(Message msg, int what) { 8973 if (msg.replyTo == null) return; 8974 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 8975 mReplyChannel.replyToMessage(msg, dstMsg); 8976 } 8977 8978 private void replyToMessage(Message msg, int what, int arg1) { 8979 if (msg.replyTo == null) return; 8980 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 8981 dstMsg.arg1 = arg1; 8982 mReplyChannel.replyToMessage(msg, dstMsg); 8983 } 8984 8985 private void replyToMessage(Message msg, int what, Object obj) { 8986 if (msg.replyTo == null) return; 8987 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 8988 dstMsg.obj = obj; 8989 mReplyChannel.replyToMessage(msg, dstMsg); 8990 } 8991 8992 /** 8993 * arg2 on the source message has a unique id that needs to be retained in replies 8994 * to match the request 8995 * <p>see WifiManager for details 8996 */ 8997 private Message obtainMessageWithWhatAndArg2(Message srcMsg, int what) { 8998 Message msg = Message.obtain(); 8999 msg.what = what; 9000 msg.arg2 = srcMsg.arg2; 9001 return msg; 9002 } 9003 9004 /** 9005 * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT 9006 * @param msg Must have a WifiConfiguration obj to succeed 9007 */ 9008 private void broadcastWifiCredentialChanged(int wifiCredentialEventType, 9009 WifiConfiguration config) { 9010 if (config != null && config.preSharedKey != null) { 9011 Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); 9012 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); 9013 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, 9014 wifiCredentialEventType); 9015 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT, 9016 android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE); 9017 } 9018 } 9019 9020 private static int parseHex(char ch) { 9021 if ('0' <= ch && ch <= '9') { 9022 return ch - '0'; 9023 } else if ('a' <= ch && ch <= 'f') { 9024 return ch - 'a' + 10; 9025 } else if ('A' <= ch && ch <= 'F') { 9026 return ch - 'A' + 10; 9027 } else { 9028 throw new NumberFormatException("" + ch + " is not a valid hex digit"); 9029 } 9030 } 9031 9032 private byte[] parseHex(String hex) { 9033 /* This only works for good input; don't throw bad data at it */ 9034 if (hex == null) { 9035 return new byte[0]; 9036 } 9037 9038 if (hex.length() % 2 != 0) { 9039 throw new NumberFormatException(hex + " is not a valid hex string"); 9040 } 9041 9042 byte[] result = new byte[(hex.length())/2 + 1]; 9043 result[0] = (byte) ((hex.length())/2); 9044 for (int i = 0, j = 1; i < hex.length(); i += 2, j++) { 9045 int val = parseHex(hex.charAt(i)) * 16 + parseHex(hex.charAt(i+1)); 9046 byte b = (byte) (val & 0xFF); 9047 result[j] = b; 9048 } 9049 9050 return result; 9051 } 9052 9053 private static String makeHex(byte[] bytes) { 9054 StringBuilder sb = new StringBuilder(); 9055 for (byte b : bytes) { 9056 sb.append(String.format("%02x", b)); 9057 } 9058 return sb.toString(); 9059 } 9060 9061 private static String makeHex(byte[] bytes, int from, int len) { 9062 StringBuilder sb = new StringBuilder(); 9063 for (int i = 0; i < len; i++) { 9064 sb.append(String.format("%02x", bytes[from+i])); 9065 } 9066 return sb.toString(); 9067 } 9068 9069 private static byte[] concat(byte[] array1, byte[] array2, byte[] array3) { 9070 9071 int len = array1.length + array2.length + array3.length; 9072 9073 if (array1.length != 0) { 9074 len++; /* add another byte for size */ 9075 } 9076 9077 if (array2.length != 0) { 9078 len++; /* add another byte for size */ 9079 } 9080 9081 if (array3.length != 0) { 9082 len++; /* add another byte for size */ 9083 } 9084 9085 byte[] result = new byte[len]; 9086 9087 int index = 0; 9088 if (array1.length != 0) { 9089 result[index] = (byte) (array1.length & 0xFF); 9090 index++; 9091 for (byte b : array1) { 9092 result[index] = b; 9093 index++; 9094 } 9095 } 9096 9097 if (array2.length != 0) { 9098 result[index] = (byte) (array2.length & 0xFF); 9099 index++; 9100 for (byte b : array2) { 9101 result[index] = b; 9102 index++; 9103 } 9104 } 9105 9106 if (array3.length != 0) { 9107 result[index] = (byte) (array3.length & 0xFF); 9108 index++; 9109 for (byte b : array3) { 9110 result[index] = b; 9111 index++; 9112 } 9113 } 9114 return result; 9115 } 9116 9117 private static byte[] concatHex(byte[] array1, byte[] array2) { 9118 9119 int len = array1.length + array2.length; 9120 9121 byte[] result = new byte[len]; 9122 9123 int index = 0; 9124 if (array1.length != 0) { 9125 for (byte b : array1) { 9126 result[index] = b; 9127 index++; 9128 } 9129 } 9130 9131 if (array2.length != 0) { 9132 for (byte b : array2) { 9133 result[index] = b; 9134 index++; 9135 } 9136 } 9137 9138 return result; 9139 } 9140 9141 String getGsmSimAuthResponse(String[] requestData, TelephonyManager tm) { 9142 StringBuilder sb = new StringBuilder(); 9143 for (String challenge : requestData) { 9144 if (challenge == null || challenge.isEmpty()) { 9145 continue; 9146 } 9147 logd("RAND = " + challenge); 9148 9149 byte[] rand = null; 9150 try { 9151 rand = parseHex(challenge); 9152 } catch (NumberFormatException e) { 9153 loge("malformed challenge"); 9154 continue; 9155 } 9156 9157 String base64Challenge = android.util.Base64.encodeToString( 9158 rand, android.util.Base64.NO_WRAP); 9159 /* 9160 * First, try with appType = 2 => USIM according to 9161 * com.android.internal.telephony.PhoneConstants#APPTYPE_xxx 9162 */ 9163 int appType = 2; 9164 String tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge); 9165 if (tmResponse == null) { 9166 /* Then, in case of failure, issue may be due to sim type, retry as a simple sim 9167 * appType = 1 => SIM 9168 */ 9169 appType = 1; 9170 tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge); 9171 } 9172 logv("Raw Response - " + tmResponse); 9173 9174 if (tmResponse == null || tmResponse.length() <= 4) { 9175 loge("bad response - " + tmResponse); 9176 return null; 9177 } 9178 9179 byte[] result = android.util.Base64.decode(tmResponse, android.util.Base64.DEFAULT); 9180 logv("Hex Response -" + makeHex(result)); 9181 int sres_len = result[0]; 9182 if (sres_len >= result.length) { 9183 loge("malfomed response - " + tmResponse); 9184 return null; 9185 } 9186 String sres = makeHex(result, 1, sres_len); 9187 int kc_offset = 1 + sres_len; 9188 if (kc_offset >= result.length) { 9189 loge("malfomed response - " + tmResponse); 9190 return null; 9191 } 9192 int kc_len = result[kc_offset]; 9193 if (kc_offset + kc_len > result.length) { 9194 loge("malfomed response - " + tmResponse); 9195 return null; 9196 } 9197 String kc = makeHex(result, 1 + kc_offset, kc_len); 9198 sb.append(":" + kc + ":" + sres); 9199 logv("kc:" + kc + " sres:" + sres); 9200 } 9201 9202 return sb.toString(); 9203 } 9204 9205 void handleGsmAuthRequest(SimAuthRequestData requestData) { 9206 if (targetWificonfiguration == null 9207 || targetWificonfiguration.networkId == requestData.networkId) { 9208 logd("id matches targetWifiConfiguration"); 9209 } else { 9210 logd("id does not match targetWifiConfiguration"); 9211 return; 9212 } 9213 9214 TelephonyManager tm = (TelephonyManager) 9215 mContext.getSystemService(Context.TELEPHONY_SERVICE); 9216 9217 if (tm == null) { 9218 loge("could not get telephony manager"); 9219 mWifiNative.simAuthFailedResponse(requestData.networkId); 9220 return; 9221 } 9222 9223 String response = getGsmSimAuthResponse(requestData.data, tm); 9224 if (response == null) { 9225 mWifiNative.simAuthFailedResponse(requestData.networkId); 9226 } else { 9227 logv("Supplicant Response -" + response); 9228 mWifiNative.simAuthResponse(requestData.networkId, "GSM-AUTH", response); 9229 } 9230 } 9231 9232 void handle3GAuthRequest(SimAuthRequestData requestData) { 9233 StringBuilder sb = new StringBuilder(); 9234 byte[] rand = null; 9235 byte[] authn = null; 9236 String res_type = "UMTS-AUTH"; 9237 9238 if (targetWificonfiguration == null 9239 || targetWificonfiguration.networkId == requestData.networkId) { 9240 logd("id matches targetWifiConfiguration"); 9241 } else { 9242 logd("id does not match targetWifiConfiguration"); 9243 return; 9244 } 9245 if (requestData.data.length == 2) { 9246 try { 9247 rand = parseHex(requestData.data[0]); 9248 authn = parseHex(requestData.data[1]); 9249 } catch (NumberFormatException e) { 9250 loge("malformed challenge"); 9251 } 9252 } else { 9253 loge("malformed challenge"); 9254 } 9255 9256 String tmResponse = ""; 9257 if (rand != null && authn != null) { 9258 String base64Challenge = android.util.Base64.encodeToString( 9259 concatHex(rand,authn), android.util.Base64.NO_WRAP); 9260 9261 TelephonyManager tm = (TelephonyManager) 9262 mContext.getSystemService(Context.TELEPHONY_SERVICE); 9263 if (tm != null) { 9264 int appType = 2; // 2 => USIM 9265 tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge); 9266 logv("Raw Response - " + tmResponse); 9267 } else { 9268 loge("could not get telephony manager"); 9269 } 9270 } 9271 9272 boolean good_response = false; 9273 if (tmResponse != null && tmResponse.length() > 4) { 9274 byte[] result = android.util.Base64.decode(tmResponse, 9275 android.util.Base64.DEFAULT); 9276 loge("Hex Response - " + makeHex(result)); 9277 byte tag = result[0]; 9278 if (tag == (byte) 0xdb) { 9279 logv("successful 3G authentication "); 9280 int res_len = result[1]; 9281 String res = makeHex(result, 2, res_len); 9282 int ck_len = result[res_len + 2]; 9283 String ck = makeHex(result, res_len + 3, ck_len); 9284 int ik_len = result[res_len + ck_len + 3]; 9285 String ik = makeHex(result, res_len + ck_len + 4, ik_len); 9286 sb.append(":" + ik + ":" + ck + ":" + res); 9287 logv("ik:" + ik + "ck:" + ck + " res:" + res); 9288 good_response = true; 9289 } else if (tag == (byte) 0xdc) { 9290 loge("synchronisation failure"); 9291 int auts_len = result[1]; 9292 String auts = makeHex(result, 2, auts_len); 9293 res_type = "UMTS-AUTS"; 9294 sb.append(":" + auts); 9295 logv("auts:" + auts); 9296 good_response = true; 9297 } else { 9298 loge("bad response - unknown tag = " + tag); 9299 } 9300 } else { 9301 loge("bad response - " + tmResponse); 9302 } 9303 9304 if (good_response) { 9305 String response = sb.toString(); 9306 logv("Supplicant Response -" + response); 9307 mWifiNative.simAuthResponse(requestData.networkId, res_type, response); 9308 } else { 9309 mWifiNative.umtsAuthFailedResponse(requestData.networkId); 9310 } 9311 } 9312 9313 public int getCurrentUserId() { 9314 return mCurrentUserId; 9315 } 9316 9317 private boolean isCurrentUserProfile(int userId) { 9318 if (userId == mCurrentUserId) { 9319 return true; 9320 } 9321 final UserInfo parent = mUserManager.getProfileParent(userId); 9322 return parent != null && parent.id == mCurrentUserId; 9323 } 9324 9325 public List<UserInfo> getCurrentUserProfiles() { 9326 return mUserManager.getProfiles(mCurrentUserId); 9327 } 9328 9329 /** 9330 * @param reason reason code from supplicant on network disconnected event 9331 * @return true if this is a suspicious disconnect 9332 */ 9333 static boolean unexpectedDisconnectedReason(int reason) { 9334 return reason == 2 // PREV_AUTH_NOT_VALID 9335 || reason == 6 // CLASS2_FRAME_FROM_NONAUTH_STA 9336 || reason == 7 // FRAME_FROM_NONASSOC_STA 9337 || reason == 8 // STA_HAS_LEFT 9338 || reason == 9 // STA_REQ_ASSOC_WITHOUT_AUTH 9339 || reason == 14 // MICHAEL_MIC_FAILURE 9340 || reason == 15 // 4WAY_HANDSHAKE_TIMEOUT 9341 || reason == 16 // GROUP_KEY_UPDATE_TIMEOUT 9342 || reason == 18 // GROUP_CIPHER_NOT_VALID 9343 || reason == 19 // PAIRWISE_CIPHER_NOT_VALID 9344 || reason == 23 // IEEE_802_1X_AUTH_FAILED 9345 || reason == 34; // DISASSOC_LOW_ACK 9346 } 9347 9348 /** 9349 * Update WifiMetrics before dumping 9350 */ 9351 void updateWifiMetrics() { 9352 int numSavedNetworks = mWifiConfigManager.getConfiguredNetworksSize(); 9353 int numOpenNetworks = 0; 9354 int numPersonalNetworks = 0; 9355 int numEnterpriseNetworks = 0; 9356 int numNetworksAddedByUser = 0; 9357 int numNetworksAddedByApps = 0; 9358 for (WifiConfiguration config : mWifiConfigManager.getConfiguredNetworks()) { 9359 if (config.allowedAuthAlgorithms.get(WifiConfiguration.AuthAlgorithm.OPEN)) { 9360 numOpenNetworks++; 9361 } else if (config.isEnterprise()) { 9362 numEnterpriseNetworks++; 9363 } else { 9364 numPersonalNetworks++; 9365 } 9366 if (config.selfAdded) { 9367 numNetworksAddedByUser++; 9368 } else { 9369 numNetworksAddedByApps++; 9370 } 9371 } 9372 mWifiMetrics.setNumSavedNetworks(numSavedNetworks); 9373 mWifiMetrics.setNumOpenNetworks(numOpenNetworks); 9374 mWifiMetrics.setNumPersonalNetworks(numPersonalNetworks); 9375 mWifiMetrics.setNumEnterpriseNetworks(numEnterpriseNetworks); 9376 mWifiMetrics.setNumNetworksAddedByUser(numNetworksAddedByUser); 9377 mWifiMetrics.setNumNetworksAddedByApps(numNetworksAddedByApps); 9378 9379 /* <TODO> decide how to access WifiServiecImpl.isLocationEnabled() or if to do it manually 9380 mWifiMetrics.setIsLocationEnabled(Settings.Secure.getInt( 9381 mContext.getContentResolver(), 9382 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) 9383 != Settings.Secure.LOCATION_MODE_OFF); 9384 */ 9385 9386 /* <TODO> decide how statemachine will access WifiSettingsStore 9387 mWifiMetrics.setIsScanningAlwaysEnabled(mSettingsStore.isScanningAlwaysAvailable()); 9388 */ 9389 } 9390 9391 private static String getLinkPropertiesSummary(LinkProperties lp) { 9392 List<String> attributes = new ArrayList(6); 9393 if (lp.hasIPv4Address()) { 9394 attributes.add("v4"); 9395 } 9396 if (lp.hasIPv4DefaultRoute()) { 9397 attributes.add("v4r"); 9398 } 9399 if (lp.hasIPv4DnsServer()) { 9400 attributes.add("v4dns"); 9401 } 9402 if (lp.hasGlobalIPv6Address()) { 9403 attributes.add("v6"); 9404 } 9405 if (lp.hasIPv6DefaultRoute()) { 9406 attributes.add("v6r"); 9407 } 9408 if (lp.hasIPv6DnsServer()) { 9409 attributes.add("v6dns"); 9410 } 9411 9412 // TODO: Replace with String.join(" ", attributes) once we're fully on JDK 8. 9413 StringBuilder sb = new StringBuilder(); 9414 boolean first = true; 9415 for (String attr : attributes) { 9416 if (!first) { 9417 sb.append(" "); 9418 } else { 9419 first = false; 9420 } 9421 sb.append(attr); 9422 } 9423 return sb.toString(); 9424 } 9425 9426 /** 9427 * Try to connect to the network of candidate. According to the current connected network, this 9428 * API determines whether no action, disconnect and connect, or roaming. 9429 * 9430 * @param candidate the candidate network to connect to 9431 */ 9432 private void tryToConnectToNetwork(WifiConfiguration candidate) { 9433 if (candidate == null) { 9434 if (DBG) { 9435 Log.d(TAG, "Try to connect to null, give up"); 9436 } 9437 return; 9438 } 9439 9440 ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate(); 9441 if (scanResultCandidate == null) { 9442 Log.e(TAG, "tryToConnectToNetwork: bad candidate. Network:" + candidate 9443 + " scanresult: " + scanResultCandidate); 9444 return; 9445 } 9446 9447 String targetBssid = scanResultCandidate.BSSID; 9448 String targetAssociationId = candidate.SSID + " : " + targetBssid; 9449 if (targetBssid != null && targetBssid.equals(mWifiInfo.getBSSID())) { 9450 if (DBG) { 9451 Log.d(TAG, "tryToConnectToNetwork: Already connect to" + targetAssociationId); 9452 } 9453 return; 9454 } 9455 9456 WifiConfiguration currentConnectedNetwork = mWifiConfigManager 9457 .getWifiConfiguration(mWifiInfo.getNetworkId()); 9458 String currentAssociationId = (currentConnectedNetwork == null) ? "Disconnected" : 9459 (mWifiInfo.getSSID() + " : " + mWifiInfo.getBSSID()); 9460 9461 if (currentConnectedNetwork != null 9462 && (currentConnectedNetwork.networkId == candidate.networkId 9463 || currentConnectedNetwork.isLinked(candidate))) { 9464 if (DBG) { 9465 Log.d(TAG, "tryToConnectToNetwork: Roaming from " + currentAssociationId + " to " 9466 + targetAssociationId); 9467 } 9468 sendMessage(CMD_AUTO_ROAM, candidate.networkId, 0, scanResultCandidate); 9469 } else { 9470 if (DBG) { 9471 Log.d(TAG, "tryToConnectToNetwork: Reconnect from " + currentAssociationId + " to " 9472 + targetAssociationId); 9473 } 9474 9475 sendMessage(CMD_AUTO_CONNECT, candidate.networkId, 0, scanResultCandidate.BSSID); 9476 } 9477 } 9478} 9479