summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Schwarzenbach <easchwar@google.com>2018-02-06 11:28:50 -0800
committerEric Schwarzenbach <easchwar@google.com>2018-03-21 15:31:40 -0700
commit12d31e7fea8e5c17dddc0ab433c26c31a3bf2550 (patch)
treec0b45c623a27af03fa6a08b04bbd8b356af66e88
parent563e1b048d0edd4a1ea95c555951f31b16b77f50 (diff)
Add metrics for Wifi Wake
Test: runtest, manual Bug: 72762459 Change-Id: I0bb64c9a6bff0fde8c1203de4445698247bb781a
-rw-r--r--service/java/com/android/server/wifi/WakeupController.java26
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java2
-rw-r--r--service/java/com/android/server/wifi/WifiMetrics.java10
-rw-r--r--service/java/com/android/server/wifi/WifiWakeMetrics.java294
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java56
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiWakeMetricsTest.java254
6 files changed, 632 insertions, 10 deletions
diff --git a/service/java/com/android/server/wifi/WakeupController.java b/service/java/com/android/server/wifi/WakeupController.java
index 4adee42c5..6fe51570e 100644
--- a/service/java/com/android/server/wifi/WakeupController.java
+++ b/service/java/com/android/server/wifi/WakeupController.java
@@ -61,6 +61,7 @@ public class WakeupController {
private final WifiConfigManager mWifiConfigManager;
private final WifiInjector mWifiInjector;
private final WakeupConfigStoreData mWakeupConfigStoreData;
+ private final WifiWakeMetrics mWifiWakeMetrics;
private final WifiScanner.ScanListener mScanListener = new WifiScanner.ScanListener() {
@Override
@@ -97,6 +98,9 @@ public class WakeupController {
/** Whether the WakeupController is currently active. */
private boolean mIsActive = false;
+ /** The number of scans that have been handled by the controller since last {@link #reset()}. */
+ private int mNumScansHandled = 0;
+
public WakeupController(
Context context,
Looper looper,
@@ -105,6 +109,7 @@ public class WakeupController {
WakeupOnboarding wakeupOnboarding,
WifiConfigManager wifiConfigManager,
WifiConfigStore wifiConfigStore,
+ WifiWakeMetrics wifiWakeMetrics,
WifiInjector wifiInjector,
FrameworkFacade frameworkFacade) {
mContext = context;
@@ -113,6 +118,7 @@ public class WakeupController {
mWakeupEvaluator = wakeupEvaluator;
mWakeupOnboarding = wakeupOnboarding;
mWifiConfigManager = wifiConfigManager;
+ mWifiWakeMetrics = wifiWakeMetrics;
mFrameworkFacade = frameworkFacade;
mWifiInjector = wifiInjector;
mContentObserver = new ContentObserver(mHandler) {
@@ -156,6 +162,7 @@ public class WakeupController {
// If already active, we don't want to re-initialize the lock, so return early.
if (mIsActive) {
+ // TODO record metric for calls to start() when already active
return;
}
setActive(true);
@@ -163,7 +170,10 @@ public class WakeupController {
// ensure feature is enabled and store data has been read before performing work
if (isEnabled()) {
mWakeupOnboarding.maybeShowNotification();
- mWakeupLock.initialize(getMostRecentSavedScanResults());
+
+ Set<ScanResultMatchInfo> mostRecentSavedScanResults = getMostRecentSavedScanResults();
+ mWifiWakeMetrics.recordStartEvent(mostRecentSavedScanResults.size());
+ mWakeupLock.initialize(mostRecentSavedScanResults);
}
}
@@ -182,6 +192,8 @@ public class WakeupController {
/** Resets the WakeupController, setting {@link #mIsActive} to false. */
public void reset() {
Log.d(TAG, "reset()");
+ mWifiWakeMetrics.recordResetEvent(mNumScansHandled);
+ mNumScansHandled = 0;
setActive(false);
}
@@ -214,7 +226,6 @@ public class WakeupController {
goodSavedNetworks.add(ScanResultMatchInfo.fromWifiConfiguration(config));
}
- Log.d(TAG, "getGoodSavedNetworks: " + goodSavedNetworks.size());
return goodSavedNetworks;
}
@@ -240,6 +251,9 @@ public class WakeupController {
return;
}
+ // only count scan as handled if isEnabled
+ mNumScansHandled++;
+
// need to show notification here in case user enables Wifi Wake when Wifi is off
mWakeupOnboarding.maybeShowNotification();
if (!mWakeupOnboarding.isOnboarded()) {
@@ -260,6 +274,7 @@ public class WakeupController {
}
Log.d(TAG, "WakeupLock emptied");
+ mWifiWakeMetrics.recordUnlockEvent(mNumScansHandled);
}
ScanResult network =
@@ -288,6 +303,7 @@ public class WakeupController {
// TODO(b/72180295): ensure that there is no race condition with WifiServiceImpl here
if (mWifiInjector.getWifiSettingsStore().handleWifiToggled(true /* wifiEnabled */)) {
mWifiInjector.getWifiController().sendMessage(CMD_WIFI_TOGGLED);
+ mWifiWakeMetrics.recordWakeupEvent(mNumScansHandled);
}
}
@@ -305,9 +321,13 @@ public class WakeupController {
/** 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("mWifiWakeupEnabled: " + mWifiWakeupEnabled);
+ pw.println("isOnboarded: " + mWakeupOnboarding.isOnboarded());
+ pw.println("configStore hasBeenRead: " + mWakeupConfigStoreData.hasBeenRead());
pw.println("mIsActive: " + mIsActive);
+ pw.println("mNumScansHandled: " + mNumScansHandled);
+
mWakeupLock.dump(fd, pw, args);
}
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 28e36169b..eb4cb496f 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -266,7 +266,7 @@ public class WifiInjector {
mWakeupController = new WakeupController(mContext,
mWifiStateMachineHandlerThread.getLooper(), new WakeupLock(mWifiConfigManager),
WakeupEvaluator.fromContext(mContext), wakeupOnboarding, mWifiConfigManager,
- mWifiConfigStore, this, mFrameworkFacade);
+ mWifiConfigStore, mWifiMetrics.getWakeupMetrics(), this, mFrameworkFacade);
mLockManager = new WifiLockManager(mContext, BatteryStatsService.getService());
mWifiController = new WifiController(mContext, mWifiStateMachine, wifiStateMachineLooper,
mSettingsStore, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade,
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 992182686..f076f8f62 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -190,6 +190,9 @@ public class WifiMetrics {
/** Wifi power metrics*/
private WifiPowerMetrics mWifiPowerMetrics = new WifiPowerMetrics();
+ /** Wifi Wake metrics */
+ private final WifiWakeMetrics mWifiWakeMetrics = new WifiWakeMetrics();
+
class RouterFingerPrint {
private WifiMetricsProto.RouterFingerPrint mRouterFingerPrintProto;
RouterFingerPrint() {
@@ -1877,6 +1880,7 @@ public class WifiMetrics {
+ mWpsMetrics.numWpsCancellation);
mWifiPowerMetrics.dump(pw);
+ mWifiWakeMetrics.dump(pw);
}
}
}
@@ -2163,6 +2167,7 @@ public class WifiMetrics {
mWifiLogProto.wpsMetrics = mWpsMetrics;
mWifiLogProto.wifiPowerStats = mWifiPowerMetrics.buildProto();
+ mWifiLogProto.wifiWakeStats = mWifiWakeMetrics.buildProto();
}
}
@@ -2226,6 +2231,7 @@ public class WifiMetrics {
mSoftApEventListTethered.clear();
mSoftApEventListLocalOnly.clear();
mWpsMetrics.clear();
+ mWifiWakeMetrics.clear();
}
}
@@ -2410,6 +2416,10 @@ public class WifiMetrics {
return mWifiAwareMetrics;
}
+ public WifiWakeMetrics getWakeupMetrics() {
+ return mWifiWakeMetrics;
+ }
+
// Rather than generate a StaEvent for each SUPPLICANT_STATE_CHANGE, cache these in a bitmask
// and attach it to the next event which is generated.
private int mSupplicantStateChangeBitmask = 0;
diff --git a/service/java/com/android/server/wifi/WifiWakeMetrics.java b/service/java/com/android/server/wifi/WifiWakeMetrics.java
new file mode 100644
index 000000000..fba72369f
--- /dev/null
+++ b/service/java/com/android/server/wifi/WifiWakeMetrics.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.wifi;
+
+import android.annotation.Nullable;
+import android.os.SystemClock;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wifi.nano.WifiMetricsProto.WifiWakeStats;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Holds WifiWake metrics and converts them to a protobuf included in WifiLog.
+ */
+public class WifiWakeMetrics {
+
+ /** Maximum number of sessions to store in WifiWakeStats proto. */
+ @VisibleForTesting
+ static final int MAX_RECORDED_SESSIONS = 10;
+
+ @GuardedBy("mLock")
+ private final List<Session> mSessions = new ArrayList<>();
+ @GuardedBy("mLock")
+ private Session mCurrentSession;
+
+ private boolean mIsInSession = false;
+ private int mTotalSessions = 0;
+
+ private final Object mLock = new Object();
+
+ /**
+ * Records the beginning of a Wifi Wake session.
+ *
+ * <p>Starts the session.
+ *
+ * @param numNetworks The total number of networks stored in the WakeupLock at initialization.
+ */
+ public void recordStartEvent(int numNetworks) {
+ synchronized (mLock) {
+ mCurrentSession = new Session(numNetworks, SystemClock.elapsedRealtime());
+ mIsInSession = true;
+ }
+ }
+
+ /**
+ * Records the unlock event of the current Wifi Wake session.
+ *
+ * <p>The unlock event occurs when the WakeupLock has all of its networks removed. This event
+ * will not be recorded if the start event recorded 0 locked networks.
+ *
+ * <p>Note: The start event must be recorded before this event, otherwise this call will be
+ * ignored.
+ *
+ * @param numScans The total number of elapsed scans since start.
+ */
+ public void recordUnlockEvent(int numScans) {
+ synchronized (mLock) {
+ if (!mIsInSession) {
+ return;
+ }
+ mCurrentSession.recordUnlockEvent(numScans, SystemClock.elapsedRealtime());
+ }
+ }
+
+ /**
+ * Records the wakeup event of the current Wifi Wake session.
+ *
+ * <p>The wakeup event occurs when Wifi is re-enabled by the WakeupController.
+ *
+ * <p>Note: The start event must be recorded before this event, otherwise this call will be
+ * ignored.
+ *
+ * @param numScans The total number of elapsed scans since start.
+ */
+ public void recordWakeupEvent(int numScans) {
+ synchronized (mLock) {
+ if (!mIsInSession) {
+ return;
+ }
+ mCurrentSession.recordWakeupEvent(numScans, SystemClock.elapsedRealtime());
+ }
+ }
+
+ /**
+ * Records the reset event of the current Wifi Wake session.
+ *
+ * <p>The reset event occurs when Wifi enters client mode. Stores the first
+ * {@link #MAX_RECORDED_SESSIONS} in the session list.
+ *
+ * <p>Note: The start event must be recorded before this event, otherwise this call will be
+ * ignored. This event ends the current session.
+ *
+ * @param numScans The total number of elapsed scans since start.
+ */
+ public void recordResetEvent(int numScans) {
+ synchronized (mLock) {
+ if (!mIsInSession) {
+ return;
+ }
+ mCurrentSession.recordResetEvent(numScans, SystemClock.elapsedRealtime());
+
+ mTotalSessions++;
+ if (mSessions.size() < MAX_RECORDED_SESSIONS) {
+ mSessions.add(mCurrentSession);
+ }
+ mIsInSession = false;
+ }
+ }
+
+ /**
+ * Returns the consolidated WifiWakeStats proto for WifiMetrics.
+ */
+ public WifiWakeStats buildProto() {
+ WifiWakeStats proto = new WifiWakeStats();
+
+ proto.numSessions = mTotalSessions;
+ proto.sessions = new WifiWakeStats.Session[mSessions.size()];
+
+ for (int i = 0; i < mSessions.size(); i++) {
+ proto.sessions[i] = mSessions.get(i).buildProto();
+ }
+
+ return proto;
+ }
+
+ /**
+ * Dump all WifiWake stats to console (pw)
+ * @param pw
+ */
+ public void dump(PrintWriter pw) {
+ synchronized (mLock) {
+ pw.println("-------WifiWake metrics-------");
+ pw.println("mTotalSessions: " + mTotalSessions);
+ pw.println("mIsInSession: " + mIsInSession);
+ pw.println("Stored Sessions: " + mSessions.size());
+ for (Session session : mSessions) {
+ session.dump(pw);
+ }
+ if (mCurrentSession != null) {
+ pw.println("Current Session: ");
+ mCurrentSession.dump(pw);
+ }
+ pw.println("----end of WifiWake metrics----");
+ }
+ }
+
+ /**
+ * Clears WifiWakeMetrics.
+ *
+ * <p>Keeps the current WifiWake session.
+ */
+ public void clear() {
+ mSessions.clear();
+ mTotalSessions = 0;
+ }
+
+ /** A single WifiWake session. */
+ public static class Session {
+
+ private final long mStartTimestamp;
+ private final int mNumNetworks;
+
+ @VisibleForTesting
+ @Nullable
+ Event mUnlockEvent;
+ @VisibleForTesting
+ @Nullable
+ Event mWakeupEvent;
+ @VisibleForTesting
+ @Nullable
+ Event mResetEvent;
+
+ /** Creates a new WifiWake session. */
+ public Session(int numNetworks, long timestamp) {
+ mNumNetworks = numNetworks;
+ mStartTimestamp = timestamp;
+ }
+
+ /**
+ * Records an unlock event.
+ *
+ * <p>Ignores subsequent calls.
+ *
+ * @param numScans Total number of scans at the time of this event.
+ * @param timestamp The timestamp of the event.
+ */
+ public void recordUnlockEvent(int numScans, long timestamp) {
+ if (mUnlockEvent == null) {
+ mUnlockEvent = new Event(numScans, timestamp - mStartTimestamp);
+ }
+ }
+
+ /**
+ * Records a wakeup event.
+ *
+ * <p>Ignores subsequent calls.
+ *
+ * @param numScans Total number of scans at the time of this event.
+ * @param timestamp The timestamp of the event.
+ */
+ public void recordWakeupEvent(int numScans, long timestamp) {
+ if (mWakeupEvent == null) {
+ mWakeupEvent = new Event(numScans, timestamp - mStartTimestamp);
+ }
+ }
+
+ /**
+ * Records a reset event.
+ *
+ * <p>Ignores subsequent calls.
+ *
+ * @param numScans Total number of scans at the time of this event.
+ * @param timestamp The timestamp of the event.
+ */
+ public void recordResetEvent(int numScans, long timestamp) {
+ if (mResetEvent == null) {
+ mResetEvent = new Event(numScans, timestamp - mStartTimestamp);
+ }
+ }
+
+ /** Returns the proto representation of this session. */
+ public WifiWakeStats.Session buildProto() {
+ WifiWakeStats.Session sessionProto = new WifiWakeStats.Session();
+ sessionProto.startTimeMillis = mStartTimestamp;
+ sessionProto.lockedNetworksAtStart = mNumNetworks;
+
+ if (mUnlockEvent != null) {
+ sessionProto.unlockEvent = mUnlockEvent.buildProto();
+ }
+ if (mWakeupEvent != null) {
+ sessionProto.wakeupEvent = mWakeupEvent.buildProto();
+ }
+ if (mResetEvent != null) {
+ sessionProto.resetEvent = mResetEvent.buildProto();
+ }
+
+ return sessionProto;
+ }
+
+ /** Dumps the current state of the session. */
+ public void dump(PrintWriter pw) {
+ pw.println("WifiWakeMetrics.Session:");
+ pw.println("mStartTimestamp: " + mStartTimestamp);
+ pw.println("mNumNetworks: " + mNumNetworks);
+ pw.println("mUnlockEvent: " + (mUnlockEvent == null ? "{}" : mUnlockEvent.toString()));
+ pw.println("mWakeupEvent: " + (mWakeupEvent == null ? "{}" : mWakeupEvent.toString()));
+ pw.println("mResetEvent: " + (mResetEvent == null ? "{}" : mResetEvent.toString()));
+ }
+ }
+
+ /** An event in a WifiWake session. */
+ public static class Event {
+
+ /** Total number of scans that have elapsed prior to this event. */
+ public final int mNumScans;
+ /** Total elapsed time in milliseconds at the instant of this event. */
+ public final long mElapsedTime;
+
+ public Event(int numScans, long elapsedTime) {
+ mNumScans = numScans;
+ mElapsedTime = elapsedTime;
+ }
+
+ /** Returns the proto representation of this event. */
+ public WifiWakeStats.Session.Event buildProto() {
+ WifiWakeStats.Session.Event eventProto = new WifiWakeStats.Session.Event();
+ eventProto.elapsedScans = mNumScans;
+ eventProto.elapsedTimeMillis = mElapsedTime;
+ return eventProto;
+ }
+
+ @Override
+ public String toString() {
+ return "{ mNumScans: " + mNumScans + ", elapsedTime: " + mElapsedTime + " }";
+ }
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
index 79d1a1c29..f246c4884 100644
--- a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
@@ -19,8 +19,11 @@ package com.android.server.wifi;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -64,6 +67,8 @@ public class WakeupControllerTest {
@Mock private WifiConfigManager mWifiConfigManager;
@Mock private FrameworkFacade mFrameworkFacade;
@Mock private WifiSettingsStore mWifiSettingsStore;
+ @Mock private WifiWakeMetrics mWifiWakeMetrics;
+ @Mock private WifiController mWifiController;
private TestLooper mLooper;
private WakeupController mWakeupController;
@@ -78,6 +83,8 @@ public class WakeupControllerTest {
when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner);
when(mWifiInjector.getWifiSettingsStore()).thenReturn(mWifiSettingsStore);
+ when(mWifiInjector.getWifiController()).thenReturn(mWifiController);
+ when(mWifiSettingsStore.handleWifiToggled(anyBoolean())).thenReturn(true);
mLooper = new TestLooper();
@@ -109,6 +116,7 @@ public class WakeupControllerTest {
mWakeupOnboarding,
mWifiConfigManager,
mWifiConfigStore,
+ mWifiWakeMetrics,
mWifiInjector,
mFrameworkFacade);
@@ -190,6 +198,7 @@ public class WakeupControllerTest {
initializeWakeupController(true /* enabled */);
mWakeupController.start();
verify(mWakeupLock).initialize(any());
+ verify(mWifiWakeMetrics).recordStartEvent(anyInt());
}
/**
@@ -200,6 +209,7 @@ public class WakeupControllerTest {
initializeWakeupController(false /* enabled */);
mWakeupController.start();
verify(mWakeupLock, never()).initialize(any());
+ verify(mWifiWakeMetrics, never()).recordStartEvent(anyInt());
}
/**
@@ -208,14 +218,17 @@ public class WakeupControllerTest {
@Test
public void startDoesNotInitializeWakeupLockIfAlreadyActive() {
initializeWakeupController(true /* enabled */);
- InOrder inOrder = Mockito.inOrder(mWakeupLock);
+ InOrder lockInOrder = Mockito.inOrder(mWakeupLock);
+ InOrder metricsInOrder = Mockito.inOrder(mWifiWakeMetrics);
mWakeupController.start();
- inOrder.verify(mWakeupLock).initialize(any());
+ lockInOrder.verify(mWakeupLock).initialize(any());
+ metricsInOrder.verify(mWifiWakeMetrics).recordStartEvent(anyInt());
mWakeupController.stop();
mWakeupController.start();
- inOrder.verify(mWakeupLock, never()).initialize(any());
+ lockInOrder.verify(mWakeupLock, never()).initialize(any());
+ metricsInOrder.verify(mWifiWakeMetrics, never()).recordStartEvent(anyInt());
}
/**
@@ -248,15 +261,20 @@ public class WakeupControllerTest {
@Test
public void resetSetsActiveToFalse() {
initializeWakeupController(true /* enabled */);
- InOrder inOrder = Mockito.inOrder(mWakeupLock);
+ InOrder lockInOrder = Mockito.inOrder(mWakeupLock);
+ InOrder metricsInOrder = Mockito.inOrder(mWifiWakeMetrics);
mWakeupController.start();
- inOrder.verify(mWakeupLock).initialize(any());
+ lockInOrder.verify(mWakeupLock).initialize(any());
+ metricsInOrder.verify(mWifiWakeMetrics).recordStartEvent(anyInt());
mWakeupController.stop();
mWakeupController.reset();
+ metricsInOrder.verify(mWifiWakeMetrics).recordResetEvent(0 /* numScans */);
+
mWakeupController.start();
- inOrder.verify(mWakeupLock).initialize(any());
+ lockInOrder.verify(mWakeupLock).initialize(any());
+ metricsInOrder.verify(mWifiWakeMetrics).recordStartEvent(anyInt());
}
/**
@@ -290,6 +308,7 @@ public class WakeupControllerTest {
initializeWakeupController(true /* enabled */);
mWakeupController.start();
verify(mWakeupLock).initialize(eq(expectedMatchInfos));
+ verify(mWifiWakeMetrics).recordStartEvent(expectedMatchInfos.size());
}
/**
@@ -314,6 +333,30 @@ public class WakeupControllerTest {
}
/**
+ * Verify that WifiWakeMetrics logs the unlock event when the WakeupLock is emptied.
+ */
+ @Test
+ public void recordMetricsWhenWakeupLockIsEmptied() {
+ initializeWakeupController(true /* enabled */);
+ mWakeupController.start();
+
+ // Simulates emptying the lock: first returns false then returns true
+ when(mWakeupLock.isEmpty()).thenReturn(false).thenReturn(true);
+
+ ArgumentCaptor<WifiScanner.ScanListener> scanListenerArgumentCaptor =
+ ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
+
+ verify(mWifiScanner).registerScanListener(scanListenerArgumentCaptor.capture());
+ WifiScanner.ScanListener scanListener = scanListenerArgumentCaptor.getValue();
+
+ // incoming scan results
+ scanListener.onResults(mTestScanDatas);
+
+ verify(mWakeupLock, times(2)).isEmpty();
+ verify(mWifiWakeMetrics).recordUnlockEvent(1 /* numScans */);
+ }
+
+ /**
* Verify that the controller searches for viable networks during onResults when WakeupLock is
* empty.
*/
@@ -388,6 +431,7 @@ public class WakeupControllerTest {
verify(mWakeupEvaluator).findViableNetwork(any(), any());
verify(mWifiSettingsStore).handleWifiToggled(true /* wifiEnabled */);
+ verify(mWifiWakeMetrics).recordWakeupEvent(1 /* numScans */);
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiWakeMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiWakeMetricsTest.java
new file mode 100644
index 000000000..37a658976
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/WifiWakeMetricsTest.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+
+import com.android.server.wifi.nano.WifiMetricsProto.WifiWakeStats;
+
+import org.junit.Before;
+import org.junit.Test;
+
+
+public class WifiWakeMetricsTest {
+
+ private WifiWakeMetrics mWifiWakeMetrics;
+
+ @Before
+ public void setUp() {
+ mWifiWakeMetrics = new WifiWakeMetrics();
+ }
+
+ @Test
+ public void buildsEmptyProto() {
+ WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto();
+ assertNotNull(wifiWakeStats);
+ assertEquals(wifiWakeStats.numSessions, 0);
+ assertEquals(wifiWakeStats.sessions.length, 0);
+ }
+
+ @Test
+ public void buildsMultiSessionProto_fewerThanMax() {
+ mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */);
+ mWifiWakeMetrics.recordResetEvent(0 /* numScans */);
+
+ mWifiWakeMetrics.recordStartEvent(1 /* numNetworks */);
+ mWifiWakeMetrics.recordResetEvent(0 /* numScans */);
+
+ mWifiWakeMetrics.recordStartEvent(2 /* numNetworks */);
+ mWifiWakeMetrics.recordResetEvent(0 /* numScans */);
+
+ WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto();
+ assertNotNull(wifiWakeStats);
+ assertEquals(wifiWakeStats.numSessions, 3);
+ assertEquals(wifiWakeStats.sessions.length, 3);
+ }
+
+ @Test
+ public void buildsMultiSessionProto_greaterThanMax() {
+ int numSessions = WifiWakeMetrics.MAX_RECORDED_SESSIONS + 1;
+ for (int i = 0; i < numSessions; i++) {
+ mWifiWakeMetrics.recordStartEvent(i);
+ mWifiWakeMetrics.recordResetEvent(i);
+ }
+
+ WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto();
+ assertNotNull(wifiWakeStats);
+ assertEquals(wifiWakeStats.numSessions, numSessions);
+ assertEquals(wifiWakeStats.sessions.length, WifiWakeMetrics.MAX_RECORDED_SESSIONS);
+
+ // ensure that the first (not last) MAX_RECORDED_SESSIONS are recorded
+ for (int i = 0; i < WifiWakeMetrics.MAX_RECORDED_SESSIONS; i++) {
+ WifiWakeStats.Session session = wifiWakeStats.sessions[i];
+ assertNotNull(session);
+ assertEquals(session.lockedNetworksAtStart, i);
+ }
+ }
+
+ @Test
+ public void buildProtoDoesNotIncludeCurrentSession() {
+ mWifiWakeMetrics.recordStartEvent(1 /* numNetworks */);
+ mWifiWakeMetrics.recordResetEvent(0 /* numScans */);
+
+ mWifiWakeMetrics.recordStartEvent(2 /* numNetworks */);
+
+ WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto();
+ assertNotNull(wifiWakeStats);
+ assertEquals(wifiWakeStats.numSessions, 1);
+ assertEquals(wifiWakeStats.sessions.length, 1);
+ assertEquals(wifiWakeStats.sessions[0].lockedNetworksAtStart, 1);
+ }
+
+ @Test
+ public void ignoresEventsIfStartNotCalled() {
+ mWifiWakeMetrics.recordUnlockEvent(1 /* numScans */);
+ mWifiWakeMetrics.recordWakeupEvent(1 /* numScans */);
+ mWifiWakeMetrics.recordResetEvent(1 /* numScans */);
+
+ WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto();
+ assertNotNull(wifiWakeStats);
+ assertEquals(wifiWakeStats.numSessions, 0);
+ assertEquals(wifiWakeStats.sessions.length, 0);
+ }
+
+ @Test
+ public void ignoresEventsAfterResetAndBeforeStartCalled() {
+ mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */);
+ mWifiWakeMetrics.recordWakeupEvent(1 /* numScans */);
+ mWifiWakeMetrics.recordResetEvent(1 /* numScans */);
+
+ mWifiWakeMetrics.recordWakeupEvent(10 /* numScans */);
+
+ // verify only 1 session
+ WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto();
+ assertNotNull(wifiWakeStats);
+ assertEquals(wifiWakeStats.numSessions, 1);
+ assertEquals(wifiWakeStats.sessions.length, 1);
+
+ // verify it didn't overwrite session
+ WifiWakeStats.Session session = wifiWakeStats.sessions[0];
+ assertNotNull(session.wakeupEvent);
+ assertEquals(session.wakeupEvent.elapsedScans, 1);
+ }
+
+ @Test
+ public void clearRemovesSessions() {
+ mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */);
+ mWifiWakeMetrics.recordResetEvent(0 /* numScans */);
+
+ mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */);
+ mWifiWakeMetrics.recordResetEvent(0 /* numScans */);
+
+ mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */);
+ mWifiWakeMetrics.recordResetEvent(0 /* numScans */);
+
+ // verify sessions
+ WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto();
+ assertNotNull(wifiWakeStats);
+ assertEquals(wifiWakeStats.numSessions, 3);
+ assertEquals(wifiWakeStats.sessions.length, 3);
+
+ mWifiWakeMetrics.clear();
+ wifiWakeStats = mWifiWakeMetrics.buildProto();
+ assertNotNull(wifiWakeStats);
+ assertEquals(wifiWakeStats.numSessions, 0);
+ assertEquals(wifiWakeStats.sessions.length, 0);
+ }
+
+ @Test
+ public void clearDoesNotInterruptCurrentSession() {
+ mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */);
+ mWifiWakeMetrics.recordResetEvent(0 /* numScans */);
+ mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */);
+ mWifiWakeMetrics.recordResetEvent(0 /* numScans */);
+
+ mWifiWakeMetrics.recordStartEvent(1 /* numNetworks */);
+ mWifiWakeMetrics.clear();
+ mWifiWakeMetrics.recordResetEvent(0 /* numScans */);
+
+ // keeps the current session
+ WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto();
+ assertNotNull(wifiWakeStats);
+ assertEquals(wifiWakeStats.numSessions, 1);
+ assertEquals(wifiWakeStats.sessions.length, 1);
+ }
+
+ @Test
+ public void session_buildsEmptyProto() {
+ WifiWakeMetrics.Session session =
+ new WifiWakeMetrics.Session(1 /* numNetworks */, 1000 /* timestamp */);
+
+ WifiWakeStats.Session sessionProto = session.buildProto();
+ assertNotNull(sessionProto);
+ assertEquals(sessionProto.lockedNetworksAtStart, 1);
+ assertEquals(sessionProto.startTimeMillis, 1000);
+ assertNull(sessionProto.unlockEvent);
+ assertNull(sessionProto.wakeupEvent);
+ assertNull(sessionProto.resetEvent);
+ }
+
+ @Test
+ public void session_recordsEvents() {
+ WifiWakeMetrics.Session session =
+ new WifiWakeMetrics.Session(1 /* numNetworks */, 1000 /* timestamp */);
+
+ session.recordUnlockEvent(1 /* numScans */, 1100 /* timestamp */);
+ assertNotNull(session.mUnlockEvent);
+ assertEquals(session.mUnlockEvent.mNumScans, 1);
+ assertEquals(session.mUnlockEvent.mElapsedTime, 100);
+
+ session.recordWakeupEvent(2 /* numScans */, 1200 /* timestamp */);
+ assertNotNull(session.mWakeupEvent);
+ assertEquals(session.mWakeupEvent.mNumScans, 2);
+ assertEquals(session.mWakeupEvent.mElapsedTime, 200);
+
+ session.recordResetEvent(3 /* numScans */, 1300 /* timestamp */);
+ assertNotNull(session.mResetEvent);
+ assertEquals(session.mResetEvent.mNumScans, 3);
+ assertEquals(session.mResetEvent.mElapsedTime, 300);
+ }
+
+ @Test
+ public void session_buildProto() {
+ WifiWakeMetrics.Session session =
+ new WifiWakeMetrics.Session(1 /* numNetworks */, 1000 /* timestamp */);
+
+ session.recordUnlockEvent(1 /* numScans */, 1100 /* timestamp */);
+ session.recordWakeupEvent(2 /* numScans */, 1200 /* timestamp */);
+ session.recordResetEvent(3 /* numScans */, 1300 /* timestamp */);
+
+ WifiWakeStats.Session sessionProto = session.buildProto();
+ assertNotNull(sessionProto);
+ assertEquals(sessionProto.lockedNetworksAtStart, 1);
+ assertEquals(sessionProto.startTimeMillis, 1000);
+
+ verifyEventProto(sessionProto.unlockEvent, 1, 100);
+ verifyEventProto(sessionProto.wakeupEvent, 2, 200);
+ verifyEventProto(sessionProto.resetEvent, 3, 300);
+ }
+
+ @Test
+ public void session_ignoresRepeatedEvents() {
+ WifiWakeMetrics.Session session =
+ new WifiWakeMetrics.Session(1 /* numNetworks */, 1000 /* timestamp */);
+
+ session.recordResetEvent(1 /* numScans */, 1100 /* timestamp */);
+ assertNotNull(session.mResetEvent);
+ assertEquals(session.mResetEvent.mNumScans, 1);
+ assertEquals(session.mResetEvent.mElapsedTime, 100);
+
+ session.recordResetEvent(2 /* numScans */, 1200 /* timestamp */);
+ assertEquals(session.mResetEvent.mNumScans, 1);
+ assertEquals(session.mResetEvent.mElapsedTime, 100);
+ }
+
+ @Test
+ public void event_buildsProto() {
+ WifiWakeMetrics.Event event =
+ new WifiWakeMetrics.Event(1 /* numScans */, 1000 /* elapsedTime */);
+
+ verifyEventProto(event.buildProto(), 1, 1000);
+ }
+
+ private void verifyEventProto(WifiWakeStats.Session.Event event, int scans, int elapsedTime) {
+ assertNotNull(event);
+ assertEquals(event.elapsedScans, scans);
+ assertEquals(event.elapsedTimeMillis, elapsedTime);
+ }
+}