blob: a63f49b1fe3df87fa6c53c77bf85bcb1e5b71092 [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 Salo9af68f12019-02-15 13:50:11 -080045import org.junit.After;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080046import org.junit.Before;
47import org.junit.Test;
Alex Saloeeba0232019-03-14 18:56:54 -070048import org.mockito.ArgumentCaptor;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080049import org.mockito.Mock;
50import org.mockito.MockitoAnnotations;
51
52@SmallTest
53public class AttentionDetectorTest extends AndroidTestCase {
54
Alex Saloeeba0232019-03-14 18:56:54 -070055 @Mock
Alex Salo2b7dbe82019-04-11 14:45:42 -070056 private PackageManager mPackageManager;
57 @Mock
Alex Saloeeba0232019-03-14 18:56:54 -070058 private AttentionManagerInternal mAttentionManagerInternal;
59 @Mock
60 private Runnable mOnUserAttention;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080061 private TestableAttentionDetector mAttentionDetector;
62 private long mAttentionTimeout;
63 private long mNextDimming;
Alex Salo9af68f12019-02-15 13:50:11 -080064 private int mIsSettingEnabled;
Lucas Dupin0a5d7972019-01-16 18:52:30 -080065
66 @Before
67 public void setUp() {
68 MockitoAnnotations.initMocks(this);
Alex Salo2b7dbe82019-04-11 14:45:42 -070069 when(mPackageManager.getAttentionServicePackageName()).thenReturn("com.google.android.as");
70 when(mPackageManager.checkPermission(any(), any())).thenReturn(
71 PackageManager.PERMISSION_GRANTED);
Alex Saloeeba0232019-03-14 18:56:54 -070072 when(mAttentionManagerInternal.checkAttention(anyLong(), any()))
Lucas Dupin0a5d7972019-01-16 18:52:30 -080073 .thenReturn(true);
74 mAttentionDetector = new TestableAttentionDetector();
75 mAttentionDetector.onWakefulnessChangeStarted(PowerManagerInternal.WAKEFULNESS_AWAKE);
76 mAttentionDetector.setAttentionServiceSupported(true);
77 mNextDimming = SystemClock.uptimeMillis() + 3000L;
Alex Salo9af68f12019-02-15 13:50:11 -080078
79 // Save the existing state.
80 mIsSettingEnabled = Settings.System.getIntForUser(getContext().getContentResolver(),
81 Settings.System.ADAPTIVE_SLEEP, 0, UserHandle.USER_CURRENT);
82
83 Settings.System.putIntForUser(getContext().getContentResolver(),
84 Settings.System.ADAPTIVE_SLEEP, 1, UserHandle.USER_CURRENT);
85 mAttentionDetector.updateEnabledFromSettings(getContext());
86 }
87
88 @After
89 public void tearDown() {
90 Settings.System.putIntForUser(getContext().getContentResolver(),
91 Settings.System.ADAPTIVE_SLEEP, mIsSettingEnabled, UserHandle.USER_CURRENT);
Lucas Dupin0a5d7972019-01-16 18:52:30 -080092 }
93
94 @Test
95 public void testOnUserActivity_checksAttention() {
96 long when = registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -070097 verify(mAttentionManagerInternal).checkAttention(anyLong(), any());
Lucas Dupin0a5d7972019-01-16 18:52:30 -080098 assertThat(when).isLessThan(mNextDimming);
99 }
100
101 @Test
Alex Salo9af68f12019-02-15 13:50:11 -0800102 public void testOnUserActivity_doesntCheckIfNotEnabled() {
103 Settings.System.putIntForUser(getContext().getContentResolver(),
104 Settings.System.ADAPTIVE_SLEEP, 0, UserHandle.USER_CURRENT);
105 mAttentionDetector.updateEnabledFromSettings(getContext());
106 long when = registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -0700107 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
Alex Salo9af68f12019-02-15 13:50:11 -0800108 assertThat(mNextDimming).isEqualTo(when);
109 }
110
111 @Test
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800112 public void testOnUserActivity_doesntCheckIfNotSupported() {
113 mAttentionDetector.setAttentionServiceSupported(false);
114 long when = registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -0700115 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800116 assertThat(mNextDimming).isEqualTo(when);
117 }
118
119 @Test
Alex Salo2b7dbe82019-04-11 14:45:42 -0700120 public void testOnUserActivity_doesntCheckIfNotSufficientPermissions() {
121 when(mPackageManager.checkPermission(any(), any())).thenReturn(
122 PackageManager.PERMISSION_DENIED);
123
124 long when = registerAttention();
125 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
126 assertThat(mNextDimming).isEqualTo(when);
127 }
128
129 @Test
130 public void testOnUserActivity_disablesSettingIfNotSufficientPermissions() {
131 when(mPackageManager.checkPermission(any(), any())).thenReturn(
132 PackageManager.PERMISSION_DENIED);
133
134 registerAttention();
135 boolean enabled = Settings.System.getIntForUser(getContext().getContentResolver(),
136 Settings.System.ADAPTIVE_SLEEP, 0, UserHandle.USER_CURRENT) == 1;
137 assertFalse(enabled);
138 }
139
140 @Test
Alex Salo7a6e3a62019-02-27 15:08:15 -0800141 public void testOnUserActivity_doesntCrashIfNoAttentionService() {
142 mAttentionManagerInternal = null;
143 registerAttention();
144 // Does not crash.
145 }
146
147 @Test
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800148 public void onUserActivity_ignoresWhiteListedActivityTypes() {
149 for (int i = 0; i < NUM_USER_ACTIVITY_TYPES; i++) {
150 int result = mAttentionDetector.onUserActivity(SystemClock.uptimeMillis(), i);
151 if (result == -1) {
152 throw new AssertionError("User activity " + i + " isn't listed in"
153 + " AttentionDetector#onUserActivity. Please consider how this new activity"
154 + " type affects the attention service.");
155 }
156 }
157 }
158
159 @Test
160 public void testUpdateUserActivity_ignoresWhenItsNotTimeYet() {
161 long now = SystemClock.uptimeMillis();
162 mNextDimming = now;
163 mAttentionDetector.onUserActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH);
164 mAttentionDetector.updateUserActivity(mNextDimming + 5000L);
Alex Saloeeba0232019-03-14 18:56:54 -0700165 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800166 }
167
168 @Test
Alex Salo1761fce2019-02-13 15:54:50 -0800169 public void testUpdateUserActivity_schedulesTheNextCheck() {
170 long now = SystemClock.uptimeMillis();
171 mNextDimming = now;
172 mAttentionDetector.onUserActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH);
173 long nextTimeout = mAttentionDetector.updateUserActivity(mNextDimming + 5000L);
174 assertThat(nextTimeout).isEqualTo(mNextDimming + 5000L);
175 }
176
177 @Test
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800178 public void testOnUserActivity_ignoresAfterMaximumExtension() {
179 long now = SystemClock.uptimeMillis();
180 mAttentionDetector.onUserActivity(now - 15000L, PowerManager.USER_ACTIVITY_EVENT_TOUCH);
181 mAttentionDetector.updateUserActivity(now + 2000L);
Alex Saloeeba0232019-03-14 18:56:54 -0700182 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800183 }
184
185 @Test
Alex Salocbe610a2019-05-01 14:18:46 -0700186 public void testOnUserActivity_ignoresIfAlreadyDoneForThatNextScreenDimming() {
187 long when = registerAttention();
188 verify(mAttentionManagerInternal).checkAttention(anyLong(), any());
189 assertThat(when).isLessThan(mNextDimming);
190 clearInvocations(mAttentionManagerInternal);
191
192 long redundantWhen = mAttentionDetector.updateUserActivity(mNextDimming);
193 assertThat(redundantWhen).isEqualTo(mNextDimming);
194 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
195 }
196
197 @Test
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800198 public void testOnUserActivity_skipsIfAlreadyScheduled() {
199 registerAttention();
200 reset(mAttentionManagerInternal);
Alex Salocbe610a2019-05-01 14:18:46 -0700201 long when = mAttentionDetector.updateUserActivity(mNextDimming + 1);
Alex Saloeeba0232019-03-14 18:56:54 -0700202 verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800203 assertThat(when).isLessThan(mNextDimming);
204 }
205
206 @Test
207 public void testOnWakefulnessChangeStarted_cancelsRequestWhenNotAwake() {
208 registerAttention();
209 mAttentionDetector.onWakefulnessChangeStarted(PowerManagerInternal.WAKEFULNESS_ASLEEP);
Alex Saloeeba0232019-03-14 18:56:54 -0700210
211 ArgumentCaptor<AttentionCallbackInternal> callbackCaptor = ArgumentCaptor.forClass(
212 AttentionCallbackInternal.class);
213 verify(mAttentionManagerInternal).cancelAttentionCheck(callbackCaptor.capture());
214 assertEquals(callbackCaptor.getValue(), mAttentionDetector.mCallback);
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800215 }
216
217 @Test
218 public void testCallbackOnSuccess_ignoresIfNoAttention() {
219 registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -0700220 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_ABSENT,
221 SystemClock.uptimeMillis());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800222 verify(mOnUserAttention, never()).run();
223 }
224
225 @Test
226 public void testCallbackOnSuccess_callsCallback() {
227 registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -0700228 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
229 SystemClock.uptimeMillis());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800230 verify(mOnUserAttention).run();
231 }
232
233 @Test
Alex Salo69ff3212019-04-06 16:24:00 -0700234 public void testCallbackOnSuccess_doesNotCallNonCurrentCallback() {
235 mAttentionDetector.mRequestId = 5;
236 registerAttention(); // mRequestId = 6;
237 mAttentionDetector.mRequestId = 55;
238
239 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
240 SystemClock.uptimeMillis());
241 verify(mOnUserAttention, never()).run();
242 }
243
244 @Test
245 public void testCallbackOnSuccess_callsCallbackAfterOldCallbackCame() {
246 mAttentionDetector.mRequestId = 5;
247 registerAttention(); // mRequestId = 6;
248 mAttentionDetector.mRequestId = 55;
249
250 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
251 SystemClock.uptimeMillis()); // old callback came
252 mAttentionDetector.mRequestId = 6; // now back to current
253 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
254 SystemClock.uptimeMillis());
255 verify(mOnUserAttention).run();
256 }
257
258 @Test
259 public void testCallbackOnSuccess_DoesNotGoIntoInfiniteLoop() {
260 // Mimic real behavior
261 doAnswer((invocation) -> {
262 // Mimic a cache hit: calling onSuccess() immediately
263 registerAttention();
264 mAttentionDetector.mRequestId++;
265 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
266 SystemClock.uptimeMillis());
267 return null;
268 }).when(mOnUserAttention).run();
269
270 registerAttention();
271 // This test fails with literal stack overflow:
272 // e.g. java.lang.StackOverflowError: stack size 1039KB
273 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
274 SystemClock.uptimeMillis());
275
276 // We don't actually get here when the test fails
277 verify(mOnUserAttention, atMost(1)).run();
278 }
279
280 @Test
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800281 public void testCallbackOnFailure_unregistersCurrentRequestCode() {
282 registerAttention();
Alex Saloeeba0232019-03-14 18:56:54 -0700283 mAttentionDetector.mCallback.onFailure(AttentionService.ATTENTION_FAILURE_UNKNOWN);
284 mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
285 SystemClock.uptimeMillis());
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800286 verify(mOnUserAttention, never()).run();
287 }
288
289 private long registerAttention() {
290 mAttentionTimeout = 4000L;
291 mAttentionDetector.onUserActivity(SystemClock.uptimeMillis(),
292 PowerManager.USER_ACTIVITY_EVENT_TOUCH);
293 return mAttentionDetector.updateUserActivity(mNextDimming);
294 }
295
296 private class TestableAttentionDetector extends AttentionDetector {
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800297 private boolean mAttentionServiceSupported;
298
299 TestableAttentionDetector() {
300 super(AttentionDetectorTest.this.mOnUserAttention, new Object());
301 mAttentionManager = mAttentionManagerInternal;
Alex Salo2b7dbe82019-04-11 14:45:42 -0700302 mPackageManager = AttentionDetectorTest.this.mPackageManager;
303 mContentResolver = getContext().getContentResolver();
Lucas Dupin0a5d7972019-01-16 18:52:30 -0800304 mMaximumExtensionMillis = 10000L;
305 }
306
307 void setAttentionServiceSupported(boolean supported) {
308 mAttentionServiceSupported = supported;
309 }
310
311 @Override
312 public boolean isAttentionServiceSupported() {
313 return mAttentionServiceSupported;
314 }
315
316 @Override
317 public long getAttentionTimeout() {
318 return mAttentionTimeout;
319 }
320 }
321}