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

Commit b03a7b7d authored by Sandro Meier's avatar Sandro Meier
Browse files

Add id to InputDeviceDesc of VirtualInputDevice

Virtual input devices did not store the deviceId as this was not needed.
This change stores the deviceId during the device initialization (deviceId
is given to InputDeviceListener callback, which is used to wait for a
virtual device to be initialized and configured)

The deviceId is needed to restrict an input device to a display group.

Bug: 244516415
Test: atest android.hardware.input.cts.tests.VirtualKeyboardTest
Change-Id: I982191d543556e2728e41d6da01ab1a631e50e1a
parent cd4d015a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ interface IVirtualDevice {
            IBinder token,
            in Point screenSize);
    void unregisterInputDevice(IBinder token);
    int getInputDeviceId(IBinder token);
    boolean sendDpadKeyEvent(IBinder token, in VirtualKeyEvent event);
    boolean sendKeyEvent(IBinder token, in VirtualKeyEvent event);
    boolean sendButtonEvent(IBinder token, in VirtualMouseButtonEvent event);
+11 −0
Original line number Diff line number Diff line
@@ -49,6 +49,17 @@ abstract class VirtualInputDevice implements Closeable {
        mToken = token;
    }

    /**
     * @return The device id of this device.
     * @hide
     */
    public int getInputDeviceId() {
        try {
            return mVirtualDevice.getInputDeviceId(mToken);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    @Override
    @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+57 −6
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.hardware.input.VirtualMouseScrollEvent;
import android.hardware.input.VirtualTouchEvent;
import android.os.Handler;
import android.os.IBinder;
import android.os.IInputConstants;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Slog;
@@ -75,7 +76,7 @@ class InputController {
    @interface PhysType {
    }

    private final Object mLock;
    final Object mLock;

    /* Token -> file descriptor associations. */
    @VisibleForTesting
@@ -220,6 +221,19 @@ class InputController {
        }
    }

    /**
     * @return the device id for a given token (identifiying a device)
     */
    int getInputDeviceId(IBinder token) {
        synchronized (mLock) {
            final InputDeviceDescriptor inputDeviceDescriptor = mInputDeviceDescriptors.get(token);
            if (inputDeviceDescriptor == null) {
                throw new IllegalArgumentException("Could not get device id for given token");
            }
            return inputDeviceDescriptor.getInputDeviceId();
        }
    }

    void setShowPointerIcon(boolean visible, int displayId) {
        mInputManagerInternal.setPointerIconVisible(visible, displayId);
    }
@@ -393,8 +407,20 @@ class InputController {
                        + inputDeviceDescriptor.getCreationOrderNumber());
                fout.println("          type: " + inputDeviceDescriptor.getType());
                fout.println("          phys: " + inputDeviceDescriptor.getPhys());
                fout.println(
                        "          inputDeviceId: " + inputDeviceDescriptor.getInputDeviceId());
            }
        }
    }

    @VisibleForTesting
    void addDeviceForTesting(IBinder deviceToken, int fd, int type, int displayId,
            String phys, int inputDeviceId) {
        synchronized (mLock) {
            mInputDeviceDescriptors.put(deviceToken,
                    new InputDeviceDescriptor(fd, () -> {}, type, displayId, phys,
                            inputDeviceId));
        }
    }

    private static native int nativeOpenUinputDpad(String deviceName, int vendorId,
@@ -493,16 +519,20 @@ class InputController {
        private final @Type int mType;
        private final int mDisplayId;
        private final String mPhys;
        // The input device id that was associated to the device by the InputReader on device
        // creation.
        private final int mInputDeviceId;
        // Monotonically increasing number; devices with lower numbers were created earlier.
        private final long mCreationOrderNumber;

        InputDeviceDescriptor(int fd, IBinder.DeathRecipient deathRecipient, @Type int type,
                int displayId, String phys) {
                int displayId, String phys, int inputDeviceId) {
            mFd = fd;
            mDeathRecipient = deathRecipient;
            mType = type;
            mDisplayId = displayId;
            mPhys = phys;
            mInputDeviceId = inputDeviceId;
            mCreationOrderNumber = sNextCreationOrderNumber.getAndIncrement();
        }

@@ -533,6 +563,10 @@ class InputController {
        public String getPhys() {
            return mPhys;
        }

        public int getInputDeviceId() {
            return mInputDeviceId;
        }
    }

    private final class BinderDeathRecipient implements IBinder.DeathRecipient {
@@ -558,6 +592,8 @@ class InputController {
        private final CountDownLatch mDeviceAddedLatch = new CountDownLatch(1);
        private final InputManager.InputDeviceListener mListener;

        private int mInputDeviceId = IInputConstants.INVALID_INPUT_DEVICE_ID;

        WaitForDevice(String deviceName, int vendorId, int productId) {
            mListener = new InputManager.InputDeviceListener() {
                @Override
@@ -572,6 +608,7 @@ class InputController {
                    if (id.getVendorId() != vendorId || id.getProductId() != productId) {
                        return;
                    }
                    mInputDeviceId = deviceId;
                    mDeviceAddedLatch.countDown();
                }

@@ -588,8 +625,13 @@ class InputController {
            InputManager.getInstance().registerInputDeviceListener(mListener, mHandler);
        }

        /** Note: This must not be called from {@link #mHandler}'s thread. */
        void waitForDeviceCreation() throws DeviceCreationException {
        /**
         * Note: This must not be called from {@link #mHandler}'s thread.
         * @throws DeviceCreationException if the device was not created successfully within the
         * timeout.
         * @return The id of the created input device.
         */
        int waitForDeviceCreation() throws DeviceCreationException {
            try {
                if (!mDeviceAddedLatch.await(1, TimeUnit.MINUTES)) {
                    throw new DeviceCreationException(
@@ -599,6 +641,12 @@ class InputController {
                throw new DeviceCreationException(
                        "Interrupted while waiting for virtual device to be created.", e);
            }
            if (mInputDeviceId == IInputConstants.INVALID_INPUT_DEVICE_ID) {
                throw new IllegalStateException(
                        "Virtual input device was created with an invalid "
                                + "id=" + mInputDeviceId);
            }
            return mInputDeviceId;
        }

        @Override
@@ -643,6 +691,8 @@ class InputController {
        final int fd;
        final BinderDeathRecipient binderDeathRecipient;

        final int inputDeviceId;

        setUniqueIdAssociation(displayId, phys);
        try (WaitForDevice waiter = new WaitForDevice(deviceName, vendorId, productId)) {
            fd = deviceOpener.get();
@@ -652,7 +702,7 @@ class InputController {
            }
            // The fd is valid from here, so ensure that all failures close the fd after this point.
            try {
                waiter.waitForDeviceCreation();
                inputDeviceId = waiter.waitForDeviceCreation();

                binderDeathRecipient = new BinderDeathRecipient(deviceToken);
                try {
@@ -672,7 +722,8 @@ class InputController {

        synchronized (mLock) {
            mInputDeviceDescriptors.put(deviceToken,
                    new InputDeviceDescriptor(fd, binderDeathRecipient, type, displayId, phys));
                    new InputDeviceDescriptor(fd, binderDeathRecipient, type, displayId, phys,
                            inputDeviceId));
        }
    }

+11 −0
Original line number Diff line number Diff line
@@ -497,6 +497,17 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
        }
    }

    @Override // Binder call
    public int getInputDeviceId(IBinder token) {
        final long binderToken = Binder.clearCallingIdentity();
        try {
            return mInputController.getInputDeviceId(token);
        } finally {
            Binder.restoreCallingIdentity(binderToken);
        }
    }


    @Override // Binder call
    public boolean sendDpadKeyEvent(IBinder token, VirtualKeyEvent event) {
        final long binderToken = Binder.clearCallingIdentity();
+28 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.companion.virtual;

import static com.google.common.truth.Truth.assertWithMessage;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -25,6 +27,7 @@ import static org.mockito.Mockito.verify;

import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.IInputManager;
import android.hardware.input.InputManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -87,6 +90,30 @@ public class InputControllerTest {
                threadVerifier);
    }

    @Test
    public void registerInputDevice_deviceCreation_hasDeviceId() {
        final IBinder device1Token = new Binder("device1");
        mInputController.createMouse("mouse", /*vendorId= */ 1, /*productId= */ 1, device1Token,
                /* displayId= */ 1);
        int device1Id = mInputController.getInputDeviceId(device1Token);

        final IBinder device2Token = new Binder("device2");
        mInputController.createKeyboard("keyboard", /*vendorId= */2, /*productId= */ 2,
                device2Token, 2);
        int device2Id = mInputController.getInputDeviceId(device2Token);

        assertWithMessage("Different devices should have different id").that(
                device1Id).isNotEqualTo(device2Id);


        int[] deviceIds = InputManager.getInstance().getInputDeviceIds();
        assertWithMessage("InputManager's deviceIds list should contain id of device 1").that(
                deviceIds).asList().contains(device1Id);
        assertWithMessage("InputManager's deviceIds list should contain id of device 2").that(
                deviceIds).asList().contains(device2Id);

    }

    @Test
    public void unregisterInputDevice_allMiceUnregistered_clearPointerDisplayId() {
        final IBinder deviceToken = new Binder();
@@ -115,4 +142,5 @@ public class InputControllerTest {
        mInputController.unregisterInputDevice(deviceToken);
        verify(mInputManagerInternalMock).setVirtualMousePointerDisplayId(eq(1));
    }

}
Loading