diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl index 0304815ef8fe2..27403ec4fe59f 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -122,9 +122,9 @@ interface IInputManager { void removePortAssociation(in String inputPort); // Add a runtime association between the input device and display. - void addUniqueIdAssociation(in String inputDeviceName, in String displayUniqueId); + void addUniqueIdAssociation(in String inputPort, in String displayUniqueId); // Remove the runtime association between the input device and display. - void removeUniqueIdAssociation(in String inputDeviceName); + void removeUniqueIdAssociation(in String inputPort); InputSensorInfo[] getSensorList(int deviceId); diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index cbc837393b6b7..979e9dd6a1f64 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -1359,19 +1359,18 @@ public final class InputManager { } /** - * Add a runtime association between the input device name and display, by unique id. Input - * device names are expected to be unique. - * @param inputDeviceName The name of the input device. + * 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. *

* Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}. *

* @hide */ - public void addUniqueIdAssociation(@NonNull String inputDeviceName, - @NonNull String displayUniqueId) { + public void addUniqueIdAssociation(@NonNull String inputPort, @NonNull String displayUniqueId) { try { - mIm.addUniqueIdAssociation(inputDeviceName, displayUniqueId); + mIm.addUniqueIdAssociation(inputPort, displayUniqueId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1379,15 +1378,15 @@ public final class InputManager { /** * Removes a runtime association between the input device and display. - * @param inputDeviceName The name of the input device. + * @param inputPort The port of the input device. *

* Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}. *

* @hide */ - public void removeUniqueIdAssociation(@NonNull String inputDeviceName) { + public void removeUniqueIdAssociation(@NonNull String inputPort) { try { - mIm.removeUniqueIdAssociation(inputDeviceName); + mIm.removeUniqueIdAssociation(inputPort); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/services/companion/java/com/android/server/companion/virtual/InputController.java b/services/companion/java/com/android/server/companion/virtual/InputController.java index 6c56e2f777f36..e6bfd1ff7f1aa 100644 --- a/services/companion/java/com/android/server/companion/virtual/InputController.java +++ b/services/companion/java/com/android/server/companion/virtual/InputController.java @@ -18,8 +18,11 @@ package com.android.server.companion.virtual; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.StringDef; import android.graphics.Point; import android.graphics.PointF; +import android.hardware.display.DisplayManagerInternal; +import android.hardware.input.InputManager; import android.hardware.input.InputManagerInternal; import android.hardware.input.VirtualKeyEvent; import android.hardware.input.VirtualMouseButtonEvent; @@ -48,6 +51,20 @@ class InputController { private static final String TAG = "VirtualInputController"; + private static final AtomicLong sNextPhysId = new AtomicLong(1); + + static final String PHYS_TYPE_KEYBOARD = "Keyboard"; + static final String PHYS_TYPE_MOUSE = "Mouse"; + static final String PHYS_TYPE_TOUCHSCREEN = "Touchscreen"; + @StringDef(prefix = { "PHYS_TYPE_" }, value = { + PHYS_TYPE_KEYBOARD, + PHYS_TYPE_MOUSE, + PHYS_TYPE_TOUCHSCREEN, + }) + @Retention(RetentionPolicy.SOURCE) + @interface PhysType { + } + private final Object mLock; /* Token -> file descriptor associations. */ @@ -56,6 +73,8 @@ class InputController { final Map mInputDeviceDescriptors = new ArrayMap<>(); private final NativeWrapper mNativeWrapper; + private final DisplayManagerInternal mDisplayManagerInternal; + private final InputManagerInternal mInputManagerInternal; /** * Because the pointer is a singleton, it can only be targeted at one display at a time. Because @@ -73,6 +92,8 @@ class InputController { mLock = lock; mNativeWrapper = nativeWrapper; mActivePointerDisplayId = Display.INVALID_DISPLAY; + mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); + mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); } void close() { @@ -90,7 +111,9 @@ class InputController { int productId, @NonNull IBinder deviceToken, int displayId) { - final int fd = mNativeWrapper.openUinputKeyboard(deviceName, vendorId, productId); + final String phys = createPhys(PHYS_TYPE_KEYBOARD); + setUniqueIdAssociation(displayId, phys); + final int fd = mNativeWrapper.openUinputKeyboard(deviceName, vendorId, productId, phys); if (fd < 0) { throw new RuntimeException( "A native error occurred when creating keyboard: " + -fd); @@ -99,7 +122,7 @@ class InputController { synchronized (mLock) { mInputDeviceDescriptors.put(deviceToken, new InputDeviceDescriptor(fd, binderDeathRecipient, - InputDeviceDescriptor.TYPE_KEYBOARD, displayId)); + InputDeviceDescriptor.TYPE_KEYBOARD, displayId, phys)); } try { deviceToken.linkToDeath(binderDeathRecipient, /* flags= */ 0); @@ -114,7 +137,9 @@ class InputController { int productId, @NonNull IBinder deviceToken, int displayId) { - final int fd = mNativeWrapper.openUinputMouse(deviceName, vendorId, productId); + final String phys = createPhys(PHYS_TYPE_MOUSE); + setUniqueIdAssociation(displayId, phys); + final int fd = mNativeWrapper.openUinputMouse(deviceName, vendorId, productId, phys); if (fd < 0) { throw new RuntimeException( "A native error occurred when creating mouse: " + -fd); @@ -123,11 +148,9 @@ class InputController { synchronized (mLock) { mInputDeviceDescriptors.put(deviceToken, new InputDeviceDescriptor(fd, binderDeathRecipient, - InputDeviceDescriptor.TYPE_MOUSE, displayId)); - final InputManagerInternal inputManagerInternal = - LocalServices.getService(InputManagerInternal.class); - inputManagerInternal.setVirtualMousePointerDisplayId(displayId); - inputManagerInternal.setPointerAcceleration(1); + InputDeviceDescriptor.TYPE_MOUSE, displayId, phys)); + mInputManagerInternal.setVirtualMousePointerDisplayId(displayId); + mInputManagerInternal.setPointerAcceleration(1); mActivePointerDisplayId = displayId; } try { @@ -144,7 +167,9 @@ class InputController { @NonNull IBinder deviceToken, int displayId, @NonNull Point screenSize) { - final int fd = mNativeWrapper.openUinputTouchscreen(deviceName, vendorId, productId, + final String phys = createPhys(PHYS_TYPE_TOUCHSCREEN); + setUniqueIdAssociation(displayId, phys); + final int fd = mNativeWrapper.openUinputTouchscreen(deviceName, vendorId, productId, phys, screenSize.y, screenSize.x); if (fd < 0) { throw new RuntimeException( @@ -154,7 +179,7 @@ class InputController { synchronized (mLock) { mInputDeviceDescriptors.put(deviceToken, new InputDeviceDescriptor(fd, binderDeathRecipient, - InputDeviceDescriptor.TYPE_TOUCHSCREEN, displayId)); + InputDeviceDescriptor.TYPE_TOUCHSCREEN, displayId, phys)); } try { deviceToken.linkToDeath(binderDeathRecipient, /* flags= */ 0); @@ -174,6 +199,7 @@ class InputController { } token.unlinkToDeath(inputDeviceDescriptor.getDeathRecipient(), /* flags= */ 0); mNativeWrapper.closeUinput(inputDeviceDescriptor.getFileDescriptor()); + InputManager.getInstance().removeUniqueIdAssociation(inputDeviceDescriptor.getPhys()); // Reset values to the default if all virtual mice are unregistered, or set display // id if there's another mouse (choose the most recent). @@ -197,9 +223,7 @@ class InputController { } } if (mostRecentlyCreatedMouse != null) { - final InputManagerInternal inputManagerInternal = - LocalServices.getService(InputManagerInternal.class); - inputManagerInternal.setVirtualMousePointerDisplayId( + mInputManagerInternal.setVirtualMousePointerDisplayId( mostRecentlyCreatedMouse.getDisplayId()); mActivePointerDisplayId = mostRecentlyCreatedMouse.getDisplayId(); } else { @@ -209,14 +233,21 @@ class InputController { } private void resetMouseValuesLocked() { - final InputManagerInternal inputManagerInternal = - LocalServices.getService(InputManagerInternal.class); - inputManagerInternal.setVirtualMousePointerDisplayId(Display.INVALID_DISPLAY); - inputManagerInternal.setPointerAcceleration( + mInputManagerInternal.setVirtualMousePointerDisplayId(Display.INVALID_DISPLAY); + mInputManagerInternal.setPointerAcceleration( IInputConstants.DEFAULT_POINTER_ACCELERATION); mActivePointerDisplayId = Display.INVALID_DISPLAY; } + private static String createPhys(@PhysType String type) { + return String.format("virtual%s:%d", type, sNextPhysId.getAndIncrement()); + } + + private void setUniqueIdAssociation(int displayId, String phys) { + final String displayUniqueId = mDisplayManagerInternal.getDisplayInfo(displayId).uniqueId; + InputManager.getInstance().addUniqueIdAssociation(phys, displayUniqueId); + } + boolean sendKeyEvent(@NonNull IBinder token, @NonNull VirtualKeyEvent event) { synchronized (mLock) { final InputDeviceDescriptor inputDeviceDescriptor = mInputDeviceDescriptors.get( @@ -321,17 +352,18 @@ class InputController { fout.println(" creationOrder: " + inputDeviceDescriptor.getCreationOrderNumber()); fout.println(" type: " + inputDeviceDescriptor.getType()); + fout.println(" phys: " + inputDeviceDescriptor.getPhys()); } fout.println(" Active mouse display id: " + mActivePointerDisplayId); } } private static native int nativeOpenUinputKeyboard(String deviceName, int vendorId, - int productId); - private static native int nativeOpenUinputMouse(String deviceName, int vendorId, - int productId); + int productId, String phys); + private static native int nativeOpenUinputMouse(String deviceName, int vendorId, int productId, + String phys); private static native int nativeOpenUinputTouchscreen(String deviceName, int vendorId, - int productId, int height, int width); + int productId, String phys, int height, int width); private static native boolean nativeCloseUinput(int fd); private static native boolean nativeWriteKeyEvent(int fd, int androidKeyCode, int action); private static native boolean nativeWriteButtonEvent(int fd, int buttonCode, int action); @@ -345,20 +377,18 @@ class InputController { /** Wrapper around the static native methods for tests. */ @VisibleForTesting protected static class NativeWrapper { - public int openUinputKeyboard(String deviceName, int vendorId, int productId) { - return nativeOpenUinputKeyboard(deviceName, vendorId, - productId); + public int openUinputKeyboard(String deviceName, int vendorId, int productId, String phys) { + return nativeOpenUinputKeyboard(deviceName, vendorId, productId, phys); } - public int openUinputMouse(String deviceName, int vendorId, int productId) { - return nativeOpenUinputMouse(deviceName, vendorId, - productId); + public int openUinputMouse(String deviceName, int vendorId, int productId, String phys) { + return nativeOpenUinputMouse(deviceName, vendorId, productId, phys); } - public int openUinputTouchscreen(String deviceName, int vendorId, int productId, int height, - int width) { - return nativeOpenUinputTouchscreen(deviceName, vendorId, - productId, height, width); + public int openUinputTouchscreen(String deviceName, int vendorId, + int productId, String phys, int height, int width) { + return nativeOpenUinputTouchscreen(deviceName, vendorId, productId, phys, height, + width); } public boolean closeUinput(int fd) { @@ -410,15 +440,17 @@ class InputController { private final IBinder.DeathRecipient mDeathRecipient; private final @Type int mType; private final int mDisplayId; + private final String mPhys; // 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) { + InputDeviceDescriptor(int fd, IBinder.DeathRecipient deathRecipient, @Type int type, + int displayId, String phys) { mFd = fd; mDeathRecipient = deathRecipient; mType = type; mDisplayId = displayId; + mPhys = phys; mCreationOrderNumber = sNextCreationOrderNumber.getAndIncrement(); } @@ -445,6 +477,10 @@ class InputController { public long getCreationOrderNumber() { return mCreationOrderNumber; } + + public String getPhys() { + return mPhys; + } } private final class BinderDeathRecipient implements IBinder.DeathRecipient { diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index de933cc470058..783a88ca29bf7 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -2285,14 +2285,8 @@ public class InputManagerService extends IInputManager.Stub nativeNotifyPortAssociationsChanged(mPtr); } - /** - * Add a runtime association between the input device name and the display unique id. - * @param inputDeviceName The name of the input device. - * @param displayUniqueId The unique id of the associated display. - */ @Override // Binder call - public void addUniqueIdAssociation(@NonNull String inputDeviceName, - @NonNull String displayUniqueId) { + public void addUniqueIdAssociation(@NonNull String inputPort, @NonNull String displayUniqueId) { if (!checkCallingPermission( android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY, "addNameAssociation()")) { @@ -2300,20 +2294,16 @@ public class InputManagerService extends IInputManager.Stub "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission"); } - Objects.requireNonNull(inputDeviceName); + Objects.requireNonNull(inputPort); Objects.requireNonNull(displayUniqueId); synchronized (mAssociationsLock) { - mUniqueIdAssociations.put(inputDeviceName, displayUniqueId); + mUniqueIdAssociations.put(inputPort, displayUniqueId); } nativeChangeUniqueIdAssociation(mPtr); } - /** - * Remove the runtime association between the input device and the display. - * @param inputDeviceName The port of the input device to be cleared. - */ @Override // Binder call - public void removeUniqueIdAssociation(@NonNull String inputDeviceName) { + public void removeUniqueIdAssociation(@NonNull String inputPort) { if (!checkCallingPermission( android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY, "removeUniqueIdAssociation()")) { @@ -2321,9 +2311,9 @@ public class InputManagerService extends IInputManager.Stub "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission"); } - Objects.requireNonNull(inputDeviceName); + Objects.requireNonNull(inputPort); synchronized (mAssociationsLock) { - mUniqueIdAssociations.remove(inputDeviceName); + mUniqueIdAssociations.remove(inputPort); } nativeChangeUniqueIdAssociation(mPtr); } @@ -2594,6 +2584,13 @@ public class InputManagerService extends IInputManager.Stub pw.println(" display: " + v); }); } + if (!mUniqueIdAssociations.isEmpty()) { + pw.println("Unique Id Associations:"); + mUniqueIdAssociations.forEach((k, v) -> { + pw.print(" port: " + k); + pw.println(" uniqueId: " + v); + }); + } } } diff --git a/services/core/jni/com_android_server_companion_virtual_InputController.cpp b/services/core/jni/com_android_server_companion_virtual_InputController.cpp index 43018a900f4ce..adc91fc3f2e8c 100644 --- a/services/core/jni/com_android_server_companion_virtual_InputController.cpp +++ b/services/core/jni/com_android_server_companion_virtual_InputController.cpp @@ -186,7 +186,7 @@ static std::map KEY_CODE_MAPPING = { }; /** Creates a new uinput device and assigns a file descriptor. */ -static int openUinput(const char* readableName, jint vendorId, jint productId, +static int openUinput(const char* readableName, jint vendorId, jint productId, const char* phys, DeviceType deviceType, jint screenHeight, jint screenWidth) { android::base::unique_fd fd(TEMP_FAILURE_RETRY(::open("/dev/uinput", O_WRONLY | O_NONBLOCK))); if (fd < 0) { @@ -194,6 +194,8 @@ static int openUinput(const char* readableName, jint vendorId, jint productId, return -errno; } + ioctl(fd, UI_SET_PHYS, phys); + ioctl(fd, UI_SET_EVBIT, EV_KEY); ioctl(fd, UI_SET_EVBIT, EV_SYN); switch (deviceType) { @@ -295,28 +297,30 @@ static int openUinput(const char* readableName, jint vendorId, jint productId, return fd.release(); } -static int openUinputJni(JNIEnv* env, jstring name, jint vendorId, jint productId, +static int openUinputJni(JNIEnv* env, jstring name, jint vendorId, jint productId, jstring phys, DeviceType deviceType, int screenHeight, int screenWidth) { ScopedUtfChars readableName(env, name); - return openUinput(readableName.c_str(), vendorId, productId, deviceType, screenHeight, - screenWidth); + ScopedUtfChars readablePhys(env, phys); + return openUinput(readableName.c_str(), vendorId, productId, readablePhys.c_str(), deviceType, + screenHeight, screenWidth); } static int nativeOpenUinputKeyboard(JNIEnv* env, jobject thiz, jstring name, jint vendorId, - jint productId) { - return openUinputJni(env, name, vendorId, productId, DeviceType::KEYBOARD, /* screenHeight */ 0, - /* screenWidth */ 0); + jint productId, jstring phys) { + return openUinputJni(env, name, vendorId, productId, phys, DeviceType::KEYBOARD, + /* screenHeight */ 0, /* screenWidth */ 0); } static int nativeOpenUinputMouse(JNIEnv* env, jobject thiz, jstring name, jint vendorId, - jint productId) { - return openUinputJni(env, name, vendorId, productId, DeviceType::MOUSE, /* screenHeight */ 0, - /* screenWidth */ 0); + jint productId, jstring phys) { + return openUinputJni(env, name, vendorId, productId, phys, DeviceType::MOUSE, + /* screenHeight */ 0, /* screenWidth */ 0); } static int nativeOpenUinputTouchscreen(JNIEnv* env, jobject thiz, jstring name, jint vendorId, - jint productId, jint height, jint width) { - return openUinputJni(env, name, vendorId, productId, DeviceType::TOUCHSCREEN, height, width); + jint productId, jstring phys, jint height, jint width) { + return openUinputJni(env, name, vendorId, productId, phys, DeviceType::TOUCHSCREEN, height, + width); } static bool nativeCloseUinput(JNIEnv* env, jobject thiz, jint fd) { @@ -435,9 +439,11 @@ static bool nativeWriteScrollEvent(JNIEnv* env, jobject thiz, jint fd, jfloat xA } static JNINativeMethod methods[] = { - {"nativeOpenUinputKeyboard", "(Ljava/lang/String;II)I", (void*)nativeOpenUinputKeyboard}, - {"nativeOpenUinputMouse", "(Ljava/lang/String;II)I", (void*)nativeOpenUinputMouse}, - {"nativeOpenUinputTouchscreen", "(Ljava/lang/String;IIII)I", + {"nativeOpenUinputKeyboard", "(Ljava/lang/String;IILjava/lang/String;)I", + (void*)nativeOpenUinputKeyboard}, + {"nativeOpenUinputMouse", "(Ljava/lang/String;IILjava/lang/String;)I", + (void*)nativeOpenUinputMouse}, + {"nativeOpenUinputTouchscreen", "(Ljava/lang/String;IILjava/lang/String;II)I", (void*)nativeOpenUinputTouchscreen}, {"nativeCloseUinput", "(I)Z", (void*)nativeCloseUinput}, {"nativeWriteKeyEvent", "(III)Z", (void*)nativeWriteKeyEvent}, diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java index ff1b6f66ef85b..83fa7ac025036 100644 --- a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java @@ -17,17 +17,23 @@ package com.android.server.companion.virtual; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import android.hardware.display.DisplayManagerInternal; +import android.hardware.input.IInputManager; +import android.hardware.input.InputManager; import android.hardware.input.InputManagerInternal; import android.os.Binder; import android.os.IBinder; import android.os.IInputConstants; import android.platform.test.annotations.Presubmit; import android.view.Display; +import android.view.DisplayInfo; import androidx.test.runner.AndroidJUnit4; @@ -46,18 +52,31 @@ public class InputControllerTest { @Mock private InputManagerInternal mInputManagerInternalMock; @Mock + private DisplayManagerInternal mDisplayManagerInternalMock; + @Mock private InputController.NativeWrapper mNativeWrapperMock; + @Mock + private IInputManager mIInputManagerMock; private InputController mInputController; @Before - public void setUp() { + public void setUp() throws Exception { MockitoAnnotations.initMocks(this); doNothing().when(mInputManagerInternalMock).setVirtualMousePointerDisplayId(anyInt()); LocalServices.removeServiceForTest(InputManagerInternal.class); LocalServices.addService(InputManagerInternal.class, mInputManagerInternalMock); + final DisplayInfo displayInfo = new DisplayInfo(); + displayInfo.uniqueId = "uniqueId"; + doReturn(displayInfo).when(mDisplayManagerInternalMock).getDisplayInfo(anyInt()); + LocalServices.removeServiceForTest(DisplayManagerInternal.class); + LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock); + + InputManager.resetInstance(mIInputManagerMock); + doNothing().when(mIInputManagerMock).addUniqueIdAssociation(anyString(), anyString()); + doNothing().when(mIInputManagerMock).removeUniqueIdAssociation(anyString()); mInputController = new InputController(new Object(), mNativeWrapperMock); } diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java index e36263e247bff..ceb723a407f9a 100644 --- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java @@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -57,6 +58,7 @@ import android.os.WorkSource; import android.platform.test.annotations.Presubmit; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.view.DisplayInfo; import android.view.KeyEvent; import androidx.test.InstrumentationRegistry; @@ -80,6 +82,8 @@ public class VirtualDeviceManagerServiceTest { private static final int DISPLAY_ID = 2; private static final int PRODUCT_ID = 10; private static final int VENDOR_ID = 5; + private static final String UNIQUE_ID = "uniqueid"; + private static final String PHYS = "phys"; private static final int HEIGHT = 1800; private static final int WIDTH = 900; private static final Binder BINDER = new Binder("binder"); @@ -116,6 +120,12 @@ public class VirtualDeviceManagerServiceTest { LocalServices.removeServiceForTest(InputManagerInternal.class); LocalServices.addService(InputManagerInternal.class, mInputManagerInternalMock); + final DisplayInfo displayInfo = new DisplayInfo(); + displayInfo.uniqueId = UNIQUE_ID; + doReturn(displayInfo).when(mDisplayManagerInternalMock).getDisplayInfo(anyInt()); + LocalServices.removeServiceForTest(DisplayManagerInternal.class); + LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock); + mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); doNothing().when(mContext).enforceCallingOrSelfPermission( eq(Manifest.permission.CREATE_VIRTUAL_DEVICE), anyString()); @@ -274,7 +284,8 @@ public class VirtualDeviceManagerServiceTest { BINDER); assertWithMessage("Virtual keyboard should register fd when the display matches") .that(mInputController.mInputDeviceDescriptors).isNotEmpty(); - verify(mNativeWrapperMock).openUinputKeyboard(DEVICE_NAME, VENDOR_ID, PRODUCT_ID); + verify(mNativeWrapperMock).openUinputKeyboard(eq(DEVICE_NAME), eq(VENDOR_ID), + eq(PRODUCT_ID), anyString()); } @Test @@ -284,7 +295,8 @@ public class VirtualDeviceManagerServiceTest { BINDER); assertWithMessage("Virtual keyboard should register fd when the display matches") .that(mInputController.mInputDeviceDescriptors).isNotEmpty(); - verify(mNativeWrapperMock).openUinputMouse(DEVICE_NAME, VENDOR_ID, PRODUCT_ID); + verify(mNativeWrapperMock).openUinputMouse(eq(DEVICE_NAME), eq(VENDOR_ID), eq(PRODUCT_ID), + anyString()); } @Test @@ -294,8 +306,8 @@ public class VirtualDeviceManagerServiceTest { BINDER, new Point(WIDTH, HEIGHT)); assertWithMessage("Virtual keyboard should register fd when the display matches") .that(mInputController.mInputDeviceDescriptors).isNotEmpty(); - verify(mNativeWrapperMock).openUinputTouchscreen(DEVICE_NAME, VENDOR_ID, PRODUCT_ID, HEIGHT, - WIDTH); + verify(mNativeWrapperMock).openUinputTouchscreen(eq(DEVICE_NAME), eq(VENDOR_ID), + eq(PRODUCT_ID), anyString(), eq(HEIGHT), eq(WIDTH)); } @Test @@ -315,7 +327,7 @@ public class VirtualDeviceManagerServiceTest { final int action = VirtualKeyEvent.ACTION_UP; mInputController.mInputDeviceDescriptors.put(BINDER, new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 1, - /* displayId= */ 1)); + /* displayId= */ 1, PHYS)); mDeviceImpl.sendKeyEvent(BINDER, new VirtualKeyEvent.Builder().setKeyCode(keyCode) .setAction(action).build()); verify(mNativeWrapperMock).writeKeyEvent(fd, keyCode, action); @@ -340,7 +352,7 @@ public class VirtualDeviceManagerServiceTest { final int action = VirtualMouseButtonEvent.ACTION_BUTTON_PRESS; mInputController.mInputDeviceDescriptors.put(BINDER, new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2, - /* displayId= */ 1)); + /* displayId= */ 1, PHYS)); mInputController.mActivePointerDisplayId = 1; mDeviceImpl.sendButtonEvent(BINDER, new VirtualMouseButtonEvent.Builder() .setButtonCode(buttonCode) @@ -355,7 +367,7 @@ public class VirtualDeviceManagerServiceTest { final int action = VirtualMouseButtonEvent.ACTION_BUTTON_PRESS; mInputController.mInputDeviceDescriptors.put(BINDER, new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2, - /* displayId= */ 1)); + /* displayId= */ 1, PHYS)); assertThrows( IllegalStateException.class, () -> @@ -381,7 +393,7 @@ public class VirtualDeviceManagerServiceTest { final float y = 0.7f; mInputController.mInputDeviceDescriptors.put(BINDER, new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2, - /* displayId= */ 1)); + /* displayId= */ 1, PHYS)); mInputController.mActivePointerDisplayId = 1; mDeviceImpl.sendRelativeEvent(BINDER, new VirtualMouseRelativeEvent.Builder() .setRelativeX(x).setRelativeY(y).build()); @@ -395,7 +407,7 @@ public class VirtualDeviceManagerServiceTest { final float y = 0.7f; mInputController.mInputDeviceDescriptors.put(BINDER, new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2, - /* displayId= */ 1)); + /* displayId= */ 1, PHYS)); assertThrows( IllegalStateException.class, () -> @@ -422,7 +434,7 @@ public class VirtualDeviceManagerServiceTest { final float y = 1f; mInputController.mInputDeviceDescriptors.put(BINDER, new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2, - /* displayId= */ 1)); + /* displayId= */ 1, PHYS)); mInputController.mActivePointerDisplayId = 1; mDeviceImpl.sendScrollEvent(BINDER, new VirtualMouseScrollEvent.Builder() .setXAxisMovement(x) @@ -437,7 +449,7 @@ public class VirtualDeviceManagerServiceTest { final float y = 1f; mInputController.mInputDeviceDescriptors.put(BINDER, new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2, - /* displayId= */ 1)); + /* displayId= */ 1, PHYS)); assertThrows( IllegalStateException.class, () -> @@ -470,7 +482,7 @@ public class VirtualDeviceManagerServiceTest { final int action = VirtualTouchEvent.ACTION_UP; mInputController.mInputDeviceDescriptors.put(BINDER, new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 3, - /* displayId= */ 1)); + /* displayId= */ 1, PHYS)); mDeviceImpl.sendTouchEvent(BINDER, new VirtualTouchEvent.Builder().setX(x) .setY(y).setAction(action).setPointerId(pointerId).setToolType(toolType).build()); verify(mNativeWrapperMock).writeTouchEvent(fd, pointerId, toolType, action, x, y, Float.NaN, @@ -489,7 +501,7 @@ public class VirtualDeviceManagerServiceTest { final float majorAxisSize = 10.0f; mInputController.mInputDeviceDescriptors.put(BINDER, new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 3, - /* displayId= */ 1)); + /* displayId= */ 1, PHYS)); mDeviceImpl.sendTouchEvent(BINDER, new VirtualTouchEvent.Builder().setX(x) .setY(y).setAction(action).setPointerId(pointerId).setToolType(toolType) .setPressure(pressure).setMajorAxisSize(majorAxisSize).build());