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

Commit 97186682 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

VirtualInputDeviceController: Use input device phys to identify device

Use the "phys" identifier to identify a virtual input device upon
creation, instead of using the name. The input device name is part of
the exposed API surfaces, so we should not have artificial requirements
in such surfaces, like requiring the name to be unique. Since the phys
is uniquely generated by the system, it should be used to uniquely
identify the device instead.

Bug: 443074681
Bug: 443736238
Test: atest InputTests, manual with hellocomputercontrol app
Flag: EXEMPT bug fix
Change-Id: I97fe38ae251bc686561924e1a3f888bcae9da391
parent 452a21f9
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -4221,6 +4221,11 @@ public class InputManagerService extends IInputManager.Stub
        }
    }

    @Nullable
    String getPhysicalLocationPath(int deviceId) {
        return mNative.getPhysicalLocationPath(deviceId);
    }

    interface KeyboardBacklightControllerInterface {
        default void incrementKeyboardBacklight(int deviceId) {}
        default void decrementKeyboardBacklight(int deviceId) {}
+10 −0
Original line number Diff line number Diff line
@@ -345,6 +345,13 @@ interface NativeInputManagerService {
     */
    void setAccessibilityPointerMotionFilterEnabled(boolean enabled);

    /**
     * Get the physical location path of the input device, if known. This is also known as the
     * "phys" identifier.
     */
    @Nullable
    String getPhysicalLocationPath(int deviceId);

    /** The native implementation of InputManagerService methods. */
    class NativeImpl implements NativeInputManagerService {
        /** Pointer to native input manager service object, used by native code. */
@@ -673,5 +680,8 @@ interface NativeInputManagerService {

        @Override
        public native void setAccessibilityPointerMotionFilterEnabled(boolean enabled);

        @Override
        public native String getPhysicalLocationPath(int deviceId);
    }
}
+7 −2
Original line number Diff line number Diff line
@@ -771,7 +771,8 @@ class VirtualInputDeviceController {

        private int mInputDeviceId = IInputConstants.INVALID_INPUT_DEVICE_ID;

        WaitForDevice(String deviceName, int vendorId, int productId, int associatedDisplayId) {
        WaitForDevice(@NonNull String phys, @NonNull String deviceName, int vendorId, int productId,
                int associatedDisplayId) {
            mDeviceName = deviceName;
            mListener = new InputDeviceListener() {
                @Override
@@ -799,6 +800,9 @@ class VirtualInputDeviceController {
                    if (!device.getName().equals(deviceName)) {
                        return false;
                    }
                    if (!phys.equals(mService.getPhysicalLocationPath(deviceId))) {
                        return false;
                    }
                    final InputDeviceIdentifier id = device.getIdentifier();
                    if (id.getVendorId() != vendorId || id.getProductId() != productId) {
                        return false;
@@ -893,7 +897,8 @@ class VirtualInputDeviceController {
        if (disableSettingsForVirtualDevices()) {
            mService.addVirtualDevice(phys);
        }
        try (WaitForDevice waiter = new WaitForDevice(deviceName, vendorId, productId, displayId)) {
        try (WaitForDevice waiter = new WaitForDevice(phys, deviceName, vendorId, productId,
                displayId)) {
            ptr = deviceOpener.get();
            // See INVALID_PTR in libs/input/VirtualInputDevice.cpp.
            if (ptr == 0) {
+7 −0
Original line number Diff line number Diff line
@@ -3338,6 +3338,12 @@ static void nativeSetAccessibilityPointerMotionFilterEnabled(JNIEnv* env, jobjec
    im->getInputManager()->getChoreographer().setAccessibilityPointerMotionFilterEnabled(enabled);
}

static jstring nativeGetPhysicalLocationPath(JNIEnv* env, jobject nativeImplObj, jint deviceId) {
    NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
    const auto phys = im->getInputManager()->getReader().getPhysicalLocationPath(deviceId);
    return !phys.has_value() || phys->empty() ? nullptr : env->NewStringUTF(phys->c_str());
}

// ----------------------------------------------------------------------------

static const JNINativeMethod gInputManagerMethods[] = {
@@ -3473,6 +3479,7 @@ static const JNINativeMethod gInputManagerMethods[] = {
        {"setKernelWakeEnabled", "(IZ)Z", (void*)nativeSetKernelWakeEnabled},
        {"setAccessibilityPointerMotionFilterEnabled", "(Z)V",
         (void*)nativeSetAccessibilityPointerMotionFilterEnabled},
        {"getPhysicalLocationPath", "(I)Ljava/lang/String;", (void*)nativeGetPhysicalLocationPath},
};

#define FIND_CLASS(var, className) \
+20 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.SparseArray;
import android.view.DisplayInfo;
import android.view.InputDevice;
import android.view.KeyEvent;
@@ -87,6 +88,8 @@ public class VirtualInputDeviceControllerTest {
    private InputManagerGlobal.TestSession mInputSession;
    private final List<InputDevice> mDevices = new ArrayList<>();
    private IInputDevicesChangedListener mDevicesChangedListener;
    // deviceId -> phys
    private final SparseArray<String> mPhysByDeviceId = new SparseArray<>();
    // uniqueId -> displayId
    private final Map<String, Integer> mDisplayIdMapping = new HashMap<>();
    // phys -> uniqueId
@@ -131,6 +134,8 @@ public class VirtualInputDeviceControllerTest {
                .when(mInputManagerService).addVirtualDevice(anyString());
        doAnswer(inv -> mVirtualDevices.remove(inv.getArgument(0)))
                .when(mInputManagerService).removeVirtualDevice(anyString());
        doAnswer(inv -> mPhysByDeviceId.get(inv.getArgument(0)))
                .when(mInputManagerService).getPhysicalLocationPath(anyInt());


        // Set a new instance of InputManager for testing that uses the IInputManager mock as the
@@ -177,6 +182,7 @@ public class VirtualInputDeviceControllerTest {
                .setAssociatedDisplayId(mDisplayIdMapping.get(mUniqueIdAssociationByPort.get(phys)))
                .build();
        mDevices.add(device);
        mPhysByDeviceId.put(device.getId(), phys);
        try {
            mDevicesChangedListener.onInputDevicesChanged(
                    mDevices.stream().flatMapToInt(
@@ -238,6 +244,20 @@ public class VirtualInputDeviceControllerTest {
                        NAME_2, VENDOR_ID, PRODUCT_ID, TOKEN_1, DISPLAY_ID_2));
    }

    @Test
    public void createInputDevice_differentDevices_haveUniquePhys() throws RemoteException {
        final int d1 = mInputController.createDpad(NAME, VENDOR_ID, PRODUCT_ID, TOKEN_1,
                DISPLAY_ID_1).getInputDeviceId();
        final int d2 = mInputController.createDpad(NAME_2, VENDOR_ID, PRODUCT_ID, TOKEN_2,
                DISPLAY_ID_1).getInputDeviceId();

        final String phys1 = mPhysByDeviceId.get(d1);
        final String phys2 = mPhysByDeviceId.get(d2);
        assertThat(phys1).isNotEmpty();
        assertThat(phys2).isNotEmpty();
        assertThat(phys1).isNotEqualTo(phys2);
    }

    @Test
    public void getCursorPosition_returnsPositionFromService() {
        mInputController.createMouse(NAME, VENDOR_ID, PRODUCT_ID, TOKEN_1, DISPLAY_ID_1);