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

Commit b6f1128f authored by Michael Crimando's avatar Michael Crimando Committed by Antonio Kantek
Browse files

Bind an input device via descriptor



These changes solve a problem for systems that have multiple displays
as well as 2 or more input devices with the exact same name. (e.g. 2
Xbox Series X controllers will report the exact same device name).

Currently the default behavior for overall Android is that input
device inputs go towards the last screen that the user touched.
On systems where a single computer is used for displaying content to
multiple people, this can be a problem. A user may be trying to play a
game with a controller on screen 1, while a second user tries to
browse the internet on screen 2. If the user on screen 2 touches the
screen, it'll keep sending the controller input events to screen 2
instead of the game on screen 1.

To fix this, the system can use a function to bind controllers to a
display. The system can just find an input device by device name
and make sure all inputs from that controller go to the correct
display. That ensures that no matter what, the controller inputs go to
the desired game on screen 1.

Now consider a single system with 2 screens and 2 different users
trying to play controller games. User A will want their controller
inputs to go to screen 1 and User B will want their controller inputs
to go to screen 2. This is possible with the current functionality.
That is, unless the controllers have the exact same device name. In
that case the controllers can only be locked to one screen or another.

Device names are not unique. However, descriptors are unique per
device. This would allow the system to uniquely identify each input
device and bind them to the correct screen.

Descriptors also cover certain scenarios. Such as a keyboard with a
track pad built into it. It'll be 2 different input devices with 2
different device names but the same descriptor.

Test: Built and run on hardware, (Adopted to run on Android 12L)
Test: Passed all tests under atest InputManagerServiceTests with lunch sdk_phone_x86_64-eng
Test: atest FrameworksServicesTests InputTests InputManagerServiceTests
Test: atest libsurfaceflinger_unittest
Bug: 324075859

Signed-off-by: default avatarMichael Crimando <mcriman1@ford.com>
Change-Id: I5c65b61652e5f4946d63d8ab7309093e49e65083
parent 85c0cb10
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -1763,14 +1763,16 @@ package android.hardware.input {
  }

  public final class InputManager {
    method public void addUniqueIdAssociation(@NonNull String, @NonNull String);
    method @FlaggedApi("com.android.input.flags.device_associations") @RequiresPermission("android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY") public void addUniqueIdAssociationByDescriptor(@NonNull String, @NonNull String);
    method @FlaggedApi("com.android.input.flags.device_associations") @RequiresPermission("android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY") public void addUniqueIdAssociationByPort(@NonNull String, @NonNull String);
    method @RequiresPermission(android.Manifest.permission.REMAP_MODIFIER_KEYS) public void clearAllModifierKeyRemappings();
    method @NonNull public java.util.List<java.lang.String> getKeyboardLayoutDescriptors();
    method @NonNull public String getKeyboardLayoutTypeForLayoutDescriptor(@NonNull String);
    method @NonNull @RequiresPermission(android.Manifest.permission.REMAP_MODIFIER_KEYS) public java.util.Map<java.lang.Integer,java.lang.Integer> getModifierKeyRemapping();
    method public int getMousePointerSpeed();
    method @RequiresPermission(android.Manifest.permission.REMAP_MODIFIER_KEYS) public void remapModifierKey(int, int);
    method public void removeUniqueIdAssociation(@NonNull String);
    method @FlaggedApi("com.android.input.flags.device_associations") @RequiresPermission("android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY") public void removeUniqueIdAssociationByDescriptor(@NonNull String);
    method @FlaggedApi("com.android.input.flags.device_associations") @RequiresPermission("android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY") public void removeUniqueIdAssociationByPort(@NonNull String);
    field public static final long BLOCK_UNTRUSTED_TOUCHES = 158002302L; // 0x96aec7eL
  }

+8 −0
Original line number Diff line number Diff line
@@ -977,8 +977,16 @@ RequiresPermission: android.hardware.hdmi.HdmiControlManager#setHdmiCecVersion(i
    Method 'setHdmiCecVersion' documentation mentions permissions already declared by @RequiresPermission
RequiresPermission: android.hardware.input.InputManager#addUniqueIdAssociation(String, String):
    Method 'addUniqueIdAssociation' documentation mentions permissions without declaring @RequiresPermission
