diff options
8 files changed, 81 insertions, 5 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 89c772826822..e5bc2a3579bc 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -50640,6 +50640,7 @@ package android.view { field public static final int KEYCODE_DVR = 173; // 0xad field public static final int KEYCODE_E = 33; // 0x21 field public static final int KEYCODE_EISU = 212; // 0xd4 + field @FlaggedApi("com.android.hardware.input.emoji_and_screenshot_keycodes_available") public static final int KEYCODE_EMOJI_PICKER = 317; // 0x13d field public static final int KEYCODE_ENDCALL = 6; // 0x6 field public static final int KEYCODE_ENTER = 66; // 0x42 field public static final int KEYCODE_ENVELOPE = 65; // 0x41 @@ -50772,6 +50773,7 @@ package android.view { field public static final int KEYCODE_RIGHT_BRACKET = 72; // 0x48 field public static final int KEYCODE_RO = 217; // 0xd9 field public static final int KEYCODE_S = 47; // 0x2f + field @FlaggedApi("com.android.hardware.input.emoji_and_screenshot_keycodes_available") public static final int KEYCODE_SCREENSHOT = 318; // 0x13e field public static final int KEYCODE_SCROLL_LOCK = 116; // 0x74 field public static final int KEYCODE_SEARCH = 84; // 0x54 field public static final int KEYCODE_SEMICOLON = 74; // 0x4a diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 42cf08ff9a66..cea6547f8f83 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -3606,7 +3606,7 @@ package android.view { method public final int getDisplayId(); method public final void setDisplayId(int); field public static final int FLAG_IS_ACCESSIBILITY_EVENT = 2048; // 0x800 - field public static final int LAST_KEYCODE = 316; // 0x13c + field public static final int LAST_KEYCODE = 318; // 0x13e } public final class KeyboardShortcutGroup implements android.os.Parcelable { diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig index 0ed6569afd2a..2041f6a5a845 100644 --- a/core/java/android/hardware/input/input_framework.aconfig +++ b/core/java/android/hardware/input/input_framework.aconfig @@ -33,6 +33,13 @@ flag { flag { namespace: "input_native" + name: "emoji_and_screenshot_keycodes_available" + description: "Add new KeyEvent keycodes for opening Emoji Picker and Taking Screenshots" + bug: "315307777" +} + +flag { + namespace: "input_native" name: "keyboard_a11y_slow_keys_flag" description: "Controls if the slow keys accessibility feature for physical keyboard is available to the user" bug: "294546335" diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index c6601e8d3085..1ee9509b116a 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -19,6 +19,7 @@ package android.view; import static android.os.IInputConstants.INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT; import static android.view.Display.INVALID_DISPLAY; +import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; @@ -31,6 +32,8 @@ import android.util.Log; import android.util.SparseIntArray; import android.view.KeyCharacterMap.KeyData; +import com.android.hardware.input.Flags; + import java.util.concurrent.TimeUnit; /** @@ -384,7 +387,13 @@ public class KeyEvent extends InputEvent implements Parcelable { public static final int KEYCODE_META_RIGHT = 118; /** Key code constant: Function modifier key. */ public static final int KEYCODE_FUNCTION = 119; - /** Key code constant: System Request / Print Screen key. */ + /** + * Key code constant: System Request / Print Screen key. + * + * This key is sent to the app first and only if the app doesn't handle it, the framework + * handles it (to take a screenshot), unlike {@code KEYCODE_TAKE_SCREENSHOT} which is + * fully handled by the framework. + */ public static final int KEYCODE_SYSRQ = 120; /** Key code constant: Break / Pause key. */ public static final int KEYCODE_BREAK = 121; @@ -921,14 +930,25 @@ public class KeyEvent extends InputEvent implements Parcelable { * User customizable key #4. */ public static final int KEYCODE_MACRO_4 = 316; - + /** Key code constant: To open emoji picker */ + @FlaggedApi(Flags.FLAG_EMOJI_AND_SCREENSHOT_KEYCODES_AVAILABLE) + public static final int KEYCODE_EMOJI_PICKER = 317; + /** + * Key code constant: To take a screenshot + * + * This key is fully handled by the framework and will not be sent to the foreground app, + * unlike {@code KEYCODE_SYSRQ} which is sent to the app first and only if the app + * doesn't handle it, the framework handles it (to take a screenshot). + */ + @FlaggedApi(Flags.FLAG_EMOJI_AND_SCREENSHOT_KEYCODES_AVAILABLE) + public static final int KEYCODE_SCREENSHOT = 318; /** * Integer value of the last KEYCODE. Increases as new keycodes are added to KeyEvent. * @hide */ @TestApi - public static final int LAST_KEYCODE = KEYCODE_MACRO_4; + public static final int LAST_KEYCODE = KEYCODE_SCREENSHOT; // NOTE: If you add a new keycode here you must also add it to: // isSystem() diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 1fdcc64a90c8..51790b875465 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -75,6 +75,7 @@ import static android.view.WindowManagerGlobal.ADD_OKAY; import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED; import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled; +import static com.android.hardware.input.Flags.emojiAndScreenshotKeycodesAvailable; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT; @@ -3779,6 +3780,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { sendSystemKeyToStatusBarAsync(event); return true; } + case KeyEvent.KEYCODE_SCREENSHOT: + if (emojiAndScreenshotKeycodesAvailable() && down && repeatCount == 0) { + interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/); + } + return true; } if (isValidGlobalKey(keyCode) && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) { @@ -5022,6 +5028,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_MACRO_4: result &= ~ACTION_PASS_TO_USER; break; + case KeyEvent.KEYCODE_EMOJI_PICKER: + if (!emojiAndScreenshotKeycodesAvailable()) { + // Don't allow EMOJI_PICKER key to be dispatched until flag is released. + result &= ~ACTION_PASS_TO_USER; + } + break; } if (useHapticFeedback) { diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java index 0382ca0d9fec..e21388e57a9e 100644 --- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java +++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java @@ -34,6 +34,7 @@ import static android.view.KeyEvent.KEYCODE_SHIFT_LEFT; import static android.view.KeyEvent.KEYCODE_SLASH; import static android.view.KeyEvent.KEYCODE_SPACE; import static android.view.KeyEvent.KEYCODE_TAB; +import static android.view.KeyEvent.KEYCODE_SCREENSHOT; import static android.view.KeyEvent.KEYCODE_U; import static android.view.KeyEvent.KEYCODE_Z; @@ -193,4 +194,26 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase { mPhoneWindowManager.verifyNewBrightness(newBrightness[i]); } } + + /** + * Sends a KEYCODE_SCREENSHOT and validates screenshot is taken if flag is enabled + */ + @Test + public void testTakeScreenshot_flagEnabled() { + mSetFlagsRule.enableFlags(com.android.hardware.input.Flags + .FLAG_EMOJI_AND_SCREENSHOT_KEYCODES_AVAILABLE); + sendKeyCombination(new int[]{KEYCODE_SCREENSHOT}, 0); + mPhoneWindowManager.assertTakeScreenshotCalled(); + } + + /** + * Sends a KEYCODE_SCREENSHOT and validates screenshot is not taken if flag is disabled + */ + @Test + public void testTakeScreenshot_flagDisabled() { + mSetFlagsRule.disableFlags(com.android.hardware.input.Flags + .FLAG_EMOJI_AND_SCREENSHOT_KEYCODES_AVAILABLE); + sendKeyCombination(new int[]{KEYCODE_SCREENSHOT}, 0); + mPhoneWindowManager.assertTakeScreenshotNotCalled(); + } } diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java index 157d1627d993..fee6582c1ba4 100644 --- a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java +++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java @@ -46,6 +46,7 @@ import static com.android.server.policy.WindowManagerPolicy.ACTION_PASS_TO_USER; import static java.util.Collections.unmodifiableMap; import android.content.Context; +import android.platform.test.flag.junit.SetFlagsRule; import android.util.ArrayMap; import android.view.InputDevice; import android.view.KeyCharacterMap; @@ -57,11 +58,17 @@ import com.android.internal.util.test.FakeSettingsProviderRule; import org.junit.After; import org.junit.Rule; +import org.junit.rules.RuleChain; import java.util.Map; class ShortcutKeyTestBase { - @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); + + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + public final FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); + + @Rule + public RuleChain rules = RuleChain.outerRule(mSettingsProviderRule).around(mSetFlagsRule); TestPhoneWindowManager mPhoneWindowManager; DispatchedKeyHandler mDispatchedKeyHandler = event -> false; diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java index c8abd8d7297e..2904c0325d40 100644 --- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java @@ -596,6 +596,11 @@ class TestPhoneWindowManager { verify(mDisplayPolicy).takeScreenshot(anyInt(), anyInt()); } + void assertTakeScreenshotNotCalled() { + mTestLooper.dispatchAll(); + verify(mDisplayPolicy, never()).takeScreenshot(anyInt(), anyInt()); + } + void assertShowGlobalActionsCalled() { mTestLooper.dispatchAll(); verify(mPhoneWindowManager).showGlobalActions(); |