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

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

Merge "Add support for customizing touchpad 3-finger tap" into main

parents 2ba21d45 b8813113
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -19,13 +19,26 @@ package android.hardware.input;
/** @hide */
@JavaDerive(equals=true)
parcelable AidlInputGestureData {
    int keycode;
    int modifierState;
    int gestureType;
    Trigger trigger;

    // App launch parameters: Only set if gestureType is KEY_GESTURE_TYPE_LAUNCH_APPLICATION
    int gestureType;
    // App launch parameters (Only set if gestureType is LAUNCH_APPLICATION)
    String appLaunchCategory;
    String appLaunchRole;
    String appLaunchPackageName;
    String appLaunchClassName;

    parcelable KeyTrigger {
        int keycode;
        int modifierState;
    }

    parcelable TouchpadGestureTrigger {
        int gestureType;
    }

    union Trigger {
        KeyTrigger key;
        TouchpadGestureTrigger touchpadGesture;
    }
}
+76 −26
Original line number Diff line number Diff line
@@ -35,20 +35,40 @@ import java.util.Objects;
 */
public final class InputGestureData {

    public static final int TOUCHPAD_GESTURE_TYPE_UNKNOWN = 0;
    public static final int TOUCHPAD_GESTURE_TYPE_THREE_FINGER_TAP = 1;

    @NonNull
    private final AidlInputGestureData mInputGestureData;

