blob: 2e2f6220a21a8f2f4e5da781d73b84144e7d1fa7 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include "VirtualTouchpadService.h"
2
Kevin Schoedel4b64dd42017-03-07 13:06:25 -05003#include <inttypes.h>
4
5#include <binder/IPCThreadState.h>
6#include <binder/PermissionCache.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08007#include <binder/Status.h>
Kevin Schoedel4b64dd42017-03-07 13:06:25 -05008#include <cutils/log.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08009#include <linux/input.h>
Kevin Schoedel4b64dd42017-03-07 13:06:25 -050010#include <private/android_filesystem_config.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080011#include <utils/Errors.h>
12
13namespace android {
14namespace dvr {
15
Kevin Schoedel4b64dd42017-03-07 13:06:25 -050016namespace {
17const String16 kDumpPermission("android.permission.DUMP");
18const String16 kTouchPermission("android.permission.RESTRICTED_VR_ACCESS");
19} // anonymous namespace
20
21VirtualTouchpadService::~VirtualTouchpadService() {
22 if (client_pid_) {
23 client_pid_ = 0;
24 touchpad_->Detach();
25 }
26}
27
28binder::Status VirtualTouchpadService::attach() {
29 pid_t pid;
30 if (!CheckTouchPermission(&pid)) {
31 return binder::Status::fromStatusT(PERMISSION_DENIED);
32 }
33 if (client_pid_ == pid) {
34 // The same client has called attach() twice with no intervening detach().
35 // This indicates a problem with the client, so return an error.
36 // However, since the client is already attached, any touchpad actions
37 // it takes will still work.
38 ALOGE("pid=%ld attached twice", static_cast<long>(pid));
39 return binder::Status::fromStatusT(ALREADY_EXISTS);
40 }
41 if (client_pid_ != 0) {
42 // Attach while another client is attached. This can happen if the client
43 // dies without cleaning up after itself, so move ownership to the current
44 // caller. If two actual clients have connected, the problem will be
45 // reported when the previous client performs any touchpad action.
46 ALOGE("pid=%ld replaces %ld", static_cast<long>(pid),
47 static_cast<long>(client_pid_));
48 }
49 client_pid_ = pid;
50 if (const status_t error = touchpad_->Attach()) {
51 return binder::Status::fromStatusT(error);
52 }
53 return binder::Status::ok();
54}
55
56binder::Status VirtualTouchpadService::detach() {
57 if (!CheckPermissions()) {
58 return binder::Status::fromStatusT(PERMISSION_DENIED);
59 }
60 client_pid_ = 0;
61 if (const status_t error = touchpad_->Detach()) {
62 return binder::Status::fromStatusT(error);
63 }
64 return binder::Status::ok();
65}
66
67binder::Status VirtualTouchpadService::touch(int touchpad, float x, float y,
68 float pressure) {
69 if (!CheckPermissions()) {
70 return binder::Status::fromStatusT(PERMISSION_DENIED);
71 }
72 if (const status_t error = touchpad_->Touch(touchpad, x, y, pressure)) {
73 return binder::Status::fromStatusT(error);
74 }
75 return binder::Status::ok();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080076}
77
Kevin Schoedel3002b8a2017-03-06 14:34:39 -050078binder::Status VirtualTouchpadService::buttonState(int touchpad, int buttons) {
Kevin Schoedel4b64dd42017-03-07 13:06:25 -050079 if (!CheckPermissions()) {
80 return binder::Status::fromStatusT(PERMISSION_DENIED);
81 }
82 if (const status_t error = touchpad_->ButtonState(touchpad, buttons)) {
83 return binder::Status::fromStatusT(error);
84 }
85 return binder::Status::ok();
86}
87
88status_t VirtualTouchpadService::dump(
89 int fd, const Vector<String16>& args[[gnu::unused]]) {
90 String8 result;
91 const android::IPCThreadState* ipc = android::IPCThreadState::self();
92 const pid_t pid = ipc->getCallingPid();
93 const uid_t uid = ipc->getCallingUid();
94 if ((uid != AID_SHELL) &&
95 !PermissionCache::checkPermission(kDumpPermission, pid, uid)) {
96 result.appendFormat("Permission denial: can't dump " LOG_TAG
97 " from pid=%ld, uid=%ld\n",
98 static_cast<long>(pid), static_cast<long>(uid));
99 } else {
100 result.appendFormat("[service]\nclient_pid = %ld\n\n",
101 static_cast<long>(client_pid_));
102 touchpad_->dumpInternal(result);
103 }
104 write(fd, result.string(), result.size());
105 return OK;
106}
107
108bool VirtualTouchpadService::CheckPermissions() {
109 pid_t pid;
110 if (!CheckTouchPermission(&pid)) {
111 return false;
112 }
113 if (client_pid_ != pid) {
114 ALOGE("pid=%ld is not owner", static_cast<long>(pid));
115 return false;
116 }
117 return true;
118}
119
120bool VirtualTouchpadService::CheckTouchPermission(pid_t* out_pid) {
121 const android::IPCThreadState* ipc = android::IPCThreadState::self();
122 *out_pid = ipc->getCallingPid();
123#ifdef SELINUX_ACCESS_CONTROL
124 return true;
125#else
126 const uid_t uid = ipc->getCallingUid();
127 const bool permission = PermissionCache::checkPermission(kTouchPermission, *out_pid, uid);
128 if (!permission) {
129 ALOGE("permission denied to pid=%ld uid=%ld", static_cast<long>(*out_pid),
130 static_cast<long>(uid));
131 }
132 return permission;
133#endif
Kevin Schoedel43b5b062017-01-19 13:46:17 -0500134}
135
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800136} // namespace dvr
137} // namespace android