1 /*
2  * Copyright (C) 2017 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;
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.Matchers.anyInt;
23 import static org.mockito.Matchers.eq;
24 import static org.mockito.Mockito.never;
25 import static org.mockito.Mockito.times;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.when;
28 
29 import android.app.StatusBarManager;
30 import android.content.Context;
31 import android.content.res.Resources;
32 import android.os.Looper;
33 import android.os.UserHandle;
34 import android.platform.test.annotations.Presubmit;
35 import android.provider.Settings;
36 import android.test.mock.MockContentResolver;
37 import android.util.MutableBoolean;
38 import android.view.KeyEvent;
39 
40 import androidx.test.InstrumentationRegistry;
41 import androidx.test.filters.SmallTest;
42 import androidx.test.runner.AndroidJUnit4;
43 
44 import com.android.internal.logging.MetricsLogger;
45 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
46 import com.android.internal.util.test.FakeSettingsProvider;
47 import com.android.server.LocalServices;
48 import com.android.server.statusbar.StatusBarManagerInternal;
49 
50 import org.junit.Before;
51 import org.junit.BeforeClass;
52 import org.junit.Test;
53 import org.junit.runner.RunWith;
54 import org.mockito.ArgumentCaptor;
55 import org.mockito.Mock;
56 import org.mockito.MockitoAnnotations;
57 
58 import java.util.List;
59 
60 /**
61  * Unit tests for {@link GestureLauncherService}.
62  * runtest frameworks-services -c com.android.server.GestureLauncherServiceTest
63  */
64 @Presubmit
65 @SmallTest
66 @RunWith(AndroidJUnit4.class)
67 public class GestureLauncherServiceTest {
68 
69     private static final int FAKE_USER_ID = 1337;
70     private static final int FAKE_SOURCE = 1982;
71     private static final long INITIAL_EVENT_TIME_MILLIS = 20000L;
72     private static final long IGNORED_DOWN_TIME = 1234L;
73     private static final int IGNORED_ACTION = 13;
74     private static final int IGNORED_CODE = 1999;
75     private static final int IGNORED_REPEAT = 42;
76     private static final int IGNORED_META_STATE = 0;
77     private static final int IGNORED_DEVICE_ID = 0;
78     private static final int IGNORED_SCANCODE = 0;
79 
80     private @Mock Context mContext;
81     private @Mock Resources mResources;
82     private @Mock StatusBarManagerInternal mStatusBarManagerInternal;
83     private @Mock MetricsLogger mMetricsLogger;
84     private MockContentResolver mContentResolver;
85     private GestureLauncherService mGestureLauncherService;
86 
87     @BeforeClass
oneTimeInitialization()88     public static void oneTimeInitialization() {
89         if (Looper.myLooper() == null) {
90             Looper.prepare();
91         }
92     }
93 
94     @Before
setup()95     public void setup() {
96         MockitoAnnotations.initMocks(this);
97 
98         LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
99         LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal);
100 
101         final Context originalContext = InstrumentationRegistry.getContext();
102         when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo());
103         when(mContext.getResources()).thenReturn(mResources);
104         mContentResolver = new MockContentResolver(mContext);
105         mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
106         when(mContext.getContentResolver()).thenReturn(mContentResolver);
107 
108         mGestureLauncherService = new GestureLauncherService(mContext, mMetricsLogger);
109     }
110 
111     @Test
testIsCameraDoubleTapPowerEnabled_configFalse()112     public void testIsCameraDoubleTapPowerEnabled_configFalse() {
113         withCameraDoubleTapPowerEnableConfigValue(false);
114         assertFalse(mGestureLauncherService.isCameraDoubleTapPowerEnabled(mResources));
115     }
116 
117     @Test
testIsCameraDoubleTapPowerEnabled_configTrue()118     public void testIsCameraDoubleTapPowerEnabled_configTrue() {
119         withCameraDoubleTapPowerEnableConfigValue(true);
120         assertTrue(mGestureLauncherService.isCameraDoubleTapPowerEnabled(mResources));
121     }
122 
123     @Test
testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingDisabled()124     public void testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingDisabled() {
125         withCameraDoubleTapPowerEnableConfigValue(false);
126         withCameraDoubleTapPowerDisableSettingValue(1);
127         assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled(
128                 mContext, FAKE_USER_ID));
129     }
130 
131     @Test
testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingEnabled()132     public void testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingEnabled() {
133         withCameraDoubleTapPowerEnableConfigValue(false);
134         withCameraDoubleTapPowerDisableSettingValue(0);
135         assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled(
136                 mContext, FAKE_USER_ID));
137     }
138 
139     @Test
testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingDisabled()140     public void testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingDisabled() {
141         withCameraDoubleTapPowerEnableConfigValue(true);
142         withCameraDoubleTapPowerDisableSettingValue(1);
143         assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled(
144                 mContext, FAKE_USER_ID));
145     }
146 
147     @Test
testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingEnabled()148     public void testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingEnabled() {
149         withCameraDoubleTapPowerEnableConfigValue(true);
150         withCameraDoubleTapPowerDisableSettingValue(0);
151         assertTrue(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled(
152                 mContext, FAKE_USER_ID));
153     }
154 
155     @Test
testHandleCameraLaunchGesture_userSetupComplete()156     public void testHandleCameraLaunchGesture_userSetupComplete() {
157         withUserSetupCompleteValue(true);
158 
159         boolean useWakeLock = false;
160         assertTrue(mGestureLauncherService.handleCameraGesture(useWakeLock, FAKE_SOURCE));
161         verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected(FAKE_SOURCE);
162     }
163 
164     @Test
testHandleCameraLaunchGesture_userSetupNotComplete()165     public void testHandleCameraLaunchGesture_userSetupNotComplete() {
166         withUserSetupCompleteValue(false);
167 
168         boolean useWakeLock = false;
169         assertFalse(mGestureLauncherService.handleCameraGesture(useWakeLock, FAKE_SOURCE));
170     }
171 
172     @Test
testInterceptPowerKeyDown_firstPowerDownCameraPowerGestureOnInteractive()173     public void testInterceptPowerKeyDown_firstPowerDownCameraPowerGestureOnInteractive() {
174         withCameraDoubleTapPowerEnableConfigValue(true);
175         withCameraDoubleTapPowerDisableSettingValue(0);
176         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
177 
178         long eventTime = INITIAL_EVENT_TIME_MILLIS +
179                 GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
180         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
181                 IGNORED_REPEAT);
182         boolean interactive = true;
183         MutableBoolean outLaunched = new MutableBoolean(true);
184         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
185                 outLaunched);
186         assertFalse(intercepted);
187         assertFalse(outLaunched.value);
188         verify(mMetricsLogger).histogram("power_consecutive_short_tap_count", 1);
189         verify(mMetricsLogger).histogram("power_double_tap_interval", (int) eventTime);
190     }
191 
192     @Test
testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffInteractive()193     public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffInteractive() {
194         withCameraDoubleTapPowerEnableConfigValue(false);
195         withCameraDoubleTapPowerDisableSettingValue(1);
196         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
197 
198         long eventTime = INITIAL_EVENT_TIME_MILLIS;
199         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
200                 IGNORED_REPEAT);
201         boolean interactive = true;
202         MutableBoolean outLaunched = new MutableBoolean(true);
203         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
204                 outLaunched);
205         assertFalse(intercepted);
206         assertFalse(outLaunched.value);
207 
208         final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
209         eventTime += interval;
210         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
211                 IGNORED_REPEAT);
212         outLaunched.value = true;
213         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
214                 outLaunched);
215         assertFalse(intercepted);
216         assertFalse(outLaunched.value);
217 
218         verify(mMetricsLogger, never())
219             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
220 
221         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
222         verify(mMetricsLogger, times(2)).histogram(
223                 eq("power_double_tap_interval"), intervalCaptor.capture());
224         List<Integer> intervals = intervalCaptor.getAllValues();
225         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
226         assertEquals((int) interval, intervals.get(1).intValue());
227 
228         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
229         verify(mMetricsLogger, times(2)).histogram(
230                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
231         List<Integer> tapCounts = tapCountCaptor.getAllValues();
232         assertEquals(1, tapCounts.get(0).intValue());
233         assertEquals(2, tapCounts.get(1).intValue());
234     }
235 
236     @Test
testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffInteractive()237     public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffInteractive() {
238         withCameraDoubleTapPowerEnableConfigValue(false);
239         withCameraDoubleTapPowerDisableSettingValue(1);
240         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
241 
242         long eventTime = INITIAL_EVENT_TIME_MILLIS;
243         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
244                 IGNORED_REPEAT);
245         boolean interactive = true;
246         MutableBoolean outLaunched = new MutableBoolean(true);
247         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
248                 outLaunched);
249         assertFalse(intercepted);
250         assertFalse(outLaunched.value);
251 
252         final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS;
253         eventTime += interval;
254         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
255                 IGNORED_REPEAT);
256         outLaunched.value = true;
257         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
258                 outLaunched);
259         assertFalse(intercepted);
260         assertFalse(outLaunched.value);
261 
262         verify(mMetricsLogger, never())
263             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
264 
265         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
266         verify(mMetricsLogger, times(2)).histogram(
267                 eq("power_double_tap_interval"), intervalCaptor.capture());
268         List<Integer> intervals = intervalCaptor.getAllValues();
269         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
270         assertEquals((int) interval, intervals.get(1).intValue());
271 
272         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
273         verify(mMetricsLogger, times(2)).histogram(
274                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
275         List<Integer> tapCounts = tapCountCaptor.getAllValues();
276         assertEquals(1, tapCounts.get(0).intValue());
277         // The interval is too long to launch the camera, but short enough to count as a
278         // sequential tap.
279         assertEquals(2, tapCounts.get(1).intValue());
280     }
281 
282     @Test
testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffInteractive()283     public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffInteractive() {
284         withCameraDoubleTapPowerEnableConfigValue(false);
285         withCameraDoubleTapPowerDisableSettingValue(1);
286         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
287 
288         long eventTime = INITIAL_EVENT_TIME_MILLIS;
289         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
290                 IGNORED_REPEAT);
291         boolean interactive = true;
292         MutableBoolean outLaunched = new MutableBoolean(true);
293         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
294                 outLaunched);
295         assertFalse(intercepted);
296         assertFalse(outLaunched.value);
297 
298         long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS;
299         eventTime += interval;
300         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
301                 IGNORED_REPEAT);
302         outLaunched.value = true;
303         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
304                 outLaunched);
305         assertFalse(intercepted);
306         assertFalse(outLaunched.value);
307 
308         verify(mMetricsLogger, never())
309             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
310 
311         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
312         verify(mMetricsLogger, times(2)).histogram(
313                 eq("power_double_tap_interval"), intervalCaptor.capture());
314         List<Integer> intervals = intervalCaptor.getAllValues();
315         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
316         assertEquals((int) interval, intervals.get(1).intValue());
317 
318         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
319         verify(mMetricsLogger, times(2)).histogram(
320                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
321         List<Integer> tapCounts = tapCountCaptor.getAllValues();
322         assertEquals(1, tapCounts.get(0).intValue());
323         assertEquals(1, tapCounts.get(1).intValue());
324     }
325 
326     @Test
327     public void
testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupComplete()328     testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupComplete() {
329         withCameraDoubleTapPowerEnableConfigValue(true);
330         withCameraDoubleTapPowerDisableSettingValue(0);
331         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
332         withUserSetupCompleteValue(true);
333 
334         long eventTime = INITIAL_EVENT_TIME_MILLIS;
335         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
336                 IGNORED_REPEAT);
337         boolean interactive = true;
338         MutableBoolean outLaunched = new MutableBoolean(true);
339         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
340                 outLaunched);
341         assertFalse(intercepted);
342         assertFalse(outLaunched.value);
343 
344         final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
345         eventTime += interval;
346         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
347                 IGNORED_REPEAT);
348         outLaunched.value = false;
349         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
350                 outLaunched);
351         assertTrue(intercepted);
352         assertTrue(outLaunched.value);
353 
354         verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected(
355                 StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
356         verify(mMetricsLogger)
357             .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval);
358 
359         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
360         verify(mMetricsLogger, times(2)).histogram(
361                 eq("power_double_tap_interval"), intervalCaptor.capture());
362         List<Integer> intervals = intervalCaptor.getAllValues();
363         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
364         assertEquals((int) interval, intervals.get(1).intValue());
365 
366         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
367         verify(mMetricsLogger, times(2)).histogram(
368                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
369         List<Integer> tapCounts = tapCountCaptor.getAllValues();
370         assertEquals(1, tapCounts.get(0).intValue());
371         assertEquals(2, tapCounts.get(1).intValue());
372     }
373 
374     @Test
testInterceptPowerKeyDown_longpress()375     public void testInterceptPowerKeyDown_longpress() {
376         withCameraDoubleTapPowerEnableConfigValue(true);
377         withCameraDoubleTapPowerDisableSettingValue(0);
378         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
379         withUserSetupCompleteValue(true);
380 
381         long eventTime = INITIAL_EVENT_TIME_MILLIS;
382         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
383                 IGNORED_REPEAT);
384         boolean interactive = true;
385         MutableBoolean outLaunched = new MutableBoolean(true);
386         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
387                 outLaunched);
388         assertFalse(intercepted);
389         assertFalse(outLaunched.value);
390 
391         final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
392         eventTime += interval;
393         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
394                 IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE,
395                 KeyEvent.FLAG_LONG_PRESS);
396         outLaunched.value = false;
397         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
398                 outLaunched);
399         assertFalse(intercepted);
400         assertFalse(outLaunched.value);
401 
402         verify(mMetricsLogger, never())
403                 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
404 
405         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
406         verify(mMetricsLogger, times(1)).histogram(
407                 eq("power_double_tap_interval"), intervalCaptor.capture());
408         List<Integer> intervals = intervalCaptor.getAllValues();
409         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
410 
411         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
412         verify(mMetricsLogger, times(1)).histogram(
413                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
414         List<Integer> tapCounts = tapCountCaptor.getAllValues();
415         assertEquals(1, tapCounts.get(0).intValue());
416     }
417 
418     @Test
419     public void
testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupIncomplete()420     testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupIncomplete() {
421         withCameraDoubleTapPowerEnableConfigValue(true);
422         withCameraDoubleTapPowerDisableSettingValue(0);
423         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
424         withUserSetupCompleteValue(false);
425 
426         long eventTime = INITIAL_EVENT_TIME_MILLIS;
427         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
428                 IGNORED_REPEAT);
429         boolean interactive = true;
430         MutableBoolean outLaunched = new MutableBoolean(true);
431         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
432                 outLaunched);
433         assertFalse(intercepted);
434         assertFalse(outLaunched.value);
435 
436         final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
437         eventTime += interval;
438         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
439                 IGNORED_REPEAT);
440         outLaunched.value = true;
441         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
442                 outLaunched);
443         assertFalse(intercepted);
444         assertFalse(outLaunched.value);
445 
446         verify(mMetricsLogger, never())
447             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
448 
449         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
450         verify(mMetricsLogger, times(2)).histogram(
451                 eq("power_double_tap_interval"), intervalCaptor.capture());
452         List<Integer> intervals = intervalCaptor.getAllValues();
453         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
454         assertEquals((int) interval, intervals.get(1).intValue());
455 
456         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
457         verify(mMetricsLogger, times(2)).histogram(
458                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
459         List<Integer> tapCounts = tapCountCaptor.getAllValues();
460         assertEquals(1, tapCounts.get(0).intValue());
461         // The interval is too long to launch the camera, but short enough to count as a
462         // sequential tap.
463         assertEquals(2, tapCounts.get(1).intValue());
464     }
465 
466     @Test
testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnInteractive()467     public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnInteractive() {
468         withCameraDoubleTapPowerEnableConfigValue(true);
469         withCameraDoubleTapPowerDisableSettingValue(0);
470         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
471 
472         long eventTime = INITIAL_EVENT_TIME_MILLIS;
473         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
474                 IGNORED_REPEAT);
475         boolean interactive = true;
476         MutableBoolean outLaunched = new MutableBoolean(true);
477         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
478                 outLaunched);
479         assertFalse(intercepted);
480         assertFalse(outLaunched.value);
481 
482         final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS;
483         eventTime += interval;
484         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
485                 IGNORED_REPEAT);
486         outLaunched.value = true;
487         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
488                 outLaunched);
489         assertFalse(intercepted);
490         assertFalse(outLaunched.value);
491 
492         verify(mMetricsLogger, never())
493             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
494 
495         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
496         verify(mMetricsLogger, times(2)).histogram(
497                 eq("power_double_tap_interval"), intervalCaptor.capture());
498         List<Integer> intervals = intervalCaptor.getAllValues();
499         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
500         assertEquals((int) interval, intervals.get(1).intValue());
501 
502         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
503         verify(mMetricsLogger, times(2)).histogram(
504                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
505         List<Integer> tapCounts = tapCountCaptor.getAllValues();
506         assertEquals(1, tapCounts.get(0).intValue());
507         // The interval is too long to launch the camera, but short enough to count as a
508         // sequential tap.
509         assertEquals(2, tapCounts.get(1).intValue());
510     }
511 
512     @Test
testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnInteractive()513     public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnInteractive() {
514         withCameraDoubleTapPowerEnableConfigValue(true);
515         withCameraDoubleTapPowerDisableSettingValue(0);
516         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
517 
518         long eventTime = INITIAL_EVENT_TIME_MILLIS;
519         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
520                 IGNORED_REPEAT);
521         boolean interactive = true;
522         MutableBoolean outLaunched = new MutableBoolean(true);
523         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
524                 outLaunched);
525         assertFalse(intercepted);
526         assertFalse(outLaunched.value);
527 
528         long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS;
529         eventTime += interval;
530         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
531                 IGNORED_REPEAT);
532         outLaunched.value = true;
533         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
534                 outLaunched);
535         assertFalse(intercepted);
536         assertFalse(outLaunched.value);
537 
538         verify(mMetricsLogger, never())
539             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
540 
541         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
542         verify(mMetricsLogger, times(2)).histogram(
543                 eq("power_double_tap_interval"), intervalCaptor.capture());
544         List<Integer> intervals = intervalCaptor.getAllValues();
545         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
546         assertEquals((int) interval, intervals.get(1).intValue());
547 
548         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
549         verify(mMetricsLogger, times(2)).histogram(
550                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
551         List<Integer> tapCounts = tapCountCaptor.getAllValues();
552         assertEquals(1, tapCounts.get(0).intValue());
553         assertEquals(1, tapCounts.get(1).intValue());
554     }
555 
556     @Test
testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffNotInteractive()557     public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffNotInteractive() {
558         withCameraDoubleTapPowerEnableConfigValue(false);
559         withCameraDoubleTapPowerDisableSettingValue(1);
560         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
561 
562         long eventTime = INITIAL_EVENT_TIME_MILLIS;
563         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
564                 IGNORED_REPEAT);
565         boolean interactive = false;
566         MutableBoolean outLaunched = new MutableBoolean(true);
567         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
568                 outLaunched);
569         assertFalse(intercepted);
570         assertFalse(outLaunched.value);
571 
572         final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
573         eventTime += interval;
574         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
575                 IGNORED_REPEAT);
576         outLaunched.value = true;
577         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
578                 outLaunched);
579         assertFalse(intercepted);
580         assertFalse(outLaunched.value);
581 
582         verify(mMetricsLogger, never())
583             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
584 
585         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
586         verify(mMetricsLogger, times(2)).histogram(
587                 eq("power_double_tap_interval"), intervalCaptor.capture());
588         List<Integer> intervals = intervalCaptor.getAllValues();
589         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
590         assertEquals((int) interval, intervals.get(1).intValue());
591 
592         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
593         verify(mMetricsLogger, times(2)).histogram(
594                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
595         List<Integer> tapCounts = tapCountCaptor.getAllValues();
596         assertEquals(1, tapCounts.get(0).intValue());
597         assertEquals(2, tapCounts.get(1).intValue());
598     }
599 
600     @Test
testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffNotInteractive()601     public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffNotInteractive() {
602         withCameraDoubleTapPowerEnableConfigValue(false);
603         withCameraDoubleTapPowerDisableSettingValue(1);
604         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
605 
606         long eventTime = INITIAL_EVENT_TIME_MILLIS;
607         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
608                 IGNORED_REPEAT);
609         boolean interactive = false;
610         MutableBoolean outLaunched = new MutableBoolean(true);
611         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
612                 outLaunched);
613         assertFalse(intercepted);
614         assertFalse(outLaunched.value);
615 
616         final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS;
617         eventTime += interval;
618         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
619                 IGNORED_REPEAT);
620         outLaunched.value = true;
621         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
622                 outLaunched);
623         assertFalse(intercepted);
624         assertFalse(outLaunched.value);
625         verify(mMetricsLogger, never())
626             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
627 
628         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
629         verify(mMetricsLogger, times(2)).histogram(
630                 eq("power_double_tap_interval"), intervalCaptor.capture());
631         List<Integer> intervals = intervalCaptor.getAllValues();
632         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
633         assertEquals((int) interval, intervals.get(1).intValue());
634 
635         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
636         verify(mMetricsLogger, times(2)).histogram(
637                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
638         List<Integer> tapCounts = tapCountCaptor.getAllValues();
639         assertEquals(1, tapCounts.get(0).intValue());
640         // The interval is too long to launch the camera, but short enough to count as a
641         // sequential tap.
642         assertEquals(2, tapCounts.get(1).intValue());
643     }
644 
645     @Test
testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffNotInteractive()646     public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffNotInteractive() {
647         withCameraDoubleTapPowerEnableConfigValue(false);
648         withCameraDoubleTapPowerDisableSettingValue(1);
649         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
650 
651         long eventTime = INITIAL_EVENT_TIME_MILLIS;
652         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
653                 IGNORED_REPEAT);
654         boolean interactive = false;
655         MutableBoolean outLaunched = new MutableBoolean(true);
656         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
657                 outLaunched);
658         assertFalse(intercepted);
659         assertFalse(outLaunched.value);
660 
661         long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS;
662         eventTime += interval;
663         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
664                 IGNORED_REPEAT);
665         outLaunched.value = true;
666         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
667                 outLaunched);
668         assertFalse(intercepted);
669         assertFalse(outLaunched.value);
670         verify(mMetricsLogger, never())
671             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
672 
673         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
674         verify(mMetricsLogger, times(2)).histogram(
675                 eq("power_double_tap_interval"), intervalCaptor.capture());
676         List<Integer> intervals = intervalCaptor.getAllValues();
677         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
678         assertEquals((int) interval, intervals.get(1).intValue());
679 
680         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
681         verify(mMetricsLogger, times(2)).histogram(
682                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
683         List<Integer> tapCounts = tapCountCaptor.getAllValues();
684         assertEquals(1, tapCounts.get(0).intValue());
685         assertEquals(1, tapCounts.get(1).intValue());
686     }
687 
688     @Test
689     public void
testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupComplete()690     testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupComplete() {
691         withCameraDoubleTapPowerEnableConfigValue(true);
692         withCameraDoubleTapPowerDisableSettingValue(0);
693         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
694         withUserSetupCompleteValue(true);
695 
696         long eventTime = INITIAL_EVENT_TIME_MILLIS;
697         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
698                 IGNORED_REPEAT);
699         boolean interactive = false;
700         MutableBoolean outLaunched = new MutableBoolean(true);
701         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
702                 outLaunched);
703         assertFalse(intercepted);
704         assertFalse(outLaunched.value);
705 
706         final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
707         eventTime += interval;
708         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
709                 IGNORED_REPEAT);
710         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
711                 outLaunched);
712         assertFalse(intercepted);
713         assertTrue(outLaunched.value);
714 
715         verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected(
716                 StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
717         verify(mMetricsLogger)
718             .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval);
719 
720         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
721         verify(mMetricsLogger, times(2)).histogram(
722                 eq("power_double_tap_interval"), intervalCaptor.capture());
723         List<Integer> intervals = intervalCaptor.getAllValues();
724         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
725         assertEquals((int) interval, intervals.get(1).intValue());
726 
727         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
728         verify(mMetricsLogger, times(2)).histogram(
729                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
730         List<Integer> tapCounts = tapCountCaptor.getAllValues();
731         assertEquals(1, tapCounts.get(0).intValue());
732         assertEquals(2, tapCounts.get(1).intValue());
733     }
734 
735     @Test
736     public void
testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupIncomplete()737     testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupIncomplete() {
738         withCameraDoubleTapPowerEnableConfigValue(true);
739         withCameraDoubleTapPowerDisableSettingValue(0);
740         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
741         withUserSetupCompleteValue(false);
742 
743         long eventTime = INITIAL_EVENT_TIME_MILLIS;
744         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
745                 IGNORED_REPEAT);
746         boolean interactive = false;
747         MutableBoolean outLaunched = new MutableBoolean(true);
748         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
749                 outLaunched);
750         assertFalse(intercepted);
751         assertFalse(outLaunched.value);
752 
753         final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
754         eventTime += interval;
755         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
756                 IGNORED_REPEAT);
757         outLaunched.value = true;
758         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
759                 outLaunched);
760         assertFalse(intercepted);
761         assertFalse(outLaunched.value);
762 
763         verify(mMetricsLogger, never())
764             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
765 
766         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
767         verify(mMetricsLogger, times(2)).histogram(
768                 eq("power_double_tap_interval"), intervalCaptor.capture());
769         List<Integer> intervals = intervalCaptor.getAllValues();
770         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
771         assertEquals((int) interval, intervals.get(1).intValue());
772 
773         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
774         verify(mMetricsLogger, times(2)).histogram(
775                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
776         List<Integer> tapCounts = tapCountCaptor.getAllValues();
777         assertEquals(1, tapCounts.get(0).intValue());
778         assertEquals(2, tapCounts.get(1).intValue());
779     }
780 
781     @Test
testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnNotInteractive()782     public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnNotInteractive() {
783         withCameraDoubleTapPowerEnableConfigValue(true);
784         withCameraDoubleTapPowerDisableSettingValue(0);
785         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
786 
787         long eventTime = INITIAL_EVENT_TIME_MILLIS;
788         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
789                 IGNORED_REPEAT);
790         boolean interactive = false;
791         MutableBoolean outLaunched = new MutableBoolean(true);
792         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
793                 outLaunched);
794         assertFalse(intercepted);
795         assertFalse(outLaunched.value);
796 
797         final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS;
798         eventTime += interval;
799         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
800                 IGNORED_REPEAT);
801         outLaunched.value = true;
802         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
803                 outLaunched);
804         assertFalse(intercepted);
805         assertFalse(outLaunched.value);
806 
807         verify(mMetricsLogger, never())
808             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
809 
810         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
811         verify(mMetricsLogger, times(2)).histogram(
812                 eq("power_double_tap_interval"), intervalCaptor.capture());
813         List<Integer> intervals = intervalCaptor.getAllValues();
814         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
815         assertEquals((int) interval, intervals.get(1).intValue());
816 
817         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
818         verify(mMetricsLogger, times(2)).histogram(
819                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
820         List<Integer> tapCounts = tapCountCaptor.getAllValues();
821         assertEquals(1, tapCounts.get(0).intValue());
822         // The interval is too long to launch the camera, but short enough to count as a
823         // sequential tap.
824         assertEquals(2, tapCounts.get(1).intValue());
825     }
826 
827     @Test
testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnNotInteractive()828     public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnNotInteractive() {
829         withCameraDoubleTapPowerEnableConfigValue(true);
830         withCameraDoubleTapPowerDisableSettingValue(0);
831         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
832 
833         long eventTime = INITIAL_EVENT_TIME_MILLIS;
834         KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
835                 IGNORED_REPEAT);
836         boolean interactive = false;
837         MutableBoolean outLaunched = new MutableBoolean(true);
838         boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
839                 outLaunched);
840         assertFalse(intercepted);
841         assertFalse(outLaunched.value);
842 
843         long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS;
844         eventTime += interval;
845         keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
846                 IGNORED_REPEAT);
847         outLaunched.value = true;
848         intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
849                 outLaunched);
850         assertFalse(intercepted);
851         assertFalse(outLaunched.value);
852 
853         verify(mMetricsLogger, never())
854             .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
855 
856         final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
857         verify(mMetricsLogger, times(2)).histogram(
858                 eq("power_double_tap_interval"), intervalCaptor.capture());
859         List<Integer> intervals = intervalCaptor.getAllValues();
860         assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
861         assertEquals((int) interval, intervals.get(1).intValue());
862 
863         final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
864         verify(mMetricsLogger, times(2)).histogram(
865                 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
866         List<Integer> tapCounts = tapCountCaptor.getAllValues();
867         assertEquals(1, tapCounts.get(0).intValue());
868         assertEquals(1, tapCounts.get(1).intValue());
869     }
870 
withCameraDoubleTapPowerEnableConfigValue(boolean enableConfigValue)871     private void withCameraDoubleTapPowerEnableConfigValue(boolean enableConfigValue) {
872         when(mResources.getBoolean(
873                 com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled))
874                 .thenReturn(enableConfigValue);
875     }
876 
withCameraDoubleTapPowerDisableSettingValue(int disableSettingValue)877     private void withCameraDoubleTapPowerDisableSettingValue(int disableSettingValue) {
878         Settings.Secure.putIntForUser(
879                 mContentResolver,
880                 Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
881                 disableSettingValue,
882                 UserHandle.USER_CURRENT);
883     }
884 
withUserSetupCompleteValue(boolean userSetupComplete)885     private void withUserSetupCompleteValue(boolean userSetupComplete) {
886         int userSetupCompleteValue = userSetupComplete ? 1 : 0;
887         Settings.Secure.putIntForUser(
888                 mContentResolver,
889                 Settings.Secure.USER_SETUP_COMPLETE,
890                 userSetupCompleteValue,
891                 UserHandle.USER_CURRENT);
892     }
893 }
894