RequiresPermission: android.hardware.input.InputManager#addUniqueIdAssociationByDescriptor(String, String):
    Method 'addUniqueIdAssociationByDescriptor' documentation mentions permissions already declared by @RequiresPermission
RequiresPermission: android.hardware.input.InputManager#addUniqueIdAssociationByPort(String, String):
    Method 'addUniqueIdAssociationByPort' documentation mentions permissions already declared by @RequiresPermission
RequiresPermission: android.hardware.input.InputManager#removeUniqueIdAssociation(String):
    Method 'removeUniqueIdAssociation' documentation mentions permissions without declaring @RequiresPermission
RequiresPermission: android.hardware.input.InputManager#removeUniqueIdAssociationByDescriptor(String):
    Method 'removeUniqueIdAssociationByDescriptor' documentation mentions permissions already declared by @RequiresPermission
RequiresPermission: android.hardware.input.InputManager#removeUniqueIdAssociationByPort(String):
    Method 'removeUniqueIdAssociationByPort' documentation mentions permissions already declared by @RequiresPermission
RequiresPermission: android.hardware.location.GeofenceHardware#addGeofence(int, int, android.hardware.location.GeofenceHardwareRequest, android.hardware.location.GeofenceHardwareCallback):
    Method 'addGeofence' documentation mentions permissions without declaring @RequiresPermission
