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

Commit 067ba845 authored by Vaibhav Devmurari's avatar Vaibhav Devmurari
Browse files

Shift Key gestures handled by InputManager to IMS from PWM

Test: atest InputTests
Bug: 358569822
Flag: com.android.hardware.input.use_key_gesture_event_handler
Change-Id: Ia104f506a22dacf6886bc86c9876c66bfd9751c6
parent e8c64031
Loading
Loading
Loading
Loading
+70 −4
Original line number Diff line number Diff line
@@ -456,6 +456,14 @@ public class InputManagerService extends IInputManager.Stub
        void registerLocalService(InputManagerInternal localService) {
            LocalServices.addService(InputManagerInternal.class, localService);
        }

        KeyboardBacklightControllerInterface getKeyboardBacklightController(
                NativeInputManagerService nativeService, PersistentDataStore dataStore) {
            return InputFeatureFlagProvider.isKeyboardBacklightControlEnabled()
                    ? new KeyboardBacklightController(mContext, nativeService, dataStore,
                    mLooper, mUEventManager)
                    : new KeyboardBacklightControllerInterface() {};
        }
    }

    public InputManagerService(Context context) {
@@ -479,10 +487,7 @@ public class InputManagerService extends IInputManager.Stub
                        injector.getLooper(), this) : null;
        mBatteryController = new BatteryController(mContext, mNative, injector.getLooper(),
                injector.getUEventManager());
        mKeyboardBacklightController = InputFeatureFlagProvider.isKeyboardBacklightControlEnabled()
                ? new KeyboardBacklightController(mContext, mNative, mDataStore,
                        injector.getLooper(), injector.getUEventManager())
                : new KeyboardBacklightControllerInterface() {};
        mKeyboardBacklightController = injector.getKeyboardBacklightController(mNative, mDataStore);
        mStickyModifierStateController = new StickyModifierStateController();
        mKeyGestureController = new KeyGestureController(mContext, injector.getLooper());
        mKeyboardLedController = new KeyboardLedController(mContext, injector.getLooper(),
@@ -606,6 +611,8 @@ public class InputManagerService extends IInputManager.Stub
        mKeyRemapper.systemRunning();
        mPointerIconCache.systemRunning();
        mKeyboardGlyphManager.systemRunning();

        initKeyGestures();
    }

    private void reloadDeviceAliases() {
@@ -2504,6 +2511,59 @@ public class InputManagerService extends IInputManager.Stub
                null, null, null) == PERMISSION_GRANTED;
    }

    private void initKeyGestures() {
        if (!useKeyGestureEventHandler()) {
            return;
        }
        InputManager im = Objects.requireNonNull(mContext.getSystemService(InputManager.class));
        im.registerKeyGestureEventHandler(new InputManager.KeyGestureEventHandler() {
            @Override
            public boolean handleKeyGestureEvent(@NonNull KeyGestureEvent event,
                    @Nullable IBinder focussedToken) {
                int deviceId = event.getDeviceId();
                boolean complete = event.getAction() == KeyGestureEvent.ACTION_GESTURE_COMPLETE
                        && !event.isCancelled();
                switch (event.getKeyGestureType()) {
                    case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP:
                        if (complete) {
                            mKeyboardBacklightController.incrementKeyboardBacklight(deviceId);
                        }
                        return true;
                    case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN:
                        if (complete) {
                            mKeyboardBacklightController.decrementKeyboardBacklight(deviceId);
                        }
                        return true;
                    case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE:
                        // TODO(b/367748270): Add functionality to turn keyboard backlight on/off.
                        return true;
                    case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK:
                        if (complete) {
                            mNative.toggleCapsLock(deviceId);
                        }
                        return true;
                    default:
                        return false;

                }
            }

            @Override
            public boolean isKeyGestureSupported(int gestureType) {
                switch (gestureType) {
                    case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP:
                    case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN:
                    case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE:
                    case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK:
                        return true;
                    default:
                        return false;

                }
            }
        });
    }

    // Native callback.
    @SuppressWarnings("unused")
    private KeyEvent dispatchUnhandledKey(IBinder focus, KeyEvent event, int policyFlags) {
@@ -3207,6 +3267,8 @@ public class InputManagerService extends IInputManager.Stub
            mKeyboardBacklightController.onInteractiveChanged(interactive);
        }

        // TODO(b/358569822): Remove this method from InputManagerInternal after key gesture
        //  handler refactoring complete
        @Override
        public void toggleCapsLock(int deviceId) {
            mNative.toggleCapsLock(deviceId);
@@ -3294,11 +3356,15 @@ public class InputManagerService extends IInputManager.Stub
            mKeyboardBacklightController.notifyUserActivity();
        }

        // TODO(b/358569822): Remove this method from InputManagerInternal after key gesture
        //  handler refactoring complete
        @Override
        public void incrementKeyboardBacklight(int deviceId) {
            mKeyboardBacklightController.incrementKeyboardBacklight(deviceId);
        }

        // TODO(b/358569822): Remove this method from InputManagerInternal after key gesture
        //  handler refactoring complete
        @Override
        public void decrementKeyboardBacklight(int deviceId) {
            mKeyboardBacklightController.decrementKeyboardBacklight(deviceId);
+0 −23
Original line number Diff line number Diff line
@@ -3849,10 +3849,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                    case KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS:
                    case KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SEARCH:
                    case KeyGestureEvent.KEY_GESTURE_TYPE_LANGUAGE_SWITCH:
                    case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP:
                    case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN:
                    case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE:
                    case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK:
                        return true;
                    default:
                        return false;
@@ -4010,25 +4006,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                    sendSwitchKeyboardLayout(displayId, focusedToken, direction);
                }
                return true;
            // TODO (b/358569822): Move these input specific gesture handling to IMS since we
            //  are calling into InputManager through internal API anyways
            case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP:
                if (complete) {
                    mInputManagerInternal.incrementKeyboardBacklight(deviceId);
                }
                return true;
            case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN:
                if (complete) {
                    mInputManagerInternal.decrementKeyboardBacklight(deviceId);
                }
                return true;
            case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE:
                return true;
            case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK:
                if (complete) {
                    mInputManagerInternal.toggleCapsLock(deviceId);
                }
                return true;
        }
        return false;
    }
