diff options
author | David Su <dysu@google.com> | 2018-10-10 15:10:07 -0700 |
---|---|---|
committer | David Su <dysu@google.com> | 2018-10-31 09:47:23 -0700 |
commit | f27f8fc96593d686ca8c71fa851635d50a47b549 (patch) | |
tree | 501db90525c1f387a19a392115ffd95635ba6691 | |
parent | 1223e9aa52466139b4de0637c4f9dd3d00b8b20b (diff) |
Increased Wifi Wake consecutive missed scans to 5 and force add last disconnected network to Wakeup Lock.
Due to low latency Wifi scans on new devices being more flaky than
before, increase the number of missed scans required to evict from 3 to
5. In addition, always add the last connected network to the Wakeup
Lock, since we do not want to automatically reconnect to a network that
the user manually disconnected from.
Bug: 112812039
Bug: 112047384
Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Test: connect to AP, disable Wifi on device, wait for scans to
initialize Wakeup Lock (trigger scans by opening Google Maps), turn off
AP, wait for AP to be evicted from Wakeup Lock, turn on AP, Wifi Wake
should turn on Wifi and reconnect to AP.
Test: ACTS WifiWakeTest
Change-Id: I506a1c860ddbd2bfbcd52cf6a23f1ee4e0ca00c6
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) { |