• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "VirtualTouchpadService.h"
2 
3 #include <inttypes.h>
4 
5 #include <binder/IPCThreadState.h>
6 #include <binder/PermissionCache.h>
7 #include <binder/Status.h>
8 #include <cutils/log.h>
9 #include <linux/input.h>
10 #include <private/android_filesystem_config.h>
11 #include <utils/Errors.h>
12 
13 namespace android {
14 namespace dvr {
15 
16 namespace {
17 const String16 kDumpPermission("android.permission.DUMP");
18 const String16 kTouchPermission("android.permission.RESTRICTED_VR_ACCESS");
19 }  // anonymous namespace
20 
~VirtualTouchpadService()21 VirtualTouchpadService::~VirtualTouchpadService() {
22   if (client_pid_) {
23     client_pid_ = 0;
24     touchpad_->Detach();
25   }
26 }
27 
attach()28 binder::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     client_pid_ = pid;
49     return binder::Status::ok();
50   }
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 
detach()58 binder::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 
touch(int touchpad,float x,float y,float pressure)69 binder::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();
78 }
79 
buttonState(int touchpad,int buttons)80 binder::Status VirtualTouchpadService::buttonState(int touchpad, int buttons) {
81   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 
dump(int fd,const Vector<String16> & args)90 status_t VirtualTouchpadService::dump(
91     int fd, const Vector<String16>& args[[gnu::unused]]) {
92   String8 result;
93   const android::IPCThreadState* ipc = android::IPCThreadState::self();
94   const pid_t pid = ipc->getCallingPid();
95   const uid_t uid = ipc->getCallingUid();
96   if ((uid != AID_SHELL) &&
97       !PermissionCache::checkPermission(kDumpPermission, pid, uid)) {
98     result.appendFormat("Permission denial: can't dump " LOG_TAG
99                         " from pid=%ld, uid=%ld\n",
100                         static_cast<long>(pid), static_cast<long>(uid));
101   } else {
102     result.appendFormat("[service]\nclient_pid = %ld\n\n",
103                         static_cast<long>(client_pid_));
104     touchpad_->dumpInternal(result);
105   }
106   write(fd, result.string(), result.size());
107   return OK;
108 }
109 
CheckPermissions()110 bool VirtualTouchpadService::CheckPermissions() {
111   pid_t pid;
112   if (!CheckTouchPermission(&pid)) {
113     return false;
114   }
115   if (client_pid_ != pid) {
116     ALOGE("pid=%ld is not owner", static_cast<long>(pid));
117     return false;
118   }
119   return true;
120 }
121 
CheckTouchPermission(pid_t * out_pid)122 bool VirtualTouchpadService::CheckTouchPermission(pid_t* out_pid) {
123   const android::IPCThreadState* ipc = android::IPCThreadState::self();
124   *out_pid = ipc->getCallingPid();
125   const uid_t uid = ipc->getCallingUid();
126   const bool permission = PermissionCache::checkPermission(kTouchPermission, *out_pid, uid);
127   if (!permission) {
128     ALOGE("permission denied to pid=%ld uid=%ld", static_cast<long>(*out_pid),
129           static_cast<long>(uid));
130   }
131   return permission;
132 }
133 
134 }  // namespace dvr
135 }  // namespace android
136