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 13namespace android { 14namespace dvr { 15 16namespace { 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 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 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(); 78} 79 80binder::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 90binder::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 100status_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(); 135 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; 142} 143 144} // namespace dvr 145} // namespace android 146