Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c20cc5d2 authored by Vaibhav Devmurari's avatar Vaibhav Devmurari
Browse files

Shift Open notes key gesture handling to SystemUI

Test: atest NoteTaskInitializerTest
Bug: 358569822
Flag: com.android.hardware.input.use_key_gesture_event_handler
Change-Id: Ie65fa7949d1314d073c03e4144225af9f6712e82
parent ad0012cb
Loading
Loading
Loading
Loading
+47 −1
Original line number Diff line number Diff line
@@ -19,11 +19,15 @@ import android.app.role.OnRoleHoldersChangedListener
import android.app.role.RoleManager
import android.content.Context
import android.content.pm.UserInfo
import android.hardware.input.InputManager
import android.hardware.input.KeyGestureEvent
import android.os.IBinder
import android.os.UserHandle
import android.view.KeyEvent
import android.view.KeyEvent.KEYCODE_N
import android.view.KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL
import android.view.ViewConfiguration
import com.android.hardware.input.Flags.useKeyGestureEventHandler
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.dagger.qualifiers.Background
@@ -47,6 +51,7 @@ constructor(
    private val optionalBubbles: Optional<Bubbles>,
    private val userTracker: UserTracker,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    private val inputManager: InputManager,
    @Background private val backgroundExecutor: Executor,
    @NoteTaskEnabledKey private val isEnabled: Boolean,
) {
@@ -59,6 +64,7 @@ constructor(
        if (!isEnabled || optionalBubbles.isEmpty) return

        initializeHandleSystemKey()
        initializeKeyGestureEventHandler()
        initializeOnRoleHoldersChanged()
        initializeOnUserUnlocked()
        initializeUserTracker()
@@ -72,6 +78,16 @@ constructor(
        commandQueue.addCallback(callbacks)
    }

    /**
     * Initializes a [InputManager.KeyGestureEventHandler] which will handle shortcuts for opening
     * the notes role via [NoteTaskController].
     */
    private fun initializeKeyGestureEventHandler() {
        if (useKeyGestureEventHandler()) {
            inputManager.registerKeyGestureEventHandler(callbacks)
        }
    }

    /**
     * Initializes the [RoleManager] role holder changed listener to ensure [NoteTaskController]
     * will always update whenever the role holder app changes. Keep in mind that a role may change
@@ -110,7 +126,8 @@ constructor(
            KeyguardUpdateMonitorCallback(),
            CommandQueue.Callbacks,
            UserTracker.Callback,
            OnRoleHoldersChangedListener {
            OnRoleHoldersChangedListener,
            InputManager.KeyGestureEventHandler {

            override fun handleSystemKey(key: KeyEvent) {
                key.toNoteTaskEntryPointOrNull()?.let(controller::showNoteTask)
@@ -131,6 +148,17 @@ constructor(
            override fun onProfilesChanged(profiles: List<UserInfo>) {
                controller.updateNoteTaskForCurrentUserAndManagedProfiles()
            }

            override fun handleKeyGestureEvent(
                event: KeyGestureEvent,
                focusedToken: IBinder?
            ): Boolean {
                return this@NoteTaskInitializer.handleKeyGestureEvent(event)
            }

            override fun isKeyGestureSupported(gestureType: Int): Boolean {
                return this@NoteTaskInitializer.isKeyGestureSupported(gestureType);
            }
        }

    /**
@@ -171,6 +199,24 @@ constructor(
        return !isMultiPress && !isLongPress
    }

    private fun handleKeyGestureEvent(event: KeyGestureEvent): Boolean {
        // This method is on input hot path and should be kept lightweight. Shift all complex
        // processing onto background executor wherever possible.
        if (event.keyGestureType != KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES) {
            return false
        }
        debugLog {
            "handleKeyGestureEvent: Received OPEN_NOTES gesture event from keycodes: " +
                event.keycodes.contentToString()
        }
        backgroundExecutor.execute { controller.showNoteTask(KEYBOARD_SHORTCUT) }
        return true
    }

    private fun isKeyGestureSupported(gestureType: Int): Boolean {
        return gestureType == KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES
    }

    companion object {
        val MULTI_PRESS_TIMEOUT = ViewConfiguration.getMultiPressTimeout().toLong()
        val LONG_PRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout().toLong()
+30 −0
Original line number Diff line number Diff line
@@ -17,8 +17,12 @@ package com.android.systemui.notetask

import android.app.role.RoleManager
import android.app.role.RoleManager.ROLE_NOTES
import android.hardware.input.InputManager
import android.hardware.input.KeyGestureEvent
import android.os.UserHandle
import android.os.UserManager
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
import android.view.KeyEvent
import android.view.KeyEvent.ACTION_DOWN
import android.view.KeyEvent.ACTION_UP
@@ -42,6 +46,7 @@ import com.google.common.truth.Truth.assertThat
import java.util.Optional
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
@@ -57,7 +62,11 @@ import org.mockito.MockitoAnnotations.initMocks
@RunWith(AndroidJUnit4::class)
internal class NoteTaskInitializerTest : SysuiTestCase() {

    @get:Rule
    val setFlagsRule = SetFlagsRule()

    @Mock lateinit var commandQueue: CommandQueue
    @Mock lateinit var inputManager: InputManager
    @Mock lateinit var bubbles: Bubbles
    @Mock lateinit var controller: NoteTaskController
    @Mock lateinit var roleManager: RoleManager
@@ -86,6 +95,7 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
            roleManager = roleManager,
            userTracker = userTracker,
            keyguardUpdateMonitor = keyguardMonitor,
            inputManager = inputManager,
            backgroundExecutor = executor,
        )

@@ -171,6 +181,26 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
        verify(controller).showNoteTask(any())
    }

    @Test
    @EnableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
    fun initialize_handleKeyGestureEvent() {
        val gestureEvent = KeyGestureEvent.Builder()
            .setKeycodes(intArrayOf(KeyEvent.KEYCODE_N))
            .setModifierState(KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON)
            .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES)
            .setAction(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
            .build()
        val underTest = createUnderTest(isEnabled = true, bubbles = bubbles)
        underTest.initialize()
        val callback =
            withArgCaptor { verify(inputManager).registerKeyGestureEventHandler(capture()) }

        assertThat(callback.handleKeyGestureEvent(gestureEvent, null)).isTrue()

        executor.runAllReady()
        verify(controller).showNoteTask(any())
    }

    @Test
    fun initialize_userUnlocked_shouldUpdateNoteTask() {
        whenever(keyguardMonitor.isUserUnlocked(userTracker.userId)).thenReturn(false)
+5 −1
Original line number Diff line number Diff line
@@ -259,7 +259,11 @@ final class KeyGestureController {
            case KeyEvent.KEYCODE_N:
                if (firstDown && event.isMetaPressed()) {
                    if (event.isCtrlPressed()) {
                        // TODO(b/358569822): Move open notes handling in System UI instead of PWM
                        return handleKeyGesture(deviceId, new int[]{keyCode},
                                KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON,
                                KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES,
                                KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId,
                                focusedToken, /* flags = */0);
                    } else {
                        return handleKeyGesture(deviceId, new int[]{keyCode},
                                KeyEvent.META_META_ON,
+12 −0
Original line number Diff line number Diff line
@@ -285,6 +285,18 @@ class KeyGestureControllerTests {
                KeyEvent.META_META_ON,
                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
            ),
            TestData(
                "META + CTRL + N -> Open Notes",
                intArrayOf(
                    KeyEvent.KEYCODE_META_LEFT,
                    KeyEvent.KEYCODE_CTRL_LEFT,
                    KeyEvent.KEYCODE_N
                ),
                KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES,
                intArrayOf(KeyEvent.KEYCODE_N),
                KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON,
                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
            ),
            TestData(
                "META + CTRL + S -> Take Screenshot",
                intArrayOf(