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 21 VirtualTouchpadService::~VirtualTouchpadService() { 22 if (client_pid_) { 23 client_pid_ = 0; 24 touchpad_->Detach(); 25 } 26 } 27 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 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 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 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 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 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 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