• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.policy;
18 
19 import static android.view.KeyEvent.KEYCODE_ALT_LEFT;
20 import static android.view.KeyEvent.KEYCODE_B;
21 import static android.view.KeyEvent.KEYCODE_BRIGHTNESS_DOWN;
22 import static android.view.KeyEvent.KEYCODE_C;
23 import static android.view.KeyEvent.KEYCODE_CTRL_LEFT;
24 import static android.view.KeyEvent.KEYCODE_DEL;
25 import static android.view.KeyEvent.KEYCODE_E;
26 import static android.view.KeyEvent.KEYCODE_ENTER;
27 import static android.view.KeyEvent.KEYCODE_H;
28 import static android.view.KeyEvent.KEYCODE_J;
29 import static android.view.KeyEvent.KEYCODE_M;
30 import static android.view.KeyEvent.KEYCODE_META_LEFT;
31 import static android.view.KeyEvent.KEYCODE_N;
32 import static android.view.KeyEvent.KEYCODE_P;
33 import static android.view.KeyEvent.KEYCODE_S;
34 import static android.view.KeyEvent.KEYCODE_SHIFT_LEFT;
35 import static android.view.KeyEvent.KEYCODE_SLASH;
36 import static android.view.KeyEvent.KEYCODE_SPACE;
37 import static android.view.KeyEvent.KEYCODE_TAB;
38 import static android.view.KeyEvent.KEYCODE_SCREENSHOT;
39 import static android.view.KeyEvent.KEYCODE_U;
40 import static android.view.KeyEvent.KEYCODE_Z;
41 
42 import android.app.role.RoleManager;
43 import android.content.ComponentName;
44 import android.content.Intent;
45 import android.hardware.input.AppLaunchData;
46 import android.hardware.input.KeyGestureEvent;
47 import android.os.RemoteException;
48 import android.platform.test.annotations.DisableFlags;
49 import android.platform.test.annotations.EnableFlags;
50 import android.platform.test.annotations.Presubmit;
51 import android.util.SparseArray;
52 
53 import androidx.test.filters.SmallTest;
54 
55 import org.junit.Before;
56 import org.junit.Test;
57 
58 @Presubmit
59 @SmallTest
60 @EnableFlags(com.android.hardware.input.Flags.FLAG_MODIFIER_SHORTCUT_MANAGER_REFACTOR)
61 public class ModifierShortcutTests extends ShortcutKeyTestBase {
62 
63     private static final SparseArray<String> INTENT_SHORTCUTS =  new SparseArray<>();
64     private static final SparseArray<String> ROLE_SHORTCUTS =  new SparseArray<>();
65     static {
66         // These shortcuts should align with those defined in
67         // services/tests/wmtests/res/xml/bookmarks.xml
INTENT_SHORTCUTS.append(KEYCODE_U, Intent.CATEGORY_APP_CALCULATOR)68         INTENT_SHORTCUTS.append(KEYCODE_U, Intent.CATEGORY_APP_CALCULATOR);
INTENT_SHORTCUTS.append(KEYCODE_P, Intent.CATEGORY_APP_CONTACTS)69         INTENT_SHORTCUTS.append(KEYCODE_P, Intent.CATEGORY_APP_CONTACTS);
INTENT_SHORTCUTS.append(KEYCODE_E, Intent.CATEGORY_APP_EMAIL)70         INTENT_SHORTCUTS.append(KEYCODE_E, Intent.CATEGORY_APP_EMAIL);
INTENT_SHORTCUTS.append(KEYCODE_C, Intent.CATEGORY_APP_CALENDAR)71         INTENT_SHORTCUTS.append(KEYCODE_C, Intent.CATEGORY_APP_CALENDAR);
INTENT_SHORTCUTS.append(KEYCODE_M, Intent.CATEGORY_APP_MAPS)72         INTENT_SHORTCUTS.append(KEYCODE_M, Intent.CATEGORY_APP_MAPS);
73 
ROLE_SHORTCUTS.append(KEYCODE_B, RoleManager.ROLE_BROWSER)74         ROLE_SHORTCUTS.append(KEYCODE_B, RoleManager.ROLE_BROWSER);
75     }
76     private static final int ANY_DISPLAY_ID = 123;
77 
78     @Before
setUp()79     public void setUp() {
80         setUpPhoneWindowManager();
81     }
82 
83     /**
84      * Test meta+ shortcuts defined in bookmarks.xml.
85      */
86     @Test
87     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testMetaShortcuts_withoutKeyGestureEventHandling()88     public void testMetaShortcuts_withoutKeyGestureEventHandling() {
89         for (int i = 0; i < INTENT_SHORTCUTS.size(); i++) {
90             final int keyCode = INTENT_SHORTCUTS.keyAt(i);
91             final String category = INTENT_SHORTCUTS.valueAt(i);
92 
93             sendKeyCombination(new int[]{KEYCODE_META_LEFT, keyCode}, 0);
94             mPhoneWindowManager.assertLaunchCategory(category);
95         }
96 
97         mPhoneWindowManager.overrideRoleManager();
98         for (int i = 0; i < ROLE_SHORTCUTS.size(); i++) {
99             final int keyCode = ROLE_SHORTCUTS.keyAt(i);
100             final String role = ROLE_SHORTCUTS.valueAt(i);
101 
102             sendKeyCombination(new int[]{KEYCODE_META_LEFT, keyCode}, 0);
103             mPhoneWindowManager.assertLaunchRole(role);
104         }
105 
106         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_B}, 0);
107         mPhoneWindowManager.assertLaunchRole(RoleManager.ROLE_BROWSER);
108 
109         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_P}, 0);
110         mPhoneWindowManager.assertLaunchCategory(Intent.CATEGORY_APP_CONTACTS);
111 
112         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_J}, 0);
113         mPhoneWindowManager.assertActivityTargetLaunched(
114                 new ComponentName("com.test", "com.test.BookmarkTest"));
115 
116     }
117 
118     @Test
119     @EnableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testMetaShortcuts_withKeyGestureEventHandling()120     public void testMetaShortcuts_withKeyGestureEventHandling() {
121         for (int i = 0; i < INTENT_SHORTCUTS.size(); i++) {
122             final String category = INTENT_SHORTCUTS.valueAt(i);
123             mPhoneWindowManager.sendKeyGestureEvent(
124                     new KeyGestureEvent.Builder()
125                             .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION)
126                             .setAction(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
127                             .setAppLaunchData(AppLaunchData.createLaunchDataForCategory(category))
128                             .build()
129             );
130             mPhoneWindowManager.assertLaunchCategory(category);
131         }
132 
133         mPhoneWindowManager.overrideRoleManager();
134         for (int i = 0; i < ROLE_SHORTCUTS.size(); i++) {
135             final String role = ROLE_SHORTCUTS.valueAt(i);
136 
137             mPhoneWindowManager.sendKeyGestureEvent(
138                     new KeyGestureEvent.Builder()
139                             .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION)
140                             .setAction(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
141                             .setAppLaunchData(AppLaunchData.createLaunchDataForRole(role))
142                             .build()
143             );
144             mPhoneWindowManager.assertLaunchRole(role);
145         }
146 
147         mPhoneWindowManager.sendKeyGestureEvent(
148                 new KeyGestureEvent.Builder()
149                         .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION)
150                         .setAction(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
151                         .setAppLaunchData(
152                                 new AppLaunchData.ComponentData("com.test",
153                                         "com.test.BookmarkTest"))
154                         .build()
155         );
156         mPhoneWindowManager.assertActivityTargetLaunched(
157                 new ComponentName("com.test", "com.test.BookmarkTest"));
158 
159     }
160 
161     /**
162      * ALT + TAB to show recent apps.
163      */
164     @Test
165     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testAltTab()166     public void testAltTab() {
167         mPhoneWindowManager.overrideStatusBarManagerInternal();
168         sendKeyCombination(new int[]{KEYCODE_ALT_LEFT, KEYCODE_TAB}, 0);
169         mPhoneWindowManager.assertShowRecentApps();
170     }
171 
172     /**
173      * CTRL + SPACE to switch keyboard layout.
174      */
175     @Test
176     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testCtrlSpace()177     public void testCtrlSpace() {
178         sendKeyCombination(new int[]{KEYCODE_CTRL_LEFT, KEYCODE_SPACE}, /* duration= */ 0,
179                 ANY_DISPLAY_ID);
180         mPhoneWindowManager.assertSwitchKeyboardLayout(/* direction= */ 1, ANY_DISPLAY_ID);
181     }
182 
183     /**
184      * CTRL + SHIFT + SPACE to switch keyboard layout backwards.
185      */
186     @Test
187     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testCtrlShiftSpace()188     public void testCtrlShiftSpace() {
189         sendKeyCombination(new int[]{KEYCODE_CTRL_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_SPACE},
190                 /* duration= */ 0, ANY_DISPLAY_ID);
191         mPhoneWindowManager.assertSwitchKeyboardLayout(/* direction= */ -1, ANY_DISPLAY_ID);
192     }
193 
194     /**
195      * CTRL + ALT + Z to enable accessibility service.
196      */
197     @Test
198     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testCtrlAltZ()199     public void testCtrlAltZ() {
200         sendKeyCombination(new int[]{KEYCODE_CTRL_LEFT, KEYCODE_ALT_LEFT, KEYCODE_Z}, 0);
201         mPhoneWindowManager.assertAccessibilityKeychordCalled();
202     }
203 
204     /**
205      * META + CTRL+ S to take screenshot.
206      */
207     @Test
208     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testMetaCtrlS()209     public void testMetaCtrlS() {
210         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_CTRL_LEFT, KEYCODE_S}, 0);
211         mPhoneWindowManager.assertTakeScreenshotCalled();
212     }
213 
214     /**
215      * META + N to expand notification panel.
216      */
217     @Test
218     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testMetaN()219     public void testMetaN() throws RemoteException {
220         mPhoneWindowManager.overrideTogglePanel();
221         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_N}, 0);
222         mPhoneWindowManager.assertTogglePanel();
223     }
224 
225     /**
226      * META + SLASH to toggle shortcuts menu.
227      */
228     @Test
229     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testMetaSlash()230     public void testMetaSlash() {
231         mPhoneWindowManager.overrideStatusBarManagerInternal();
232         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SLASH}, 0);
233         mPhoneWindowManager.assertToggleShortcutsMenu();
234     }
235 
236     /**
237      * META  + ALT to toggle Cap Lock.
238      */
239     @Test
240     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testMetaAlt()241     public void testMetaAlt() {
242         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_ALT_LEFT}, 0);
243         mPhoneWindowManager.assertToggleCapsLock();
244     }
245 
246     /**
247      * META + H to go to homescreen
248      */
249     @Test
250     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testMetaH()251     public void testMetaH() {
252         mPhoneWindowManager.overrideLaunchHome();
253         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_H}, 0);
254         mPhoneWindowManager.assertGoToHomescreen();
255     }
256 
257     /**
258      * META + ENTER to go to homescreen
259      */
260     @Test
261     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testMetaEnter()262     public void testMetaEnter() {
263         mPhoneWindowManager.overrideLaunchHome();
264         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_ENTER}, 0);
265         mPhoneWindowManager.assertGoToHomescreen();
266     }
267 
268     /**
269      * Sends a KEYCODE_BRIGHTNESS_DOWN event and validates the brightness is decreased as expected;
270      */
271     @Test
272     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testKeyCodeBrightnessDown()273     public void testKeyCodeBrightnessDown() {
274         float[] currentBrightness = new float[]{0.1f, 0.05f, 0.0f};
275         float[] newBrightness = new float[]{0.065738f, 0.0275134f, 0.0f};
276 
277         for (int i = 0; i < currentBrightness.length; i++) {
278             mPhoneWindowManager.prepareBrightnessDecrease(currentBrightness[i]);
279             sendKey(KEYCODE_BRIGHTNESS_DOWN);
280             mPhoneWindowManager.verifyNewBrightness(newBrightness[i]);
281         }
282     }
283 
284     /**
285      * Sends a KEYCODE_SCREENSHOT and validates screenshot is taken if flag is enabled
286      */
287     @Test
288     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testTakeScreenshot_flagEnabled()289     public void testTakeScreenshot_flagEnabled() {
290         sendKeyCombination(new int[]{KEYCODE_SCREENSHOT}, 0);
291         mPhoneWindowManager.assertTakeScreenshotCalled();
292     }
293 
294     /**
295      * META+CTRL+BACKSPACE for taking a bugreport when the flag is enabled.
296      */
297     @Test
298     @EnableFlags(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
299     @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
testTakeBugReport_flagEnabled()300     public void testTakeBugReport_flagEnabled() throws RemoteException {
301         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_CTRL_LEFT, KEYCODE_DEL}, 0);
302         mPhoneWindowManager.assertTakeBugreport(true);
303     }
304 
305     /**
306      * META+CTRL+BACKSPACE for taking a bugreport does nothing when the flag is disabledd.
307      */
308     @Test
309     @DisableFlags({com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT,
310             com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER})
testTakeBugReport_flagDisabled()311     public void testTakeBugReport_flagDisabled() throws RemoteException {
312         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_CTRL_LEFT, KEYCODE_DEL}, 0);
313         mPhoneWindowManager.assertTakeBugreport(false);
314     }
315 
316 }
317