Add support for Meta+Ctrl+N to open Notes task
Test: manual Bug: 246661404 Change-Id: I6a0e6a2d44d56c1e27c842b51a3c3469ea607af4
This commit is contained in:
@@ -427,7 +427,7 @@ package android.app {
|
||||
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void collapsePanels();
|
||||
method public void expandNotificationsPanel();
|
||||
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public int getLastSystemKey();
|
||||
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void handleSystemKey(int);
|
||||
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void handleSystemKey(@NonNull android.view.KeyEvent);
|
||||
method public void sendNotificationFeedback(@Nullable String, @Nullable android.os.Bundle);
|
||||
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setExpansionDisabledForSimNetworkLock(boolean);
|
||||
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void togglePanel();
|
||||
|
||||
@@ -46,6 +46,7 @@ import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.internal.statusbar.AppClipsServiceConnector;
|
||||
@@ -740,7 +741,7 @@ public class StatusBarManager {
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.STATUS_BAR)
|
||||
@TestApi
|
||||
public void handleSystemKey(int key) {
|
||||
public void handleSystemKey(@NonNull KeyEvent key) {
|
||||
try {
|
||||
final IStatusBarService svc = getService();
|
||||
if (svc != null) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.media.INearbyMediaDevicesProvider;
|
||||
import android.media.MediaRoute2Info;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.view.KeyEvent;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
|
||||
import com.android.internal.statusbar.IAddTileResultCallback;
|
||||
@@ -141,7 +142,7 @@ oneway interface IStatusBar
|
||||
void addQsTile(in ComponentName tile);
|
||||
void remQsTile(in ComponentName tile);
|
||||
void clickQsTile(in ComponentName tile);
|
||||
void handleSystemKey(in int key);
|
||||
void handleSystemKey(in KeyEvent key);
|
||||
|
||||
/**
|
||||
* Methods to show toast messages for screen pinning
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.media.MediaRoute2Info;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.view.KeyEvent;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
|
||||
import com.android.internal.logging.InstanceId;
|
||||
@@ -110,7 +111,7 @@ interface IStatusBarService
|
||||
void remTile(in ComponentName tile);
|
||||
void clickTile(in ComponentName tile);
|
||||
@UnsupportedAppUsage
|
||||
void handleSystemKey(in int key);
|
||||
void handleSystemKey(in KeyEvent key);
|
||||
int getLastSystemKey();
|
||||
|
||||
/**
|
||||
|
||||
@@ -296,7 +296,8 @@ private fun createNoteTaskIntent(info: NoteTaskInfo): Intent =
|
||||
|
||||
// EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint
|
||||
// was used to start the note task.
|
||||
putExtra(Intent.EXTRA_USE_STYLUS_MODE, true)
|
||||
val useStylusMode = info.entryPoint != NoteTaskEntryPoint.KEYBOARD_SHORTCUT
|
||||
putExtra(Intent.EXTRA_USE_STYLUS_MODE, useStylusMode)
|
||||
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
// We should ensure the note experience can be opened both as a full screen (lockscreen)
|
||||
|
||||
@@ -25,7 +25,8 @@ import com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity
|
||||
* An entry point represents where the note task has ben called from. In rare cases, it may
|
||||
* represent a "re-entry" (i.e., [APP_CLIPS]).
|
||||
*/
|
||||
enum class NoteTaskEntryPoint {
|
||||
enum class
|
||||
NoteTaskEntryPoint {
|
||||
|
||||
/** @see [LaunchNoteTaskActivity] */
|
||||
WIDGET_PICKER_SHORTCUT,
|
||||
@@ -38,4 +39,7 @@ enum class NoteTaskEntryPoint {
|
||||
|
||||
/** @see [AppClipsTrampolineActivity] */
|
||||
APP_CLIPS,
|
||||
|
||||
/** @see [NoteTaskInitializer.callbacks] */
|
||||
KEYBOARD_SHORTCUT,
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.systemui.notetask
|
||||
import com.android.internal.logging.UiEvent
|
||||
import com.android.internal.logging.UiEventLogger
|
||||
import com.android.systemui.notetask.NoteTaskEntryPoint.APP_CLIPS
|
||||
import com.android.systemui.notetask.NoteTaskEntryPoint.KEYBOARD_SHORTCUT
|
||||
import com.android.systemui.notetask.NoteTaskEntryPoint.QUICK_AFFORDANCE
|
||||
import com.android.systemui.notetask.NoteTaskEntryPoint.TAIL_BUTTON
|
||||
import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT
|
||||
@@ -51,6 +52,7 @@ class NoteTaskEventLogger @Inject constructor(private val uiEventLogger: UiEvent
|
||||
WIDGET_PICKER_SHORTCUT -> NOTE_OPENED_VIA_SHORTCUT
|
||||
QUICK_AFFORDANCE -> NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
|
||||
APP_CLIPS -> return
|
||||
KEYBOARD_SHORTCUT -> return
|
||||
null -> return
|
||||
}
|
||||
uiEventLogger.log(event, info.uid, info.packageName)
|
||||
@@ -70,6 +72,7 @@ class NoteTaskEventLogger @Inject constructor(private val uiEventLogger: UiEvent
|
||||
WIDGET_PICKER_SHORTCUT -> return
|
||||
QUICK_AFFORDANCE -> return
|
||||
APP_CLIPS -> return
|
||||
KEYBOARD_SHORTCUT -> return
|
||||
null -> return
|
||||
}
|
||||
uiEventLogger.log(event, info.uid, info.packageName)
|
||||
|
||||
@@ -41,9 +41,12 @@ constructor(
|
||||
@VisibleForTesting
|
||||
val callbacks =
|
||||
object : CommandQueue.Callbacks {
|
||||
override fun handleSystemKey(keyCode: Int) {
|
||||
if (keyCode == KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL) {
|
||||
override fun handleSystemKey(key: KeyEvent) {
|
||||
if (key.keyCode == KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL) {
|
||||
controller.showNoteTask(NoteTaskEntryPoint.TAIL_BUTTON)
|
||||
} else if (key.keyCode == KeyEvent.KEYCODE_N && key.isMetaPressed &&
|
||||
key.isCtrlPressed) {
|
||||
controller.showNoteTask(NoteTaskEntryPoint.KEYBOARD_SHORTCUT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +336,8 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
|
||||
@Override
|
||||
public void expandNotificationPanel() {
|
||||
verifyCallerAndClearCallingIdentity("expandNotificationPanel",
|
||||
() -> mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN));
|
||||
() -> mCommandQueue.handleSystemKey(new KeyEvent(KeyEvent.ACTION_DOWN,
|
||||
KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -53,6 +53,7 @@ import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Pair;
|
||||
import android.util.SparseArray;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
import android.view.WindowInsetsController.Appearance;
|
||||
import android.view.WindowInsetsController.Behavior;
|
||||
@@ -302,7 +303,7 @@ public class CommandQueue extends IStatusBar.Stub implements
|
||||
default void remQsTile(ComponentName tile) { }
|
||||
default void clickTile(ComponentName tile) { }
|
||||
|
||||
default void handleSystemKey(int arg1) { }
|
||||
default void handleSystemKey(KeyEvent arg1) { }
|
||||
default void showPinningEnterExitToast(boolean entering) { }
|
||||
default void showPinningEscapeToast() { }
|
||||
default void handleShowGlobalActionsMenu() { }
|
||||
@@ -891,9 +892,9 @@ public class CommandQueue extends IStatusBar.Stub implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSystemKey(int key) {
|
||||
public void handleSystemKey(KeyEvent key) {
|
||||
synchronized (mLock) {
|
||||
mHandler.obtainMessage(MSG_HANDLE_SYSTEM_KEY, key, 0).sendToTarget();
|
||||
mHandler.obtainMessage(MSG_HANDLE_SYSTEM_KEY, key).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1534,7 +1535,7 @@ public class CommandQueue extends IStatusBar.Stub implements
|
||||
break;
|
||||
case MSG_HANDLE_SYSTEM_KEY:
|
||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||
mCallbacks.get(i).handleSystemKey(msg.arg1);
|
||||
mCallbacks.get(i).handleSystemKey((KeyEvent) msg.obj);
|
||||
}
|
||||
break;
|
||||
case MSG_SHOW_GLOBAL_ACTIONS:
|
||||
|
||||
@@ -308,7 +308,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
|
||||
* settings. Down action closes the entire panel.
|
||||
*/
|
||||
@Override
|
||||
public void handleSystemKey(int key) {
|
||||
public void handleSystemKey(KeyEvent key) {
|
||||
if (CentralSurfaces.SPEW) {
|
||||
Log.d(CentralSurfaces.TAG, "handleNavigationKey: " + key);
|
||||
}
|
||||
@@ -320,11 +320,11 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
|
||||
// Panels are not available in setup
|
||||
if (!mDeviceProvisionedController.isCurrentUserSetup()) return;
|
||||
|
||||
if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP == key) {
|
||||
if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP == key.getKeyCode()) {
|
||||
mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_UP);
|
||||
mNotificationPanelViewController.collapse(
|
||||
false /* delayed */, 1.0f /* speedUpFactor */);
|
||||
} else if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN == key) {
|
||||
} else if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN == key.getKeyCode()) {
|
||||
mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_DOWN);
|
||||
if (mNotificationPanelViewController.isFullyCollapsed()) {
|
||||
if (mVibrateOnOpening) {
|
||||
|
||||
@@ -295,8 +295,8 @@ public final class WMShell implements
|
||||
@Override
|
||||
public void notifyExpandNotification() {
|
||||
mSysUiMainExecutor.execute(
|
||||
() -> mCommandQueue.handleSystemKey(
|
||||
KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN));
|
||||
() -> mCommandQueue.handleSystemKey(new KeyEvent(KeyEvent.ACTION_DOWN,
|
||||
KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN)));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -369,6 +369,39 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
|
||||
|
||||
verifyZeroInteractions(context, bubbles, eventLogger)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun showNoteTask_keyboardShortcut_shouldStartActivity() {
|
||||
val expectedInfo =
|
||||
NOTE_TASK_INFO.copy(
|
||||
entryPoint = NoteTaskEntryPoint.KEYBOARD_SHORTCUT,
|
||||
isKeyguardLocked = true,
|
||||
)
|
||||
whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
|
||||
whenever(resolver.resolveInfo(any(), any())).thenReturn(expectedInfo)
|
||||
|
||||
createNoteTaskController()
|
||||
.showNoteTask(
|
||||
entryPoint = expectedInfo.entryPoint!!,
|
||||
)
|
||||
|
||||
val intentCaptor = argumentCaptor<Intent>()
|
||||
val userCaptor = argumentCaptor<UserHandle>()
|
||||
verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
|
||||
intentCaptor.value.let { intent ->
|
||||
assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
|
||||
assertThat(intent.`package`).isEqualTo(NOTE_TASK_PACKAGE_NAME)
|
||||
assertThat(intent.flags and FLAG_ACTIVITY_NEW_TASK).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
|
||||
assertThat(intent.flags and FLAG_ACTIVITY_MULTIPLE_TASK)
|
||||
.isEqualTo(FLAG_ACTIVITY_MULTIPLE_TASK)
|
||||
assertThat(intent.flags and FLAG_ACTIVITY_NEW_DOCUMENT)
|
||||
.isEqualTo(FLAG_ACTIVITY_NEW_DOCUMENT)
|
||||
assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, true)).isFalse()
|
||||
}
|
||||
assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
|
||||
verify(eventLogger).logNoteTaskOpened(expectedInfo)
|
||||
verifyZeroInteractions(bubbles)
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region setNoteTaskShortcutEnabled
|
||||
|
||||
@@ -98,14 +98,24 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
|
||||
// region handleSystemKey
|
||||
@Test
|
||||
fun handleSystemKey_receiveValidSystemKey_shouldShowNoteTask() {
|
||||
createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL)
|
||||
createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent(KeyEvent.ACTION_DOWN,
|
||||
KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL))
|
||||
|
||||
verify(controller).showNoteTask(entryPoint = NoteTaskEntryPoint.TAIL_BUTTON)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleSystemKey_receiveKeyboardShortcut_shouldShowNoteTask() {
|
||||
createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
|
||||
KeyEvent.KEYCODE_N, 0, KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON))
|
||||
|
||||
verify(controller).showNoteTask(entryPoint = NoteTaskEntryPoint.KEYBOARD_SHORTCUT)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleSystemKey_receiveInvalidSystemKey_shouldDoNothing() {
|
||||
createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent.KEYCODE_UNKNOWN)
|
||||
createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent(KeyEvent.ACTION_DOWN,
|
||||
KeyEvent.KEYCODE_UNKNOWN))
|
||||
|
||||
verifyZeroInteractions(controller)
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.hardware.biometrics.IBiometricSysuiReceiver;
|
||||
import android.hardware.biometrics.PromptInfo;
|
||||
import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
import android.view.WindowInsetsController.Appearance;
|
||||
@@ -397,9 +398,10 @@ public class CommandQueueTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testHandleSysKey() {
|
||||
mCommandQueue.handleSystemKey(1);
|
||||
KeyEvent testEvent = new KeyEvent(1, 1);
|
||||
mCommandQueue.handleSystemKey(testEvent);
|
||||
waitForIdleSync();
|
||||
verify(mCallbacks).handleSystemKey(eq(1));
|
||||
verify(mCallbacks).handleSystemKey(eq(testEvent));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -729,7 +729,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
mAutofillManagerInternal.onBackKeyPressed();
|
||||
break;
|
||||
case MSG_SYSTEM_KEY_PRESS:
|
||||
sendSystemKeyToStatusBar(msg.arg1);
|
||||
sendSystemKeyToStatusBar((KeyEvent) msg.obj);
|
||||
break;
|
||||
case MSG_HANDLE_ALL_APPS:
|
||||
launchAllAppsAction();
|
||||
@@ -949,7 +949,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
final boolean handledByPowerManager = mPowerManagerInternal.interceptPowerKeyDown(event);
|
||||
|
||||
// Inform the StatusBar; but do not allow it to consume the event.
|
||||
sendSystemKeyToStatusBarAsync(event.getKeyCode());
|
||||
sendSystemKeyToStatusBarAsync(event);
|
||||
|
||||
// If the power key has still not yet been handled, then detect short
|
||||
// press, long press, or multi press and decide what to do.
|
||||
@@ -3001,7 +3001,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
break;
|
||||
case KeyEvent.KEYCODE_N:
|
||||
if (down && event.isMetaPressed()) {
|
||||
toggleNotificationPanel();
|
||||
if (event.isCtrlPressed()) {
|
||||
sendSystemKeyToStatusBarAsync(event);
|
||||
} else {
|
||||
toggleNotificationPanel();
|
||||
}
|
||||
return key_consumed;
|
||||
}
|
||||
break;
|
||||
@@ -4119,7 +4123,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||
case KeyEvent.KEYCODE_VOLUME_MUTE: {
|
||||
if (down) {
|
||||
sendSystemKeyToStatusBarAsync(event.getKeyCode());
|
||||
sendSystemKeyToStatusBarAsync(event);
|
||||
|
||||
NotificationManager nm = getNotificationService();
|
||||
if (nm != null && !mHandleVolumeKeysInWM) {
|
||||
@@ -4397,7 +4401,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
case KeyEvent.KEYCODE_STYLUS_BUTTON_TERTIARY:
|
||||
case KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL: {
|
||||
if (down && mStylusButtonsEnabled) {
|
||||
sendSystemKeyToStatusBarAsync(keyCode);
|
||||
sendSystemKeyToStatusBarAsync(event);
|
||||
}
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
break;
|
||||
@@ -4494,7 +4498,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
if (!mAccessibilityManager.isEnabled()
|
||||
|| !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
|
||||
if (mSystemNavigationKeysEnabled) {
|
||||
sendSystemKeyToStatusBarAsync(event.getKeyCode());
|
||||
sendSystemKeyToStatusBarAsync(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4503,11 +4507,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
/**
|
||||
* Notify the StatusBar that a system key was pressed.
|
||||
*/
|
||||
private void sendSystemKeyToStatusBar(int keyCode) {
|
||||
private void sendSystemKeyToStatusBar(KeyEvent key) {
|
||||
IStatusBarService statusBar = getStatusBarService();
|
||||
if (statusBar != null) {
|
||||
try {
|
||||
statusBar.handleSystemKey(keyCode);
|
||||
statusBar.handleSystemKey(key);
|
||||
} catch (RemoteException e) {
|
||||
// Oh well.
|
||||
}
|
||||
@@ -4517,8 +4521,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
/**
|
||||
* Notify the StatusBar that a system key was pressed without blocking the current thread.
|
||||
*/
|
||||
private void sendSystemKeyToStatusBarAsync(int keyCode) {
|
||||
Message message = mHandler.obtainMessage(MSG_SYSTEM_KEY_PRESS, keyCode, 0);
|
||||
private void sendSystemKeyToStatusBarAsync(KeyEvent keyEvent) {
|
||||
Message message = mHandler.obtainMessage(MSG_SYSTEM_KEY_PRESS, keyEvent);
|
||||
message.setAsynchronous(true);
|
||||
mHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ import android.util.IndentingPrintWriter;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
import android.view.WindowInsetsController.Appearance;
|
||||
@@ -902,12 +903,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSystemKey(int key) throws RemoteException {
|
||||
public void handleSystemKey(KeyEvent key) throws RemoteException {
|
||||
if (!checkCanCollapseStatusBar("handleSystemKey")) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLastSystemKey = key;
|
||||
mLastSystemKey = key.getKeyCode();
|
||||
|
||||
if (mBar != null) {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user