From f4fa114cb88f49b5e3165280adfb343be0fe9d3d Mon Sep 17 00:00:00 2001 From: Philip Junker Date: Thu, 7 Oct 2021 18:06:34 +0200 Subject: [PATCH] Move logic from dreamDisplayGroupNoUpdateLocked into PowerGroup. Add onWakefulnessChangedCallback which is called whenever the wakefulness of a PowerGroup changes. Set the wakefulness for a new PowerGroup to WAKEFULNESS_AWAKE instead of the current global wakefulness. This way the newly added PowerGroup will not directly go to sleep if the device happens to be asleep. Introduce per power group lastWakeTime and lastSleepTime. Rename setGlobalWakefulnessLocked() to updateGlobalWakefulnessLocked(), getGlobalWakefulnessLocked() to recalculateGlobalWakefulnessLocked() and getWakefulnessLocked() to getGlobalWakefulnessLocked(). Rename dreamDisplayGroupNoUpdateLocked() to dreamPowerGroupLocked(). Rename sleepDisplayGroupNoUpdateLocked() to dozePowerGroupLocked(). Rename reallySleepDisplayGroupNoUpdateLocked() to sleepPowerGroupLocked(). Rename wakeDisplayGroupNoUpdateLocked() to wakePowerGroupLocked(). Test: atest FrameworksServicesTests:PowerManagerServiceTest Bug: 200653844 Change-Id: Ic90f3b0c116e8e9db7df730f1500c0e8b99fe677 --- core/java/android/os/PowerManager.java | 16 + .../com/android/server/power/PowerGroup.java | 157 ++++++- .../server/power/PowerManagerService.java | 431 ++++++++---------- .../android/server/power/PowerGroupTest.java | 129 ++++++ .../server/power/PowerManagerServiceTest.java | 164 ++++--- 5 files changed, 582 insertions(+), 315 deletions(-) create mode 100644 services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index d4a338bef02b0..e5a863110d838 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -44,6 +44,7 @@ import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.time.Duration; +import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicLong; @@ -703,6 +704,21 @@ public final class PowerManager { public long wakeTime; public @WakeReason int wakeReason; public long sleepDuration; + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof WakeData) { + final WakeData other = (WakeData) o; + return wakeTime == other.wakeTime && wakeReason == other.wakeReason + && sleepDuration == other.sleepDuration; + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(wakeTime, wakeReason, sleepDuration); + } } /** diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java index 9127484e89773..c1bfdf7a343f0 100644 --- a/services/core/java/com/android/server/power/PowerGroup.java +++ b/services/core/java/com/android/server/power/PowerGroup.java @@ -16,9 +16,16 @@ package com.android.server.power; +import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP; import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE; +import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING; +import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING; +import static android.os.PowerManagerInternal.isInteractive; import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; +import android.os.PowerManager; +import android.os.Trace; +import android.util.Slog; import android.view.Display; /** @@ -31,47 +38,66 @@ import android.view.Display; */ public class PowerGroup { private static final String TAG = PowerGroup.class.getSimpleName(); + private static final boolean DEBUG = false; private final DisplayPowerRequest mDisplayPowerRequest; + private final PowerGroupListener mWakefulnessListener; private final boolean mSupportsSandman; private final int mGroupId; - - // True if DisplayManagerService has applied all the latest display states that were requested - // for this group + /** True if DisplayManagerService has applied all the latest display states that were requested + * for this group. */ private boolean mReady; - // True if this group is in the process of powering on + /** True if this group is in the process of powering on */ private boolean mPoweringOn; - // True if this group is about to dream + /** True if this group is about to dream */ private boolean mIsSandmanSummoned; private int mUserActivitySummary; - // The current wakefulness of this group + /** The current wakefulness of this group */ private int mWakefulness; private int mWakeLockSummary; private long mLastPowerOnTime; private long mLastUserActivityTime; private long mLastUserActivityTimeNoChangeLights; + /** Timestamp (milliseconds since boot) of the last time the power group was awoken.*/ + private long mLastWakeTime; + /** Timestamp (milliseconds since boot) of the last time the power group was put to sleep. */ + private long mLastSleepTime; - PowerGroup(int groupId, DisplayPowerRequest displayPowerRequest, int wakefulness, boolean ready, - boolean supportsSandman) { - this.mGroupId = groupId; - this.mDisplayPowerRequest = displayPowerRequest; - this.mWakefulness = wakefulness; - this.mReady = ready; - this.mSupportsSandman = supportsSandman; + PowerGroup(int groupId, PowerGroupListener wakefulnessListener, + DisplayPowerRequest displayPowerRequest, int wakefulness, boolean ready, + boolean supportsSandman, long eventTime) { + mGroupId = groupId; + mWakefulnessListener = wakefulnessListener; + mDisplayPowerRequest = displayPowerRequest; + mWakefulness = wakefulness; + mReady = ready; + mSupportsSandman = supportsSandman; + mLastWakeTime = eventTime; + mLastSleepTime = eventTime; } - PowerGroup() { - this.mGroupId = Display.DEFAULT_DISPLAY_GROUP; - this.mDisplayPowerRequest = new DisplayPowerRequest(); - this.mWakefulness = WAKEFULNESS_AWAKE; - this.mReady = false; - this.mSupportsSandman = true; - } + PowerGroup(int wakefulness, PowerGroupListener wakefulnessListener, long eventTime) { + mGroupId = Display.DEFAULT_DISPLAY_GROUP; + mWakefulnessListener = wakefulnessListener; + mDisplayPowerRequest = new DisplayPowerRequest(); + mWakefulness = wakefulness; + mReady = false; + mSupportsSandman = true; + mLastWakeTime = eventTime; + mLastSleepTime = eventTime; } DisplayPowerRequest getDisplayPowerRequestLocked() { return mDisplayPowerRequest; } + long getLastWakeTimeLocked() { + return mLastWakeTime; + } + + long getLastSleepTimeLocked() { + return mLastSleepTime; + } + int getWakefulnessLocked() { return mWakefulness; } @@ -85,9 +111,19 @@ public class PowerGroup { * * @return {@code true} if the wakefulness value was changed; {@code false} otherwise. */ - boolean setWakefulnessLocked(int newWakefulness) { + boolean setWakefulnessLocked(int newWakefulness, long eventTime, int uid, int reason, int opUid, + String opPackageName, String details) { if (mWakefulness != newWakefulness) { + if (newWakefulness == WAKEFULNESS_AWAKE) { + setLastPowerOnTimeLocked(eventTime); + setIsPoweringOnLocked(true); + mLastWakeTime = eventTime; + } else if (isInteractive(mWakefulness) && !isInteractive(newWakefulness)) { + mLastSleepTime = eventTime; + } mWakefulness = newWakefulness; + mWakefulnessListener.onWakefulnessChangedLocked(mGroupId, mWakefulness, eventTime, + reason, uid, opUid, opPackageName, details); return true; } return false; @@ -105,8 +141,9 @@ public class PowerGroup { * Sets whether the displays of this group are all ready. * *

A display is ready if its reported - * {@link DisplayManagerInternal.DisplayPowerCallbacks#onStateChanged() actual state} matches - * its {@link DisplayManagerInternal#requestPowerState requested state}. + * {@link android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks#onStateChanged() + * actual state} matches its + * {@link android.hardware.display.DisplayManagerInternal#requestPowerState requested state}. * * @param isReady {@code true} if every display in the group is ready; otherwise {@code false}. * @return {@code true} if the ready state changed; otherwise {@code false}. @@ -148,6 +185,62 @@ public class PowerGroup { mIsSandmanSummoned = isSandmanSummoned; } + boolean dreamLocked(long eventTime, int uid) { + if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE) { + return false; + } + + Trace.traceBegin(Trace.TRACE_TAG_POWER, "dreamPowerGroup" + getGroupId()); + try { + Slog.i(TAG, "Napping power group (groupId=" + getGroupId() + ", uid=" + uid + ")..."); + setSandmanSummonedLocked(true); + setWakefulnessLocked(WAKEFULNESS_DREAMING, eventTime, uid, /* reason= */0, + /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_POWER); + } + return true; + } + + boolean dozeLocked(long eventTime, int uid, int reason) { + if (eventTime < getLastWakeTimeLocked() || !isInteractive(mWakefulness)) { + return false; + } + + Trace.traceBegin(Trace.TRACE_TAG_POWER, "powerOffDisplay"); + try { + reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX, + Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN)); + Slog.i(TAG, "Powering off display group due to " + + PowerManager.sleepReasonToString(reason) + " (groupId= " + getGroupId() + + ", uid= " + uid + ")..."); + + setSandmanSummonedLocked(/* isSandmanSummoned= */ true); + setWakefulnessLocked(WAKEFULNESS_DOZING, eventTime, uid, reason, /* opUid= */ 0, + /* opPackageName= */ null, /* details= */ null); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_POWER); + } + return true; + } + + boolean sleepLocked(long eventTime, int uid, int reason) { + if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) { + return false; + } + + Trace.traceBegin(Trace.TRACE_TAG_POWER, "sleepPowerGroup"); + try { + Slog.i(TAG, "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ")..."); + setSandmanSummonedLocked(/* isSandmanSummoned= */ true); + setWakefulnessLocked(WAKEFULNESS_ASLEEP, eventTime, uid, reason, /* opUid= */0, + /* opPackageName= */ null, /* details= */ null); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_POWER); + } + return true; + } + long getLastUserActivityTimeLocked() { return mLastUserActivityTime; } @@ -187,4 +280,22 @@ public class PowerGroup { public boolean supportsSandmanLocked() { return mSupportsSandman; } + + protected interface PowerGroupListener { + /** + * Informs the recipient about a wakefulness change of a {@link PowerGroup}. + * + * @param groupId The PowerGroup's id for which the wakefulness has changed. + * @param wakefulness The new wakefulness. + * @param eventTime The time of the event. + * @param reason The reason, any of {@link android.os.PowerManager.WakeReason} or + * {@link android.os.PowerManager.GoToSleepReason}. + * @param uid The uid which caused the wakefulness change. + * @param opUid The uid used for AppOps. + * @param opPackageName The Package name used for AppOps. + * @param details Details about the event. + */ + void onWakefulnessChangedLocked(int groupId, int wakefulness, long eventTime, int reason, + int uid, int opUid, String opPackageName, String details); + } } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index abfa016aef438..4185b2d9e4975 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -29,6 +29,7 @@ import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP; import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE; import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING; import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING; +import static android.os.PowerManagerInternal.isInteractive; import static android.os.PowerManagerInternal.wakefulnessToString; import static com.android.internal.util.LatencyTracker.ACTION_TURN_ON_SCREEN; @@ -338,12 +339,12 @@ public final class PowerManagerService extends SystemService private boolean mRequestWaitForNegativeProximity; // Timestamp of the last time the device was awoken or put to sleep. - private long mLastWakeTime; - private long mLastSleepTime; + private long mLastGlobalWakeTime; + private long mLastGlobalSleepTime; // Last reason the device went to sleep. - private @WakeReason int mLastWakeReason; - private int mLastSleepReason; + private @WakeReason int mLastGlobalWakeReason; + private int mLastGlobalSleepReason; // Timestamp of last time power boost interaction was sent. private long mLastInteractivePowerHintTime; @@ -352,6 +353,8 @@ public final class PowerManagerService extends SystemService private long mLastScreenBrightnessBoostTime; private boolean mScreenBrightnessBoostInProgress; + private final PowerGroupWakefulnessChangeListener mPowerGroupWakefulnessChangeListener; + // The suspend blocker used to keep the CPU alive while the device is booting. private final SuspendBlocker mBootingSuspendBlocker; @@ -397,6 +400,10 @@ public final class PowerManagerService extends SystemService // The current battery level percentage. private int mBatteryLevel; + // True if updatePowerStateLocked() is already in progress. + // TODO(b/215518989): Remove this once transactions are in place + private boolean mUpdatePowerStateInProgress; + /** * The lock that should be held when interacting with {@link #mEnhancedDischargeTimeElapsed}, * {@link #mLastEnhancedDischargeTimeUpdatedElapsed}, and @@ -640,6 +647,23 @@ public final class PowerManagerService extends SystemService // but the DreamService has not yet been told to start (it's an async process). private boolean mDozeStartInProgress; + private final class PowerGroupWakefulnessChangeListener implements + PowerGroup.PowerGroupListener { + @GuardedBy("mLock") + @Override + public void onWakefulnessChangedLocked(int groupId, int wakefulness, long eventTime, + int reason, int uid, int opUid, String opPackageName, String details) { + if (wakefulness == WAKEFULNESS_AWAKE) { + // Kick user activity to prevent newly awake group from timing out instantly. + userActivityNoUpdateLocked(mPowerGroups.get(groupId), eventTime, + PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid); + } + mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS; + updateGlobalWakefulnessLocked(eventTime, reason, uid, opUid, opPackageName, details); + updatePowerStateLocked(); + } + } + private final class DisplayGroupPowerChangeListener implements DisplayManagerInternal.DisplayGroupListener { @@ -658,10 +682,12 @@ public final class PowerManagerService extends SystemService final boolean supportsSandman = groupId == Display.DEFAULT_DISPLAY_GROUP; final PowerGroup powerGroup = new PowerGroup( groupId, + mPowerGroupWakefulnessChangeListener, new DisplayPowerRequest(), - getGlobalWakefulnessLocked(), + WAKEFULNESS_AWAKE, /* ready= */ false, - supportsSandman); + supportsSandman, + mClock.uptimeMillis()); mPowerGroups.append(groupId, powerGroup); onPowerGroupEventLocked(DISPLAY_GROUP_ADDED, powerGroup); } @@ -992,6 +1018,8 @@ public final class PowerManagerService extends SystemService mInattentiveSleepWarningOverlayController = mInjector.createInattentiveSleepWarningController(); + mPowerGroupWakefulnessChangeListener = new PowerGroupWakefulnessChangeListener(); + // Save brightness values: // Get float values from config. // Store float if valid @@ -1144,10 +1172,10 @@ public final class PowerManagerService extends SystemService updatePowerStateLocked(); if (sQuiescent) { - sleepDisplayGroupNoUpdateLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), + sleepPowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), mClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_QUIESCENT, - PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID); + Process.SYSTEM_UID); } mContext.getSystemService(DeviceStateManager.class).registerCallback( @@ -1164,7 +1192,9 @@ public final class PowerManagerService extends SystemService mPolicy = getLocalService(WindowManagerPolicy.class); mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class); mAttentionDetector.systemReady(mContext); - mPowerGroups.append(Display.DEFAULT_DISPLAY_GROUP, new PowerGroup()); + mPowerGroups.append(Display.DEFAULT_DISPLAY_GROUP, + new PowerGroup(WAKEFULNESS_AWAKE, mPowerGroupWakefulnessChangeListener, + mClock.uptimeMillis())); DisplayGroupPowerChangeListener displayGroupPowerChangeListener = new DisplayGroupPowerChangeListener(); mDisplayManagerInternal.registerDisplayGroupListener(displayGroupPowerChangeListener); @@ -1503,7 +1533,7 @@ public final class PowerManagerService extends SystemService opUid = wakeLock.mOwnerUid; } for (int idx = 0; idx < mPowerGroups.size(); idx++) { - wakeDisplayGroupNoUpdateLocked(mPowerGroups.valueAt(idx), mClock.uptimeMillis(), + wakePowerGroupLocked(mPowerGroups.valueAt(idx), mClock.uptimeMillis(), PowerManager.WAKE_REASON_APPLICATION, wakeLock.mTag, opUid, opPackageName, opUid); } @@ -1777,13 +1807,15 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") private boolean userActivityNoUpdateLocked(final PowerGroup powerGroup, long eventTime, int event, int flags, int uid) { + final int groupId = powerGroup.getGroupId(); if (DEBUG_SPEW) { - Slog.d(TAG, "userActivityNoUpdateLocked: groupId=" + powerGroup.getGroupId() + Slog.d(TAG, "userActivityNoUpdateLocked: groupId=" + groupId + ", eventTime=" + eventTime + ", event=" + event + ", flags=0x" + Integer.toHexString(flags) + ", uid=" + uid); } - if (eventTime < mLastSleepTime || eventTime < mLastWakeTime || !mSystemReady) { + if (eventTime < powerGroup.getLastSleepTimeLocked() + || eventTime < powerGroup.getLastWakeTimeLocked() || !mSystemReady) { return false; } @@ -1801,7 +1833,6 @@ public final class PowerManagerService extends SystemService mUserInactiveOverrideFromWindowManager = false; mOverriddenTimeout = -1; } - final int wakefulness = powerGroup.getWakefulnessLocked(); if (wakefulness == WAKEFULNESS_ASLEEP || wakefulness == WAKEFULNESS_DOZING @@ -1846,42 +1877,33 @@ public final class PowerManagerService extends SystemService } } - private void wakeDisplayGroup(int groupId, long eventTime, @WakeReason int reason, - String details, int uid, String opPackageName, int opUid) { - synchronized (mLock) { - if (wakeDisplayGroupNoUpdateLocked(mPowerGroups.get(groupId), eventTime, reason, - details, uid, opPackageName, opUid)) { - updatePowerStateLocked(); - } - } - } - @GuardedBy("mLock") - private boolean wakeDisplayGroupNoUpdateLocked(final PowerGroup powerGroup, long eventTime, + private void wakePowerGroupLocked(final PowerGroup powerGroup, long eventTime, @WakeReason int reason, String details, int uid, String opPackageName, int opUid) { final int groupId = powerGroup.getGroupId(); if (DEBUG_SPEW) { - Slog.d(TAG, "wakeDisplayGroupNoUpdateLocked: eventTime=" + eventTime + Slog.d(TAG, "wakePowerGroupLocked: eventTime=" + eventTime + ", groupId=" + groupId + ", uid=" + uid); } - if (eventTime < mLastSleepTime || mForceSuspendActive || !mSystemReady) { - return false; + if (eventTime < powerGroup.getLastSleepTimeLocked() || mForceSuspendActive + || !mSystemReady) { + return; } - final int currentState = powerGroup.getWakefulnessLocked(); - if (currentState == WAKEFULNESS_AWAKE) { + final int currentWakefulness = powerGroup.getWakefulnessLocked(); + if (currentWakefulness == WAKEFULNESS_AWAKE) { if (!mBootCompleted && sQuiescent) { mDirty |= DIRTY_QUIESCENT; - return true; + updatePowerStateLocked(); } - return false; + return; } Trace.traceBegin(Trace.TRACE_TAG_POWER, "powerOnDisplay"); try { - Slog.i(TAG, "Powering on display group from" - + PowerManagerInternal.wakefulnessToString(currentState) + Slog.i(TAG, "Waking up power group from " + + PowerManagerInternal.wakefulnessToString(currentWakefulness) + " (groupId=" + groupId + ", uid=" + uid + ", reason=" + PowerManager.wakeReasonToString(reason) @@ -1892,183 +1914,96 @@ public final class PowerManagerService extends SystemService LatencyTracker.getInstance(mContext) .onActionStart(ACTION_TURN_ON_SCREEN, String.valueOf(groupId)); - setWakefulnessLocked(powerGroup, WAKEFULNESS_AWAKE, eventTime, uid, reason, opUid, + powerGroup.setWakefulnessLocked(WAKEFULNESS_AWAKE, eventTime, uid, reason, opUid, opPackageName, details); - powerGroup.setLastPowerOnTimeLocked(eventTime); - powerGroup.setIsPoweringOnLocked(true); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } - - return true; - } - - private void sleepDisplayGroup(int groupId, long eventTime, int reason, int flags, - int uid) { - synchronized (mLock) { - if (sleepDisplayGroupNoUpdateLocked(mPowerGroups.get(groupId), eventTime, reason, flags, - uid)) { - updatePowerStateLocked(); - } - } } @GuardedBy("mLock") - private boolean sleepDisplayGroupNoUpdateLocked(final PowerGroup powerGroup, long eventTime, - int reason, int flags, int uid) { + private boolean dreamPowerGroupLocked(PowerGroup powerGroup, long eventTime, int uid) { + if (DEBUG_SPEW) { + Slog.d(TAG, "dreamPowerGroup: groupId=" + powerGroup.getGroupId() + ", eventTime=" + + eventTime + ", uid=" + uid); + } + if (!mBootCompleted || !mSystemReady) { + return false; + } + return powerGroup.dreamLocked(eventTime, uid); + } + + @GuardedBy("mLock") + private boolean dozePowerGroupLocked(final PowerGroup powerGroup, long eventTime, + int reason, int uid) { if (DEBUG_SPEW) { Slog.d(TAG, "sleepDisplayGroupNoUpdateLocked: eventTime=" + eventTime + ", groupId=" + powerGroup.getGroupId() + ", reason=" + reason - + ", flags=" + flags + ", uid=" + uid); + + ", uid=" + uid); } - if (eventTime < mLastWakeTime - || !PowerManagerInternal.isInteractive(getWakefulnessLocked()) - || !mSystemReady - || !mBootCompleted) { + if (!mSystemReady || !mBootCompleted) { return false; } - final int wakefulness = powerGroup.getWakefulnessLocked(); - if (!PowerManagerInternal.isInteractive(wakefulness)) { - return false; - } - - Trace.traceBegin(Trace.TRACE_TAG_POWER, "powerOffDisplay"); - try { - reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX, - Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN)); - Slog.i(TAG, "Powering off display group due to " - + PowerManager.sleepReasonToString(reason) - + " (groupId= " + powerGroup.getGroupId() + ", uid= " + uid + ")..."); - - powerGroup.setSandmanSummonedLocked(/* isSandmanSummoned= */ true); - setWakefulnessLocked(powerGroup, WAKEFULNESS_DOZING, eventTime, uid, reason, - /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null); - if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) { - reallySleepDisplayGroupNoUpdateLocked(powerGroup, eventTime, uid); - } - } finally { - Trace.traceEnd(Trace.TRACE_TAG_POWER); - } - return true; - } - - private void dreamDisplayGroup(int groupId, long eventTime, int uid) { - synchronized (mLock) { - if (dreamDisplayGroupNoUpdateLocked(mPowerGroups.get(groupId), eventTime, uid)) { - updatePowerStateLocked(); - } - } + return powerGroup.dozeLocked(eventTime, uid, reason); } @GuardedBy("mLock") - private boolean dreamDisplayGroupNoUpdateLocked(final PowerGroup powerGroup, long eventTime, + private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime, int reason, int uid) { if (DEBUG_SPEW) { - Slog.d(TAG, "dreamDisplayGroupNoUpdateLocked: eventTime=" + eventTime - + ", uid=" + uid); + Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime + ", uid=" + uid); } - - if (eventTime < mLastWakeTime || getWakefulnessLocked() != WAKEFULNESS_AWAKE - || !mBootCompleted || !mSystemReady) { + if (!mBootCompleted || !mSystemReady) { return false; } - Trace.traceBegin(Trace.TRACE_TAG_POWER, "napDisplayGroup"); - try { - Slog.i(TAG, "Napping display group (groupId=" + powerGroup.getGroupId() + ", uid=" + uid - + ")..."); - - powerGroup.setSandmanSummonedLocked(/* isSandmanSummoned= */ true); - setWakefulnessLocked(powerGroup, WAKEFULNESS_DREAMING, eventTime, uid, - /* reason= */0, /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null); - - } finally { - Trace.traceEnd(Trace.TRACE_TAG_POWER); - } - return true; - } - - @GuardedBy("mLock") - private boolean reallySleepDisplayGroupNoUpdateLocked(final PowerGroup powerGroup, - long eventTime, int uid) { - if (DEBUG_SPEW) { - Slog.d(TAG, "reallySleepDisplayGroupNoUpdateLocked: eventTime=" + eventTime - + ", uid=" + uid); - } - - if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP - || !mBootCompleted || !mSystemReady - || powerGroup.getWakefulnessLocked() - == WAKEFULNESS_ASLEEP) { - return false; - } - - Trace.traceBegin(Trace.TRACE_TAG_POWER, "reallySleepDisplayGroup"); - try { - Slog.i(TAG, - "Sleeping display group (groupId=" + powerGroup.getGroupId() + ", uid=" + uid - + ")..."); - - setWakefulnessLocked(powerGroup, WAKEFULNESS_ASLEEP, eventTime, uid, - PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, /* opUid= */ 0, - /* opPackageName= */ null, /* details= */ null); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_POWER); - } - return true; + return powerGroup.sleepLocked(eventTime, uid, reason); } @VisibleForTesting @GuardedBy("mLock") void setWakefulnessLocked(int groupId, int wakefulness, long eventTime, int uid, int reason, int opUid, String opPackageName, String details) { - setWakefulnessLocked(mPowerGroups.get(groupId), wakefulness, eventTime, uid, reason, opUid, + mPowerGroups.get(groupId).setWakefulnessLocked(wakefulness, eventTime, uid, reason, opUid, opPackageName, details); } - @GuardedBy("mLock") - private void setWakefulnessLocked(final PowerGroup powerGroup, int wakefulness, long eventTime, - int uid, int reason, int opUid, String opPackageName, String details) { - if (powerGroup.setWakefulnessLocked(wakefulness)) { - mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS; - setGlobalWakefulnessLocked(getGlobalWakefulnessLocked(), - eventTime, reason, uid, opUid, opPackageName, details); - if (wakefulness == WAKEFULNESS_AWAKE) { - // Kick user activity to prevent newly awake group from timing out instantly. - userActivityNoUpdateLocked(powerGroup, eventTime, - PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid); - } - } - } - @SuppressWarnings("deprecation") @GuardedBy("mLock") - private void setGlobalWakefulnessLocked(int wakefulness, long eventTime, int reason, int uid, + private void updateGlobalWakefulnessLocked(long eventTime, int reason, int uid, int opUid, String opPackageName, String details) { - if (getWakefulnessLocked() == wakefulness) { + int newWakefulness = recalculateGlobalWakefulnessLocked(); + int currentWakefulness = getGlobalWakefulnessLocked(); + if (currentWakefulness == newWakefulness) { return; } // Phase 1: Handle pre-wakefulness change bookkeeping. final String traceMethodName; - switch (wakefulness) { + switch (newWakefulness) { case WAKEFULNESS_ASLEEP: traceMethodName = "reallyGoToSleep"; Slog.i(TAG, "Sleeping (uid " + uid + ")..."); + // TODO(b/215518989): Remove this once transactions are in place + if (currentWakefulness != WAKEFULNESS_DOZING) { + // in case we are going to sleep without dozing before + mLastGlobalSleepTime = eventTime; + mLastGlobalSleepReason = reason; + } break; case WAKEFULNESS_AWAKE: traceMethodName = "wakeUp"; Slog.i(TAG, "Waking up from " - + PowerManagerInternal.wakefulnessToString(getWakefulnessLocked()) + + PowerManagerInternal.wakefulnessToString(currentWakefulness) + " (uid=" + uid + ", reason=" + PowerManager.wakeReasonToString(reason) + ", details=" + details + ")..."); - mLastWakeTime = eventTime; - mLastWakeReason = reason; + mLastGlobalWakeTime = eventTime; + mLastGlobalWakeReason = reason; break; case WAKEFULNESS_DREAMING: @@ -2081,13 +2016,13 @@ public final class PowerManagerService extends SystemService Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason) + " (uid " + uid + ")..."); - mLastSleepTime = eventTime; - mLastSleepReason = reason; + mLastGlobalSleepTime = eventTime; + mLastGlobalSleepReason = reason; mDozeStartInProgress = true; break; default: - throw new IllegalArgumentException("Unexpected wakefulness: " + wakefulness); + throw new IllegalArgumentException("Unexpected wakefulness: " + newWakefulness); } Trace.traceBegin(Trace.TRACE_TAG_POWER, traceMethodName); @@ -2095,20 +2030,20 @@ public final class PowerManagerService extends SystemService // Phase 2: Handle wakefulness change and bookkeeping. // Under lock, invalidate before set ensures caches won't return stale values. mInjector.invalidateIsInteractiveCaches(); - mWakefulnessRaw = wakefulness; + mWakefulnessRaw = newWakefulness; mWakefulnessChanging = true; mDirty |= DIRTY_WAKEFULNESS; // This is only valid while we are in wakefulness dozing. Set to false otherwise. - mDozeStartInProgress &= (getWakefulnessLocked() == WAKEFULNESS_DOZING); + mDozeStartInProgress &= (newWakefulness == WAKEFULNESS_DOZING); if (mNotifier != null) { - mNotifier.onWakefulnessChangeStarted(wakefulness, reason, eventTime); + mNotifier.onWakefulnessChangeStarted(newWakefulness, reason, eventTime); } - mAttentionDetector.onWakefulnessChangeStarted(wakefulness); + mAttentionDetector.onWakefulnessChangeStarted(newWakefulness); // Phase 3: Handle post-wakefulness change bookkeeping. - switch (wakefulness) { + switch (newWakefulness) { case WAKEFULNESS_AWAKE: mNotifier.onWakeUp(reason, details, uid, opPackageName, opUid); if (sQuiescent) { @@ -2116,7 +2051,13 @@ public final class PowerManagerService extends SystemService } break; + case WAKEFULNESS_ASLEEP: + // fallthrough case WAKEFULNESS_DOZING: + if (!isInteractive(currentWakefulness)) { + // TODO(b/215518989): remove this once transactions are in place + break; + } // Report the number of wake locks that will be cleared by going to sleep. int numWakeLocksCleared = 0; final int numWakeLocks = mWakeLocks.size(); @@ -2140,7 +2081,7 @@ public final class PowerManagerService extends SystemService @VisibleForTesting @GuardedBy("mLock") - int getWakefulnessLocked() { + int getGlobalWakefulnessLocked() { return mWakefulnessRaw; } @@ -2163,10 +2104,9 @@ public final class PowerManagerService extends SystemService * */ @GuardedBy("mLock") - int getGlobalWakefulnessLocked() { - final int size = mPowerGroups.size(); + int recalculateGlobalWakefulnessLocked() { int deviceWakefulness = WAKEFULNESS_ASLEEP; - for (int i = 0; i < size; i++) { + for (int i = 0; i < mPowerGroups.size(); i++) { final int wakefulness = mPowerGroups.valueAt(i).getWakefulnessLocked(); if (wakefulness == WAKEFULNESS_AWAKE) { return WAKEFULNESS_AWAKE; @@ -2187,10 +2127,10 @@ public final class PowerManagerService extends SystemService void onPowerGroupEventLocked(int event, PowerGroup powerGroup) { final int groupId = powerGroup.getGroupId(); if (event == DisplayGroupPowerChangeListener.DISPLAY_GROUP_REMOVED) { - mPowerGroups.remove(groupId); + mPowerGroups.delete(groupId); } - final int oldWakefulness = getWakefulnessLocked(); - final int newWakefulness = getGlobalWakefulnessLocked(); + final int oldWakefulness = getGlobalWakefulnessLocked(); + final int newWakefulness = recalculateGlobalWakefulnessLocked(); if (event == DisplayGroupPowerChangeListener.DISPLAY_GROUP_ADDED && newWakefulness == WAKEFULNESS_AWAKE) { @@ -2215,13 +2155,9 @@ public final class PowerManagerService extends SystemService default: reason = 0; } - - setGlobalWakefulnessLocked( - getGlobalWakefulnessLocked(), - mClock.uptimeMillis(), reason, Process.SYSTEM_UID, Process.SYSTEM_UID, - mContext.getOpPackageName(), "groupId: " + groupId); + updateGlobalWakefulnessLocked(mClock.uptimeMillis(), reason, Process.SYSTEM_UID, + Process.SYSTEM_UID, mContext.getOpPackageName(), "groupId: " + groupId); } - mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS; updatePowerStateLocked(); } @@ -2243,15 +2179,15 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") private void finishWakefulnessChangeIfNeededLocked() { if (mWakefulnessChanging && areAllDisplaysReadyLocked()) { - if (getWakefulnessLocked() == WAKEFULNESS_DOZING + if (getGlobalWakefulnessLocked() == WAKEFULNESS_DOZING && (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) { return; // wait until dream has enabled dozing } else { // Doze wakelock acquired (doze started) or device is no longer dozing. mDozeStartInProgress = false; } - if (getWakefulnessLocked() == WAKEFULNESS_DOZING - || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) { + if (getGlobalWakefulnessLocked() == WAKEFULNESS_DOZING + || getGlobalWakefulnessLocked() == WAKEFULNESS_ASLEEP) { logSleepTimeoutRecapturedLocked(); } mWakefulnessChanging = false; @@ -2282,7 +2218,7 @@ public final class PowerManagerService extends SystemService */ @GuardedBy("mLock") private void updatePowerStateLocked() { - if (!mSystemReady || mDirty == 0) { + if (!mSystemReady || mDirty == 0 || mUpdatePowerStateInProgress) { return; } if (!Thread.holdsLock(mLock)) { @@ -2290,6 +2226,7 @@ public final class PowerManagerService extends SystemService } Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState"); + mUpdatePowerStateInProgress = true; try { // Phase 0: Basic state updates. updateIsPoweredLocked(mDirty); @@ -2332,6 +2269,7 @@ public final class PowerManagerService extends SystemService updateSuspendBlockerLocked(); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); + mUpdatePowerStateInProgress = false; } } @@ -2397,7 +2335,7 @@ public final class PowerManagerService extends SystemService final long now = mClock.uptimeMillis(); if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType, dockedOnWirelessCharger)) { - wakeDisplayGroupNoUpdateLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), + wakePowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), now, PowerManager.WAKE_REASON_PLUGGED_IN, "android.server.power:PLUGGED:" + mIsPowered, Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID); @@ -2446,7 +2384,7 @@ public final class PowerManagerService extends SystemService } // If already dreaming and becoming powered, then don't wake. - if (mIsPowered && getWakefulnessLocked() == WAKEFULNESS_DREAMING) { + if (mIsPowered && getGlobalWakefulnessLocked() == WAKEFULNESS_DREAMING) { return false; } @@ -2456,7 +2394,7 @@ public final class PowerManagerService extends SystemService } // On Always On Display, SystemUI shows the charging indicator - if (mAlwaysOnEnabled && getWakefulnessLocked() == WAKEFULNESS_DOZING) { + if (mAlwaysOnEnabled && getGlobalWakefulnessLocked() == WAKEFULNESS_DOZING) { return false; } @@ -2540,24 +2478,23 @@ public final class PowerManagerService extends SystemService for (int idx = 0; idx < mPowerGroups.size(); idx++) { final PowerGroup powerGroup = mPowerGroups.valueAt(idx); - final int wakeLockSummary = adjustWakeLockSummary( - powerGroup.getWakefulnessLocked(), + final int wakeLockSummary = adjustWakeLockSummary(powerGroup.getWakefulnessLocked(), invalidGroupWakeLockSummary | powerGroup.getWakeLockSummaryLocked()); powerGroup.setWakeLockSummaryLocked(wakeLockSummary); } - mWakeLockSummary = adjustWakeLockSummary(getWakefulnessLocked(), + mWakeLockSummary = adjustWakeLockSummary(getGlobalWakefulnessLocked(), mWakeLockSummary); for (int i = 0; i < numProfiles; i++) { final ProfilePowerState profile = mProfilePowerState.valueAt(i); - profile.mWakeLockSummary = adjustWakeLockSummary(getWakefulnessLocked(), + profile.mWakeLockSummary = adjustWakeLockSummary(getGlobalWakefulnessLocked(), profile.mWakeLockSummary); } if (DEBUG_SPEW) { Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness=" - + PowerManagerInternal.wakefulnessToString(getWakefulnessLocked()) + + PowerManagerInternal.wakefulnessToString(getGlobalWakefulnessLocked()) + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)); } } @@ -2706,11 +2643,12 @@ public final class PowerManagerService extends SystemService int groupUserActivitySummary = 0; long groupNextTimeout = 0; final PowerGroup powerGroup = mPowerGroups.valueAt(idx); - if (powerGroup.getWakefulnessLocked() != WAKEFULNESS_ASLEEP) { + final int wakefulness = powerGroup.getWakefulnessLocked(); + if (wakefulness != WAKEFULNESS_ASLEEP) { final long lastUserActivityTime = powerGroup.getLastUserActivityTimeLocked(); final long lastUserActivityTimeNoChangeLights = powerGroup.getLastUserActivityTimeNoChangeLightsLocked(); - if (lastUserActivityTime >= mLastWakeTime) { + if (lastUserActivityTime >= powerGroup.getLastWakeTimeLocked()) { groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration; if (now < groupNextTimeout) { groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; @@ -2721,8 +2659,8 @@ public final class PowerManagerService extends SystemService } } } - if (groupUserActivitySummary == 0 - && lastUserActivityTimeNoChangeLights >= mLastWakeTime) { + if (groupUserActivitySummary == 0 && lastUserActivityTimeNoChangeLights + >= powerGroup.getLastWakeTimeLocked()) { groupNextTimeout = lastUserActivityTimeNoChangeLights + screenOffTimeout; if (now < groupNextTimeout) { final DisplayPowerRequest displayPowerRequest = @@ -2740,7 +2678,7 @@ public final class PowerManagerService extends SystemService if (sleepTimeout >= 0) { final long anyUserActivity = Math.max(lastUserActivityTime, lastUserActivityTimeNoChangeLights); - if (anyUserActivity >= mLastWakeTime) { + if (anyUserActivity >= powerGroup.getLastWakeTimeLocked()) { groupNextTimeout = anyUserActivity + sleepTimeout; if (now < groupNextTimeout) { groupUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM; @@ -2786,7 +2724,7 @@ public final class PowerManagerService extends SystemService if (DEBUG_SPEW) { Slog.d(TAG, "updateUserActivitySummaryLocked: groupId=" + powerGroup.getGroupId() - + ", mWakefulness=" + wakefulnessToString(powerGroup.getWakefulnessLocked()) + + ", mWakefulness=" + wakefulnessToString(wakefulness) + ", mUserActivitySummary=0x" + Integer.toHexString( groupUserActivitySummary) + ", nextTimeout=" + TimeUtils.formatUptime(groupNextTimeout)); @@ -2884,7 +2822,7 @@ public final class PowerManagerService extends SystemService return false; } - if (getWakefulnessLocked() != WAKEFULNESS_AWAKE) { + if (getGlobalWakefulnessLocked() != WAKEFULNESS_AWAKE) { mInattentiveSleepWarningOverlayController.dismiss(false); return true; } else if (attentiveTimeout < 0 || isBeingKeptFromInattentiveSleepLocked() @@ -3024,14 +2962,13 @@ public final class PowerManagerService extends SystemService if (DEBUG) { Slog.i(TAG, "Going to sleep now due to long user inactivity"); } - changed = sleepDisplayGroupNoUpdateLocked(powerGroup, time, - PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, - PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID); + changed = sleepPowerGroupLocked(powerGroup, time, + PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, Process.SYSTEM_UID); } else if (shouldNapAtBedTimeLocked()) { - changed = dreamDisplayGroupNoUpdateLocked(powerGroup, time, Process.SYSTEM_UID); + changed = dreamPowerGroupLocked(powerGroup, time, Process.SYSTEM_UID); } else { - changed = sleepDisplayGroupNoUpdateLocked(powerGroup, time, - PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID); + changed = dozePowerGroupLocked(powerGroup, time, + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, Process.SYSTEM_UID); } } return changed; @@ -3228,25 +3165,27 @@ public final class PowerManagerService extends SystemService // Dream has ended or will be stopped. Update the power state. if (isItBedTimeYetLocked(powerGroup)) { - final int flags = isAttentiveTimeoutExpired(powerGroup, now) - ? PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE : 0; - sleepDisplayGroupNoUpdateLocked(powerGroup, now, - PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, flags, Process.SYSTEM_UID); + if (isAttentiveTimeoutExpired(powerGroup, now)) { + sleepPowerGroupLocked(powerGroup, now, + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, Process.SYSTEM_UID); + } else { + dozePowerGroupLocked(powerGroup, now, + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, Process.SYSTEM_UID); + } } else { - wakeDisplayGroupNoUpdateLocked(powerGroup, now, + wakePowerGroupLocked(powerGroup, now, PowerManager.WAKE_REASON_UNKNOWN, "android.server.power:DREAM_FINISHED", Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID); } - updatePowerStateLocked(); } else if (wakefulness == WAKEFULNESS_DOZING) { if (isDreaming) { return; // continue dozing } // Doze has ended or will be stopped. Update the power state. - reallySleepDisplayGroupNoUpdateLocked(powerGroup, now, Process.SYSTEM_UID); - updatePowerStateLocked(); + sleepPowerGroupLocked(powerGroup, now, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, + Process.SYSTEM_UID); } } @@ -3263,7 +3202,7 @@ public final class PowerManagerService extends SystemService private boolean canDreamLocked(final PowerGroup powerGroup) { final DisplayPowerRequest displayPowerRequest = powerGroup.getDisplayPowerRequestLocked(); if (!mBootCompleted - || getWakefulnessLocked() != WAKEFULNESS_DREAMING + || getGlobalWakefulnessLocked() != WAKEFULNESS_DREAMING || !mDreamsSupportedConfig || !mDreamsEnabledSetting || !displayPowerRequest.isBrightOrDim() @@ -3294,7 +3233,7 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") private boolean canDozeLocked() { // TODO (b/175764708): Support per-display doze. - return getWakefulnessLocked() == WAKEFULNESS_DOZING; + return getGlobalWakefulnessLocked() == WAKEFULNESS_DOZING; } /** @@ -3375,15 +3314,15 @@ public final class PowerManagerService extends SystemService final boolean ready = mDisplayManagerInternal.requestPowerState(groupId, displayPowerRequest, mRequestWaitForNegativeProximity); - mNotifier.onScreenPolicyUpdate(groupId, displayPowerRequest.policy); + mNotifier.onScreenPolicyUpdate(powerGroup.getGroupId(), displayPowerRequest.policy); + int wakefulness = powerGroup.getWakefulnessLocked(); if (DEBUG_SPEW) { Slog.d(TAG, "updateDisplayPowerStateLocked: displayReady=" + ready + ", groupId=" + groupId + ", policy=" + policyToString(displayPowerRequest.policy) + ", mWakefulness=" - + PowerManagerInternal.wakefulnessToString( - powerGroup.getWakefulnessLocked()) + + PowerManagerInternal.wakefulnessToString(wakefulness) + ", mWakeLockSummary=0x" + Integer.toHexString( powerGroup.getWakeLockSummaryLocked()) + ", mUserActivitySummary=0x" + Integer.toHexString( @@ -3401,7 +3340,7 @@ public final class PowerManagerService extends SystemService final boolean displayReadyStateChanged = powerGroup.setReadyLocked(ready); final boolean poweringOn = powerGroup.isPoweringOnLocked(); if (ready && displayReadyStateChanged && poweringOn - && powerGroup.getWakefulnessLocked() == WAKEFULNESS_AWAKE) { + && wakefulness == WAKEFULNESS_AWAKE) { powerGroup.setIsPoweringOnLocked(false); LatencyTracker.getInstance(mContext).onActionEnd(ACTION_TURN_ON_SCREEN); Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, groupId); @@ -3424,7 +3363,7 @@ public final class PowerManagerService extends SystemService if (mScreenBrightnessBoostInProgress) { final long now = mClock.uptimeMillis(); mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT); - if (mLastScreenBrightnessBoostTime > mLastSleepTime) { + if (mLastScreenBrightnessBoostTime > mLastGlobalSleepTime) { final long boostTimeout = mLastScreenBrightnessBoostTime + SCREEN_BRIGHTNESS_BOOST_TIMEOUT; if (boostTimeout > now) { @@ -3656,7 +3595,7 @@ public final class PowerManagerService extends SystemService // Here we wait for mWakefulnessChanging to become false since the wakefulness // transition to DOZING isn't considered "changed" until the doze wake lock is // acquired. - if (getWakefulnessLocked() == WAKEFULNESS_DOZING && mDozeStartInProgress) { + if (getGlobalWakefulnessLocked() == WAKEFULNESS_DOZING && mDozeStartInProgress) { return true; } @@ -3721,7 +3660,7 @@ public final class PowerManagerService extends SystemService private boolean isInteractiveInternal() { synchronized (mLock) { - return PowerManagerInternal.isInteractive(getWakefulnessLocked()); + return PowerManagerInternal.isInteractive(getGlobalWakefulnessLocked()); } } @@ -4092,7 +4031,7 @@ public final class PowerManagerService extends SystemService private void boostScreenBrightnessInternal(long eventTime, int uid) { synchronized (mLock) { - if (!mSystemReady || getWakefulnessLocked() == WAKEFULNESS_ASLEEP + if (!mSystemReady || getGlobalWakefulnessLocked() == WAKEFULNESS_ASLEEP || eventTime < mLastScreenBrightnessBoostTime) { return; } @@ -4225,14 +4164,9 @@ public final class PowerManagerService extends SystemService synchronized (mLock) { mForceSuspendActive = true; // Place the system in an non-interactive state - boolean updatePowerState = false; for (int idx = 0; idx < mPowerGroups.size(); idx++) { - updatePowerState |= sleepDisplayGroupNoUpdateLocked(mPowerGroups.valueAt(idx), - mClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_FORCE_SUSPEND, - PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, uid); - } - if (updatePowerState) { - updatePowerStateLocked(); + sleepPowerGroupLocked(mPowerGroups.valueAt(idx), mClock.uptimeMillis(), + PowerManager.GO_TO_SLEEP_REASON_FORCE_SUSPEND, uid); } // Disable all the partial wake locks as well @@ -4331,7 +4265,7 @@ public final class PowerManagerService extends SystemService mConstants.dump(pw); pw.println(" mDirty=0x" + Integer.toHexString(mDirty)); pw.println(" mWakefulness=" - + PowerManagerInternal.wakefulnessToString(getWakefulnessLocked())); + + PowerManagerInternal.wakefulnessToString(getGlobalWakefulnessLocked())); pw.println(" mWakefulnessChanging=" + mWakefulnessChanging); pw.println(" mIsPowered=" + mIsPowered); pw.println(" mPlugType=" + mPlugType); @@ -4382,9 +4316,10 @@ public final class PowerManagerService extends SystemService pw.println(" mDeviceIdleMode=" + mDeviceIdleMode); pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist)); pw.println(" mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist)); - pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime)); - pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime)); - pw.println(" mLastSleepReason=" + PowerManager.sleepReasonToString(mLastSleepReason)); + pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastGlobalWakeTime)); + pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastGlobalSleepTime)); + pw.println(" mLastSleepReason=" + PowerManager.sleepReasonToString( + mLastGlobalSleepReason)); pw.println(" mLastInteractivePowerHintTime=" + TimeUtils.formatUptime(mLastInteractivePowerHintTime)); pw.println(" mLastScreenBrightnessBoostTime=" @@ -4565,7 +4500,7 @@ public final class PowerManagerService extends SystemService synchronized (mLock) { mConstants.dumpProto(proto); proto.write(PowerManagerServiceDumpProto.DIRTY, mDirty); - proto.write(PowerManagerServiceDumpProto.WAKEFULNESS, getWakefulnessLocked()); + proto.write(PowerManagerServiceDumpProto.WAKEFULNESS, getGlobalWakefulnessLocked()); proto.write(PowerManagerServiceDumpProto.IS_WAKEFULNESS_CHANGING, mWakefulnessChanging); proto.write(PowerManagerServiceDumpProto.IS_POWERED, mIsPowered); proto.write(PowerManagerServiceDumpProto.PLUG_TYPE, mPlugType); @@ -4664,8 +4599,8 @@ public final class PowerManagerService extends SystemService proto.write(PowerManagerServiceDumpProto.DEVICE_IDLE_TEMP_WHITELIST, id); } - proto.write(PowerManagerServiceDumpProto.LAST_WAKE_TIME_MS, mLastWakeTime); - proto.write(PowerManagerServiceDumpProto.LAST_SLEEP_TIME_MS, mLastSleepTime); + proto.write(PowerManagerServiceDumpProto.LAST_WAKE_TIME_MS, mLastGlobalWakeTime); + proto.write(PowerManagerServiceDumpProto.LAST_SLEEP_TIME_MS, mLastGlobalSleepTime); proto.write( PowerManagerServiceDumpProto.LAST_INTERACTIVE_POWER_HINT_TIME_MS, mLastInteractivePowerHintTime); @@ -5505,8 +5440,10 @@ public final class PowerManagerService extends SystemService final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { - wakeDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, reason, details, uid, - opPackageName, uid); + synchronized (mLock) { + wakePowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), eventTime, + reason, details, uid, opPackageName, uid); + } } finally { Binder.restoreCallingIdentity(ident); } @@ -5524,7 +5461,14 @@ public final class PowerManagerService extends SystemService final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { - sleepDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, reason, flags, uid); + synchronized (mLock) { + PowerGroup defaultPowerGroup = mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP); + if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) { + sleepPowerGroupLocked(defaultPowerGroup, eventTime, reason, uid); + } else { + dozePowerGroupLocked(defaultPowerGroup, eventTime, reason, uid); + } + } } finally { Binder.restoreCallingIdentity(ident); } @@ -5542,7 +5486,10 @@ public final class PowerManagerService extends SystemService final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { - dreamDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, uid); + synchronized (mLock) { + dreamPowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), + eventTime, uid); + } } finally { Binder.restoreCallingIdentity(ident); } @@ -6181,13 +6128,15 @@ public final class PowerManagerService extends SystemService private int getLastSleepReasonInternal() { synchronized (mLock) { - return mLastSleepReason; + return mLastGlobalSleepReason; } } + @VisibleForTesting private PowerManager.WakeData getLastWakeupInternal() { synchronized (mLock) { - return new WakeData(mLastWakeTime, mLastWakeReason, mLastWakeTime - mLastSleepTime); + return new WakeData(mLastGlobalWakeTime, mLastGlobalWakeReason, + mLastGlobalWakeTime - mLastGlobalSleepTime); } } diff --git a/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java b/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java new file mode 100644 index 0000000000000..c59b58d5c4d29 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2022 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.power; + + +import static android.os.PowerManager.GO_TO_SLEEP_REASON_APPLICATION; +import static android.os.PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN; +import static android.os.PowerManager.GO_TO_SLEEP_REASON_TIMEOUT; +import static android.os.PowerManager.WAKE_REASON_GESTURE; +import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP; +import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE; +import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING; +import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.verify; + +import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Tests for {@link com.android.server.power.PowerGroup}. + * + * Build/Install/Run: + * atest FrameworksServicesTests:PowerManagerServiceTest + */ +public class PowerGroupTest { + + private static final int GROUP_ID = 0; + private static final long TIMESTAMP_CREATE = 1; + private static final long TIMESTAMP1 = 999; + private static final long TIMESTAMP2 = TIMESTAMP1 + 10; + private static final long TIMESTAMP3 = TIMESTAMP2 + 10; + private static final int UID = 11; + + private PowerGroup mPowerGroup; + @Mock + private PowerGroup.PowerGroupListener mWakefulnessCallbackMock; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mPowerGroup = new PowerGroup(GROUP_ID, mWakefulnessCallbackMock, new DisplayPowerRequest(), + WAKEFULNESS_AWAKE, /* ready= */ true, /* supportsSandman= */true, TIMESTAMP_CREATE); + } + + @Test + public void testDreamPowerGroupTriggersOnWakefulnessChangedCallback() { + mPowerGroup.dreamLocked(TIMESTAMP1, UID); + verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID), + eq(WAKEFULNESS_DREAMING), eq(TIMESTAMP1), eq(GO_TO_SLEEP_REASON_APPLICATION), + eq(UID), /* opUid= */anyInt(), /* opPackageName= */ isNull(), /* details= */ + isNull()); + } + + @Test + public void testLastWakeAndSleepTimeIsUpdated() { + assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP_CREATE); + assertThat(mPowerGroup.getLastSleepTimeLocked()).isEqualTo(TIMESTAMP_CREATE); + + // Verify that the transition to WAKEFULNESS_DOZING updates the last sleep time + String details = "PowerGroup1 Timeout"; + mPowerGroup.setWakefulnessLocked(WAKEFULNESS_DOZING, TIMESTAMP1, UID, + GO_TO_SLEEP_REASON_TIMEOUT, /* opUid= */ 0, /* opPackageName= */ null, details); + assertThat(mPowerGroup.getLastSleepTimeLocked()).isEqualTo(TIMESTAMP1); + assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP_CREATE); + assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID), + eq(WAKEFULNESS_DOZING), eq(TIMESTAMP1), eq(GO_TO_SLEEP_REASON_TIMEOUT), + eq(UID), /* opUid= */anyInt(), /* opPackageName= */ isNull(), eq(details)); + + // Verify that the transition to WAKEFULNESS_ASLEEP after dozing does not update the last + // wake or sleep time + mPowerGroup.setWakefulnessLocked(WAKEFULNESS_ASLEEP, TIMESTAMP2, UID, + GO_TO_SLEEP_REASON_DEVICE_ADMIN, /* opUid= */ 0, /* opPackageName= */ null, + details); + assertThat(mPowerGroup.getLastSleepTimeLocked()).isEqualTo(TIMESTAMP1); + assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP_CREATE); + assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID), + eq(WAKEFULNESS_ASLEEP), eq(TIMESTAMP2), eq(GO_TO_SLEEP_REASON_DEVICE_ADMIN), + eq(UID), /* opUid= */anyInt(), /* opPackageName= */ isNull(), eq(details)); + + // Verify that waking up the power group only updates the last wake time + details = "PowerGroup1 Gesture"; + mPowerGroup.setWakefulnessLocked(WAKEFULNESS_AWAKE, TIMESTAMP2, UID, + WAKE_REASON_GESTURE, /* opUid= */ 0, /* opPackageName= */ null, details); + assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP2); + assertThat(mPowerGroup.getLastSleepTimeLocked()).isEqualTo(TIMESTAMP1); + assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID), + eq(WAKEFULNESS_AWAKE), eq(TIMESTAMP2), eq(WAKE_REASON_GESTURE), + eq(UID), /* opUid= */ anyInt(), /* opPackageName= */ isNull(), eq(details)); + + // Verify that a transition to WAKEFULNESS_ASLEEP from an interactive state updates the last + // sleep time + mPowerGroup.setWakefulnessLocked(WAKEFULNESS_ASLEEP, TIMESTAMP3, UID, + GO_TO_SLEEP_REASON_DEVICE_ADMIN, /* opUid= */ 0, /* opPackageName= */ null, + details); + assertThat(mPowerGroup.getLastSleepTimeLocked()).isEqualTo(TIMESTAMP3); + assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP2); + assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID), + eq(WAKEFULNESS_ASLEEP), eq(TIMESTAMP3), eq(GO_TO_SLEEP_REASON_DEVICE_ADMIN), + eq(UID), /* opUid= */anyInt(), /* opPackageName= */ isNull(), eq(details)); + } +} 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 c832a3ed49b6b..d35c679c18bd4 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -111,6 +111,7 @@ import java.util.concurrent.atomic.AtomicReference; * Build/Install/Run: * atest FrameworksServicesTests:PowerManagerServiceTest */ +@SuppressWarnings("GuardedBy") public class PowerManagerServiceTest { private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent"; private static final String SYSTEM_PROPERTY_REBOOT_REASON = "sys.boot.reason"; @@ -437,7 +438,7 @@ public class PowerManagerServiceTest { @Test public void testWakefulnessAwake_InitialValue() { createService(); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); } @Test @@ -445,12 +446,12 @@ public class PowerManagerServiceTest { createService(); // Start with AWAKE state startSystem(); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); // Take a nap and verify. mService.getBinderServiceInstance().goToSleep(mClock.now(), PowerManager.GO_TO_SLEEP_REASON_APPLICATION, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); } @Test @@ -467,21 +468,21 @@ public class PowerManagerServiceTest { int flags = PowerManager.FULL_WAKE_LOCK; mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName, null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */); // Ensure that the flag does *NOT* work with a partial wake lock. flags = PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP; mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName, null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */); // Verify that flag forces a wakeup when paired to a FULL_WAKE_LOCK flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP; mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName, null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */); } @@ -492,7 +493,7 @@ public class PowerManagerServiceTest { forceSleep(); mService.getBinderServiceInstance().wakeUp(mClock.now(), PowerManager.WAKE_REASON_UNKNOWN, "testing IPowerManager.wakeUp()", "pkg.name"); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); } /** @@ -511,7 +512,7 @@ public class PowerManagerServiceTest { .thenReturn(false); mService.readConfigurationLocked(); setPluggedIn(true); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); when(mResourcesSpy.getBoolean(com.android.internal.R.bool.config_unplugTurnsOnScreen)) .thenReturn(true); mService.readConfigurationLocked(); @@ -526,20 +527,20 @@ public class PowerManagerServiceTest { when(mWirelessChargerDetectorMock.update(true /* isPowered */, BatteryManager.BATTERY_PLUGGED_WIRELESS)).thenReturn(false); setPluggedIn(true); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); // Test 3: // Do not wake up if the phone is being REMOVED from a wireless charger when(mBatteryManagerInternalMock.getPlugType()).thenReturn(0); setPluggedIn(false); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); // Test 4: // Do not wake if we are dreaming. forceAwake(); // Needs to be awake first before it can dream. forceDream(); setPluggedIn(true); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); forceSleep(); // Test 5: @@ -552,7 +553,7 @@ public class PowerManagerServiceTest { com.android.internal.R.bool.config_allowTheaterModeWakeFromUnplug)) .thenReturn(false); setPluggedIn(false); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); Settings.Global.putInt( mContextSpy.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0); mUserSwitchedReceiver.onReceive(mContextSpy, new Intent(Intent.ACTION_USER_SWITCHED)); @@ -565,14 +566,14 @@ public class PowerManagerServiceTest { forceAwake(); forceDozing(); setPluggedIn(true); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); // Test 7: // Finally, take away all the factors above and ensure the device wakes up! forceAwake(); forceSleep(); setPluggedIn(false); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); } @Test @@ -580,12 +581,12 @@ public class PowerManagerServiceTest { createService(); // Start with AWAKE state startSystem(); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); // Take a nap and verify. mService.getBinderServiceInstance().goToSleep(mClock.now(), PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); } @Test @@ -616,12 +617,12 @@ public class PowerManagerServiceTest { mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); // Verify that we start awake - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); // Grab the wakefulness value when PowerManager finally calls into the // native component to actually perform the suspend. when(mNativeWrapperMock.nativeForceSuspend()).then(inv -> { - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); return true; }); @@ -629,7 +630,7 @@ public class PowerManagerServiceTest { assertThat(retval).isTrue(); // Still asleep when the function returns. - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); } @Test @@ -662,7 +663,7 @@ public class PowerManagerServiceTest { mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); // Verify that we start awake - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); // Create a wakelock mService.getBinderServiceInstance().acquireWakeLock(new Binder(), flags, tag, pkg, @@ -718,7 +719,7 @@ public class PowerManagerServiceTest { // Start with AWAKE state startSystem(); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); assertTrue(isAcquired[0]); // Take a nap and verify we no longer hold the blocker @@ -728,7 +729,7 @@ public class PowerManagerServiceTest { when(mDreamManagerInternalMock.isDreaming()).thenReturn(true); mService.getBinderServiceInstance().goToSleep(mClock.now(), PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); assertFalse(isAcquired[0]); // Override the display state by DreamManager and verify is reacquires the blocker. @@ -841,9 +842,9 @@ public class PowerManagerServiceTest { verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).show(); when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(true); advanceTime(70); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); forceAwake(); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).dismiss(false); } @@ -862,7 +863,7 @@ public class PowerManagerServiceTest { createService(); startSystem(); advanceTime(20); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo( PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE); } @@ -882,9 +883,9 @@ public class PowerManagerServiceTest { PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg, null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); advanceTime(60); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo( PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE); } @@ -912,7 +913,7 @@ public class PowerManagerServiceTest { mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */); advanceTime(520); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo( PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE); } @@ -934,7 +935,7 @@ public class PowerManagerServiceTest { PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS); advanceTime(520); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo( PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE); } @@ -955,7 +956,7 @@ public class PowerManagerServiceTest { PowerManager.USER_ACTIVITY_EVENT_OTHER, 0 /* flags */); advanceTime(520); - assertThat(mService.getWakefulnessLocked()).isNotEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isNotEqualTo(WAKEFULNESS_ASLEEP); } @Test @@ -984,14 +985,14 @@ public class PowerManagerServiceTest { PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg, null /* workSource */, null /* historyTag */, Display.DEFAULT_DISPLAY); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( WAKEFULNESS_AWAKE); advanceTime(15000); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( @@ -1024,14 +1025,14 @@ public class PowerManagerServiceTest { PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg, null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( WAKEFULNESS_AWAKE); advanceTime(15000); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( @@ -1069,14 +1070,14 @@ public class PowerManagerServiceTest { WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( WAKEFULNESS_AWAKE); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); listener.get().onDisplayGroupRemoved(nonDefaultDisplayGroupId); advanceTime(15000); assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( WAKEFULNESS_DOZING); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); } @Test @@ -1084,7 +1085,7 @@ public class PowerManagerServiceTest { createService(); startSystem(); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); verify(mNotifierMock, never()).onWakefulnessChangeStarted(anyInt(), anyInt(), anyLong()); } @@ -1103,7 +1104,7 @@ public class PowerManagerServiceTest { createService(); startSystem(); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); verify(mNotifierMock).onWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP), anyInt(), anyLong()); } @@ -1137,7 +1138,7 @@ public class PowerManagerServiceTest { PowerManager.WAKE_REASON_UNKNOWN, "testing IPowerManager.wakeUp()", "pkg.name"); mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( DisplayPowerRequest.POLICY_BRIGHT); } @@ -1418,23 +1419,23 @@ public class PowerManagerServiceTest { startSystem(); listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0, null, null); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, 0, 0, 0, 0, null, null); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE, 0, 0, 0, 0, null, null); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); } @Test - public void testMultiDisplay_addDisplayGroup_preservesWakefulness() { + public void testMultiDisplay_addDisplayGroup_wakesDeviceUp() { final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; final AtomicReference listener = new AtomicReference<>(); @@ -1446,15 +1447,15 @@ public class PowerManagerServiceTest { createService(); startSystem(); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0, null, null); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); } @Test @@ -1471,18 +1472,79 @@ public class PowerManagerServiceTest { startSystem(); listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0, null, null); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); listener.get().onDisplayGroupRemoved(nonDefaultDisplayGroupId); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE, 0, 0, 0, 0, null, null); - assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + } + + @Test + public void testMultiDisplay_updatesLastGlobalWakeTime() { + final int nonDefaultPowerGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; + final AtomicReference listener = + new AtomicReference<>(); + long eventTime1 = 10; + long eventTime2 = eventTime1 + 1; + long eventTime3 = eventTime2 + 1; + long eventTime4 = eventTime3 + 1; + doAnswer((Answer) invocation -> { + listener.set(invocation.getArgument(0)); + return null; + }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any()); + + createService(); + startSystem(); + listener.get().onDisplayGroupAdded(nonDefaultPowerGroupId); + + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + + mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_DOZING, eventTime1, + 0, PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, 0, null, null); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + + mService.setWakefulnessLocked(nonDefaultPowerGroupId, WAKEFULNESS_DOZING, eventTime2, + 0, PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, null, null); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo( + PowerManager.GO_TO_SLEEP_REASON_APPLICATION); + + mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE, + eventTime3, /* uid= */ 0, PowerManager.WAKE_REASON_PLUGGED_IN, /* opUid= */ + 0, /* opPackageName= */ null, /* details= */ null); + PowerManager.WakeData wakeData = mService.getLocalServiceInstance().getLastWakeup(); + assertThat(wakeData.wakeTime).isEqualTo(eventTime3); + assertThat(wakeData.wakeReason).isEqualTo(PowerManager.WAKE_REASON_PLUGGED_IN); + assertThat(wakeData.sleepDuration).isEqualTo(eventTime3 - eventTime2); + + // The global wake time and reason as well as sleep duration shouldn't change when another + // PowerGroup wakes up. + mService.setWakefulnessLocked(nonDefaultPowerGroupId, WAKEFULNESS_AWAKE, + eventTime4, /* uid= */ 0, PowerManager.WAKE_REASON_CAMERA_LAUNCH, /* opUid= */ + 0, /* opPackageName= */ null, /* details= */ null); + assertThat(wakeData.wakeTime).isEqualTo(eventTime3); + assertThat(wakeData.wakeReason).isEqualTo(PowerManager.WAKE_REASON_PLUGGED_IN); + assertThat(wakeData.sleepDuration).isEqualTo(eventTime3 - eventTime2); + } + + @Test + public void testLastSleepTime_notUpdatedWhenDreaming() { + createService(); + startSystem(); + + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + PowerManager.WakeData initialWakeData = mService.getLocalServiceInstance().getLastWakeup(); + + forceDream(); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); + assertThat(mService.getLocalServiceInstance().getLastWakeup()).isEqualTo(initialWakeData); } @Test