Add synthetic back button to virtual touchpad/stylus.
Also add a bit more error checking and documentation.
Test: added to VirtualTouchpad_test.cpp
Bug: 34673438
Change-Id: I3851a2ad79c5338cdd1db0c7d460aecfff082cc3
diff --git a/services/vr/virtual_touchpad/VirtualTouchpad.cpp b/services/vr/virtual_touchpad/VirtualTouchpad.cpp
index b137dd7..f3936fc 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpad.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpad.cpp
@@ -1,20 +1,29 @@
#include "VirtualTouchpad.h"
+#include <android/input.h>
#include <cutils/log.h>
#include <inttypes.h>
#include <linux/input.h>
+// References:
+// [0] Multi-touch (MT) Protocol,
+// https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt
+
namespace android {
namespace dvr {
namespace {
-// Virtual evdev device properties.
+// Virtual evdev device properties. The name is arbitrary, but Android can
+// use it to look up device configuration, so it must be unique. Vendor and
+// product values must be 0 to indicate an internal device and prevent a
+// similar lookup that could conflict with a physical device.
static const char* const kDeviceName = "vr window manager virtual touchpad";
static constexpr int16_t kDeviceBusType = BUS_VIRTUAL;
-static constexpr int16_t kDeviceVendor = 0x18D1; // Google USB vendor ID.
-static constexpr int16_t kDeviceProduct = 0x5652; // 'VR'
+static constexpr int16_t kDeviceVendor = 0;
+static constexpr int16_t kDeviceProduct = 0;
static constexpr int16_t kDeviceVersion = 0x0001;
+
static constexpr int32_t kWidth = 0x10000;
static constexpr int32_t kHeight = 0x10000;
static constexpr int32_t kSlots = 2;
@@ -32,18 +41,24 @@
injector_->ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1);
injector_->ConfigureAbsSlots(kSlots);
injector_->ConfigureKey(BTN_TOUCH);
+ injector_->ConfigureKey(BTN_BACK);
injector_->ConfigureEnd();
return injector_->GetError();
}
int VirtualTouchpad::Touch(float x, float y, float pressure) {
- int error = 0;
+ if ((x < 0.0f) || (x >= 1.0f) || (y < 0.0f) || (y >= 1.0f)) {
+ return EINVAL;
+ }
int32_t device_x = x * kWidth;
int32_t device_y = y * kHeight;
touches_ = ((touches_ & 1) << 1) | (pressure > 0);
ALOGV("(%f,%f) %f -> (%" PRId32 ",%" PRId32 ") %d",
x, y, pressure, device_x, device_y, touches_);
+ if (!injector_) {
+ return EvdevInjector::ERROR_SEQUENCING;
+ }
injector_->ResetError();
switch (touches_) {
case 0b00: // Hover continues.
@@ -76,5 +91,30 @@
return injector_->GetError();
}
+int VirtualTouchpad::ButtonState(int buttons) {
+ const int changes = last_motion_event_buttons_ ^ buttons;
+ if (!changes) {
+ return 0;
+ }
+ if (buttons & ~AMOTION_EVENT_BUTTON_BACK) {
+ return ENOTSUP;
+ }
+ ALOGV("change %X from %X to %X", changes, last_motion_event_buttons_,
+ buttons);
+
+ if (!injector_) {
+ return EvdevInjector::ERROR_SEQUENCING;
+ }
+ injector_->ResetError();
+ if (changes & AMOTION_EVENT_BUTTON_BACK) {
+ injector_->SendKey(BTN_BACK,
+ (buttons & AMOTION_EVENT_BUTTON_BACK)
+ ? EvdevInjector::KEY_PRESS
+ : EvdevInjector::KEY_RELEASE);
+ }
+ last_motion_event_buttons_ = buttons;
+ return injector_->GetError();
+}
+
} // namespace dvr
} // namespace android