diff options
4 files changed, 175 insertions, 62 deletions
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 73f08c68fdb2..3f59f896a82e 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1305,4 +1305,44 @@ <string name="delete_blob_text">Delete shared data</string> <!-- Shared data: confirmation dialog text when attempting delete some shared data [CHAR LIMIT=NONE] --> <string name="delete_blob_confirmation_text">Are you sure you want to delete this shared data?</string> + + <!-- Summary for add user entry in the choice dialog [CHAR LIMIT=none] --> + <string name="user_add_user_item_summary">Users have their own apps and content</string> + <!-- Summary for add restricted profile entry in the choice dialog [CHAR LIMIT=none] --> + <string name="user_add_profile_item_summary">You can restrict access to apps and content from your account</string> + <!-- Button text for adding a regular user [CHAR LIMIT=25] --> + <string name="user_add_user_item_title">User</string> + <!-- Button text for adding a restricted profile [CHAR LIMIT=25] --> + <string name="user_add_profile_item_title">Restricted profile</string> + <!-- Title for add user confirmation dialog [CHAR LIMIT=30] --> + <string name="user_add_user_title">Add new user?</string> + <!-- Message for add user confirmation dialog - long version. [CHAR LIMIT=none] --> + <string name="user_add_user_message_long">You can share this device with other people by creating additional users. Each user has their own space, which they can customize with apps, wallpaper, and so on. Users can also adjust device settings like Wi\u2011Fi that affect everyone.\n\nWhen you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. Accessibility settings and services may not transfer to the new user.</string> + <!-- Message for add user confirmation dialog - short version. [CHAR LIMIT=none] --> + <string name="user_add_user_message_short">When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. </string> + <!-- Title of dialog to setup a new user [CHAR LIMIT=30] --> + <string name="user_setup_dialog_title">Set up user now?</string> + <!-- Message in dialog to setup a new user after creation [CHAR LIMIT=none] --> + <string name="user_setup_dialog_message">Make sure the person is available to take the device and set up their space</string> + <!-- Message in dialog to setup a new restricted profile after creation [CHAR LIMIT=none] --> + <string name="user_setup_profile_dialog_message">Set up profile now?</string> + <!-- Button text to setup the new user now [CHAR LIMIT=25] --> + <string name="user_setup_button_setup_now">Set up now</string> + <!-- Button text to setup the new user later [CHAR LIMIT=25] --> + <string name="user_setup_button_setup_later">Not now</string> + <!-- Title for add user type dialog [CHAR LIMIT=45] --> + <string name="user_add_user_type_title">Add</string> + <!-- User details new user name [CHAR LIMIT=30] --> + <string name="user_new_user_name">New user</string> + <!-- User details new restricted profile name [CHAR LIMIT=30] --> + <string name="user_new_profile_name">New profile</string> + <!-- Text shown for title of user info setting [CHAR LIMIT=20]--> + <string name="user_info_settings_title">User info</string> + <!-- Text shown for title of profile info setting [CHAR LIMIT=20]--> + <string name="profile_info_settings_title">Profile info</string> + <!-- User settings warning that restricted profile needs a screen lock [CHAR LIMIT=NONE] --> + <string name="user_need_lock_message">Before you can create a restricted profile, you\u2019ll need to set up a screen lock to protect your apps and personal data.</string> + <!-- User settings dialog button to set screen lock [CHAR LIMIT=25] --> + <string name="user_set_lock_button">Set lock</string> + </resources> 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. */ |