blob: 523f890ce798c8fab2b6f7e9ab8af0b5666e746e [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_));
Kevin Schoedel0d5a06a2017-03-22 13:33:32 -040048 client_pid_ = pid;
49 return binder::Status::ok();
Kevin Schoedel4b64dd42017-03-07 13:06:25 -050050 }
51 client_pid_ = pid;
52 if (const status_t error = touchpad_->Attach()) {
53 return binder::Status::fromStatusT(error);
54 }
55 return binder::Status::ok();
56}
57
58binder::Status VirtualTouchpadService::detach() {
59 if (!CheckPermissions()) {
60 return binder::Status::fromStatusT(PERMISSION_DENIED);
61 }
62 client_pid_ = 0;
63 if (const status_t error = touchpad_->Detach()) {
64 return binder::Status::fromStatusT(error);
65 }
66 return binder::Status::ok();
67}
68
69binder::Status VirtualTouchpadService::touch(int touchpad, float x, float y,
70 float pressure) {
71 if (!CheckPermissions()) {
72 return binder::Status::fromStatusT(PERMISSION_DENIED);
73 }
74 if (const status_t error = touchpad_->Touch(touchpad, x, y, pressure)) {
75 return binder::Status::fromStatusT(error);
76 }
77 return binder::Status::ok();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080078}
79
Kevin Schoedel3002b8a2017-03-06 14:34:39 -050080binder::Status VirtualTouchpadService::buttonState(int touchpad, int buttons) {
Kevin Schoedel4b64dd42017-03-07 13:06:25 -050081 if (!CheckPermissions()) {
82 return binder::Status::fromStatusT(PERMISSION_DENIED);
83 }
84 if (const status_t error = touchpad_->ButtonState(touchpad, buttons)) {
85 return binder::Status::fromStatusT(error);
86 }
87 return binder::Status::ok();
88}
89
Kevin Schoedeld8fccf02017-06-05 11:13:20 -040090binder::Status VirtualTouchpadService::scroll(int touchpad, float x, float y) {
91 if (!CheckPermissions()) {
92 return binder::Status::fromStatusT(PERMISSION_DENIED);
93 }
94 if (const status_t error = touchpad_->Scroll(touchpad, x, y)) {
95 return binder::Status::fromStatusT(error);
96 }
97 return binder::Status::ok();
98}
99
Kevin Schoedel4b64dd42017-03-07 13:06:25 -0500100status_t VirtualTouchpadService::dump(
101 int fd, const Vector<String16>& args[[gnu::unused]]) {
102 String8 result;
103 const android::IPCThreadState* ipc = android::IPCThreadState::self();
104 const pid_t pid = ipc->getCallingPid();
105 const uid_t uid = ipc->getCallingUid();
106 if ((uid != AID_SHELL) &&
107 !PermissionCache::checkPermission(kDumpPermission, pid, uid)) {
108 result.appendFormat("Permission denial: can't dump " LOG_TAG
109 " from pid=%ld, uid=%ld\n",
110 static_cast<long>(pid), static_cast<long>(uid));
111 } else {
112 result.appendFormat("[service]\nclient_pid = %ld\n\n",
113 static_cast<long>(client_pid_));
114 touchpad_->dumpInternal(result);
115 }
116 write(fd, result.string(), result.size());
117 return OK;
118}
119
120bool VirtualTouchpadService::CheckPermissions() {
121 pid_t pid;
122 if (!CheckTouchPermission(&pid)) {
123 return false;
124 }
125 if (client_pid_ != pid) {
126 ALOGE("pid=%ld is not owner", static_cast<long>(pid));
127 return false;
128 }
129 return true;
130}
131
132bool VirtualTouchpadService::CheckTouchPermission(pid_t* out_pid) {
133 const android::IPCThreadState* ipc = android::IPCThreadState::self();
134 *out_pid = ipc->getCallingPid();
Kevin Schoedel4b64dd42017-03-07 13:06:25 -0500135 const uid_t uid = ipc->getCallingUid();
136 const bool permission = PermissionCache::checkPermission(kTouchPermission, *out_pid, uid);
137 if (!permission) {
138 ALOGE("permission denied to pid=%ld uid=%ld", static_cast<long>(*out_pid),
139 static_cast<long>(uid));
140 }
141 return permission;
Kevin Schoedel43b5b062017-01-19 13:46:17 -0500142}
143
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800144} // namespace dvr
145} // namespace android