Merge changes I8d835c08,I4620691a
* changes:
Add dump commmand for Wifi Wake.
Connect WakeupLock and WakeupController to the config store data.
diff --git a/service/java/com/android/server/wifi/WakeupConfigStoreData.java b/service/java/com/android/server/wifi/WakeupConfigStoreData.java
index f839ac8..5775117 100644
--- a/service/java/com/android/server/wifi/WakeupConfigStoreData.java
+++ b/service/java/com/android/server/wifi/WakeupConfigStoreData.java
@@ -45,8 +45,10 @@
/**
* Interface defining a data source for the store data.
+ *
+ * @param <T> Type of data source
*/
- interface DataSource<T> {
+ public interface DataSource<T> {
/**
* Returns the data from the data source.
*/
diff --git a/service/java/com/android/server/wifi/WakeupController.java b/service/java/com/android/server/wifi/WakeupController.java
index a3c095a..8787bfd 100644
--- a/service/java/com/android/server/wifi/WakeupController.java
+++ b/service/java/com/android/server/wifi/WakeupController.java
@@ -24,6 +24,9 @@
import com.android.internal.annotations.VisibleForTesting;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
/**
* WakeupController is responsible managing Auto Wifi.
*
@@ -38,16 +41,26 @@
private final Handler mHandler;
private final FrameworkFacade mFrameworkFacade;
private final ContentObserver mContentObserver;
+ private final WakeupLock mWakeupLock;
+ private final WifiConfigManager mWifiConfigManager;
/** Whether this feature is enabled in Settings. */
private boolean mWifiWakeupEnabled;
+ /** Whether the WakeupController is currently active. */
+ private boolean mIsActive = false;
+
public WakeupController(
Context context,
Looper looper,
+ WakeupLock wakeupLock,
+ WifiConfigManager wifiConfigManager,
+ WifiConfigStore wifiConfigStore,
FrameworkFacade frameworkFacade) {
mContext = context;
mHandler = new Handler(looper);
+ mWakeupLock = wakeupLock;
+ mWifiConfigManager = wifiConfigManager;
mFrameworkFacade = frameworkFacade;
mContentObserver = new ContentObserver(mHandler) {
@Override
@@ -59,6 +72,19 @@
mFrameworkFacade.registerContentObserver(mContext, Settings.Global.getUriFor(
Settings.Global.WIFI_WAKEUP_ENABLED), true, mContentObserver);
mContentObserver.onChange(false /* selfChange */);
+
+ // registering the store data here has the effect of reading the persisted value of the
+ // data sources after system boot finishes
+ WakeupConfigStoreData wakeupConfigStoreData =
+ new WakeupConfigStoreData(new IsActiveDataSource(), mWakeupLock.getDataSource());
+ wifiConfigStore.registerStoreData(wakeupConfigStoreData);
+ }
+
+ private void setActive(boolean isActive) {
+ if (mIsActive != isActive) {
+ mIsActive = isActive;
+ mWifiConfigManager.saveToStore(false /* forceWrite */);
+ }
}
/**
@@ -71,4 +97,26 @@
boolean isEnabled() {
return mWifiWakeupEnabled;
}
+
+ /** Dumps wakeup controller state. */
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("Dump of WakeupController");
+ pw.println("mWifiWakeupEnabled: " + mWifiWakeupEnabled);
+ pw.println("USE_PLATFORM_WIFI_WAKE: " + USE_PLATFORM_WIFI_WAKE);
+ pw.println("mIsActive: " + mIsActive);
+ mWakeupLock.dump(fd, pw, args);
+ }
+
+ private class IsActiveDataSource implements WakeupConfigStoreData.DataSource<Boolean> {
+
+ @Override
+ public Boolean getData() {
+ return mIsActive;
+ }
+
+ @Override
+ public void setData(Boolean data) {
+ mIsActive = data;
+ }
+ }
}
diff --git a/service/java/com/android/server/wifi/WakeupLock.java b/service/java/com/android/server/wifi/WakeupLock.java
index 73cda91..1fcd9f8 100644
--- a/service/java/com/android/server/wifi/WakeupLock.java
+++ b/service/java/com/android/server/wifi/WakeupLock.java
@@ -17,12 +17,16 @@
package com.android.server.wifi;
import android.util.ArrayMap;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
/**
* A lock to determine whether Auto Wifi can re-enable Wifi.
@@ -31,18 +35,24 @@
*/
public class WakeupLock {
+ private static final String TAG = WakeupLock.class.getSimpleName();
+
@VisibleForTesting
static final int CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT = 3;
- private Map<ScanResultMatchInfo, Integer> mLockedNetworks = new ArrayMap<>();
- // TODO(easchwar) read initial value of mLockedNetworks from file
- public WakeupLock() {
+ private final WifiConfigManager mWifiConfigManager;
+ private final Map<ScanResultMatchInfo, Integer> mLockedNetworks = new ArrayMap<>();
+
+ public WakeupLock(WifiConfigManager wifiConfigManager) {
+ mWifiConfigManager = wifiConfigManager;
}
/**
* Initializes the WakeupLock with the given {@link ScanResultMatchInfo} list.
*
+ * <p>This saves the wakeup lock to the store.
+ *
* @param scanResultList list of ScanResultMatchInfos to start the lock with
*/
public void initialize(Collection<ScanResultMatchInfo> scanResultList) {
@@ -50,17 +60,23 @@
for (ScanResultMatchInfo scanResultMatchInfo : scanResultList) {
mLockedNetworks.put(scanResultMatchInfo, CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT);
}
+
+ Log.d(TAG, "Lock initialized. Number of networks: " + mLockedNetworks.size());
+
+ mWifiConfigManager.saveToStore(false /* forceWrite */);
}
/**
* Updates the lock with the given {@link ScanResultMatchInfo} list.
*
* <p>If a network in the lock is not present in the list, reduce the number of scans
- * required to evict by one. Remove any entries in the list with 0 scans required to evict.
+ * required to evict by one. Remove any entries in the list with 0 scans required to evict. If
+ * any entries in the lock are removed, the store is updated.
*
* @param scanResultList list of present ScanResultMatchInfos to update the lock with
*/
public void update(Collection<ScanResultMatchInfo> scanResultList) {
+ boolean hasChanged = false;
Iterator<Map.Entry<ScanResultMatchInfo, Integer>> it =
mLockedNetworks.entrySet().iterator();
while (it.hasNext()) {
@@ -76,9 +92,13 @@
entry.setValue(entry.getValue() - 1);
if (entry.getValue() <= 0) {
it.remove();
+ hasChanged = true;
}
}
- // TODO(easchwar) write the updated list to file
+
+ if (hasChanged) {
+ mWifiConfigManager.saveToStore(false /* forceWrite */);
+ }
}
/**
@@ -87,4 +107,36 @@
public boolean isEmpty() {
return mLockedNetworks.isEmpty();
}
+
+ /** Returns the data source for the WakeupLock config store data. */
+ public WakeupConfigStoreData.DataSource<Set<ScanResultMatchInfo>> getDataSource() {
+ return new WakeupLockDataSource();
+ }
+
+ /** Dumps wakeup lock contents. */
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("WakeupLock: ");
+ pw.println("Locked networks: " + mLockedNetworks.size());
+ for (Map.Entry<ScanResultMatchInfo, Integer> entry : mLockedNetworks.entrySet()) {
+ pw.println(entry.getKey() + ", scans to evict: " + entry.getValue());
+ }
+ }
+
+ private class WakeupLockDataSource
+ implements WakeupConfigStoreData.DataSource<Set<ScanResultMatchInfo>> {
+
+ @Override
+ public Set<ScanResultMatchInfo> getData() {
+ return mLockedNetworks.keySet();
+ }
+
+ @Override
+ public void setData(Set<ScanResultMatchInfo> data) {
+ mLockedNetworks.clear();
+ for (ScanResultMatchInfo network : data) {
+ mLockedNetworks.put(network, CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT);
+ }
+
+ }
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 11fb682..dc48163 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -230,7 +230,8 @@
new OpenNetworkRecommender(),
new ConnectToNetworkNotificationBuilder(mContext, mFrameworkFacade));
mWakeupController = new WakeupController(mContext,
- mWifiStateMachineHandlerThread.getLooper(), mFrameworkFacade);
+ mWifiStateMachineHandlerThread.getLooper(), new WakeupLock(mWifiConfigManager),
+ mWifiConfigManager, mWifiConfigStore, mFrameworkFacade);
mLockManager = new WifiLockManager(mContext, BatteryStatsService.getService());
mWifiController = new WifiController(mContext, mWifiStateMachine, mSettingsStore,
mLockManager, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade);
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 910e90d..1521bb9 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -2281,6 +2281,7 @@
} else {
pw.println("mWifiConnectivityManager is not initialized");
}
+ mWifiInjector.getWakeupController().dump(fd, pw, args);
}
public void handleUserSwitch(int userId) {
diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
index 742c520..5e45570 100644
--- a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
@@ -18,6 +18,8 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -29,12 +31,18 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+
/**
* Unit tests for {@link WakeupController}.
*/
public class WakeupControllerTest {
@Mock private Context mContext;
+ @Mock private WakeupLock mWakeupLock;
+ @Mock private WifiConfigManager mWifiConfigManager;
+ @Mock private WifiConfigStore mWifiConfigStore;
@Mock private FrameworkFacade mFrameworkFacade;
private TestLooper mLooper;
@@ -47,6 +55,11 @@
mLooper = new TestLooper();
}
+ private WakeupController newWakeupController() {
+ return new WakeupController(mContext, mLooper.getLooper(), mWakeupLock, mWifiConfigManager,
+ mWifiConfigStore, mFrameworkFacade);
+ }
+
/**
* Verify WakeupController is enabled when the settings toggle is true.
*/
@@ -54,8 +67,7 @@
public void verifyEnabledWhenToggledOn() {
when(mFrameworkFacade.getIntegerSetting(mContext,
Settings.Global.WIFI_WAKEUP_ENABLED, 0)).thenReturn(1);
- mWakeupController = new WakeupController(mContext, mLooper.getLooper(),
- mFrameworkFacade);
+ mWakeupController = newWakeupController();
assertTrue(mWakeupController.isEnabled());
}
@@ -67,9 +79,30 @@
public void verifyDisabledWhenToggledOff() {
when(mFrameworkFacade.getIntegerSetting(mContext,
Settings.Global.WIFI_WAKEUP_ENABLED, 0)).thenReturn(0);
- mWakeupController = new WakeupController(mContext, mLooper.getLooper(),
- mFrameworkFacade);
+ mWakeupController = newWakeupController();
assertFalse(mWakeupController.isEnabled());
}
+
+ /**
+ * Verify WakeupController registers its store data with the WifiConfigStore on construction.
+ */
+ @Test
+ public void registersWakeupConfigStoreData() {
+ mWakeupController = newWakeupController();
+ verify(mWifiConfigStore).registerStoreData(any(WakeupConfigStoreData.class));
+ }
+
+ /**
+ * Verify that dump calls also dump the state of the WakeupLock.
+ */
+ @Test
+ public void dumpIncludesWakeupLock() {
+ mWakeupController = newWakeupController();
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ PrintWriter writer = new PrintWriter(stream);
+ mWakeupController.dump(null, writer, null);
+
+ verify(mWakeupLock).dump(null, writer, null);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java
index bad9e3a..7144ecf 100644
--- a/tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java
@@ -18,9 +18,13 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.Collection;
@@ -35,6 +39,8 @@
private static final String SSID_1 = "ssid1";
private static final String SSID_2 = "ssid2";
+ @Mock private WifiConfigManager mWifiConfigManager;
+
private ScanResultMatchInfo mNetwork1;
private ScanResultMatchInfo mNetwork2;
private WakeupLock mWakeupLock;
@@ -44,6 +50,8 @@
*/
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
mNetwork1 = new ScanResultMatchInfo();
mNetwork1.networkSsid = SSID_1;
mNetwork1.networkType = ScanResultMatchInfo.NETWORK_TYPE_OPEN;
@@ -52,7 +60,7 @@
mNetwork2.networkSsid = SSID_2;
mNetwork2.networkType = ScanResultMatchInfo.NETWORK_TYPE_EAP;
- mWakeupLock = new WakeupLock();
+ mWakeupLock = new WakeupLock(mWifiConfigManager);
}
/**
@@ -69,6 +77,18 @@
}
/**
+ * Updates the lock enough times to evict any networks not passed in.
+ *
+ * <p>It calls update {@link WakeupLock#CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT} times with
+ * the given network list. It does not make any assertions about the state of the lock.
+ */
+ private void updateEnoughTimesToEvictWithoutAsserts(Collection<ScanResultMatchInfo> networks) {
+ for (int i = 0; i < WakeupLock.CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT; i++) {
+ mWakeupLock.update(networks);
+ }
+ }
+
+ /**
* Verify that the WakeupLock is not empty immediately after being initialized with networks.
*/
@Test
@@ -161,4 +181,34 @@
updateEnoughTimesToEvictWithAsserts(Collections.singletonList(mNetwork2));
assertTrue(mWakeupLock.isEmpty());
}
+
+ /**
+ * Verify that initializing the lock persists the SSID list to the config store.
+ */
+ @Test
+ public void initializeShouldSaveSsidsToStore() {
+ mWakeupLock.initialize(Collections.singletonList(mNetwork1));
+ verify(mWifiConfigManager).saveToStore(eq(false));
+ }
+
+ /**
+ * Verify that update saves to store if the lock changes.
+ */
+ @Test
+ public void updateShouldOnlySaveIfLockChanges() {
+ mWakeupLock.initialize(Collections.singletonList(mNetwork1));
+ updateEnoughTimesToEvictWithoutAsserts(Collections.emptyList());
+
+ // need exactly 2 invocations: 1 for initialize, 1 for successful update
+ verify(mWifiConfigManager, times(2)).saveToStore(eq(false));
+ }
+
+ /**
+ * Verify that update does not save to store if the lock does not change.
+ */
+ @Test
+ public void updateShouldNotSaveIfLockDoesNotChange() {
+ mWakeupLock.update(Collections.singletonList(mNetwork1));
+ verify(mWifiConfigManager, never()).saveToStore(anyBoolean());
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
index 80536aa..e6972ea 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
@@ -376,6 +376,7 @@
@Mock IProvisioningCallback mProvisioningCallback;
@Mock HandlerThread mWifiServiceHandlerThread;
@Mock WifiPermissionsWrapper mWifiPermissionsWrapper;
+ @Mock WakeupController mWakeupController;
public WifiStateMachineTest() throws Exception {
}
@@ -422,6 +423,7 @@
when(mWifiServiceHandlerThread.getLooper()).thenReturn(mLooper.getLooper());
when(mWifiInjector.getWifiServiceHandlerThread()).thenReturn(mWifiServiceHandlerThread);
when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper);
+ when(mWifiInjector.getWakeupController()).thenReturn(mWakeupController);
when(mWifiNative.setupForClientMode(WIFI_IFACE_NAME))
.thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mClientInterface));
@@ -2829,4 +2831,15 @@
currentConfig.networkId = lastSelectedNetworkId - 1;
assertFalse(mWsm.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig));
}
+
+ /**
+ * Verify that WSM dump includes WakeupController.
+ */
+ @Test
+ public void testDumpShouldDumpWakeupController() {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ PrintWriter writer = new PrintWriter(stream);
+ mWsm.dump(null, writer, null);
+ verify(mWakeupController).dump(null, writer, null);
+ }
}