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
diff --git a/services/vr/virtual_touchpad/Android.mk b/services/vr/virtual_touchpad/Android.mk
index b78eb99..88b2dd9 100644
--- a/services/vr/virtual_touchpad/Android.mk
+++ b/services/vr/virtual_touchpad/Android.mk
@@ -9,7 +9,8 @@
VirtualTouchpadEvdev.cpp
shared_libs := \
- libbase
+ libbase \
+ libutils
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(src)
@@ -24,21 +25,23 @@
# 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_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
diff --git a/services/vr/virtual_touchpad/EvdevInjector.cpp b/services/vr/virtual_touchpad/EvdevInjector.cpp
index d8a1dfa..b4c0a52 100644
--- a/services/vr/virtual_touchpad/EvdevInjector.cpp
+++ b/services/vr/virtual_touchpad/EvdevInjector.cpp
@@ -307,5 +307,11 @@
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
diff --git a/services/vr/virtual_touchpad/EvdevInjector.h b/services/vr/virtual_touchpad/EvdevInjector.h
index 1b1c4da..c69dbef 100644
--- a/services/vr/virtual_touchpad/EvdevInjector.h
+++ b/services/vr/virtual_touchpad/EvdevInjector.h
@@ -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 @@
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; }
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
index 175173f..782b19c 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
@@ -10,17 +10,49 @@
class VirtualTouchpadClientImpl : public VirtualTouchpadClient {
public:
- VirtualTouchpadClientImpl(sp<IVirtualTouchpadService> service)
- : service_(service) {}
- ~VirtualTouchpadClientImpl() override {}
+ VirtualTouchpadClientImpl() {}
+ ~VirtualTouchpadClientImpl() override {
+ if (service_ != nullptr) {
+ Detach();
+ }
+ }
- status_t Touch(int touchpad,
- float x, float y, float pressure) override {
+ 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 {
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 @@
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 @@
} // 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
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
index f25a2ad..bc29408 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
@@ -32,15 +32,10 @@
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 @@
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::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 @@
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
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
index ec8006b..b158cec 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
@@ -18,15 +18,17 @@
static sp<VirtualTouchpad> Create();
// VirtualTouchpad implementation:
+ status_t Attach() override;
+ status_t Detach() override;
status_t Touch(int touchpad, float x, float y, float pressure) override;
status_t ButtonState(int touchpad, int buttons) override;
+ void dumpInternal(String8& result) override;
protected:
VirtualTouchpadEvdev() {}
~VirtualTouchpadEvdev() override {}
- status_t Initialize();
- // Must be called only between construction and Initialize().
+ // Must be called only between construction and Attach().
inline void SetEvdevInjectorForTesting(EvdevInjector* injector) {
injector_ = injector;
}
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
index a1f281c..2e2f622 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
@@ -1,22 +1,136 @@
#include "VirtualTouchpadService.h"
+#include <inttypes.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/PermissionCache.h>
#include <binder/Status.h>
+#include <cutils/log.h>
#include <linux/input.h>
-#include <log/log.h>
+#include <private/android_filesystem_config.h>
#include <utils/Errors.h>
namespace android {
namespace dvr {
-binder::Status VirtualTouchpadService::touch(int touchpad,
- float x, float y, float pressure) {
- const status_t error = touchpad_->Touch(touchpad, x, y, pressure);
- return error ? binder::Status::fromStatusT(error) : binder::Status::ok();
+namespace {
+const String16 kDumpPermission("android.permission.DUMP");
+const String16 kTouchPermission("android.permission.RESTRICTED_VR_ACCESS");
+} // anonymous namespace
+
+VirtualTouchpadService::~VirtualTouchpadService() {
+ if (client_pid_) {
+ client_pid_ = 0;
+ touchpad_->Detach();
+ }
+}
+
+binder::Status VirtualTouchpadService::attach() {
+ pid_t pid;
+ if (!CheckTouchPermission(&pid)) {
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+ if (client_pid_ == pid) {
+ // The same client has called attach() twice with no intervening detach().
+ // This indicates a problem with the client, so return an error.
+ // However, since the client is already attached, any touchpad actions
+ // it takes will still work.
+ ALOGE("pid=%ld attached twice", static_cast<long>(pid));
+ return binder::Status::fromStatusT(ALREADY_EXISTS);
+ }
+ if (client_pid_ != 0) {
+ // Attach while another client is attached. This can happen if the client
+ // dies without cleaning up after itself, so move ownership to the current
+ // caller. If two actual clients have connected, the problem will be
+ // reported when the previous client performs any touchpad action.
+ ALOGE("pid=%ld replaces %ld", static_cast<long>(pid),
+ static_cast<long>(client_pid_));
+ }
+ client_pid_ = pid;
+ if (const status_t error = touchpad_->Attach()) {
+ return binder::Status::fromStatusT(error);
+ }
+ return binder::Status::ok();
+}
+
+binder::Status VirtualTouchpadService::detach() {
+ if (!CheckPermissions()) {
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+ client_pid_ = 0;
+ if (const status_t error = touchpad_->Detach()) {
+ return binder::Status::fromStatusT(error);
+ }
+ return binder::Status::ok();
+}
+
+binder::Status VirtualTouchpadService::touch(int touchpad, float x, float y,
+ float pressure) {
+ if (!CheckPermissions()) {
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+ if (const status_t error = touchpad_->Touch(touchpad, x, y, pressure)) {
+ return binder::Status::fromStatusT(error);
+ }
+ return binder::Status::ok();
}
binder::Status VirtualTouchpadService::buttonState(int touchpad, int buttons) {
- const status_t error = touchpad_->ButtonState(touchpad, buttons);
- return error ? binder::Status::fromStatusT(error) : binder::Status::ok();
+ if (!CheckPermissions()) {
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+ if (const status_t error = touchpad_->ButtonState(touchpad, buttons)) {
+ return binder::Status::fromStatusT(error);
+ }
+ return binder::Status::ok();
+}
+
+status_t VirtualTouchpadService::dump(
+ int fd, const Vector<String16>& args[[gnu::unused]]) {
+ String8 result;
+ const android::IPCThreadState* ipc = android::IPCThreadState::self();
+ const pid_t pid = ipc->getCallingPid();
+ const uid_t uid = ipc->getCallingUid();
+ if ((uid != AID_SHELL) &&
+ !PermissionCache::checkPermission(kDumpPermission, pid, uid)) {
+ result.appendFormat("Permission denial: can't dump " LOG_TAG
+ " from pid=%ld, uid=%ld\n",
+ static_cast<long>(pid), static_cast<long>(uid));
+ } else {
+ result.appendFormat("[service]\nclient_pid = %ld\n\n",
+ static_cast<long>(client_pid_));
+ touchpad_->dumpInternal(result);
+ }
+ write(fd, result.string(), result.size());
+ return OK;
+}
+
+bool VirtualTouchpadService::CheckPermissions() {
+ pid_t pid;
+ if (!CheckTouchPermission(&pid)) {
+ return false;
+ }
+ if (client_pid_ != pid) {
+ ALOGE("pid=%ld is not owner", static_cast<long>(pid));
+ return false;
+ }
+ return true;
+}
+
+bool VirtualTouchpadService::CheckTouchPermission(pid_t* out_pid) {
+ const android::IPCThreadState* ipc = android::IPCThreadState::self();
+ *out_pid = ipc->getCallingPid();
+#ifdef SELINUX_ACCESS_CONTROL
+ return true;
+#else
+ const uid_t uid = ipc->getCallingUid();
+ const bool permission = PermissionCache::checkPermission(kTouchPermission, *out_pid, uid);
+ if (!permission) {
+ ALOGE("permission denied to pid=%ld uid=%ld", static_cast<long>(*out_pid),
+ static_cast<long>(uid));
+ }
+ return permission;
+#endif
}
} // namespace dvr
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.h b/services/vr/virtual_touchpad/VirtualTouchpadService.h
index 9b880b2..194d787 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.h
@@ -14,17 +14,28 @@
class VirtualTouchpadService : public BnVirtualTouchpadService {
public:
VirtualTouchpadService(sp<VirtualTouchpad> touchpad)
- : touchpad_(touchpad) {}
- ~VirtualTouchpadService() override {}
+ : touchpad_(touchpad), client_pid_(0) {}
+ ~VirtualTouchpadService() override;
protected:
// Implements IVirtualTouchpadService.
+ binder::Status attach() override;
+ binder::Status detach() override;
binder::Status touch(int touchpad, float x, float y, float pressure) override;
binder::Status buttonState(int touchpad, int buttons) override;
+ // Implements BBinder::dump().
+ status_t dump(int fd, const Vector<String16>& args) override;
+
private:
+ bool CheckPermissions();
+ bool CheckTouchPermission(pid_t* out_pid);
+
sp<VirtualTouchpad> touchpad_;
+ // Only one client at a time can use the virtual touchpad.
+ pid_t client_pid_;
+
VirtualTouchpadService(const VirtualTouchpadService&) = delete;
void operator=(const VirtualTouchpadService&) = delete;
};
diff --git a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl b/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
index 496c5e2..9cfb186 100644
--- a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
+++ b/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
@@ -6,6 +6,16 @@
const String SERVICE_NAME = "virtual_touchpad";
/**
+ * Initialize the virtual touchpad.
+ */
+ void attach() = 0;
+
+ /**
+ * Shut down the virtual touchpad.
+ */
+ void detach() = 1;
+
+ /**
* Generate a simulated touch event.
*
* @param touchpad Selects touchpad.
@@ -15,7 +25,7 @@
*
* Position values in the range [0.0, 1.0) map to the screen.
*/
- void touch(int touchpad, float x, float y, float pressure);
+ void touch(int touchpad, float x, float y, float pressure) = 2;
/**
* Generate a simulated touchpad button state event.
@@ -23,5 +33,5 @@
* @param touchpad Selects touchpad.
* @param buttons A union of MotionEvent BUTTON_* values.
*/
- void buttonState(int touchpad, int buttons);
+ void buttonState(int touchpad, int buttons) = 3;
}
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpad.h b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
index d24d121..b1ee700 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpad.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
@@ -3,6 +3,7 @@
#include <utils/Errors.h>
#include <utils/RefBase.h>
+#include <utils/String8.h>
#include <utils/StrongPointer.h>
namespace android {
@@ -21,10 +22,18 @@
// Implementations should provide this, and hide their constructors.
// For the user, switching implementations should be as simple as changing
// the class whose |Create()| is called.
+ // Implementations should be minimial; major resource allocation should
+ // be performed in Attach().
static sp<VirtualTouchpad> Create() {
return sp<VirtualTouchpad>();
}
+ // Initialize a virtual touchpad.
+ virtual status_t Attach() = 0;
+
+ // Shut down a virtual touchpad.
+ virtual status_t Detach() = 0;
+
// Generate a simulated touch event.
//
// @param touchpad Touchpad selector index.
@@ -49,6 +58,9 @@
//
virtual status_t ButtonState(int touchpad, int buttons) = 0;
+ // Report state for 'dumpsys'.
+ virtual void dumpInternal(String8& result) = 0;
+
protected:
VirtualTouchpad() {}
~VirtualTouchpad() override {}
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
index dd9c265..471d9e0 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
@@ -13,8 +13,11 @@
public:
// VirtualTouchpad implementation:
static sp<VirtualTouchpad> Create();
+ status_t Attach() override;
+ status_t Detach() override;
status_t Touch(int touchpad, float x, float y, float pressure) override;
status_t ButtonState(int touchpad, int buttons) override;
+ void dumpInternal(String8& result) override;
protected:
VirtualTouchpadClient() {}
diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
index 469a2d0..b11a983 100644
--- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
+++ b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
@@ -97,7 +97,6 @@
static sp<VirtualTouchpad> Create(EvdevInjectorForTesting& injector) {
VirtualTouchpadForTesting* const touchpad = new VirtualTouchpadForTesting();
touchpad->SetEvdevInjectorForTesting(&injector);
- touchpad->Initialize();
return sp<VirtualTouchpad>(touchpad);
}
};
@@ -123,6 +122,9 @@
EvdevInjectorForTesting injector(record);
sp<VirtualTouchpad> touchpad(VirtualTouchpadForTesting::Create(injector));
+ status_t touch_status = touchpad->Attach();
+ EXPECT_EQ(0, touch_status);
+
// Check some aspects of uinput_user_dev.
const uinput_user_dev* uidev = injector.GetUiDev();
for (int i = 0; i < ABS_CNT; ++i) {
@@ -151,6 +153,7 @@
// From ConfigureKey(BTN_TOUCH):
expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY);
expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH);
+ expect.IoctlSetInt(UI_SET_KEYBIT, BTN_BACK);
// From ConfigureEnd():
expect.Write(uidev, sizeof(uinput_user_dev));
expect.IoctlVoid(UI_DEV_CREATE);
@@ -158,7 +161,7 @@
expect.Reset();
record.Reset();
- int touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0, 0, 0);
+ touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0, 0, 0);
EXPECT_EQ(0, touch_status);
expect.WriteInputEvent(EV_ABS, ABS_MT_SLOT, 0);
expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
@@ -180,16 +183,22 @@
expect.Reset();
record.Reset();
- touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.0f, 1.0f, 1.0f);
+ touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.99f, 0.99f, 0.99f);
EXPECT_EQ(0, touch_status);
expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
- expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, width);
- expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, height);
+ expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.99f * width);
+ expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.99f * height);
expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
EXPECT_EQ(expect.GetString(), record.GetString());
expect.Reset();
record.Reset();
+ touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.0f, 1.0f, 1.0f);
+ EXPECT_EQ(EINVAL, touch_status);
+ EXPECT_EQ(expect.GetString(), record.GetString());
+
+ expect.Reset();
+ record.Reset();
touch_status =
touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 0.75f, -0.01f);
EXPECT_EQ(0, touch_status);
@@ -224,6 +233,10 @@
expect.Reset();
record.Reset();
+ touch_status = touchpad->Detach();
+ EXPECT_EQ(0, touch_status);
+ expect.Close();
+ EXPECT_EQ(expect.GetString(), record.GetString());
}
TEST_F(VirtualTouchpadTest, Badness) {
@@ -232,11 +245,14 @@
EvdevInjectorForTesting injector(record);
sp<VirtualTouchpad> touchpad(VirtualTouchpadForTesting::Create(injector));
+ status_t touch_status = touchpad->Attach();
+ EXPECT_EQ(0, touch_status);
+
// Touch off-screen should return an error,
// and should not result in any system calls.
expect.Reset();
record.Reset();
- status_t touch_status =
+ touch_status =
touchpad->Touch(VirtualTouchpad::PRIMARY, -0.25f, 0.75f, 1.0f);
EXPECT_NE(OK, touch_status);
touch_status =
@@ -256,6 +272,10 @@
AMOTION_EVENT_BUTTON_FORWARD);
EXPECT_NE(OK, touch_status);
EXPECT_EQ(expect.GetString(), record.GetString());
+
+ // Repeated attach is an error.
+ touch_status = touchpad->Attach();
+ EXPECT_NE(0, touch_status);
}
} // namespace dvr
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index fae1dd9..10588b7 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -250,8 +250,12 @@
translate_ = Eigen::Translation3f(0, 0, -2.5f);
- if (!InitializeTouch())
- ALOGE("Failed to initialize virtual touchpad");
+ virtual_touchpad_ = VirtualTouchpadClient::Create();
+ const status_t touchpad_status = virtual_touchpad_->Attach();
+ if (touchpad_status != OK) {
+ ALOGE("Failed to connect to virtual touchpad");
+ return touchpad_status;
+ }
surface_flinger_view_.reset(new SurfaceFlingerView);
if (!surface_flinger_view_->Initialize(this))
@@ -702,22 +706,10 @@
controller_mesh_->Draw();
}
-bool ShellView::InitializeTouch() {
- virtual_touchpad_ = VirtualTouchpadClient::Create();
- if (!virtual_touchpad_.get()) {
- ALOGE("Failed to connect to virtual touchpad");
- return false;
- }
- return true;
-}
-
void ShellView::Touch() {
if (!virtual_touchpad_.get()) {
ALOGE("missing virtual touchpad");
- // Try to reconnect; useful in development.
- if (!InitializeTouch()) {
- return;
- }
+ return;
}
const android::status_t status = virtual_touchpad_->Touch(
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index c477669..49456c6 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -58,7 +58,6 @@
bool test_ime);
bool IsImeHit(const vec3& view_location, const vec3& view_direction,
vec3 *hit_location);
- bool InitializeTouch();
void Touch();
bool OnTouchpadButton(bool down, int button);
diff --git a/services/vr/vr_window_manager/vr_window_manager_binder.cpp b/services/vr/vr_window_manager/vr_window_manager_binder.cpp
index c2138b7..bd3f3ee 100644
--- a/services/vr/vr_window_manager/vr_window_manager_binder.cpp
+++ b/services/vr/vr_window_manager/vr_window_manager_binder.cpp
@@ -16,7 +16,8 @@
namespace {
const String16 kDumpPermission("android.permission.DUMP");
-const String16 kSendMeControllerInputPermission("TODO"); // TODO(kpschoedel)
+const String16 kSendMeControllerInputPermission(
+ "android.permission.RESTRICTED_VR_ACCESS");
} // anonymous namespace
constexpr size_t AshmemControllerDataProvider::kRegionLength;
@@ -136,8 +137,8 @@
int fd, const Vector<String16>& args [[gnu::unused]]) {
String8 result;
const android::IPCThreadState* ipc = android::IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
+ const pid_t pid = ipc->getCallingPid();
+ const uid_t uid = ipc->getCallingUid();
if ((uid != AID_SHELL) &&
!PermissionCache::checkPermission(kDumpPermission, pid, uid)) {
result.appendFormat("Permission denial: can't dump " LOG_TAG