Support multi-touch screen
Bug: 331179939
Test: pinch zoom
Change-Id: I76bb46a67607df8af0c83dce3113b6611e4fae9f
diff --git a/java/framework/src/android/system/virtualmachine/VirtualMachine.java b/java/framework/src/android/system/virtualmachine/VirtualMachine.java
index d1321f0..a203358 100644
--- a/java/framework/src/android/system/virtualmachine/VirtualMachine.java
+++ b/java/framework/src/android/system/virtualmachine/VirtualMachine.java
@@ -903,11 +903,11 @@
if (vmConfig.getCustomImageConfig().useTouch()) {
ParcelFileDescriptor[] pfds = ParcelFileDescriptor.createSocketPair();
mTouchSock = pfds[0];
- InputDevice.SingleTouch t = new InputDevice.SingleTouch();
+ InputDevice.MultiTouch t = new InputDevice.MultiTouch();
t.width = rawConfig.displayConfig.width;
t.height = rawConfig.displayConfig.height;
t.pfd = pfds[1];
- inputDevices.add(InputDevice.singleTouch(t));
+ inputDevices.add(InputDevice.multiTouch(t));
}
if (vmConfig.getCustomImageConfig().useKeyboard()) {
ParcelFileDescriptor[] pfds = ParcelFileDescriptor.createSocketPair();
@@ -1061,7 +1061,7 @@
}
/** @hide */
- public boolean sendSingleTouchEvent(MotionEvent event) {
+ public boolean sendMultiTouchEvent(MotionEvent event) {
if (mTouchSock == null) {
Log.d(TAG, "mTouchSock == null");
return false;
@@ -1074,17 +1074,56 @@
short ABS_X = 0x00;
short ABS_Y = 0x01;
short SYN_REPORT = 0x00;
+ short ABS_MT_SLOT = 0x2f;
+ short ABS_MT_POSITION_X = 0x35;
+ short ABS_MT_POSITION_Y = 0x36;
+ short ABS_MT_TRACKING_ID = 0x39;
- int x = (int) event.getX();
- int y = (int) event.getY();
- boolean down = event.getAction() != MotionEvent.ACTION_UP;
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_MOVE:
+ List<InputEvent> events =
+ new ArrayList<>(
+ event.getPointerCount() * 6 /*InputEvent per a pointer*/
+ + 1 /*SYN*/);
+ for (int actionIdx = 0; actionIdx < event.getPointerCount(); actionIdx++) {
+ int pointerId = event.getPointerId(actionIdx);
+ int x = (int) event.getRawX(actionIdx);
+ int y = (int) event.getRawY(actionIdx);
+ events.add(new InputEvent(EV_ABS, ABS_MT_SLOT, pointerId));
+ events.add(new InputEvent(EV_ABS, ABS_MT_TRACKING_ID, pointerId));
+ events.add(new InputEvent(EV_ABS, ABS_MT_POSITION_X, x));
+ events.add(new InputEvent(EV_ABS, ABS_MT_POSITION_Y, y));
+ events.add(new InputEvent(EV_ABS, ABS_X, x));
+ events.add(new InputEvent(EV_ABS, ABS_Y, y));
+ }
+ events.add(new InputEvent(EV_SYN, SYN_REPORT, 0));
+ return writeEventsToSock(mTouchSock, events);
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_POINTER_DOWN:
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
+ break;
+ default:
+ return false;
+ }
+ boolean down =
+ event.getActionMasked() == MotionEvent.ACTION_DOWN
+ || event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN;
+ int actionIdx = event.getActionIndex();
+ int pointerId = event.getPointerId(actionIdx);
+ int x = (int) event.getRawX(actionIdx);
+ int y = (int) event.getRawY(actionIdx);
return writeEventsToSock(
mTouchSock,
Arrays.asList(
+ new InputEvent(EV_KEY, BTN_TOUCH, down ? 1 : 0),
+ new InputEvent(EV_ABS, ABS_MT_SLOT, pointerId),
+ new InputEvent(EV_ABS, ABS_MT_TRACKING_ID, down ? pointerId : -1),
+ new InputEvent(EV_ABS, ABS_MT_POSITION_X, x),
+ new InputEvent(EV_ABS, ABS_MT_POSITION_Y, y),
new InputEvent(EV_ABS, ABS_X, x),
new InputEvent(EV_ABS, ABS_Y, y),
- new InputEvent(EV_KEY, BTN_TOUCH, down ? 1 : 0),
new InputEvent(EV_SYN, SYN_REPORT, 0)));
}
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index 425beed..026834f 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -814,6 +814,12 @@
width: u32::try_from(trackpad.width)?,
name: if !trackpad.name.is_empty() { Some(trackpad.name.clone()) } else { None },
},
+ InputDevice::MultiTouch(multi_touch) => InputDeviceOption::MultiTouch {
+ file: clone_file(multi_touch.pfd.as_ref().ok_or(anyhow!("pfd should have value"))?)?,
+ height: u32::try_from(multi_touch.height)?,
+ width: u32::try_from(multi_touch.width)?,
+ name: if !multi_touch.name.is_empty() { Some(multi_touch.name.clone()) } else { None },
+ },
})
}
/// Given the configuration for a disk image, assembles the `DiskFile` to pass to crosvm.
diff --git a/virtualizationmanager/src/crosvm.rs b/virtualizationmanager/src/crosvm.rs
index 379a498..6af84b6 100644
--- a/virtualizationmanager/src/crosvm.rs
+++ b/virtualizationmanager/src/crosvm.rs
@@ -223,6 +223,7 @@
Mouse(File),
Switches(File),
MultiTouchTrackpad { file: File, width: u32, height: u32, name: Option<String> },
+ MultiTouch { file: File, width: u32, height: u32, name: Option<String> },
}
type VfioDevice = Strong<dyn IBoundDevice>;
@@ -1164,6 +1165,13 @@
height,
name.as_ref().map_or("".into(), |n| format!(",name={}", n))
),
+ InputDeviceOption::MultiTouch { file, width, height, name } => format!(
+ "multi-touch[path={},width={},height={}{}]",
+ add_preserved_fd(&mut preserved_fds, file),
+ width,
+ height,
+ name.as_ref().map_or("".into(), |n| format!(",name={}", n))
+ ),
});
}
}
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/InputDevice.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/InputDevice.aidl
index e998d02..bb06fff 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/InputDevice.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/InputDevice.aidl
@@ -51,10 +51,20 @@
int height = 1080;
@utf8InCpp String name = "";
}
+
+ parcelable MultiTouch {
+ ParcelFileDescriptor pfd;
+ // Default values come from https://crosvm.dev/book/devices/input.html#multi-touch
+ int width = 1280;
+ int height = 1080;
+ @utf8InCpp String name = "";
+ }
+
SingleTouch singleTouch;
EvDev evDev;
Keyboard keyboard;
Mouse mouse;
Switches switches;
Trackpad trackpad;
+ MultiTouch multiTouch;
}
diff --git a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
index 7a69c07..6f85c42 100644
--- a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
+++ b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
@@ -352,7 +352,7 @@
if (mVirtualMachine == null) {
return false;
}
- return mVirtualMachine.sendSingleTouchEvent(event);
+ return mVirtualMachine.sendMultiTouchEvent(event);
});
surfaceView.requestUnbufferedDispatch(InputDevice.SOURCE_ANY);
surfaceView.setOnCapturedPointerListener(