summaryrefslogtreecommitdiffstats
path: root/service
diff options
context:
space:
mode:
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/WifiAutoJoinController.java52
-rw-r--r--service/java/com/android/server/wifi/WifiConfigStore.java87
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java8
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java325
4 files changed, 367 insertions, 105 deletions
diff --git a/service/java/com/android/server/wifi/WifiAutoJoinController.java b/service/java/com/android/server/wifi/WifiAutoJoinController.java
index a971dcd56..cd71f487c 100644
--- a/service/java/com/android/server/wifi/WifiAutoJoinController.java
+++ b/service/java/com/android/server/wifi/WifiAutoJoinController.java
@@ -158,6 +158,7 @@ public class WifiAutoJoinController {
int numScanResultsKnown = 0; // Record number of scan results we knew about
WifiConfiguration associatedConfig = null;
boolean didAssociate = false;
+ long now = System.currentTimeMillis();
ArrayList<NetworkKey> unknownScanResults = new ArrayList<NetworkKey>();
@@ -224,7 +225,11 @@ public class WifiAutoJoinController {
if (associatedConfig != null && associatedConfig.SSID != null) {
if (VDBG) {
logDbg("addToScanCache save associated config "
- + associatedConfig.SSID + " with " + result.SSID);
+ + associatedConfig.SSID + " with " + result.SSID
+ + " status " + associatedConfig.autoJoinStatus
+ + " reason " + associatedConfig.disableReason
+ + " tsp " + associatedConfig.blackListTimestamp
+ + " was " + (now - associatedConfig.blackListTimestamp));
}
mWifiStateMachine.sendMessage(
WifiStateMachine.CMD_AUTO_SAVE_NETWORK, associatedConfig);
@@ -232,7 +237,6 @@ public class WifiAutoJoinController {
}
} else {
// If the scan result has been blacklisted fir 18 hours -> unblacklist
- long now = System.currentTimeMillis();
if ((now - result.blackListTimestamp) > loseBlackListHardMilli) {
result.setAutoJoinStatus(ScanResult.ENABLED);
}
@@ -1129,6 +1133,8 @@ public class WifiAutoJoinController {
didBailDueToWeakRssi = false;
int networkSwitchType = AUTO_JOIN_IDLE;
+ long now = System.currentTimeMillis();
+
String lastSelectedConfiguration = mWifiConfigStore.getLastSelectedConfiguration();
// Reset the currentConfiguration Key, and set it only if WifiStateMachine and
@@ -1261,19 +1267,52 @@ public class WifiAutoJoinController {
if (config.autoJoinStatus >=
WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE) {
+ // Wait for 5 minutes before reenabling config that have known,
+ // repeated connection or DHCP failures
+ if (config.disableReason == WifiConfiguration.DISABLED_DHCP_FAILURE
+ || config.disableReason
+ == WifiConfiguration.DISABLED_ASSOCIATION_REJECT
+ || config.disableReason
+ == WifiConfiguration.DISABLED_AUTH_FAILURE) {
+ if (config.blackListTimestamp == 0
+ || (config.blackListTimestamp > now)) {
+ // Sanitize the timestamp
+ config.blackListTimestamp = now;
+ }
+ if ((now - config.blackListTimestamp) >
+ mWifiConfigStore.wifiConfigBlacklistMinTimeMilli) {
+ // Re-enable the WifiConfiguration
+ config.status = WifiConfiguration.Status.ENABLED;
+
+ // Reset the blacklist condition
+ config.numConnectionFailures = 0;
+ config.numIpConfigFailures = 0;
+ config.numAuthFailures = 0;
+ config.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_ENABLED);
+
+ config.dirty = true;
+ } else {
+ if (VDBG) {
+ long delay = mWifiConfigStore.wifiConfigBlacklistMinTimeMilli
+ - (now - config.blackListTimestamp);
+ logDbg("attemptautoJoin " + config.configKey()
+ + " dont unblacklist yet, waiting for "
+ + delay + " ms");
+ }
+ }
+ }
// Avoid networks disabled because of AUTH failure altogether
if (DBG) {
logDbg("attemptAutoJoin skip candidate due to auto join status "
+ Integer.toString(config.autoJoinStatus) + " key "
+ config.configKey(true)
- + " reason " + config.disableReason);
+ + " reason " + config.disableReason);
}
continue;
}
// Try to un-blacklist based on elapsed time
if (config.blackListTimestamp > 0) {
- long now = System.currentTimeMillis();
if (now < config.blackListTimestamp) {
/**
* looks like there was a change in the system clock since we black listed, and
@@ -1489,6 +1528,11 @@ public class WifiAutoJoinController {
!isOpenNetwork(result)) {
continue;
}
+ if (mWifiConfigStore.mDeletedEphemeralSSIDs.contains
+ ("\"" + result.SSID + "\"")) {
+ // SSID had been Forgotten by user, then don't score it
+ continue;
+ }
if ((nowMs - result.seen) < mScanResultAutoJoinAge) {
// Increment usage count for the network
mWifiConnectionStatistics.incrementOrAddUntrusted(result.SSID, 0, 1);
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
index c7b8ab301..9d5844523 100644
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiConfigStore.java
@@ -158,6 +158,15 @@ public class WifiConfigStore extends IpConfigStore {
*/
private Set<Long> mDeletedSSIDs = new HashSet<Long>();
+ /**
+ * Framework keeps a list of ephemeral SSIDs that where deleted by user,
+ * so as, framework knows not to autojoin again those SSIDs based on scorer input.
+ * The list is never cleared up.
+ *
+ * The SSIDs are encoded in a String as per definition of WifiConfiguration.SSID field.
+ */
+ public Set<String> mDeletedEphemeralSSIDs = new HashSet<String>();
+
/* Tracks the highest priority of configured networks */
private int mLastPriority = -1;
@@ -209,6 +218,7 @@ public class WifiConfigStore extends IpConfigStore {
private static final String EPHEMERAL_KEY = "EPHEMERAL: ";
private static final String NUM_ASSOCIATION_KEY = "NUM_ASSOCIATION: ";
private static final String DELETED_CRC32_KEY = "DELETED_CRC32: ";
+ private static final String DELETED_EPHEMERAL_KEY = "DELETED_EPHEMERAL: ";
private static final String JOIN_ATTEMPT_BOOST_KEY = "JOIN_ATTEMPT_BOOST: ";
private static final String THRESHOLD_INITIAL_AUTO_JOIN_ATTEMPT_RSSI_MIN_5G_KEY
@@ -346,6 +356,9 @@ public class WifiConfigStore extends IpConfigStore {
public int maxConnectionErrorsToBlacklist = 4;
public int wifiConfigBlacklistMinTimeMilli = 1000 * 60 * 5;
+ // How long a disconnected config remain considered as the last user selection
+ public int wifiConfigLastSelectionHysteresis = 1000 * 60 * 3;
+
// Boost RSSI values of associated networks
public int associatedHysteresisHigh = +14;
public int associatedHysteresisLow = +8;
@@ -730,7 +743,7 @@ public class WifiConfigStore extends IpConfigStore {
&& (config.autoJoinStatus
<= WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE)) {
- // Wait for 20 minutes before reenabling config that have known, repeated connection
+ // Wait for 5 minutes before reenabling config that have known, repeated connection
// or DHCP failures
if (config.disableReason == WifiConfiguration.DISABLED_DHCP_FAILURE
|| config.disableReason == WifiConfiguration.DISABLED_ASSOCIATION_REJECT
@@ -830,6 +843,15 @@ public class WifiConfigStore extends IpConfigStore {
+ " Uid=" + Integer.toString(config.creatorUid)
+ "/" + Integer.toString(config.lastUpdateUid));
}
+
+ if (mDeletedEphemeralSSIDs.remove(config.SSID)) {
+ if (VDBG) {
+ loge("WifiConfigStore: removed from ephemeral blacklist: " + config.SSID);
+ }
+ // NOTE: This will be flushed to disk as part of the addOrUpdateNetworkNative call
+ // below, since we're creating/modifying a config.
+ }
+
boolean newNetwork = (config.networkId == INVALID_NETWORK_ID);
NetworkUpdateResult result = addOrUpdateNetworkNative(config, uid);
int netId = result.getNetworkId();
@@ -947,6 +969,42 @@ public class WifiConfigStore extends IpConfigStore {
}
}
+
+ /**
+ * Disable an ephemeral SSID for the purpose of auto-joining thru scored.
+ * This SSID will never be scored anymore.
+ * The only way to "un-disable it" is if the user create a network for that SSID and then
+ * forget it.
+ *
+ * @param SSID caller must ensure that the SSID passed thru this API match
+ * the WifiConfiguration.SSID rules, and thus be surrounded by quotes.
+ * @return the {@link WifiConfiguration} corresponding to this SSID, if any, so that we can
+ * disconnect if this is the current network.
+ */
+ WifiConfiguration disableEphemeralNetwork(String SSID) {
+ if (SSID == null) {
+ return null;
+ }
+
+ WifiConfiguration foundConfig = null;
+
+ mDeletedEphemeralSSIDs.add(SSID);
+ loge("Forget ephemeral SSID " + SSID + " num=" + mDeletedEphemeralSSIDs.size());
+
+ for (WifiConfiguration config : mConfiguredNetworks.values()) {
+ if (SSID.equals(config.SSID) && config.ephemeral) {
+ loge("Found ephemeral config in disableEphemeralNetwork: " + config.networkId);
+ foundConfig = config;
+ }
+ }
+
+ // Force a write, because the mDeletedEphemeralSSIDs list has changed even though the
+ // configurations may not have.
+ writeKnownNetworkHistory(true);
+
+ return foundConfig;
+ }
+
/**
* Forget the specified network and save config
*
@@ -1719,6 +1777,13 @@ public class WifiConfigStore extends IpConfigStore {
out.writeUTF(SEPARATOR_KEY);
}
}
+ if (mDeletedEphemeralSSIDs != null && mDeletedEphemeralSSIDs.size() > 0) {
+ for (String ssid : mDeletedEphemeralSSIDs) {
+ out.writeUTF(DELETED_EPHEMERAL_KEY);
+ out.writeUTF(ssid);
+ out.writeUTF(SEPARATOR_KEY);
+ }
+ }
}
});
}
@@ -2049,6 +2114,13 @@ public class WifiConfigStore extends IpConfigStore {
Long c = Long.parseLong(crc);
mDeletedSSIDs.add(c);
}
+ if (key.startsWith(DELETED_EPHEMERAL_KEY)) {
+ String s = key.replace(DELETED_EPHEMERAL_KEY, "");
+ if (!TextUtils.isEmpty(s)) {
+ s = s.replace(SEPARATOR_KEY, "");
+ mDeletedEphemeralSSIDs.add(s);
+ }
+ }
}
}
}
@@ -3066,8 +3138,9 @@ public class WifiConfigStore extends IpConfigStore {
// Try to make a non verified WifiConfiguration, but only if the original
// configuration was not self already added
if (VDBG) {
- loge("associateWithConfiguration: will create " +
- result.SSID + " and associate it with: " + link.SSID);
+ loge("associateWithConfiguration: try to create " +
+ result.SSID + " and associate it with: " + link.SSID
+ + " key " + link.configKey());
}
config = wifiConfigurationFromScanResult(result);
if (config != null) {
@@ -3077,6 +3150,10 @@ public class WifiConfigStore extends IpConfigStore {
config.peerWifiConfiguration = link.configKey();
if (config.allowedKeyManagement.equals(link.allowedKeyManagement) &&
config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
+ if (VDBG && config != null) {
+ loge("associateWithConfiguration: got a config from beacon"
+ + config.SSID + " key " + config.configKey());
+ }
// Transfer the credentials from the configuration we are linking from
String psk = readNetworkVariableFromSupplicantFile(link.SSID, "psk");
if (psk != null) {
@@ -3108,6 +3185,10 @@ public class WifiConfigStore extends IpConfigStore {
}
if (config != null) break;
}
+ if (VDBG && config != null) {
+ loge("associateWithConfiguration: success, created: " + config.SSID
+ + " key " + config.configKey());
+ }
}
}
return config;
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 8066b4c4b..cc5824e67 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -1313,6 +1313,14 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
return new Messenger(mClientHandler);
}
+ /**
+ * Disable an ephemeral network, i.e. network that is created thru a WiFi Scorer
+ */
+ public void disableEphemeralNetwork(String SSID) {
+ enforceAccessPermission();
+ enforceChangePermission();
+ mWifiStateMachine.disableEphemeralNetwork(SSID);
+ }
/**
* Get the IP and proxy configuration file
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 09920f5d1..a1ff29484 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -578,6 +578,9 @@ public class WifiStateMachine extends StateMachine {
/* Disconnecting state watchdog */
static final int CMD_DISCONNECTING_WATCHDOG_TIMER = BASE + 96;
+ /* Disable an ephemeral network */
+ static final int CMD_DISABLE_EPHEMERAL_NETWORK = BASE + 98;
+
/* P2p commands */
/* We are ok with no response here since we wont do much with it anyway */
public static final int CMD_ENABLE_P2P = BASE + 131;
@@ -862,6 +865,8 @@ public class WifiStateMachine extends StateMachine {
// Used for debug and stats gathering
private static int sScanAlarmIntentCount = 0;
+ final static int frameworkMinScanIntervalSaneValue = 10000;
+
public WifiStateMachine(Context context, String wlanInterface,
WifiTrafficPoller trafficPoller){
super("WifiStateMachine");
@@ -910,9 +915,13 @@ public class WifiStateMachine extends StateMachine {
mScanIntent = getPrivateBroadcast(ACTION_START_SCAN, SCAN_REQUEST);
mBatchedScanIntervalIntent = getPrivateBroadcast(ACTION_REFRESH_BATCHED_SCAN, 0);
- mDefaultFrameworkScanIntervalMs = mContext.getResources().getInteger(
+ // Make sure the interval is not configured less than 10 seconds
+ int period = mContext.getResources().getInteger(
R.integer.config_wifi_framework_scan_interval);
-
+ if (period < frameworkMinScanIntervalSaneValue) {
+ period = frameworkMinScanIntervalSaneValue;
+ }
+ mDefaultFrameworkScanIntervalMs = period;
mDriverStopDelayMs = mContext.getResources().getInteger(
R.integer.config_wifi_driver_stop_delay);
@@ -949,10 +958,10 @@ public class WifiStateMachine extends StateMachine {
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- sScanAlarmIntentCount++;
- startScan(SCAN_ALARM_SOURCE, -2, null, null);
+ sScanAlarmIntentCount++; // Used for debug only
+ startScan(SCAN_ALARM_SOURCE, mDelayedScanCounter.incrementAndGet(), null, null);
if (VDBG)
- loge("WiFiStateMachine SCAN ALARM");
+ loge("WiFiStateMachine SCAN ALARM -> " + mDelayedScanCounter.get());
}
},
new IntentFilter(ACTION_START_SCAN));
@@ -1123,35 +1132,27 @@ public class WifiStateMachine extends StateMachine {
*/
private long mFrameworkScanIntervalMs = 10000;
- private long mCurrentScanAlarmMs = 10000;
- private void setScanAlarm(boolean enabled, int delayMilli) {
+ private AtomicInteger mDelayedScanCounter = new AtomicInteger();
+
+ private void setScanAlarm(boolean enabled) {
if (PDBG) {
loge("setScanAlarm " + enabled
- + " period " + mCurrentScanAlarmMs
- + " initial delay " + delayMilli);
+ + " period " + mDefaultFrameworkScanIntervalMs
+ + " mBackgroundScanSupported " + mBackgroundScanSupported);
+ }
+ if (mBackgroundScanSupported == false) {
+ // Scan alarm is only used for background scans if they are not
+ // offloaded to the wifi chipset, hence enable the scan alarm
+ // gicing us RTC_WAKEUP of backgroundScan is NOT supported
+ enabled = true;
}
- if (mCurrentScanAlarmMs <= 0) enabled = false;
+
if (enabled == mAlarmEnabled) return;
if (enabled) {
- long initialDelayMilli;
- if (delayMilli <= 0) {
- // scan now
- startScan(SCAN_ALARM_SOURCE, 0, null, null);
- initialDelayMilli = mCurrentScanAlarmMs;
- } else {
- initialDelayMilli = delayMilli;
- }
-
- int type = AlarmManager.RTC;
-
/* Set RTC_WAKEUP alarms if PNO is not supported - because no one is */
/* going to wake up the host processor to look for access points */
- if (mBackgroundScanSupported == false)
- type = AlarmManager.RTC_WAKEUP;
-
- mAlarmManager.setRepeating(type,
- System.currentTimeMillis() + initialDelayMilli,
- mCurrentScanAlarmMs,
+ mAlarmManager.set(AlarmManager.RTC_WAKEUP,
+ System.currentTimeMillis() + mDefaultFrameworkScanIntervalMs,
mScanIntent);
mAlarmEnabled = true;
} else {
@@ -1160,6 +1161,53 @@ public class WifiStateMachine extends StateMachine {
}
}
+ private void cancelDelayedScan() {
+ mDelayedScanCounter.incrementAndGet();
+ loge("cancelDelayedScan -> " + mDelayedScanCounter);
+ }
+
+ private boolean checkAndRestartDelayedScan(int counter, boolean restart, int milli,
+ ScanSettings settings, WorkSource workSource) {
+ if (counter != mDelayedScanCounter.get()) {
+ return false;
+ }
+ if (restart)
+ startDelayedScan(milli, settings, workSource);
+ return true;
+ }
+
+ private void startDelayedScan(int milli, ScanSettings settings, WorkSource workSource) {
+ if (milli <= 0) return;
+ /**
+ * The cases where the scan alarm should be run are :
+ * - DisconnectedState && screenOn => used delayed timer
+ * - DisconnectedState && !screenOn && mBackgroundScanSupported => PNO
+ * - DisconnectedState && !screenOn && !mBackgroundScanSupported => used RTC_WAKEUP Alarm
+ * - ConnectedState && screenOn => used delayed timer
+ */
+
+ mDelayedScanCounter.incrementAndGet();
+ if (mScreenOn &&
+ (getCurrentState() == mDisconnectedState
+ || getCurrentState() == mConnectedState)) {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, settings);
+ bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource);
+ bundle.putLong(SCAN_REQUEST_TIME, System.currentTimeMillis());
+ sendMessageDelayed(CMD_START_SCAN, SCAN_ALARM_SOURCE,
+ mDelayedScanCounter.get(), bundle, milli);
+ if (DBG) loge("startDelayedScan send -> " + mDelayedScanCounter + " milli " + milli);
+ } else if (mBackgroundScanSupported == false
+ && !mScreenOn && getCurrentState() == mDisconnectedState) {
+ setScanAlarm(true);
+ if (DBG) loge("startDelayedScan start scan alarm -> "
+ + mDelayedScanCounter + " milli " + milli);
+ } else {
+ if (DBG) loge("startDelayedScan unhandled -> "
+ + mDelayedScanCounter + " milli " + milli);
+ }
+ }
+
private boolean setRandomMacOui() {
String oui = mContext.getResources().getString(
R.string.config_wifi_random_mac_oui, GOOGLE_OUI);
@@ -1592,7 +1640,7 @@ public class WifiStateMachine extends StateMachine {
private static int MESSAGE_HANDLING_STATUS_UNKNOWN = 0;
private static int MESSAGE_HANDLING_STATUS_REFUSED = -1;
private static int MESSAGE_HANDLING_STATUS_FAIL = -2;
- private static int MESSAGE_HANDLING_STATUS_BUFFERED = -3;
+ private static int MESSAGE_HANDLING_STATUS_OBSOLETE = -3;
private static int MESSAGE_HANDLING_STATUS_DEFERRED = -4;
private static int MESSAGE_HANDLING_STATUS_DISCARD = -5;
private static int MESSAGE_HANDLING_STATUS_LOOPED = -6;
@@ -1602,9 +1650,11 @@ public class WifiStateMachine extends StateMachine {
//TODO: this is used only to track connection attempts, however the link state and packet per
//TODO: second logic should be folded into that
- private boolean isScanAllowed() {
+ private boolean checkOrDeferScanAllowed(Message msg) {
long now = System.currentTimeMillis();
if (lastConnectAttempt != 0 && (now - lastConnectAttempt) < 10000) {
+ Message dmsg = Message.obtain(msg);
+ sendMessageDelayed(dmsg, 11000 - (now - lastConnectAttempt));
return false;
}
return true;
@@ -1667,7 +1717,6 @@ public class WifiStateMachine extends StateMachine {
mRxTime = stats.rx_time;
mRunningBeaconCount = stats.beacon_rx;
if (dbg) {
- loge("WifiLinkLayerStats:");
loge(stats.toString());
}
}
@@ -1717,7 +1766,8 @@ public class WifiStateMachine extends StateMachine {
loge(ts + " noteScanStart" + workSource.toString()
+ " uid " + Integer.toString(callingUid));
} else {
- loge(ts + " noteScanstart no scan source");
+ loge(ts + " noteScanstart no scan source"
+ + " uid " + Integer.toString(callingUid));
}
}
startRadioScanStats();
@@ -1742,9 +1792,11 @@ public class WifiStateMachine extends StateMachine {
if (DBG) {
String ts = String.format("[%,d ms]", now);
if (mScanWorkSource != null)
- loge(ts + " noteScanEnd " + mScanWorkSource.toString());
+ loge(ts + " noteScanEnd " + mScanWorkSource.toString()
+ + " onTime=" + mOnTimeThisScan);
else
- loge(ts + " noteScanEnd no scan source");
+ loge(ts + " noteScanEnd no scan source"
+ + " onTime=" + mOnTimeThisScan);
}
if (mScanWorkSource != null) {
try {
@@ -2019,6 +2071,12 @@ public class WifiStateMachine extends StateMachine {
}
}
+ public void disableEphemeralNetwork(String SSID) {
+ if (SSID != null) {
+ sendMessage(CMD_DISABLE_EPHEMERAL_NETWORK, SSID);
+ }
+ }
+
/**
* Get unsynchronized pointer to scan result list
* Can be called only from AutoJoinController which runs in the WifiStateMachine context
@@ -2412,6 +2470,7 @@ public class WifiStateMachine extends StateMachine {
WifiConfiguration config;
Long now;
String report;
+ String key;
StringBuilder sb = new StringBuilder();
if (mScreenOn) {
sb.append("!");
@@ -2448,6 +2507,7 @@ public class WifiStateMachine extends StateMachine {
if (lastScanDuration != 0) {
sb.append(" dur:").append(lastScanDuration);
}
+ sb.append(" cnt=").append(mDelayedScanCounter);
sb.append(" rssi=").append(mWifiInfo.getRssi());
sb.append(" f=").append(mWifiInfo.getFrequency());
sb.append(" sc=").append(mWifiInfo.score);
@@ -2568,6 +2628,11 @@ public class WifiStateMachine extends StateMachine {
sb.append(",").append(mRxTime);
}
sb.append(String.format(" bcn=%d", mRunningBeaconCount));
+ sb.append(String.format(" con=%d", mConnectionRequests));
+ key = mWifiConfigStore.getLastSelectedConfiguration();
+ if (key != null) {
+ sb.append(" last=").append(key);
+ }
break;
case WifiMonitor.NETWORK_CONNECTION_EVENT:
sb.append(" ");
@@ -2581,6 +2646,10 @@ public class WifiStateMachine extends StateMachine {
sb.append(" ").append(config.configKey());
}
sb.append(printTime());
+ key = mWifiConfigStore.getLastSelectedConfiguration();
+ if (key != null) {
+ sb.append(" last=").append(key);
+ }
break;
case CMD_TARGET_BSSID:
case CMD_ASSOCIATED_BSSID:
@@ -2764,7 +2833,7 @@ public class WifiStateMachine extends StateMachine {
sb.append(Integer.toString(msg.arg1));
sb.append(" ");
sb.append(Integer.toString(msg.arg2));
- String key = mWifiConfigStore.getLastSelectedConfiguration();
+ key = mWifiConfigStore.getLastSelectedConfiguration();
if (key != null) {
sb.append(" last=").append(key);
}
@@ -2934,7 +3003,6 @@ public class WifiStateMachine extends StateMachine {
mScreenOn = screenOn;
if (PDBG) {
loge(" handleScreenStateChanged Enter: screenOn=" + screenOn
- + " mCurrentScanAlarmMs = " + Long.toString(mCurrentScanAlarmMs)
+ " mUserWantsSuspendOpt=" + mUserWantsSuspendOpt
+ " state " + getCurrentState().getName()
+ " suppState:" + mSupplicantStateTracker.getSupplicantStateName());
@@ -2955,38 +3023,41 @@ public class WifiStateMachine extends StateMachine {
getWifiLinkLayerStats(false);
mOnTimeScreenStateChange = mOnTime;
lastScreenStateChangeTimeStamp = lastLinkLayerStatsUpdate;
+ mEnableBackgroundScan = false;
+ cancelDelayedScan();
if (screenOn) {
+ setScanAlarm(false);
clearBlacklist();
fullBandConnectedTimeIntervalMilli = mWifiConfigStore.associatedPartialScanPeriodMilli;
- // Start the scan alarm so as to enable autojoin
+ // In either Disconnectedstate or ConnectedState,
+ // start the scan alarm so as to enable autojoin
if (getCurrentState() == mConnectedState
&& mWifiConfigStore.enableAutoJoinScanWhenAssociated) {
- mCurrentScanAlarmMs = mWifiConfigStore.associatedPartialScanPeriodMilli;
- // Scan after 200ms
- setScanAlarm(true, 200);
+ // Scan after 500ms
+ startDelayedScan(500, null, null);
} else if (getCurrentState() == mDisconnectedState) {
- mCurrentScanAlarmMs = mDisconnectedScanPeriodMs;
// Scan after 200ms
- setScanAlarm(true, 200);
+ startDelayedScan(200, null, null);
+ }
+ } else if (startBackgroundScanIfNeeded) {
+ // Screen Off and Disconnected and chipset doesn't support scan offload
+ // => start scan alarm
+ // Screen Off and Disconnected and chipset does support scan offload
+ // => will use scan offload (i.e. background scan)
+ if (!mBackgroundScanSupported) {
+ setScanAlarm(true);
+ } else {
+ mEnableBackgroundScan = true;
}
- } else {
- setScanAlarm(false, 0);
}
-
- if (mBackgroundScanSupported) {
- mEnableBackgroundScan = (screenOn == false);
- }
-
if (DBG) logd("backgroundScan enabled=" + mEnableBackgroundScan
+ " startBackgroundScanIfNeeded:" + startBackgroundScanIfNeeded);
-
if (startBackgroundScanIfNeeded) {
// to scan for them in background, we need all networks enabled
enableBackgroundScan(mEnableBackgroundScan);
}
-
if (DBG) log("handleScreenStateChanged Exit: " + screenOn);
}
@@ -3381,16 +3452,21 @@ public class WifiStateMachine extends StateMachine {
attemptAutoJoin = false;
}
if (DBG) {
+ String selection = mWifiConfigStore.getLastSelectedConfiguration();
+ if (selection == null) {
+ selection = "<none>";
+ }
loge("wifi setScanResults state" + getCurrentState()
+ " sup_state=" + state
+ " debouncing=" + linkDebouncing
- + " mConnectionRequests=" + mConnectionRequests);
+ + " mConnectionRequests=" + mConnectionRequests
+ + " selection=" + selection);
}
if (attemptAutoJoin) {
messageHandlingStatus = MESSAGE_HANDLING_STATUS_PROCESSED;
}
- // Loose last selected configuration if we have been disconnected for 30 minutes
- if (getDisconnectedTimeMilli() > 1000 * 60 * 30) {
+ // Loose last selected configuration if we have been disconnected for 5 minutes
+ if (getDisconnectedTimeMilli() > mWifiConfigStore.wifiConfigLastSelectionHysteresis) {
mWifiConfigStore.setLastSelectedConfiguration(WifiConfiguration.INVALID_NETWORK_ID);
}
@@ -4220,7 +4296,14 @@ public class WifiStateMachine extends StateMachine {
linkDebouncing = false;
/* Reset roaming parameters */
mAutoRoaming = WifiAutoJoinController.AUTO_JOIN_IDLE;
- fullBandConnectedTimeIntervalMilli = 20 * 1000; // Start scans at 20 seconds interval
+
+ /**
+ * fullBandConnectedTimeIntervalMilli:
+ * - start scans at mWifiConfigStore.associatedPartialScanPeriodMilli seconds interval
+ * - exponentially increase to mWifiConfigStore.associatedFullScanMaxIntervalMilli
+ * Initialize to sane value = 20 seconds
+ */
+ fullBandConnectedTimeIntervalMilli = 20 * 1000;
setNetworkDetailedState(DetailedState.DISCONNECTED);
if (mNetworkAgent != null) {
@@ -4713,6 +4796,7 @@ public class WifiStateMachine extends StateMachine {
case CMD_UNWANTED_NETWORK:
case CMD_DISCONNECTING_WATCHDOG_TIMER:
case CMD_ROAM_WATCHDOG_TIMER:
+ case CMD_DISABLE_EPHEMERAL_NETWORK:
messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
break;
case DhcpStateMachine.CMD_ON_QUIT:
@@ -5057,6 +5141,8 @@ public class WifiStateMachine extends StateMachine {
break;
case CMD_SET_OPERATIONAL_MODE:
mOperationalMode = message.arg1;
+ mWifiConfigStore.
+ setLastSelectedConfiguration(WifiConfiguration.INVALID_NETWORK_ID);
break;
case CMD_TARGET_BSSID:
// Trying to associate to this BSSID
@@ -5227,7 +5313,7 @@ public class WifiStateMachine extends StateMachine {
public void enter() {
if (PDBG) {
- loge("Driverstarted State enter");
+ loge("DriverStartedState enter");
}
mIsRunning = true;
mInDelayedStop = false;
@@ -5643,6 +5729,10 @@ public class WifiStateMachine extends StateMachine {
startScan(ENABLE_WIFI, 0, null, null);
}
+ // Loose last selection choice since user toggled WiFi
+ mWifiConfigStore.
+ setLastSelectedConfiguration(WifiConfiguration.INVALID_NETWORK_ID);
+
mOperationalMode = CONNECT_MODE;
transitionTo(mDisconnectedState);
} else {
@@ -5691,6 +5781,9 @@ public class WifiStateMachine extends StateMachine {
case CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER:
s = "CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER";
break;
+ case CMD_DISABLE_EPHEMERAL_NETWORK:
+ s = "CMD_DISABLE_EPHEMERAL_NETWORK";
+ break;
case CMD_START_DRIVER:
s = "CMD_START_DRIVER";
break;
@@ -6025,6 +6118,10 @@ public class WifiStateMachine extends StateMachine {
WifiConfiguration config = mWifiConfigStore.getWifiConfiguration(mLastNetworkId);
if (config != null) {
config.lastDisconnected = System.currentTimeMillis();
+ if (config.ephemeral) {
+ // Remove ephemeral WifiConfigurations from file
+ mWifiConfigStore.forgetNetwork(mLastNetworkId);
+ }
}
}
}
@@ -6240,6 +6337,15 @@ public class WifiStateMachine extends StateMachine {
WifiManager.ERROR);
}
break;
+ case CMD_DISABLE_EPHEMERAL_NETWORK:
+ config = mWifiConfigStore.disableEphemeralNetwork((String)message.obj);
+ if (config != null) {
+ if (config.networkId == mLastNetworkId) {
+ // Disconnect and let autojoin reselect a new network
+ sendMessage(CMD_DISCONNECT);
+ }
+ }
+ break;
case CMD_BLACKLIST_NETWORK:
mWifiNative.addToBlacklist((String) message.obj);
break;
@@ -6877,6 +6983,8 @@ public class WifiStateMachine extends StateMachine {
if (message.arg1 == SCAN_ONLY_WITH_WIFI_OFF_MODE) {
noteWifiDisabledWhileAssociated();
}
+ mWifiConfigStore.
+ setLastSelectedConfiguration(WifiConfiguration.INVALID_NETWORK_ID);
}
break;
case CMD_SET_COUNTRY_CODE:
@@ -6892,6 +7000,20 @@ public class WifiStateMachine extends StateMachine {
+ " RSSI=" + mWifiInfo.getRssi());
//}
if (message.arg1 == SCAN_ALARM_SOURCE) {
+ // Check if the CMD_START_SCAN message is obsolete (and thus if it should
+ // not be processed) and restart the scan if needed
+ boolean shouldScan =
+ mScreenOn && mWifiConfigStore.enableAutoJoinScanWhenAssociated;
+ if (!checkAndRestartDelayedScan(message.arg2,
+ shouldScan,
+ mWifiConfigStore.associatedPartialScanPeriodMilli, null, null)) {
+ messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE;
+ loge("WifiStateMachine L2Connected CMD_START_SCAN source "
+ + message.arg1
+ + " " + message.arg2 + ", " + mDelayedScanCounter
+ + " -> obsolete");
+ return HANDLED;
+ }
boolean tryFullBandScan = false;
boolean restrictChannelList = false;
long now_ms = System.currentTimeMillis();
@@ -6997,13 +7119,14 @@ public class WifiStateMachine extends StateMachine {
WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, message);
}
}
+
} else {
loge("CMD_START_SCAN : connected mode and no configuration");
messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR;
}
} else {
// Not scan alarm source
- handleScanRequest(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, message);
+ return NOT_HANDLED;
}
break;
/* Ignore connection to same network */
@@ -7147,6 +7270,8 @@ public class WifiStateMachine extends StateMachine {
}
obtainingIpWatchdogCount++;
loge("Start Dhcp Watchdog " + obtainingIpWatchdogCount);
+ // Get Link layer stats so as we get fresh tx packet counters
+ getWifiLinkLayerStats(true);
sendMessageDelayed(obtainMessage(CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER,
obtainingIpWatchdogCount, 0), OBTAINING_IP_ADDRESS_GUARD_TIMER_MSEC);
} else {
@@ -7283,7 +7408,7 @@ public class WifiStateMachine extends StateMachine {
log("RoamingState Enter"
+ " mScreenOn=" + mScreenOn );
}
- setScanAlarm(false, 0);
+ setScanAlarm(false);
// Make sure we disconnect if roaming fails
roamWatchdogCount++;
@@ -7414,11 +7539,8 @@ public class WifiStateMachine extends StateMachine {
}
if (mScreenOn
&& mWifiConfigStore.enableAutoJoinScanWhenAssociated) {
- mCurrentScanAlarmMs = mWifiConfigStore.associatedPartialScanPeriodMilli;
- // Scan after 200ms
- setScanAlarm(true, 200);
- } else {
- mCurrentScanAlarmMs = 0;
+ // restart scan alarm
+ startDelayedScan(mWifiConfigStore.associatedPartialScanPeriodMilli, null, null);
}
registerConnected();
lastConnectAttempt = 0;
@@ -7619,7 +7741,7 @@ public class WifiStateMachine extends StateMachine {
@Override
public void exit() {
loge("WifiStateMachine: Leaving Connected state");
- setScanAlarm(false, 0);
+ setScanAlarm(false);
mLastDriverRoamAttempt = 0;
}
}
@@ -7628,7 +7750,6 @@ public class WifiStateMachine extends StateMachine {
@Override
public void enter() {
- mCurrentScanAlarmMs = mDisconnectedScanPeriodMs;
if (PDBG) {
loge(" Enter DisconnectingState State scan interval " + mFrameworkScanIntervalMs
@@ -7658,7 +7779,7 @@ public class WifiStateMachine extends StateMachine {
}
break;
case CMD_START_SCAN:
- // Ignore scans while disconnecting
+ deferMessage(message);
return HANDLED;
case CMD_DISCONNECTING_WATCHDOG_TIMER:
if (disconnectingWatchdogCount == message.arg1) {
@@ -7682,11 +7803,6 @@ public class WifiStateMachine extends StateMachine {
}
return HANDLED;
}
-
- @Override
- public void exit() {
- mCurrentScanAlarmMs = 0;
- }
}
class DisconnectedState extends State {
@@ -7699,17 +7815,10 @@ public class WifiStateMachine extends StateMachine {
return;
}
- // Loose the last selection choice
- // mWifiAutoJoinController.setLastSelectedConfiguration
- // (WifiConfiguration.INVALID_NETWORK_ID);
-
mFrameworkScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS,
mDefaultFrameworkScanIntervalMs);
- if (mScreenOn)
- mCurrentScanAlarmMs = mDisconnectedScanPeriodMs;
-
if (PDBG) {
loge(" Enter disconnected State scan interval " + mFrameworkScanIntervalMs
+ " mEnableBackgroundScan= " + mEnableBackgroundScan
@@ -7720,23 +7829,28 @@ public class WifiStateMachine extends StateMachine {
/** clear the roaming state, if we were roaming, we failed */
mAutoRoaming = WifiAutoJoinController.AUTO_JOIN_IDLE;
- /**
- * - screen dark and PNO supported => scan alarm disabled
- * - everything else => scan alarm enabled with mDefaultFrameworkScanIntervalMs period
- */
- if ((mScreenOn == false) && mEnableBackgroundScan) {
-
- /* If a regular scan result is pending, do not initiate background
- * scan until the scan results are returned. This is needed because
- * initiating a background scan will cancel the regular scan and
- * scan results will not be returned until background scanning is
- * cleared
+ if (mScreenOn) {
+ /**
+ * screen lit and => delayed timer
*/
- if (!mIsScanOngoing) {
- enableBackgroundScan(true);
- }
+ startDelayedScan(mDisconnectedScanPeriodMs, null, null);
} else {
- setScanAlarm(true, 200);
+ /**
+ * screen dark and PNO supported => scan alarm disabled
+ */
+ if (mEnableBackgroundScan) {
+ /* If a regular scan result is pending, do not initiate background
+ * scan until the scan results are returned. This is needed because
+ * initiating a background scan will cancel the regular scan and
+ * scan results will not be returned until background scanning is
+ * cleared
+ */
+ if (!mIsScanOngoing) {
+ enableBackgroundScan(true);
+ }
+ } else {
+ setScanAlarm(true);
+ }
}
/**
@@ -7805,16 +7919,32 @@ public class WifiStateMachine extends StateMachine {
ret = NOT_HANDLED;
break;
case CMD_START_SCAN:
- if (!isScanAllowed()) {
- // Ignore the scan request
+ if (!checkOrDeferScanAllowed(message)) {
+ // The scan request was rescheduled
+ messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED;
return HANDLED;
}
/* Disable background scan temporarily during a regular scan */
if (mEnableBackgroundScan) {
enableBackgroundScan(false);
}
- /* Handled in parent state */
- ret = NOT_HANDLED;
+ if (message.arg1 == SCAN_ALARM_SOURCE) {
+ // Check if the CMD_START_SCAN message is obsolete (and thus if it should
+ // not be processed) and restart the scan
+ if (!checkAndRestartDelayedScan(message.arg2,
+ true, mDisconnectedScanPeriodMs, null, null)) {
+ messageHandlingStatus = MESSAGE_HANDLING_STATUS_OBSOLETE;
+ loge("WifiStateMachine Disconnected CMD_START_SCAN source "
+ + message.arg1
+ + " " + message.arg2 + ", " + mDelayedScanCounter
+ + " -> obsolete");
+ return HANDLED;
+ }
+ handleScanRequest(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, message);
+ ret = HANDLED;
+ } else {
+ ret = NOT_HANDLED;
+ }
break;
case WifiMonitor.SCAN_RESULTS_EVENT:
/* Re-enable background scan when a pending scan result is received */
@@ -7866,8 +7996,7 @@ public class WifiStateMachine extends StateMachine {
if (mEnableBackgroundScan) {
enableBackgroundScan(false);
}
- mCurrentScanAlarmMs = 0;
- setScanAlarm(false, 0);
+ setScanAlarm(false);
}
}