summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Horvath <robhor@google.com>2020-03-23 14:46:25 +0100
committerRobert Horvath <robhor@google.com>2020-03-23 16:37:13 +0100
commite75cf0ac168039c6a15edf5543d7fbd7578432bf (patch)
tree014d9e6608368cb090ea2d4eb7821b1bff3d6c25
parent0a9aff3ac39cc1aa9641eabab0ad681a2ad1ebd7 (diff)
Deterministic PowerManagerServiceTest
To make PowerManagerServiceTest deterministic, remove dependency on real time clock by mocking it out. Use TestLooper, which allows making Handler behaviour deterministic as well. Test: atest PowerManagerServiceTest Bug: 152193749 Change-Id: I4d9cd686ac672261bbb038249c0358e451b58710
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java104
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java57
-rw-r--r--tests/utils/testutils/java/android/os/test/TestLooper.java36
3 files changed, 135 insertions, 62 deletions
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b1c40cc07ba4..5025835b5a59 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -241,7 +241,7 @@ public final class PowerManagerService extends SystemService
private final Context mContext;
private final ServiceThread mHandlerThread;
- private final PowerManagerHandler mHandler;
+ private final Handler mHandler;
private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
private final BatterySaverController mBatterySaverController;
private final BatterySaverPolicy mBatterySaverPolicy;
@@ -252,6 +252,7 @@ public final class PowerManagerService extends SystemService
private final LocalService mLocalService;
private final NativeWrapper mNativeWrapper;
private final SystemPropertiesWrapper mSystemProperties;
+ private final Clock mClock;
private final Injector mInjector;
private LightsManager mLightsManager;
@@ -597,7 +598,7 @@ public final class PowerManagerService extends SystemService
@Override
public void onForegroundProfileSwitch(@UserIdInt int newProfileId) throws RemoteException {
- final long now = SystemClock.uptimeMillis();
+ final long now = mClock.uptimeMillis();
synchronized (mLock) {
mForegroundProfile = newProfileId;
maybeUpdateForegroundProfileLastActivityLocked(now);
@@ -625,11 +626,11 @@ public final class PowerManagerService extends SystemService
// Whether profile has been locked last time it timed out.
boolean mLockingNotified;
- public ProfilePowerState(@UserIdInt int userId, long screenOffTimeout) {
+ public ProfilePowerState(@UserIdInt int userId, long screenOffTimeout, long now) {
mUserId = userId;
mScreenOffTimeout = screenOffTimeout;
// Not accurate but at least won't cause immediate locking of the profile.
- mLastUserActivityTime = SystemClock.uptimeMillis();
+ mLastUserActivityTime = now;
}
}
@@ -756,6 +757,15 @@ public final class PowerManagerService extends SystemService
}
}
+ /** Functional interface for providing time. */
+ @VisibleForTesting
+ interface Clock {
+ /**
+ * Returns current time in milliseconds since boot, not counting time spent in deep sleep.
+ */
+ long uptimeMillis();
+ }
+
@VisibleForTesting
static class Injector {
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
@@ -822,6 +832,17 @@ public final class PowerManagerService extends SystemService
};
}
+ Clock createClock() {
+ return SystemClock::uptimeMillis;
+ }
+
+ /**
+ * Handler for asynchronous operations performed by the power manager.
+ */
+ Handler createHandler(Looper looper, Handler.Callback callback) {
+ return new Handler(looper, callback, true /*async*/);
+ }
+
void invalidateIsInteractiveCaches() {
PowerManager.invalidateIsInteractiveCaches();
}
@@ -853,12 +874,14 @@ public final class PowerManagerService extends SystemService
mLocalService = new LocalService();
mNativeWrapper = injector.createNativeWrapper();
mSystemProperties = injector.createSystemPropertiesWrapper();
+ mClock = injector.createClock();
mInjector = injector;
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
mHandlerThread.start();
- mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
+ mHandler = injector.createHandler(mHandlerThread.getLooper(),
+ new PowerManagerHandlerCallback());
mConstants = new Constants(mHandler);
mAmbientDisplayConfiguration = mInjector.createAmbientDisplayConfiguration(context);
mAmbientDisplaySuppressionController =
@@ -1002,7 +1025,7 @@ public final class PowerManagerService extends SystemService
incrementBootCount();
} else if (phase == PHASE_BOOT_COMPLETED) {
- final long now = SystemClock.uptimeMillis();
+ final long now = mClock.uptimeMillis();
mBootCompleted = true;
mDirty |= DIRTY_BOOT_COMPLETED;
@@ -1011,7 +1034,7 @@ public final class PowerManagerService extends SystemService
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
if (sQuiescent) {
- goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
+ goToSleepNoUpdateLocked(mClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_QUIESCENT,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
}
@@ -1354,7 +1377,7 @@ public final class PowerManagerService extends SystemService
opPackageName = wakeLock.mPackageName;
opUid = wakeLock.mOwnerUid;
}
- wakeUpNoUpdateLocked(SystemClock.uptimeMillis(),
+ wakeUpNoUpdateLocked(mClock.uptimeMillis(),
PowerManager.WAKE_REASON_APPLICATION, wakeLock.mTag,
opUid, opPackageName, opUid);
}
@@ -1420,7 +1443,7 @@ public final class PowerManagerService extends SystemService
private void applyWakeLockFlagsOnReleaseLocked(WakeLock wakeLock) {
if ((wakeLock.mFlags & PowerManager.ON_AFTER_RELEASE) != 0
&& isScreenLock(wakeLock)) {
- userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
+ userActivityNoUpdateLocked(mClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_OTHER,
PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,
wakeLock.mOwnerUid);
@@ -1484,7 +1507,7 @@ public final class PowerManagerService extends SystemService
}
private void restartNofifyLongTimerLocked(WakeLock wakeLock) {
- wakeLock.mAcquireTime = SystemClock.uptimeMillis();
+ wakeLock.mAcquireTime = mClock.uptimeMillis();
if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
== PowerManager.PARTIAL_WAKE_LOCK && mNotifyLongScheduled == 0) {
enqueueNotifyLongMsgLocked(wakeLock.mAcquireTime + MIN_LONG_WAKE_CHECK_INTERVAL);
@@ -1569,7 +1592,7 @@ public final class PowerManagerService extends SystemService
private void onUserAttention() {
synchronized (mLock) {
- if (userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
+ if (userActivityNoUpdateLocked(mClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_ATTENTION, 0 /* flags */,
Process.SYSTEM_UID)) {
updatePowerStateLocked();
@@ -1844,7 +1867,7 @@ public final class PowerManagerService extends SystemService
* had the system not been told the user was inactive.
*/
private void logSleepTimeoutRecapturedLocked() {
- final long now = SystemClock.uptimeMillis();
+ final long now = mClock.uptimeMillis();
final long savedWakeTimeMs = mOverriddenTimeout - now;
if (savedWakeTimeMs >= 0) {
EventLogTags.writePowerSoftSleepRequested(savedWakeTimeMs);
@@ -1867,7 +1890,7 @@ public final class PowerManagerService extends SystemService
}
if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0);
- final int latencyMs = (int) (SystemClock.uptimeMillis() - mLastWakeTime);
+ final int latencyMs = (int) (mClock.uptimeMillis() - mLastWakeTime);
if (latencyMs >= SCREEN_ON_LATENCY_WARNING_MS) {
Slog.w(TAG, "Screen on took " + latencyMs + " ms");
}
@@ -1903,7 +1926,7 @@ public final class PowerManagerService extends SystemService
// Phase 1: Update wakefulness.
// Loop because the wake lock and user activity computations are influenced
// by changes in wakefulness.
- final long now = SystemClock.uptimeMillis();
+ final long now = mClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
@@ -1996,7 +2019,7 @@ public final class PowerManagerService extends SystemService
// and it shuts off right away.
// Some devices also wake the device when plugged or unplugged because
// they don't have a charging LED.
- final long now = SystemClock.uptimeMillis();
+ final long now = mClock.uptimeMillis();
if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
dockedOnWirelessCharger)) {
wakeUpNoUpdateLocked(now, PowerManager.WAKE_REASON_PLUGGED_IN,
@@ -2204,7 +2227,7 @@ public final class PowerManagerService extends SystemService
void checkForLongWakeLocks() {
synchronized (mLock) {
- final long now = SystemClock.uptimeMillis();
+ final long now = mClock.uptimeMillis();
mNotifyLongDispatched = now;
final long when = now - MIN_LONG_WAKE_CHECK_INTERVAL;
long nextCheckTime = Long.MAX_VALUE;
@@ -2533,7 +2556,7 @@ public final class PowerManagerService extends SystemService
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
}
- final long time = SystemClock.uptimeMillis();
+ final long time = mClock.uptimeMillis();
if (isAttentiveTimeoutExpired(time)) {
changed = goToSleepNoUpdateLocked(time, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
@@ -2568,7 +2591,7 @@ public final class PowerManagerService extends SystemService
return false;
}
- long now = SystemClock.uptimeMillis();
+ long now = mClock.uptimeMillis();
if (isAttentiveTimeoutExpired(now)) {
return !isBeingKeptFromInattentiveSleepLocked();
} else {
@@ -2699,7 +2722,7 @@ public final class PowerManagerService extends SystemService
}
// Determine whether the dream should continue.
- long now = SystemClock.uptimeMillis();
+ long now = mClock.uptimeMillis();
if (wakefulness == WAKEFULNESS_DREAMING) {
if (isDreaming && canDreamLocked()) {
if (mDreamsBatteryLevelDrainCutoffConfig >= 0
@@ -2881,7 +2904,7 @@ public final class PowerManagerService extends SystemService
private void updateScreenBrightnessBoostLocked(int dirty) {
if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {
if (mScreenBrightnessBoostInProgress) {
- final long now = SystemClock.uptimeMillis();
+ final long now = mClock.uptimeMillis();
mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
if (mLastScreenBrightnessBoostTime > mLastSleepTime) {
final long boostTimeout = mLastScreenBrightnessBoostTime +
@@ -2968,7 +2991,7 @@ public final class PowerManagerService extends SystemService
synchronized (mLock) {
mProximityPositive = false;
mDirty |= DIRTY_PROXIMITY_POSITIVE;
- userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
+ userActivityNoUpdateLocked(mClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
}
@@ -3289,7 +3312,8 @@ public final class PowerManagerService extends SystemService
if (profile != null) {
profile.mScreenOffTimeout = timeMs;
} else {
- mProfilePowerState.put(userId, new ProfilePowerState(userId, timeMs));
+ mProfilePowerState.put(userId, new ProfilePowerState(userId, timeMs,
+ mClock.uptimeMillis()));
// We need to recalculate wake locks for the new profile state.
mDirty |= DIRTY_WAKE_LOCKS;
}
@@ -3646,14 +3670,14 @@ public final class PowerManagerService extends SystemService
@VisibleForTesting
boolean wasDeviceIdleForInternal(long ms) {
synchronized (mLock) {
- return mLastUserActivityTime + ms < SystemClock.uptimeMillis();
+ return mLastUserActivityTime + ms < mClock.uptimeMillis();
}
}
@VisibleForTesting
void onUserActivity() {
synchronized (mLock) {
- mLastUserActivityTime = SystemClock.uptimeMillis();
+ mLastUserActivityTime = mClock.uptimeMillis();
}
}
@@ -3662,7 +3686,7 @@ public final class PowerManagerService extends SystemService
synchronized (mLock) {
mForceSuspendActive = true;
// Place the system in an non-interactive state
- goToSleepInternal(SystemClock.uptimeMillis(),
+ goToSleepInternal(mClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_FORCE_SUSPEND,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, uid);
@@ -3777,21 +3801,21 @@ public final class PowerManagerService extends SystemService
if (mNotifyLongScheduled == 0) {
pw.print("(none)");
} else {
- TimeUtils.formatDuration(mNotifyLongScheduled, SystemClock.uptimeMillis(), pw);
+ TimeUtils.formatDuration(mNotifyLongScheduled, mClock.uptimeMillis(), pw);
}
pw.println();
pw.print(" mNotifyLongDispatched=");
if (mNotifyLongDispatched == 0) {
pw.print("(none)");
} else {
- TimeUtils.formatDuration(mNotifyLongDispatched, SystemClock.uptimeMillis(), pw);
+ TimeUtils.formatDuration(mNotifyLongDispatched, mClock.uptimeMillis(), pw);
}
pw.println();
pw.print(" mNotifyLongNextCheck=");
if (mNotifyLongNextCheck == 0) {
pw.print("(none)");
} else {
- TimeUtils.formatDuration(mNotifyLongNextCheck, SystemClock.uptimeMillis(), pw);
+ TimeUtils.formatDuration(mNotifyLongNextCheck, mClock.uptimeMillis(), pw);
}
pw.println();
pw.println(" mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary));
@@ -4389,15 +4413,11 @@ public final class PowerManagerService extends SystemService
};
/**
- * Handler for asynchronous operations performed by the power manager.
+ * Callback for asynchronous operations performed by the power manager.
*/
- private final class PowerManagerHandler extends Handler {
- public PowerManagerHandler(Looper looper) {
- super(looper, null, true /*async*/);
- }
-
+ private final class PowerManagerHandlerCallback implements Handler.Callback {
@Override
- public void handleMessage(Message msg) {
+ public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_USER_ACTIVITY_TIMEOUT:
handleUserActivityTimeout();
@@ -4415,6 +4435,8 @@ public final class PowerManagerService extends SystemService
handleAttentiveTimeout();
break;
}
+
+ return true;
}
}
@@ -4505,7 +4527,7 @@ public final class PowerManagerService extends SystemService
}
if (mNotifiedAcquired) {
sb.append(" ACQ=");
- TimeUtils.formatDuration(mAcquireTime-SystemClock.uptimeMillis(), sb);
+ TimeUtils.formatDuration(mAcquireTime-mClock.uptimeMillis(), sb);
}
if (mNotifiedLong) {
sb.append(" LONG");
@@ -4817,7 +4839,7 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public void userActivity(long eventTime, int event, int flags) {
- final long now = SystemClock.uptimeMillis();
+ final long now = mClock.uptimeMillis();
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED
&& mContext.checkCallingOrSelfPermission(
@@ -4855,7 +4877,7 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public void wakeUp(long eventTime, @WakeReason int reason, String details,
String opPackageName) {
- if (eventTime > SystemClock.uptimeMillis()) {
+ if (eventTime > mClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -4873,7 +4895,7 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public void goToSleep(long eventTime, int reason, int flags) {
- if (eventTime > SystemClock.uptimeMillis()) {
+ if (eventTime > mClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -4891,7 +4913,7 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public void nap(long eventTime) {
- if (eventTime > SystemClock.uptimeMillis()) {
+ if (eventTime > mClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -5286,7 +5308,7 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public void boostScreenBrightness(long eventTime) {
- if (eventTime > SystemClock.uptimeMillis()) {
+ if (eventTime > mClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index bb5147132433..d244e687c8b8 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -61,8 +61,8 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerSaveState;
-import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.test.TestLooper;
import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
import android.test.mock.MockContentResolver;
@@ -84,6 +84,7 @@ import com.android.server.power.batterysaver.BatterySaverController;
import com.android.server.power.batterysaver.BatterySaverPolicy;
import com.android.server.power.batterysaver.BatterySaverStateMachine;
import com.android.server.power.batterysaver.BatterySavingStats;
+import com.android.server.testutils.OffsettableClock;
import org.junit.After;
import org.junit.Before;
@@ -132,6 +133,8 @@ public class PowerManagerServiceTest {
private BatteryReceiver mBatteryReceiver;
private UserSwitchedReceiver mUserSwitchedReceiver;
private Resources mResourcesSpy;
+ private OffsettableClock mClock;
+ private TestLooper mTestLooper;
private class IntentFilterMatcher implements ArgumentMatcher<IntentFilter> {
private final IntentFilter mFilter;
@@ -189,6 +192,9 @@ public class PowerManagerServiceTest {
Settings.Global.putInt(mContextSpy.getContentResolver(),
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
+
+ mClock = new OffsettableClock.Stopped();
+ mTestLooper = new TestLooper(mClock::now);
}
private PowerManagerService createService() {
@@ -250,6 +256,16 @@ public class PowerManagerServiceTest {
}
@Override
+ PowerManagerService.Clock createClock() {
+ return () -> mClock.now();
+ }
+
+ @Override
+ Handler createHandler(Looper looper, Handler.Callback callback) {
+ return new Handler(mTestLooper.getLooper(), callback);
+ }
+
+ @Override
void invalidateIsInteractiveCaches() {
// Avoids an SELinux failure.
}
@@ -297,21 +313,21 @@ public class PowerManagerServiceTest {
}
private void forceSleep() {
- mService.getBinderServiceInstance().goToSleep(SystemClock.uptimeMillis(),
+ mService.getBinderServiceInstance().goToSleep(mClock.now(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
}
private void forceDream() {
- mService.getBinderServiceInstance().nap(SystemClock.uptimeMillis());
+ mService.getBinderServiceInstance().nap(mClock.now());
}
private void forceAwake() {
- mService.getBinderServiceInstance().wakeUp(SystemClock.uptimeMillis(),
+ mService.getBinderServiceInstance().wakeUp(mClock.now(),
PowerManager.WAKE_REASON_UNKNOWN, "testing IPowerManager.wakeUp()", "pkg.name");
}
private void forceDozing() {
- mService.getBinderServiceInstance().goToSleep(SystemClock.uptimeMillis(),
+ mService.getBinderServiceInstance().goToSleep(mClock.now(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
}
@@ -341,6 +357,11 @@ public class PowerManagerServiceTest {
.thenReturn(minimumScreenOffTimeoutConfigMillis);
}
+ private void advanceTime(long timeMs) {
+ mClock.fastForward(timeMs);
+ mTestLooper.dispatchAll();
+ }
+
@Test
public void testUpdatePowerScreenPolicy_UpdateDisplayPowerRequest() {
createService();
@@ -403,7 +424,7 @@ public class PowerManagerServiceTest {
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
// Take a nap and verify.
- mService.getBinderServiceInstance().goToSleep(SystemClock.uptimeMillis(),
+ mService.getBinderServiceInstance().goToSleep(mClock.now(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
}
@@ -445,7 +466,7 @@ public class PowerManagerServiceTest {
createService();
startSystem();
forceSleep();
- mService.getBinderServiceInstance().wakeUp(SystemClock.uptimeMillis(),
+ mService.getBinderServiceInstance().wakeUp(mClock.now(),
PowerManager.WAKE_REASON_UNKNOWN, "testing IPowerManager.wakeUp()", "pkg.name");
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
}
@@ -540,7 +561,7 @@ public class PowerManagerServiceTest {
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
// Take a nap and verify.
- mService.getBinderServiceInstance().goToSleep(SystemClock.uptimeMillis(),
+ mService.getBinderServiceInstance().goToSleep(mClock.now(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
}
@@ -550,7 +571,7 @@ public class PowerManagerServiceTest {
int interval = 1000;
createService();
mService.onUserActivity();
- SystemClock.sleep(interval + 1 /* just a little more */);
+ advanceTime(interval + 1 /* just a little more */);
assertThat(mService.wasDeviceIdleForInternal(interval)).isTrue();
}
@@ -678,7 +699,7 @@ public class PowerManagerServiceTest {
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
null /* workSource */, null /* historyTag */);
when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
- mService.getBinderServiceInstance().goToSleep(SystemClock.uptimeMillis(),
+ mService.getBinderServiceInstance().goToSleep(mClock.now(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
assertFalse(isAcquired[0]);
@@ -718,16 +739,16 @@ public class PowerManagerServiceTest {
createService();
startSystem();
- mService.getBinderServiceInstance().userActivity(SystemClock.uptimeMillis(),
+ mService.getBinderServiceInstance().userActivity(mClock.now(),
PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
verify(mInattentiveSleepWarningControllerMock, never()).show();
- SystemClock.sleep(150);
+ advanceTime(150);
verify(mInattentiveSleepWarningControllerMock, times(1)).show();
verify(mInattentiveSleepWarningControllerMock, never()).dismiss(anyBoolean());
when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(true);
- mService.getBinderServiceInstance().userActivity(SystemClock.uptimeMillis(),
+ mService.getBinderServiceInstance().userActivity(mClock.now(),
PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
verify(mInattentiveSleepWarningControllerMock, times(1)).dismiss(true);
}
@@ -740,10 +761,10 @@ public class PowerManagerServiceTest {
createService();
startSystem();
- SystemClock.sleep(50);
+ advanceTime(50);
verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).show();
when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(true);
- SystemClock.sleep(70);
+ advanceTime(70);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
forceAwake();
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
@@ -764,7 +785,7 @@ public class PowerManagerServiceTest {
setAttentiveTimeout(5);
createService();
startSystem();
- SystemClock.sleep(20);
+ advanceTime(20);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
}
@@ -772,7 +793,7 @@ public class PowerManagerServiceTest {
public void testInattentiveSleep_goesToSleepWithWakeLock() throws Exception {
final String pkg = mContextSpy.getOpPackageName();
final Binder token = new Binder();
- final String tag = "sleep_testWithWakeLock";
+ final String tag = "testInattentiveSleep_goesToSleepWithWakeLock";
setMinimumScreenOffTimeoutConfig(5);
setAttentiveTimeout(30);
@@ -783,7 +804,7 @@ public class PowerManagerServiceTest {
PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
null /* workSource */, null /* historyTag */);
- SystemClock.sleep(60);
+ advanceTime(60);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
}
diff --git a/tests/utils/testutils/java/android/os/test/TestLooper.java b/tests/utils/testutils/java/android/os/test/TestLooper.java
index 01bd47b9c608..a826646f69f3 100644
--- a/tests/utils/testutils/java/android/os/test/TestLooper.java
+++ b/tests/utils/testutils/java/android/os/test/TestLooper.java
@@ -48,6 +48,8 @@ public class TestLooper {
private static final Method MESSAGE_MARK_IN_USE_METHOD;
private static final String TAG = "TestLooper";
+ private final Clock mClock;
+
private AutoDispatchThread mAutoDispatchThread;
static {
@@ -69,8 +71,25 @@ public class TestLooper {
}
}
-
+ /**
+ * Creates a TestLooper and installs it as the looper for the current thread.
+ */
public TestLooper() {
+ this(SystemClock::uptimeMillis);
+ }
+
+ /**
+ * Creates a TestLooper with a custom clock and installs it as the looper for the current
+ * thread.
+ *
+ * Messages are dispatched when their {@link Message#when} is before or at {@link
+ * Clock#uptimeMillis()}.
+ * Use a custom clock with care. When using an offsettable clock like {@link
+ * com.android.server.testutils.OffsettableClock} be sure not to double offset messages by
+ * offsetting the clock and calling {@link #moveTimeForward(long)}. Instead, offset the clock
+ * and call {@link #dispatchAll()}.
+ */
+ public TestLooper(Clock clock) {
try {
mLooper = LOOPER_CONSTRUCTOR.newInstance(false);
@@ -80,6 +99,8 @@ public class TestLooper {
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new RuntimeException("Reflection error constructing or accessing looper", e);
}
+
+ mClock = clock;
}
public Looper getLooper() {
@@ -116,9 +137,13 @@ public class TestLooper {
}
}
+ private long currentTime() {
+ return mClock.uptimeMillis();
+ }
+
private Message messageQueueNext() {
try {
- long now = SystemClock.uptimeMillis();
+ long now = currentTime();
Message prevMsg = null;
Message msg = getMessageLinkedList();
@@ -157,7 +182,7 @@ public class TestLooper {
public synchronized boolean isIdle() {
Message messageList = getMessageLinkedList();
- return messageList != null && SystemClock.uptimeMillis() >= messageList.getWhen();
+ return messageList != null && currentTime() >= messageList.getWhen();
}
/**
@@ -187,6 +212,7 @@ public class TestLooper {
/**
* Dispatch all messages currently in the queue
* Will not fail if there are no messages pending
+ *
* @return the number of messages dispatched
*/
public synchronized int dispatchAll() {
@@ -198,6 +224,10 @@ public class TestLooper {
return count;
}
+ public interface Clock {
+ long uptimeMillis();
+ }
+
/**
* Thread used to dispatch messages when the main thread is blocked waiting for a response.
*/