blob: 44769180824e32743a113d1307d551008731da92 [file] [log] [blame]
Lucas Dupin0a5d7972019-01-16 18:52:30 -08001/*
2 * Copyright (C) 2019 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
17package com.android.server.power;
18
19import static android.os.BatteryStats.Uid.NUM_USER_ACTIVITY_TYPES;
20
21import static com.google.common.truth.Truth.assertThat;
22
23import static org.mockito.ArgumentMatchers.any;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080024import static org.mockito.ArgumentMatchers.anyLong;
Alex Salo69ff3212019-04-06 16:24:00 -070025import static org.mockito.Mockito.atMost;
Alex Salocbe610a2019-05-01 14:18:46 -070026import static org.mockito.Mockito.clearInvocations;
Alex Salo69ff3212019-04-06 16:24:00 -070027import static org.mockito.Mockito.doAnswer;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080028import static org.mockito.Mockito.never;
29import static org.mockito.Mockito.reset;
30import static org.mockito.Mockito.verify;
31import static org.mockito.Mockito.when;
32
33import android.attention.AttentionManagerInternal;
Alex Saloeeba0232019-03-14 18:56:54 -070034import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
Alex Salo2b7dbe82019-04-11 14:45:42 -070035import android.content.pm.PackageManager;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080036import android.os.PowerManager;
37import android.os.PowerManagerInternal;
38import android.os.SystemClock;
Alex Salo9af68f12019-02-15 13:50:11 -080039import android.os.UserHandle;
40import android.provider.Settings;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080041import android.service.attention.AttentionService;
42import android.test.AndroidTestCase;
43import android.test.suitebuilder.annotation.SmallTest;
44
Alex Salo49489762019-06-03 16:23:30 -070045import com.android.server.wm.WindowManagerInternal;
46
Alex Salo9af68f12019-02-15 13:50:11 -080047import org.junit.After;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080048import org.junit.Before;
49import org.junit.Test;
Alex Saloeeba0232019-03-14 18:56:54 -070050import org.mockito.ArgumentCaptor;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080051import org.mockito.Mock;
52import org.mockito.MockitoAnnotations;
53
54@SmallTest
55public class AttentionDetectorTest extends AndroidTestCase {
56
Alex Saloeeba0232019-03-14 18:56:54 -070057 @Mock
Alex Salo2b7dbe82019-04-11 14:45:42 -070058 private PackageManager mPackageManager;
59 @Mock
Alex Saloeeba0232019-03-14 18:56:54 -070060 private AttentionManagerInternal mAttentionManagerInternal;
61 @Mock
Alex Salo49489762019-06-03 16:23:30 -070062 private WindowManagerInternal mWindowManagerInternal;
63 @Mock
Alex Saloeeba0232019-03-14 18:56:54 -070064 private Runnable mOnUserAttention;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080065 private TestableAttentionDetector mAttentionDetector;
66 private long mAttentionTimeout;
67 private long mNextDimming;
Alex Salo9af68f12019-02-15 13:50:11 -080068 private int mIsSettingEnabled;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080069
70 @Before
71 public void setUp() {
72 MockitoAnnotations.initMocks(this);
Alex Salo2b7dbe82019-04-11 14:45:42 -070073 when(mPackageManager.getAttentionServicePackageName()).thenReturn("com.google.android.as");
74 when(mPackageManager.checkPermission(any(), any())).thenReturn(
75 PackageManager.PERMISSION_GRANTED);
Alex Saloeeba0232019-03-14 18:56:54 -070076 when(mAttentionManagerInternal.checkAttention(anyLong(), any()))
Lucas Dupin0a5d7972019-01-16 18:52:30 -080077 .thenReturn(true);
Alex Salo49489762019-06-03 16:23:30 -070078 when(mWindowManagerInternal.isKeyguardShowingAndNotOccluded()).thenReturn(false);
Lucas Dupin0a5d7972019-01-16 18:52:30 -080079 mAttentionDetector = new TestableAttentionDetector();
80 mAttentionDetector.onWakefulnessChangeStarted(PowerManagerInternal.WAKEFULNESS_AWAKE);
81 mAttentionDetector.setAttentionServiceSupported(true);
82 mNextDimming = SystemClock.uptimeMillis() + 3000L;
Alex Salo9af68f12019-02-15 13:50:11 -080083
84 // Save the existing state.
85 mIsSettingEnabled = Settings.System.getIntForUser(getContext().getContentResolver(),
86 Settings.System.ADAPTIVE_SLEEP, 0, UserHandle.USER_CURRENT);
87
88 Settings.System.putIntForUser(getContext().getContentResolver(),
89 Settings.System.ADAPTIVE_SLEEP, 1, UserHandle.USER_CURRENT);
90 mAttentionDetector.updateEnabledFromSettings(getContext());
91 }
92
93 @After
94 public void tearDown() {
95 Settings.System.putIntForUser(getContext().getContentResolver(),
96 Settings.System.ADAPTIVE_SLEEP, mIsSettingEnabled, UserHandle.USER_CURRENT);
Lucas Dupin0a5d7972019-01-16 18:52:30 -080097 }
98
99 @Test
100 public void testOnUserActivity_checksAttention() {
101 long when = registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -0700102 verify(mAttentionManagerInternal).checkAttention(anyLong(), any());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800103 assertThat(when).isLessThan(mNextDimming);
104 }
105
106 @Test
Alex Salo9af68f12019-02-15 13:50:11 -0800107 public void testOnUserActivity_doesntCheckIfNotEnabled() {
108 Settings.System.putIntForUser(getContext().getContentResolver(),
109 Settings.System.ADAPTIVE_SLEEP, 0, UserHandle.USER_CURRENT);
110 mAttentionDetector.updateEnabledFromSettings(getContext());
111 long when = registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -0700112 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
Alex Salo9af68f12019-02-15 13:50:11 -0800113 assertThat(mNextDimming).isEqualTo(when);
114 }
115
116 @Test
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800117 public void testOnUserActivity_doesntCheckIfNotSupported() {
118 mAttentionDetector.setAttentionServiceSupported(false);
119 long when = registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -0700120 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800121 assertThat(mNextDimming).isEqualTo(when);
122 }
123
124 @Test
Alex Salo49489762019-06-03 16:23:30 -0700125 public void testOnUserActivity_doesntCheckIfInLockscreen() {
126 when(mWindowManagerInternal.isKeyguardShowingAndNotOccluded()).thenReturn(true);
127
128 long when = registerAttention();
129 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
130 assertThat(mNextDimming).isEqualTo(when);
131 }
132
133 @Test
Alex Salo2b7dbe82019-04-11 14:45:42 -0700134 public void testOnUserActivity_doesntCheckIfNotSufficientPermissions() {
135 when(mPackageManager.checkPermission(any(), any())).thenReturn(
136 PackageManager.PERMISSION_DENIED);
137
138 long when = registerAttention();
139 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
140 assertThat(mNextDimming).isEqualTo(when);
141 }
142
143 @Test
144 public void testOnUserActivity_disablesSettingIfNotSufficientPermissions() {
145 when(mPackageManager.checkPermission(any(), any())).thenReturn(
146 PackageManager.PERMISSION_DENIED);
147
148 registerAttention();
149 boolean enabled = Settings.System.getIntForUser(getContext().getContentResolver(),
150 Settings.System.ADAPTIVE_SLEEP, 0, UserHandle.USER_CURRENT) == 1;
151 assertFalse(enabled);
152 }
153
154 @Test
Alex Salo7a6e3a62019-02-27 15:08:15 -0800155 public void testOnUserActivity_doesntCrashIfNoAttentionService() {
156 mAttentionManagerInternal = null;
157 registerAttention();
158 // Does not crash.
159 }
160
161 @Test
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800162 public void onUserActivity_ignoresWhiteListedActivityTypes() {
163 for (int i = 0; i < NUM_USER_ACTIVITY_TYPES; i++) {
164 int result = mAttentionDetector.onUserActivity(SystemClock.uptimeMillis(), i);
165 if (result == -1) {
166 throw new AssertionError("User activity " + i + " isn't listed in"
167 + " AttentionDetector#onUserActivity. Please consider how this new activity"
168 + " type affects the attention service.");
169 }
170 }
171 }
172
173 @Test
174 public void testUpdateUserActivity_ignoresWhenItsNotTimeYet() {
175 long now = SystemClock.uptimeMillis();
176 mNextDimming = now;
177 mAttentionDetector.onUserActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH);
178 mAttentionDetector.updateUserActivity(mNextDimming + 5000L);
Alex Saloeeba0232019-03-14 18:56:54 -0700179 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800180 }
181
182 @Test
Alex Salo1761fce2019-02-13 15:54:50 -0800183 public void testUpdateUserActivity_schedulesTheNextCheck() {
184 long now = SystemClock.uptimeMillis();
185 mNextDimming = now;
186 mAttentionDetector.onUserActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH);
187 long nextTimeout = mAttentionDetector.updateUserActivity(mNextDimming + 5000L);
188 assertThat(nextTimeout).isEqualTo(mNextDimming + 5000L);
189 }
190
191 @Test
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800192 public void testOnUserActivity_ignoresAfterMaximumExtension() {
193 long now = SystemClock.uptimeMillis();
194 mAttentionDetector.onUserActivity(now - 15000L, PowerManager.USER_ACTIVITY_EVENT_TOUCH);
195 mAttentionDetector.updateUserActivity(now + 2000L);
Alex Saloeeba0232019-03-14 18:56:54 -0700196 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800197 }
198
199 @Test
Alex Salocbe610a2019-05-01 14:18:46 -0700200 public void testOnUserActivity_ignoresIfAlreadyDoneForThatNextScreenDimming() {
201 long when = registerAttention();
202 verify(mAttentionManagerInternal).checkAttention(anyLong(), any());
203 assertThat(when).isLessThan(mNextDimming);
204 clearInvocations(mAttentionManagerInternal);
205
206 long redundantWhen = mAttentionDetector.updateUserActivity(mNextDimming);
207 assertThat(redundantWhen).isEqualTo(mNextDimming);
208 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
209 }
210
211 @Test
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800212 public void testOnUserActivity_skipsIfAlreadyScheduled() {
213 registerAttention();
214 reset(mAttentionManagerInternal);
Alex Salocbe610a2019-05-01 14:18:46 -0700215 long when = mAttentionDetector.updateUserActivity(mNextDimming + 1);
Alex Saloeeba0232019-03-14 18:56:54 -0700216 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800217 assertThat(when).isLessThan(mNextDimming);
218 }
219
220 @Test
221 public void testOnWakefulnessChangeStarted_cancelsRequestWhenNotAwake() {
222 registerAttention();
223 mAttentionDetector.onWakefulnessChangeStarted(PowerManagerInternal.WAKEFULNESS_ASLEEP);
Alex Saloeeba0232019-03-14 18:56:54 -0700224
225 ArgumentCaptor<AttentionCallbackInternal> callbackCaptor = ArgumentCaptor.forClass(
226 AttentionCallbackInternal.class);
227 verify(mAttentionManagerInternal).cancelAttentionCheck(callbackCaptor.capture());
228 assertEquals(callbackCaptor.getValue(), mAttentionDetector.mCallback);
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800229 }
230
231 @Test
232 public void testCallbackOnSuccess_ignoresIfNoAttention() {
233 registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -0700234 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_ABSENT,
235 SystemClock.uptimeMillis());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800236 verify(mOnUserAttention, never()).run();
237 }
238
239 @Test
240 public void testCallbackOnSuccess_callsCallback() {
241 registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -0700242 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
243 SystemClock.uptimeMillis());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800244 verify(mOnUserAttention).run();
245 }
246
247 @Test
Alex Salo69ff3212019-04-06 16:24:00 -0700248 public void testCallbackOnSuccess_doesNotCallNonCurrentCallback() {
249 mAttentionDetector.mRequestId = 5;
250 registerAttention(); // mRequestId = 6;
251 mAttentionDetector.mRequestId = 55;
252
253 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
254 SystemClock.uptimeMillis());
255 verify(mOnUserAttention, never()).run();
256 }
257
258 @Test
259 public void testCallbackOnSuccess_callsCallbackAfterOldCallbackCame() {
260 mAttentionDetector.mRequestId = 5;
261 registerAttention(); // mRequestId = 6;
262 mAttentionDetector.mRequestId = 55;
263
264 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
265 SystemClock.uptimeMillis()); // old callback came
266 mAttentionDetector.mRequestId = 6; // now back to current
267 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
268 SystemClock.uptimeMillis());
269 verify(mOnUserAttention).run();
270 }
271
272 @Test
273 public void testCallbackOnSuccess_DoesNotGoIntoInfiniteLoop() {
274 // Mimic real behavior
275 doAnswer((invocation) -> {
276 // Mimic a cache hit: calling onSuccess() immediately
277 registerAttention();
278 mAttentionDetector.mRequestId++;
279 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
280 SystemClock.uptimeMillis());
281 return null;
282 }).when(mOnUserAttention).run();
283
284 registerAttention();
285 // This test fails with literal stack overflow:
286 // e.g. java.lang.StackOverflowError: stack size 1039KB
287 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
288 SystemClock.uptimeMillis());
289
290 // We don't actually get here when the test fails
291 verify(mOnUserAttention, atMost(1)).run();
292 }
293
294 @Test
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800295 public void testCallbackOnFailure_unregistersCurrentRequestCode() {
296 registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -0700297 mAttentionDetector.mCallback.onFailure(AttentionService.ATTENTION_FAILURE_UNKNOWN);
298 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
299 SystemClock.uptimeMillis());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800300 verify(mOnUserAttention, never()).run();
301 }
302
303 private long registerAttention() {
304 mAttentionTimeout = 4000L;
305 mAttentionDetector.onUserActivity(SystemClock.uptimeMillis(),
306 PowerManager.USER_ACTIVITY_EVENT_TOUCH);
307 return mAttentionDetector.updateUserActivity(mNextDimming);
308 }
309
310 private class TestableAttentionDetector extends AttentionDetector {
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800311 private boolean mAttentionServiceSupported;
312
313 TestableAttentionDetector() {
314 super(AttentionDetectorTest.this.mOnUserAttention, new Object());
315 mAttentionManager = mAttentionManagerInternal;
Alex Salo49489762019-06-03 16:23:30 -0700316 mWindowManager = mWindowManagerInternal;
Alex Salo2b7dbe82019-04-11 14:45:42 -0700317 mPackageManager = AttentionDetectorTest.this.mPackageManager;
318 mContentResolver = getContext().getContentResolver();
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800319 mMaximumExtensionMillis = 10000L;
320 }
321
322 void setAttentionServiceSupported(boolean supported) {
323 mAttentionServiceSupported = supported;
324 }
325
326 @Override
327 public boolean isAttentionServiceSupported() {
328 return mAttentionServiceSupported;
329 }
330
331 @Override
332 public long getAttentionTimeout() {
333 return mAttentionTimeout;
334 }
335 }
336}