+79 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.Manifest
import android.content.Context
import android.content.ContextWrapper
import android.content.PermissionChecker
import android.content.pm.PackageManager
import android.content.pm.PackageManagerInternal
import android.hardware.display.DisplayManager
import android.hardware.display.DisplayViewport
import android.hardware.display.VirtualDisplay
@@ -29,10 +31,13 @@ import android.hardware.input.InputManagerGlobal
import android.os.InputEventInjectionSync
import android.os.SystemClock
import android.os.test.TestLooper
import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.Presubmit
import android.platform.test.flag.junit.SetFlagsRule
import android.provider.Settings
import android.view.View.OnKeyListener
import android.view.InputDevice
import android.view.KeyCharacterMap
import android.view.KeyEvent
import android.view.SurfaceHolder
import android.view.SurfaceView
@@ -94,6 +99,10 @@ class InputManagerServiceTests {
        ExtendedMockitoRule.Builder(this).mockStatic(LocalServices::class.java)
            .mockStatic(PermissionChecker::class.java).build()!!

    @JvmField
    @Rule
    val setFlagsRule = SetFlagsRule()

    @get:Rule
    val fakeSettingsProviderRule = FakeSettingsProvider.rule()!!

@@ -106,9 +115,15 @@ class InputManagerServiceTests {
    @Mock
    private lateinit var windowManagerInternal: WindowManagerInternal

    @Mock
    private lateinit var packageManagerInternal: PackageManagerInternal

    @Mock
    private lateinit var uEventManager: UEventManager

    @Mock
    private lateinit var kbdController: InputManagerService.KeyboardBacklightControllerInterface

    private lateinit var service: InputManagerService
    private lateinit var localService: InputManagerInternal
    private lateinit var context: Context
@@ -135,15 +150,29 @@ class InputManagerServiceTests {
                override fun registerLocalService(service: InputManagerInternal?) {
                    localService = service!!
                }

                override fun getKeyboardBacklightController(
                    nativeService: NativeInputManagerService?,
                    dataStore: PersistentDataStore?
                ): InputManagerService.KeyboardBacklightControllerInterface {
                    return kbdController
                }
            })
        inputManagerGlobalSession = InputManagerGlobal.createTestSession(service)
        val inputManager = InputManager(context)
        whenever(context.getSystemService(InputManager::class.java)).thenReturn(inputManager)
        whenever(context.getSystemService(Context.INPUT_SERVICE)).thenReturn(inputManager)
        whenever(context.checkCallingOrSelfPermission(Manifest.permission.MANAGE_KEY_GESTURES))
            .thenReturn(
                PackageManager.PERMISSION_GRANTED
            )

        ExtendedMockito.doReturn(windowManagerInternal).`when` {
            LocalServices.getService(eq(WindowManagerInternal::class.java))
        }
        ExtendedMockito.doReturn(packageManagerInternal).`when` {
            LocalServices.getService(eq(PackageManagerInternal::class.java))
        }

        assertTrue("Local service must be registered", this::localService.isInitialized)
        service.setWindowManagerCallbacks(wmCallbacks)
@@ -442,6 +471,37 @@ class InputManagerServiceTests {
        verify(mockOnKeyListener, never()).onKey(mockSurfaceView1, KeyEvent.KEYCODE_A, upEvent)
    }

    @Test
    @EnableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
    fun handleKeyGestures_keyboardBacklight() {
        service.systemRunning()

        val backlightDownEvent = createKeyEvent(KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN)
        service.interceptKeyBeforeDispatching(null, backlightDownEvent, /* policyFlags = */0)
        verify(kbdController).decrementKeyboardBacklight(anyInt())

        val backlightUpEvent = createKeyEvent(KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP)
        service.interceptKeyBeforeDispatching(null, backlightUpEvent, /* policyFlags = */0)
        verify(kbdController).incrementKeyboardBacklight(anyInt())
    }

    @Test
    @EnableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
    fun handleKeyGestures_toggleCapsLock() {
        service.systemRunning()

        val metaDownEvent = createKeyEvent(KeyEvent.KEYCODE_META_LEFT)
        service.interceptKeyBeforeDispatching(null, metaDownEvent, /* policyFlags = */0)
        val altDownEvent =
            createKeyEvent(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.META_META_ON, KeyEvent.ACTION_DOWN)
        service.interceptKeyBeforeDispatching(null, altDownEvent, /* policyFlags = */0)
        val altUpEvent =
            createKeyEvent(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.META_META_ON, KeyEvent.ACTION_UP)
        service.interceptKeyBeforeDispatching(null, altUpEvent, /* policyFlags = */0)

        verify(native).toggleCapsLock(anyInt())
    }

    fun overrideSendActionKeyEventsToFocusedWindow(
        hasPermission: Boolean,
        hasPrivateFlag: Boolean
@@ -476,6 +536,25 @@ class InputManagerServiceTests {
        )
        whenever(windowManagerInternal.getKeyInterceptionInfoFromToken(any())).thenReturn(info)
    }

    private fun createKeyEvent(
        keycode: Int,
        modifierState: Int = 0,
        action: Int = KeyEvent.ACTION_DOWN
    ): KeyEvent {
        return KeyEvent(
            /* downTime = */0,
            /* eventTime = */0,
            action,
            keycode,
            /* repeat = */0,
            modifierState,
            KeyCharacterMap.VIRTUAL_KEYBOARD,
            /* scancode = */0,
            /* flags = */0,
            InputDevice.SOURCE_KEYBOARD
        )
    }
}

private fun <T> whenever(methodCall: T): OngoingStubbing<T> = `when`(methodCall)