Loading services/core/java/com/android/server/display/DisplayPowerController.java +26 −32 Original line number Diff line number Diff line Loading @@ -492,6 +492,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // Used to scale the brightness in doze mode private float mDozeScaleFactor; // Used to keep track of the display state from the latest request to override the doze screen // state. @GuardedBy("mLock") private int mPendingOverrideDozeScreenStateLocked; /** * Creates the display power controller. */ Loading Loading @@ -803,16 +808,29 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Override public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) { Slog.i(TAG, "New offload doze override: " + Display.stateToString(displayState)); mHandler.postAtTime(() -> { if (mDisplayOffloadSession == null || !(DisplayOffloadSession.isSupportedOffloadState(displayState) if (mDisplayOffloadSession != null && (DisplayOffloadSession.isSupportedOffloadState(displayState) || displayState == Display.STATE_UNKNOWN)) { return; if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) { mWakelockController.acquireWakelock( WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE); } synchronized (mLock) { mPendingOverrideDozeScreenStateLocked = displayState; } mHandler.postAtTime(() -> { synchronized (mLock) { mDisplayStateController .overrideDozeScreenState(mPendingOverrideDozeScreenStateLocked, reason); } mDisplayStateController.overrideDozeScreenState(displayState, reason); updatePowerState(); if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) { mWakelockController.releaseWakelock( WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE); } }, mClock.uptimeMillis()); } } @Override public void setDisplayOffloadSession(DisplayOffloadSession session) { Loading Loading @@ -1338,30 +1356,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN); } if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) { // Sometimes, a display-state change can come without an associated PowerRequest, // as with DisplayOffload. For those cases, we have to make sure to also mark the // display as "not ready" so that we can inform power-manager when the state-change is // complete. if (mPowerState.getScreenState() != state) { final boolean wasReady; synchronized (mLock) { wasReady = mDisplayReadyLocked; mDisplayReadyLocked = false; mustNotify = true; } if (wasReady) { // If we went from ready to not-ready from the state-change (instead of a // PowerRequest) there's a good chance that nothing is keeping PowerManager // from suspending. Grab the unfinished business suspend blocker to keep the // device awake until the display-state change goes into effect. mWakelockController.acquireWakelock( WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS); } } } // Animate the screen state change unless already animating. // The transition may be deferred, so after this point we will use the // actual state instead of the desired one. Loading services/core/java/com/android/server/display/WakelockController.java +72 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.hardware.display.DisplayManagerInternal; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.utils.DebugUtils; Loading @@ -37,7 +38,8 @@ public final class WakelockController { public static final int WAKE_LOCK_PROXIMITY_NEGATIVE = 2; public static final int WAKE_LOCK_PROXIMITY_DEBOUNCE = 3; public static final int WAKE_LOCK_STATE_CHANGED = 4; public static final int WAKE_LOCK_UNFINISHED_BUSINESS = 5; public static final int WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE = 5; public static final int WAKE_LOCK_UNFINISHED_BUSINESS = 6; @VisibleForTesting static final int WAKE_LOCK_MAX = WAKE_LOCK_UNFINISHED_BUSINESS; Loading @@ -53,18 +55,23 @@ public final class WakelockController { WAKE_LOCK_PROXIMITY_NEGATIVE, WAKE_LOCK_PROXIMITY_DEBOUNCE, WAKE_LOCK_STATE_CHANGED, WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE, WAKE_LOCK_UNFINISHED_BUSINESS }) @Retention(RetentionPolicy.SOURCE) public @interface WAKE_LOCK_TYPE { } private final Object mLock = new Object(); // Asynchronous callbacks into the power manager service. // Only invoked from the handler thread while no locks are held. private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks; // Identifiers for suspend blocker acquisition requests private final String mSuspendBlockerIdUnfinishedBusiness; @GuardedBy("mLock") private final String mSuspendBlockerOverrideDozeScreenState; private final String mSuspendBlockerIdOnStateChanged; private final String mSuspendBlockerIdProxPositive; private final String mSuspendBlockerIdProxNegative; Loading @@ -73,6 +80,10 @@ public final class WakelockController { // True if we have unfinished business and are holding a suspend-blocker. private boolean mUnfinishedBusiness; // True if we have are holding a suspend-blocker to override the doze screen state. @GuardedBy("mLock") private boolean mIsOverrideDozeScreenStateAcquired; // True if we have have debounced the proximity change impact and are holding a suspend-blocker. private boolean mHasProximityDebounced; Loading Loading @@ -108,6 +119,7 @@ public final class WakelockController { mTag = TAG + "[" + mDisplayId + "]"; mDisplayPowerCallbacks = callbacks; mSuspendBlockerIdUnfinishedBusiness = "[" + displayId + "]unfinished business"; mSuspendBlockerOverrideDozeScreenState = "[" + displayId + "]override doze screen state"; mSuspendBlockerIdOnStateChanged = "[" + displayId + "]on state changed"; mSuspendBlockerIdProxPositive = "[" + displayId + "]prox positive"; mSuspendBlockerIdProxNegative = "[" + displayId + "]prox negative"; Loading Loading @@ -154,6 +166,10 @@ public final class WakelockController { return acquireProxDebounceSuspendBlocker(); case WAKE_LOCK_STATE_CHANGED: return acquireStateChangedSuspendBlocker(); case WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE: synchronized (mLock) { return acquireOverrideDozeScreenStateSuspendBlockerLocked(); } case WAKE_LOCK_UNFINISHED_BUSINESS: return acquireUnfinishedBusinessSuspendBlocker(); default: Loading @@ -171,6 +187,10 @@ public final class WakelockController { return releaseProxDebounceSuspendBlocker(); case WAKE_LOCK_STATE_CHANGED: return releaseStateChangedSuspendBlocker(); case WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE: synchronized (mLock) { return releaseOverrideDozeScreenStateSuspendBlockerLocked(); } case WAKE_LOCK_UNFINISHED_BUSINESS: return releaseUnfinishedBusinessSuspendBlocker(); default: Loading Loading @@ -219,6 +239,42 @@ public final class WakelockController { return false; } /** * Acquires the suspend blocker to override the doze screen state and notifies the * PowerManagerService about the changes. Note that this utility is syncronized because a * request to override the doze screen state can come from a non-power thread. */ @GuardedBy("mLock") private boolean acquireOverrideDozeScreenStateSuspendBlockerLocked() { // Grab a wake lock if we have unfinished business. if (!mIsOverrideDozeScreenStateAcquired) { if (DEBUG) { Slog.d(mTag, "Acquiring suspend blocker to override the doze screen state..."); } mDisplayPowerCallbacks.acquireSuspendBlocker(mSuspendBlockerOverrideDozeScreenState); mIsOverrideDozeScreenStateAcquired = true; return true; } return false; } /** * Releases the override doze screen state suspend blocker and notifies the PowerManagerService * about the changes. */ @GuardedBy("mLock") private boolean releaseOverrideDozeScreenStateSuspendBlockerLocked() { if (mIsOverrideDozeScreenStateAcquired) { if (DEBUG) { Slog.d(mTag, "Finished overriding doze screen state..."); } mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerOverrideDozeScreenState); mIsOverrideDozeScreenStateAcquired = false; return true; } return false; } /** * Acquires the unfinished business wakelock and notifies the PowerManagerService about the * changes. Loading Loading @@ -366,6 +422,7 @@ public final class WakelockController { pw.println(" mOnStateChangePending=" + isOnStateChangedPending()); pw.println(" mOnProximityPositiveMessages=" + isProximityPositiveAcquired()); pw.println(" mOnProximityNegativeMessages=" + isProximityNegativeAcquired()); pw.println(" mIsOverrideDozeScreenStateAcquired=" + isOverrideDozeScreenStateAcquired()); } @VisibleForTesting Loading Loading @@ -393,6 +450,13 @@ public final class WakelockController { return mSuspendBlockerIdProxDebounce; } @VisibleForTesting String getSuspendBlockerOverrideDozeScreenState() { synchronized (mLock) { return mSuspendBlockerOverrideDozeScreenState; } } @VisibleForTesting boolean hasUnfinishedBusiness() { return mUnfinishedBusiness; Loading @@ -417,4 +481,11 @@ public final class WakelockController { boolean hasProximitySensorDebounced() { return mHasProximityDebounced; } @VisibleForTesting boolean isOverrideDozeScreenStateAcquired() { synchronized (mLock) { return mIsOverrideDozeScreenStateAcquired; } } } services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +8 −3 Original line number Diff line number Diff line Loading @@ -1621,16 +1621,21 @@ public final class DisplayPowerControllerTest { advanceTime(1); // Run updatePowerState reset(mHolder.wakelockController); when(mHolder.wakelockController .acquireWakelock(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE)) .thenReturn(true); mHolder.dpc.overrideDozeScreenState( supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); advanceTime(1); // Run updatePowerState // Should get a wakelock to notify powermanager verify(mHolder.wakelockController, atLeastOnce()).acquireWakelock( eq(WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS)); verify(mHolder.wakelockController).acquireWakelock( eq(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE)); advanceTime(1); // Run updatePowerState verify(mHolder.displayPowerState) .setScreenState(supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); verify(mHolder.wakelockController).releaseWakelock( eq(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE)); } @Test Loading services/tests/displayservicetests/src/com/android/server/display/WakelockControllerTest.java +24 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ public final class WakelockControllerTest { "[" + DISPLAY_ID + "]prox negative"); assertEquals(mWakelockController.getSuspendBlockerProxDebounceId(), "[" + DISPLAY_ID + "]prox debounce"); assertEquals(mWakelockController.getSuspendBlockerOverrideDozeScreenState(), "[" + DISPLAY_ID + "]override doze screen state"); } @Test Loading Loading @@ -161,6 +163,28 @@ public final class WakelockControllerTest { .releaseSuspendBlocker(mWakelockController.getSuspendBlockerProxDebounceId()); } @Test public void acquireOverrideDozeScreenStateSuspendBlocker() throws Exception { // Acquire the suspend blocker verifyWakelockAcquisitionAndReaquisition(WakelockController .WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE, () -> mWakelockController.isOverrideDozeScreenStateAcquired()); // Verify acquire happened only once verify(mDisplayPowerCallbacks, times(1)) .acquireSuspendBlocker(mWakelockController .getSuspendBlockerOverrideDozeScreenState()); // Release the suspend blocker verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE, () -> mWakelockController.isOverrideDozeScreenStateAcquired()); // Verify suspend blocker was released only once verify(mDisplayPowerCallbacks, times(1)) .releaseSuspendBlocker(mWakelockController .getSuspendBlockerOverrideDozeScreenState()); } @Test public void proximityPositiveRunnableWorksAsExpected() { // Acquire the suspend blocker twice Loading Loading
services/core/java/com/android/server/display/DisplayPowerController.java +26 −32 Original line number Diff line number Diff line Loading @@ -492,6 +492,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // Used to scale the brightness in doze mode private float mDozeScaleFactor; // Used to keep track of the display state from the latest request to override the doze screen // state. @GuardedBy("mLock") private int mPendingOverrideDozeScreenStateLocked; /** * Creates the display power controller. */ Loading Loading @@ -803,16 +808,29 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Override public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) { Slog.i(TAG, "New offload doze override: " + Display.stateToString(displayState)); mHandler.postAtTime(() -> { if (mDisplayOffloadSession == null || !(DisplayOffloadSession.isSupportedOffloadState(displayState) if (mDisplayOffloadSession != null && (DisplayOffloadSession.isSupportedOffloadState(displayState) || displayState == Display.STATE_UNKNOWN)) { return; if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) { mWakelockController.acquireWakelock( WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE); } synchronized (mLock) { mPendingOverrideDozeScreenStateLocked = displayState; } mHandler.postAtTime(() -> { synchronized (mLock) { mDisplayStateController .overrideDozeScreenState(mPendingOverrideDozeScreenStateLocked, reason); } mDisplayStateController.overrideDozeScreenState(displayState, reason); updatePowerState(); if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) { mWakelockController.releaseWakelock( WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE); } }, mClock.uptimeMillis()); } } @Override public void setDisplayOffloadSession(DisplayOffloadSession session) { Loading Loading @@ -1338,30 +1356,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN); } if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) { // Sometimes, a display-state change can come without an associated PowerRequest, // as with DisplayOffload. For those cases, we have to make sure to also mark the // display as "not ready" so that we can inform power-manager when the state-change is // complete. if (mPowerState.getScreenState() != state) { final boolean wasReady; synchronized (mLock) { wasReady = mDisplayReadyLocked; mDisplayReadyLocked = false; mustNotify = true; } if (wasReady) { // If we went from ready to not-ready from the state-change (instead of a // PowerRequest) there's a good chance that nothing is keeping PowerManager // from suspending. Grab the unfinished business suspend blocker to keep the // device awake until the display-state change goes into effect. mWakelockController.acquireWakelock( WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS); } } } // Animate the screen state change unless already animating. // The transition may be deferred, so after this point we will use the // actual state instead of the desired one. Loading
services/core/java/com/android/server/display/WakelockController.java +72 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.hardware.display.DisplayManagerInternal; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.utils.DebugUtils; Loading @@ -37,7 +38,8 @@ public final class WakelockController { public static final int WAKE_LOCK_PROXIMITY_NEGATIVE = 2; public static final int WAKE_LOCK_PROXIMITY_DEBOUNCE = 3; public static final int WAKE_LOCK_STATE_CHANGED = 4; public static final int WAKE_LOCK_UNFINISHED_BUSINESS = 5; public static final int WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE = 5; public static final int WAKE_LOCK_UNFINISHED_BUSINESS = 6; @VisibleForTesting static final int WAKE_LOCK_MAX = WAKE_LOCK_UNFINISHED_BUSINESS; Loading @@ -53,18 +55,23 @@ public final class WakelockController { WAKE_LOCK_PROXIMITY_NEGATIVE, WAKE_LOCK_PROXIMITY_DEBOUNCE, WAKE_LOCK_STATE_CHANGED, WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE, WAKE_LOCK_UNFINISHED_BUSINESS }) @Retention(RetentionPolicy.SOURCE) public @interface WAKE_LOCK_TYPE { } private final Object mLock = new Object(); // Asynchronous callbacks into the power manager service. // Only invoked from the handler thread while no locks are held. private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks; // Identifiers for suspend blocker acquisition requests private final String mSuspendBlockerIdUnfinishedBusiness; @GuardedBy("mLock") private final String mSuspendBlockerOverrideDozeScreenState; private final String mSuspendBlockerIdOnStateChanged; private final String mSuspendBlockerIdProxPositive; private final String mSuspendBlockerIdProxNegative; Loading @@ -73,6 +80,10 @@ public final class WakelockController { // True if we have unfinished business and are holding a suspend-blocker. private boolean mUnfinishedBusiness; // True if we have are holding a suspend-blocker to override the doze screen state. @GuardedBy("mLock") private boolean mIsOverrideDozeScreenStateAcquired; // True if we have have debounced the proximity change impact and are holding a suspend-blocker. private boolean mHasProximityDebounced; Loading Loading @@ -108,6 +119,7 @@ public final class WakelockController { mTag = TAG + "[" + mDisplayId + "]"; mDisplayPowerCallbacks = callbacks; mSuspendBlockerIdUnfinishedBusiness = "[" + displayId + "]unfinished business"; mSuspendBlockerOverrideDozeScreenState = "[" + displayId + "]override doze screen state"; mSuspendBlockerIdOnStateChanged = "[" + displayId + "]on state changed"; mSuspendBlockerIdProxPositive = "[" + displayId + "]prox positive"; mSuspendBlockerIdProxNegative = "[" + displayId + "]prox negative"; Loading Loading @@ -154,6 +166,10 @@ public final class WakelockController { return acquireProxDebounceSuspendBlocker(); case WAKE_LOCK_STATE_CHANGED: return acquireStateChangedSuspendBlocker(); case WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE: synchronized (mLock) { return acquireOverrideDozeScreenStateSuspendBlockerLocked(); } case WAKE_LOCK_UNFINISHED_BUSINESS: return acquireUnfinishedBusinessSuspendBlocker(); default: Loading @@ -171,6 +187,10 @@ public final class WakelockController { return releaseProxDebounceSuspendBlocker(); case WAKE_LOCK_STATE_CHANGED: return releaseStateChangedSuspendBlocker(); case WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE: synchronized (mLock) { return releaseOverrideDozeScreenStateSuspendBlockerLocked(); } case WAKE_LOCK_UNFINISHED_BUSINESS: return releaseUnfinishedBusinessSuspendBlocker(); default: Loading Loading @@ -219,6 +239,42 @@ public final class WakelockController { return false; } /** * Acquires the suspend blocker to override the doze screen state and notifies the * PowerManagerService about the changes. Note that this utility is syncronized because a * request to override the doze screen state can come from a non-power thread. */ @GuardedBy("mLock") private boolean acquireOverrideDozeScreenStateSuspendBlockerLocked() { // Grab a wake lock if we have unfinished business. if (!mIsOverrideDozeScreenStateAcquired) { if (DEBUG) { Slog.d(mTag, "Acquiring suspend blocker to override the doze screen state..."); } mDisplayPowerCallbacks.acquireSuspendBlocker(mSuspendBlockerOverrideDozeScreenState); mIsOverrideDozeScreenStateAcquired = true; return true; } return false; } /** * Releases the override doze screen state suspend blocker and notifies the PowerManagerService * about the changes. */ @GuardedBy("mLock") private boolean releaseOverrideDozeScreenStateSuspendBlockerLocked() { if (mIsOverrideDozeScreenStateAcquired) { if (DEBUG) { Slog.d(mTag, "Finished overriding doze screen state..."); } mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerOverrideDozeScreenState); mIsOverrideDozeScreenStateAcquired = false; return true; } return false; } /** * Acquires the unfinished business wakelock and notifies the PowerManagerService about the * changes. Loading Loading @@ -366,6 +422,7 @@ public final class WakelockController { pw.println(" mOnStateChangePending=" + isOnStateChangedPending()); pw.println(" mOnProximityPositiveMessages=" + isProximityPositiveAcquired()); pw.println(" mOnProximityNegativeMessages=" + isProximityNegativeAcquired()); pw.println(" mIsOverrideDozeScreenStateAcquired=" + isOverrideDozeScreenStateAcquired()); } @VisibleForTesting Loading Loading @@ -393,6 +450,13 @@ public final class WakelockController { return mSuspendBlockerIdProxDebounce; } @VisibleForTesting String getSuspendBlockerOverrideDozeScreenState() { synchronized (mLock) { return mSuspendBlockerOverrideDozeScreenState; } } @VisibleForTesting boolean hasUnfinishedBusiness() { return mUnfinishedBusiness; Loading @@ -417,4 +481,11 @@ public final class WakelockController { boolean hasProximitySensorDebounced() { return mHasProximityDebounced; } @VisibleForTesting boolean isOverrideDozeScreenStateAcquired() { synchronized (mLock) { return mIsOverrideDozeScreenStateAcquired; } } }
services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +8 −3 Original line number Diff line number Diff line Loading @@ -1621,16 +1621,21 @@ public final class DisplayPowerControllerTest { advanceTime(1); // Run updatePowerState reset(mHolder.wakelockController); when(mHolder.wakelockController .acquireWakelock(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE)) .thenReturn(true); mHolder.dpc.overrideDozeScreenState( supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); advanceTime(1); // Run updatePowerState // Should get a wakelock to notify powermanager verify(mHolder.wakelockController, atLeastOnce()).acquireWakelock( eq(WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS)); verify(mHolder.wakelockController).acquireWakelock( eq(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE)); advanceTime(1); // Run updatePowerState verify(mHolder.displayPowerState) .setScreenState(supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); verify(mHolder.wakelockController).releaseWakelock( eq(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE)); } @Test Loading
services/tests/displayservicetests/src/com/android/server/display/WakelockControllerTest.java +24 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ public final class WakelockControllerTest { "[" + DISPLAY_ID + "]prox negative"); assertEquals(mWakelockController.getSuspendBlockerProxDebounceId(), "[" + DISPLAY_ID + "]prox debounce"); assertEquals(mWakelockController.getSuspendBlockerOverrideDozeScreenState(), "[" + DISPLAY_ID + "]override doze screen state"); } @Test Loading Loading @@ -161,6 +163,28 @@ public final class WakelockControllerTest { .releaseSuspendBlocker(mWakelockController.getSuspendBlockerProxDebounceId()); } @Test public void acquireOverrideDozeScreenStateSuspendBlocker() throws Exception { // Acquire the suspend blocker verifyWakelockAcquisitionAndReaquisition(WakelockController .WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE, () -> mWakelockController.isOverrideDozeScreenStateAcquired()); // Verify acquire happened only once verify(mDisplayPowerCallbacks, times(1)) .acquireSuspendBlocker(mWakelockController .getSuspendBlockerOverrideDozeScreenState()); // Release the suspend blocker verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE, () -> mWakelockController.isOverrideDozeScreenStateAcquired()); // Verify suspend blocker was released only once verify(mDisplayPowerCallbacks, times(1)) .releaseSuspendBlocker(mWakelockController .getSuspendBlockerOverrideDozeScreenState()); } @Test public void proximityPositiveRunnableWorksAsExpected() { // Acquire the suspend blocker twice Loading