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

Commit 4b64dd48 authored by Kevin Schoedel's avatar Kevin Schoedel
Browse files

Revise virtual touchpad interface.

- Explicit start and stop, outside of which the evdev devices
  don't exist.
- Permission test (not compiled by default pending build & SELinux
  support for temporarily retaining a second copy of the service
  for vr_wm).
- Enforce a single user of the touchpad.
- Support 'dumpsys'.

Bug: 36051900
Test: log inspection
Change-Id: I038ed2632d5adf50a3565a981031691d5dc5f7cd
parent a9ba6a93
Loading
Loading
Loading
Loading
+12 −9
Original line number Diff line number Diff line
@@ -9,7 +9,8 @@ src := \
  VirtualTouchpadEvdev.cpp

shared_libs := \
  libbase
  libbase \
  libutils

include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(src)
@@ -24,21 +25,23 @@ include $(BUILD_STATIC_LIBRARY)

# Touchpad unit tests.

test_src_files := \
  tests/VirtualTouchpad_test.cpp

static_libs := \
test_static_libs := \
  libbase \
  libcutils \
  libutils \
  libvirtualtouchpad

test_shared_libs := \
  libutils

test_src_files := \
  tests/VirtualTouchpad_test.cpp

$(foreach file,$(test_src_files), \
    $(eval include $(CLEAR_VARS)) \
    $(eval LOCAL_SRC_FILES := $(file)) \
    $(eval LOCAL_C_INCLUDES := $(LOCAL_PATH)/include) \
    $(eval LOCAL_STATIC_LIBRARIES := $(static_libs)) \
    $(eval LOCAL_SHARED_LIBRARIES := $(shared_libs)) \
    $(eval LOCAL_STATIC_LIBRARIES := $(test_static_libs)) \
    $(eval LOCAL_SHARED_LIBRARIES := $(test_shared_libs)) \
    $(eval LOCAL_CPPFLAGS += -std=c++11) \
    $(eval LOCAL_LDLIBS := -llog) \
    $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
@@ -70,7 +73,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES := $(static_libs)
LOCAL_SHARED_LIBRARIES := $(shared_libs)
LOCAL_CPPFLAGS += -std=c++11
LOCAL_CFLAGS += -DLOG_TAG=\"VrVirtualTouchpad\"
LOCAL_CFLAGS += -DLOG_TAG=\"VrVirtualTouchpad\" -DSELINUX_ACCESS_CONTROL
LOCAL_LDLIBS := -llog
LOCAL_MODULE := virtual_touchpad
LOCAL_MODULE_TAGS := optional
+6 −0
Original line number Diff line number Diff line
@@ -307,5 +307,11 @@ int EvdevInjector::EnableEventType(uint16_t type) {
  return 0;
}

void EvdevInjector::dumpInternal(String8& result) {
  result.append("[injector]\n");
  result.appendFormat("state = %d\n", static_cast<int>(state_));
  result.appendFormat("error = %d\n\n", error_);
}

}  // namespace dvr
}  // namespace android
+3 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@

#include <android-base/unique_fd.h>
#include <linux/uinput.h>
#include <utils/String8.h>