RequiresPermission: android.hardware.location.GeofenceHardware#getMonitoringTypes():
+11 −4
Original line number Diff line number Diff line
@@ -165,10 +165,17 @@ interface IInputManager {
    // static association for the cleared input port will be restored.
    void removePortAssociation(in String inputPort);

    // Add a runtime association between the input device and display.
    void addUniqueIdAssociation(in String inputPort, in String displayUniqueId);
    // Remove the runtime association between the input device and display.
    void removeUniqueIdAssociation(in String inputPort);
    // Add a runtime association between the input device and display, using device's descriptor.
    void addUniqueIdAssociationByDescriptor(in String inputDeviceDescriptor,
            in String displayUniqueId);
    // Remove the runtime association between the input device and display, using device's
    // descriptor.
    void removeUniqueIdAssociationByDescriptor(in String inputDeviceDescriptor);

    // Add a runtime association between the input device and display, using device's port.
    void addUniqueIdAssociationByPort(in String inputPort, in String displayUniqueId);
    // Remove the runtime association between the input device and display, using device's port.
    void removeUniqueIdAssociationByPort(in String inputPort);

    InputSensorInfo[] getSensorList(int deviceId);

+57 −10
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.hardware.input;

import static com.android.input.flags.Flags.FLAG_INPUT_DEVICE_VIEW_BEHAVIOR_API;
import static com.android.input.flags.Flags.FLAG_DEVICE_ASSOCIATIONS;
import static com.android.hardware.input.Flags.keyboardLayoutPreviewFlag;

import android.Manifest;
@@ -1054,13 +1055,14 @@ public final class InputManager {
    /**
     * Add a runtime association between the input port and the display port. This overrides any
     * static associations.
     * @param inputPort The port of the input device.
     * @param displayPort The physical port of the associated display.
     * @param inputPort the port of the input device
     * @param displayPort the physical port of the associated display
     * <p>
     * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY)
    public void addPortAssociation(@NonNull String inputPort, int displayPort) {
        try {
            mIm.addPortAssociation(inputPort, displayPort);
@@ -1072,12 +1074,13 @@ public final class InputManager {
    /**
     * Remove the runtime association between the input port and the display port. Any existing
     * static association for the cleared input port will be restored.
     * @param inputPort The port of the input device to be cleared.
     * @param inputPort the port of the input device to be cleared
     * <p>
     * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY)
    public void removePortAssociation(@NonNull String inputPort) {
        try {
            mIm.removePortAssociation(inputPort);
@@ -1089,30 +1092,74 @@ public final class InputManager {
    /**
     * Add a runtime association between the input port and display, by unique id. Input ports are
     * expected to be unique.
     * @param inputPort The port of the input device.
     * @param displayUniqueId The unique id of the associated display.
     * @param inputPort the port of the input device
     * @param displayUniqueId the unique id of the associated display
     * <p>
     * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
    @FlaggedApi(FLAG_DEVICE_ASSOCIATIONS)
    @RequiresPermission(android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY)
    @TestApi
    public void addUniqueIdAssociation(@NonNull String inputPort,
    public void addUniqueIdAssociationByPort(@NonNull String inputPort,
            @NonNull String displayUniqueId) {
        mGlobal.addUniqueIdAssociation(inputPort, displayUniqueId);
        mGlobal.addUniqueIdAssociationByPort(inputPort, displayUniqueId);
    }

    /**
     * Removes a runtime association between the input device and display.
     * @param inputPort The port of the input device.
     * @param inputPort the port of the input device
     * <p>
     * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
    @FlaggedApi(FLAG_DEVICE_ASSOCIATIONS)
    @RequiresPermission(android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY)
    @TestApi
    public void removeUniqueIdAssociation(@NonNull String inputPort) {
        mGlobal.removeUniqueIdAssociation(inputPort);
    public void removeUniqueIdAssociationByPort(@NonNull String inputPort) {
        mGlobal.removeUniqueIdAssociationByPort(inputPort);
    }

    /**
     * Add a runtime association between the input device name and display, by descriptor. Input
     * device descriptors are expected to be unique per physical device, though one physical
     * device can have multiple virtual input devices that possess the same descriptor.
     * E.g. a keyboard with built in trackpad will be 2 different input devices with the same
     * descriptor.
     * @param inputDeviceDescriptor the descriptor of the input device
     * @param displayUniqueId the unique id of the associated display
     * <p>
     * Requires {@link android.Manifest.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
    @FlaggedApi(FLAG_DEVICE_ASSOCIATIONS)
    @RequiresPermission(android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY)
    @TestApi
    public void addUniqueIdAssociationByDescriptor(@NonNull String inputDeviceDescriptor,
                                                   @NonNull String displayUniqueId) {
        mGlobal.addUniqueIdAssociationByDescriptor(inputDeviceDescriptor, displayUniqueId);
    }

    /**
     * Removes a runtime association between the input device and display.
    }

    /**
     * Removes a runtime association between the input device and display.
     * @param inputDeviceDescriptor the descriptor of the input device
     * <p>
     * Requires {@link android.Manifest.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
    @FlaggedApi(FLAG_DEVICE_ASSOCIATIONS)
    @RequiresPermission(android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY)
    @TestApi
    public void removeUniqueIdAssociationByDescriptor(@NonNull String inputDeviceDescriptor) {
        mGlobal.removeUniqueIdAssociationByDescriptor(inputDeviceDescriptor);
    }

    /**
+30 −6
Original line number Diff line number Diff line
@@ -1467,22 +1467,46 @@ public final class InputManagerGlobal {
    }

    /**
     * @see InputManager#addUniqueIdAssociation(String, String)
     * @see InputManager#addUniqueIdAssociationByPort(String, String)
     */
    public void addUniqueIdAssociation(@NonNull String inputPort, @NonNull String displayUniqueId) {
    public void addUniqueIdAssociationByPort(@NonNull String inputPort,
                                             @NonNull String displayUniqueId) {
        try {
            mIm.addUniqueIdAssociation(inputPort, displayUniqueId);
            mIm.addUniqueIdAssociationByPort(inputPort, displayUniqueId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @see InputManager#removeUniqueIdAssociation(String)
     * @see InputManager#removeUniqueIdAssociationByPort(String)
     */
    public void removeUniqueIdAssociation(@NonNull String inputPort) {
    public void removeUniqueIdAssociationByPort(@NonNull String inputPort) {
        try {
            mIm.removeUniqueIdAssociation(inputPort);
            mIm.removeUniqueIdAssociationByPort(inputPort);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @see InputManager#addUniqueIdAssociationByDescriptor(String, String)
     */
    public void addUniqueIdAssociationByDescriptor(@NonNull String inputDeviceDescriptor,
                                                   @NonNull String displayUniqueId) {
        try {
            mIm.addUniqueIdAssociationByDescriptor(inputDeviceDescriptor, displayUniqueId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @see InputManager#removeUniqueIdAssociationByDescriptor(String)
     */
    public void removeUniqueIdAssociationByDescriptor(@NonNull String inputDeviceDescriptor) {
        try {
            mIm.removeUniqueIdAssociationByDescriptor(inputDeviceDescriptor);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
Loading