summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl11
-rw-r--r--core/java/android/hardware/input/IKeyboardSystemShortcutListener.aidl27
-rw-r--r--core/java/android/hardware/input/InputManager.java47
-rw-r--r--core/java/android/hardware/input/InputManagerGlobal.java101
-rw-r--r--core/java/android/hardware/input/KeyboardSystemShortcut.java522
-rw-r--r--core/res/AndroidManifest.xml6
-rw-r--r--services/core/java/com/android/server/input/InputManagerInternal.java17
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java48
-rw-r--r--services/core/java/com/android/server/input/KeyboardMetricsCollector.java334
-rw-r--r--services/core/java/com/android/server/input/KeyboardShortcutCallbackHandler.java137
-rw-r--r--services/core/java/com/android/server/policy/ModifierShortcutManager.java121
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java209
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/KeyboardSystemShortcutTests.java (renamed from services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java)302
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java29
-rw-r--r--tests/Input/src/android/hardware/input/KeyboardSystemShortcutListenerTest.kt202
-rw-r--r--tests/Input/src/com/android/server/input/KeyboardShortcutCallbackHandlerTests.kt96
16 files changed, 1647 insertions, 562 deletions
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 1767d6438999..98e11375f077 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -25,6 +25,7 @@ import android.hardware.input.IInputDeviceBatteryListener;
import android.hardware.input.IInputDeviceBatteryState;
import android.hardware.input.IKeyboardBacklightListener;
import android.hardware.input.IKeyboardBacklightState;
+import android.hardware.input.IKeyboardSystemShortcutListener;
import android.hardware.input.IStickyModifierStateListener;
import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.KeyboardLayoutSelectionResult;
@@ -239,4 +240,14 @@ interface IInputManager {
void unregisterStickyModifierStateListener(IStickyModifierStateListener listener);
KeyGlyphMap getKeyGlyphMap(int deviceId);
+
+ @EnforcePermission("MONITOR_KEYBOARD_SYSTEM_SHORTCUTS")
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ + "android.Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)")
+ void registerKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener);
+
+ @EnforcePermission("MONITOR_KEYBOARD_SYSTEM_SHORTCUTS")
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ + "android.Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)")
+ void unregisterKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener);
}
diff --git a/core/java/android/hardware/input/IKeyboardSystemShortcutListener.aidl b/core/java/android/hardware/input/IKeyboardSystemShortcutListener.aidl
new file mode 100644
index 000000000000..8d44917845f4
--- /dev/null
+++ b/core/java/android/hardware/input/IKeyboardSystemShortcutListener.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+package android.hardware.input;
+
+/** @hide */
+oneway interface IKeyboardSystemShortcutListener {
+
+ /**
+ * Called when the keyboard system shortcut is triggered.
+ */
+ void onKeyboardSystemShortcutTriggered(int deviceId, in int[] keycodes, int modifierState,
+ int shortcut);
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index d7952eb26f7e..6bc522b2b386 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -1378,6 +1378,36 @@ public final class InputManager {
}
/**
+ * Registers a keyboard system shortcut listener for {@link KeyboardSystemShortcut} being
+ * triggered.
+ *
+ * @param executor an executor on which the callback will be called
+ * @param listener the {@link KeyboardSystemShortcutListener}
+ * @throws IllegalArgumentException if {@code listener} has already been registered previously.
+ * @throws NullPointerException if {@code listener} or {@code executor} is null.
+ * @hide
+ * @see #unregisterKeyboardSystemShortcutListener(KeyboardSystemShortcutListener)
+ */
+ @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
+ public void registerKeyboardSystemShortcutListener(@NonNull Executor executor,
+ @NonNull KeyboardSystemShortcutListener listener) throws IllegalArgumentException {
+ mGlobal.registerKeyboardSystemShortcutListener(executor, listener);
+ }
+
+ /**
+ * Unregisters a previously added keyboard system shortcut listener.
+ *
+ * @param listener the {@link KeyboardSystemShortcutListener}
+ * @hide
+ * @see #registerKeyboardSystemShortcutListener(Executor, KeyboardSystemShortcutListener)
+ */
+ @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
+ public void unregisterKeyboardSystemShortcutListener(
+ @NonNull KeyboardSystemShortcutListener listener) {
+ mGlobal.unregisterKeyboardSystemShortcutListener(listener);
+ }
+
+ /**
* A callback used to be notified about battery state changes for an input device. The
* {@link #onBatteryStateChanged(int, long, BatteryState)} method will be called once after the
* listener is successfully registered to provide the initial battery state of the device.
@@ -1478,4 +1508,21 @@ public final class InputManager {
*/
void onStickyModifierStateChanged(@NonNull StickyModifierState state);
}
+
+ /**
+ * A callback used to be notified about keyboard system shortcuts being triggered.
+ *
+ * @see #registerKeyboardSystemShortcutListener(Executor, KeyboardSystemShortcutListener)
+ * @see #unregisterKeyboardSystemShortcutListener(KeyboardSystemShortcutListener)
+ * @hide
+ */
+ public interface KeyboardSystemShortcutListener {
+ /**
+ * Called when a keyboard system shortcut is triggered.
+ *
+ * @param systemShortcut the shortcut info about the shortcut that was triggered.
+ */
+ void onKeyboardSystemShortcutTriggered(int deviceId,
+ @NonNull KeyboardSystemShortcut systemShortcut);
+ }
}
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
index 7b471806cfc1..f7fa5577a047 100644
--- a/core/java/android/hardware/input/InputManagerGlobal.java
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -26,6 +26,7 @@ import android.hardware.SensorManager;
import android.hardware.input.InputManager.InputDeviceBatteryListener;
import android.hardware.input.InputManager.InputDeviceListener;
import android.hardware.input.InputManager.KeyboardBacklightListener;
+import android.hardware.input.InputManager.KeyboardSystemShortcutListener;
import android.hardware.input.InputManager.OnTabletModeChangedListener;
import android.hardware.input.InputManager.StickyModifierStateListener;
import android.hardware.lights.Light;
@@ -110,6 +111,14 @@ public final class InputManagerGlobal {
@Nullable
private IStickyModifierStateListener mStickyModifierStateListener;
+ private final Object mKeyboardSystemShortcutListenerLock = new Object();
+ @GuardedBy("mKeyboardSystemShortcutListenerLock")
+ @Nullable
+ private ArrayList<KeyboardSystemShortcutListenerDelegate> mKeyboardSystemShortcutListeners;
+ @GuardedBy("mKeyboardSystemShortcutListenerLock")
+ @Nullable
+ private IKeyboardSystemShortcutListener mKeyboardSystemShortcutListener;
+
// InputDeviceSensorManager gets notified synchronously from the binder thread when input
// devices change, so it must be synchronized with the input device listeners.
@GuardedBy("mInputDeviceListeners")
@@ -1055,6 +1064,98 @@ public final class InputManagerGlobal {
}
}
+ private static final class KeyboardSystemShortcutListenerDelegate {
+ final KeyboardSystemShortcutListener mListener;
+ final Executor mExecutor;
+
+ KeyboardSystemShortcutListenerDelegate(KeyboardSystemShortcutListener listener,
+ Executor executor) {
+ mListener = listener;
+ mExecutor = executor;
+ }
+
+ void onKeyboardSystemShortcutTriggered(int deviceId,
+ KeyboardSystemShortcut systemShortcut) {
+ mExecutor.execute(() ->
+ mListener.onKeyboardSystemShortcutTriggered(deviceId, systemShortcut));
+ }
+ }
+
+ private class LocalKeyboardSystemShortcutListener extends IKeyboardSystemShortcutListener.Stub {
+
+ @Override
+ public void onKeyboardSystemShortcutTriggered(int deviceId, int[] keycodes,
+ int modifierState, int shortcut) {
+ synchronized (mKeyboardSystemShortcutListenerLock) {
+ if (mKeyboardSystemShortcutListeners == null) return;
+ final int numListeners = mKeyboardSystemShortcutListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ mKeyboardSystemShortcutListeners.get(i)
+ .onKeyboardSystemShortcutTriggered(deviceId,
+ new KeyboardSystemShortcut(keycodes, modifierState, shortcut));
+ }
+ }
+ }
+ }
+
+ /**
+ * @see InputManager#registerKeyboardSystemShortcutListener(Executor,
+ * KeyboardSystemShortcutListener)
+ */
+ @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
+ void registerKeyboardSystemShortcutListener(@NonNull Executor executor,
+ @NonNull KeyboardSystemShortcutListener listener) throws IllegalArgumentException {
+ Objects.requireNonNull(executor, "executor should not be null");
+ Objects.requireNonNull(listener, "listener should not be null");
+
+ synchronized (mKeyboardSystemShortcutListenerLock) {
+ if (mKeyboardSystemShortcutListener == null) {
+ mKeyboardSystemShortcutListeners = new ArrayList<>();
+ mKeyboardSystemShortcutListener = new LocalKeyboardSystemShortcutListener();
+
+ try {
+ mIm.registerKeyboardSystemShortcutListener(mKeyboardSystemShortcutListener);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ final int numListeners = mKeyboardSystemShortcutListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ if (mKeyboardSystemShortcutListeners.get(i).mListener == listener) {
+ throw new IllegalArgumentException("Listener has already been registered!");
+ }
+ }
+ KeyboardSystemShortcutListenerDelegate delegate =
+ new KeyboardSystemShortcutListenerDelegate(listener, executor);
+ mKeyboardSystemShortcutListeners.add(delegate);
+ }
+ }
+
+ /**
+ * @see InputManager#unregisterKeyboardSystemShortcutListener(KeyboardSystemShortcutListener)
+ */
+ @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
+ void unregisterKeyboardSystemShortcutListener(
+ @NonNull KeyboardSystemShortcutListener listener) {
+ Objects.requireNonNull(listener, "listener should not be null");
+
+ synchronized (mKeyboardSystemShortcutListenerLock) {
+ if (mKeyboardSystemShortcutListeners == null) {
+ return;
+ }
+ mKeyboardSystemShortcutListeners.removeIf((delegate) -> delegate.mListener == listener);
+ if (mKeyboardSystemShortcutListeners.isEmpty()) {
+ try {
+ mIm.unregisterKeyboardSystemShortcutListener(mKeyboardSystemShortcutListener);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ mKeyboardSystemShortcutListeners = null;
+ mKeyboardSystemShortcutListener = null;
+ }
+ }
+ }
+
/**
* TODO(b/330517633): Cleanup the unsupported API
*/
diff --git a/core/java/android/hardware/input/KeyboardSystemShortcut.java b/core/java/android/hardware/input/KeyboardSystemShortcut.java
new file mode 100644
index 000000000000..89cf877c3aa8
--- /dev/null
+++ b/core/java/android/hardware/input/KeyboardSystemShortcut.java
@@ -0,0 +1,522 @@
+/*
+ * 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.
+ */
+
+package android.hardware.input;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Provides information about the keyboard shortcut being triggered by an external keyboard.
+ *
+ * @hide
+ */
+@DataClass(genToString = true, genEqualsHashCode = true)
+public class KeyboardSystemShortcut {
+
+ private static final String TAG = "KeyboardSystemShortcut";
+
+ @NonNull
+ private final int[] mKeycodes;
+ private final int mModifierState;
+ @SystemShortcut
+ private final int mSystemShortcut;
+
+
+ public static final int SYSTEM_SHORTCUT_UNSPECIFIED =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__UNSPECIFIED;
+ public static final int SYSTEM_SHORTCUT_HOME =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__HOME;
+ public static final int SYSTEM_SHORTCUT_RECENT_APPS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__RECENT_APPS;
+ public static final int SYSTEM_SHORTCUT_BACK =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BACK;
+ public static final int SYSTEM_SHORTCUT_APP_SWITCH =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__APP_SWITCH;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_ASSISTANT =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_ASSISTANT;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_VOICE_ASSISTANT;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SYSTEM_SETTINGS;
+ public static final int SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_NOTIFICATION_PANEL;
+ public static final int SYSTEM_SHORTCUT_TOGGLE_TASKBAR =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_TASKBAR;
+ public static final int SYSTEM_SHORTCUT_TAKE_SCREENSHOT =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TAKE_SCREENSHOT;
+ public static final int SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_SHORTCUT_HELPER;
+ public static final int SYSTEM_SHORTCUT_BRIGHTNESS_UP =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_UP;
+ public static final int SYSTEM_SHORTCUT_BRIGHTNESS_DOWN =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_DOWN;
+ public static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_UP;
+ public static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_DOWN;
+ public static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_TOGGLE;
+ public static final int SYSTEM_SHORTCUT_VOLUME_UP =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_UP;
+ public static final int SYSTEM_SHORTCUT_VOLUME_DOWN =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_DOWN;
+ public static final int SYSTEM_SHORTCUT_VOLUME_MUTE =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_MUTE;
+ public static final int SYSTEM_SHORTCUT_ALL_APPS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ALL_APPS;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_SEARCH =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SEARCH;
+ public static final int SYSTEM_SHORTCUT_LANGUAGE_SWITCH =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LANGUAGE_SWITCH;
+ public static final int SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ACCESSIBILITY_ALL_APPS;
+ public static final int SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_CAPS_LOCK;
+ public static final int SYSTEM_SHORTCUT_SYSTEM_MUTE =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_MUTE;
+ public static final int SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SPLIT_SCREEN_NAVIGATION;
+ public static final int SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__CHANGE_SPLITSCREEN_FOCUS;
+ public static final int SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TRIGGER_BUG_REPORT;
+ public static final int SYSTEM_SHORTCUT_LOCK_SCREEN =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LOCK_SCREEN;
+ public static final int SYSTEM_SHORTCUT_OPEN_NOTES =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_NOTES;
+ public static final int SYSTEM_SHORTCUT_TOGGLE_POWER =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_POWER;
+ public static final int SYSTEM_SHORTCUT_SYSTEM_NAVIGATION =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_NAVIGATION;
+ public static final int SYSTEM_SHORTCUT_SLEEP =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SLEEP;
+ public static final int SYSTEM_SHORTCUT_WAKEUP =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__WAKEUP;
+ public static final int SYSTEM_SHORTCUT_MEDIA_KEY =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MEDIA_KEY;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_BROWSER;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_EMAIL;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CONTACTS;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALENDAR;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALCULATOR;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MUSIC;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MAPS;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MESSAGING;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_GALLERY;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FILES;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_WEATHER;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FITNESS;
+ public static final int SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_APPLICATION_BY_PACKAGE_NAME;
+ public static final int SYSTEM_SHORTCUT_DESKTOP_MODE =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__DESKTOP_MODE;
+ public static final int SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MULTI_WINDOW_NAVIGATION;
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/input/KeyboardSystemShortcut.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @IntDef(prefix = "SYSTEM_SHORTCUT_", value = {
+ SYSTEM_SHORTCUT_UNSPECIFIED,
+ SYSTEM_SHORTCUT_HOME,
+ SYSTEM_SHORTCUT_RECENT_APPS,
+ SYSTEM_SHORTCUT_BACK,
+ SYSTEM_SHORTCUT_APP_SWITCH,
+ SYSTEM_SHORTCUT_LAUNCH_ASSISTANT,
+ SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT,
+ SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS,
+ SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ SYSTEM_SHORTCUT_TOGGLE_TASKBAR,
+ SYSTEM_SHORTCUT_TAKE_SCREENSHOT,
+ SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER,
+ SYSTEM_SHORTCUT_BRIGHTNESS_UP,
+ SYSTEM_SHORTCUT_BRIGHTNESS_DOWN,
+ SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP,
+ SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN,
+ SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE,
+ SYSTEM_SHORTCUT_VOLUME_UP,
+ SYSTEM_SHORTCUT_VOLUME_DOWN,
+ SYSTEM_SHORTCUT_VOLUME_MUTE,
+ SYSTEM_SHORTCUT_ALL_APPS,
+ SYSTEM_SHORTCUT_LAUNCH_SEARCH,
+ SYSTEM_SHORTCUT_LANGUAGE_SWITCH,
+ SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS,
+ SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK,
+ SYSTEM_SHORTCUT_SYSTEM_MUTE,
+ SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION,
+ SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS,
+ SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT,
+ SYSTEM_SHORTCUT_LOCK_SCREEN,
+ SYSTEM_SHORTCUT_OPEN_NOTES,
+ SYSTEM_SHORTCUT_TOGGLE_POWER,
+ SYSTEM_SHORTCUT_SYSTEM_NAVIGATION,
+ SYSTEM_SHORTCUT_SLEEP,
+ SYSTEM_SHORTCUT_WAKEUP,
+ SYSTEM_SHORTCUT_MEDIA_KEY,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER,
+ SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS,
+ SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME,
+ SYSTEM_SHORTCUT_DESKTOP_MODE,
+ SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @DataClass.Generated.Member
+ public @interface SystemShortcut {}
+
+ @DataClass.Generated.Member
+ public static String systemShortcutToString(@SystemShortcut int value) {
+ switch (value) {
+ case SYSTEM_SHORTCUT_UNSPECIFIED:
+ return "SYSTEM_SHORTCUT_UNSPECIFIED";
+ case SYSTEM_SHORTCUT_HOME:
+ return "SYSTEM_SHORTCUT_HOME";
+ case SYSTEM_SHORTCUT_RECENT_APPS:
+ return "SYSTEM_SHORTCUT_RECENT_APPS";
+ case SYSTEM_SHORTCUT_BACK:
+ return "SYSTEM_SHORTCUT_BACK";
+ case SYSTEM_SHORTCUT_APP_SWITCH:
+ return "SYSTEM_SHORTCUT_APP_SWITCH";
+ case SYSTEM_SHORTCUT_LAUNCH_ASSISTANT:
+ return "SYSTEM_SHORTCUT_LAUNCH_ASSISTANT";
+ case SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT:
+ return "SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT";
+ case SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS:
+ return "SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS";
+ case SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL:
+ return "SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL";
+ case SYSTEM_SHORTCUT_TOGGLE_TASKBAR:
+ return "SYSTEM_SHORTCUT_TOGGLE_TASKBAR";
+ case SYSTEM_SHORTCUT_TAKE_SCREENSHOT:
+ return "SYSTEM_SHORTCUT_TAKE_SCREENSHOT";
+ case SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER:
+ return "SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER";
+ case SYSTEM_SHORTCUT_BRIGHTNESS_UP:
+ return "SYSTEM_SHORTCUT_BRIGHTNESS_UP";
+ case SYSTEM_SHORTCUT_BRIGHTNESS_DOWN:
+ return "SYSTEM_SHORTCUT_BRIGHTNESS_DOWN";
+ case SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP:
+ return "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP";
+ case SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN:
+ return "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN";
+ case SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE:
+ return "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE";
+ case SYSTEM_SHORTCUT_VOLUME_UP:
+ return "SYSTEM_SHORTCUT_VOLUME_UP";
+ case SYSTEM_SHORTCUT_VOLUME_DOWN:
+ return "SYSTEM_SHORTCUT_VOLUME_DOWN";
+ case SYSTEM_SHORTCUT_VOLUME_MUTE:
+ return "SYSTEM_SHORTCUT_VOLUME_MUTE";
+ case SYSTEM_SHORTCUT_ALL_APPS:
+ return "SYSTEM_SHORTCUT_ALL_APPS";
+ case SYSTEM_SHORTCUT_LAUNCH_SEARCH:
+ return "SYSTEM_SHORTCUT_LAUNCH_SEARCH";
+ case SYSTEM_SHORTCUT_LANGUAGE_SWITCH:
+ return "SYSTEM_SHORTCUT_LANGUAGE_SWITCH";
+ case SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS:
+ return "SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS";
+ case SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK:
+ return "SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK";
+ case SYSTEM_SHORTCUT_SYSTEM_MUTE:
+ return "SYSTEM_SHORTCUT_SYSTEM_MUTE";
+ case SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION:
+ return "SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION";
+ case SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS:
+ return "SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS";
+ case SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT:
+ return "SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT";
+ case SYSTEM_SHORTCUT_LOCK_SCREEN:
+ return "SYSTEM_SHORTCUT_LOCK_SCREEN";
+ case SYSTEM_SHORTCUT_OPEN_NOTES:
+ return "SYSTEM_SHORTCUT_OPEN_NOTES";
+ case SYSTEM_SHORTCUT_TOGGLE_POWER:
+ return "SYSTEM_SHORTCUT_TOGGLE_POWER";
+ case SYSTEM_SHORTCUT_SYSTEM_NAVIGATION:
+ return "SYSTEM_SHORTCUT_SYSTEM_NAVIGATION";
+ case SYSTEM_SHORTCUT_SLEEP:
+ return "SYSTEM_SHORTCUT_SLEEP";
+ case SYSTEM_SHORTCUT_WAKEUP:
+ return "SYSTEM_SHORTCUT_WAKEUP";
+ case SYSTEM_SHORTCUT_MEDIA_KEY:
+ return "SYSTEM_SHORTCUT_MEDIA_KEY";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER";
+ case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS:
+ return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS";
+ case SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME:
+ return "SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME";
+ case SYSTEM_SHORTCUT_DESKTOP_MODE:
+ return "SYSTEM_SHORTCUT_DESKTOP_MODE";
+ case SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION:
+ return "SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION";
+ default: return Integer.toHexString(value);
+ }
+ }
+
+ @DataClass.Generated.Member
+ public KeyboardSystemShortcut(
+ @NonNull int[] keycodes,
+ int modifierState,
+ @SystemShortcut int systemShortcut) {
+ this.mKeycodes = keycodes;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mKeycodes);
+ this.mModifierState = modifierState;
+ this.mSystemShortcut = systemShortcut;
+
+ if (!(mSystemShortcut == SYSTEM_SHORTCUT_UNSPECIFIED)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_HOME)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_RECENT_APPS)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_BACK)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_APP_SWITCH)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_ASSISTANT)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_TASKBAR)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_TAKE_SCREENSHOT)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_BRIGHTNESS_UP)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_BRIGHTNESS_DOWN)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_VOLUME_UP)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_VOLUME_DOWN)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_VOLUME_MUTE)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_ALL_APPS)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_SEARCH)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LANGUAGE_SWITCH)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_SYSTEM_MUTE)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LOCK_SCREEN)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_OPEN_NOTES)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_POWER)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_SYSTEM_NAVIGATION)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_SLEEP)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_WAKEUP)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_MEDIA_KEY)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_DESKTOP_MODE)
+ && !(mSystemShortcut == SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION)) {
+ throw new java.lang.IllegalArgumentException(
+ "systemShortcut was " + mSystemShortcut + " but must be one of: "
+ + "SYSTEM_SHORTCUT_UNSPECIFIED(" + SYSTEM_SHORTCUT_UNSPECIFIED + "), "
+ + "SYSTEM_SHORTCUT_HOME(" + SYSTEM_SHORTCUT_HOME + "), "
+ + "SYSTEM_SHORTCUT_RECENT_APPS(" + SYSTEM_SHORTCUT_RECENT_APPS + "), "
+ + "SYSTEM_SHORTCUT_BACK(" + SYSTEM_SHORTCUT_BACK + "), "
+ + "SYSTEM_SHORTCUT_APP_SWITCH(" + SYSTEM_SHORTCUT_APP_SWITCH + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_ASSISTANT(" + SYSTEM_SHORTCUT_LAUNCH_ASSISTANT + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT(" + SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS(" + SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS + "), "
+ + "SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL(" + SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL + "), "
+ + "SYSTEM_SHORTCUT_TOGGLE_TASKBAR(" + SYSTEM_SHORTCUT_TOGGLE_TASKBAR + "), "
+ + "SYSTEM_SHORTCUT_TAKE_SCREENSHOT(" + SYSTEM_SHORTCUT_TAKE_SCREENSHOT + "), "
+ + "SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER(" + SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER + "), "
+ + "SYSTEM_SHORTCUT_BRIGHTNESS_UP(" + SYSTEM_SHORTCUT_BRIGHTNESS_UP + "), "
+ + "SYSTEM_SHORTCUT_BRIGHTNESS_DOWN(" + SYSTEM_SHORTCUT_BRIGHTNESS_DOWN + "), "
+ + "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP(" + SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP + "), "
+ + "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN(" + SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN + "), "
+ + "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE(" + SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE + "), "
+ + "SYSTEM_SHORTCUT_VOLUME_UP(" + SYSTEM_SHORTCUT_VOLUME_UP + "), "
+ + "SYSTEM_SHORTCUT_VOLUME_DOWN(" + SYSTEM_SHORTCUT_VOLUME_DOWN + "), "
+ + "SYSTEM_SHORTCUT_VOLUME_MUTE(" + SYSTEM_SHORTCUT_VOLUME_MUTE + "), "
+ + "SYSTEM_SHORTCUT_ALL_APPS(" + SYSTEM_SHORTCUT_ALL_APPS + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_SEARCH(" + SYSTEM_SHORTCUT_LAUNCH_SEARCH + "), "
+ + "SYSTEM_SHORTCUT_LANGUAGE_SWITCH(" + SYSTEM_SHORTCUT_LANGUAGE_SWITCH + "), "
+ + "SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS(" + SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS + "), "
+ + "SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK(" + SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK + "), "
+ + "SYSTEM_SHORTCUT_SYSTEM_MUTE(" + SYSTEM_SHORTCUT_SYSTEM_MUTE + "), "
+ + "SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION(" + SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION + "), "
+ + "SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS(" + SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS + "), "
+ + "SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT(" + SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT + "), "
+ + "SYSTEM_SHORTCUT_LOCK_SCREEN(" + SYSTEM_SHORTCUT_LOCK_SCREEN + "), "
+ + "SYSTEM_SHORTCUT_OPEN_NOTES(" + SYSTEM_SHORTCUT_OPEN_NOTES + "), "
+ + "SYSTEM_SHORTCUT_TOGGLE_POWER(" + SYSTEM_SHORTCUT_TOGGLE_POWER + "), "
+ + "SYSTEM_SHORTCUT_SYSTEM_NAVIGATION(" + SYSTEM_SHORTCUT_SYSTEM_NAVIGATION + "), "
+ + "SYSTEM_SHORTCUT_SLEEP(" + SYSTEM_SHORTCUT_SLEEP + "), "
+ + "SYSTEM_SHORTCUT_WAKEUP(" + SYSTEM_SHORTCUT_WAKEUP + "), "
+ + "SYSTEM_SHORTCUT_MEDIA_KEY(" + SYSTEM_SHORTCUT_MEDIA_KEY + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS + "), "
+ + "SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME(" + SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME + "), "
+ + "SYSTEM_SHORTCUT_DESKTOP_MODE(" + SYSTEM_SHORTCUT_DESKTOP_MODE + "), "
+ + "SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION(" + SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION + ")");
+ }
+
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull int[] getKeycodes() {
+ return mKeycodes;
+ }
+
+ @DataClass.Generated.Member
+ public int getModifierState() {
+ return mModifierState;
+ }
+
+ @DataClass.Generated.Member
+ public @SystemShortcut int getSystemShortcut() {
+ return mSystemShortcut;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "KeyboardSystemShortcut { " +
+ "keycodes = " + java.util.Arrays.toString(mKeycodes) + ", " +
+ "modifierState = " + mModifierState + ", " +
+ "systemShortcut = " + systemShortcutToString(mSystemShortcut) +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(KeyboardSystemShortcut other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ KeyboardSystemShortcut that = (KeyboardSystemShortcut) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && java.util.Arrays.equals(mKeycodes, that.mKeycodes)
+ && mModifierState == that.mModifierState
+ && mSystemShortcut == that.mSystemShortcut;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + java.util.Arrays.hashCode(mKeycodes);
+ _hash = 31 * _hash + mModifierState;
+ _hash = 31 * _hash + mSystemShortcut;
+ return _hash;
+ }
+
+ @DataClass.Generated(
+ time = 1722890917041L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/hardware/input/KeyboardSystemShortcut.java",
+ inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull int[] mKeycodes\nprivate final int mModifierState\nprivate final @android.hardware.input.KeyboardSystemShortcut.SystemShortcut int mSystemShortcut\npublic static final int SYSTEM_SHORTCUT_UNSPECIFIED\npublic static final int SYSTEM_SHORTCUT_HOME\npublic static final int SYSTEM_SHORTCUT_RECENT_APPS\npublic static final int SYSTEM_SHORTCUT_BACK\npublic static final int SYSTEM_SHORTCUT_APP_SWITCH\npublic static final int SYSTEM_SHORTCUT_LAUNCH_ASSISTANT\npublic static final int SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT\npublic static final int SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS\npublic static final int SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL\npublic static final int SYSTEM_SHORTCUT_TOGGLE_TASKBAR\npublic static final int SYSTEM_SHORTCUT_TAKE_SCREENSHOT\npublic static final int SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER\npublic static final int SYSTEM_SHORTCUT_BRIGHTNESS_UP\npublic static final int SYSTEM_SHORTCUT_BRIGHTNESS_DOWN\npublic static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP\npublic static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN\npublic static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE\npublic static final int SYSTEM_SHORTCUT_VOLUME_UP\npublic static final int SYSTEM_SHORTCUT_VOLUME_DOWN\npublic static final int SYSTEM_SHORTCUT_VOLUME_MUTE\npublic static final int SYSTEM_SHORTCUT_ALL_APPS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_SEARCH\npublic static final int SYSTEM_SHORTCUT_LANGUAGE_SWITCH\npublic static final int SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS\npublic static final int SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK\npublic static final int SYSTEM_SHORTCUT_SYSTEM_MUTE\npublic static final int SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION\npublic static final int SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS\npublic static final int SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT\npublic static final int SYSTEM_SHORTCUT_LOCK_SCREEN\npublic static final int SYSTEM_SHORTCUT_OPEN_NOTES\npublic static final int SYSTEM_SHORTCUT_TOGGLE_POWER\npublic static final int SYSTEM_SHORTCUT_SYSTEM_NAVIGATION\npublic static final int SYSTEM_SHORTCUT_SLEEP\npublic static final int SYSTEM_SHORTCUT_WAKEUP\npublic static final int SYSTEM_SHORTCUT_MEDIA_KEY\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME\npublic static final int SYSTEM_SHORTCUT_DESKTOP_MODE\npublic static final int SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION\nclass KeyboardSystemShortcut extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 50727a2415c6..7aeabeed2a08 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -8132,6 +8132,12 @@
<permission android:name="android.permission.MONITOR_STICKY_MODIFIER_STATE"
android:protectionLevel="signature" />
+ <!-- Allows low-level access to monitor keyboard system shortcuts
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS"
+ android:protectionLevel="signature" />
+
<uses-permission android:name="android.permission.HANDLE_QUERY_PACKAGE_RESTART" />
<!-- Allows financed device kiosk apps to perform actions on the Device Lock service
diff --git a/services/core/java/com/android/server/input/InputManagerInternal.java b/services/core/java/com/android/server/input/InputManagerInternal.java
index d32a5ed60094..819b9a166daa 100644
--- a/services/core/java/com/android/server/input/InputManagerInternal.java
+++ b/services/core/java/com/android/server/input/InputManagerInternal.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.graphics.PointF;
import android.hardware.display.DisplayViewport;
+import android.hardware.input.KeyboardSystemShortcut;
import android.os.IBinder;
import android.view.InputChannel;
import android.view.inputmethod.InputMethodSubtype;
@@ -227,4 +228,20 @@ public abstract class InputManagerInternal {
* since boot.
*/
public abstract int getLastUsedInputDeviceId();
+
+ /**
+ * Notify Keyboard system shortcut was triggered by the user and handled by the framework.
+ *
+ * NOTE: This is just to notify that a system shortcut was triggered. No further action is
+ * required to execute the said shortcut. This callback is meant for purposes of providing user
+ * hints or logging, etc.
+ *
+ * @param deviceId the device ID of the keyboard using which the shortcut was triggered
+ * @param keycodes the keys pressed for triggering the shortcut
+ * @param modifierState the modifier state of the key event that triggered the shortcut
+ * @param shortcut the shortcut that was triggered
+ *
+ */
+ public abstract void notifyKeyboardShortcutTriggered(int deviceId, int[] keycodes,
+ int modifierState, @KeyboardSystemShortcut.SystemShortcut int shortcut);
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index a06ad145100d..e555761e34e1 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -47,6 +47,7 @@ import android.hardware.input.IInputDevicesChangedListener;
import android.hardware.input.IInputManager;
import android.hardware.input.IInputSensorEventListener;
import android.hardware.input.IKeyboardBacklightListener;
+import android.hardware.input.IKeyboardSystemShortcutListener;
import android.hardware.input.IStickyModifierStateListener;
import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.InputDeviceIdentifier;
@@ -56,6 +57,7 @@ import android.hardware.input.InputSettings;
import android.hardware.input.KeyGlyphMap;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.KeyboardLayoutSelectionResult;
+import android.hardware.input.KeyboardSystemShortcut;
import android.hardware.input.TouchCalibration;
import android.hardware.lights.Light;
import android.hardware.lights.LightState;
@@ -157,6 +159,7 @@ public class InputManagerService extends IInputManager.Stub
private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1;
private static final int MSG_RELOAD_DEVICE_ALIASES = 2;
private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 3;
+ private static final int MSG_KEYBOARD_SYSTEM_SHORTCUT_TRIGGERED = 4;
private static final int DEFAULT_VIBRATION_MAGNITUDE = 192;
private static final AdditionalDisplayInputProperties
@@ -306,6 +309,9 @@ public class InputManagerService extends IInputManager.Stub
// Manages Sticky modifier state
private final StickyModifierStateController mStickyModifierStateController;
+ // Manages keyboard system shortcut callbacks
+ private final KeyboardShortcutCallbackHandler mKeyboardShortcutCallbackHandler;
+
// Manages Keyboard microphone mute led
private final KeyboardLedController mKeyboardLedController;
@@ -461,6 +467,7 @@ public class InputManagerService extends IInputManager.Stub
injector.getLooper(), injector.getUEventManager())
: new KeyboardBacklightControllerInterface() {};
mStickyModifierStateController = new StickyModifierStateController();
+ mKeyboardShortcutCallbackHandler = new KeyboardShortcutCallbackHandler();
mKeyboardLedController = new KeyboardLedController(mContext, injector.getLooper(),
mNative);
mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper());
@@ -2703,6 +2710,36 @@ public class InputManagerService extends IInputManager.Stub
lockedModifierState);
}
+ @Override
+ @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
+ public void registerKeyboardSystemShortcutListener(
+ @NonNull IKeyboardSystemShortcutListener listener) {
+ super.registerKeyboardSystemShortcutListener_enforcePermission();
+ Objects.requireNonNull(listener);
+ mKeyboardShortcutCallbackHandler.registerKeyboardSystemShortcutListener(listener,
+ Binder.getCallingPid());
+ }
+
+ @Override
+ @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
+ public void unregisterKeyboardSystemShortcutListener(
+ @NonNull IKeyboardSystemShortcutListener listener) {
+ super.unregisterKeyboardSystemShortcutListener_enforcePermission();
+ Objects.requireNonNull(listener);
+ mKeyboardShortcutCallbackHandler.unregisterKeyboardSystemShortcutListener(listener,
+ Binder.getCallingPid());
+ }
+
+ private void handleKeyboardSystemShortcutTriggered(int deviceId,
+ KeyboardSystemShortcut shortcut) {
+ InputDevice device = getInputDevice(deviceId);
+ if (device == null || device.isVirtual() || !device.isFullKeyboard()) {
+ return;
+ }
+ KeyboardMetricsCollector.logKeyboardSystemsEventReportedAtom(device, shortcut);
+ mKeyboardShortcutCallbackHandler.onKeyboardSystemShortcutTriggered(deviceId, shortcut);
+ }
+
/**
* Callback interface implemented by the Window Manager.
*/
@@ -2871,6 +2908,10 @@ public class InputManagerService extends IInputManager.Stub
boolean inTabletMode = (boolean) args.arg1;
deliverTabletModeChanged(whenNanos, inTabletMode);
break;
+ case MSG_KEYBOARD_SYSTEM_SHORTCUT_TRIGGERED:
+ int deviceId = msg.arg1;
+ KeyboardSystemShortcut shortcut = (KeyboardSystemShortcut) msg.obj;
+ handleKeyboardSystemShortcutTriggered(deviceId, shortcut);
}
}
}
@@ -3196,6 +3237,13 @@ public class InputManagerService extends IInputManager.Stub
public int getLastUsedInputDeviceId() {
return mNative.getLastUsedInputDeviceId();
}
+
+ @Override
+ public void notifyKeyboardShortcutTriggered(int deviceId, int[] keycodes, int modifierState,
+ @KeyboardSystemShortcut.SystemShortcut int shortcut) {
+ mHandler.obtainMessage(MSG_KEYBOARD_SYSTEM_SHORTCUT_TRIGGERED, deviceId, 0,
+ new KeyboardSystemShortcut(keycodes, modifierState, shortcut)).sendToTarget();
+ }
}
@Override
diff --git a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
index f21fd4132f0f..3d2f95105e76 100644
--- a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
+++ b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
@@ -24,31 +24,25 @@ import static android.hardware.input.KeyboardLayoutSelectionResult.layoutSelecti
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.role.RoleManager;
-import android.content.Intent;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.KeyboardLayoutSelectionResult.LayoutSelectionCriteria;
+import android.hardware.input.KeyboardSystemShortcut;
import android.icu.util.ULocale;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.InputDevice;
-import android.view.KeyEvent;
import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.KeyboardConfiguredProto.KeyboardLayoutConfig;
import com.android.internal.os.KeyboardConfiguredProto.RepeatedKeyboardLayoutConfig;
import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.policy.ModifierShortcutManager;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Objects;
-import java.util.Set;
/**
* Collect Keyboard metrics
@@ -66,336 +60,20 @@ public final class KeyboardMetricsCollector {
@VisibleForTesting
public static final String DEFAULT_LANGUAGE_TAG = "None";
- public enum KeyboardLogEvent {
- UNSPECIFIED(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__UNSPECIFIED,
- "INVALID_KEYBOARD_EVENT"),
- HOME(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__HOME,
- "HOME"),
- RECENT_APPS(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__RECENT_APPS,
- "RECENT_APPS"),
- BACK(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BACK,
- "BACK"),
- APP_SWITCH(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__APP_SWITCH,
- "APP_SWITCH"),
- LAUNCH_ASSISTANT(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_ASSISTANT,
- "LAUNCH_ASSISTANT"),
- LAUNCH_VOICE_ASSISTANT(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_VOICE_ASSISTANT,
- "LAUNCH_VOICE_ASSISTANT"),
- LAUNCH_SYSTEM_SETTINGS(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SYSTEM_SETTINGS,
- "LAUNCH_SYSTEM_SETTINGS"),
- TOGGLE_NOTIFICATION_PANEL(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_NOTIFICATION_PANEL,
- "TOGGLE_NOTIFICATION_PANEL"),
- TOGGLE_TASKBAR(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_TASKBAR,
- "TOGGLE_TASKBAR"),
- TAKE_SCREENSHOT(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TAKE_SCREENSHOT,
- "TAKE_SCREENSHOT"),
- OPEN_SHORTCUT_HELPER(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_SHORTCUT_HELPER,
- "OPEN_SHORTCUT_HELPER"),
- BRIGHTNESS_UP(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_UP,
- "BRIGHTNESS_UP"),
- BRIGHTNESS_DOWN(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_DOWN,
- "BRIGHTNESS_DOWN"),
- KEYBOARD_BACKLIGHT_UP(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_UP,
- "KEYBOARD_BACKLIGHT_UP"),
- KEYBOARD_BACKLIGHT_DOWN(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_DOWN,
- "KEYBOARD_BACKLIGHT_DOWN"),
- KEYBOARD_BACKLIGHT_TOGGLE(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_TOGGLE,
- "KEYBOARD_BACKLIGHT_TOGGLE"),
- VOLUME_UP(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_UP,
- "VOLUME_UP"),
- VOLUME_DOWN(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_DOWN,
- "VOLUME_DOWN"),
- VOLUME_MUTE(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_MUTE,
- "VOLUME_MUTE"),
- ALL_APPS(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ALL_APPS,
- "ALL_APPS"),
- LAUNCH_SEARCH(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SEARCH,
- "LAUNCH_SEARCH"),
- LANGUAGE_SWITCH(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LANGUAGE_SWITCH,
- "LANGUAGE_SWITCH"),
- ACCESSIBILITY_ALL_APPS(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ACCESSIBILITY_ALL_APPS,
- "ACCESSIBILITY_ALL_APPS"),
- TOGGLE_CAPS_LOCK(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_CAPS_LOCK,
- "TOGGLE_CAPS_LOCK"),
- SYSTEM_MUTE(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_MUTE,
- "SYSTEM_MUTE"),
- SPLIT_SCREEN_NAVIGATION(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SPLIT_SCREEN_NAVIGATION,
- "SPLIT_SCREEN_NAVIGATION"),
-
- CHANGE_SPLITSCREEN_FOCUS(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__CHANGE_SPLITSCREEN_FOCUS,
- "CHANGE_SPLITSCREEN_FOCUS"),
- TRIGGER_BUG_REPORT(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TRIGGER_BUG_REPORT,
- "TRIGGER_BUG_REPORT"),
- LOCK_SCREEN(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LOCK_SCREEN,
- "LOCK_SCREEN"),
- OPEN_NOTES(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_NOTES,
- "OPEN_NOTES"),
- TOGGLE_POWER(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_POWER,
- "TOGGLE_POWER"),
- SYSTEM_NAVIGATION(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_NAVIGATION,
- "SYSTEM_NAVIGATION"),
- SLEEP(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SLEEP,
- "SLEEP"),
- WAKEUP(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__WAKEUP,
- "WAKEUP"),
- MEDIA_KEY(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MEDIA_KEY,
- "MEDIA_KEY"),
- LAUNCH_DEFAULT_BROWSER(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_BROWSER,
- "LAUNCH_DEFAULT_BROWSER"),
- LAUNCH_DEFAULT_EMAIL(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_EMAIL,
- "LAUNCH_DEFAULT_EMAIL"),
- LAUNCH_DEFAULT_CONTACTS(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CONTACTS,
- "LAUNCH_DEFAULT_CONTACTS"),
- LAUNCH_DEFAULT_CALENDAR(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALENDAR,
- "LAUNCH_DEFAULT_CALENDAR"),
- LAUNCH_DEFAULT_CALCULATOR(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALCULATOR,
- "LAUNCH_DEFAULT_CALCULATOR"),
- LAUNCH_DEFAULT_MUSIC(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MUSIC,
- "LAUNCH_DEFAULT_MUSIC"),
- LAUNCH_DEFAULT_MAPS(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MAPS,
- "LAUNCH_DEFAULT_MAPS"),
- LAUNCH_DEFAULT_MESSAGING(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MESSAGING,
- "LAUNCH_DEFAULT_MESSAGING"),
- LAUNCH_DEFAULT_GALLERY(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_GALLERY,
- "LAUNCH_DEFAULT_GALLERY"),
- LAUNCH_DEFAULT_FILES(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FILES,
- "LAUNCH_DEFAULT_FILES"),
- LAUNCH_DEFAULT_WEATHER(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_WEATHER,
- "LAUNCH_DEFAULT_WEATHER"),
- LAUNCH_DEFAULT_FITNESS(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FITNESS,
- "LAUNCH_DEFAULT_FITNESS"),
- LAUNCH_APPLICATION_BY_PACKAGE_NAME(
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_APPLICATION_BY_PACKAGE_NAME,
- "LAUNCH_APPLICATION_BY_PACKAGE_NAME"),
- DESKTOP_MODE(
- FrameworkStatsLog
- .KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__DESKTOP_MODE,
- "DESKTOP_MODE"),
- MULTI_WINDOW_NAVIGATION(FrameworkStatsLog
- .KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MULTI_WINDOW_NAVIGATION,
- "MULTIWINDOW_NAVIGATION");
-
-
- private final int mValue;
- private final String mName;
-
- private static final SparseArray<KeyboardLogEvent> VALUE_TO_ENUM_MAP = new SparseArray<>();
-
- static {
- for (KeyboardLogEvent type : KeyboardLogEvent.values()) {
- VALUE_TO_ENUM_MAP.put(type.mValue, type);
- }
- }
-
- KeyboardLogEvent(int enumValue, String enumName) {
- mValue = enumValue;
- mName = enumName;
- }
-
- public int getIntValue() {
- return mValue;
- }
-
- /**
- * Convert int value to corresponding KeyboardLogEvent enum. If can't find any matching
- * value will return {@code null}
- */
- @Nullable
- public static KeyboardLogEvent from(int value) {
- return VALUE_TO_ENUM_MAP.get(value);
- }
-
- /**
- * Find KeyboardLogEvent corresponding to volume up/down/mute key events.
- */
- @Nullable
- public static KeyboardLogEvent getVolumeEvent(int keycode) {
- switch (keycode) {
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- return VOLUME_DOWN;
- case KeyEvent.KEYCODE_VOLUME_UP:
- return VOLUME_UP;
- case KeyEvent.KEYCODE_VOLUME_MUTE:
- return VOLUME_MUTE;
- default:
- return null;
- }
- }
-
- /**
- * Find KeyboardLogEvent corresponding to brightness up/down key events.
- */
- @Nullable
- public static KeyboardLogEvent getBrightnessEvent(int keycode) {
- switch (keycode) {
- case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:
- return BRIGHTNESS_DOWN;
- case KeyEvent.KEYCODE_BRIGHTNESS_UP:
- return BRIGHTNESS_UP;
- default:
- return null;
- }
- }
-
- /**
- * Find KeyboardLogEvent corresponding to intent filter category. Returns
- * {@code null if no matching event found}
- */
- @Nullable
- public static KeyboardLogEvent getLogEventFromIntent(Intent intent) {
- Intent selectorIntent = intent.getSelector();
- if (selectorIntent != null) {
- Set<String> selectorCategories = selectorIntent.getCategories();
- if (selectorCategories != null && !selectorCategories.isEmpty()) {
- for (String intentCategory : selectorCategories) {
- KeyboardLogEvent logEvent = getEventFromSelectorCategory(intentCategory);
- if (logEvent == null) {
- continue;
- }
- return logEvent;
- }
- }
- }
-
- // The shortcut may be targeting a system role rather than using an intent selector,
- // so check for that.
- String role = intent.getStringExtra(ModifierShortcutManager.EXTRA_ROLE);
- if (!TextUtils.isEmpty(role)) {
- return getLogEventFromRole(role);
- }
-
- Set<String> intentCategories = intent.getCategories();
- if (intentCategories == null || intentCategories.isEmpty()
- || !intentCategories.contains(Intent.CATEGORY_LAUNCHER)) {
- return null;
- }
- if (intent.getComponent() == null) {
- return null;
- }
-
- // TODO(b/280423320): Add new field package name associated in the
- // KeyboardShortcutEvent atom and log it accordingly.
- return LAUNCH_APPLICATION_BY_PACKAGE_NAME;
- }
-
- @Nullable
- private static KeyboardLogEvent getEventFromSelectorCategory(String category) {
- switch (category) {
- case Intent.CATEGORY_APP_BROWSER:
- return LAUNCH_DEFAULT_BROWSER;
- case Intent.CATEGORY_APP_EMAIL:
- return LAUNCH_DEFAULT_EMAIL;
- case Intent.CATEGORY_APP_CONTACTS:
- return LAUNCH_DEFAULT_CONTACTS;
- case Intent.CATEGORY_APP_CALENDAR:
- return LAUNCH_DEFAULT_CALENDAR;
- case Intent.CATEGORY_APP_CALCULATOR:
- return LAUNCH_DEFAULT_CALCULATOR;
- case Intent.CATEGORY_APP_MUSIC:
- return LAUNCH_DEFAULT_MUSIC;
- case Intent.CATEGORY_APP_MAPS:
- return LAUNCH_DEFAULT_MAPS;
- case Intent.CATEGORY_APP_MESSAGING:
- return LAUNCH_DEFAULT_MESSAGING;
- case Intent.CATEGORY_APP_GALLERY:
- return LAUNCH_DEFAULT_GALLERY;
- case Intent.CATEGORY_APP_FILES:
- return LAUNCH_DEFAULT_FILES;
- case Intent.CATEGORY_APP_WEATHER:
- return LAUNCH_DEFAULT_WEATHER;
- case Intent.CATEGORY_APP_FITNESS:
- return LAUNCH_DEFAULT_FITNESS;
- default:
- return null;
- }
- }
-
- /**
- * Find KeyboardLogEvent corresponding to the provide system role name.
- * Returns {@code null} if no matching event found.
- */
- @Nullable
- private static KeyboardLogEvent getLogEventFromRole(String role) {
- if (RoleManager.ROLE_BROWSER.equals(role)) {
- return LAUNCH_DEFAULT_BROWSER;
- } else if (RoleManager.ROLE_SMS.equals(role)) {
- return LAUNCH_DEFAULT_MESSAGING;
- } else {
- Log.w(TAG, "Keyboard shortcut to launch "
- + role + " not supported for logging");
- return null;
- }
- }
- }
-
/**
* Log keyboard system shortcuts for the proto
* {@link com.android.os.input.KeyboardSystemsEventReported}
* defined in "stats/atoms/input/input_extension_atoms.proto"
*/
- public static void logKeyboardSystemsEventReportedAtom(@Nullable InputDevice inputDevice,
- @Nullable KeyboardLogEvent keyboardSystemEvent, int modifierState, int... keyCodes) {
- // Logging Keyboard system event only for an external HW keyboard. We should not log events
- // for virtual keyboards or internal Key events.
- if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
- return;
- }
- if (keyboardSystemEvent == null) {
- Slog.w(TAG, "Invalid keyboard event logging, keycode = " + Arrays.toString(keyCodes)
- + ", modifier state = " + modifierState);
- return;
- }
+ public static void logKeyboardSystemsEventReportedAtom(@NonNull InputDevice inputDevice,
+ @NonNull KeyboardSystemShortcut keyboardSystemShortcut) {
FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED,
inputDevice.getVendorId(), inputDevice.getProductId(),
- keyboardSystemEvent.getIntValue(), keyCodes, modifierState,
- inputDevice.getDeviceBus());
+ keyboardSystemShortcut.getSystemShortcut(), keyboardSystemShortcut.getKeycodes(),
+ keyboardSystemShortcut.getModifierState(), inputDevice.getDeviceBus());
if (DEBUG) {
- Slog.d(TAG, "Logging Keyboard system event: " + keyboardSystemEvent.mName);
+ Slog.d(TAG, "Logging Keyboard system event: " + keyboardSystemShortcut);
}
}
diff --git a/services/core/java/com/android/server/input/KeyboardShortcutCallbackHandler.java b/services/core/java/com/android/server/input/KeyboardShortcutCallbackHandler.java
new file mode 100644
index 000000000000..092058e6f7d0
--- /dev/null
+++ b/services/core/java/com/android/server/input/KeyboardShortcutCallbackHandler.java
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+package com.android.server.input;
+
+import android.annotation.BinderThread;
+import android.hardware.input.IKeyboardSystemShortcutListener;
+import android.hardware.input.KeyboardSystemShortcut;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * A thread-safe component of {@link InputManagerService} responsible for managing callbacks when a
+ * keyboard shortcut is triggered.
+ */
+final class KeyboardShortcutCallbackHandler {
+
+ private static final String TAG = "KeyboardShortcut";
+
+ // To enable these logs, run:
+ // 'adb shell setprop log.tag.KeyboardShortcutCallbackHandler DEBUG' (requires restart)
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ // List of currently registered keyboard system shortcut listeners keyed by process pid
+ @GuardedBy("mKeyboardSystemShortcutListenerRecords")
+ private final SparseArray<KeyboardSystemShortcutListenerRecord>
+ mKeyboardSystemShortcutListenerRecords = new SparseArray<>();
+
+ public void onKeyboardSystemShortcutTriggered(int deviceId,
+ KeyboardSystemShortcut systemShortcut) {
+ if (DEBUG) {
+ Slog.d(TAG, "Keyboard system shortcut triggered, deviceId = " + deviceId
+ + ", systemShortcut = " + systemShortcut);
+ }
+
+ synchronized (mKeyboardSystemShortcutListenerRecords) {
+ for (int i = 0; i < mKeyboardSystemShortcutListenerRecords.size(); i++) {
+ mKeyboardSystemShortcutListenerRecords.valueAt(i).onKeyboardSystemShortcutTriggered(
+ deviceId, systemShortcut);
+ }
+ }
+ }
+
+ /** Register the keyboard system shortcut listener for a process. */
+ @BinderThread
+ public void registerKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener,
+ int pid) {
+ synchronized (mKeyboardSystemShortcutListenerRecords) {
+ if (mKeyboardSystemShortcutListenerRecords.get(pid) != null) {
+ throw new IllegalStateException("The calling process has already registered "
+ + "a KeyboardSystemShortcutListener.");
+ }
+ KeyboardSystemShortcutListenerRecord record = new KeyboardSystemShortcutListenerRecord(
+ pid, listener);
+ try {
+ listener.asBinder().linkToDeath(record, 0);
+ } catch (RemoteException ex) {
+ throw new RuntimeException(ex);
+ }
+ mKeyboardSystemShortcutListenerRecords.put(pid, record);
+ }
+ }
+
+ /** Unregister the keyboard system shortcut listener for a process. */
+ @BinderThread
+ public void unregisterKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener,
+ int pid) {
+ synchronized (mKeyboardSystemShortcutListenerRecords) {
+ KeyboardSystemShortcutListenerRecord record =
+ mKeyboardSystemShortcutListenerRecords.get(pid);
+ if (record == null) {
+ throw new IllegalStateException("The calling process has no registered "
+ + "KeyboardSystemShortcutListener.");
+ }
+ if (record.mListener.asBinder() != listener.asBinder()) {
+ throw new IllegalStateException("The calling process has a different registered "
+ + "KeyboardSystemShortcutListener.");
+ }
+ record.mListener.asBinder().unlinkToDeath(record, 0);
+ mKeyboardSystemShortcutListenerRecords.remove(pid);
+ }
+ }
+
+ private void onKeyboardSystemShortcutListenerDied(int pid) {
+ synchronized (mKeyboardSystemShortcutListenerRecords) {
+ mKeyboardSystemShortcutListenerRecords.remove(pid);
+ }
+ }
+
+ // A record of a registered keyboard system shortcut listener from one process.
+ private class KeyboardSystemShortcutListenerRecord implements IBinder.DeathRecipient {
+ public final int mPid;
+ public final IKeyboardSystemShortcutListener mListener;
+
+ KeyboardSystemShortcutListenerRecord(int pid, IKeyboardSystemShortcutListener listener) {
+ mPid = pid;
+ mListener = listener;
+ }
+
+ @Override
+ public void binderDied() {
+ if (DEBUG) {
+ Slog.d(TAG, "Keyboard system shortcut listener for pid " + mPid + " died.");
+ }
+ onKeyboardSystemShortcutListenerDied(mPid);
+ }
+
+ public void onKeyboardSystemShortcutTriggered(int deviceId, KeyboardSystemShortcut data) {
+ try {
+ mListener.onKeyboardSystemShortcutTriggered(deviceId, data.getKeycodes(),
+ data.getModifierState(), data.getSystemShortcut());
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify process " + mPid
+ + " that keyboard system shortcut was triggered, assuming it died.", ex);
+ binderDied();
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/policy/ModifierShortcutManager.java b/services/core/java/com/android/server/policy/ModifierShortcutManager.java
index cefecbc99bd7..5a4518606ca6 100644
--- a/services/core/java/com/android/server/policy/ModifierShortcutManager.java
+++ b/services/core/java/com/android/server/policy/ModifierShortcutManager.java
@@ -30,6 +30,7 @@ import android.content.pm.PackageManager;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Icon;
import android.hardware.input.InputManager;
+import android.hardware.input.KeyboardSystemShortcut;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -39,7 +40,6 @@ import android.util.Log;
import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
-import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.KeyboardShortcutGroup;
@@ -49,8 +49,8 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.IShortcutService;
import com.android.internal.util.XmlUtils;
-import com.android.server.input.KeyboardMetricsCollector;
-import com.android.server.input.KeyboardMetricsCollector.KeyboardLogEvent;
+import com.android.server.LocalServices;
+import com.android.server.input.InputManagerInternal;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -61,6 +61,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Manages quick launch shortcuts by:
@@ -123,6 +124,7 @@ public class ModifierShortcutManager {
private final Context mContext;
private final Handler mHandler;
+ private final InputManagerInternal mInputManagerInternal;
private boolean mSearchKeyShortcutPending = false;
private boolean mConsumeSearchKeyUp = true;
private UserHandle mCurrentUser;
@@ -136,6 +138,7 @@ public class ModifierShortcutManager {
mRoleIntents.remove(roleName);
}, UserHandle.ALL);
mCurrentUser = currentUser;
+ mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
loadShortcuts();
}
@@ -473,7 +476,7 @@ public class ModifierShortcutManager {
+ "keyCode=" + KeyEvent.keyCodeToString(keyCode) + ","
+ " category=" + category + " role=" + role);
}
- logKeyboardShortcut(keyEvent, KeyboardLogEvent.getLogEventFromIntent(intent));
+ notifyKeyboardShortcutTriggered(keyEvent, getSystemShortcutFromIntent(intent));
return true;
} else {
return false;
@@ -494,22 +497,19 @@ public class ModifierShortcutManager {
+ "the activity to which it is registered was not found: "
+ "META+ or SEARCH" + KeyEvent.keyCodeToString(keyCode));
}
- logKeyboardShortcut(keyEvent, KeyboardLogEvent.getLogEventFromIntent(shortcutIntent));
+ notifyKeyboardShortcutTriggered(keyEvent, getSystemShortcutFromIntent(shortcutIntent));
return true;
}
return false;
}
- private void logKeyboardShortcut(KeyEvent event, KeyboardLogEvent logEvent) {
- mHandler.post(() -> handleKeyboardLogging(event, logEvent));
- }
-
- private void handleKeyboardLogging(KeyEvent event, KeyboardLogEvent logEvent) {
- final InputManager inputManager = mContext.getSystemService(InputManager.class);
- final InputDevice inputDevice = inputManager != null
- ? inputManager.getInputDevice(event.getDeviceId()) : null;
- KeyboardMetricsCollector.logKeyboardSystemsEventReportedAtom(inputDevice,
- logEvent, event.getMetaState(), event.getKeyCode());
+ private void notifyKeyboardShortcutTriggered(KeyEvent event,
+ @KeyboardSystemShortcut.SystemShortcut int systemShortcut) {
+ if (systemShortcut == KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED) {
+ return;
+ }
+ mInputManagerInternal.notifyKeyboardShortcutTriggered(event.getDeviceId(),
+ new int[]{event.getKeyCode()}, event.getMetaState(), systemShortcut);
}
/**
@@ -708,6 +708,97 @@ public class ModifierShortcutManager {
return context.getString(resid);
};
+
+ /**
+ * Find Keyboard shortcut event corresponding to intent filter category. Returns
+ * {@code SYSTEM_SHORTCUT_UNSPECIFIED if no matching event found}
+ */
+ @KeyboardSystemShortcut.SystemShortcut
+ private static int getSystemShortcutFromIntent(Intent intent) {
+ Intent selectorIntent = intent.getSelector();
+ if (selectorIntent != null) {
+ Set<String> selectorCategories = selectorIntent.getCategories();
+ if (selectorCategories != null && !selectorCategories.isEmpty()) {
+ for (String intentCategory : selectorCategories) {
+ int systemShortcut = getEventFromSelectorCategory(intentCategory);
+ if (systemShortcut == KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED) {
+ continue;
+ }
+ return systemShortcut;
+ }
+ }
+ }
+
+ // The shortcut may be targeting a system role rather than using an intent selector,
+ // so check for that.
+ String role = intent.getStringExtra(ModifierShortcutManager.EXTRA_ROLE);
+ if (!TextUtils.isEmpty(role)) {
+ return getLogEventFromRole(role);
+ }
+
+ Set<String> intentCategories = intent.getCategories();
+ if (intentCategories == null || intentCategories.isEmpty()
+ || !intentCategories.contains(Intent.CATEGORY_LAUNCHER)) {
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED;
+ }
+ if (intent.getComponent() == null) {
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED;
+ }
+
+ // TODO(b/280423320): Add new field package name associated in the
+ // KeyboardShortcutEvent atom and log it accordingly.
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME;
+ }
+
+ @KeyboardSystemShortcut.SystemShortcut
+ private static int getEventFromSelectorCategory(String category) {
+ switch (category) {
+ case Intent.CATEGORY_APP_BROWSER:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER;
+ case Intent.CATEGORY_APP_EMAIL:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL;
+ case Intent.CATEGORY_APP_CONTACTS:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS;
+ case Intent.CATEGORY_APP_CALENDAR:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR;
+ case Intent.CATEGORY_APP_CALCULATOR:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR;
+ case Intent.CATEGORY_APP_MUSIC:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC;
+ case Intent.CATEGORY_APP_MAPS:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS;
+ case Intent.CATEGORY_APP_MESSAGING:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING;
+ case Intent.CATEGORY_APP_GALLERY:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY;
+ case Intent.CATEGORY_APP_FILES:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES;
+ case Intent.CATEGORY_APP_WEATHER:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER;
+ case Intent.CATEGORY_APP_FITNESS:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS;
+ default:
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED;
+ }
+ }
+
+ /**
+ * Find KeyboardLogEvent corresponding to the provide system role name.
+ * Returns {@code null} if no matching event found.
+ */
+ @KeyboardSystemShortcut.SystemShortcut
+ private static int getLogEventFromRole(String role) {
+ if (RoleManager.ROLE_BROWSER.equals(role)) {
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER;
+ } else if (RoleManager.ROLE_SMS.equals(role)) {
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING;
+ } else {
+ Log.w(TAG, "Keyboard shortcut to launch "
+ + role + " not supported for logging");
+ return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED;
+ }
+ }
+
void dump(String prefix, PrintWriter pw) {
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", prefix);
ipw.println("ModifierShortcutManager shortcuts:");
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 4ddc8a5700aa..720c1c201158 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -139,6 +139,7 @@ import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
import android.hardware.input.InputManager;
+import android.hardware.input.KeyboardSystemShortcut;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioSystem;
@@ -227,8 +228,6 @@ import com.android.server.LocalServices;
import com.android.server.SystemServiceManager;
import com.android.server.UiThread;
import com.android.server.input.InputManagerInternal;
-import com.android.server.input.KeyboardMetricsCollector;
-import com.android.server.input.KeyboardMetricsCollector.KeyboardLogEvent;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.pm.UserManagerInternal;
import com.android.server.policy.KeyCombinationManager.TwoKeysCombinationRule;
@@ -732,7 +731,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private static final int MSG_LAUNCH_ASSIST = 23;
private static final int MSG_RINGER_TOGGLE_CHORD = 24;
private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 25;
- private static final int MSG_LOG_KEYBOARD_SYSTEM_EVENT = 26;
private static final int MSG_SET_DEFERRED_KEY_ACTIONS_EXECUTABLE = 27;
private class PolicyHandler extends Handler {
@@ -820,9 +818,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
handleSwitchKeyboardLayout(object.keyEvent, object.direction,
object.focusedToken);
break;
- case MSG_LOG_KEYBOARD_SYSTEM_EVENT:
- handleKeyboardSystemEvent(KeyboardLogEvent.from(msg.arg1), (KeyEvent) msg.obj);
- break;
case MSG_SET_DEFERRED_KEY_ACTIONS_EXECUTABLE:
final int keyCode = msg.arg1;
final long downTime = (Long) msg.obj;
@@ -1824,7 +1819,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private void handleShortPressOnHome(KeyEvent event) {
- logKeyboardSystemsEvent(event, KeyboardLogEvent.HOME);
+ notifyKeyboardShortcutTriggered(event, KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME);
// Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
final HdmiControl hdmiControl = getHdmiControl();
@@ -2058,7 +2053,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
switch (mDoubleTapOnHomeBehavior) {
case DOUBLE_TAP_HOME_RECENT_SYSTEM_UI:
- logKeyboardSystemsEvent(event, KeyboardLogEvent.APP_SWITCH);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH);
mHomeConsumed = true;
toggleRecentApps();
break;
@@ -2086,19 +2082,23 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case LONG_PRESS_HOME_ALL_APPS:
if (mHasFeatureLeanback) {
launchAllAppsAction();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.ALL_APPS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_ALL_APPS);
} else {
launchAllAppsViaA11y();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.ACCESSIBILITY_ALL_APPS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS);
}
break;
case LONG_PRESS_HOME_ASSIST:
- logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_ASSISTANT);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT);
launchAssistAction(null, event.getDeviceId(), event.getEventTime(),
AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
break;
case LONG_PRESS_HOME_NOTIFICATION_PANEL:
- logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL);
toggleNotificationPanel();
break;
default:
@@ -3285,39 +3285,29 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
};
- /**
- * Log the keyboard shortcuts without blocking the current thread.
- *
- * We won't log keyboard events when the input device is null
- * or when it is virtual.
- */
- private void handleKeyboardSystemEvent(KeyboardLogEvent keyboardLogEvent, KeyEvent event) {
- final InputDevice inputDevice = mInputManager.getInputDevice(event.getDeviceId());
- KeyboardMetricsCollector.logKeyboardSystemsEventReportedAtom(inputDevice,
- keyboardLogEvent, event.getMetaState(), event.getKeyCode());
- event.recycle();
- }
-
- private void logKeyboardSystemsEventOnActionUp(KeyEvent event,
- KeyboardLogEvent keyboardSystemEvent) {
+ private void notifyKeyboardShortcutTriggeredOnActionUp(KeyEvent event,
+ @KeyboardSystemShortcut.SystemShortcut int systemShortcut) {
if (event.getAction() != KeyEvent.ACTION_UP) {
return;
}
- logKeyboardSystemsEvent(event, keyboardSystemEvent);
+ notifyKeyboardShortcutTriggered(event, systemShortcut);
}
- private void logKeyboardSystemsEventOnActionDown(KeyEvent event,
- KeyboardLogEvent keyboardSystemEvent) {
+ private void notifyKeyboardShortcutTriggeredOnActionDown(KeyEvent event,
+ @KeyboardSystemShortcut.SystemShortcut int systemShortcut) {
if (event.getAction() != KeyEvent.ACTION_DOWN) {
return;
}
- logKeyboardSystemsEvent(event, keyboardSystemEvent);
+ notifyKeyboardShortcutTriggered(event, systemShortcut);
}
- private void logKeyboardSystemsEvent(KeyEvent event, KeyboardLogEvent keyboardSystemEvent) {
- KeyEvent eventToLog = KeyEvent.obtain(event);
- mHandler.obtainMessage(MSG_LOG_KEYBOARD_SYSTEM_EVENT, keyboardSystemEvent.getIntValue(), 0,
- eventToLog).sendToTarget();
+ private void notifyKeyboardShortcutTriggered(KeyEvent event,
+ @KeyboardSystemShortcut.SystemShortcut int systemShortcut) {
+ if (systemShortcut == KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED) {
+ return;
+ }
+ mInputManagerInternal.notifyKeyboardShortcutTriggered(event.getDeviceId(),
+ new int[]{event.getKeyCode()}, event.getMetaState(), systemShortcut);
}
@Override
@@ -3427,7 +3417,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_RECENT_APPS:
if (firstDown) {
showRecentApps(false /* triggeredFromAltTab */);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS);
}
return true;
case KeyEvent.KEYCODE_APP_SWITCH:
@@ -3436,7 +3427,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
preloadRecentApps();
} else if (!down) {
toggleRecentApps();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.APP_SWITCH);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH);
}
}
return true;
@@ -3445,7 +3437,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD,
deviceId, event.getEventTime(),
AssistUtils.INVOCATION_TYPE_UNKNOWN);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_ASSISTANT);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT);
return true;
}
break;
@@ -3458,14 +3451,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_I:
if (firstDown && event.isMetaPressed()) {
showSystemSettings();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_SYSTEM_SETTINGS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS);
return true;
}
break;
case KeyEvent.KEYCODE_L:
if (firstDown && event.isMetaPressed()) {
lockNow(null /* options */);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.LOCK_SCREEN);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LOCK_SCREEN);
return true;
}
break;
@@ -3473,10 +3468,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (firstDown && event.isMetaPressed()) {
if (event.isCtrlPressed()) {
sendSystemKeyToStatusBarAsync(event);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.OPEN_NOTES);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_NOTES);
} else {
toggleNotificationPanel();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL);
}
return true;
}
@@ -3484,7 +3481,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_S:
if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.TAKE_SCREENSHOT);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TAKE_SCREENSHOT);
return true;
}
break;
@@ -3497,14 +3495,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} catch (RemoteException e) {
Slog.d(TAG, "Error taking bugreport", e);
}
- logKeyboardSystemsEvent(event, KeyboardLogEvent.TRIGGER_BUG_REPORT);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT);
return true;
}
}
// fall through
case KeyEvent.KEYCODE_ESCAPE:
if (firstDown && event.isMetaPressed()) {
- logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK);
injectBackGesture(event.getDownTime());
return true;
}
@@ -3513,7 +3513,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
if (statusbar != null) {
statusbar.moveFocusedTaskToFullscreen(getTargetDisplayIdForKeyEvent(event));
- logKeyboardSystemsEvent(event, KeyboardLogEvent.MULTI_WINDOW_NAVIGATION);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION);
return true;
}
}
@@ -3523,7 +3524,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
if (statusbar != null) {
statusbar.moveFocusedTaskToDesktop(getTargetDisplayIdForKeyEvent(event));
- logKeyboardSystemsEvent(event, KeyboardLogEvent.DESKTOP_MODE);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_DESKTOP_MODE);
return true;
}
}
@@ -3533,12 +3535,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (event.isCtrlPressed()) {
moveFocusedTaskToStageSplit(getTargetDisplayIdForKeyEvent(event),
true /* leftOrTop */);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION);
} else if (event.isAltPressed()) {
setSplitscreenFocus(true /* leftOrTop */);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.CHANGE_SPLITSCREEN_FOCUS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS);
} else {
- logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK);
injectBackGesture(event.getDownTime());
}
return true;
@@ -3549,11 +3554,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (event.isCtrlPressed()) {
moveFocusedTaskToStageSplit(getTargetDisplayIdForKeyEvent(event),
false /* leftOrTop */);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION);
return true;
} else if (event.isAltPressed()) {
setSplitscreenFocus(false /* leftOrTop */);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.CHANGE_SPLITSCREEN_FOCUS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS);
return true;
}
}
@@ -3561,7 +3568,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_SLASH:
if (firstDown && event.isMetaPressed() && !keyguardOn) {
toggleKeyboardShortcutsMenu(event.getDeviceId());
- logKeyboardSystemsEvent(event, KeyboardLogEvent.OPEN_SHORTCUT_HELPER);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER);
return true;
}
break;
@@ -3613,25 +3621,32 @@ public class PhoneWindowManager implements WindowManagerPolicy {
| Intent.FLAG_ACTIVITY_NO_USER_ACTION);
intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true);
startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.getBrightnessEvent(keyCode));
+
+ int systemShortcut = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN
+ ? KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_DOWN
+ : KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_UP;
+ notifyKeyboardShortcutTriggered(event, systemShortcut);
}
return true;
case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN:
if (down) {
mInputManagerInternal.decrementKeyboardBacklight(event.getDeviceId());
- logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_DOWN);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN);
}
return true;
case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP:
if (down) {
mInputManagerInternal.incrementKeyboardBacklight(event.getDeviceId());
- logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_UP);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP);
}
return true;
case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE:
// TODO: Add logic
if (!down) {
- logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_TOGGLE);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE);
}
return true;
case KeyEvent.KEYCODE_VOLUME_UP:
@@ -3658,7 +3673,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (firstDown && !keyguardOn && isUserSetupComplete()) {
if (event.isMetaPressed()) {
showRecentApps(false);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS);
return true;
} else if (mRecentAppsHeldModifiers == 0) {
final int shiftlessModifiers =
@@ -3667,7 +3683,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
shiftlessModifiers, KeyEvent.META_ALT_ON)) {
mRecentAppsHeldModifiers = shiftlessModifiers;
showRecentApps(true);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS);
return true;
}
}
@@ -3680,17 +3697,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);
msg.setAsynchronous(true);
msg.sendToTarget();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.ALL_APPS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_ALL_APPS);
} else {
launchAllAppsViaA11y();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.ACCESSIBILITY_ALL_APPS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS);
}
}
return true;
case KeyEvent.KEYCODE_NOTIFICATION:
if (!down) {
toggleNotificationPanel();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL);
}
return true;
case KeyEvent.KEYCODE_SEARCH:
@@ -3698,7 +3718,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
switch (mSearchKeyBehavior) {
case SEARCH_KEY_BEHAVIOR_TARGET_ACTIVITY: {
launchTargetSearchActivity();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_SEARCH);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SEARCH);
return true;
}
case SEARCH_KEY_BEHAVIOR_DEFAULT_SEARCH:
@@ -3711,7 +3732,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (firstDown) {
int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
sendSwitchKeyboardLayout(event, focusedToken, direction);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.LANGUAGE_SWITCH);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LANGUAGE_SWITCH);
return true;
}
break;
@@ -3730,11 +3752,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mPendingCapsLockToggle) {
mInputManagerInternal.toggleCapsLock(event.getDeviceId());
mPendingCapsLockToggle = false;
- logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK);
} else if (mPendingMetaAction) {
if (!canceled) {
launchAllAppsViaA11y();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.ACCESSIBILITY_ALL_APPS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS);
}
mPendingMetaAction = false;
}
@@ -3762,14 +3786,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mPendingCapsLockToggle) {
mInputManagerInternal.toggleCapsLock(event.getDeviceId());
mPendingCapsLockToggle = false;
- logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK);
return true;
}
}
break;
case KeyEvent.KEYCODE_CAPS_LOCK:
if (!down) {
- logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK);
}
break;
case KeyEvent.KEYCODE_STYLUS_BUTTON_PRIMARY:
@@ -3783,10 +3809,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (firstDown) {
if (mSettingsKeyBehavior == SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL) {
toggleNotificationPanel();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL);
} else if (mSettingsKeyBehavior == SETTINGS_KEY_BEHAVIOR_SETTINGS_ACTIVITY) {
showSystemSettings();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_SYSTEM_SETTINGS);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS);
}
}
return true;
@@ -4732,7 +4760,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Handle special keys.
switch (keyCode) {
case KeyEvent.KEYCODE_BACK: {
- logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.BACK);
+ notifyKeyboardShortcutTriggeredOnActionUp(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK);
if (down) {
// There may have other embedded activities on the same Task. Try to move the
// focus before processing the back event.
@@ -4753,8 +4782,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
- logKeyboardSystemsEventOnActionDown(event,
- KeyboardLogEvent.getVolumeEvent(keyCode));
+ int systemShortcut = keyCode == KEYCODE_VOLUME_DOWN
+ ? KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_DOWN
+ : keyCode == KEYCODE_VOLUME_UP
+ ? KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_UP
+ : KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_MUTE;
+ notifyKeyboardShortcutTriggeredOnActionDown(event, systemShortcut);
if (down) {
sendSystemKeyToStatusBarAsync(event);
@@ -4855,7 +4888,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
case KeyEvent.KEYCODE_TV_POWER: {
- logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.TOGGLE_POWER);
+ notifyKeyboardShortcutTriggeredOnActionUp(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER);
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down && hdmiControlManager != null) {
@@ -4865,7 +4899,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
case KeyEvent.KEYCODE_POWER: {
- logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.TOGGLE_POWER);
+ notifyKeyboardShortcutTriggeredOnActionUp(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER);
EventLogTags.writeInterceptPower(
KeyEvent.actionToString(event.getAction()),
mPowerKeyHandled ? 1 : 0,
@@ -4888,14 +4923,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
// fall through
case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
- logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.SYSTEM_NAVIGATION);
+ notifyKeyboardShortcutTriggeredOnActionUp(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION);
result &= ~ACTION_PASS_TO_USER;
interceptSystemNavigationKey(event);
break;
}
case KeyEvent.KEYCODE_SLEEP: {
- logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.SLEEP);
+ notifyKeyboardShortcutTriggeredOnActionUp(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP);
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false;
if (!mPowerManager.isInteractive()) {
@@ -4911,7 +4948,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
case KeyEvent.KEYCODE_SOFT_SLEEP: {
- logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.SLEEP);
+ notifyKeyboardShortcutTriggeredOnActionUp(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP);
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false;
if (!down) {
@@ -4922,7 +4960,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
case KeyEvent.KEYCODE_WAKEUP: {
- logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.WAKEUP);
+ notifyKeyboardShortcutTriggeredOnActionUp(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_WAKEUP);
result &= ~ACTION_PASS_TO_USER;
isWakeKey = true;
break;
@@ -4931,7 +4970,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_MUTE:
result &= ~ACTION_PASS_TO_USER;
if (down && event.getRepeatCount() == 0) {
- logKeyboardSystemsEvent(event, KeyboardLogEvent.SYSTEM_MUTE);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_MUTE);
toggleMicrophoneMuteFromKey();
}
break;
@@ -4946,7 +4986,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_MEDIA_RECORD:
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
- logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.MEDIA_KEY);
+ notifyKeyboardShortcutTriggeredOnActionUp(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY);
if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
// If the global session is active pass all media keys to it
// instead of the active window.
@@ -4991,7 +5032,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
0 /* unused */, event.getEventTime() /* eventTime */);
msg.setAsynchronous(true);
msg.sendToTarget();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_ASSISTANT);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT);
}
result &= ~ACTION_PASS_TO_USER;
break;
@@ -5002,7 +5044,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK);
msg.setAsynchronous(true);
msg.sendToTarget();
- logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_VOICE_ASSISTANT);
+ notifyKeyboardShortcutTriggered(event,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT);
}
result &= ~ACTION_PASS_TO_USER;
break;
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyboardSystemShortcutTests.java
index aa28147a3973..e26f3e0f699a 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/KeyboardSystemShortcutTests.java
@@ -22,6 +22,7 @@ import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_HOME_ASSIS
import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_HOME_NOTIFICATION_PANEL;
import static com.android.server.policy.PhoneWindowManager.SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL;
+import android.hardware.input.KeyboardSystemShortcut;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
@@ -31,7 +32,6 @@ import android.view.KeyEvent;
import androidx.test.filters.MediumTest;
import com.android.internal.annotations.Keep;
-import com.android.server.input.KeyboardMetricsCollector.KeyboardLogEvent;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
@@ -44,15 +44,12 @@ import org.junit.runner.RunWith;
@Presubmit
@MediumTest
@RunWith(JUnitParamsRunner.class)
-public class ShortcutLoggingTests extends ShortcutKeyTestBase {
+public class KeyboardSystemShortcutTests extends ShortcutKeyTestBase {
@Rule
public final CheckFlagsRule mCheckFlagsRule =
DeviceFlagsValueProvider.createCheckFlagsRule();
- private static final int VENDOR_ID = 0x123;
- private static final int PRODUCT_ID = 0x456;
- private static final int DEVICE_BUS = 0x789;
private static final int META_KEY = KeyEvent.KEYCODE_META_LEFT;
private static final int META_ON = MODIFIER.get(KeyEvent.KEYCODE_META_LEFT);
private static final int ALT_KEY = KeyEvent.KEYCODE_ALT_LEFT;
@@ -64,245 +61,316 @@ public class ShortcutLoggingTests extends ShortcutKeyTestBase {
@Keep
private static Object[][] shortcutTestArguments() {
- // testName, testKeys, expectedLogEvent, expectedKey, expectedModifierState
+ // testName, testKeys, expectedSystemShortcut, expectedKey, expectedModifierState
return new Object[][]{
{"Meta + H -> Open Home", new int[]{META_KEY, KeyEvent.KEYCODE_H},
- KeyboardLogEvent.HOME, KeyEvent.KEYCODE_H, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME, KeyEvent.KEYCODE_H, META_ON},
{"Meta + Enter -> Open Home", new int[]{META_KEY, KeyEvent.KEYCODE_ENTER},
- KeyboardLogEvent.HOME, KeyEvent.KEYCODE_ENTER, META_ON},
- {"HOME key -> Open Home", new int[]{KeyEvent.KEYCODE_HOME}, KeyboardLogEvent.HOME,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME, KeyEvent.KEYCODE_ENTER,
+ META_ON},
+ {"HOME key -> Open Home", new int[]{KeyEvent.KEYCODE_HOME},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME,
KeyEvent.KEYCODE_HOME, 0},
{"RECENT_APPS key -> Open Overview", new int[]{KeyEvent.KEYCODE_RECENT_APPS},
- KeyboardLogEvent.RECENT_APPS, KeyEvent.KEYCODE_RECENT_APPS, 0},
- {"Meta + Tab -> Open OVerview", new int[]{META_KEY, KeyEvent.KEYCODE_TAB},
- KeyboardLogEvent.RECENT_APPS, KeyEvent.KEYCODE_TAB, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS,
+ KeyEvent.KEYCODE_RECENT_APPS, 0},
+ {"Meta + Tab -> Open Overview", new int[]{META_KEY, KeyEvent.KEYCODE_TAB},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS, KeyEvent.KEYCODE_TAB,
+ META_ON},
{"Alt + Tab -> Open Overview", new int[]{ALT_KEY, KeyEvent.KEYCODE_TAB},
- KeyboardLogEvent.RECENT_APPS, KeyEvent.KEYCODE_TAB, ALT_ON},
- {"BACK key -> Go back", new int[]{KeyEvent.KEYCODE_BACK}, KeyboardLogEvent.BACK,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS, KeyEvent.KEYCODE_TAB,
+ ALT_ON},
+ {"BACK key -> Go back", new int[]{KeyEvent.KEYCODE_BACK},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK,
KeyEvent.KEYCODE_BACK, 0},
{"Meta + Escape -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_ESCAPE},
- KeyboardLogEvent.BACK, KeyEvent.KEYCODE_ESCAPE, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK, KeyEvent.KEYCODE_ESCAPE,
+ META_ON},
{"Meta + Left arrow -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DPAD_LEFT},
- KeyboardLogEvent.BACK, KeyEvent.KEYCODE_DPAD_LEFT, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK, KeyEvent.KEYCODE_DPAD_LEFT,
+ META_ON},
{"Meta + Del -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DEL},
- KeyboardLogEvent.BACK, KeyEvent.KEYCODE_DEL, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK, KeyEvent.KEYCODE_DEL, META_ON},
{"APP_SWITCH key -> Open App switcher", new int[]{KeyEvent.KEYCODE_APP_SWITCH},
- KeyboardLogEvent.APP_SWITCH, KeyEvent.KEYCODE_APP_SWITCH, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH,
+ KeyEvent.KEYCODE_APP_SWITCH, 0},
{"ASSIST key -> Launch assistant", new int[]{KeyEvent.KEYCODE_ASSIST},
- KeyboardLogEvent.LAUNCH_ASSISTANT, KeyEvent.KEYCODE_ASSIST, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT,
+ KeyEvent.KEYCODE_ASSIST, 0},
{"Meta + A -> Launch assistant", new int[]{META_KEY, KeyEvent.KEYCODE_A},
- KeyboardLogEvent.LAUNCH_ASSISTANT, KeyEvent.KEYCODE_A, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_A,
+ META_ON},
{"VOICE_ASSIST key -> Launch Voice Assistant",
new int[]{KeyEvent.KEYCODE_VOICE_ASSIST},
- KeyboardLogEvent.LAUNCH_VOICE_ASSISTANT, KeyEvent.KEYCODE_VOICE_ASSIST, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT,
+ KeyEvent.KEYCODE_VOICE_ASSIST, 0},
{"Meta + I -> Launch System Settings", new int[]{META_KEY, KeyEvent.KEYCODE_I},
- KeyboardLogEvent.LAUNCH_SYSTEM_SETTINGS, KeyEvent.KEYCODE_I, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS,
+ KeyEvent.KEYCODE_I, META_ON},
{"Meta + N -> Toggle Notification panel", new int[]{META_KEY, KeyEvent.KEYCODE_N},
- KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_N, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyEvent.KEYCODE_N, META_ON},
{"NOTIFICATION key -> Toggle Notification Panel",
new int[]{KeyEvent.KEYCODE_NOTIFICATION},
- KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_NOTIFICATION,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyEvent.KEYCODE_NOTIFICATION,
0},
{"Meta + Ctrl + S -> Take Screenshot",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_S},
- KeyboardLogEvent.TAKE_SCREENSHOT, KeyEvent.KEYCODE_S, META_ON | CTRL_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TAKE_SCREENSHOT, KeyEvent.KEYCODE_S,
+ META_ON | CTRL_ON},
{"Meta + / -> Open Shortcut Helper", new int[]{META_KEY, KeyEvent.KEYCODE_SLASH},
- KeyboardLogEvent.OPEN_SHORTCUT_HELPER, KeyEvent.KEYCODE_SLASH, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER,
+ KeyEvent.KEYCODE_SLASH, META_ON},
{"BRIGHTNESS_UP key -> Increase Brightness",
- new int[]{KeyEvent.KEYCODE_BRIGHTNESS_UP}, KeyboardLogEvent.BRIGHTNESS_UP,
+ new int[]{KeyEvent.KEYCODE_BRIGHTNESS_UP},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_UP,
KeyEvent.KEYCODE_BRIGHTNESS_UP, 0},
{"BRIGHTNESS_DOWN key -> Decrease Brightness",
new int[]{KeyEvent.KEYCODE_BRIGHTNESS_DOWN},
- KeyboardLogEvent.BRIGHTNESS_DOWN, KeyEvent.KEYCODE_BRIGHTNESS_DOWN, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_DOWN,
+ KeyEvent.KEYCODE_BRIGHTNESS_DOWN, 0},
{"KEYBOARD_BACKLIGHT_UP key -> Increase Keyboard Backlight",
new int[]{KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP},
- KeyboardLogEvent.KEYBOARD_BACKLIGHT_UP,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP,
KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP, 0},
{"KEYBOARD_BACKLIGHT_DOWN key -> Decrease Keyboard Backlight",
new int[]{KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN},
- KeyboardLogEvent.KEYBOARD_BACKLIGHT_DOWN,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN,
KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN, 0},
{"KEYBOARD_BACKLIGHT_TOGGLE key -> Toggle Keyboard Backlight",
new int[]{KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE},
- KeyboardLogEvent.KEYBOARD_BACKLIGHT_TOGGLE,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE,
KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE, 0},
{"VOLUME_UP key -> Increase Volume", new int[]{KeyEvent.KEYCODE_VOLUME_UP},
- KeyboardLogEvent.VOLUME_UP, KeyEvent.KEYCODE_VOLUME_UP, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_UP,
+ KeyEvent.KEYCODE_VOLUME_UP, 0},
{"VOLUME_DOWN key -> Decrease Volume", new int[]{KeyEvent.KEYCODE_VOLUME_DOWN},
- KeyboardLogEvent.VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_DOWN, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_DOWN,
+ KeyEvent.KEYCODE_VOLUME_DOWN, 0},
{"VOLUME_MUTE key -> Mute Volume", new int[]{KeyEvent.KEYCODE_VOLUME_MUTE},
- KeyboardLogEvent.VOLUME_MUTE, KeyEvent.KEYCODE_VOLUME_MUTE, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_MUTE,
+ KeyEvent.KEYCODE_VOLUME_MUTE, 0},
{"ALL_APPS key -> Open App Drawer in Accessibility mode",
new int[]{KeyEvent.KEYCODE_ALL_APPS},
- KeyboardLogEvent.ACCESSIBILITY_ALL_APPS, KeyEvent.KEYCODE_ALL_APPS, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS,
+ KeyEvent.KEYCODE_ALL_APPS, 0},
{"SEARCH key -> Launch Search Activity", new int[]{KeyEvent.KEYCODE_SEARCH},
- KeyboardLogEvent.LAUNCH_SEARCH, KeyEvent.KEYCODE_SEARCH, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SEARCH,
+ KeyEvent.KEYCODE_SEARCH, 0},
{"LANGUAGE_SWITCH key -> Switch Keyboard Language",
new int[]{KeyEvent.KEYCODE_LANGUAGE_SWITCH},
- KeyboardLogEvent.LANGUAGE_SWITCH, KeyEvent.KEYCODE_LANGUAGE_SWITCH, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LANGUAGE_SWITCH,
+ KeyEvent.KEYCODE_LANGUAGE_SWITCH, 0},
{"META key -> Open App Drawer in Accessibility mode", new int[]{META_KEY},
- KeyboardLogEvent.ACCESSIBILITY_ALL_APPS, META_KEY, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS, META_KEY,
+ META_ON},
{"Meta + Alt -> Toggle CapsLock", new int[]{META_KEY, ALT_KEY},
- KeyboardLogEvent.TOGGLE_CAPS_LOCK, ALT_KEY, META_ON | ALT_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK, ALT_KEY,
+ META_ON | ALT_ON},
{"Alt + Meta -> Toggle CapsLock", new int[]{ALT_KEY, META_KEY},
- KeyboardLogEvent.TOGGLE_CAPS_LOCK, META_KEY, META_ON | ALT_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK, META_KEY,
+ META_ON | ALT_ON},
{"CAPS_LOCK key -> Toggle CapsLock", new int[]{KeyEvent.KEYCODE_CAPS_LOCK},
- KeyboardLogEvent.TOGGLE_CAPS_LOCK, KeyEvent.KEYCODE_CAPS_LOCK, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK,
+ KeyEvent.KEYCODE_CAPS_LOCK, 0},
{"MUTE key -> Mute System Microphone", new int[]{KeyEvent.KEYCODE_MUTE},
- KeyboardLogEvent.SYSTEM_MUTE, KeyEvent.KEYCODE_MUTE, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_MUTE, KeyEvent.KEYCODE_MUTE,
+ 0},
{"Meta + Ctrl + DPAD_UP -> Split screen navigation",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_UP},
- KeyboardLogEvent.MULTI_WINDOW_NAVIGATION, KeyEvent.KEYCODE_DPAD_UP,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION,
+ KeyEvent.KEYCODE_DPAD_UP,
META_ON | CTRL_ON},
{"Meta + Ctrl + DPAD_LEFT -> Split screen navigation",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_LEFT},
- KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION, KeyEvent.KEYCODE_DPAD_LEFT,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION,
+ KeyEvent.KEYCODE_DPAD_LEFT,
META_ON | CTRL_ON},
{"Meta + Ctrl + DPAD_RIGHT -> Split screen navigation",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_RIGHT},
- KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION, KeyEvent.KEYCODE_DPAD_RIGHT,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION,
+ KeyEvent.KEYCODE_DPAD_RIGHT,
META_ON | CTRL_ON},
{"Meta + L -> Lock Homescreen", new int[]{META_KEY, KeyEvent.KEYCODE_L},
- KeyboardLogEvent.LOCK_SCREEN, KeyEvent.KEYCODE_L, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LOCK_SCREEN, KeyEvent.KEYCODE_L,
+ META_ON},
{"Meta + Ctrl + N -> Open Notes", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_N},
- KeyboardLogEvent.OPEN_NOTES, KeyEvent.KEYCODE_N, META_ON | CTRL_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_NOTES, KeyEvent.KEYCODE_N,
+ META_ON | CTRL_ON},
{"POWER key -> Toggle Power", new int[]{KeyEvent.KEYCODE_POWER},
- KeyboardLogEvent.TOGGLE_POWER, KeyEvent.KEYCODE_POWER, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER, KeyEvent.KEYCODE_POWER,
+ 0},
{"TV_POWER key -> Toggle Power", new int[]{KeyEvent.KEYCODE_TV_POWER},
- KeyboardLogEvent.TOGGLE_POWER, KeyEvent.KEYCODE_TV_POWER, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER,
+ KeyEvent.KEYCODE_TV_POWER, 0},
{"SYSTEM_NAVIGATION_DOWN key -> System Navigation",
new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN},
- KeyboardLogEvent.SYSTEM_NAVIGATION, KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION,
+ KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN,
0},
{"SYSTEM_NAVIGATION_UP key -> System Navigation",
new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP},
- KeyboardLogEvent.SYSTEM_NAVIGATION, KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION,
+ KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP,
0},
{"SYSTEM_NAVIGATION_LEFT key -> System Navigation",
new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT},
- KeyboardLogEvent.SYSTEM_NAVIGATION, KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION,
+ KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT,
0},
{"SYSTEM_NAVIGATION_RIGHT key -> System Navigation",
new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT},
- KeyboardLogEvent.SYSTEM_NAVIGATION,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION,
KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT, 0},
{"SLEEP key -> System Sleep", new int[]{KeyEvent.KEYCODE_SLEEP},
- KeyboardLogEvent.SLEEP, KeyEvent.KEYCODE_SLEEP, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP, KeyEvent.KEYCODE_SLEEP, 0},
{"SOFT_SLEEP key -> System Sleep", new int[]{KeyEvent.KEYCODE_SOFT_SLEEP},
- KeyboardLogEvent.SLEEP, KeyEvent.KEYCODE_SOFT_SLEEP, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP, KeyEvent.KEYCODE_SOFT_SLEEP,
+ 0},
{"WAKEUP key -> System Wakeup", new int[]{KeyEvent.KEYCODE_WAKEUP},
- KeyboardLogEvent.WAKEUP, KeyEvent.KEYCODE_WAKEUP, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_WAKEUP, KeyEvent.KEYCODE_WAKEUP, 0},
{"MEDIA_PLAY key -> Media Control", new int[]{KeyEvent.KEYCODE_MEDIA_PLAY},
- KeyboardLogEvent.MEDIA_KEY, KeyEvent.KEYCODE_MEDIA_PLAY, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY,
+ KeyEvent.KEYCODE_MEDIA_PLAY, 0},
{"MEDIA_PAUSE key -> Media Control", new int[]{KeyEvent.KEYCODE_MEDIA_PAUSE},
- KeyboardLogEvent.MEDIA_KEY, KeyEvent.KEYCODE_MEDIA_PAUSE, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY,
+ KeyEvent.KEYCODE_MEDIA_PAUSE, 0},
{"MEDIA_PLAY_PAUSE key -> Media Control",
- new int[]{KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE}, KeyboardLogEvent.MEDIA_KEY,
+ new int[]{KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY,
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0},
{"Meta + B -> Launch Default Browser", new int[]{META_KEY, KeyEvent.KEYCODE_B},
- KeyboardLogEvent.LAUNCH_DEFAULT_BROWSER, KeyEvent.KEYCODE_B, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER,
+ KeyEvent.KEYCODE_B, META_ON},
{"EXPLORER key -> Launch Default Browser", new int[]{KeyEvent.KEYCODE_EXPLORER},
- KeyboardLogEvent.LAUNCH_DEFAULT_BROWSER, KeyEvent.KEYCODE_EXPLORER, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER,
+ KeyEvent.KEYCODE_EXPLORER, 0},
{"Meta + C -> Launch Default Contacts", new int[]{META_KEY, KeyEvent.KEYCODE_C},
- KeyboardLogEvent.LAUNCH_DEFAULT_CONTACTS, KeyEvent.KEYCODE_C, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS,
+ KeyEvent.KEYCODE_C, META_ON},
{"CONTACTS key -> Launch Default Contacts", new int[]{KeyEvent.KEYCODE_CONTACTS},
- KeyboardLogEvent.LAUNCH_DEFAULT_CONTACTS, KeyEvent.KEYCODE_CONTACTS, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS,
+ KeyEvent.KEYCODE_CONTACTS, 0},
{"Meta + E -> Launch Default Email", new int[]{META_KEY, KeyEvent.KEYCODE_E},
- KeyboardLogEvent.LAUNCH_DEFAULT_EMAIL, KeyEvent.KEYCODE_E, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL,
+ KeyEvent.KEYCODE_E, META_ON},
{"ENVELOPE key -> Launch Default Email", new int[]{KeyEvent.KEYCODE_ENVELOPE},
- KeyboardLogEvent.LAUNCH_DEFAULT_EMAIL, KeyEvent.KEYCODE_ENVELOPE, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL,
+ KeyEvent.KEYCODE_ENVELOPE, 0},
{"Meta + K -> Launch Default Calendar", new int[]{META_KEY, KeyEvent.KEYCODE_K},
- KeyboardLogEvent.LAUNCH_DEFAULT_CALENDAR, KeyEvent.KEYCODE_K, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR,
+ KeyEvent.KEYCODE_K, META_ON},
{"CALENDAR key -> Launch Default Calendar", new int[]{KeyEvent.KEYCODE_CALENDAR},
- KeyboardLogEvent.LAUNCH_DEFAULT_CALENDAR, KeyEvent.KEYCODE_CALENDAR, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR,
+ KeyEvent.KEYCODE_CALENDAR, 0},
{"Meta + P -> Launch Default Music", new int[]{META_KEY, KeyEvent.KEYCODE_P},
- KeyboardLogEvent.LAUNCH_DEFAULT_MUSIC, KeyEvent.KEYCODE_P, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC,
+ KeyEvent.KEYCODE_P, META_ON},
{"MUSIC key -> Launch Default Music", new int[]{KeyEvent.KEYCODE_MUSIC},
- KeyboardLogEvent.LAUNCH_DEFAULT_MUSIC, KeyEvent.KEYCODE_MUSIC, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC,
+ KeyEvent.KEYCODE_MUSIC, 0},
{"Meta + U -> Launch Default Calculator", new int[]{META_KEY, KeyEvent.KEYCODE_U},
- KeyboardLogEvent.LAUNCH_DEFAULT_CALCULATOR, KeyEvent.KEYCODE_U, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR,
+ KeyEvent.KEYCODE_U, META_ON},
{"CALCULATOR key -> Launch Default Calculator",
new int[]{KeyEvent.KEYCODE_CALCULATOR},
- KeyboardLogEvent.LAUNCH_DEFAULT_CALCULATOR, KeyEvent.KEYCODE_CALCULATOR, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR,
+ KeyEvent.KEYCODE_CALCULATOR, 0},
{"Meta + M -> Launch Default Maps", new int[]{META_KEY, KeyEvent.KEYCODE_M},
- KeyboardLogEvent.LAUNCH_DEFAULT_MAPS, KeyEvent.KEYCODE_M, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS,
+ KeyEvent.KEYCODE_M, META_ON},
{"Meta + S -> Launch Default Messaging App",
new int[]{META_KEY, KeyEvent.KEYCODE_S},
- KeyboardLogEvent.LAUNCH_DEFAULT_MESSAGING, KeyEvent.KEYCODE_S, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING,
+ KeyEvent.KEYCODE_S, META_ON},
{"Meta + Ctrl + DPAD_DOWN -> Enter desktop mode",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_DOWN},
- KeyboardLogEvent.DESKTOP_MODE, KeyEvent.KEYCODE_DPAD_DOWN,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_DESKTOP_MODE,
+ KeyEvent.KEYCODE_DPAD_DOWN,
META_ON | CTRL_ON}};
}
@Keep
private static Object[][] longPressOnHomeTestArguments() {
- // testName, testKeys, longPressOnHomeBehavior, expectedLogEvent, expectedKey,
+ // testName, testKeys, longPressOnHomeBehavior, expectedSystemShortcut, expectedKey,
// expectedModifierState
return new Object[][]{
{"Long press HOME key -> Toggle Notification panel",
new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_NOTIFICATION_PANEL,
- KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_HOME, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyEvent.KEYCODE_HOME, 0},
{"Long press META + ENTER -> Toggle Notification panel",
new int[]{META_KEY, KeyEvent.KEYCODE_ENTER},
LONG_PRESS_HOME_NOTIFICATION_PANEL,
- KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_ENTER,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyEvent.KEYCODE_ENTER,
META_ON},
{"Long press META + H -> Toggle Notification panel",
new int[]{META_KEY, KeyEvent.KEYCODE_H}, LONG_PRESS_HOME_NOTIFICATION_PANEL,
- KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_H, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyEvent.KEYCODE_H, META_ON},
{"Long press HOME key -> Launch assistant",
new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_ASSIST,
- KeyboardLogEvent.LAUNCH_ASSISTANT, KeyEvent.KEYCODE_HOME, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT,
+ KeyEvent.KEYCODE_HOME, 0},
{"Long press META + ENTER -> Launch assistant",
new int[]{META_KEY, KeyEvent.KEYCODE_ENTER}, LONG_PRESS_HOME_ASSIST,
- KeyboardLogEvent.LAUNCH_ASSISTANT, KeyEvent.KEYCODE_ENTER, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT,
+ KeyEvent.KEYCODE_ENTER, META_ON},
{"Long press META + H -> Launch assistant",
new int[]{META_KEY, KeyEvent.KEYCODE_H}, LONG_PRESS_HOME_ASSIST,
- KeyboardLogEvent.LAUNCH_ASSISTANT, KeyEvent.KEYCODE_H, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_H,
+ META_ON},
{"Long press HOME key -> Open App Drawer in Accessibility mode",
new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_ALL_APPS,
- KeyboardLogEvent.ACCESSIBILITY_ALL_APPS, KeyEvent.KEYCODE_HOME, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS,
+ KeyEvent.KEYCODE_HOME, 0},
{"Long press META + ENTER -> Open App Drawer in Accessibility mode",
new int[]{META_KEY, KeyEvent.KEYCODE_ENTER}, LONG_PRESS_HOME_ALL_APPS,
- KeyboardLogEvent.ACCESSIBILITY_ALL_APPS, KeyEvent.KEYCODE_ENTER, META_ON},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS,
+ KeyEvent.KEYCODE_ENTER, META_ON},
{"Long press META + H -> Open App Drawer in Accessibility mode",
new int[]{META_KEY, KeyEvent.KEYCODE_H},
- LONG_PRESS_HOME_ALL_APPS, KeyboardLogEvent.ACCESSIBILITY_ALL_APPS,
+ LONG_PRESS_HOME_ALL_APPS,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS,
KeyEvent.KEYCODE_H, META_ON}};
}
@Keep
private static Object[][] doubleTapOnHomeTestArguments() {
- // testName, testKeys, doubleTapOnHomeBehavior, expectedLogEvent, expectedKey,
+ // testName, testKeys, doubleTapOnHomeBehavior, expectedSystemShortcut, expectedKey,
// expectedModifierState
return new Object[][]{
{"Double tap HOME -> Open App switcher",
new int[]{KeyEvent.KEYCODE_HOME}, DOUBLE_TAP_HOME_RECENT_SYSTEM_UI,
- KeyboardLogEvent.APP_SWITCH, KeyEvent.KEYCODE_HOME, 0},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH, KeyEvent.KEYCODE_HOME,
+ 0},
{"Double tap META + ENTER -> Open App switcher",
new int[]{META_KEY, KeyEvent.KEYCODE_ENTER},
- DOUBLE_TAP_HOME_RECENT_SYSTEM_UI, KeyboardLogEvent.APP_SWITCH,
+ DOUBLE_TAP_HOME_RECENT_SYSTEM_UI,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH,
KeyEvent.KEYCODE_ENTER, META_ON},
{"Double tap META + H -> Open App switcher",
new int[]{META_KEY, KeyEvent.KEYCODE_H}, DOUBLE_TAP_HOME_RECENT_SYSTEM_UI,
- KeyboardLogEvent.APP_SWITCH, KeyEvent.KEYCODE_H, META_ON}};
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH, KeyEvent.KEYCODE_H,
+ META_ON}};
}
@Keep
private static Object[][] settingsKeyTestArguments() {
- // testName, testKeys, settingsKeyBehavior, expectedLogEvent, expectedKey,
+ // testName, testKeys, settingsKeyBehavior, expectedSystemShortcut, expectedKey,
// expectedModifierState
return new Object[][]{
{"SETTINGS key -> Toggle Notification panel", new int[]{KeyEvent.KEYCODE_SETTINGS},
SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL,
- KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_SETTINGS, 0}};
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyEvent.KEYCODE_SETTINGS, 0}};
}
@Before
public void setUp() {
setUpPhoneWindowManager(/*supportSettingsUpdate*/ true);
- mPhoneWindowManager.overrideKeyEventSource(VENDOR_ID, PRODUCT_ID, DEVICE_BUS);
mPhoneWindowManager.overrideLaunchHome();
mPhoneWindowManager.overrideSearchKeyBehavior(
PhoneWindowManager.SEARCH_KEY_BEHAVIOR_TARGET_ACTIVITY);
@@ -318,56 +386,64 @@ public class ShortcutLoggingTests extends ShortcutKeyTestBase {
@Test
@Parameters(method = "shortcutTestArguments")
- public void testShortcuts(String testName, int[] testKeys, KeyboardLogEvent expectedLogEvent,
- int expectedKey, int expectedModifierState) {
- sendKeyCombination(testKeys, 0 /* duration */);
- mPhoneWindowManager.assertShortcutLogged(VENDOR_ID, PRODUCT_ID, expectedLogEvent,
- expectedKey, expectedModifierState, DEVICE_BUS,
- "Failed while executing " + testName);
+ public void testShortcut(String testName, int[] testKeys,
+ @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey,
+ int expectedModifierState) {
+ testShortcutInternal(testName, testKeys, expectedSystemShortcut, expectedKey,
+ expectedModifierState);
}
@Test
@Parameters(method = "longPressOnHomeTestArguments")
public void testLongPressOnHome(String testName, int[] testKeys, int longPressOnHomeBehavior,
- KeyboardLogEvent expectedLogEvent, int expectedKey, int expectedModifierState) {
+ @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey,
+ int expectedModifierState) {
mPhoneWindowManager.overrideLongPressOnHomeBehavior(longPressOnHomeBehavior);
sendLongPressKeyCombination(testKeys);
- mPhoneWindowManager.assertShortcutLogged(VENDOR_ID, PRODUCT_ID, expectedLogEvent,
- expectedKey, expectedModifierState, DEVICE_BUS,
+ mPhoneWindowManager.assertKeyboardShortcutTriggered(
+ new int[]{expectedKey}, expectedModifierState, expectedSystemShortcut,
"Failed while executing " + testName);
}
@Test
@Parameters(method = "doubleTapOnHomeTestArguments")
public void testDoubleTapOnHomeBehavior(String testName, int[] testKeys,
- int doubleTapOnHomeBehavior, KeyboardLogEvent expectedLogEvent, int expectedKey,
+ int doubleTapOnHomeBehavior,
+ @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey,
int expectedModifierState) {
mPhoneWindowManager.overriderDoubleTapOnHomeBehavior(doubleTapOnHomeBehavior);
sendKeyCombination(testKeys, 0 /* duration */);
sendKeyCombination(testKeys, 0 /* duration */);
- mPhoneWindowManager.assertShortcutLogged(VENDOR_ID, PRODUCT_ID, expectedLogEvent,
- expectedKey, expectedModifierState, DEVICE_BUS,
+ mPhoneWindowManager.assertKeyboardShortcutTriggered(
+ new int[]{expectedKey}, expectedModifierState, expectedSystemShortcut,
"Failed while executing " + testName);
}
@Test
@Parameters(method = "settingsKeyTestArguments")
- public void testSettingsKey(String testName, int[] testKeys,
- int settingsKeyBehavior, KeyboardLogEvent expectedLogEvent, int expectedKey,
+ public void testSettingsKey(String testName, int[] testKeys, int settingsKeyBehavior,
+ @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey,
int expectedModifierState) {
mPhoneWindowManager.overrideSettingsKeyBehavior(settingsKeyBehavior);
- sendKeyCombination(testKeys, 0 /* duration */);
- mPhoneWindowManager.assertShortcutLogged(VENDOR_ID, PRODUCT_ID, expectedLogEvent,
- expectedKey, expectedModifierState, DEVICE_BUS,
- "Failed while executing " + testName);
+ testShortcutInternal(testName, testKeys, expectedSystemShortcut, expectedKey,
+ expectedModifierState);
}
@Test
@RequiresFlagsEnabled(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
public void testBugreportShortcutPress() {
- sendKeyCombination(new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DEL}, 0);
- mPhoneWindowManager.assertShortcutLogged(VENDOR_ID, PRODUCT_ID,
- KeyboardLogEvent.TRIGGER_BUG_REPORT, KeyEvent.KEYCODE_DEL, META_ON | CTRL_ON,
- DEVICE_BUS, "Failed to log bugreport shortcut.");
+ testShortcutInternal("Meta + Ctrl + Del -> Trigger bug report",
+ new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DEL},
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT, KeyEvent.KEYCODE_DEL,
+ META_ON | CTRL_ON);
+ }
+
+ private void testShortcutInternal(String testName, int[] testKeys,
+ @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey,
+ int expectedModifierState) {
+ sendKeyCombination(testKeys, 0 /* duration */);
+ mPhoneWindowManager.assertKeyboardShortcutTriggered(
+ new int[]{expectedKey}, expectedModifierState, expectedSystemShortcut,
+ "Failed while executing " + testName);
}
}
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 6f8c91c97af4..f9b5c2a6c77f 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -26,7 +26,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyLong;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.description;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -50,6 +49,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.after;
+import static org.mockito.Mockito.description;
import static org.mockito.Mockito.mockingDetails;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.withSettings;
@@ -70,6 +70,7 @@ import android.hardware.SensorPrivacyManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.InputManager;
+import android.hardware.input.KeyboardSystemShortcut;
import android.media.AudioManagerInternal;
import android.os.Handler;
import android.os.HandlerThread;
@@ -85,7 +86,6 @@ import android.os.test.TestLooper;
import android.service.dreams.DreamManagerInternal;
import android.telecom.TelecomManager;
import android.view.Display;
-import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.autofill.AutofillManagerInternal;
@@ -93,11 +93,9 @@ import android.view.autofill.AutofillManagerInternal;
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.internal.accessibility.AccessibilityShortcutController;
import com.android.internal.policy.KeyInterceptionInfo;
-import com.android.internal.util.FrameworkStatsLog;
import com.android.server.GestureLauncherService;
import com.android.server.LocalServices;
import com.android.server.input.InputManagerInternal;
-import com.android.server.input.KeyboardMetricsCollector.KeyboardLogEvent;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.pm.UserManagerInternal;
import com.android.server.policy.keyguard.KeyguardServiceDelegate;
@@ -269,7 +267,6 @@ class TestPhoneWindowManager {
// Return mocked services: LocalServices.getService
mMockitoSession = mockitoSession()
.mockStatic(LocalServices.class, spyStubOnly)
- .mockStatic(FrameworkStatsLog.class)
.strictness(Strictness.LENIENT)
.startMocking();
@@ -583,19 +580,6 @@ class TestPhoneWindowManager {
doReturn(mPackageManager).when(mContext).getPackageManager();
}
- void overrideKeyEventSource(int vendorId, int productId, int deviceBus) {
- InputDevice device = new InputDevice.Builder()
- .setId(1)
- .setVendorId(vendorId)
- .setProductId(productId)
- .setDeviceBus(deviceBus)
- .setSources(InputDevice.SOURCE_KEYBOARD)
- .setKeyboardType(InputDevice.KEYBOARD_TYPE_ALPHABETIC)
- .build();
- doReturn(mInputManager).when(mContext).getSystemService(eq(InputManager.class));
- doReturn(device).when(mInputManager).getInputDevice(anyInt());
- }
-
void overrideInjectKeyEvent() {
doReturn(true).when(mInputManager).injectInputEvent(any(KeyEvent.class), anyInt());
}
@@ -820,12 +804,11 @@ class TestPhoneWindowManager {
Assert.assertEquals(targetActivity, intentCaptor.getValue().getComponent());
}
- void assertShortcutLogged(int vendorId, int productId, KeyboardLogEvent logEvent,
- int expectedKey, int expectedModifierState, int deviceBus, String errorMsg) {
+ void assertKeyboardShortcutTriggered(int[] keycodes, int modifierState, int systemShortcut,
+ String errorMsg) {
mTestLooper.dispatchAll();
- verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED,
- vendorId, productId, logEvent.getIntValue(), new int[]{expectedKey},
- expectedModifierState, deviceBus), description(errorMsg));
+ verify(mInputManagerInternal, description(errorMsg)).notifyKeyboardShortcutTriggered(
+ anyInt(), eq(keycodes), eq(modifierState), eq(systemShortcut));
}
void assertSwitchToTask(int persistentId) throws RemoteException {
diff --git a/tests/Input/src/android/hardware/input/KeyboardSystemShortcutListenerTest.kt b/tests/Input/src/android/hardware/input/KeyboardSystemShortcutListenerTest.kt
new file mode 100644
index 000000000000..24d7291bec87
--- /dev/null
+++ b/tests/Input/src/android/hardware/input/KeyboardSystemShortcutListenerTest.kt
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+package android.hardware.input
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.os.Handler
+import android.os.HandlerExecutor
+import android.os.test.TestLooper
+import android.platform.test.annotations.Presubmit
+import android.platform.test.flag.junit.SetFlagsRule
+import android.view.KeyEvent
+import androidx.test.core.app.ApplicationProvider
+import com.android.server.testutils.any
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnitRunner
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+import kotlin.test.assertNull
+import kotlin.test.fail
+
+/**
+ * Tests for [InputManager.KeyboardSystemShortcutListener].
+ *
+ * Build/Install/Run:
+ * atest InputTests:KeyboardSystemShortcutListenerTest
+ */
+@Presubmit
+@RunWith(MockitoJUnitRunner::class)
+class KeyboardSystemShortcutListenerTest {
+
+ companion object {
+ const val DEVICE_ID = 1
+ val HOME_SHORTCUT = KeyboardSystemShortcut(
+ intArrayOf(KeyEvent.KEYCODE_H),
+ KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME
+ )
+ }
+
+ @get:Rule
+ val rule = SetFlagsRule()
+
+ private val testLooper = TestLooper()
+ private val executor = HandlerExecutor(Handler(testLooper.looper))
+ private var registeredListener: IKeyboardSystemShortcutListener? = null
+ private lateinit var context: Context
+ private lateinit var inputManager: InputManager
+ private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
+
+ @Mock
+ private lateinit var iInputManagerMock: IInputManager
+
+ @Before
+ fun setUp() {
+ context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
+ inputManagerGlobalSession = InputManagerGlobal.createTestSession(iInputManagerMock)
+ inputManager = InputManager(context)
+ `when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
+ .thenReturn(inputManager)
+
+ // Handle keyboard system shortcut listener registration.
+ doAnswer {
+ val listener = it.getArgument(0) as IKeyboardSystemShortcutListener
+ if (registeredListener != null &&
+ registeredListener!!.asBinder() != listener.asBinder()) {
+ // There can only be one registered keyboard system shortcut listener per process.
+ fail("Trying to register a new listener when one already exists")
+ }
+ registeredListener = listener
+ null
+ }.`when`(iInputManagerMock).registerKeyboardSystemShortcutListener(any())
+
+ // Handle keyboard system shortcut listener being unregistered.
+ doAnswer {
+ val listener = it.getArgument(0) as IKeyboardSystemShortcutListener
+ if (registeredListener == null ||
+ registeredListener!!.asBinder() != listener.asBinder()) {
+ fail("Trying to unregister a listener that is not registered")
+ }
+ registeredListener = null
+ null
+ }.`when`(iInputManagerMock).unregisterKeyboardSystemShortcutListener(any())
+ }
+
+ @After
+ fun tearDown() {
+ if (this::inputManagerGlobalSession.isInitialized) {
+ inputManagerGlobalSession.close()
+ }
+ }
+
+ private fun notifyKeyboardSystemShortcutTriggered(id: Int, shortcut: KeyboardSystemShortcut) {
+ registeredListener!!.onKeyboardSystemShortcutTriggered(
+ id,
+ shortcut.keycodes,
+ shortcut.modifierState,
+ shortcut.systemShortcut
+ )
+ }
+
+ @Test
+ fun testListenerHasCorrectSystemShortcutNotified() {
+ var callbackCount = 0
+
+ // Add a keyboard system shortcut listener
+ inputManager.registerKeyboardSystemShortcutListener(executor) {
+ deviceId: Int, systemShortcut: KeyboardSystemShortcut ->
+ assertEquals(DEVICE_ID, deviceId)
+ assertEquals(HOME_SHORTCUT, systemShortcut)
+ callbackCount++
+ }
+
+ // Notifying keyboard system shortcut triggered will notify the listener.
+ notifyKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT)
+ testLooper.dispatchNext()
+ assertEquals(1, callbackCount)
+ }
+
+ @Test
+ fun testAddingListenersRegistersInternalCallbackListener() {
+ // Set up two callbacks.
+ val callback1 = InputManager.KeyboardSystemShortcutListener {_, _ -> }
+ val callback2 = InputManager.KeyboardSystemShortcutListener {_, _ -> }
+
+ assertNull(registeredListener)
+
+ // Adding the listener should register the callback with InputManagerService.
+ inputManager.registerKeyboardSystemShortcutListener(executor, callback1)
+ assertNotNull(registeredListener)
+
+ // Adding another listener should not register new internal listener.
+ val currListener = registeredListener
+ inputManager.registerKeyboardSystemShortcutListener(executor, callback2)
+ assertEquals(currListener, registeredListener)
+ }
+
+ @Test
+ fun testRemovingListenersUnregistersInternalCallbackListener() {
+ // Set up two callbacks.
+ val callback1 = InputManager.KeyboardSystemShortcutListener {_, _ -> }
+ val callback2 = InputManager.KeyboardSystemShortcutListener {_, _ -> }
+
+ inputManager.registerKeyboardSystemShortcutListener(executor, callback1)
+ inputManager.registerKeyboardSystemShortcutListener(executor, callback2)
+
+ // Only removing all listeners should remove the internal callback
+ inputManager.unregisterKeyboardSystemShortcutListener(callback1)
+ assertNotNull(registeredListener)
+ inputManager.unregisterKeyboardSystemShortcutListener(callback2)
+ assertNull(registeredListener)
+ }
+
+ @Test
+ fun testMultipleListeners() {
+ // Set up two callbacks.
+ var callbackCount1 = 0
+ var callbackCount2 = 0
+ val callback1 = InputManager.KeyboardSystemShortcutListener { _, _ -> callbackCount1++ }
+ val callback2 = InputManager.KeyboardSystemShortcutListener { _, _ -> callbackCount2++ }
+
+ // Add both keyboard system shortcut listeners
+ inputManager.registerKeyboardSystemShortcutListener(executor, callback1)
+ inputManager.registerKeyboardSystemShortcutListener(executor, callback2)
+
+ // Notifying keyboard system shortcut triggered, should notify both the callbacks.
+ notifyKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT)
+ testLooper.dispatchAll()
+ assertEquals(1, callbackCount1)
+ assertEquals(1, callbackCount2)
+
+ inputManager.unregisterKeyboardSystemShortcutListener(callback2)
+ // Notifying keyboard system shortcut triggered, should still trigger callback1 but not
+ // callback2.
+ notifyKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT)
+ testLooper.dispatchAll()
+ assertEquals(2, callbackCount1)
+ assertEquals(1, callbackCount2)
+ }
+}
diff --git a/tests/Input/src/com/android/server/input/KeyboardShortcutCallbackHandlerTests.kt b/tests/Input/src/com/android/server/input/KeyboardShortcutCallbackHandlerTests.kt
new file mode 100644
index 000000000000..5a40a1c8201e
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/KeyboardShortcutCallbackHandlerTests.kt
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+package com.android.server.input
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.hardware.input.IKeyboardSystemShortcutListener
+import android.hardware.input.KeyboardSystemShortcut
+import android.platform.test.annotations.Presubmit
+import android.view.KeyEvent
+import androidx.test.core.app.ApplicationProvider
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mockito
+import org.mockito.junit.MockitoJUnit
+
+/**
+ * Tests for {@link KeyboardShortcutCallbackHandler}.
+ *
+ * Build/Install/Run:
+ * atest InputTests:KeyboardShortcutCallbackHandlerTests
+ */
+@Presubmit
+class KeyboardShortcutCallbackHandlerTests {
+
+ companion object {
+ val DEVICE_ID = 1
+ val HOME_SHORTCUT = KeyboardSystemShortcut(
+ intArrayOf(KeyEvent.KEYCODE_H),
+ KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON,
+ KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME
+ )
+ }
+
+ @get:Rule
+ val rule = MockitoJUnit.rule()!!
+
+ private lateinit var keyboardShortcutCallbackHandler: KeyboardShortcutCallbackHandler
+ private lateinit var context: Context
+ private var lastShortcut: KeyboardSystemShortcut? = null
+
+ @Before
+ fun setup() {
+ context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
+ keyboardShortcutCallbackHandler = KeyboardShortcutCallbackHandler()
+ }
+
+ @Test
+ fun testKeyboardSystemShortcutTriggered_registerUnregisterListener() {
+ val listener = KeyboardSystemShortcutListener()
+
+ // Register keyboard system shortcut listener
+ keyboardShortcutCallbackHandler.registerKeyboardSystemShortcutListener(listener, 0)
+ keyboardShortcutCallbackHandler.onKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT)
+ assertEquals(
+ "Listener should get callback on keyboard system shortcut triggered",
+ HOME_SHORTCUT,
+ lastShortcut!!
+ )
+
+ // Unregister listener
+ lastShortcut = null
+ keyboardShortcutCallbackHandler.unregisterKeyboardSystemShortcutListener(listener, 0)
+ keyboardShortcutCallbackHandler.onKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT)
+ assertNull("Listener should not get callback after being unregistered", lastShortcut)
+ }
+
+ inner class KeyboardSystemShortcutListener : IKeyboardSystemShortcutListener.Stub() {
+ override fun onKeyboardSystemShortcutTriggered(
+ deviceId: Int,
+ keycodes: IntArray,
+ modifierState: Int,
+ shortcut: Int
+ ) {
+ assertEquals(DEVICE_ID, deviceId)
+ lastShortcut = KeyboardSystemShortcut(keycodes, modifierState, shortcut)
+ }
+ }
+} \ No newline at end of file