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.ArgumentMatchers.any; 23 import static org.mockito.Matchers.anyInt; 24 import static org.mockito.Matchers.eq; 25 import static org.mockito.Mockito.never; 26 import static org.mockito.Mockito.times; 27 import static org.mockito.Mockito.verify; 28 import static org.mockito.Mockito.when; 29 30 import android.app.StatusBarManager; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.res.Resources; 34 import android.os.Looper; 35 import android.os.UserHandle; 36 import android.platform.test.annotations.Presubmit; 37 import android.provider.Settings; 38 import android.telecom.TelecomManager; 39 import android.test.mock.MockContentResolver; 40 import android.testing.TestableLooper; 41 import android.util.MutableBoolean; 42 import android.view.KeyEvent; 43 44 import androidx.test.InstrumentationRegistry; 45 import androidx.test.filters.SmallTest; 46 import androidx.test.runner.AndroidJUnit4; 47 48 import com.android.internal.logging.MetricsLogger; 49 import com.android.internal.logging.UiEventLogger; 50 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 51 import com.android.internal.util.test.FakeSettingsProvider; 52 import com.android.server.statusbar.StatusBarManagerInternal; 53 54 import org.junit.Before; 55 import org.junit.BeforeClass; 56 import org.junit.Test; 57 import org.junit.runner.RunWith; 58 import org.mockito.ArgumentCaptor; 59 import org.mockito.Mock; 60 import org.mockito.MockitoAnnotations; 61 62 import java.util.List; 63 64 /** 65 * Unit tests for {@link GestureLauncherService}. 66 * runtest frameworks-services -c com.android.server.GestureLauncherServiceTest 67 */ 68 @Presubmit 69 @SmallTest 70 @RunWith(AndroidJUnit4.class) 71 @TestableLooper.RunWithLooper(setAsMainLooper = true) 72 public class GestureLauncherServiceTest { 73 74 private static final int FAKE_USER_ID = 1337; 75 private static final int FAKE_SOURCE = 1982; 76 private static final long INITIAL_EVENT_TIME_MILLIS = 20000L; 77 private static final long IGNORED_DOWN_TIME = 1234L; 78 private static final int IGNORED_ACTION = 13; 79 private static final int IGNORED_CODE = 1999; 80 private static final int IGNORED_REPEAT = 42; 81 private static final int IGNORED_META_STATE = 0; 82 private static final int IGNORED_DEVICE_ID = 0; 83 private static final int IGNORED_SCANCODE = 0; 84 85 private @Mock Context mContext; 86 private @Mock Resources mResources; 87 private @Mock StatusBarManagerInternal mStatusBarManagerInternal; 88 private @Mock TelecomManager mTelecomManager; 89 private @Mock MetricsLogger mMetricsLogger; 90 @Mock private UiEventLogger mUiEventLogger; 91 private MockContentResolver mContentResolver; 92 private GestureLauncherService mGestureLauncherService; 93 94 @BeforeClass oneTimeInitialization()95 public static void oneTimeInitialization() { 96 if (Looper.myLooper() == null) { 97 Looper.prepare(); 98 } 99 } 100 101 @Before setup()102 public void setup() { 103 MockitoAnnotations.initMocks(this); 104 105 LocalServices.removeServiceForTest(StatusBarManagerInternal.class); 106 LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal); 107 108 final Context originalContext = InstrumentationRegistry.getContext(); 109 when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo()); 110 when(mContext.getResources()).thenReturn(mResources); 111 mContentResolver = new MockContentResolver(mContext); 112 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); 113 when(mContext.getContentResolver()).thenReturn(mContentResolver); 114 when(mContext.getSystemService(Context.TELECOM_SERVICE)).thenReturn(mTelecomManager); 115 when(mTelecomManager.createLaunchEmergencyDialerIntent(null)).thenReturn(new Intent()); 116 117 mGestureLauncherService = new GestureLauncherService(mContext, mMetricsLogger, 118 mUiEventLogger); 119 } 120 121 @Test testIsCameraDoubleTapPowerEnabled_configFalse()122 public void testIsCameraDoubleTapPowerEnabled_configFalse() { 123 withCameraDoubleTapPowerEnableConfigValue(false); 124 assertFalse(mGestureLauncherService.isCameraDoubleTapPowerEnabled(mResources)); 125 } 126 127 @Test testIsCameraDoubleTapPowerEnabled_configTrue()128 public void testIsCameraDoubleTapPowerEnabled_configTrue() { 129 withCameraDoubleTapPowerEnableConfigValue(true); 130 assertTrue(mGestureLauncherService.isCameraDoubleTapPowerEnabled(mResources)); 131 } 132 133 @Test testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingDisabled()134 public void testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingDisabled() { 135 withCameraDoubleTapPowerEnableConfigValue(false); 136 withCameraDoubleTapPowerDisableSettingValue(1); 137 assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( 138 mContext, FAKE_USER_ID)); 139 } 140 141 @Test testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingEnabled()142 public void testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingEnabled() { 143 withCameraDoubleTapPowerEnableConfigValue(false); 144 withCameraDoubleTapPowerDisableSettingValue(0); 145 assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( 146 mContext, FAKE_USER_ID)); 147 } 148 149 @Test testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingDisabled()150 public void testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingDisabled() { 151 withCameraDoubleTapPowerEnableConfigValue(true); 152 withCameraDoubleTapPowerDisableSettingValue(1); 153 assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( 154 mContext, FAKE_USER_ID)); 155 } 156 157 @Test testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingEnabled()158 public void testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingEnabled() { 159 withCameraDoubleTapPowerEnableConfigValue(true); 160 withCameraDoubleTapPowerDisableSettingValue(0); 161 assertTrue(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( 162 mContext, FAKE_USER_ID)); 163 } 164 165 @Test testIsEmergencyGestureSettingEnabled_settingDisabled()166 public void testIsEmergencyGestureSettingEnabled_settingDisabled() { 167 withEmergencyGestureEnabledConfigValue(true); 168 withEmergencyGestureEnabledSettingValue(false); 169 assertFalse(mGestureLauncherService.isEmergencyGestureSettingEnabled( 170 mContext, FAKE_USER_ID)); 171 } 172 173 @Test testIsEmergencyGestureSettingEnabled_settingEnabled()174 public void testIsEmergencyGestureSettingEnabled_settingEnabled() { 175 withEmergencyGestureEnabledConfigValue(true); 176 withEmergencyGestureEnabledSettingValue(true); 177 assertTrue(mGestureLauncherService.isEmergencyGestureSettingEnabled( 178 mContext, FAKE_USER_ID)); 179 } 180 181 @Test testIsEmergencyGestureSettingEnabled_supportDisabled()182 public void testIsEmergencyGestureSettingEnabled_supportDisabled() { 183 withEmergencyGestureEnabledConfigValue(false); 184 withEmergencyGestureEnabledSettingValue(true); 185 assertFalse(mGestureLauncherService.isEmergencyGestureSettingEnabled( 186 mContext, FAKE_USER_ID)); 187 } 188 189 @Test testHandleCameraLaunchGesture_userSetupComplete()190 public void testHandleCameraLaunchGesture_userSetupComplete() { 191 withUserSetupCompleteValue(true); 192 193 boolean useWakeLock = false; 194 assertTrue(mGestureLauncherService.handleCameraGesture(useWakeLock, FAKE_SOURCE)); 195 verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected(FAKE_SOURCE); 196 } 197 198 @Test testHandleEmergencyGesture_userSetupComplete()199 public void testHandleEmergencyGesture_userSetupComplete() { 200 withUserSetupCompleteValue(true); 201 202 assertTrue(mGestureLauncherService.handleEmergencyGesture()); 203 } 204 205 @Test testHandleCameraLaunchGesture_userSetupNotComplete()206 public void testHandleCameraLaunchGesture_userSetupNotComplete() { 207 withUserSetupCompleteValue(false); 208 209 boolean useWakeLock = false; 210 assertFalse(mGestureLauncherService.handleCameraGesture(useWakeLock, FAKE_SOURCE)); 211 } 212 213 @Test testHandleEmergencyGesture_userSetupNotComplete()214 public void testHandleEmergencyGesture_userSetupNotComplete() { 215 withUserSetupCompleteValue(false); 216 217 assertFalse(mGestureLauncherService.handleEmergencyGesture()); 218 } 219 220 @Test testInterceptPowerKeyDown_firstPowerDownCameraPowerGestureOnInteractive()221 public void testInterceptPowerKeyDown_firstPowerDownCameraPowerGestureOnInteractive() { 222 withCameraDoubleTapPowerEnableConfigValue(true); 223 withCameraDoubleTapPowerDisableSettingValue(0); 224 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 225 226 long eventTime = INITIAL_EVENT_TIME_MILLIS + 227 GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 228 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 229 IGNORED_REPEAT); 230 boolean interactive = true; 231 MutableBoolean outLaunched = new MutableBoolean(true); 232 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 233 outLaunched); 234 assertFalse(intercepted); 235 assertFalse(outLaunched.value); 236 verify(mMetricsLogger).histogram("power_consecutive_short_tap_count", 1); 237 verify(mMetricsLogger).histogram("power_double_tap_interval", (int) eventTime); 238 } 239 240 @Test testInterceptPowerKeyDown_firstPowerDown_emergencyGestureNotLaunched()241 public void testInterceptPowerKeyDown_firstPowerDown_emergencyGestureNotLaunched() { 242 withEmergencyGestureEnabledSettingValue(true); 243 mGestureLauncherService.updateEmergencyGestureEnabled(); 244 245 long eventTime = INITIAL_EVENT_TIME_MILLIS 246 + GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS - 1; 247 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 248 IGNORED_REPEAT); 249 boolean interactive = true; 250 MutableBoolean outLaunched = new MutableBoolean(true); 251 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 252 outLaunched); 253 254 assertFalse(intercepted); 255 assertFalse(outLaunched.value); 256 verify(mMetricsLogger).histogram("power_double_tap_interval", (int) eventTime); 257 } 258 259 @Test testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffInteractive()260 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffInteractive() { 261 withCameraDoubleTapPowerEnableConfigValue(false); 262 withCameraDoubleTapPowerDisableSettingValue(1); 263 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 264 265 long eventTime = INITIAL_EVENT_TIME_MILLIS; 266 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 267 IGNORED_REPEAT); 268 boolean interactive = true; 269 MutableBoolean outLaunched = new MutableBoolean(true); 270 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 271 outLaunched); 272 assertFalse(intercepted); 273 assertFalse(outLaunched.value); 274 275 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 276 eventTime += interval; 277 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 278 IGNORED_REPEAT); 279 outLaunched.value = true; 280 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 281 outLaunched); 282 assertFalse(intercepted); 283 assertFalse(outLaunched.value); 284 285 verify(mMetricsLogger, never()) 286 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 287 verify(mUiEventLogger, never()).log(any()); 288 289 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 290 verify(mMetricsLogger, times(2)).histogram( 291 eq("power_double_tap_interval"), intervalCaptor.capture()); 292 List<Integer> intervals = intervalCaptor.getAllValues(); 293 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 294 assertEquals((int) interval, intervals.get(1).intValue()); 295 296 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 297 verify(mMetricsLogger, times(2)).histogram( 298 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 299 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 300 assertEquals(1, tapCounts.get(0).intValue()); 301 assertEquals(2, tapCounts.get(1).intValue()); 302 } 303 304 @Test testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffInteractive()305 public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffInteractive() { 306 withCameraDoubleTapPowerEnableConfigValue(false); 307 withCameraDoubleTapPowerDisableSettingValue(1); 308 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 309 310 long eventTime = INITIAL_EVENT_TIME_MILLIS; 311 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 312 IGNORED_REPEAT); 313 boolean interactive = true; 314 MutableBoolean outLaunched = new MutableBoolean(true); 315 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 316 outLaunched); 317 assertFalse(intercepted); 318 assertFalse(outLaunched.value); 319 320 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; 321 eventTime += interval; 322 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 323 IGNORED_REPEAT); 324 outLaunched.value = true; 325 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 326 outLaunched); 327 assertFalse(intercepted); 328 assertFalse(outLaunched.value); 329 330 verify(mMetricsLogger, never()) 331 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 332 verify(mUiEventLogger, never()).log(any()); 333 334 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 335 verify(mMetricsLogger, times(2)).histogram( 336 eq("power_double_tap_interval"), intervalCaptor.capture()); 337 List<Integer> intervals = intervalCaptor.getAllValues(); 338 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 339 assertEquals((int) interval, intervals.get(1).intValue()); 340 341 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 342 verify(mMetricsLogger, times(2)).histogram( 343 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 344 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 345 assertEquals(1, tapCounts.get(0).intValue()); 346 // The interval is too long to launch the camera, but short enough to count as a 347 // sequential tap. 348 assertEquals(2, tapCounts.get(1).intValue()); 349 } 350 351 @Test testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffInteractive()352 public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffInteractive() { 353 withCameraDoubleTapPowerEnableConfigValue(false); 354 withCameraDoubleTapPowerDisableSettingValue(1); 355 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 356 357 long eventTime = INITIAL_EVENT_TIME_MILLIS; 358 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 359 IGNORED_REPEAT); 360 boolean interactive = true; 361 MutableBoolean outLaunched = new MutableBoolean(true); 362 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 363 outLaunched); 364 assertFalse(intercepted); 365 assertFalse(outLaunched.value); 366 367 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS; 368 eventTime += interval; 369 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 370 IGNORED_REPEAT); 371 outLaunched.value = true; 372 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 373 outLaunched); 374 assertFalse(intercepted); 375 assertFalse(outLaunched.value); 376 377 verify(mMetricsLogger, never()) 378 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 379 verify(mUiEventLogger, never()).log(any()); 380 381 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 382 verify(mMetricsLogger, times(2)).histogram( 383 eq("power_double_tap_interval"), intervalCaptor.capture()); 384 List<Integer> intervals = intervalCaptor.getAllValues(); 385 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 386 assertEquals((int) interval, intervals.get(1).intValue()); 387 388 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 389 verify(mMetricsLogger, times(2)).histogram( 390 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 391 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 392 assertEquals(1, tapCounts.get(0).intValue()); 393 assertEquals(1, tapCounts.get(1).intValue()); 394 } 395 396 @Test 397 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupComplete()398 testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupComplete() { 399 withCameraDoubleTapPowerEnableConfigValue(true); 400 withCameraDoubleTapPowerDisableSettingValue(0); 401 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 402 withUserSetupCompleteValue(true); 403 404 long eventTime = INITIAL_EVENT_TIME_MILLIS; 405 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 406 IGNORED_REPEAT); 407 boolean interactive = true; 408 MutableBoolean outLaunched = new MutableBoolean(true); 409 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 410 outLaunched); 411 assertFalse(intercepted); 412 assertFalse(outLaunched.value); 413 414 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 415 eventTime += interval; 416 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 417 IGNORED_REPEAT); 418 outLaunched.value = false; 419 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 420 outLaunched); 421 assertTrue(intercepted); 422 assertTrue(outLaunched.value); 423 424 verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected( 425 StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); 426 verify(mMetricsLogger) 427 .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval); 428 verify(mUiEventLogger, times(1)) 429 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER); 430 431 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 432 verify(mMetricsLogger, times(2)).histogram( 433 eq("power_double_tap_interval"), intervalCaptor.capture()); 434 List<Integer> intervals = intervalCaptor.getAllValues(); 435 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 436 assertEquals((int) interval, intervals.get(1).intValue()); 437 438 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 439 verify(mMetricsLogger, times(2)).histogram( 440 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 441 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 442 assertEquals(1, tapCounts.get(0).intValue()); 443 assertEquals(2, tapCounts.get(1).intValue()); 444 } 445 446 @Test 447 public void testInterceptPowerKeyDown_fiveInboundPresses_cameraAndEmergencyEnabled_bothLaunch()448 testInterceptPowerKeyDown_fiveInboundPresses_cameraAndEmergencyEnabled_bothLaunch() { 449 withCameraDoubleTapPowerEnableConfigValue(true); 450 withCameraDoubleTapPowerDisableSettingValue(0); 451 withEmergencyGestureEnabledConfigValue(true); 452 withEmergencyGestureEnabledSettingValue(true); 453 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 454 mGestureLauncherService.updateEmergencyGestureEnabled(); 455 withUserSetupCompleteValue(true); 456 457 // First button press does nothing 458 long eventTime = INITIAL_EVENT_TIME_MILLIS; 459 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 460 IGNORED_REPEAT); 461 boolean interactive = true; 462 MutableBoolean outLaunched = new MutableBoolean(true); 463 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 464 outLaunched); 465 assertFalse(intercepted); 466 assertFalse(outLaunched.value); 467 468 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 469 470 // 2nd button triggers camera 471 eventTime += interval; 472 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 473 IGNORED_REPEAT); 474 outLaunched.value = false; 475 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 476 outLaunched); 477 assertTrue(intercepted); 478 assertTrue(outLaunched.value); 479 480 // Camera checks 481 verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected( 482 StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); 483 verify(mMetricsLogger) 484 .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval); 485 verify(mUiEventLogger, times(1)) 486 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER); 487 488 final ArgumentCaptor<Integer> cameraIntervalCaptor = ArgumentCaptor.forClass(Integer.class); 489 verify(mMetricsLogger, times(2)).histogram( 490 eq("power_double_tap_interval"), cameraIntervalCaptor.capture()); 491 List<Integer> cameraIntervals = cameraIntervalCaptor.getAllValues(); 492 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, cameraIntervals.get(0).intValue()); 493 assertEquals((int) interval, cameraIntervals.get(1).intValue()); 494 495 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 496 verify(mMetricsLogger, times(2)).histogram( 497 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 498 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 499 assertEquals(1, tapCounts.get(0).intValue()); 500 assertEquals(2, tapCounts.get(1).intValue()); 501 502 // Continue the button presses for the emergency gesture. 503 504 // Presses 3 and 4 should not trigger any gesture 505 for (int i = 0; i < 2; i++) { 506 eventTime += interval; 507 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 508 IGNORED_REPEAT); 509 outLaunched.value = false; 510 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 511 outLaunched); 512 assertTrue(intercepted); 513 assertFalse(outLaunched.value); 514 } 515 516 // Fifth button press should trigger the emergency flow 517 eventTime += interval; 518 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 519 IGNORED_REPEAT); 520 outLaunched.value = false; 521 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 522 outLaunched); 523 assertTrue(intercepted); 524 assertTrue(outLaunched.value); 525 526 verify(mUiEventLogger, times(1)) 527 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); 528 verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected(); 529 530 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 531 verify(mMetricsLogger, times(5)).histogram( 532 eq("power_double_tap_interval"), intervalCaptor.capture()); 533 List<Integer> intervals = intervalCaptor.getAllValues(); 534 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 535 assertEquals((int) interval, intervals.get(1).intValue()); 536 } 537 538 @Test 539 public void testInterceptPowerKeyDown_fiveInboundPresses_emergencyGestureEnabled_launchesFlow()540 testInterceptPowerKeyDown_fiveInboundPresses_emergencyGestureEnabled_launchesFlow() { 541 withEmergencyGestureEnabledConfigValue(true); 542 withEmergencyGestureEnabledSettingValue(true); 543 mGestureLauncherService.updateEmergencyGestureEnabled(); 544 withUserSetupCompleteValue(true); 545 546 // First button press does nothing 547 long eventTime = INITIAL_EVENT_TIME_MILLIS; 548 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 549 IGNORED_REPEAT); 550 boolean interactive = true; 551 MutableBoolean outLaunched = new MutableBoolean(true); 552 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 553 outLaunched); 554 assertFalse(intercepted); 555 assertFalse(outLaunched.value); 556 557 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 558 // 3 more button presses which should not trigger any gesture (camera gesture disabled) 559 for (int i = 0; i < 3; i++) { 560 eventTime += interval; 561 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 562 IGNORED_REPEAT); 563 outLaunched.value = false; 564 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 565 outLaunched); 566 assertTrue(intercepted); 567 assertFalse(outLaunched.value); 568 } 569 570 // Fifth button press should trigger the emergency flow 571 eventTime += interval; 572 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 573 IGNORED_REPEAT); 574 outLaunched.value = false; 575 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 576 outLaunched); 577 assertTrue(outLaunched.value); 578 assertTrue(intercepted); 579 580 verify(mUiEventLogger, times(1)) 581 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); 582 verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected(); 583 584 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 585 verify(mMetricsLogger, times(5)).histogram( 586 eq("power_double_tap_interval"), intervalCaptor.capture()); 587 List<Integer> intervals = intervalCaptor.getAllValues(); 588 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 589 assertEquals((int) interval, intervals.get(1).intValue()); 590 } 591 592 @Test 593 public void testInterceptPowerKeyDown_tenInboundPresses_emergencyGestureEnabled_keyIntercepted()594 testInterceptPowerKeyDown_tenInboundPresses_emergencyGestureEnabled_keyIntercepted() { 595 withEmergencyGestureEnabledConfigValue(true); 596 withEmergencyGestureEnabledSettingValue(true); 597 mGestureLauncherService.updateEmergencyGestureEnabled(); 598 withUserSetupCompleteValue(true); 599 600 // First button press does nothing 601 long eventTime = INITIAL_EVENT_TIME_MILLIS; 602 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 603 IGNORED_REPEAT); 604 boolean interactive = true; 605 MutableBoolean outLaunched = new MutableBoolean(true); 606 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 607 outLaunched); 608 assertFalse(intercepted); 609 assertFalse(outLaunched.value); 610 611 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 612 // 3 more button presses which should not trigger any gesture, but intercepts action. 613 for (int i = 0; i < 3; i++) { 614 eventTime += interval; 615 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 616 IGNORED_REPEAT); 617 outLaunched.value = false; 618 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 619 outLaunched); 620 assertTrue(intercepted); 621 assertFalse(outLaunched.value); 622 } 623 624 // Fifth button press should trigger the emergency flow 625 eventTime += interval; 626 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 627 IGNORED_REPEAT); 628 outLaunched.value = false; 629 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 630 outLaunched); 631 assertTrue(outLaunched.value); 632 assertTrue(intercepted); 633 634 // 5 more button presses which should not trigger any gesture, but intercepts action. 635 for (int i = 0; i < 5; i++) { 636 eventTime += interval; 637 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 638 IGNORED_REPEAT); 639 outLaunched.value = false; 640 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 641 outLaunched); 642 assertTrue(intercepted); 643 assertFalse(outLaunched.value); 644 } 645 } 646 647 @Test testInterceptPowerKeyDown_longpress()648 public void testInterceptPowerKeyDown_longpress() { 649 withCameraDoubleTapPowerEnableConfigValue(true); 650 withCameraDoubleTapPowerDisableSettingValue(0); 651 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 652 withUserSetupCompleteValue(true); 653 654 long eventTime = INITIAL_EVENT_TIME_MILLIS; 655 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 656 IGNORED_REPEAT); 657 boolean interactive = true; 658 MutableBoolean outLaunched = new MutableBoolean(true); 659 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 660 outLaunched); 661 assertFalse(intercepted); 662 assertFalse(outLaunched.value); 663 664 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 665 eventTime += interval; 666 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 667 IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE, 668 KeyEvent.FLAG_LONG_PRESS); 669 outLaunched.value = false; 670 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 671 outLaunched); 672 assertFalse(intercepted); 673 assertFalse(outLaunched.value); 674 675 verify(mMetricsLogger, never()) 676 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 677 verify(mUiEventLogger, never()).log(any()); 678 679 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 680 verify(mMetricsLogger, times(1)).histogram( 681 eq("power_double_tap_interval"), intervalCaptor.capture()); 682 List<Integer> intervals = intervalCaptor.getAllValues(); 683 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 684 685 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 686 verify(mMetricsLogger, times(1)).histogram( 687 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 688 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 689 assertEquals(1, tapCounts.get(0).intValue()); 690 } 691 692 @Test 693 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupIncomplete()694 testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupIncomplete() { 695 withCameraDoubleTapPowerEnableConfigValue(true); 696 withCameraDoubleTapPowerDisableSettingValue(0); 697 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 698 withUserSetupCompleteValue(false); 699 700 long eventTime = INITIAL_EVENT_TIME_MILLIS; 701 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 702 IGNORED_REPEAT); 703 boolean interactive = true; 704 MutableBoolean outLaunched = new MutableBoolean(true); 705 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 706 outLaunched); 707 assertFalse(intercepted); 708 assertFalse(outLaunched.value); 709 710 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 711 eventTime += interval; 712 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 713 IGNORED_REPEAT); 714 outLaunched.value = true; 715 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 716 outLaunched); 717 assertFalse(intercepted); 718 assertFalse(outLaunched.value); 719 720 verify(mMetricsLogger, never()) 721 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 722 verify(mUiEventLogger, never()).log(any()); 723 724 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 725 verify(mMetricsLogger, times(2)).histogram( 726 eq("power_double_tap_interval"), intervalCaptor.capture()); 727 List<Integer> intervals = intervalCaptor.getAllValues(); 728 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 729 assertEquals((int) interval, intervals.get(1).intValue()); 730 731 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 732 verify(mMetricsLogger, times(2)).histogram( 733 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 734 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 735 assertEquals(1, tapCounts.get(0).intValue()); 736 // The interval is too long to launch the camera, but short enough to count as a 737 // sequential tap. 738 assertEquals(2, tapCounts.get(1).intValue()); 739 } 740 741 @Test testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnInteractive()742 public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnInteractive() { 743 withCameraDoubleTapPowerEnableConfigValue(true); 744 withCameraDoubleTapPowerDisableSettingValue(0); 745 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 746 747 long eventTime = INITIAL_EVENT_TIME_MILLIS; 748 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 749 IGNORED_REPEAT); 750 boolean interactive = true; 751 MutableBoolean outLaunched = new MutableBoolean(true); 752 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 753 outLaunched); 754 assertFalse(intercepted); 755 assertFalse(outLaunched.value); 756 757 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; 758 eventTime += interval; 759 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 760 IGNORED_REPEAT); 761 outLaunched.value = true; 762 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 763 outLaunched); 764 assertFalse(intercepted); 765 assertFalse(outLaunched.value); 766 767 verify(mMetricsLogger, never()) 768 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 769 verify(mUiEventLogger, never()).log(any()); 770 771 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 772 verify(mMetricsLogger, times(2)).histogram( 773 eq("power_double_tap_interval"), intervalCaptor.capture()); 774 List<Integer> intervals = intervalCaptor.getAllValues(); 775 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 776 assertEquals((int) interval, intervals.get(1).intValue()); 777 778 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 779 verify(mMetricsLogger, times(2)).histogram( 780 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 781 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 782 assertEquals(1, tapCounts.get(0).intValue()); 783 // The interval is too long to launch the camera, but short enough to count as a 784 // sequential tap. 785 assertEquals(2, tapCounts.get(1).intValue()); 786 } 787 788 @Test testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnInteractive()789 public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnInteractive() { 790 withCameraDoubleTapPowerEnableConfigValue(true); 791 withCameraDoubleTapPowerDisableSettingValue(0); 792 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 793 794 long eventTime = INITIAL_EVENT_TIME_MILLIS; 795 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 796 IGNORED_REPEAT); 797 boolean interactive = true; 798 MutableBoolean outLaunched = new MutableBoolean(true); 799 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 800 outLaunched); 801 assertFalse(intercepted); 802 assertFalse(outLaunched.value); 803 804 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS; 805 eventTime += interval; 806 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 807 IGNORED_REPEAT); 808 outLaunched.value = true; 809 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 810 outLaunched); 811 assertFalse(intercepted); 812 assertFalse(outLaunched.value); 813 814 verify(mMetricsLogger, never()) 815 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 816 verify(mUiEventLogger, never()).log(any()); 817 818 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 819 verify(mMetricsLogger, times(2)).histogram( 820 eq("power_double_tap_interval"), intervalCaptor.capture()); 821 List<Integer> intervals = intervalCaptor.getAllValues(); 822 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 823 assertEquals((int) interval, intervals.get(1).intValue()); 824 825 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 826 verify(mMetricsLogger, times(2)).histogram( 827 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 828 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 829 assertEquals(1, tapCounts.get(0).intValue()); 830 assertEquals(1, tapCounts.get(1).intValue()); 831 } 832 833 @Test testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffNotInteractive()834 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffNotInteractive() { 835 withCameraDoubleTapPowerEnableConfigValue(false); 836 withCameraDoubleTapPowerDisableSettingValue(1); 837 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 838 839 long eventTime = INITIAL_EVENT_TIME_MILLIS; 840 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 841 IGNORED_REPEAT); 842 boolean interactive = false; 843 MutableBoolean outLaunched = new MutableBoolean(true); 844 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 845 outLaunched); 846 assertFalse(intercepted); 847 assertFalse(outLaunched.value); 848 849 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 850 eventTime += interval; 851 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 852 IGNORED_REPEAT); 853 outLaunched.value = true; 854 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 855 outLaunched); 856 assertFalse(intercepted); 857 assertFalse(outLaunched.value); 858 859 verify(mMetricsLogger, never()) 860 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 861 verify(mUiEventLogger, never()).log(any()); 862 863 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 864 verify(mMetricsLogger, times(2)).histogram( 865 eq("power_double_tap_interval"), intervalCaptor.capture()); 866 List<Integer> intervals = intervalCaptor.getAllValues(); 867 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 868 assertEquals((int) interval, intervals.get(1).intValue()); 869 870 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 871 verify(mMetricsLogger, times(2)).histogram( 872 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 873 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 874 assertEquals(1, tapCounts.get(0).intValue()); 875 assertEquals(2, tapCounts.get(1).intValue()); 876 } 877 878 @Test testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffNotInteractive()879 public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOffNotInteractive() { 880 withCameraDoubleTapPowerEnableConfigValue(false); 881 withCameraDoubleTapPowerDisableSettingValue(1); 882 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 883 884 long eventTime = INITIAL_EVENT_TIME_MILLIS; 885 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 886 IGNORED_REPEAT); 887 boolean interactive = false; 888 MutableBoolean outLaunched = new MutableBoolean(true); 889 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 890 outLaunched); 891 assertFalse(intercepted); 892 assertFalse(outLaunched.value); 893 894 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; 895 eventTime += interval; 896 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 897 IGNORED_REPEAT); 898 outLaunched.value = true; 899 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 900 outLaunched); 901 assertFalse(intercepted); 902 assertFalse(outLaunched.value); 903 verify(mMetricsLogger, never()) 904 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 905 verify(mUiEventLogger, never()).log(any()); 906 907 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 908 verify(mMetricsLogger, times(2)).histogram( 909 eq("power_double_tap_interval"), intervalCaptor.capture()); 910 List<Integer> intervals = intervalCaptor.getAllValues(); 911 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 912 assertEquals((int) interval, intervals.get(1).intValue()); 913 914 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 915 verify(mMetricsLogger, times(2)).histogram( 916 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 917 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 918 assertEquals(1, tapCounts.get(0).intValue()); 919 // The interval is too long to launch the camera, but short enough to count as a 920 // sequential tap. 921 assertEquals(2, tapCounts.get(1).intValue()); 922 } 923 924 @Test testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffNotInteractive()925 public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffNotInteractive() { 926 withCameraDoubleTapPowerEnableConfigValue(false); 927 withCameraDoubleTapPowerDisableSettingValue(1); 928 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 929 930 long eventTime = INITIAL_EVENT_TIME_MILLIS; 931 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 932 IGNORED_REPEAT); 933 boolean interactive = false; 934 MutableBoolean outLaunched = new MutableBoolean(true); 935 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 936 outLaunched); 937 assertFalse(intercepted); 938 assertFalse(outLaunched.value); 939 940 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS; 941 eventTime += interval; 942 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 943 IGNORED_REPEAT); 944 outLaunched.value = true; 945 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 946 outLaunched); 947 assertFalse(intercepted); 948 assertFalse(outLaunched.value); 949 verify(mMetricsLogger, never()) 950 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 951 verify(mUiEventLogger, never()).log(any()); 952 953 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 954 verify(mMetricsLogger, times(2)).histogram( 955 eq("power_double_tap_interval"), intervalCaptor.capture()); 956 List<Integer> intervals = intervalCaptor.getAllValues(); 957 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 958 assertEquals((int) interval, intervals.get(1).intValue()); 959 960 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 961 verify(mMetricsLogger, times(2)).histogram( 962 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 963 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 964 assertEquals(1, tapCounts.get(0).intValue()); 965 assertEquals(1, tapCounts.get(1).intValue()); 966 } 967 968 @Test 969 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupComplete()970 testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupComplete() { 971 withCameraDoubleTapPowerEnableConfigValue(true); 972 withCameraDoubleTapPowerDisableSettingValue(0); 973 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 974 withUserSetupCompleteValue(true); 975 976 long eventTime = INITIAL_EVENT_TIME_MILLIS; 977 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 978 IGNORED_REPEAT); 979 boolean interactive = false; 980 MutableBoolean outLaunched = new MutableBoolean(true); 981 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 982 outLaunched); 983 assertFalse(intercepted); 984 assertFalse(outLaunched.value); 985 986 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 987 eventTime += interval; 988 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 989 IGNORED_REPEAT); 990 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 991 outLaunched); 992 assertFalse(intercepted); 993 assertTrue(outLaunched.value); 994 995 verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected( 996 StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); 997 verify(mMetricsLogger) 998 .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval); 999 verify(mUiEventLogger, times(1)) 1000 .log(GestureLauncherService.GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER); 1001 1002 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1003 verify(mMetricsLogger, times(2)).histogram( 1004 eq("power_double_tap_interval"), intervalCaptor.capture()); 1005 List<Integer> intervals = intervalCaptor.getAllValues(); 1006 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1007 assertEquals((int) interval, intervals.get(1).intValue()); 1008 1009 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1010 verify(mMetricsLogger, times(2)).histogram( 1011 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1012 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1013 assertEquals(1, tapCounts.get(0).intValue()); 1014 assertEquals(2, tapCounts.get(1).intValue()); 1015 } 1016 1017 @Test 1018 public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupIncomplete()1019 testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupIncomplete() { 1020 withCameraDoubleTapPowerEnableConfigValue(true); 1021 withCameraDoubleTapPowerDisableSettingValue(0); 1022 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 1023 withUserSetupCompleteValue(false); 1024 1025 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1026 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1027 IGNORED_REPEAT); 1028 boolean interactive = false; 1029 MutableBoolean outLaunched = new MutableBoolean(true); 1030 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1031 outLaunched); 1032 assertFalse(intercepted); 1033 assertFalse(outLaunched.value); 1034 1035 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; 1036 eventTime += interval; 1037 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1038 IGNORED_REPEAT); 1039 outLaunched.value = true; 1040 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1041 outLaunched); 1042 assertFalse(intercepted); 1043 assertFalse(outLaunched.value); 1044 1045 verify(mMetricsLogger, never()) 1046 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 1047 verify(mUiEventLogger, never()).log(any()); 1048 1049 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1050 verify(mMetricsLogger, times(2)).histogram( 1051 eq("power_double_tap_interval"), intervalCaptor.capture()); 1052 List<Integer> intervals = intervalCaptor.getAllValues(); 1053 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1054 assertEquals((int) interval, intervals.get(1).intValue()); 1055 1056 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1057 verify(mMetricsLogger, times(2)).histogram( 1058 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1059 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1060 assertEquals(1, tapCounts.get(0).intValue()); 1061 assertEquals(2, tapCounts.get(1).intValue()); 1062 } 1063 1064 @Test testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnNotInteractive()1065 public void testInterceptPowerKeyDown_intervalMidBoundsCameraPowerGestureOnNotInteractive() { 1066 withCameraDoubleTapPowerEnableConfigValue(true); 1067 withCameraDoubleTapPowerDisableSettingValue(0); 1068 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 1069 1070 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1071 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1072 IGNORED_REPEAT); 1073 boolean interactive = false; 1074 MutableBoolean outLaunched = new MutableBoolean(true); 1075 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1076 outLaunched); 1077 assertFalse(intercepted); 1078 assertFalse(outLaunched.value); 1079 1080 final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; 1081 eventTime += interval; 1082 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1083 IGNORED_REPEAT); 1084 outLaunched.value = true; 1085 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1086 outLaunched); 1087 assertFalse(intercepted); 1088 assertFalse(outLaunched.value); 1089 1090 verify(mMetricsLogger, never()) 1091 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 1092 verify(mUiEventLogger, never()).log(any()); 1093 1094 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1095 verify(mMetricsLogger, times(2)).histogram( 1096 eq("power_double_tap_interval"), intervalCaptor.capture()); 1097 List<Integer> intervals = intervalCaptor.getAllValues(); 1098 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1099 assertEquals((int) interval, intervals.get(1).intValue()); 1100 1101 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1102 verify(mMetricsLogger, times(2)).histogram( 1103 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1104 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1105 assertEquals(1, tapCounts.get(0).intValue()); 1106 // The interval is too long to launch the camera, but short enough to count as a 1107 // sequential tap. 1108 assertEquals(2, tapCounts.get(1).intValue()); 1109 } 1110 1111 @Test testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnNotInteractive()1112 public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnNotInteractive() { 1113 withCameraDoubleTapPowerEnableConfigValue(true); 1114 withCameraDoubleTapPowerDisableSettingValue(0); 1115 mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); 1116 1117 long eventTime = INITIAL_EVENT_TIME_MILLIS; 1118 KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1119 IGNORED_REPEAT); 1120 boolean interactive = false; 1121 MutableBoolean outLaunched = new MutableBoolean(true); 1122 boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1123 outLaunched); 1124 assertFalse(intercepted); 1125 assertFalse(outLaunched.value); 1126 1127 long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS; 1128 eventTime += interval; 1129 keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, 1130 IGNORED_REPEAT); 1131 outLaunched.value = true; 1132 intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, 1133 outLaunched); 1134 assertFalse(intercepted); 1135 assertFalse(outLaunched.value); 1136 1137 verify(mMetricsLogger, never()) 1138 .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); 1139 verify(mUiEventLogger, never()).log(any()); 1140 1141 final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); 1142 verify(mMetricsLogger, times(2)).histogram( 1143 eq("power_double_tap_interval"), intervalCaptor.capture()); 1144 List<Integer> intervals = intervalCaptor.getAllValues(); 1145 assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); 1146 assertEquals((int) interval, intervals.get(1).intValue()); 1147 1148 final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); 1149 verify(mMetricsLogger, times(2)).histogram( 1150 eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); 1151 List<Integer> tapCounts = tapCountCaptor.getAllValues(); 1152 assertEquals(1, tapCounts.get(0).intValue()); 1153 assertEquals(1, tapCounts.get(1).intValue()); 1154 } 1155 withCameraDoubleTapPowerEnableConfigValue(boolean enableConfigValue)1156 private void withCameraDoubleTapPowerEnableConfigValue(boolean enableConfigValue) { 1157 when(mResources.getBoolean( 1158 com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled)) 1159 .thenReturn(enableConfigValue); 1160 } 1161 withEmergencyGestureEnabledConfigValue(boolean enableConfigValue)1162 private void withEmergencyGestureEnabledConfigValue(boolean enableConfigValue) { 1163 when(mResources.getBoolean( 1164 com.android.internal.R.bool.config_emergencyGestureEnabled)) 1165 .thenReturn(enableConfigValue); 1166 } 1167 withCameraDoubleTapPowerDisableSettingValue(int disableSettingValue)1168 private void withCameraDoubleTapPowerDisableSettingValue(int disableSettingValue) { 1169 Settings.Secure.putIntForUser( 1170 mContentResolver, 1171 Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 1172 disableSettingValue, 1173 UserHandle.USER_CURRENT); 1174 } 1175 withEmergencyGestureEnabledSettingValue(boolean enable)1176 private void withEmergencyGestureEnabledSettingValue(boolean enable) { 1177 Settings.Secure.putIntForUser( 1178 mContentResolver, 1179 Settings.Secure.EMERGENCY_GESTURE_ENABLED, 1180 enable ? 1 : 0, 1181 UserHandle.USER_CURRENT); 1182 } 1183 withUserSetupCompleteValue(boolean userSetupComplete)1184 private void withUserSetupCompleteValue(boolean userSetupComplete) { 1185 int userSetupCompleteValue = userSetupComplete ? 1 : 0; 1186 Settings.Secure.putIntForUser( 1187 mContentResolver, 1188 Settings.Secure.USER_SETUP_COMPLETE, 1189 userSetupCompleteValue, 1190 UserHandle.USER_CURRENT); 1191 } 1192 } 1193