Support mouse input in single device VDM demo

Bug: 404803361
Test: manual
Flag: EXEMPT demo app
Change-Id: I4a9dcaea19076fdddc5c2c3769e34dc7d2aedf19
diff --git a/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/DisplayActivity.java b/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/DisplayActivity.java
index 941cadc..42537f4 100644
--- a/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/DisplayActivity.java
+++ b/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/DisplayActivity.java
@@ -150,6 +150,15 @@
             return true;
         });
 
+        textureView.setOnGenericMotionListener((v, event) -> {
+            if (event.getDevice() == null || mDisplay == null
+                    || !event.getDevice().supportsSource(InputDevice.SOURCE_MOUSE)) {
+                return false;
+            }
+            mDisplay.processVirtualMouseEvent(event);
+            return true;
+        });
+
         OnBackPressedCallback callback = new OnBackPressedCallback(true) {
             @Override
             public void handleOnBackPressed() {
diff --git a/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/InputController.java b/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/InputController.java
index c98388b..9836117 100644
--- a/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/InputController.java
+++ b/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/InputController.java
@@ -136,7 +136,7 @@
         }
     }
 
-    private static float clampMouseScroll(float val) {
+    static float clampMouseScroll(float val) {
         return Math.max(Math.min(val, 1f), -1f);
     }
 }
diff --git a/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/RemoteDisplay.java b/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/RemoteDisplay.java
index d183dbd..56646a6 100644
--- a/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/RemoteDisplay.java
+++ b/samples/VirtualDeviceManager/host/src/com/example/android/vdmdemo/host/RemoteDisplay.java
@@ -447,6 +447,9 @@
             case DEVICE_TYPE_ROTARY_ENCODER:
                 processRotaryEvent(motionEventToVirtualRotaryEncoderEvent((MotionEvent) event));
                 break;
+            case DEVICE_TYPE_MOUSE:
+                processVirtualMouseEvent(motionEventToVirtualMouseEvent((MotionEvent) event));
+                break;
             case DEVICE_TYPE_TOUCHSCREEN:
                 mTouchscreen.sendTouchEvent(motionEventToVirtualTouchEvent((MotionEvent) event));
                 break;
@@ -623,6 +626,36 @@
                 .build();
     }
 
+    private static Object motionEventToVirtualMouseEvent(MotionEvent event) {
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_BUTTON_PRESS:
+            case MotionEvent.ACTION_BUTTON_RELEASE:
+                return new VirtualMouseButtonEvent.Builder()
+                        .setEventTimeNanos((long) (event.getEventTime() * 1e6))
+                        .setButtonCode(event.getActionButton())
+                        .setAction(event.getAction())
+                        .build();
+            case MotionEvent.ACTION_HOVER_ENTER:
+            case MotionEvent.ACTION_HOVER_EXIT:
+            case MotionEvent.ACTION_HOVER_MOVE:
+                return new VirtualMouseRelativeEvent.Builder()
+                        .setEventTimeNanos((long) (event.getEventTime() * 1e6))
+                        .setRelativeX(event.getX())
+                        .setRelativeY(event.getY())
+                        .build();
+            case MotionEvent.ACTION_SCROLL:
+                float scrollX = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
+                float scrollY = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                return new VirtualMouseScrollEvent.Builder()
+                        .setEventTimeNanos((long) (event.getEventTime() * 1e6))
+                        .setXAxisMovement(InputController.clampMouseScroll(scrollX))
+                        .setYAxisMovement(InputController.clampMouseScroll(scrollY))
+                        .build();
+            default:
+                return null;
+        }
+    }
+
     private static VirtualRotaryEncoderScrollEvent remoteEventToVirtualRotaryEncoderEvent(
             RemoteInputEvent event) {
         return new VirtualRotaryEncoderScrollEvent.Builder()