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 | |
| 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 | #ifdef SELINUX_ACCESS_CONTROL |
| 126 | return true; |
| 127 | #else |
| 128 | const uid_t uid = ipc->getCallingUid(); |
| 129 | const bool permission = PermissionCache::checkPermission(kTouchPermission, *out_pid, uid); |
| 130 | if (!permission) { |
| 131 | ALOGE("permission denied to pid=%ld uid=%ld", static_cast<long>(*out_pid), |
| 132 | static_cast<long>(uid)); |
| 133 | } |
| 134 | return permission; |
| 135 | #endif |
Kevin Schoedel | 43b5b06 | 2017-01-19 13:46:17 -0500 | [diff] [blame] | 136 | } |
| 137 | |
Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 138 | } // namespace dvr |
| 139 | } // namespace android |