#include <cstdint>
#include <memory>
@@ -99,6 +100,8 @@ class EvdevInjector {
  int SendMultiTouchXY(int32_t slot, int32_t id, int32_t x, int32_t y);
  int SendMultiTouchLift(int32_t slot);

  void dumpInternal(String8& result);

 protected:
  // Must be called only between construction and ConfigureBegin().
  inline void SetUInputForTesting(UInput* uinput) { uinput_ = uinput; }
+44 −17
Original line number Diff line number Diff line
@@ -10,17 +10,49 @@ namespace {

class VirtualTouchpadClientImpl : public VirtualTouchpadClient {
 public:
  VirtualTouchpadClientImpl(sp<IVirtualTouchpadService> service)
      : service_(service) {}
  ~VirtualTouchpadClientImpl() override {}
  VirtualTouchpadClientImpl() {}
  ~VirtualTouchpadClientImpl() override {
    if (service_ != nullptr) {
      Detach();
    }
  }

  status_t Attach() {
    if (service_ != nullptr) {
      return ALREADY_EXISTS;
    }
    sp<IServiceManager> sm = defaultServiceManager();
    if (sm == nullptr) {
      ALOGE("no service manager");
      return NO_INIT;
    }
    sp<IVirtualTouchpadService> service =
        interface_cast<IVirtualTouchpadService>(
            sm->getService(IVirtualTouchpadService::SERVICE_NAME()));
    if (service == nullptr) {
      ALOGE("failed to get service");
      return NAME_NOT_FOUND;
    }
    service_ = service;
    return service_->attach().transactionError();
  }

  status_t Detach() {
    if (service_ == nullptr) {
      return NO_INIT;
    }
    status_t status = service_->detach().transactionError();
    service_ = nullptr;
    return status;
  }

  status_t Touch(int touchpad,
                 float x, float y, float pressure) override {
  status_t Touch(int touchpad, float x, float y, float pressure) override {
    if (service_ == nullptr) {
      return NO_INIT;
    }
    return service_->touch(touchpad, x, y, pressure).transactionError();
  }

  status_t ButtonState(int touchpad, int buttons) override {
    if (service_ == nullptr) {
      return NO_INIT;
@@ -28,6 +60,12 @@ class VirtualTouchpadClientImpl : public VirtualTouchpadClient {
    return service_->buttonState(touchpad, buttons).transactionError();
  }

  void dumpInternal(String8& result) override {
    result.append("[virtual touchpad]\n");
    result.appendFormat("connected = %s\n\n",
                        service_ != nullptr ? "true" : "false");
  }

 private:
  sp<IVirtualTouchpadService> service_;
};
@@ -35,18 +73,7 @@ class VirtualTouchpadClientImpl : public VirtualTouchpadClient {
}  // anonymous namespace

sp<VirtualTouchpad> VirtualTouchpadClient::Create() {
  sp<IServiceManager> sm = defaultServiceManager();
  if (sm == nullptr) {
    ALOGE("no service manager");
    return sp<VirtualTouchpad>();
  }
  sp<IVirtualTouchpadService> service = interface_cast<IVirtualTouchpadService>(
      sm->getService(IVirtualTouchpadService::SERVICE_NAME()));
  if (service == nullptr) {
    ALOGE("failed to get service");
    return sp<VirtualTouchpad>();
  }
  return new VirtualTouchpadClientImpl(service);
  return new VirtualTouchpadClientImpl();
}

}  // namespace dvr
+30 −8
Original line number Diff line number Diff line
@@ -32,15 +32,10 @@ static constexpr int32_t kSlots = 2;

sp<VirtualTouchpad> VirtualTouchpadEvdev::Create() {
  VirtualTouchpadEvdev* const touchpad = new VirtualTouchpadEvdev();
  const status_t status = touchpad->Initialize();
  if (status) {
    ALOGE("initialization failed: %d", status);
    return sp<VirtualTouchpad>();
  }
  return sp<VirtualTouchpad>(touchpad);
}

int VirtualTouchpadEvdev::Initialize() {
status_t VirtualTouchpadEvdev::Attach() {
  if (!injector_) {
    owned_injector_.reset(new EvdevInjector());
    injector_ = owned_injector_.get();
@@ -56,9 +51,20 @@ int VirtualTouchpadEvdev::Initialize() {
  return injector_->GetError();
}

status_t VirtualTouchpadEvdev::Detach() {
  injector_->Close();
  injector_ = nullptr;
  owned_injector_.reset();
  last_device_x_ = INT32_MIN;
  last_device_y_ = INT32_MIN;
  touches_ = 0;
  last_motion_event_buttons_ = 0;
  return OK;
}

int VirtualTouchpadEvdev::Touch(int touchpad, float x, float y,
                                float pressure) {
  (void)touchpad; // TODO(b/35992608) Support multiple virtual touchpad devices.
  (void)touchpad;  // TODO(b/35992608) Support multiple touchpad devices.
  if ((x < 0.0f) || (x >= 1.0f) || (y < 0.0f) || (y >= 1.0f)) {
    return EINVAL;
  }
@@ -104,7 +110,7 @@ int VirtualTouchpadEvdev::Touch(int touchpad, float x, float y,
}

int VirtualTouchpadEvdev::ButtonState(int touchpad, int buttons) {
  (void)touchpad; // TODO(b/35992608) Support multiple virtual touchpad devices.
  (void)touchpad;  // TODO(b/35992608) Support multiple touchpad devices.
  const int changes = last_motion_event_buttons_ ^ buttons;
  if (!changes) {
    return 0;
@@ -123,10 +129,26 @@ int VirtualTouchpadEvdev::ButtonState(int touchpad, int buttons) {
    injector_->SendKey(BTN_BACK, (buttons & AMOTION_EVENT_BUTTON_BACK)
                                     ? EvdevInjector::KEY_PRESS
                                     : EvdevInjector::KEY_RELEASE);
    injector_->SendSynReport();
  }
  last_motion_event_buttons_ = buttons;
  return injector_->GetError();
}

void VirtualTouchpadEvdev::dumpInternal(String8& result) {
  result.append("[virtual touchpad]\n");
  if (!injector_) {
    result.append("injector = none\n");
    return;
  }
  result.appendFormat("injector = %s\n", owned_injector_ ? "normal" : "test");
  result.appendFormat("touches = %d\n", touches_);
  result.appendFormat("last_position = (%" PRId32 ", %" PRId32 ")\n",
                      last_device_x_, last_device_y_);
  result.appendFormat("last_buttons = 0x%" PRIX32 "\n\n",
                      last_motion_event_buttons_);
  injector_->dumpInternal(result);
}

}  // namespace dvr
}  // namespace android
Loading