1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.display;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 import static org.mockito.Mockito.times;
23 import static org.mockito.Mockito.verify;
24 import static org.mockito.Mockito.verifyZeroInteractions;
25 
26 import android.hardware.display.DisplayManagerInternal;
27 
28 import androidx.test.filters.SmallTest;
29 import androidx.test.runner.AndroidJUnit4;
30 
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import org.mockito.Mock;
35 import org.mockito.MockitoAnnotations;
36 
37 import java.util.concurrent.Callable;
38 
39 @SmallTest
40 @RunWith(AndroidJUnit4.class)
41 public final class WakelockControllerTest {
42     private static final int DISPLAY_ID = 1;
43 
44     @Mock
45     private DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks;
46 
47     private WakelockController mWakelockController;
48 
49     @Before
before()50     public void before() {
51         MockitoAnnotations.initMocks(this);
52         mWakelockController = new WakelockController(DISPLAY_ID, mDisplayPowerCallbacks);
53     }
54 
55     @Test
validateSuspendBlockerIdsAreExpected()56     public void validateSuspendBlockerIdsAreExpected() {
57         assertEquals(mWakelockController.getSuspendBlockerUnfinishedBusinessId(),
58                 "[" + DISPLAY_ID + "]unfinished business");
59         assertEquals(mWakelockController.getSuspendBlockerOnStateChangedId(),
60                 "[" + DISPLAY_ID + "]on state changed");
61         assertEquals(mWakelockController.getSuspendBlockerProxPositiveId(),
62                 "[" + DISPLAY_ID + "]prox positive");
63         assertEquals(mWakelockController.getSuspendBlockerProxNegativeId(),
64                 "[" + DISPLAY_ID + "]prox negative");
65         assertEquals(mWakelockController.getSuspendBlockerProxDebounceId(),
66                 "[" + DISPLAY_ID + "]prox debounce");
67     }
68 
69     @Test
acquireStateChangedSuspendBlockerAcquiresIfNotAcquired()70     public void acquireStateChangedSuspendBlockerAcquiresIfNotAcquired() throws Exception {
71         // Acquire
72         verifyWakelockAcquisitionAndReaquisition(WakelockController.WAKE_LOCK_STATE_CHANGED,
73                 () -> mWakelockController.isOnStateChangedPending());
74 
75         // Verify acquire happened only once
76         verify(mDisplayPowerCallbacks, times(1))
77                 .acquireSuspendBlocker(mWakelockController.getSuspendBlockerOnStateChangedId());
78 
79         // Release
80         verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_STATE_CHANGED,
81                 () -> mWakelockController.isOnStateChangedPending());
82 
83         // Verify release happened only once
84         verify(mDisplayPowerCallbacks, times(1))
85                 .releaseSuspendBlocker(mWakelockController.getSuspendBlockerOnStateChangedId());
86     }
87 
88     @Test
acquireUnfinishedBusinessSuspendBlockerAcquiresIfNotAcquired()89     public void acquireUnfinishedBusinessSuspendBlockerAcquiresIfNotAcquired() throws Exception {
90         // Acquire
91         verifyWakelockAcquisitionAndReaquisition(WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS,
92                 () -> mWakelockController.hasUnfinishedBusiness());
93 
94         // Verify acquire happened only once
95         verify(mDisplayPowerCallbacks, times(1))
96                 .acquireSuspendBlocker(mWakelockController.getSuspendBlockerUnfinishedBusinessId());
97 
98         // Release
99         verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS,
100                 () -> mWakelockController.hasUnfinishedBusiness());
101 
102         // Verify release happened only once
103         verify(mDisplayPowerCallbacks, times(1))
104                 .releaseSuspendBlocker(mWakelockController.getSuspendBlockerUnfinishedBusinessId());
105     }
106 
107     @Test
acquireProxPositiveSuspendBlockerAcquiresIfNotAcquired()108     public void acquireProxPositiveSuspendBlockerAcquiresIfNotAcquired() throws Exception {
109         // Acquire
110         verifyWakelockAcquisitionAndReaquisition(WakelockController.WAKE_LOCK_PROXIMITY_POSITIVE,
111                 () -> mWakelockController.isProximityPositiveAcquired());
112 
113         // Verify acquire happened only once
114         verify(mDisplayPowerCallbacks, times(1))
115                 .acquireSuspendBlocker(mWakelockController.getSuspendBlockerProxPositiveId());
116 
117         // Release
118         verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_PROXIMITY_POSITIVE,
119                 () -> mWakelockController.isProximityPositiveAcquired());
120 
121         // Verify release happened only once
122         verify(mDisplayPowerCallbacks, times(1))
123                 .releaseSuspendBlocker(mWakelockController.getSuspendBlockerProxPositiveId());
124     }
125 
126     @Test
acquireProxNegativeSuspendBlockerAcquiresIfNotAcquired()127     public void acquireProxNegativeSuspendBlockerAcquiresIfNotAcquired() throws Exception {
128         // Acquire
129         verifyWakelockAcquisitionAndReaquisition(WakelockController.WAKE_LOCK_PROXIMITY_NEGATIVE,
130                 () -> mWakelockController.isProximityNegativeAcquired());
131 
132         // Verify acquire happened only once
133         verify(mDisplayPowerCallbacks, times(1))
134                 .acquireSuspendBlocker(mWakelockController.getSuspendBlockerProxNegativeId());
135 
136         // Release
137         verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_PROXIMITY_NEGATIVE,
138                 () -> mWakelockController.isProximityNegativeAcquired());
139 
140         // Verify release happened only once
141         verify(mDisplayPowerCallbacks, times(1))
142                 .releaseSuspendBlocker(mWakelockController.getSuspendBlockerProxNegativeId());
143     }
144 
145     @Test
acquireProxDebounceSuspendBlockerAcquiresIfNotAcquired()146     public void acquireProxDebounceSuspendBlockerAcquiresIfNotAcquired() throws Exception {
147         // Acquire the suspend blocker
148         verifyWakelockAcquisitionAndReaquisition(WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE,
149                 () -> mWakelockController.hasProximitySensorDebounced());
150 
151         // Verify acquire happened only once
152         verify(mDisplayPowerCallbacks, times(1))
153                 .acquireSuspendBlocker(mWakelockController.getSuspendBlockerProxDebounceId());
154 
155         // Release the suspend blocker
156         verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE,
157                 () -> mWakelockController.hasProximitySensorDebounced());
158 
159         // Verify suspend blocker was released only once
160         verify(mDisplayPowerCallbacks, times(1))
161                 .releaseSuspendBlocker(mWakelockController.getSuspendBlockerProxDebounceId());
162     }
163 
164     @Test
proximityPositiveRunnableWorksAsExpected()165     public void proximityPositiveRunnableWorksAsExpected() {
166         // Acquire the suspend blocker twice
167         assertTrue(mWakelockController.acquireWakelock(
168                 WakelockController.WAKE_LOCK_PROXIMITY_POSITIVE));
169 
170         // Execute the runnable
171         Runnable proximityPositiveRunnable = mWakelockController.getOnProximityPositiveRunnable();
172         proximityPositiveRunnable.run();
173 
174         // Validate one suspend blocker was released
175         assertFalse(mWakelockController.isProximityPositiveAcquired());
176         verify(mDisplayPowerCallbacks).onProximityPositive();
177         verify(mDisplayPowerCallbacks).releaseSuspendBlocker(
178                 mWakelockController.getSuspendBlockerProxPositiveId());
179     }
180 
181     @Test
proximityPositiveRunnableDoesNothingIfNotAcquired()182     public void proximityPositiveRunnableDoesNothingIfNotAcquired() {
183         // Execute the runnable
184         Runnable proximityPositiveRunnable = mWakelockController.getOnProximityPositiveRunnable();
185         proximityPositiveRunnable.run();
186 
187         // Validate one suspend blocker was released
188         assertFalse(mWakelockController.isProximityPositiveAcquired());
189         verifyZeroInteractions(mDisplayPowerCallbacks);
190     }
191 
192     @Test
proximityNegativeRunnableWorksAsExpected()193     public void proximityNegativeRunnableWorksAsExpected() {
194         // Acquire the suspend blocker twice
195         assertTrue(mWakelockController.acquireWakelock(
196                 WakelockController.WAKE_LOCK_PROXIMITY_NEGATIVE));
197 
198         // Execute the runnable
199         Runnable proximityNegativeRunnable = mWakelockController.getOnProximityNegativeRunnable();
200         proximityNegativeRunnable.run();
201 
202         // Validate one suspend blocker was released
203         assertFalse(mWakelockController.isProximityNegativeAcquired());
204         verify(mDisplayPowerCallbacks).onProximityNegative();
205         verify(mDisplayPowerCallbacks).releaseSuspendBlocker(
206                 mWakelockController.getSuspendBlockerProxNegativeId());
207     }
208 
209     @Test
proximityNegativeRunnableDoesNothingIfNotAcquired()210     public void proximityNegativeRunnableDoesNothingIfNotAcquired() {
211         // Execute the runnable
212         Runnable proximityNegativeRunnable = mWakelockController.getOnProximityNegativeRunnable();
213         proximityNegativeRunnable.run();
214 
215         // Validate one suspend blocker was released
216         assertFalse(mWakelockController.isProximityNegativeAcquired());
217         verifyZeroInteractions(mDisplayPowerCallbacks);
218     }
219 
220     @Test
onStateChangeRunnableWorksAsExpected()221     public void onStateChangeRunnableWorksAsExpected() {
222         // Acquire the suspend blocker twice
223         assertTrue(mWakelockController.acquireWakelock(WakelockController.WAKE_LOCK_STATE_CHANGED));
224 
225         // Execute the runnable
226         Runnable stateChangeRunnable = mWakelockController.getOnStateChangedRunnable();
227         stateChangeRunnable.run();
228 
229         // Validate one suspend blocker was released
230         assertFalse(mWakelockController.isOnStateChangedPending());
231         verify(mDisplayPowerCallbacks).onStateChanged();
232         verify(mDisplayPowerCallbacks).releaseSuspendBlocker(
233                 mWakelockController.getSuspendBlockerOnStateChangedId());
234     }
235 
236     @Test
onStateChangeRunnableDoesNothingIfNotAcquired()237     public void onStateChangeRunnableDoesNothingIfNotAcquired() {
238         // Execute the runnable
239         Runnable stateChangeRunnable = mWakelockController.getOnStateChangedRunnable();
240         stateChangeRunnable.run();
241 
242         // Validate one suspend blocker was released
243         assertFalse(mWakelockController.isOnStateChangedPending());
244         verifyZeroInteractions(mDisplayPowerCallbacks);
245     }
246 
247     @Test
testReleaseAll()248     public void testReleaseAll() throws Exception {
249         // Use WAKE_LOCK_MAX to verify it has been correctly set and used in releaseAll().
250         verifyWakelockAcquisition(WakelockController.WAKE_LOCK_MAX,
251                 () -> mWakelockController.hasUnfinishedBusiness());
252         mWakelockController.releaseAll();
253         assertFalse(mWakelockController.hasUnfinishedBusiness());
254     }
255 
verifyWakelockAcquisitionAndReaquisition(int wakelockId, Callable<Boolean> isWakelockAcquiredCallable)256     private void verifyWakelockAcquisitionAndReaquisition(int wakelockId,
257             Callable<Boolean> isWakelockAcquiredCallable)
258             throws Exception {
259         verifyWakelockAcquisition(wakelockId, isWakelockAcquiredCallable);
260         verifyWakelockReacquisition(wakelockId, isWakelockAcquiredCallable);
261     }
262 
verifyWakelockReleaseAndRerelease(int wakelockId, Callable<Boolean> isWakelockAcquiredCallable)263     private void verifyWakelockReleaseAndRerelease(int wakelockId,
264             Callable<Boolean> isWakelockAcquiredCallable)
265             throws Exception {
266         verifyWakelockRelease(wakelockId, isWakelockAcquiredCallable);
267         verifyWakelockRerelease(wakelockId, isWakelockAcquiredCallable);
268     }
269 
verifyWakelockAcquisition(int wakelockId, Callable<Boolean> isWakelockAcquiredCallable)270     private void verifyWakelockAcquisition(int wakelockId,
271             Callable<Boolean> isWakelockAcquiredCallable)
272             throws Exception {
273         assertTrue(mWakelockController.acquireWakelock(wakelockId));
274         assertTrue(isWakelockAcquiredCallable.call());
275     }
276 
verifyWakelockReacquisition(int wakelockId, Callable<Boolean> isWakelockAcquiredCallable)277     private void verifyWakelockReacquisition(int wakelockId,
278             Callable<Boolean> isWakelockAcquiredCallable)
279             throws Exception {
280         assertFalse(mWakelockController.acquireWakelock(wakelockId));
281         assertTrue(isWakelockAcquiredCallable.call());
282     }
283 
verifyWakelockRelease(int wakelockId, Callable<Boolean> isWakelockAcquiredCallable)284     private void verifyWakelockRelease(int wakelockId, Callable<Boolean> isWakelockAcquiredCallable)
285             throws Exception {
286         assertTrue(mWakelockController.releaseWakelock(wakelockId));
287         assertFalse(isWakelockAcquiredCallable.call());
288     }
289 
verifyWakelockRerelease(int wakelockId, Callable<Boolean> isWakelockAcquiredCallable)290     private void verifyWakelockRerelease(int wakelockId,
291             Callable<Boolean> isWakelockAcquiredCallable)
292             throws Exception {
293         assertFalse(mWakelockController.releaseWakelock(wakelockId));
294         assertFalse(isWakelockAcquiredCallable.call());
295     }
296 }
297