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 com.android.server.GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; 20 import static com.android.server.GestureLauncherService.EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS; 21 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertTrue; 25 import static org.mockito.ArgumentMatchers.any; 26 import static org.mockito.Matchers.anyInt; 27 import static org.mockito.Matchers.eq; 28 import static org.mockito.Mockito.never; 29 import static org.mockito.Mockito.times; 30 import static org.mockito.Mockito.verify; 31 import static org.mockito.Mockito.when; 32 33 import android.app.StatusBarManager; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.content.res.Resources; 37 import android.os.Looper; 38 import android.os.UserHandle; 39 import android.platform.test.annotations.Presubmit; 40 import android.provider.Settings; 41 import android.telecom.TelecomManager; 42 import android.test.mock.MockContentResolver; 43 import android.testing.TestableLooper; 44 import android.util.MutableBoolean; 45 import android.view.KeyEvent; 46 47 import androidx.test.InstrumentationRegistry; 48 import androidx.test.filters.SmallTest; 49 import androidx.test.runner.AndroidJUnit4; 50 51 import com.android.internal.logging.MetricsLogger; 52 import com.android.internal.logging.UiEventLogger; 53 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 54 import com.android.internal.util.test.FakeSettingsProvider; 55 import com.android.server.statusbar.StatusBarManagerInternal; 56 57 import org.junit.Before; 58 import org.junit.BeforeClass; 59 import org.junit.Test; 60 import org.junit.runner.RunWith; 61 import org.mockito.ArgumentCaptor; 62 import org.mockito.Mock; 63 import org.mockito.MockitoAnnotations; 64 65 import java.util.List; 66 67 /** 68 * Unit tests for {@link GestureLauncherService}. 69 * runtest frameworks-services -c com.android.server.GestureLauncherServiceTest 70 */ 71 @Presubmit 72 @SmallTest 73 @RunWith(AndroidJUnit4.class) 74 @TestableLooper.RunWithLooper(setAsMainLooper = true) 75 public class GestureLauncherServiceTest { 76 77 private static final int FAKE_USER_ID = 1337; 78 private static final int FAKE_SOURCE = 1982; 79 private static final long INITIAL_EVENT_TIME_MILLIS = 20000L; 80 private static final long IGNORED_DOWN_TIME = 1234L; 81 private static final int IGNORED_ACTION = 13; 82 private static final int IGNORED_CODE = 1999; 83 private static final int IGNORED_REPEAT = 42; 84 private static final int IGNORED_META_STATE = 0; 85 private static final int IGNORED_DEVICE_ID = 0; 86 private static final int IGNORED_SCANCODE = 0; 87 88 private @Mock Context mContext; 89 private @Mock Resources mResources; 90 private @Mock StatusBarManagerInternal mStatusBarManagerInternal; 91 private @Mock TelecomManager mTelecomManager; 92 private @Mock MetricsLogger mMetricsLogger; 93 @Mock private UiEventLogger mUiEventLogger; 94 private MockContentResolver mContentResolver; 95 private GestureLauncherService mGestureLauncherService; 96 97 @BeforeClass oneTimeInitialization()98 public static void oneTimeInitialization() { 99 if (Looper.myLooper() == null) { 100 Looper.prepare(); 101 } 102 } 103 104 @Before setup()105 public void setup() { 106 MockitoAnnotations.initMocks(this); 107 108 LocalServices.removeServiceForTest(StatusBarManagerInternal.class); 109 LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal); 110 111 final Context originalContext = InstrumentationRegistry.getContext(); 112 when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo()); 113 when(mContext.getResources()).thenReturn(mResources); 114 mContentResolver = new MockContentResolver(mContext); 115 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); 116 when(mContext.getContentResolver()).thenReturn(mContentResolver); 117 when(mContext.getSystemService(Context.TELECOM_SERVICE)).thenReturn(mTelecomManager); 118 when(mTelecomManager.createLaunchEmergencyDialerIntent(null)).thenReturn(new Intent()); 119 120 mGestureLauncherService = new GestureLauncherService(mContext, mMetricsLogger, 121 mUiEventLogger); 122 } 123 124 @Test testIsCameraDoubleTapPowerEnabled_configFalse()125 public void testIsCameraDoubleTapPowerEnabled_configFalse() { 126 withCameraDoubleTapPowerEnableConfigValue(false); 127 assertFalse(mGestureLauncherService.isCameraDoubleTapPowerEnabled(mResources)); 128 } 129 130 @Test testIsCameraDoubleTapPowerEnabled_configTrue()131 public void testIsCameraDoubleTapPowerEnabled_configTrue() { 132 withCameraDoubleTapPowerEnableConfigValue(true); 133 assertTrue(mGestureLauncherService.isCameraDoubleTapPowerEnabled(mResources)); 134 } 135 136 @Test testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingDisabled()137 public void testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingDisabled() { 138 withCameraDoubleTapPowerEnableConfigValue(false); 139 withCameraDoubleTapPowerDisableSettingValue(1); 140 assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( 141 mContext, FAKE_USER_ID)); 142 } 143 144 @Test testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingEnabled()145 public void testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingEnabled() { 146 withCameraDoubleTapPowerEnableConfigValue(false); 147 withCameraDoubleTapPowerDisableSettingValue(0); 148 assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( 149 mContext, FAKE_USER_ID)); 150 } 151 152 @Test testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingDisabled()153 public void testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingDisabled() { 154 withCameraDoubleTapPowerEnableConfigValue(true); 155 withCameraDoubleTapPowerDisableSettingValue(1); 156 assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( 157 mContext, FAKE_USER_ID)); 158 } 159 160 @Test testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingEnabled()161 public void testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingEnabled() { 162 withCameraDoubleTapPowerEnableConfigValue(true); 163 withCameraDoubleTapPowerDisableSettingValue(0); 164 assertTrue(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( 165 mContext, FAKE_USER_ID)); 166 } 167 168 @Test testIsEmergencyGestureSettingEnabled_settingDisabled()169 public void testIsEmergencyGestureSettingEnabled_settingDisabled() { 170 withEmergencyGestureEnabledConfigValue(true); 171 withEmergencyGestureEnabledSettingValue(false); 172 assertFalse(mGestureLauncherService.isEmergencyGestureSettingEnabled( 173 mContext, FAKE_USER_ID)); 174 } 175 176 @Test testIsEmergencyGestureSettingEnabled_settingEnabled()177 public void testIsEmergencyGestureSettingEnabled_settingEnabled() { 178 withEmergencyGestureEnabledConfigValue(true); 179 withEmergencyGestureEnabledSettingValue(true); 180 assertTrue(mGestureLauncherService.isEmergencyGestureSettingEnabled( 181 mContext, FAKE_USER_ID)); 182 } 183 184 @Test testIsEmergencyGestureSettingEnabled_supportDisabled()185 public void testIsEmergencyGestureSettingEnabled_supportDisabled() { 186 withEmergencyGestureEnabledConfigValue(false); 187 withEmergencyGestureEnabledSettingValue(true); 188 assertFalse(mGestureLauncherService.isEmergencyGestureSettingEnabled( 189 mContext, FAKE_USER_ID)); 190 } 191 192 @Test testGetEmergencyGesturePowerButtonCooldownPeriodMs_enabled()193 public void testGetEmergencyGesturePowerButtonCooldownPeriodMs_enabled() { 194 withEmergencyGesturePowerButtonCooldownPeriodMsValue(4000); 195 assertEquals(4000, 196 mGestureLauncherService.getEmergencyGesturePowerButtonCooldownPeriodMs(mContext, 197 FAKE_USER_ID)); 198 } 199 200 @Test testGetEmergencyGesturePowerButtonCooldownPeriodMs_disabled()201 public void testGetEmergencyGesturePowerButtonCooldownPeriodMs_disabled() { 202 withEmergencyGesturePowerButtonCooldownPeriodMsValue(0); 203 assertEquals(0, 204 mGestureLauncherService.getEmergencyGesturePowerButtonCooldownPeriodMs(mContext, 205 FAKE_USER_ID)); 206 } 207 208 @Test testGetEmergencyGesturePowerButtonCooldownPeriodMs_cappedAtMaximum()209 public void testGetEmergencyGesturePowerButtonCooldownPeriodMs_cappedAtMaximum() { 210 withEmergencyGesturePowerButtonCooldownPeriodMsValue(10000); 211 assertEquals(GestureLauncherService.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_MAX, 212 mGestureLauncherService.getEmergencyGesturePowerButtonCooldownPeriodMs(mContext, 213 FAKE_USER_ID)); 214 } 215 216 @Test testHandleCameraLaunchGesture_userSetupComplete()217 public void testHandleCameraLaunchGesture_userSetupComplete() { 218 withUserSetupCompleteValue(true); 219 220 boolean useWakeLock = false; 221 assertTrue(mGestureLauncherService.handleCameraGesture(useWakeLock, FAKE_SOURCE)); 222 verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected(FAKE_SOURCE); 223 } 224 225 @Test testHandleEmergencyGesture_userSetupComplete()226 public void testHandleEmergencyGesture_userSetupComplete() { 227 withUserSetupCompleteValue(true); 228 229 assertTrue(mGestureLauncherService.handleEmergencyGesture()); 230 } 231 232 @Test testHandleCameraLaunchGesture_userSetupNotComplete()233 public void testHandleCameraLaunchGesture_userSetupNotComplete() { 234 withUserSetupCompleteValue(false); 235 236 boolean useWakeLock = false; 237 assertFalse(mGestureLauncherService.handleCameraGesture(useWakeLock, FAKE_SOURCE)); 238 } 239 240 @Test testHandleEmergencyGesture_userSetupNotComplete()241 public void testHandleEmergencyGesture_userSetupNotComplete() { 242 withUserSetupCompleteValue(false); 243 244 assertFalse(mGestureLauncherService.handleEmergencyGesture()); 245 } 246 247 @Test testInterceptPowerKeyDown_firstPowerDownCameraPowerGestureOnInteractive()248 public void testInterceptPowerKeyDown_firstPowerDownCameraPowerGestureOnInteractive() { 249 withCameraDoubleTapPowerEnableConfigValue(true); 250 withCameraDoubleTapPowerDisableSettingValue(0); 251 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 252 253 long eventTime = INITIAL_EVENT_TIME_MILLIS + 254 CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 255 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 256 IGNORED_REPEAT); 257 boolean interactive = true; 258 MutableBoolean outLaunched = new MutableBoolean(true); 259 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 260 outLaunched); 261 assertFalse(intercepted); 262 assertFalse(outLaunched.value); 263 verify(mMetricsLogger).histogram("power_consecutive_short_tap_count", 1); 264 verify(mMetricsLogger).histogram("power_double_tap_interval", (int) eventTime); 265 } 266 267 @Test testInterceptPowerKeyDown_firstPowerDown_emergencyGestureNotLaunched()268 public void testInterceptPowerKeyDown_firstPowerDown_emergencyGestureNotLaunched() { 269 withEmergencyGestureEnabledSettingValue(true); 270 mGestureLauncherService.updateEmergencyGestureEnabled(); 271 272 long eventTime = INITIAL_EVENT_TIME_MILLIS 273 + GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS - 1; 274 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 275 IGNORED_REPEAT); 276 boolean interactive = true; 277 MutableBoolean outLaunched = new MutableBoolean(true); 278 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 279 outLaunched); 280 281 assertFalse(intercepted); 282 assertFalse(outLaunched.value); 283 verify(mMetricsLogger).histogram("power_double_tap_interval", (int) eventTime); 284 } 285 286 @Test testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffInteractive()287 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffInteractive() { 288 withCameraDoubleTapPowerEnableConfigValue(false); 289 withCameraDoubleTapPowerDisableSettingValue(1); 290 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 291 292 long eventTime = INITIAL_EVENT_TIME_MILLIS; 293 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 294 IGNORED_REPEAT); 295 boolean interactive = true; 296 MutableBoolean outLaunched = new MutableBoolean(true); 297 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 298 outLaunched); 299 assertFalse(intercepted); 300 assertFalse(outLaunched.value); 301 302 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 303 eventTime += interval; 304 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 305 IGNORED_REPEAT); 306 outLaunched.value = true; 307 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 308 outLaunched); 309 assertFalse(intercepted); 310 assertFalse(outLaunched.value); 311 312 verify(mMetricsLogger, never()) 313 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 314 verify(mUiEventLogger, never()).log(any()); 315 316 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 317 verify(mMetricsLogger, times(2)).histogram( 318 eq("power_double_tap_interval"), intervalCaptor.capture()); 319 List<Integer> intervals = intervalCaptor.getAllValues(); 320 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 321 assertEquals((int) interval, intervals.get(1).intValue()); 322 323 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 324 verify(mMetricsLogger, times(2)).histogram( 325 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 326 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 327 assertEquals(1, tapCounts.get(0).intValue()); 328 assertEquals(2, tapCounts.get(1).intValue()); 329 } 330 331 @Test testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffInteractive()332 public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffInteractive() { 333 withCameraDoubleTapPowerEnableConfigValue(false); 334 withCameraDoubleTapPowerDisableSettingValue(1); 335 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 336 337 long eventTime = INITIAL_EVENT_TIME_MILLIS; 338 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 339 IGNORED_REPEAT); 340 boolean interactive = true; 341 MutableBoolean outLaunched = new MutableBoolean(true); 342 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 343 outLaunched); 344 assertFalse(intercepted); 345 assertFalse(outLaunched.value); 346 347 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; 348 eventTime += interval; 349 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 350 IGNORED_REPEAT); 351 outLaunched.value = true; 352 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 353 outLaunched); 354 assertFalse(intercepted); 355 assertFalse(outLaunched.value); 356 357 verify(mMetricsLogger, never()) 358 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 359 verify(mUiEventLogger, never()).log(any()); 360 361 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 362 verify(mMetricsLogger, times(2)).histogram( 363 eq("power_double_tap_interval"), intervalCaptor.capture()); 364 List<Integer> intervals = intervalCaptor.getAllValues(); 365 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 366 assertEquals((int) interval, intervals.get(1).intValue()); 367 368 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 369 verify(mMetricsLogger, times(2)).histogram( 370 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 371 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 372 assertEquals(1, tapCounts.get(0).intValue()); 373 // The interval is too long to launch the camera, but short enough to count as a 374 // sequential tap. 375 assertEquals(2, tapCounts.get(1).intValue()); 376 } 377 378 @Test testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffInteractive()379 public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffInteractive() { 380 withCameraDoubleTapPowerEnableConfigValue(false); 381 withCameraDoubleTapPowerDisableSettingValue(1); 382 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 383 384 long eventTime = INITIAL_EVENT_TIME_MILLIS; 385 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 386 IGNORED_REPEAT); 387 boolean interactive = true; 388 MutableBoolean outLaunched = new MutableBoolean(true); 389 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 390 outLaunched); 391 assertFalse(intercepted); 392 assertFalse(outLaunched.value); 393 394 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS; 395 eventTime += interval; 396 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 397 IGNORED_REPEAT); 398 outLaunched.value = true; 399 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 400 outLaunched); 401 assertFalse(intercepted); 402 assertFalse(outLaunched.value); 403 404 verify(mMetricsLogger, never()) 405 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 406 verify(mUiEventLogger, never()).log(any()); 407 408 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 409 verify(mMetricsLogger, times(2)).histogram( 410 eq("power_double_tap_interval"), intervalCaptor.capture()); 411 List<Integer> intervals = intervalCaptor.getAllValues(); 412 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 413 assertEquals((int) interval, intervals.get(1).intValue()); 414 415 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 416 verify(mMetricsLogger, times(2)).histogram( 417 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 418 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 419 assertEquals(1, tapCounts.get(0).intValue()); 420 assertEquals(1, tapCounts.get(1).intValue()); 421 } 422 423 @Test 424 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupComplete()425 testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupComplete() { 426 withCameraDoubleTapPowerEnableConfigValue(true); 427 withCameraDoubleTapPowerDisableSettingValue(0); 428 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 429 withUserSetupCompleteValue(true); 430 431 long eventTime = INITIAL_EVENT_TIME_MILLIS; 432 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 433 IGNORED_REPEAT); 434 boolean interactive = true; 435 MutableBoolean outLaunched = new MutableBoolean(true); 436 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 437 outLaunched); 438 assertFalse(intercepted); 439 assertFalse(outLaunched.value); 440 441 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 442 eventTime += interval; 443 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 444 IGNORED_REPEAT); 445 outLaunched.value = false; 446 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 447 outLaunched); 448 assertTrue(intercepted); 449 assertTrue(outLaunched.value); 450 451 verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected( 452 StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); 453 verify(mMetricsLogger) 454 .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval); 455 verify(mUiEventLogger, times(1)) 456 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER); 457 458 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 459 verify(mMetricsLogger, times(2)).histogram( 460 eq("power_double_tap_interval"), intervalCaptor.capture()); 461 List<Integer> intervals = intervalCaptor.getAllValues(); 462 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 463 assertEquals((int) interval, intervals.get(1).intValue()); 464 465 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 466 verify(mMetricsLogger, times(2)).histogram( 467 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 468 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 469 assertEquals(1, tapCounts.get(0).intValue()); 470 assertEquals(2, tapCounts.get(1).intValue()); 471 } 472 473 @Test 474 public void testInterceptPowerKeyDown_fiveInboundPresses_cameraAndEmergencyEnabled_bothLaunch()475 testInterceptPowerKeyDown_fiveInboundPresses_cameraAndEmergencyEnabled_bothLaunch() { 476 withCameraDoubleTapPowerEnableConfigValue(true); 477 withCameraDoubleTapPowerDisableSettingValue(0); 478 withEmergencyGestureEnabledConfigValue(true); 479 withEmergencyGestureEnabledSettingValue(true); 480 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 481 mGestureLauncherService.updateEmergencyGestureEnabled(); 482 withUserSetupCompleteValue(true); 483 484 // First button press does nothing 485 long eventTime = INITIAL_EVENT_TIME_MILLIS; 486 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 487 IGNORED_REPEAT); 488 boolean interactive = true; 489 MutableBoolean outLaunched = new MutableBoolean(true); 490 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 491 outLaunched); 492 assertFalse(intercepted); 493 assertFalse(outLaunched.value); 494 495 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 496 497 // 2nd button triggers camera 498 eventTime += interval; 499 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 500 IGNORED_REPEAT); 501 outLaunched.value = false; 502 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 503 outLaunched); 504 assertTrue(intercepted); 505 assertTrue(outLaunched.value); 506 507 // Camera checks 508 verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected( 509 StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); 510 verify(mMetricsLogger) 511 .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval); 512 verify(mUiEventLogger, times(1)) 513 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER); 514 515 final ArgumentCaptor<Integer> cameraIntervalCaptor = ArgumentCaptor.forClass(Integer.class); 516 verify(mMetricsLogger, times(2)).histogram( 517 eq("power_double_tap_interval"), cameraIntervalCaptor.capture()); 518 List<Integer> cameraIntervals = cameraIntervalCaptor.getAllValues(); 519 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, cameraIntervals.get(0).intValue()); 520 assertEquals((int) interval, cameraIntervals.get(1).intValue()); 521 522 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 523 verify(mMetricsLogger, times(2)).histogram( 524 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 525 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 526 assertEquals(1, tapCounts.get(0).intValue()); 527 assertEquals(2, tapCounts.get(1).intValue()); 528 529 // Continue the button presses for the emergency gesture. 530 531 // Presses 3 and 4 should not trigger any gesture 532 for (int i = 0; i < 2; i++) { 533 eventTime += interval; 534 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 535 IGNORED_REPEAT); 536 outLaunched.value = false; 537 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 538 outLaunched); 539 assertTrue(intercepted); 540 assertFalse(outLaunched.value); 541 } 542 543 // Fifth button press should trigger the emergency flow 544 eventTime += interval; 545 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 546 IGNORED_REPEAT); 547 outLaunched.value = false; 548 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 549 outLaunched); 550 assertTrue(intercepted); 551 assertTrue(outLaunched.value); 552 553 verify(mUiEventLogger, times(1)) 554 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); 555 verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected(); 556 557 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 558 verify(mMetricsLogger, times(5)).histogram( 559 eq("power_double_tap_interval"), intervalCaptor.capture()); 560 List<Integer> intervals = intervalCaptor.getAllValues(); 561 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 562 assertEquals((int) interval, intervals.get(1).intValue()); 563 } 564 565 @Test 566 public void testInterceptPowerKeyDown_fiveInboundPresses_emergencyGestureEnabled_launchesFlow()567 testInterceptPowerKeyDown_fiveInboundPresses_emergencyGestureEnabled_launchesFlow() { 568 withEmergencyGestureEnabledConfigValue(true); 569 withEmergencyGestureEnabledSettingValue(true); 570 mGestureLauncherService.updateEmergencyGestureEnabled(); 571 withUserSetupCompleteValue(true); 572 573 // First button press does nothing 574 long eventTime = INITIAL_EVENT_TIME_MILLIS; 575 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 576 IGNORED_REPEAT); 577 boolean interactive = true; 578 MutableBoolean outLaunched = new MutableBoolean(true); 579 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 580 outLaunched); 581 assertFalse(intercepted); 582 assertFalse(outLaunched.value); 583 584 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 585 // 3 more button presses which should not trigger any gesture (camera gesture disabled) 586 for (int i = 0; i < 3; i++) { 587 eventTime += interval; 588 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 589 IGNORED_REPEAT); 590 outLaunched.value = false; 591 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 592 outLaunched); 593 assertTrue(intercepted); 594 assertFalse(outLaunched.value); 595 } 596 597 // Fifth button press should trigger the emergency flow 598 eventTime += interval; 599 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 600 IGNORED_REPEAT); 601 outLaunched.value = false; 602 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 603 outLaunched); 604 assertTrue(outLaunched.value); 605 assertTrue(intercepted); 606 607 verify(mUiEventLogger, times(1)) 608 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); 609 verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected(); 610 611 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 612 verify(mMetricsLogger, times(5)).histogram( 613 eq("power_double_tap_interval"), intervalCaptor.capture()); 614 List<Integer> intervals = intervalCaptor.getAllValues(); 615 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 616 assertEquals((int) interval, intervals.get(1).intValue()); 617 } 618 619 @Test 620 public void testInterceptPowerKeyDown_tenInboundPresses_emergencyGestureEnabled_keyIntercepted()621 testInterceptPowerKeyDown_tenInboundPresses_emergencyGestureEnabled_keyIntercepted() { 622 withEmergencyGestureEnabledConfigValue(true); 623 withEmergencyGestureEnabledSettingValue(true); 624 mGestureLauncherService.updateEmergencyGestureEnabled(); 625 withUserSetupCompleteValue(true); 626 627 // First button press does nothing 628 long eventTime = INITIAL_EVENT_TIME_MILLIS; 629 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 630 IGNORED_REPEAT); 631 boolean interactive = true; 632 MutableBoolean outLaunched = new MutableBoolean(true); 633 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 634 outLaunched); 635 assertFalse(intercepted); 636 assertFalse(outLaunched.value); 637 638 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 639 // 3 more button presses which should not trigger any gesture, but intercepts action. 640 for (int i = 0; i < 3; i++) { 641 eventTime += interval; 642 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 643 IGNORED_REPEAT); 644 outLaunched.value = false; 645 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 646 outLaunched); 647 assertTrue(intercepted); 648 assertFalse(outLaunched.value); 649 } 650 651 // Fifth button press should trigger the emergency flow 652 eventTime += interval; 653 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 654 IGNORED_REPEAT); 655 outLaunched.value = false; 656 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 657 outLaunched); 658 assertTrue(outLaunched.value); 659 assertTrue(intercepted); 660 661 // 5 more button presses which should not trigger any gesture, but intercepts action. 662 for (int i = 0; i < 5; i++) { 663 eventTime += interval; 664 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 665 IGNORED_REPEAT); 666 outLaunched.value = false; 667 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 668 outLaunched); 669 assertTrue(intercepted); 670 assertFalse(outLaunched.value); 671 } 672 } 673 674 @Test testInterceptPowerKeyDown_triggerEmergency_singleTaps_cooldownTriggered()675 public void testInterceptPowerKeyDown_triggerEmergency_singleTaps_cooldownTriggered() { 676 // Enable power button cooldown 677 withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000); 678 mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); 679 680 // Trigger emergency by tapping button 5 times 681 long eventTime = triggerEmergencyGesture(); 682 683 // Add enough interval to reset consecutive tap count 684 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; 685 eventTime += interval; 686 687 // Subsequent single tap is intercepted, but should not trigger any gesture 688 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 689 IGNORED_REPEAT); 690 boolean interactive = true; 691 MutableBoolean outLaunched = new MutableBoolean(true); 692 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 693 outLaunched); 694 assertTrue(intercepted); 695 assertFalse(outLaunched.value); 696 697 // Add enough interval to reset consecutive tap count 698 interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; 699 eventTime += interval; 700 701 // Another single tap should be the same (intercepted but should not trigger gesture) 702 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 703 IGNORED_REPEAT); 704 interactive = true; 705 outLaunched = new MutableBoolean(true); 706 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 707 outLaunched); 708 assertTrue(intercepted); 709 assertFalse(outLaunched.value); 710 } 711 712 @Test 713 public void testInterceptPowerKeyDown_triggerEmergency_cameraGestureEnabled_doubleTap_cooldownTriggered()714 testInterceptPowerKeyDown_triggerEmergency_cameraGestureEnabled_doubleTap_cooldownTriggered() { 715 // Enable camera double tap gesture 716 withCameraDoubleTapPowerEnableConfigValue(true); 717 withCameraDoubleTapPowerDisableSettingValue(0); 718 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 719 720 // Enable power button cooldown 721 withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000); 722 mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); 723 724 // Trigger emergency by tapping button 5 times 725 long eventTime = triggerEmergencyGesture(); 726 727 // Add enough interval to reset consecutive tap count 728 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; 729 eventTime += interval; 730 731 // Subsequent double tap is intercepted, but should not trigger any gesture 732 for (int i = 0; i < 2; i++) { 733 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, 734 IGNORED_CODE, IGNORED_REPEAT); 735 boolean interactive = true; 736 MutableBoolean outLaunched = new MutableBoolean(true); 737 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, 738 interactive, outLaunched); 739 assertTrue(intercepted); 740 assertFalse(outLaunched.value); 741 interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 742 eventTime += interval; 743 } 744 } 745 746 @Test testInterceptPowerKeyDown_triggerEmergency_fiveTaps_cooldownTriggered()747 public void testInterceptPowerKeyDown_triggerEmergency_fiveTaps_cooldownTriggered() { 748 // Enable power button cooldown 749 withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000); 750 mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); 751 752 // Trigger emergency by tapping button 5 times 753 long eventTime = triggerEmergencyGesture(); 754 755 // Add enough interval to reset consecutive tap count 756 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; 757 eventTime += interval; 758 759 // Subsequent 5 taps are intercepted, but should not trigger any gesture 760 for (int i = 0; i < 5; i++) { 761 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, 762 IGNORED_CODE, IGNORED_REPEAT); 763 boolean interactive = true; 764 MutableBoolean outLaunched = new MutableBoolean(true); 765 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, 766 interactive, outLaunched); 767 assertTrue(intercepted); 768 assertFalse(outLaunched.value); 769 interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 770 eventTime += interval; 771 } 772 } 773 774 @Test testInterceptPowerKeyDown_triggerEmergency_fiveFastTaps_gestureIgnored()775 public void testInterceptPowerKeyDown_triggerEmergency_fiveFastTaps_gestureIgnored() { 776 // Trigger emergency by tapping button 5 times 777 long eventTime = triggerEmergencyGesture(/* tapIntervalMs= */ 1); 778 779 // Add 1 more millisecond and send the event again. 780 eventTime += 1; 781 782 // Subsequent long press is intercepted, but should not trigger any gesture 783 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 784 IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE, 785 KeyEvent.FLAG_LONG_PRESS); 786 MutableBoolean outLaunched = new MutableBoolean(true); 787 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown( 788 keyEvent, 789 /* interactive= */ true, 790 outLaunched); 791 assertFalse(intercepted); 792 assertFalse(outLaunched.value); 793 } 794 795 @Test testInterceptPowerKeyDown_triggerEmergency_longPress_cooldownTriggered()796 public void testInterceptPowerKeyDown_triggerEmergency_longPress_cooldownTriggered() { 797 // Enable power button cooldown 798 withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000); 799 mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); 800 801 // Trigger emergency by tapping button 5 times 802 long eventTime = triggerEmergencyGesture(); 803 804 // Add enough interval to reset consecutive tap count 805 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; 806 eventTime += interval; 807 808 // Subsequent long press is intercepted, but should not trigger any gesture 809 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 810 IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE, 811 KeyEvent.FLAG_LONG_PRESS); 812 813 boolean interactive = true; 814 MutableBoolean outLaunched = new MutableBoolean(true); 815 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 816 outLaunched); 817 assertTrue(intercepted); 818 assertFalse(outLaunched.value); 819 } 820 821 @Test testInterceptPowerKeyDown_triggerEmergency_cooldownDisabled_cooldownNotTriggered()822 public void testInterceptPowerKeyDown_triggerEmergency_cooldownDisabled_cooldownNotTriggered() { 823 // Disable power button cooldown by setting cooldown period to 0 824 withEmergencyGesturePowerButtonCooldownPeriodMsValue(0); 825 mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); 826 827 // Trigger emergency by tapping button 5 times 828 long eventTime = triggerEmergencyGesture(); 829 830 // Add enough interval to reset consecutive tap count 831 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; 832 eventTime += interval; 833 834 // Subsequent single tap is NOT intercepted 835 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 836 IGNORED_REPEAT); 837 boolean interactive = true; 838 MutableBoolean outLaunched = new MutableBoolean(true); 839 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 840 outLaunched); 841 assertFalse(intercepted); 842 assertFalse(outLaunched.value); 843 844 // Add enough interval to reset consecutive tap count 845 interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; 846 eventTime += interval; 847 848 // Long press also NOT intercepted 849 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 850 IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE, 851 KeyEvent.FLAG_LONG_PRESS); 852 interactive = true; 853 outLaunched = new MutableBoolean(true); 854 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 855 outLaunched); 856 assertFalse(intercepted); 857 assertFalse(outLaunched.value); 858 } 859 860 @Test 861 public void testInterceptPowerKeyDown_triggerEmergency_outsideCooldownPeriod_cooldownNotTriggered()862 testInterceptPowerKeyDown_triggerEmergency_outsideCooldownPeriod_cooldownNotTriggered() { 863 // Enable power button cooldown 864 withEmergencyGesturePowerButtonCooldownPeriodMsValue(5000); 865 mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); 866 867 // Trigger emergency by tapping button 5 times 868 long eventTime = triggerEmergencyGesture(); 869 870 // Add enough interval to be outside of cooldown period 871 long interval = 5001; 872 eventTime += interval; 873 874 // Subsequent single tap is NOT intercepted 875 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 876 IGNORED_REPEAT); 877 boolean interactive = true; 878 MutableBoolean outLaunched = new MutableBoolean(true); 879 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 880 outLaunched); 881 assertFalse(intercepted); 882 assertFalse(outLaunched.value); 883 884 // Add enough interval to reset consecutive tap count 885 interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; 886 eventTime += interval; 887 888 // Long press also NOT intercepted 889 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 890 IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE, 891 KeyEvent.FLAG_LONG_PRESS); 892 interactive = true; 893 outLaunched = new MutableBoolean(true); 894 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 895 outLaunched); 896 assertFalse(intercepted); 897 assertFalse(outLaunched.value); 898 } 899 900 @Test testInterceptPowerKeyDown_longpress()901 public void testInterceptPowerKeyDown_longpress() { 902 withCameraDoubleTapPowerEnableConfigValue(true); 903 withCameraDoubleTapPowerDisableSettingValue(0); 904 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 905 withUserSetupCompleteValue(true); 906 907 long eventTime = INITIAL_EVENT_TIME_MILLIS; 908 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 909 IGNORED_REPEAT); 910 boolean interactive = true; 911 MutableBoolean outLaunched = new MutableBoolean(true); 912 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 913 outLaunched); 914 assertFalse(intercepted); 915 assertFalse(outLaunched.value); 916 917 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 918 eventTime += interval; 919 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 920 IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE, 921 KeyEvent.FLAG_LONG_PRESS); 922 outLaunched.value = false; 923 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 924 outLaunched); 925 assertFalse(intercepted); 926 assertFalse(outLaunched.value); 927 928 verify(mMetricsLogger, never()) 929 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 930 verify(mUiEventLogger, never()).log(any()); 931 932 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 933 verify(mMetricsLogger, times(1)).histogram( 934 eq("power_double_tap_interval"), intervalCaptor.capture()); 935 List<Integer> intervals = intervalCaptor.getAllValues(); 936 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 937 938 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 939 verify(mMetricsLogger, times(1)).histogram( 940 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 941 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 942 assertEquals(1, tapCounts.get(0).intValue()); 943 } 944 945 @Test 946 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupIncomplete()947 testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupIncomplete() { 948 withCameraDoubleTapPowerEnableConfigValue(true); 949 withCameraDoubleTapPowerDisableSettingValue(0); 950 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 951 withUserSetupCompleteValue(false); 952 953 long eventTime = INITIAL_EVENT_TIME_MILLIS; 954 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 955 IGNORED_REPEAT); 956 boolean interactive = true; 957 MutableBoolean outLaunched = new MutableBoolean(true); 958 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 959 outLaunched); 960 assertFalse(intercepted); 961 assertFalse(outLaunched.value); 962 963 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 964 eventTime += interval; 965 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 966 IGNORED_REPEAT); 967 outLaunched.value = true; 968 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 969 outLaunched); 970 assertFalse(intercepted); 971 assertFalse(outLaunched.value); 972 973 verify(mMetricsLogger, never()) 974 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 975 verify(mUiEventLogger, never()).log(any()); 976 977 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 978 verify(mMetricsLogger, times(2)).histogram( 979 eq("power_double_tap_interval"), intervalCaptor.capture()); 980 List<Integer> intervals = intervalCaptor.getAllValues(); 981 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 982 assertEquals((int) interval, intervals.get(1).intValue()); 983 984 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 985 verify(mMetricsLogger, times(2)).histogram( 986 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 987 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 988 assertEquals(1, tapCounts.get(0).intValue()); 989 // The interval is too long to launch the camera, but short enough to count as a 990 // sequential tap. 991 assertEquals(2, tapCounts.get(1).intValue()); 992 } 993 994 @Test testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnInteractive()995 public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnInteractive() { 996 withCameraDoubleTapPowerEnableConfigValue(true); 997 withCameraDoubleTapPowerDisableSettingValue(0); 998 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 999 1000 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1001 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1002 IGNORED_REPEAT); 1003 boolean interactive = true; 1004 MutableBoolean outLaunched = new MutableBoolean(true); 1005 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1006 outLaunched); 1007 assertFalse(intercepted); 1008 assertFalse(outLaunched.value); 1009 1010 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; 1011 eventTime += interval; 1012 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1013 IGNORED_REPEAT); 1014 outLaunched.value = true; 1015 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1016 outLaunched); 1017 assertFalse(intercepted); 1018 assertFalse(outLaunched.value); 1019 1020 verify(mMetricsLogger, never()) 1021 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 1022 verify(mUiEventLogger, never()).log(any()); 1023 1024 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1025 verify(mMetricsLogger, times(2)).histogram( 1026 eq("power_double_tap_interval"), intervalCaptor.capture()); 1027 List<Integer> intervals = intervalCaptor.getAllValues(); 1028 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1029 assertEquals((int) interval, intervals.get(1).intValue()); 1030 1031 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1032 verify(mMetricsLogger, times(2)).histogram( 1033 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1034 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1035 assertEquals(1, tapCounts.get(0).intValue()); 1036 // The interval is too long to launch the camera, but short enough to count as a 1037 // sequential tap. 1038 assertEquals(2, tapCounts.get(1).intValue()); 1039 } 1040 1041 @Test testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnInteractive()1042 public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnInteractive() { 1043 withCameraDoubleTapPowerEnableConfigValue(true); 1044 withCameraDoubleTapPowerDisableSettingValue(0); 1045 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 1046 1047 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1048 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1049 IGNORED_REPEAT); 1050 boolean interactive = true; 1051 MutableBoolean outLaunched = new MutableBoolean(true); 1052 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1053 outLaunched); 1054 assertFalse(intercepted); 1055 assertFalse(outLaunched.value); 1056 1057 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS; 1058 eventTime += interval; 1059 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1060 IGNORED_REPEAT); 1061 outLaunched.value = true; 1062 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1063 outLaunched); 1064 assertFalse(intercepted); 1065 assertFalse(outLaunched.value); 1066 1067 verify(mMetricsLogger, never()) 1068 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 1069 verify(mUiEventLogger, never()).log(any()); 1070 1071 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1072 verify(mMetricsLogger, times(2)).histogram( 1073 eq("power_double_tap_interval"), intervalCaptor.capture()); 1074 List<Integer> intervals = intervalCaptor.getAllValues(); 1075 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1076 assertEquals((int) interval, intervals.get(1).intValue()); 1077 1078 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1079 verify(mMetricsLogger, times(2)).histogram( 1080 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1081 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1082 assertEquals(1, tapCounts.get(0).intValue()); 1083 assertEquals(1, tapCounts.get(1).intValue()); 1084 } 1085 1086 @Test testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffNotInteractive()1087 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffNotInteractive() { 1088 withCameraDoubleTapPowerEnableConfigValue(false); 1089 withCameraDoubleTapPowerDisableSettingValue(1); 1090 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 1091 1092 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1093 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1094 IGNORED_REPEAT); 1095 boolean interactive = false; 1096 MutableBoolean outLaunched = new MutableBoolean(true); 1097 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1098 outLaunched); 1099 assertFalse(intercepted); 1100 assertFalse(outLaunched.value); 1101 1102 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 1103 eventTime += interval; 1104 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1105 IGNORED_REPEAT); 1106 outLaunched.value = true; 1107 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1108 outLaunched); 1109 assertFalse(intercepted); 1110 assertFalse(outLaunched.value); 1111 1112 verify(mMetricsLogger, never()) 1113 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 1114 verify(mUiEventLogger, never()).log(any()); 1115 1116 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1117 verify(mMetricsLogger, times(2)).histogram( 1118 eq("power_double_tap_interval"), intervalCaptor.capture()); 1119 List<Integer> intervals = intervalCaptor.getAllValues(); 1120 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1121 assertEquals((int) interval, intervals.get(1).intValue()); 1122 1123 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1124 verify(mMetricsLogger, times(2)).histogram( 1125 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1126 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1127 assertEquals(1, tapCounts.get(0).intValue()); 1128 assertEquals(2, tapCounts.get(1).intValue()); 1129 } 1130 1131 @Test testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffNotInteractive()1132 public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffNotInteractive() { 1133 withCameraDoubleTapPowerEnableConfigValue(false); 1134 withCameraDoubleTapPowerDisableSettingValue(1); 1135 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 1136 1137 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1138 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1139 IGNORED_REPEAT); 1140 boolean interactive = false; 1141 MutableBoolean outLaunched = new MutableBoolean(true); 1142 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1143 outLaunched); 1144 assertFalse(intercepted); 1145 assertFalse(outLaunched.value); 1146 1147 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; 1148 eventTime += interval; 1149 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1150 IGNORED_REPEAT); 1151 outLaunched.value = true; 1152 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1153 outLaunched); 1154 assertFalse(intercepted); 1155 assertFalse(outLaunched.value); 1156 verify(mMetricsLogger, never()) 1157 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 1158 verify(mUiEventLogger, never()).log(any()); 1159 1160 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1161 verify(mMetricsLogger, times(2)).histogram( 1162 eq("power_double_tap_interval"), intervalCaptor.capture()); 1163 List<Integer> intervals = intervalCaptor.getAllValues(); 1164 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1165 assertEquals((int) interval, intervals.get(1).intValue()); 1166 1167 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1168 verify(mMetricsLogger, times(2)).histogram( 1169 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1170 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1171 assertEquals(1, tapCounts.get(0).intValue()); 1172 // The interval is too long to launch the camera, but short enough to count as a 1173 // sequential tap. 1174 assertEquals(2, tapCounts.get(1).intValue()); 1175 } 1176 1177 @Test testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffNotInteractive()1178 public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffNotInteractive() { 1179 withCameraDoubleTapPowerEnableConfigValue(false); 1180 withCameraDoubleTapPowerDisableSettingValue(1); 1181 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 1182 1183 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1184 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1185 IGNORED_REPEAT); 1186 boolean interactive = false; 1187 MutableBoolean outLaunched = new MutableBoolean(true); 1188 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1189 outLaunched); 1190 assertFalse(intercepted); 1191 assertFalse(outLaunched.value); 1192 1193 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS; 1194 eventTime += interval; 1195 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1196 IGNORED_REPEAT); 1197 outLaunched.value = true; 1198 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1199 outLaunched); 1200 assertFalse(intercepted); 1201 assertFalse(outLaunched.value); 1202 verify(mMetricsLogger, never()) 1203 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 1204 verify(mUiEventLogger, never()).log(any()); 1205 1206 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1207 verify(mMetricsLogger, times(2)).histogram( 1208 eq("power_double_tap_interval"), intervalCaptor.capture()); 1209 List<Integer> intervals = intervalCaptor.getAllValues(); 1210 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1211 assertEquals((int) interval, intervals.get(1).intValue()); 1212 1213 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1214 verify(mMetricsLogger, times(2)).histogram( 1215 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1216 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1217 assertEquals(1, tapCounts.get(0).intValue()); 1218 assertEquals(1, tapCounts.get(1).intValue()); 1219 } 1220 1221 @Test 1222 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupComplete()1223 testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupComplete() { 1224 withCameraDoubleTapPowerEnableConfigValue(true); 1225 withCameraDoubleTapPowerDisableSettingValue(0); 1226 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 1227 withUserSetupCompleteValue(true); 1228 1229 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1230 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1231 IGNORED_REPEAT); 1232 boolean interactive = false; 1233 MutableBoolean outLaunched = new MutableBoolean(true); 1234 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1235 outLaunched); 1236 assertFalse(intercepted); 1237 assertFalse(outLaunched.value); 1238 1239 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 1240 eventTime += interval; 1241 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1242 IGNORED_REPEAT); 1243 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1244 outLaunched); 1245 assertFalse(intercepted); 1246 assertTrue(outLaunched.value); 1247 1248 verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected( 1249 StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); 1250 verify(mMetricsLogger) 1251 .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval); 1252 verify(mUiEventLogger, times(1)) 1253 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER); 1254 1255 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1256 verify(mMetricsLogger, times(2)).histogram( 1257 eq("power_double_tap_interval"), intervalCaptor.capture()); 1258 List<Integer> intervals = intervalCaptor.getAllValues(); 1259 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1260 assertEquals((int) interval, intervals.get(1).intValue()); 1261 1262 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1263 verify(mMetricsLogger, times(2)).histogram( 1264 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1265 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1266 assertEquals(1, tapCounts.get(0).intValue()); 1267 assertEquals(2, tapCounts.get(1).intValue()); 1268 } 1269 1270 @Test 1271 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupIncomplete()1272 testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupIncomplete() { 1273 withCameraDoubleTapPowerEnableConfigValue(true); 1274 withCameraDoubleTapPowerDisableSettingValue(0); 1275 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 1276 withUserSetupCompleteValue(false); 1277 1278 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1279 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1280 IGNORED_REPEAT); 1281 boolean interactive = false; 1282 MutableBoolean outLaunched = new MutableBoolean(true); 1283 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1284 outLaunched); 1285 assertFalse(intercepted); 1286 assertFalse(outLaunched.value); 1287 1288 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 1289 eventTime += interval; 1290 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1291 IGNORED_REPEAT); 1292 outLaunched.value = true; 1293 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1294 outLaunched); 1295 assertFalse(intercepted); 1296 assertFalse(outLaunched.value); 1297 1298 verify(mMetricsLogger, never()) 1299 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 1300 verify(mUiEventLogger, never()).log(any()); 1301 1302 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1303 verify(mMetricsLogger, times(2)).histogram( 1304 eq("power_double_tap_interval"), intervalCaptor.capture()); 1305 List<Integer> intervals = intervalCaptor.getAllValues(); 1306 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1307 assertEquals((int) interval, intervals.get(1).intValue()); 1308 1309 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1310 verify(mMetricsLogger, times(2)).histogram( 1311 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1312 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1313 assertEquals(1, tapCounts.get(0).intValue()); 1314 assertEquals(2, tapCounts.get(1).intValue()); 1315 } 1316 1317 @Test testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnNotInteractive()1318 public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnNotInteractive() { 1319 withCameraDoubleTapPowerEnableConfigValue(true); 1320 withCameraDoubleTapPowerDisableSettingValue(0); 1321 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 1322 1323 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1324 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1325 IGNORED_REPEAT); 1326 boolean interactive = false; 1327 MutableBoolean outLaunched = new MutableBoolean(true); 1328 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1329 outLaunched); 1330 assertFalse(intercepted); 1331 assertFalse(outLaunched.value); 1332 1333 final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; 1334 eventTime += interval; 1335 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1336 IGNORED_REPEAT); 1337 outLaunched.value = true; 1338 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1339 outLaunched); 1340 assertFalse(intercepted); 1341 assertFalse(outLaunched.value); 1342 1343 verify(mMetricsLogger, never()) 1344 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 1345 verify(mUiEventLogger, never()).log(any()); 1346 1347 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1348 verify(mMetricsLogger, times(2)).histogram( 1349 eq("power_double_tap_interval"), intervalCaptor.capture()); 1350 List<Integer> intervals = intervalCaptor.getAllValues(); 1351 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1352 assertEquals((int) interval, intervals.get(1).intValue()); 1353 1354 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1355 verify(mMetricsLogger, times(2)).histogram( 1356 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1357 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1358 assertEquals(1, tapCounts.get(0).intValue()); 1359 // The interval is too long to launch the camera, but short enough to count as a 1360 // sequential tap. 1361 assertEquals(2, tapCounts.get(1).intValue()); 1362 } 1363 1364 @Test testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnNotInteractive()1365 public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnNotInteractive() { 1366 withCameraDoubleTapPowerEnableConfigValue(true); 1367 withCameraDoubleTapPowerDisableSettingValue(0); 1368 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 1369 1370 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1371 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1372 IGNORED_REPEAT); 1373 boolean interactive = false; 1374 MutableBoolean outLaunched = new MutableBoolean(true); 1375 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1376 outLaunched); 1377 assertFalse(intercepted); 1378 assertFalse(outLaunched.value); 1379 1380 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS; 1381 eventTime += interval; 1382 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1383 IGNORED_REPEAT); 1384 outLaunched.value = true; 1385 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1386 outLaunched); 1387 assertFalse(intercepted); 1388 assertFalse(outLaunched.value); 1389 1390 verify(mMetricsLogger, never()) 1391 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 1392 verify(mUiEventLogger, never()).log(any()); 1393 1394 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1395 verify(mMetricsLogger, times(2)).histogram( 1396 eq("power_double_tap_interval"), intervalCaptor.capture()); 1397 List<Integer> intervals = intervalCaptor.getAllValues(); 1398 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1399 assertEquals((int) interval, intervals.get(1).intValue()); 1400 1401 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1402 verify(mMetricsLogger, times(2)).histogram( 1403 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1404 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1405 assertEquals(1, tapCounts.get(0).intValue()); 1406 assertEquals(1, tapCounts.get(1).intValue()); 1407 } 1408 1409 /** 1410 * Helper method to trigger emergency gesture by pressing button for 5 times. 1411 * 1412 * @return last event time. 1413 */ triggerEmergencyGesture()1414 private long triggerEmergencyGesture() { 1415 return triggerEmergencyGesture(CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1); 1416 } 1417 1418 /** 1419 * Helper method to trigger emergency gesture by pressing button for 5 times with 1420 * specified interval between each tap 1421 * 1422 * @return last event time. 1423 */ triggerEmergencyGesture(long tapIntervalMs)1424 private long triggerEmergencyGesture(long tapIntervalMs) { 1425 // Enable emergency power gesture 1426 withEmergencyGestureEnabledConfigValue(true); 1427 withEmergencyGestureEnabledSettingValue(true); 1428 mGestureLauncherService.updateEmergencyGestureEnabled(); 1429 withUserSetupCompleteValue(true); 1430 1431 // 4 button presses 1432 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1433 boolean interactive = true; 1434 KeyEvent keyEvent; 1435 MutableBoolean outLaunched = new MutableBoolean(false); 1436 for (int i = 0; i < 4; i++) { 1437 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1438 IGNORED_REPEAT); 1439 mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); 1440 eventTime += tapIntervalMs; 1441 } 1442 1443 // 5th button press should trigger the emergency flow 1444 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1445 IGNORED_REPEAT); 1446 outLaunched.value = false; 1447 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1448 outLaunched); 1449 long emergencyGestureTapDetectionMinTimeMs = Settings.Global.getInt( 1450 mContext.getContentResolver(), 1451 Settings.Global.EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS, 1452 EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS); 1453 assertTrue(intercepted); 1454 if (tapIntervalMs * 4 > emergencyGestureTapDetectionMinTimeMs) { 1455 assertTrue(outLaunched.value); 1456 verify(mUiEventLogger, times(1)) 1457 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); 1458 verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected(); 1459 } else { 1460 assertFalse(outLaunched.value); 1461 verify(mUiEventLogger, never()) 1462 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); 1463 verify(mStatusBarManagerInternal, never()).onEmergencyActionLaunchGestureDetected(); 1464 } 1465 return eventTime; 1466 } 1467 withCameraDoubleTapPowerEnableConfigValue(boolean enableConfigValue)1468 private void withCameraDoubleTapPowerEnableConfigValue(boolean enableConfigValue) { 1469 when(mResources.getBoolean( 1470 com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled)) 1471 .thenReturn(enableConfigValue); 1472 } 1473 withEmergencyGestureEnabledConfigValue(boolean enableConfigValue)1474 private void withEmergencyGestureEnabledConfigValue(boolean enableConfigValue) { 1475 when(mResources.getBoolean( 1476 com.android.internal.R.bool.config_emergencyGestureEnabled)) 1477 .thenReturn(enableConfigValue); 1478 } 1479 withCameraDoubleTapPowerDisableSettingValue(int disableSettingValue)1480 private void withCameraDoubleTapPowerDisableSettingValue(int disableSettingValue) { 1481 Settings.Secure.putIntForUser( 1482 mContentResolver, 1483 Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 1484 disableSettingValue, 1485 UserHandle.USER_CURRENT); 1486 } 1487 withEmergencyGestureEnabledSettingValue(boolean enable)1488 private void withEmergencyGestureEnabledSettingValue(boolean enable) { 1489 Settings.Secure.putIntForUser( 1490 mContentResolver, 1491 Settings.Secure.EMERGENCY_GESTURE_ENABLED, 1492 enable ? 1 : 0, 1493 UserHandle.USER_CURRENT); 1494 } 1495 withEmergencyGesturePowerButtonCooldownPeriodMsValue(int period)1496 private void withEmergencyGesturePowerButtonCooldownPeriodMsValue(int period) { 1497 Settings.Global.putInt( 1498 mContentResolver, 1499 Settings.Global.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS, 1500 period); 1501 } 1502 withUserSetupCompleteValue(boolean userSetupComplete)1503 private void withUserSetupCompleteValue(boolean userSetupComplete) { 1504 int userSetupCompleteValue = userSetupComplete ? 1 : 0; 1505 Settings.Secure.putIntForUser( 1506 mContentResolver, 1507 Settings.Secure.USER_SETUP_COMPLETE, 1508 userSetupCompleteValue, 1509 UserHandle.USER_CURRENT); 1510 } 1511 } 1512