| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 1 | #include "VirtualTouchpadService.h" | 
|  | 2 |  | 
| Kevin Schoedel | 4b64dd4 | 2017-03-07 13:06:25 -0500 | [diff] [blame] | 3 | #include <inttypes.h> | 
|  | 4 |  | 
|  | 5 | #include <binder/IPCThreadState.h> | 
|  | 6 | #include <binder/PermissionCache.h> | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 7 | #include <binder/Status.h> | 
| Kevin Schoedel | 4b64dd4 | 2017-03-07 13:06:25 -0500 | [diff] [blame] | 8 | #include <cutils/log.h> | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 9 | #include <linux/input.h> | 
| Kevin Schoedel | 4b64dd4 | 2017-03-07 13:06:25 -0500 | [diff] [blame] | 10 | #include <private/android_filesystem_config.h> | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 11 | #include <utils/Errors.h> | 
|  | 12 |  | 
|  | 13 | namespace android { | 
|  | 14 | namespace dvr { | 
|  | 15 |  | 
| Kevin Schoedel | 4b64dd4 | 2017-03-07 13:06:25 -0500 | [diff] [blame] | 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_)); | 
| Kevin Schoedel | 0d5a06a | 2017-03-22 13:33:32 -0400 | [diff] [blame] | 48 | client_pid_ = pid; | 
|  | 49 | return binder::Status::ok(); | 
| Kevin Schoedel | 4b64dd4 | 2017-03-07 13:06:25 -0500 | [diff] [blame] | 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(); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 78 | } | 
|  | 79 |  | 
| Kevin Schoedel | 3002b8a | 2017-03-06 14:34:39 -0500 | [diff] [blame] | 80 | binder::Status VirtualTouchpadService::buttonState(int touchpad, int buttons) { | 
| Kevin Schoedel | 4b64dd4 | 2017-03-07 13:06:25 -0500 | [diff] [blame] | 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 |  | 
| Kevin Schoedel | d8fccf0 | 2017-06-05 11:13:20 -0400 | [diff] [blame] | 90 | binder::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 Schoedel | 4b64dd4 | 2017-03-07 13:06:25 -0500 | [diff] [blame] | 100 | status_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 |  | 
|  | 120 | bool 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 |  | 
|  | 132 | bool VirtualTouchpadService::CheckTouchPermission(pid_t* out_pid) { | 
|  | 133 | const android::IPCThreadState* ipc = android::IPCThreadState::self(); | 
|  | 134 | *out_pid = ipc->getCallingPid(); | 
| Kevin Schoedel | 4b64dd4 | 2017-03-07 13:06:25 -0500 | [diff] [blame] | 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; | 
| Kevin Schoedel | 43b5b06 | 2017-01-19 13:46:17 -0500 | [diff] [blame] | 142 | } | 
|  | 143 |  | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 144 | }  // namespace dvr | 
|  | 145 | }  // namespace android |