diff options
author | Robert Horvath <robhor@google.com> | 2020-03-24 09:00:55 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-03-24 09:00:55 +0000 |
commit | f3107f8405c44bdcd3c7612da50050f9717b2d4b (patch) | |
tree | 77678d94b6c25c477d0f063c4d542ae0d6a96fbe | |
parent | eb95d1deeea2e078106ea4b0edffd7aeb6e4bb9b (diff) | |
parent | ac423f3a5152e78bfc52face1a400245aef10de8 (diff) |
Merge "Deterministic PowerManagerServiceTest" into rvc-dev am: ac423f3a51
Change-Id: I7b57b193984759d447a160db3f37f7eaae6bcaf5
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. */ |