/* * 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.display; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import android.hardware.display.DisplayManagerInternal; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.concurrent.Callable; @SmallTest @RunWith(AndroidJUnit4.class) public final class WakelockControllerTest { private static final int DISPLAY_ID = 1; @Mock private DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks; private WakelockController mWakelockController; @Before public void before() { MockitoAnnotations.initMocks(this); mWakelockController = new WakelockController(DISPLAY_ID, mDisplayPowerCallbacks); } @Test public void validateSuspendBlockerIdsAreExpected() { assertEquals(mWakelockController.getSuspendBlockerUnfinishedBusinessId(), "[" + DISPLAY_ID + "]unfinished business"); assertEquals(mWakelockController.getSuspendBlockerOnStateChangedId(), "[" + DISPLAY_ID + "]on state changed"); assertEquals(mWakelockController.getSuspendBlockerProxPositiveId(), "[" + DISPLAY_ID + "]prox positive"); assertEquals(mWakelockController.getSuspendBlockerProxNegativeId(), "[" + DISPLAY_ID + "]prox negative"); assertEquals(mWakelockController.getSuspendBlockerProxDebounceId(), "[" + DISPLAY_ID + "]prox debounce"); } @Test public void acquireStateChangedSuspendBlockerAcquiresIfNotAcquired() throws Exception { // Acquire verifyWakelockAcquisitionAndReaquisition(WakelockController.WAKE_LOCK_STATE_CHANGED, () -> mWakelockController.isOnStateChangedPending()); // Verify acquire happened only once verify(mDisplayPowerCallbacks, times(1)) .acquireSuspendBlocker(mWakelockController.getSuspendBlockerOnStateChangedId()); // Release verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_STATE_CHANGED, () -> mWakelockController.isOnStateChangedPending()); // Verify release happened only once verify(mDisplayPowerCallbacks, times(1)) .releaseSuspendBlocker(mWakelockController.getSuspendBlockerOnStateChangedId()); } @Test public void acquireUnfinishedBusinessSuspendBlockerAcquiresIfNotAcquired() throws Exception { // Acquire verifyWakelockAcquisitionAndReaquisition(WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS, () -> mWakelockController.hasUnfinishedBusiness()); // Verify acquire happened only once verify(mDisplayPowerCallbacks, times(1)) .acquireSuspendBlocker(mWakelockController.getSuspendBlockerUnfinishedBusinessId()); // Release verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS, () -> mWakelockController.hasUnfinishedBusiness()); // Verify release happened only once verify(mDisplayPowerCallbacks, times(1)) .releaseSuspendBlocker(mWakelockController.getSuspendBlockerUnfinishedBusinessId()); } @Test public void acquireProxPositiveSuspendBlockerAcquiresIfNotAcquired() throws Exception { // Acquire verifyWakelockAcquisitionAndReaquisition(WakelockController.WAKE_LOCK_PROXIMITY_POSITIVE, () -> mWakelockController.isProximityPositiveAcquired()); // Verify acquire happened only once verify(mDisplayPowerCallbacks, times(1)) .acquireSuspendBlocker(mWakelockController.getSuspendBlockerProxPositiveId()); // Release verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_PROXIMITY_POSITIVE, () -> mWakelockController.isProximityPositiveAcquired()); // Verify release happened only once verify(mDisplayPowerCallbacks, times(1)) .releaseSuspendBlocker(mWakelockController.getSuspendBlockerProxPositiveId()); } @Test public void acquireProxNegativeSuspendBlockerAcquiresIfNotAcquired() throws Exception { // Acquire verifyWakelockAcquisitionAndReaquisition(WakelockController.WAKE_LOCK_PROXIMITY_NEGATIVE, () -> mWakelockController.isProximityNegativeAcquired()); // Verify acquire happened only once verify(mDisplayPowerCallbacks, times(1)) .acquireSuspendBlocker(mWakelockController.getSuspendBlockerProxNegativeId()); // Release verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_PROXIMITY_NEGATIVE, () -> mWakelockController.isProximityNegativeAcquired()); // Verify release happened only once verify(mDisplayPowerCallbacks, times(1)) .releaseSuspendBlocker(mWakelockController.getSuspendBlockerProxNegativeId()); } @Test public void acquireProxDebounceSuspendBlockerAcquiresIfNotAcquired() throws Exception { // Acquire the suspend blocker verifyWakelockAcquisitionAndReaquisition(WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE, () -> mWakelockController.hasProximitySensorDebounced()); // Verify acquire happened only once verify(mDisplayPowerCallbacks, times(1)) .acquireSuspendBlocker(mWakelockController.getSuspendBlockerProxDebounceId()); // Release the suspend blocker verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE, () -> mWakelockController.hasProximitySensorDebounced()); // Verify suspend blocker was released only once verify(mDisplayPowerCallbacks, times(1)) .releaseSuspendBlocker(mWakelockController.getSuspendBlockerProxDebounceId()); } @Test public void proximityPositiveRunnableWorksAsExpected() { // Acquire the suspend blocker twice assertTrue(mWakelockController.acquireWakelock( WakelockController.WAKE_LOCK_PROXIMITY_POSITIVE)); // Execute the runnable Runnable proximityPositiveRunnable = mWakelockController.getOnProximityPositiveRunnable(); proximityPositiveRunnable.run(); // Validate one suspend blocker was released assertFalse(mWakelockController.isProximityPositiveAcquired()); verify(mDisplayPowerCallbacks).onProximityPositive(); verify(mDisplayPowerCallbacks).releaseSuspendBlocker( mWakelockController.getSuspendBlockerProxPositiveId()); } @Test public void proximityPositiveRunnableDoesNothingIfNotAcquired() { // Execute the runnable Runnable proximityPositiveRunnable = mWakelockController.getOnProximityPositiveRunnable(); proximityPositiveRunnable.run(); // Validate one suspend blocker was released assertFalse(mWakelockController.isProximityPositiveAcquired()); verifyZeroInteractions(mDisplayPowerCallbacks); } @Test public void proximityNegativeRunnableWorksAsExpected() { // Acquire the suspend blocker twice assertTrue(mWakelockController.acquireWakelock( WakelockController.WAKE_LOCK_PROXIMITY_NEGATIVE)); // Execute the runnable Runnable proximityNegativeRunnable = mWakelockController.getOnProximityNegativeRunnable(); proximityNegativeRunnable.run(); // Validate one suspend blocker was released assertFalse(mWakelockController.isProximityNegativeAcquired()); verify(mDisplayPowerCallbacks).onProximityNegative(); verify(mDisplayPowerCallbacks).releaseSuspendBlocker( mWakelockController.getSuspendBlockerProxNegativeId()); } @Test public void proximityNegativeRunnableDoesNothingIfNotAcquired() { // Execute the runnable Runnable proximityNegativeRunnable = mWakelockController.getOnProximityNegativeRunnable(); proximityNegativeRunnable.run(); // Validate one suspend blocker was released assertFalse(mWakelockController.isProximityNegativeAcquired()); verifyZeroInteractions(mDisplayPowerCallbacks); } @Test public void onStateChangeRunnableWorksAsExpected() { // Acquire the suspend blocker twice assertTrue(mWakelockController.acquireWakelock(WakelockController.WAKE_LOCK_STATE_CHANGED)); // Execute the runnable Runnable stateChangeRunnable = mWakelockController.getOnStateChangedRunnable(); stateChangeRunnable.run(); // Validate one suspend blocker was released assertFalse(mWakelockController.isOnStateChangedPending()); verify(mDisplayPowerCallbacks).onStateChanged(); verify(mDisplayPowerCallbacks).releaseSuspendBlocker( mWakelockController.getSuspendBlockerOnStateChangedId()); } @Test public void onStateChangeRunnableDoesNothingIfNotAcquired() { // Execute the runnable Runnable stateChangeRunnable = mWakelockController.getOnStateChangedRunnable(); stateChangeRunnable.run(); // Validate one suspend blocker was released assertFalse(mWakelockController.isOnStateChangedPending()); verifyZeroInteractions(mDisplayPowerCallbacks); } @Test public void testReleaseAll() throws Exception { // Use WAKE_LOCK_MAX to verify it has been correctly set and used in releaseAll(). verifyWakelockAcquisition(WakelockController.WAKE_LOCK_MAX, () -> mWakelockController.hasUnfinishedBusiness()); mWakelockController.releaseAll(); assertFalse(mWakelockController.hasUnfinishedBusiness()); } private void verifyWakelockAcquisitionAndReaquisition(int wakelockId, Callable isWakelockAcquiredCallable) throws Exception { verifyWakelockAcquisition(wakelockId, isWakelockAcquiredCallable); verifyWakelockReacquisition(wakelockId, isWakelockAcquiredCallable); } private void verifyWakelockReleaseAndRerelease(int wakelockId, Callable isWakelockAcquiredCallable) throws Exception { verifyWakelockRelease(wakelockId, isWakelockAcquiredCallable); verifyWakelockRerelease(wakelockId, isWakelockAcquiredCallable); } private void verifyWakelockAcquisition(int wakelockId, Callable isWakelockAcquiredCallable) throws Exception { assertTrue(mWakelockController.acquireWakelock(wakelockId)); assertTrue(isWakelockAcquiredCallable.call()); } private void verifyWakelockReacquisition(int wakelockId, Callable isWakelockAcquiredCallable) throws Exception { assertFalse(mWakelockController.acquireWakelock(wakelockId)); assertTrue(isWakelockAcquiredCallable.call()); } private void verifyWakelockRelease(int wakelockId, Callable isWakelockAcquiredCallable) throws Exception { assertTrue(mWakelockController.releaseWakelock(wakelockId)); assertFalse(isWakelockAcquiredCallable.call()); } private void verifyWakelockRerelease(int wakelockId, Callable isWakelockAcquiredCallable) throws Exception { assertFalse(mWakelockController.releaseWakelock(wakelockId)); assertFalse(isWakelockAcquiredCallable.call()); } }