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

Commit 99f50234 authored by Vaibhav Devmurari's avatar Vaibhav Devmurari Committed by Android (Google) Code Review
Browse files

Merge "Shift Key gestures handled by InputManager to IMS from PWM" into main

parents 58f9db23 067ba845
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)