    public InputGestureData(AidlInputGestureData inputGestureData) {
    public InputGestureData(@NonNull AidlInputGestureData inputGestureData) {
        this.mInputGestureData = inputGestureData;
        validate();
    }

    /** Returns the trigger information for this input gesture */
    public Trigger getTrigger() {
        if (mInputGestureData.keycode != KeyEvent.KEYCODE_UNKNOWN) {
            return new KeyTrigger(mInputGestureData.keycode, mInputGestureData.modifierState);
        switch (mInputGestureData.trigger.getTag()) {
            case AidlInputGestureData.Trigger.Tag.key: {
                AidlInputGestureData.KeyTrigger trigger = mInputGestureData.trigger.getKey();
                if (trigger == null) {
                    throw new RuntimeException("InputGestureData is corrupted, null key trigger!");
                }
                return createKeyTrigger(trigger.keycode, trigger.modifierState);
            }
            case AidlInputGestureData.Trigger.Tag.touchpadGesture: {
                AidlInputGestureData.TouchpadGestureTrigger trigger =
                        mInputGestureData.trigger.getTouchpadGesture();
                if (trigger == null) {
                    throw new RuntimeException(
                            "InputGestureData is corrupted, null touchpad trigger!");
                }
                return createTouchpadTrigger(trigger.gestureType);
            }
            default:
                throw new RuntimeException("InputGestureData is corrupted, invalid trigger type!");

        }
    }

    /** Returns the action to perform for this input gesture */
@@ -127,9 +147,15 @@ public final class InputGestureData {
                        "No app launch data for system action launch application");
            }
            AidlInputGestureData data = new AidlInputGestureData();
            data.trigger = new AidlInputGestureData.Trigger();
            if (mTrigger instanceof KeyTrigger keyTrigger) {
                data.keycode = keyTrigger.getKeycode();
                data.modifierState = keyTrigger.getModifierState();
                data.trigger.setKey(new AidlInputGestureData.KeyTrigger());
                data.trigger.getKey().keycode = keyTrigger.getKeycode();
                data.trigger.getKey().modifierState = keyTrigger.getModifierState();
            } else if (mTrigger instanceof TouchpadTrigger touchpadTrigger) {
                data.trigger.setTouchpadGesture(new AidlInputGestureData.TouchpadGestureTrigger());
                data.trigger.getTouchpadGesture().gestureType =
                        touchpadTrigger.getTouchpadGestureType();
            } else {
                throw new IllegalArgumentException("Invalid trigger type!");
            }
@@ -163,30 +189,12 @@ public final class InputGestureData {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        InputGestureData that = (InputGestureData) o;
        return mInputGestureData.keycode == that.mInputGestureData.keycode
                && mInputGestureData.modifierState == that.mInputGestureData.modifierState
                && mInputGestureData.gestureType == that.mInputGestureData.gestureType
                && Objects.equals(mInputGestureData.appLaunchCategory, that.mInputGestureData.appLaunchCategory)
                && Objects.equals(mInputGestureData.appLaunchRole, that.mInputGestureData.appLaunchRole)
                && Objects.equals(mInputGestureData.appLaunchPackageName, that.mInputGestureData.appLaunchPackageName)
                && Objects.equals(mInputGestureData.appLaunchPackageName, that.mInputGestureData.appLaunchPackageName);
        return Objects.equals(mInputGestureData, that.mInputGestureData);
    }

    @Override
    public int hashCode() {
        int _hash = 1;
        _hash = 31 * _hash + mInputGestureData.keycode;
        _hash = 31 * _hash + mInputGestureData.modifierState;
        _hash = 31 * _hash + mInputGestureData.gestureType;
        _hash = 31 * _hash + (mInputGestureData.appLaunchCategory != null
                ? mInputGestureData.appLaunchCategory.hashCode() : 0);
        _hash = 31 * _hash + (mInputGestureData.appLaunchRole != null
                ? mInputGestureData.appLaunchRole.hashCode() : 0);
        _hash = 31 * _hash + (mInputGestureData.appLaunchPackageName != null
                ? mInputGestureData.appLaunchPackageName.hashCode() : 0);
        _hash = 31 * _hash + (mInputGestureData.appLaunchPackageName != null
                ? mInputGestureData.appLaunchPackageName.hashCode() : 0);
        return _hash;
        return mInputGestureData.hashCode();
    }

    public interface Trigger {
@@ -197,6 +205,11 @@ public final class InputGestureData {
        return new KeyTrigger(keycode, modifierState);
    }

    /** Creates a input gesture trigger based on a touchpad gesture */
    public static Trigger createTouchpadTrigger(int touchpadGestureType) {
        return new TouchpadTrigger(touchpadGestureType);
    }

    /** Key based input gesture trigger */
    public static class KeyTrigger implements Trigger {
        private static final int SHORTCUT_META_MASK =
@@ -242,6 +255,43 @@ public final class InputGestureData {
        }
    }

    /** Touchpad based input gesture trigger */
    public static class TouchpadTrigger implements Trigger {
        private final int mTouchpadGestureType;

        private TouchpadTrigger(int touchpadGestureType) {
            if (touchpadGestureType != TOUCHPAD_GESTURE_TYPE_THREE_FINGER_TAP) {
                throw new IllegalArgumentException(
                        "Invalid touchpadGestureType = " + touchpadGestureType);
            }
            mTouchpadGestureType = touchpadGestureType;
        }

        public int getTouchpadGestureType() {
            return mTouchpadGestureType;
        }

        @Override
        public String toString() {
            return "TouchpadTrigger{" +
                    "mTouchpadGestureType=" + mTouchpadGestureType +
                    '}';
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            TouchpadTrigger that = (TouchpadTrigger) o;
            return mTouchpadGestureType == that.mTouchpadGestureType;
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(mTouchpadGestureType);
        }
    }

    /** Data for action to perform when input gesture is triggered */
    public record Action(@KeyGestureEvent.KeyGestureType int keyGestureType,
                         @Nullable AppLaunchData appLaunchData) {
+16 −0
Original line number Diff line number Diff line
@@ -361,6 +361,22 @@ final class InputGestureManager {
        }
    }

    @Nullable
    public InputGestureData getCustomGestureForTouchpadGesture(@UserIdInt int userId,
            int touchpadGestureType) {
        if (touchpadGestureType == InputGestureData.TOUCHPAD_GESTURE_TYPE_UNKNOWN) {
            return null;
        }
        synchronized (mGestureLock) {
            Map<InputGestureData.Trigger, InputGestureData> customGestures =
                    mCustomInputGestures.get(userId);
            if (customGestures == null) {
                return null;
            }
            return customGestures.get(InputGestureData.createTouchpadTrigger(touchpadGestureType));
        }
    }

    @Nullable
    public InputGestureData getSystemShortcutForKeyEvent(KeyEvent event) {
        final int keyCode = event.getKeyCode();
+3 −1
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import android.hardware.input.IKeyboardBacklightListener;
import android.hardware.input.IStickyModifierStateListener;
import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputGestureData;
import android.hardware.input.InputManager;
import android.hardware.input.InputSensorInfo;
import android.hardware.input.InputSettings;
@@ -2314,7 +2315,8 @@ public class InputManagerService extends IInputManager.Stub
    // Native callback.
    @SuppressWarnings("unused")
    private void notifyTouchpadThreeFingerTap() {
        mKeyGestureController.handleTouchpadThreeFingerTap();
        mKeyGestureController.handleTouchpadGesture(
                InputGestureData.TOUCHPAD_GESTURE_TYPE_THREE_FINGER_TAP);
    }

    // Native callback.
+19 −4
Original line number Diff line number Diff line
@@ -847,6 +847,13 @@ final class KeyGestureController {
                /* appLaunchData = */null);
    }

    private void handleTouchpadGesture(@KeyGestureEvent.KeyGestureType int keyGestureType,
            @Nullable AppLaunchData appLaunchData) {
        handleKeyGesture(KeyCharacterMap.VIRTUAL_KEYBOARD, new int[0], /* modifierState= */0,
                keyGestureType, KeyGestureEvent.ACTION_GESTURE_COMPLETE,
                Display.DEFAULT_DISPLAY, /* focusedToken = */null, /* flags = */0, appLaunchData);
    }

    @VisibleForTesting
    boolean handleKeyGesture(int deviceId, int[] keycodes, int modifierState,
            @KeyGestureEvent.KeyGestureType int gestureType, int action, int displayId,
@@ -897,11 +904,18 @@ final class KeyGestureController {
        handleKeyGesture(event, null /*focusedToken*/);
    }

    public void handleTouchpadThreeFingerTap() {
        // TODO(b/365063048): trigger a custom shortcut based on the three-finger tap.
        if (DEBUG) {
            Slog.d(TAG, "Three-finger touchpad tap occurred");
    public void handleTouchpadGesture(int touchpadGestureType) {
        // Handle custom shortcuts
        InputGestureData customGesture;
        synchronized (mUserLock) {
            customGesture = mInputGestureManager.getCustomGestureForTouchpadGesture(mCurrentUserId,
                    touchpadGestureType);
        }
        if (customGesture == null) {
            return;
        }
        handleTouchpadGesture(customGesture.getAction().keyGestureType(),
                customGesture.getAction().appLaunchData());
    }

    @MainThread
@@ -1214,6 +1228,7 @@ final class KeyGestureController {
    public void dump(IndentingPrintWriter ipw) {
        ipw.println("KeyGestureController:");
        ipw.increaseIndent();
        ipw.println("mCurrentUserId = " + mCurrentUserId);
        ipw.println("mSystemPid = " + mSystemPid);
        ipw.println("mPendingMetaAction = " + mPendingMetaAction);
        ipw.println("mPendingCapsLockToggle = " + mPendingCapsLockToggle);
Loading