diff options
12 files changed, 350 insertions, 111 deletions
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index e6dedce8feaf..72467b367cd5 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -10285,22 +10285,25 @@ </declare-styleable> <!-- @hide --> + <attr name="modifierState"> + <flag name="META" value="0x10000" /> + <flag name="CTRL" value="0x1000" /> + <flag name="ALT" value="0x02" /> + <flag name="SHIFT" value="0x1" /> + <flag name="SYM" value="0x4" /> + <flag name="FUNCTION" value="0x8" /> + <flag name="CAPS_LOCK" value="0x100000" /> + <flag name="NUM_LOCK" value="0x200000" /> + <flag name="SCROLL_LOCK" value="0x400000" /> + </attr> + + <!-- @hide --> <declare-styleable name="HardwareDefinedShortcut"> <attr name="keycode" /> <!-- The values are taken from public constants for modifier state defined in {@see KeyEvent.java}. Here we allow multiple modifier flags as value, since this represents the modifier state --> - <attr name="modifierState"> - <flag name="META" value="0x10000" /> - <flag name="CTRL" value="0x1000" /> - <flag name="ALT" value="0x02" /> - <flag name="SHIFT" value="0x1" /> - <flag name="SYM" value="0x4" /> - <flag name="FUNCTION" value="0x8" /> - <flag name="CAPS_LOCK" value="0x100000" /> - <flag name="NUM_LOCK" value="0x200000" /> - <flag name="SCROLL_LOCK" value="0x400000" /> - </attr> + <attr name="modifierState" /> <attr name="outKeycode" /> </declare-styleable> @@ -10309,6 +10312,11 @@ <attr name="keycode" /> </declare-styleable> + <declare-styleable name="Bookmark"> + <attr name="keycode" /> + <attr name="modifierState" /> + </declare-styleable> + <declare-styleable name="MediaRouteButton"> <!-- This drawable is a state list where the "activated" state indicates active media routing. Non-activated indicates diff --git a/core/res/res/xml/bookmarks.xml b/core/res/res/xml/bookmarks.xml index 22d02262c388..e735784ee5bb 100644 --- a/core/res/res/xml/bookmarks.xml +++ b/core/res/res/xml/bookmarks.xml @@ -31,29 +31,37 @@ 'u': Calculator 'y': YouTube --> -<bookmarks> +<bookmarks xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <bookmark role="android.app.role.BROWSER" - shortcut="b" /> + androidprv:keycode="KEYCODE_B" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_CONTACTS" - shortcut="c" /> + androidprv:keycode="KEYCODE_C" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_EMAIL" - shortcut="e" /> + androidprv:keycode="KEYCODE_E" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_CALENDAR" - shortcut="k" /> + androidprv:keycode="KEYCODE_K" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_MAPS" - shortcut="m" /> + androidprv:keycode="KEYCODE_M" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_MUSIC" - shortcut="p" /> + androidprv:keycode="KEYCODE_P" + androidprv:modifierState="META" /> <bookmark role="android.app.role.SMS" - shortcut="s" /> + androidprv:keycode="KEYCODE_S" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_CALCULATOR" - shortcut="u" /> + androidprv:keycode="KEYCODE_U" + androidprv:modifierState="META" /> </bookmarks> diff --git a/packages/SettingsProvider/res/xml/bookmarks.xml b/packages/SettingsProvider/res/xml/bookmarks.xml index 22d02262c388..645b275e2af5 100644 --- a/packages/SettingsProvider/res/xml/bookmarks.xml +++ b/packages/SettingsProvider/res/xml/bookmarks.xml @@ -32,6 +32,9 @@ 'y': YouTube --> <bookmarks> + <!-- TODO(b/358569822): Remove this from Settings DB + This is legacy implementation to store bookmarks in Settings DB, which is deprecated and + no longer used --> <bookmark role="android.app.role.BROWSER" shortcut="b" /> diff --git a/services/core/java/com/android/server/input/AppLaunchShortcutManager.java b/services/core/java/com/android/server/input/AppLaunchShortcutManager.java index aef207f9c027..f3820e5935d4 100644 --- a/services/core/java/com/android/server/input/AppLaunchShortcutManager.java +++ b/services/core/java/com/android/server/input/AppLaunchShortcutManager.java @@ -21,6 +21,7 @@ import android.annotation.SuppressLint; import android.app.role.RoleManager; import android.content.Context; import android.content.Intent; +import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.hardware.input.AppLaunchData; import android.hardware.input.InputGestureData; @@ -137,11 +138,19 @@ final class AppLaunchShortcutManager { String categoryName = parser.getAttributeValue(null, ATTRIBUTE_CATEGORY); String shiftName = parser.getAttributeValue(null, ATTRIBUTE_SHIFT); String roleName = parser.getAttributeValue(null, ATTRIBUTE_ROLE); - - // TODO(b/358569822): Shift bookmarks to use keycode instead of shortcutChar - int keycode = KeyEvent.KEYCODE_UNKNOWN; String shortcut = parser.getAttributeValue(null, ATTRIBUTE_SHORTCUT); - if (!TextUtils.isEmpty(shortcut)) { + int keycode; + int modifierState; + TypedArray a = mContext.getResources().obtainAttributes(parser, + R.styleable.Bookmark); + try { + keycode = a.getInt(R.styleable.Bookmark_keycode, KeyEvent.KEYCODE_UNKNOWN); + modifierState = a.getInt(R.styleable.Bookmark_modifierState, 0); + } finally { + a.recycle(); + } + if (keycode == KeyEvent.KEYCODE_UNKNOWN && !TextUtils.isEmpty(shortcut)) { + // Fetch keycode using shortcut char KeyEvent[] events = virtualKcm.getEvents(new char[]{shortcut.toLowerCase( Locale.ROOT).charAt(0)}); // Single key press can generate the character @@ -153,12 +162,17 @@ final class AppLaunchShortcutManager { Log.w(TAG, "Keycode required for bookmark with category=" + categoryName + " packageName=" + packageName + " className=" + className + " role=" + roleName + " shiftName=" + shiftName - + " shortcut=" + shortcut); + + " shortcut=" + shortcut + " modifierState=" + modifierState); continue; } - final boolean isShiftShortcut = (shiftName != null && shiftName.toLowerCase( - Locale.ROOT).equals("true")); + if (modifierState == 0) { + // Fetch modifierState using shiftName + boolean isShiftShortcut = shiftName != null && shiftName.toLowerCase( + Locale.ROOT).equals("true"); + modifierState = + KeyEvent.META_META_ON | (isShiftShortcut ? KeyEvent.META_SHIFT_ON : 0); + } AppLaunchData launchData = null; if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(className)) { launchData = AppLaunchData.createLaunchDataForComponent(packageName, className); @@ -168,11 +182,9 @@ final class AppLaunchShortcutManager { launchData = AppLaunchData.createLaunchDataForRole(roleName); } if (launchData != null) { - Log.d(TAG, "adding shortcut " + launchData + "shift=" - + isShiftShortcut + " keycode=" + keycode); + Log.d(TAG, "adding shortcut " + launchData + " modifierState=" + + modifierState + " keycode=" + keycode); // All bookmarks are based on Action key - int modifierState = - KeyEvent.META_META_ON | (isShiftShortcut ? KeyEvent.META_SHIFT_ON : 0); InputGestureData bookmark = new InputGestureData.Builder() .setTrigger(InputGestureData.createKeyTrigger(keycode, modifierState)) .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION) diff --git a/services/core/java/com/android/server/policy/ModifierShortcutManager.java b/services/core/java/com/android/server/policy/ModifierShortcutManager.java index 4f67318faddb..c9f66eb5ccb2 100644 --- a/services/core/java/com/android/server/policy/ModifierShortcutManager.java +++ b/services/core/java/com/android/server/policy/ModifierShortcutManager.java @@ -29,6 +29,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.drawable.Icon; import android.hardware.input.AppLaunchData; @@ -65,6 +66,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -84,6 +86,7 @@ public class ModifierShortcutManager { private static final String ATTRIBUTE_PACKAGE = "package"; private static final String ATTRIBUTE_CLASS = "class"; private static final String ATTRIBUTE_SHORTCUT = "shortcut"; + private static final String ATTRIBUTE_KEYCODE = "keycode"; private static final String ATTRIBUTE_CATEGORY = "category"; private static final String ATTRIBUTE_SHIFT = "shift"; private static final String ATTRIBUTE_ROLE = "role"; @@ -167,6 +170,9 @@ public class ModifierShortcutManager { }, UserHandle.ALL); mCurrentUser = currentUser; mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); + } + + void onSystemReady() { loadShortcuts(); } @@ -335,6 +341,7 @@ public class ModifierShortcutManager { try { XmlResourceParser parser = mContext.getResources().getXml(R.xml.bookmarks); XmlUtils.beginDocument(parser, TAG_BOOKMARKS); + KeyCharacterMap virtualKcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); while (true) { XmlUtils.nextElement(parser); @@ -353,15 +360,36 @@ public class ModifierShortcutManager { String categoryName = parser.getAttributeValue(null, ATTRIBUTE_CATEGORY); String shiftName = parser.getAttributeValue(null, ATTRIBUTE_SHIFT); String roleName = parser.getAttributeValue(null, ATTRIBUTE_ROLE); + final int keycode; + final int modifierState; + TypedArray a = mContext.getResources().obtainAttributes(parser, + R.styleable.Bookmark); + try { + keycode = a.getInt(R.styleable.Bookmark_keycode, KeyEvent.KEYCODE_UNKNOWN); + modifierState = a.getInt(R.styleable.Bookmark_modifierState, 0); + } finally { + a.recycle(); + } + if (TextUtils.isEmpty(shortcutName) && keycode != KeyEvent.KEYCODE_UNKNOWN) { + // Try to find shortcutChar using keycode + shortcutName = String.valueOf(virtualKcm.getDisplayLabel(keycode)).toLowerCase( + Locale.ROOT); + } if (TextUtils.isEmpty(shortcutName)) { Log.w(TAG, "Shortcut required for bookmark with category=" + categoryName + " packageName=" + packageName + " className=" + className - + " role=" + roleName + "shiftName=" + shiftName); + + " role=" + roleName + " shiftName=" + shiftName + " keycode= " + + keycode + " modifierState= " + modifierState); continue; } - final boolean isShiftShortcut = (shiftName != null && shiftName.equals("true")); + final boolean isShiftShortcut; + if (!TextUtils.isEmpty(shiftName)) { + isShiftShortcut = shiftName.equals("true"); + } else { + isShiftShortcut = (modifierState & KeyEvent.META_SHIFT_ON) != 0; + } if (modifierShortcutManagerRefactor()) { final char shortcutChar = shortcutName.charAt(0); @@ -376,7 +404,7 @@ public class ModifierShortcutManager { bookmark = new RoleBookmark(shortcutChar, isShiftShortcut, roleName); } if (bookmark != null) { - Log.d(TAG, "adding shortcut " + bookmark + "shift=" + Log.d(TAG, "adding shortcut " + bookmark + " shift=" + isShiftShortcut + " char=" + shortcutChar); mBookmarks.put(new Pair<>(shortcutChar, isShiftShortcut), bookmark); } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index dda5bcf24d07..85e7cfe33c0e 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -6610,6 +6610,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // In normal flow, systemReady is called before other system services are ready. // So it is better not to bind keyguard here. mKeyguardDelegate.onSystemReady(); + mModifierShortcutManager.onSystemReady(); mVrManagerInternal = LocalServices.getService(VrManagerInternal.class); if (mVrManagerInternal != null) { diff --git a/services/tests/wmtests/res/xml/bookmarks.xml b/services/tests/wmtests/res/xml/bookmarks.xml index 197b36623fff..787f4e85c012 100644 --- a/services/tests/wmtests/res/xml/bookmarks.xml +++ b/services/tests/wmtests/res/xml/bookmarks.xml @@ -13,60 +13,70 @@ See the License for the specific language governing permissions and limitations under the License. --> -<bookmarks> +<bookmarks xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <!-- the key combinations for the following shortcuts must be in sync with the key combinations sent by the test in ModifierShortcutTests.java --> <bookmark role="android.app.role.BROWSER" - shortcut="b" /> + androidprv:keycode="KEYCODE_B" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_CONTACTS" - shortcut="c" /> + androidprv:keycode="KEYCODE_C" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_EMAIL" - shortcut="e" /> + androidprv:keycode="KEYCODE_E" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_CALENDAR" - shortcut="k" /> + androidprv:keycode="KEYCODE_K" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_MAPS" - shortcut="m" /> + androidprv:keycode="KEYCODE_M" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_MUSIC" - shortcut="p" /> + androidprv:keycode="KEYCODE_P" + androidprv:modifierState="META" /> <bookmark role="android.app.role.SMS" - shortcut="s" /> + androidprv:keycode="KEYCODE_S" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_CALCULATOR" - shortcut="u" /> + androidprv:keycode="KEYCODE_U" + androidprv:modifierState="META" /> <bookmark role="android.app.role.BROWSER" - shortcut="b" - shift="true" /> + androidprv:keycode="KEYCODE_B" + androidprv:modifierState="META|SHIFT" /> <bookmark category="android.intent.category.APP_CONTACTS" - shortcut="c" - shift="true" /> + androidprv:keycode="KEYCODE_C" + androidprv:modifierState="META|SHIFT" /> <bookmark package="com.test" class="com.test.BookmarkTest" - shortcut="j" - shift="true" /> + androidprv:keycode="KEYCODE_J" + androidprv:modifierState="META|SHIFT" /> <!-- The following shortcuts will not be invoked by tests but are here to provide test coverage of parsing the different types of shortcut. --> <bookmark package="com.test" class="com.test.BookmarkTest" - shortcut="j" /> + androidprv:keycode="KEYCODE_J" + androidprv:modifierState="META" /> <bookmark package="com.test2" class="com.test.BookmarkTest" - shortcut="d" /> + androidprv:keycode="KEYCODE_D" + androidprv:modifierState="META" /> <!-- It's intended that this package/class will NOT resolve so we test the resolution @@ -74,6 +84,7 @@ <bookmark package="com.test3" class="com.test.BookmarkTest" - shortcut="f" /> + androidprv:keycode="KEYCODE_F" + androidprv:modifierState="META" /> </bookmarks> diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java index 0575d98b65ec..82a5add407f4 100644 --- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java +++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java @@ -116,6 +116,7 @@ public class ModifierShortcutManagerTests { mModifierShortcutManager = new ModifierShortcutManager( mContext, mHandler, UserHandle.SYSTEM); + mModifierShortcutManager.onSystemReady(); } @Test 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 a51ce9951ab4..bc03c233b459 100644 --- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java @@ -88,6 +88,7 @@ import android.service.dreams.DreamManagerInternal; import android.telecom.TelecomManager; import android.view.Display; import android.view.InputEvent; +import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.accessibility.AccessibilityManager; import android.view.autofill.AutofillManagerInternal; @@ -270,11 +271,15 @@ class TestPhoneWindowManager { // Return mocked services: LocalServices.getService mMockitoSession = mockitoSession() .mockStatic(LocalServices.class, spyStubOnly) + .mockStatic(KeyCharacterMap.class) .strictness(Strictness.LENIENT) .startMocking(); mPhoneWindowManager = spy(new PhoneWindowManager()); + KeyCharacterMap virtualKcm = mContext.getSystemService(InputManager.class) + .getInputDevice(KeyCharacterMap.VIRTUAL_KEYBOARD).getKeyCharacterMap(); + doReturn(virtualKcm).when(() -> KeyCharacterMap.load(anyInt())); doReturn(mWindowManagerInternal).when( () -> LocalServices.getService(eq(WindowManagerInternal.class))); doReturn(mActivityManagerInternal).when( diff --git a/tests/Input/res/xml/bookmarks.xml b/tests/Input/res/xml/bookmarks.xml index ba3f1871cdec..a4c898d8159a 100644 --- a/tests/Input/res/xml/bookmarks.xml +++ b/tests/Input/res/xml/bookmarks.xml @@ -14,47 +14,55 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> -<bookmarks> +<bookmarks xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <!-- the key combinations for the following shortcuts must be in sync with the key combinations sent by the test in KeyGestureControllerTests.java --> <bookmark role="android.app.role.BROWSER" - shortcut="b" /> + androidprv:keycode="KEYCODE_B" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_CONTACTS" - shortcut="c" /> + androidprv:keycode="KEYCODE_C" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_EMAIL" - shortcut="e" /> + androidprv:keycode="KEYCODE_E" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_CALENDAR" - shortcut="k" /> + androidprv:keycode="KEYCODE_K" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_MAPS" - shortcut="m" /> + androidprv:keycode="KEYCODE_M" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_MUSIC" - shortcut="p" /> + androidprv:keycode="KEYCODE_P" + androidprv:modifierState="META" /> <bookmark role="android.app.role.SMS" - shortcut="s" /> + androidprv:keycode="KEYCODE_S" + androidprv:modifierState="META" /> <bookmark category="android.intent.category.APP_CALCULATOR" - shortcut="u" /> + androidprv:keycode="KEYCODE_U" + androidprv:modifierState="META" /> <bookmark role="android.app.role.BROWSER" - shortcut="b" - shift="true" /> + androidprv:keycode="KEYCODE_B" + androidprv:modifierState="META|SHIFT" /> <bookmark category="android.intent.category.APP_CONTACTS" - shortcut="c" + androidprv:keycode="KEYCODE_C" shift="true" /> <bookmark package="com.test" class="com.test.BookmarkTest" - shortcut="j" + androidprv:keycode="KEYCODE_J" shift="true" /> </bookmarks>
\ No newline at end of file diff --git a/tests/Input/res/xml/bookmarks_legacy.xml b/tests/Input/res/xml/bookmarks_legacy.xml new file mode 100644 index 000000000000..8bacf490ad9e --- /dev/null +++ b/tests/Input/res/xml/bookmarks_legacy.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright 2024 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. + --> +<bookmarks> + <!-- The key combinations for the following shortcuts are legacy way defining bookmarks and we + should prefer new way of defining bookmarks as shown in {@link bookmarks.xml} --> + <bookmark + role="android.app.role.BROWSER" + shortcut="b" /> + <bookmark + category="android.intent.category.APP_CONTACTS" + shortcut="c" /> + <bookmark + category="android.intent.category.APP_EMAIL" + shortcut="e" /> + <bookmark + category="android.intent.category.APP_CALENDAR" + shortcut="k" /> + <bookmark + category="android.intent.category.APP_MAPS" + shortcut="m" /> + <bookmark + category="android.intent.category.APP_MUSIC" + shortcut="p" /> + <bookmark + role="android.app.role.SMS" + shortcut="s" /> + <bookmark + category="android.intent.category.APP_CALCULATOR" + shortcut="u" /> + + <bookmark + role="android.app.role.BROWSER" + shortcut="b" + shift="true" /> + + <bookmark + category="android.intent.category.APP_CONTACTS" + shortcut="c" + shift="true" /> + + <bookmark + package="com.test" + class="com.test.BookmarkTest" + shortcut="j" + shift="true" /> +</bookmarks>
\ No newline at end of file diff --git a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt index 09a686ca2c3f..d1f866843be6 100644 --- a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt +++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt @@ -115,13 +115,11 @@ class KeyGestureControllerTests { private lateinit var iInputManager: IInputManager @Mock - private lateinit var resources: Resources - - @Mock private lateinit var packageManager: PackageManager private var currentPid = 0 private lateinit var context: Context + private lateinit var resources: Resources private lateinit var keyGestureController: KeyGestureController private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession private lateinit var testLooper: TestLooper @@ -130,6 +128,7 @@ class KeyGestureControllerTests { @Before fun setup() { context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext())) + resources = Mockito.spy(context.resources) setupInputDevices() setupBehaviors() testLooper = TestLooper() @@ -146,10 +145,6 @@ class KeyGestureControllerTests { private fun setupBehaviors() { Mockito.`when`(SystemProperties.get("ro.debuggable")).thenReturn("1") Mockito.`when`(resources.getBoolean(R.bool.config_enableScreenshotChord)).thenReturn(true) - val testBookmarks: XmlResourceParser = context.resources.getXml( - com.android.test.input.R.xml.bookmarks - ) - Mockito.`when`(resources.getXml(R.xml.bookmarks)).thenReturn(testBookmarks) Mockito.`when`(context.resources).thenReturn(resources) Mockito.`when`(packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) .thenReturn(true) @@ -158,6 +153,11 @@ class KeyGestureControllerTests { Mockito.`when`(context.packageManager).thenReturn(packageManager) } + private fun setupBookmarks(bookmarkRes: Int) { + val testBookmarks: XmlResourceParser = context.resources.getXml(bookmarkRes) + Mockito.`when`(resources.getXml(R.xml.bookmarks)).thenReturn(testBookmarks) + } + private fun setupInputDevices() { val correctIm = context.getSystemService(InputManager::class.java)!! val virtualDevice = correctIm.getInputDevice(KeyCharacterMap.VIRTUAL_KEYBOARD)!! @@ -604,45 +604,6 @@ class KeyGestureControllerTests { AppLaunchData.createLaunchDataForCategory(Intent.CATEGORY_APP_CALCULATOR) ), TestData( - "META + SHIFT + B -> Launch Default Browser", - intArrayOf( - KeyEvent.KEYCODE_META_LEFT, - KeyEvent.KEYCODE_SHIFT_LEFT, - KeyEvent.KEYCODE_B - ), - KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, - intArrayOf(KeyEvent.KEYCODE_B), - KeyEvent.META_META_ON or KeyEvent.META_SHIFT_ON, - intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), - AppLaunchData.createLaunchDataForRole(RoleManager.ROLE_BROWSER) - ), - TestData( - "META + SHIFT + C -> Launch Default Contacts", - intArrayOf( - KeyEvent.KEYCODE_META_LEFT, - KeyEvent.KEYCODE_SHIFT_LEFT, - KeyEvent.KEYCODE_C - ), - KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, - intArrayOf(KeyEvent.KEYCODE_C), - KeyEvent.META_META_ON or KeyEvent.META_SHIFT_ON, - intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), - AppLaunchData.createLaunchDataForCategory(Intent.CATEGORY_APP_CONTACTS) - ), - TestData( - "META + SHIFT + J -> Launch Target Activity", - intArrayOf( - KeyEvent.KEYCODE_META_LEFT, - KeyEvent.KEYCODE_SHIFT_LEFT, - KeyEvent.KEYCODE_J - ), - KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, - intArrayOf(KeyEvent.KEYCODE_J), - KeyEvent.META_META_ON or KeyEvent.META_SHIFT_ON, - intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), - AppLaunchData.createLaunchDataForComponent("com.test", "com.test.BookmarkTest") - ), - TestData( "META + CTRL + DEL -> Trigger Bug Report", intArrayOf( KeyEvent.KEYCODE_META_LEFT, @@ -866,6 +827,139 @@ class KeyGestureControllerTests { } @Keep + private fun bookmarkArguments(): Array<TestData> { + return arrayOf( + TestData( + "META + B -> Launch Default Browser", + intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_B), + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, + intArrayOf(KeyEvent.KEYCODE_B), + KeyEvent.META_META_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), + AppLaunchData.createLaunchDataForRole(RoleManager.ROLE_BROWSER) + ), + TestData( + "META + C -> Launch Default Contacts", + intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_C), + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, + intArrayOf(KeyEvent.KEYCODE_C), + KeyEvent.META_META_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), + AppLaunchData.createLaunchDataForCategory(Intent.CATEGORY_APP_CONTACTS) + ), + TestData( + "META + E -> Launch Default Email", + intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_E), + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, + intArrayOf(KeyEvent.KEYCODE_E), + KeyEvent.META_META_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), + AppLaunchData.createLaunchDataForCategory(Intent.CATEGORY_APP_EMAIL) + ), + TestData( + "META + K -> Launch Default Calendar", + intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_K), + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, + intArrayOf(KeyEvent.KEYCODE_K), + KeyEvent.META_META_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), + AppLaunchData.createLaunchDataForCategory(Intent.CATEGORY_APP_CALENDAR) + ), + TestData( + "META + M -> Launch Default Maps", + intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_M), + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, + intArrayOf(KeyEvent.KEYCODE_M), + KeyEvent.META_META_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), + AppLaunchData.createLaunchDataForCategory(Intent.CATEGORY_APP_MAPS) + ), + TestData( + "META + P -> Launch Default Music", + intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_P), + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, + intArrayOf(KeyEvent.KEYCODE_P), + KeyEvent.META_META_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), + AppLaunchData.createLaunchDataForCategory(Intent.CATEGORY_APP_MUSIC) + ), + TestData( + "META + S -> Launch Default SMS", + intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_S), + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, + intArrayOf(KeyEvent.KEYCODE_S), + KeyEvent.META_META_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), + AppLaunchData.createLaunchDataForRole(RoleManager.ROLE_SMS) + ), + TestData( + "META + U -> Launch Default Calculator", + intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_U), + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, + intArrayOf(KeyEvent.KEYCODE_U), + KeyEvent.META_META_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), + AppLaunchData.createLaunchDataForCategory(Intent.CATEGORY_APP_CALCULATOR) + ), + TestData( + "META + SHIFT + B -> Launch Default Browser", + intArrayOf( + KeyEvent.KEYCODE_META_LEFT, + KeyEvent.KEYCODE_SHIFT_LEFT, + KeyEvent.KEYCODE_B + ), + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, + intArrayOf(KeyEvent.KEYCODE_B), + KeyEvent.META_META_ON or KeyEvent.META_SHIFT_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), + AppLaunchData.createLaunchDataForRole(RoleManager.ROLE_BROWSER) + ), + TestData( + "META + SHIFT + C -> Launch Default Contacts", + intArrayOf( + KeyEvent.KEYCODE_META_LEFT, + KeyEvent.KEYCODE_SHIFT_LEFT, + KeyEvent.KEYCODE_C + ), + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, + intArrayOf(KeyEvent.KEYCODE_C), + KeyEvent.META_META_ON or KeyEvent.META_SHIFT_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), + AppLaunchData.createLaunchDataForCategory(Intent.CATEGORY_APP_CONTACTS) + ), + TestData( + "META + SHIFT + J -> Launch Target Activity", + intArrayOf( + KeyEvent.KEYCODE_META_LEFT, + KeyEvent.KEYCODE_SHIFT_LEFT, + KeyEvent.KEYCODE_J + ), + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, + intArrayOf(KeyEvent.KEYCODE_J), + KeyEvent.META_META_ON or KeyEvent.META_SHIFT_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE), + AppLaunchData.createLaunchDataForComponent("com.test", "com.test.BookmarkTest") + ) + ) + } + + @Test + @Parameters(method = "bookmarkArguments") + fun testBookmarks(test: TestData) { + setupBookmarks(com.android.test.input.R.xml.bookmarks) + setupKeyGestureController() + testKeyGestureInternal(test) + } + + @Test + @Parameters(method = "bookmarkArguments") + fun testBookmarksLegacy(test: TestData) { + setupBookmarks(com.android.test.input.R.xml.bookmarks_legacy) + setupKeyGestureController() + testKeyGestureInternal(test) + } + + @Keep private fun systemKeysTestArguments(): Array<TestData> { return arrayOf( TestData( |