Introduce modifier shortcut key unit tests

This includes these tests for phone device:
Shortcut will start an intent to launch the specific app by category:
    Meta + A         - launch calculator
    Meta + B         - launch browser
    Meta + C         - launch contacts
    Meta + E         - launch email
    Meta + L         - launch calendar
    Meta + M         - launch maps
    Meta + P         - launch music
    Meta + S         - launch messaging

Shortcut will trigger specific behavior:
    Alt + Tab        - show recent apps
    Ctrl + Space     - switch keyboard layout
    Meta + Space     - switch keyboard layout
    Ctrl + Alt + Z   - enable accessibility service
    Meta + Ctrl + S  - take screenshot
    Meta + N         - expand notification panel
    Meta + Slash     - toggle shortcuts menu
    Meta + Alt       - toggle cap lock

Bug: 193278327
Test: atest ModifierShortcutTests

Change-Id: I713a0cccdf7304e84fa8df71cfd4c4d51305c887
This commit is contained in:
Arthur Hung
2022-09-23 07:49:18 +00:00
parent 340d1b85e8
commit 977aba93f7
2 changed files with 212 additions and 0 deletions

View File

@@ -0,0 +1,143 @@
/*
* Copyright (C) 2022 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.policy;
import static android.view.KeyEvent.KEYCODE_A;
import static android.view.KeyEvent.KEYCODE_ALT_LEFT;
import static android.view.KeyEvent.KEYCODE_B;
import static android.view.KeyEvent.KEYCODE_C;
import static android.view.KeyEvent.KEYCODE_CTRL_LEFT;
import static android.view.KeyEvent.KEYCODE_E;
import static android.view.KeyEvent.KEYCODE_L;
import static android.view.KeyEvent.KEYCODE_M;
import static android.view.KeyEvent.KEYCODE_META_LEFT;
import static android.view.KeyEvent.KEYCODE_N;
import static android.view.KeyEvent.KEYCODE_P;
import static android.view.KeyEvent.KEYCODE_S;
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_Z;
import android.content.Intent;
import android.os.RemoteException;
import android.util.SparseArray;
import org.junit.Test;
public class ModifierShortcutTests extends ShortcutKeyTestBase {
private static final SparseArray<String> META_SHORTCUTS = new SparseArray<>();
static {
META_SHORTCUTS.append(KEYCODE_A, Intent.CATEGORY_APP_CALCULATOR);
META_SHORTCUTS.append(KEYCODE_B, Intent.CATEGORY_APP_BROWSER);
META_SHORTCUTS.append(KEYCODE_C, Intent.CATEGORY_APP_CONTACTS);
META_SHORTCUTS.append(KEYCODE_E, Intent.CATEGORY_APP_EMAIL);
META_SHORTCUTS.append(KEYCODE_L, Intent.CATEGORY_APP_CALENDAR);
META_SHORTCUTS.append(KEYCODE_M, Intent.CATEGORY_APP_MAPS);
META_SHORTCUTS.append(KEYCODE_P, Intent.CATEGORY_APP_MUSIC);
META_SHORTCUTS.append(KEYCODE_S, Intent.CATEGORY_APP_MESSAGING);
}
/**
* Test meta+ shortcuts defined in bookmarks.xml.
*/
@Test
public void testMetaShortcuts() {
for (int i = 0; i < META_SHORTCUTS.size(); i++) {
final int keyCode = META_SHORTCUTS.keyAt(i);
final String category = META_SHORTCUTS.valueAt(i);
sendKeyCombination(new int[]{KEYCODE_META_LEFT, keyCode}, 0);
mPhoneWindowManager.assertLaunchCategory(category);
}
}
/**
* ALT + TAB to show recent apps.
*/
@Test
public void testAltTab() {
mPhoneWindowManager.overrideStatusBarManagerInternal();
sendKeyCombination(new int[]{KEYCODE_ALT_LEFT, KEYCODE_TAB}, 0);
mPhoneWindowManager.assertShowRecentApps();
}
/**
* CTRL + SPACE to switch keyboard layout.
*/
@Test
public void testCtrlSpace() {
sendKeyCombination(new int[]{KEYCODE_CTRL_LEFT, KEYCODE_SPACE}, 0);
mPhoneWindowManager.assertSwitchKeyboardLayout();
}
/**
* META + SPACE to switch keyboard layout.
*/
@Test
public void testMetaSpace() {
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SPACE}, 0);
mPhoneWindowManager.assertSwitchKeyboardLayout();
}
/**
* CTRL + ALT + Z to enable accessibility service.
*/
@Test
public void testCtrlAltZ() {
sendKeyCombination(new int[]{KEYCODE_CTRL_LEFT, KEYCODE_ALT_LEFT, KEYCODE_Z}, 0);
mPhoneWindowManager.assertAccessibilityKeychordCalled();
}
/**
* META + CTRL+ S to take screenshot.
*/
@Test
public void testMetaCtrlS() {
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_CTRL_LEFT, KEYCODE_S}, 0);
mPhoneWindowManager.assertTakeScreenshotCalled();
}
/**
* META + N to expand notification panel.
*/
@Test
public void testMetaN() throws RemoteException {
mPhoneWindowManager.overrideExpandNotificationsPanel();
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_N}, 0);
mPhoneWindowManager.assertExpandNotification();
}
/**
* META + SLASH to toggle shortcuts menu.
*/
@Test
public void testMetaSlash() {
mPhoneWindowManager.overrideStatusBarManagerInternal();
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SLASH}, 0);
mPhoneWindowManager.assertToggleShortcutsMenu();
}
/**
* META + ALT to toggle Cap Lock.
*/
@Test
public void testMetaAlt() {
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_ALT_LEFT}, 0);
mPhoneWindowManager.assertToggleCapsLock();
}
}

