summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java6
-rw-r--r--service/java/com/android/server/wifi/WakeupController.java68
-rw-r--r--service/java/com/android/server/wifi/WakeupLock.java2
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java3
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java57
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java11
6 files changed, 138 insertions, 9 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index a4eb8eaf1..42fa19155 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -2792,6 +2792,12 @@ public class ClientModeImpl extends StateMachine {
+ " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
}
+ WifiConfiguration wifiConfig = getCurrentWifiConfiguration();
+ if (wifiConfig != null) {
+ ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromWifiConfiguration(wifiConfig);
+ mWifiInjector.getWakeupController().setLastDisconnectInfo(matchInfo);
+ }
+
stopRssiMonitoringOffload();
clearTargetBssid("handleNetworkDisconnect");
diff --git a/service/java/com/android/server/wifi/WakeupController.java b/service/java/com/android/server/wifi/WakeupController.java
index c911e96eb..5c81a3bb0 100644
--- a/service/java/com/android/server/wifi/WakeupController.java
+++ b/service/java/com/android/server/wifi/WakeupController.java
@@ -62,6 +62,7 @@ public class WakeupController {
private final WifiInjector mWifiInjector;
private final WakeupConfigStoreData mWakeupConfigStoreData;
private final WifiWakeMetrics mWifiWakeMetrics;
+ private final Clock mClock;
private final WifiScanner.ScanListener mScanListener = new WifiScanner.ScanListener() {
@Override
@@ -104,6 +105,20 @@ public class WakeupController {
/** Whether Wifi verbose logging is enabled. */
private boolean mVerboseLoggingEnabled;
+ /**
+ * The timestamp of when the Wifi network was last disconnected (either device disconnected
+ * from the network or Wifi was turned off entirely).
+ * Note: mLastDisconnectTimestampMillis and mLastDisconnectInfo must always be updated together.
+ */
+ private long mLastDisconnectTimestampMillis;
+
+ /**
+ * The SSID of the last Wifi network the device was connected to (either device disconnected
+ * from the network or Wifi was turned off entirely).
+ * Note: mLastDisconnectTimestampMillis and mLastDisconnectInfo must always be updated together.
+ */
+ private ScanResultMatchInfo mLastDisconnectInfo;
+
public WakeupController(
Context context,
Looper looper,
@@ -114,7 +129,8 @@ public class WakeupController {
WifiConfigStore wifiConfigStore,
WifiWakeMetrics wifiWakeMetrics,
WifiInjector wifiInjector,
- FrameworkFacade frameworkFacade) {
+ FrameworkFacade frameworkFacade,
+ Clock clock) {
mContext = context;
mHandler = new Handler(looper);
mWakeupLock = wakeupLock;
@@ -143,6 +159,9 @@ public class WakeupController {
mWakeupOnboarding.getNotificationsDataSource(),
mWakeupLock.getDataSource());
wifiConfigStore.registerStoreData(mWakeupConfigStoreData);
+ mClock = clock;
+ mLastDisconnectTimestampMillis = 0;
+ mLastDisconnectInfo = null;
}
private void readWifiWakeupEnabledFromSettings() {
@@ -160,6 +179,39 @@ public class WakeupController {
}
/**
+ * Saves the SSID of the last Wifi network that was disconnected. Should only be called before
+ * WakeupController is active.
+ */
+ public void setLastDisconnectInfo(ScanResultMatchInfo scanResultMatchInfo) {
+ if (mIsActive) {
+ Log.e(TAG, "Unexpected setLastDisconnectInfo when WakeupController is active!");
+ return;
+ }
+ if (scanResultMatchInfo == null) {
+ Log.e(TAG, "Unexpected setLastDisconnectInfo(null)");
+ return;
+ }
+ mLastDisconnectTimestampMillis = mClock.getElapsedSinceBootMillis();
+ mLastDisconnectInfo = scanResultMatchInfo;
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "mLastDisconnectInfo set to " + scanResultMatchInfo);
+ }
+ }
+
+ /**
+ * If Wifi was disabled within LAST_DISCONNECT_TIMEOUT_MILLIS of losing a Wifi connection,
+ * add that Wifi connection to the Wakeup Lock as if Wifi was disabled while connected to that
+ * connection.
+ * Often times, networks with poor signal intermittently connect and disconnect, causing the
+ * user to manually turn off Wifi. If the Wifi was turned off during the disconnected phase of
+ * the intermittent connection, then that connection normally would not be added to the Wakeup
+ * Lock. This constant defines the timeout after disconnecting, in milliseconds, within which
+ * if Wifi was disabled, the network would still be added to the wakeup lock.
+ */
+ @VisibleForTesting
+ static final long LAST_DISCONNECT_TIMEOUT_MILLIS = 5 * 1000;
+
+ /**
* Starts listening for incoming scans.
*
* <p>Should only be called upon entering ScanMode. WakeupController registers its listener with
@@ -186,6 +238,18 @@ public class WakeupController {
Set<ScanResultMatchInfo> matchInfos = toMatchInfos(scanResults);
matchInfos.retainAll(getGoodSavedNetworks());
+ // ensure that the last disconnected network is added to the wakeup lock, since we don't
+ // want to automatically reconnect to the same network that the user manually
+ // disconnected from
+ long now = mClock.getElapsedSinceBootMillis();
+ if (mLastDisconnectInfo != null && ((now - mLastDisconnectTimestampMillis)
+ <= LAST_DISCONNECT_TIMEOUT_MILLIS)) {
+ matchInfos.add(mLastDisconnectInfo);
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Added last connected network to lock: " + mLastDisconnectInfo);
+ }
+ }
+
if (mVerboseLoggingEnabled) {
Log.d(TAG, "Saved networks in most recent scan:" + matchInfos);
}
@@ -204,6 +268,8 @@ public class WakeupController {
*/
public void stop() {
Log.d(TAG, "stop()");
+ mLastDisconnectTimestampMillis = 0;
+ mLastDisconnectInfo = null;
mWifiInjector.getWifiScanner().deregisterScanListener(mScanListener);
mWakeupOnboarding.onStop();
}
diff --git a/service/java/com/android/server/wifi/WakeupLock.java b/service/java/com/android/server/wifi/WakeupLock.java
index c6a8f5a34..3a1d097fc 100644
--- a/service/java/com/android/server/wifi/WakeupLock.java
+++ b/service/java/com/android/server/wifi/WakeupLock.java
@@ -39,7 +39,7 @@ public class WakeupLock {
private static final String TAG = WakeupLock.class.getSimpleName();
@VisibleForTesting
- static final int CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT = 3;
+ static final int CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT = 5;
@VisibleForTesting
static final long MAX_LOCK_TIME_MILLIS = 10 * DateUtils.MINUTE_IN_MILLIS;
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 24e125a29..5d54fa7e7 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -280,7 +280,8 @@ public class WifiInjector {
mWifiCoreHandlerThread.getLooper(),
new WakeupLock(mWifiConfigManager, mWifiMetrics.getWakeupMetrics(), mClock),
WakeupEvaluator.fromContext(mContext), wakeupOnboarding, mWifiConfigManager,
- mWifiConfigStore, mWifiMetrics.getWakeupMetrics(), this, mFrameworkFacade);
+ mWifiConfigStore, mWifiMetrics.getWakeupMetrics(), this, mFrameworkFacade,
+ mClock);
mLockManager = new WifiLockManager(mContext, BatteryStatsService.getService());
mWifiController = new WifiController(mContext, mClientModeImpl, clientModeImplLooper,
mSettingsStore, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade,
diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
index 3734ba786..dcea61a48 100644
--- a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
@@ -75,6 +75,7 @@ public class WakeupControllerTest {
@Mock private WifiWakeMetrics mWifiWakeMetrics;
@Mock private WifiController mWifiController;
@Mock private WifiNative mWifiNative;
+ @Mock private Clock mClock;
private TestLooper mLooper;
private WakeupController mWakeupController;
@@ -129,7 +130,8 @@ public class WakeupControllerTest {
mWifiConfigStore,
mWifiWakeMetrics,
mWifiInjector,
- mFrameworkFacade);
+ mFrameworkFacade,
+ mClock);
ArgumentCaptor<WakeupConfigStoreData> captor =
ArgumentCaptor.forClass(WakeupConfigStoreData.class);
@@ -563,4 +565,57 @@ public class WakeupControllerTest {
contentObserver.onChange(false /* selfChange */);
verify(mWakeupOnboarding).setOnboarded();
}
+
+ /**
+ * When Wifi disconnects from a network, and within LAST_DISCONNECT_TIMEOUT_MILLIS Wifi is
+ * disabled, then the last connected Wifi network should be added to the wakeup lock.
+ *
+ * This simulates when a Wifi network sporadically connects and disconnects. During the
+ * disconnected phase, the user forcibly disables Wifi to stop this intermittent behavior. Then,
+ * we should add the network to the wake lock to ensure Wifi Wake does not automatically
+ * reconnect to this network.
+ *
+ * Also verifies that after the above flow, when Wifi is re-enabled, then disabled again, the
+ * last connected network should be reset and no networks should be added to the wakeup lock.
+ */
+ @Test
+ public void lastConnectedNetworkAddedToLock() {
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(0L,
+ (long) (0.8 * WakeupController.LAST_DISCONNECT_TIMEOUT_MILLIS));
+ ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromScanResult(mTestScanResult);
+ when(mWifiConfigManager.getSavedNetworks()).thenReturn(Collections.emptyList());
+ when(mWifiScanner.getSingleScanResults()).thenReturn(Collections.emptyList());
+ initializeWakeupController(true);
+
+ mWakeupController.setLastDisconnectInfo(matchInfo);
+ mWakeupController.start();
+
+ verify(mWakeupLock).setLock(eq(Collections.singleton(matchInfo)));
+
+ mWakeupController.stop();
+ mWakeupController.reset();
+ mWakeupController.start();
+
+ verify(mWakeupLock).setLock(eq(Collections.emptySet()));
+ }
+
+ /**
+ * When Wifi disconnects from a network, and Wifi is disabled after more than
+ * LAST_DISCONNECT_TIMEOUT_MILLIS, the last connected Wifi network should not be added to the
+ * wakeup lock.
+ */
+ @Test
+ public void expiredLastConnectedNetworkNotAddedToLock() {
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(0L,
+ (long) (1.2 * WakeupController.LAST_DISCONNECT_TIMEOUT_MILLIS));
+ ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromScanResult(mTestScanResult);
+ when(mWifiConfigManager.getSavedNetworks()).thenReturn(Collections.emptyList());
+ when(mWifiScanner.getSingleScanResults()).thenReturn(Collections.emptyList());
+ initializeWakeupController(true);
+
+ mWakeupController.setLastDisconnectInfo(matchInfo);
+ mWakeupController.start();
+
+ verify(mWakeupLock).setLock(eq(Collections.emptySet()));
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java
index 43605f484..8bd38e156 100644
--- a/tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java
@@ -105,10 +105,10 @@ public class WakeupLockTest {
mWakeupLock.setLock(networks);
assertFalse(mWakeupLock.isInitialized());
- mWakeupLock.update(networks);
- assertFalse(mWakeupLock.isInitialized());
- mWakeupLock.update(networks);
- assertFalse(mWakeupLock.isInitialized());
+ for (int i = 0; i < WakeupLock.CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT - 1; i++) {
+ mWakeupLock.update(networks);
+ assertFalse(mWakeupLock.isInitialized());
+ }
mWakeupLock.update(networks);
assertTrue(mWakeupLock.isInitialized());
}
@@ -283,7 +283,8 @@ public class WakeupLockTest {
for (int i = 0; i < WakeupLock.CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT; i++) {
mWakeupLock.update(Collections.emptyList());
}
- verify(mWifiWakeMetrics).recordUnlockEvent(3 /* numScans */);
+ verify(mWifiWakeMetrics).recordUnlockEvent(
+ WakeupLock.CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT /* numScans */);
}
private void setLockAndInitializeByTimeout(Collection<ScanResultMatchInfo> networks) {