Loading services/core/java/com/android/server/GestureLauncherService.java +6 −3 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.util.MutableBoolean; import android.util.Slog; import android.view.KeyEvent; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.server.statusbar.StatusBarManagerInternal; Loading @@ -58,7 +59,7 @@ public class GestureLauncherService extends SystemService { * Time in milliseconds in which the power button must be pressed twice so it will be considered * as a camera launch. */ private static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300; @VisibleForTesting static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300; /** The listener that receives the gesture event. */ private final GestureEventListener mGestureListener = new GestureEventListener(); Loading Loading @@ -155,7 +156,8 @@ public class GestureLauncherService extends SystemService { } } private void updateCameraDoubleTapPowerEnabled() { @VisibleForTesting void updateCameraDoubleTapPowerEnabled() { boolean enabled = isCameraDoubleTapPowerSettingEnabled(mContext, mUserId); synchronized (this) { mCameraDoubleTapPowerEnabled = enabled; Loading Loading @@ -284,7 +286,8 @@ public class GestureLauncherService extends SystemService { /** * @return true if camera was launched, false otherwise. */ private boolean handleCameraLaunchGesture(boolean useWakelock, int source) { @VisibleForTesting boolean handleCameraLaunchGesture(boolean useWakelock, int source) { boolean userSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; if (!userSetupComplete) { Loading services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java 0 → 100644 +470 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.StatusBarManager; import android.content.Context; import android.content.res.Resources; import android.os.Looper; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.provider.Settings; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.test.mock.MockContentResolver; import android.view.KeyEvent; import android.util.MutableBoolean; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.LocalServices; import com.android.server.statusbar.StatusBarManagerInternal; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mock; import org.mockito.MockitoAnnotations; /** * Unit tests for {@link GestureLauncherService}. * runtest frameworks-services -c com.android.server.GestureLauncherServiceTest */ @Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class GestureLauncherServiceTest { private static final int FAKE_USER_ID = 1337; private static final int FAKE_SOURCE = 1982; private static final long INITIAL_EVENT_TIME_MILLIS = 20000L; private static final long IGNORED_DOWN_TIME = 1234L; private static final int IGNORED_ACTION = 13; private static final int IGNORED_CODE = 1999; private static final int IGNORED_REPEAT = 42; private @Mock Context mContext; private @Mock Resources mResources; private @Mock StatusBarManagerInternal mStatusBarManagerInternal; private MockContentResolver mContentResolver; private GestureLauncherService mGestureLauncherService; @BeforeClass public static void oneTimeInitialization() { if (Looper.myLooper() == null) { Looper.prepare(); } } @Before public void setup() { MockitoAnnotations.initMocks(this); LocalServices.removeServiceForTest(StatusBarManagerInternal.class); LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal); final Context originalContext = InstrumentationRegistry.getContext(); when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo()); when(mContext.getResources()).thenReturn(mResources); mContentResolver = new MockContentResolver(mContext); mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); when(mContext.getContentResolver()).thenReturn(mContentResolver); mGestureLauncherService = new GestureLauncherService(mContext); } @Test public void testIsCameraDoubleTapPowerEnabled_configFalse() { withCameraDoubleTapPowerEnableConfigValue(false); assertFalse(mGestureLauncherService.isCameraDoubleTapPowerEnabled(mResources)); } @Test public void testIsCameraDoubleTapPowerEnabled_configTrue() { withCameraDoubleTapPowerEnableConfigValue(true); assertTrue(mGestureLauncherService.isCameraDoubleTapPowerEnabled(mResources)); } @Test public void testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingDisabled() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(1); assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( mContext, FAKE_USER_ID)); } @Test public void testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingEnabled() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(0); assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( mContext, FAKE_USER_ID)); } @Test public void testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingDisabled() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(1); assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( mContext, FAKE_USER_ID)); } @Test public void testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingEnabled() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); assertTrue(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( mContext, FAKE_USER_ID)); } @Test public void testHandleCameraLaunchGesture_userSetupComplete() { withUserSetupCompleteValue(true); boolean useWakeLock = false; assertTrue(mGestureLauncherService.handleCameraLaunchGesture(useWakeLock, FAKE_SOURCE)); verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected(FAKE_SOURCE); } @Test public void testHandleCameraLaunchGesture_userSetupNotComplete() { withUserSetupCompleteValue(false); boolean useWakeLock = false; assertFalse(mGestureLauncherService.handleCameraLaunchGesture(useWakeLock, FAKE_SOURCE)); } @Test public void testInterceptPowerKeyDown_firstPowerDownCameraPowerGestureOnInteractive() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS + GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffInteractive() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(1); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffInteractive() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(1); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupComplete() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); withUserSetupCompleteValue(true); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = false; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertTrue(intercepted); assertTrue(outLaunched.value); verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected( StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupIncomplete() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); withUserSetupCompleteValue(false); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnInteractive() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffNotInteractive() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(1); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = false; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffNotInteractive() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(1); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = false; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupComplete() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); withUserSetupCompleteValue(true); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = false; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertTrue(outLaunched.value); verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected( StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupIncomplete() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); withUserSetupCompleteValue(false); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = false; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnNotInteractive() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = false; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } private void withCameraDoubleTapPowerEnableConfigValue(boolean enableConfigValue) { when(mResources.getBoolean( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled)) .thenReturn(enableConfigValue); } private void withCameraDoubleTapPowerDisableSettingValue(int disableSettingValue) { Settings.Secure.putIntForUser( mContentResolver, Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, disableSettingValue, UserHandle.USER_CURRENT); } private void withUserSetupCompleteValue(boolean userSetupComplete) { int userSetupCompleteValue = userSetupComplete ? 1 : 0; Settings.Secure.putIntForUser( mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, userSetupCompleteValue, UserHandle.USER_CURRENT); } } Loading
services/core/java/com/android/server/GestureLauncherService.java +6 −3 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.util.MutableBoolean; import android.util.Slog; import android.view.KeyEvent; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.server.statusbar.StatusBarManagerInternal; Loading @@ -58,7 +59,7 @@ public class GestureLauncherService extends SystemService { * Time in milliseconds in which the power button must be pressed twice so it will be considered * as a camera launch. */ private static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300; @VisibleForTesting static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300; /** The listener that receives the gesture event. */ private final GestureEventListener mGestureListener = new GestureEventListener(); Loading Loading @@ -155,7 +156,8 @@ public class GestureLauncherService extends SystemService { } } private void updateCameraDoubleTapPowerEnabled() { @VisibleForTesting void updateCameraDoubleTapPowerEnabled() { boolean enabled = isCameraDoubleTapPowerSettingEnabled(mContext, mUserId); synchronized (this) { mCameraDoubleTapPowerEnabled = enabled; Loading Loading @@ -284,7 +286,8 @@ public class GestureLauncherService extends SystemService { /** * @return true if camera was launched, false otherwise. */ private boolean handleCameraLaunchGesture(boolean useWakelock, int source) { @VisibleForTesting boolean handleCameraLaunchGesture(boolean useWakelock, int source) { boolean userSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; if (!userSetupComplete) { Loading
services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java 0 → 100644 +470 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.StatusBarManager; import android.content.Context; import android.content.res.Resources; import android.os.Looper; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.provider.Settings; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.test.mock.MockContentResolver; import android.view.KeyEvent; import android.util.MutableBoolean; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.LocalServices; import com.android.server.statusbar.StatusBarManagerInternal; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mock; import org.mockito.MockitoAnnotations; /** * Unit tests for {@link GestureLauncherService}. * runtest frameworks-services -c com.android.server.GestureLauncherServiceTest */ @Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class GestureLauncherServiceTest { private static final int FAKE_USER_ID = 1337; private static final int FAKE_SOURCE = 1982; private static final long INITIAL_EVENT_TIME_MILLIS = 20000L; private static final long IGNORED_DOWN_TIME = 1234L; private static final int IGNORED_ACTION = 13; private static final int IGNORED_CODE = 1999; private static final int IGNORED_REPEAT = 42; private @Mock Context mContext; private @Mock Resources mResources; private @Mock StatusBarManagerInternal mStatusBarManagerInternal; private MockContentResolver mContentResolver; private GestureLauncherService mGestureLauncherService; @BeforeClass public static void oneTimeInitialization() { if (Looper.myLooper() == null) { Looper.prepare(); } } @Before public void setup() { MockitoAnnotations.initMocks(this); LocalServices.removeServiceForTest(StatusBarManagerInternal.class); LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal); final Context originalContext = InstrumentationRegistry.getContext(); when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo()); when(mContext.getResources()).thenReturn(mResources); mContentResolver = new MockContentResolver(mContext); mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); when(mContext.getContentResolver()).thenReturn(mContentResolver); mGestureLauncherService = new GestureLauncherService(mContext); } @Test public void testIsCameraDoubleTapPowerEnabled_configFalse() { withCameraDoubleTapPowerEnableConfigValue(false); assertFalse(mGestureLauncherService.isCameraDoubleTapPowerEnabled(mResources)); } @Test public void testIsCameraDoubleTapPowerEnabled_configTrue() { withCameraDoubleTapPowerEnableConfigValue(true); assertTrue(mGestureLauncherService.isCameraDoubleTapPowerEnabled(mResources)); } @Test public void testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingDisabled() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(1); assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( mContext, FAKE_USER_ID)); } @Test public void testIsCameraDoubleTapPowerSettingEnabled_configFalseSettingEnabled() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(0); assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( mContext, FAKE_USER_ID)); } @Test public void testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingDisabled() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(1); assertFalse(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( mContext, FAKE_USER_ID)); } @Test public void testIsCameraDoubleTapPowerSettingEnabled_configTrueSettingEnabled() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); assertTrue(mGestureLauncherService.isCameraDoubleTapPowerSettingEnabled( mContext, FAKE_USER_ID)); } @Test public void testHandleCameraLaunchGesture_userSetupComplete() { withUserSetupCompleteValue(true); boolean useWakeLock = false; assertTrue(mGestureLauncherService.handleCameraLaunchGesture(useWakeLock, FAKE_SOURCE)); verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected(FAKE_SOURCE); } @Test public void testHandleCameraLaunchGesture_userSetupNotComplete() { withUserSetupCompleteValue(false); boolean useWakeLock = false; assertFalse(mGestureLauncherService.handleCameraLaunchGesture(useWakeLock, FAKE_SOURCE)); } @Test public void testInterceptPowerKeyDown_firstPowerDownCameraPowerGestureOnInteractive() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS + GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffInteractive() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(1); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffInteractive() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(1); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupComplete() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); withUserSetupCompleteValue(true); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = false; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertTrue(intercepted); assertTrue(outLaunched.value); verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected( StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnInteractiveSetupIncomplete() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); withUserSetupCompleteValue(false); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnInteractive() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffNotInteractive() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(1); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = false; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOffNotInteractive() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(1); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = false; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupComplete() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); withUserSetupCompleteValue(true); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = false; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertTrue(outLaunched.value); verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected( StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); } @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOnNotInteractiveSetupIncomplete() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); withUserSetupCompleteValue(false); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = false; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } @Test public void testInterceptPowerKeyDown_intervalOutOfBoundsCameraPowerGestureOnNotInteractive() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = false; MutableBoolean outLaunched = new MutableBoolean(true); boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); eventTime += GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); outLaunched.value = true; intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); assertFalse(intercepted); assertFalse(outLaunched.value); } private void withCameraDoubleTapPowerEnableConfigValue(boolean enableConfigValue) { when(mResources.getBoolean( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled)) .thenReturn(enableConfigValue); } private void withCameraDoubleTapPowerDisableSettingValue(int disableSettingValue) { Settings.Secure.putIntForUser( mContentResolver, Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, disableSettingValue, UserHandle.USER_CURRENT); } private void withUserSetupCompleteValue(boolean userSetupComplete) { int userSetupCompleteValue = userSetupComplete ? 1 : 0; Settings.Secure.putIntForUser( mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, userSetupCompleteValue, UserHandle.USER_CURRENT); } }