View File

@@ -32,6 +32,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_ASSISTANT;
import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_GLOBAL_ACTIONS;
@@ -53,6 +54,7 @@ import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
@@ -62,6 +64,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.RemoteException;
import android.os.Vibrator;
import android.service.dreams.DreamManagerInternal;
import android.telecom.TelecomManager;
@@ -73,12 +76,16 @@ import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.internal.accessibility.AccessibilityShortcutController;
import com.android.server.GestureLauncherService;
import com.android.server.LocalServices;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.vr.VrManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.DisplayPolicy;
import com.android.server.wm.DisplayRotation;
import com.android.server.wm.WindowManagerInternal;
import junit.framework.Assert;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockSettings;
import org.mockito.Mockito;
@@ -118,6 +125,8 @@ class TestPhoneWindowManager {
@Mock private GlobalActions mGlobalActions;
@Mock private AccessibilityShortcutController mAccessibilityShortcutController;
@Mock private StatusBarManagerInternal mStatusBarManagerInternal;
private StaticMockitoSession mMockitoSession;
private HandlerThread mHandlerThread;
private Handler mHandler;
@@ -226,6 +235,8 @@ class TestPhoneWindowManager {
mPhoneWindowManager.systemBooted();
overrideLaunchAccessibility();
doReturn(false).when(mPhoneWindowManager).keyguardOn();
doNothing().when(mContext).startActivityAsUser(any(), any());
}
void tearDown() {
@@ -310,6 +321,22 @@ class TestPhoneWindowManager {
doReturn(true).when(mTelecomManager).endCall();
}
void overrideExpandNotificationsPanel() {
// Can't directly mock on IStatusbarService, use spyOn and override the specific api.
mPhoneWindowManager.getStatusBarService();
spyOn(mPhoneWindowManager.mStatusBarService);
try {
doNothing().when(mPhoneWindowManager.mStatusBarService).expandNotificationsPanel();
} catch (RemoteException e) {
e.printStackTrace();
}
}
void overrideStatusBarManagerInternal() {
doReturn(mStatusBarManagerInternal).when(
() -> LocalServices.getService(eq(StatusBarManagerInternal.class)));
}
/**
* Below functions will check the policy behavior could be invoked.
*/
@@ -368,4 +395,46 @@ class TestPhoneWindowManager {
waitForIdle();
verify(mSearchManager, timeout(SHORTCUT_KEY_DELAY_MILLIS)).launchAssist(any());
}
void assertLaunchCategory(String category) {
waitForIdle();
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivityAsUser(intentCaptor.capture(), any());
Assert.assertTrue(intentCaptor.getValue().getSelector().hasCategory(category));
// Reset verifier for next call.
Mockito.reset(mContext);
}
void assertShowRecentApps() {
waitForIdle();
verify(mStatusBarManagerInternal).showRecentApps(anyBoolean());
}
void assertSwitchKeyboardLayout() {
waitForIdle();
verify(mWindowManagerFuncsImpl).switchKeyboardLayout(anyInt(), anyInt());
}
void assertTakeBugreport() {
waitForIdle();
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).sendOrderedBroadcastAsUser(intentCaptor.capture(), any(), any(), any(),
any(), anyInt(), any(), any());
Assert.assertTrue(intentCaptor.getValue().getAction() == Intent.ACTION_BUG_REPORT);
}
void assertExpandNotification() throws RemoteException {
waitForIdle();
verify(mPhoneWindowManager.mStatusBarService).expandNotificationsPanel();
}
void assertToggleShortcutsMenu() {
waitForIdle();
verify(mStatusBarManagerInternal).toggleKeyboardShortcutsMenu(anyInt());
}
void assertToggleCapsLock() {
waitForIdle();
verify(mInputManagerInternal).toggleCapsLock(anyInt());
}
}