Loading services/core/java/com/android/server/policy/PhoneWindowManager.java +15 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ import static com.android.server.wm.WindowManagerPolicyProto.ROTATION; import static com.android.server.wm.WindowManagerPolicyProto.ROTATION_MODE; import static com.android.server.wm.WindowManagerPolicyProto.SCREEN_ON_FULLY; import static com.android.server.wm.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW_COMPLETE; import static com.android.systemui.shared.Flags.enableLppSqueezeEffect; import android.accessibilityservice.AccessibilityService; import android.annotation.Nullable; Loading Loading @@ -1502,6 +1503,20 @@ public class PhoneWindowManager implements WindowManagerPolicy { Slog.d(TAG, "powerLongPress: eventTime=" + eventTime + " mLongPressOnPowerBehavior=" + mLongPressOnPowerBehavior); // Sending a synthetic KeyEvent to StatusBar service with flag FLAG_LONG_PRESS set, when // power button is long pressed if (enableLppSqueezeEffect()) { // Long press is detected in a callback, so there's no explicit hardware KeyEvent // available here. Instead, we create a synthetic power key event that has properties // similar to the original one. final KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KEYCODE_POWER); event.setFlags(KeyEvent.FLAG_LONG_PRESS); // setting both downTime and eventTime as same as downTime is sent as eventTime for long // press event in SingleKeyGestureDetector's handler event.setTime(eventTime, eventTime); sendSystemKeyToStatusBarAsync(event); } switch (behavior) { case LONG_PRESS_POWER_NOTHING: break; Loading services/tests/wmtests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ android_test { "androidx.test.rules", "androidx.test.runner", "com.android.window.flags.window-aconfig-java", "cts-input-lib", "flag-junit", "flickerlib", "frameworks-base-testutils", Loading services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java +86 −0 Original line number Diff line number Diff line Loading @@ -15,22 +15,46 @@ */ package com.android.server.policy; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.KeyEvent.ACTION_DOWN; import static android.view.KeyEvent.ACTION_UP; import static android.view.KeyEvent.FLAG_LONG_PRESS; import static android.view.KeyEvent.KEYCODE_POWER; import static android.view.KeyEvent.KEYCODE_VOLUME_UP; import static com.android.cts.input.inputeventmatchers.InputEventMatchersKt.withKeyAction; import static com.android.cts.input.inputeventmatchers.InputEventMatchersKt.withKeyCode; import static com.android.cts.input.inputeventmatchers.InputEventMatchersKt.withKeyFlags; import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_ASSISTANT; import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_GLOBAL_ACTIONS; import static com.android.server.policy.PhoneWindowManager.POWER_MULTI_PRESS_TIMEOUT_MILLIS; import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_POWER_DREAM_OR_SLEEP; import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_POWER_GO_TO_SLEEP; import static org.hamcrest.Matchers.allOf; import android.os.RemoteException; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.provider.Settings; import android.view.Display; import android.view.InputDevice; import android.view.InputEvent; import android.view.KeyCharacterMap; import android.view.KeyEvent; import androidx.annotation.NonNull; import com.android.cts.input.BlockingQueueEventVerifier; import com.android.systemui.shared.Flags; import org.junit.Before; import org.junit.Test; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; /** * Test class for power key gesture. * Loading Loading @@ -149,4 +173,66 @@ public class PowerKeyGestureTests extends ShortcutKeyTestBase { sendKey(KEYCODE_POWER); mPhoneWindowManager.assertNoPowerSleep(); } @EnableFlags(Flags.FLAG_ENABLE_LPP_SQUEEZE_EFFECT) @Test public void testPowerLongPress_flagEnabled_shouldSendSyntheticKeyEvent() throws RemoteException { final BlockingQueue<InputEvent> eventQueue = new LinkedBlockingQueue<>(); final BlockingQueueEventVerifier verifier = new BlockingQueueEventVerifier(eventQueue); mPhoneWindowManager.overrideLongPressPowerForSyntheticEvent(LONG_PRESS_POWER_ASSISTANT, eventQueue); sendKeyForTriggeringSyntheticEvent(); verifier.assertReceivedKey(allOf(withKeyCode(KEYCODE_POWER), withKeyAction(ACTION_DOWN))); verifier.assertReceivedKey(allOf(withKeyCode(KEYCODE_POWER), withKeyAction(ACTION_DOWN), withKeyFlags(FLAG_LONG_PRESS))); verifier.assertReceivedKey(allOf(withKeyCode(KEYCODE_POWER), withKeyAction(ACTION_UP))); } @DisableFlags(Flags.FLAG_ENABLE_LPP_SQUEEZE_EFFECT) @Test public void testPowerLongPress_flagDisabled_shouldNotSendSyntheticKeyEvent() throws RemoteException { final BlockingQueue<InputEvent> eventQueue = new LinkedBlockingQueue<>(); final BlockingQueueEventVerifier verifier = new BlockingQueueEventVerifier(eventQueue); mPhoneWindowManager.overrideLongPressPowerForSyntheticEvent(LONG_PRESS_POWER_ASSISTANT, eventQueue); sendKeyForTriggeringSyntheticEvent(); verifier.assertReceivedKey(allOf(withKeyCode(KEYCODE_POWER), withKeyAction(ACTION_DOWN))); verifier.assertReceivedKey(allOf(withKeyCode(KEYCODE_POWER), withKeyAction(ACTION_UP))); } private void sendKeyForTriggeringSyntheticEvent() { // send power button key down event (without setting long press flag) and move time forward // by long press duration timeout, it should send a synthetic power button down event with // long press flag set final long time = mPhoneWindowManager.getCurrentTime(); final KeyEvent downEvent = getPowerButtonKeyEvent(ACTION_DOWN, time); mPhoneWindowManager.interceptKeyBeforeQueueing(downEvent); mPhoneWindowManager.dispatchAllPendingEvents(); mPhoneWindowManager.moveTimeForward(SingleKeyGestureDetector.sDefaultLongPressTimeout); // send power button key up event to emulate power button has been released final KeyEvent upEvent = getPowerButtonKeyEvent(ACTION_UP, time); mPhoneWindowManager.interceptKeyBeforeQueueing(upEvent); mPhoneWindowManager.dispatchAllPendingEvents(); } @NonNull private KeyEvent getPowerButtonKeyEvent(final int action, final long time) { final KeyEvent downEvent = new KeyEvent( /* downTime */ time, /* eventTime */ time, /* action */ action, /* keyCode */ KEYCODE_POWER, /* repeat */ 0, /* metaState */ 0, /* deviceId */ KeyCharacterMap.VIRTUAL_KEYBOARD, /* scanCode */ 0, /* flags */ 0, /* source */ InputDevice.SOURCE_KEYBOARD ); downEvent.setDisplayId(DEFAULT_DISPLAY); return downEvent; } } services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +12 −2 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_SHUT import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM; import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAVIOR_MUTE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyList; Loading Loading @@ -130,9 +129,9 @@ import org.mockito.MockSettings; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.quality.Strictness; import org.mockito.stubbing.Answer; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.function.Supplier; class TestPhoneWindowManager { Loading Loading @@ -544,6 +543,17 @@ class TestPhoneWindowManager { } } void overrideLongPressPowerForSyntheticEvent(final int behavior, final BlockingQueue<InputEvent> eventQueue) throws RemoteException { mPhoneWindowManager.getStatusBarService(); spyOn(mPhoneWindowManager.mStatusBarService); Mockito.doAnswer(invocation -> { eventQueue.add(new KeyEvent(invocation.getArgument(0))); return null; }).when(mPhoneWindowManager.mStatusBarService).handleSystemKey(any()); overrideLongPressOnPower(behavior); } void overrideLongPressOnHomeBehavior(int behavior) { mPhoneWindowManager.mLongPressOnHomeBehavior = behavior; } Loading Loading
services/core/java/com/android/server/policy/PhoneWindowManager.java +15 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ import static com.android.server.wm.WindowManagerPolicyProto.ROTATION; import static com.android.server.wm.WindowManagerPolicyProto.ROTATION_MODE; import static com.android.server.wm.WindowManagerPolicyProto.SCREEN_ON_FULLY; import static com.android.server.wm.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW_COMPLETE; import static com.android.systemui.shared.Flags.enableLppSqueezeEffect; import android.accessibilityservice.AccessibilityService; import android.annotation.Nullable; Loading Loading @@ -1502,6 +1503,20 @@ public class PhoneWindowManager implements WindowManagerPolicy { Slog.d(TAG, "powerLongPress: eventTime=" + eventTime + " mLongPressOnPowerBehavior=" + mLongPressOnPowerBehavior); // Sending a synthetic KeyEvent to StatusBar service with flag FLAG_LONG_PRESS set, when // power button is long pressed if (enableLppSqueezeEffect()) { // Long press is detected in a callback, so there's no explicit hardware KeyEvent // available here. Instead, we create a synthetic power key event that has properties // similar to the original one. final KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KEYCODE_POWER); event.setFlags(KeyEvent.FLAG_LONG_PRESS); // setting both downTime and eventTime as same as downTime is sent as eventTime for long // press event in SingleKeyGestureDetector's handler event.setTime(eventTime, eventTime); sendSystemKeyToStatusBarAsync(event); } switch (behavior) { case LONG_PRESS_POWER_NOTHING: break; Loading
services/tests/wmtests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ android_test { "androidx.test.rules", "androidx.test.runner", "com.android.window.flags.window-aconfig-java", "cts-input-lib", "flag-junit", "flickerlib", "frameworks-base-testutils", Loading
services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java +86 −0 Original line number Diff line number Diff line Loading @@ -15,22 +15,46 @@ */ package com.android.server.policy; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.KeyEvent.ACTION_DOWN; import static android.view.KeyEvent.ACTION_UP; import static android.view.KeyEvent.FLAG_LONG_PRESS; import static android.view.KeyEvent.KEYCODE_POWER; import static android.view.KeyEvent.KEYCODE_VOLUME_UP; import static com.android.cts.input.inputeventmatchers.InputEventMatchersKt.withKeyAction; import static com.android.cts.input.inputeventmatchers.InputEventMatchersKt.withKeyCode; import static com.android.cts.input.inputeventmatchers.InputEventMatchersKt.withKeyFlags; import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_ASSISTANT; import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_GLOBAL_ACTIONS; import static com.android.server.policy.PhoneWindowManager.POWER_MULTI_PRESS_TIMEOUT_MILLIS; import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_POWER_DREAM_OR_SLEEP; import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_POWER_GO_TO_SLEEP; import static org.hamcrest.Matchers.allOf; import android.os.RemoteException; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.provider.Settings; import android.view.Display; import android.view.InputDevice; import android.view.InputEvent; import android.view.KeyCharacterMap; import android.view.KeyEvent; import androidx.annotation.NonNull; import com.android.cts.input.BlockingQueueEventVerifier; import com.android.systemui.shared.Flags; import org.junit.Before; import org.junit.Test; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; /** * Test class for power key gesture. * Loading Loading @@ -149,4 +173,66 @@ public class PowerKeyGestureTests extends ShortcutKeyTestBase { sendKey(KEYCODE_POWER); mPhoneWindowManager.assertNoPowerSleep(); } @EnableFlags(Flags.FLAG_ENABLE_LPP_SQUEEZE_EFFECT) @Test public void testPowerLongPress_flagEnabled_shouldSendSyntheticKeyEvent() throws RemoteException { final BlockingQueue<InputEvent> eventQueue = new LinkedBlockingQueue<>(); final BlockingQueueEventVerifier verifier = new BlockingQueueEventVerifier(eventQueue); mPhoneWindowManager.overrideLongPressPowerForSyntheticEvent(LONG_PRESS_POWER_ASSISTANT, eventQueue); sendKeyForTriggeringSyntheticEvent(); verifier.assertReceivedKey(allOf(withKeyCode(KEYCODE_POWER), withKeyAction(ACTION_DOWN))); verifier.assertReceivedKey(allOf(withKeyCode(KEYCODE_POWER), withKeyAction(ACTION_DOWN), withKeyFlags(FLAG_LONG_PRESS))); verifier.assertReceivedKey(allOf(withKeyCode(KEYCODE_POWER), withKeyAction(ACTION_UP))); } @DisableFlags(Flags.FLAG_ENABLE_LPP_SQUEEZE_EFFECT) @Test public void testPowerLongPress_flagDisabled_shouldNotSendSyntheticKeyEvent() throws RemoteException { final BlockingQueue<InputEvent> eventQueue = new LinkedBlockingQueue<>(); final BlockingQueueEventVerifier verifier = new BlockingQueueEventVerifier(eventQueue); mPhoneWindowManager.overrideLongPressPowerForSyntheticEvent(LONG_PRESS_POWER_ASSISTANT, eventQueue); sendKeyForTriggeringSyntheticEvent(); verifier.assertReceivedKey(allOf(withKeyCode(KEYCODE_POWER), withKeyAction(ACTION_DOWN))); verifier.assertReceivedKey(allOf(withKeyCode(KEYCODE_POWER), withKeyAction(ACTION_UP))); } private void sendKeyForTriggeringSyntheticEvent() { // send power button key down event (without setting long press flag) and move time forward // by long press duration timeout, it should send a synthetic power button down event with // long press flag set final long time = mPhoneWindowManager.getCurrentTime(); final KeyEvent downEvent = getPowerButtonKeyEvent(ACTION_DOWN, time); mPhoneWindowManager.interceptKeyBeforeQueueing(downEvent); mPhoneWindowManager.dispatchAllPendingEvents(); mPhoneWindowManager.moveTimeForward(SingleKeyGestureDetector.sDefaultLongPressTimeout); // send power button key up event to emulate power button has been released final KeyEvent upEvent = getPowerButtonKeyEvent(ACTION_UP, time); mPhoneWindowManager.interceptKeyBeforeQueueing(upEvent); mPhoneWindowManager.dispatchAllPendingEvents(); } @NonNull private KeyEvent getPowerButtonKeyEvent(final int action, final long time) { final KeyEvent downEvent = new KeyEvent( /* downTime */ time, /* eventTime */ time, /* action */ action, /* keyCode */ KEYCODE_POWER, /* repeat */ 0, /* metaState */ 0, /* deviceId */ KeyCharacterMap.VIRTUAL_KEYBOARD, /* scanCode */ 0, /* flags */ 0, /* source */ InputDevice.SOURCE_KEYBOARD ); downEvent.setDisplayId(DEFAULT_DISPLAY); return downEvent; } }
services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +12 −2 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_SHUT import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM; import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAVIOR_MUTE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyList; Loading Loading @@ -130,9 +129,9 @@ import org.mockito.MockSettings; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.quality.Strictness; import org.mockito.stubbing.Answer; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.function.Supplier; class TestPhoneWindowManager { Loading Loading @@ -544,6 +543,17 @@ class TestPhoneWindowManager { } } void overrideLongPressPowerForSyntheticEvent(final int behavior, final BlockingQueue<InputEvent> eventQueue) throws RemoteException { mPhoneWindowManager.getStatusBarService(); spyOn(mPhoneWindowManager.mStatusBarService); Mockito.doAnswer(invocation -> { eventQueue.add(new KeyEvent(invocation.getArgument(0))); return null; }).when(mPhoneWindowManager.mStatusBarService).handleSystemKey(any()); overrideLongPressOnPower(behavior); } void overrideLongPressOnHomeBehavior(int behavior) { mPhoneWindowManager.mLongPressOnHomeBehavior = behavior; } Loading