| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 1 | #include "pdx/service.h" | 
|  | 2 |  | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 3 | #include <fcntl.h> | 
| Alex Vakulenko | 4fe6058 | 2017-02-02 11:35:59 -0800 | [diff] [blame] | 4 | #include <log/log.h> | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 5 | #include <utils/misc.h> | 
|  | 6 |  | 
|  | 7 | #include <algorithm> | 
|  | 8 | #include <cstdint> | 
|  | 9 |  | 
|  | 10 | #include <pdx/trace.h> | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 11 |  | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 12 | namespace android { | 
|  | 13 | namespace pdx { | 
|  | 14 |  | 
|  | 15 | std::shared_ptr<Channel> Channel::GetFromMessageInfo(const MessageInfo& info) { | 
|  | 16 | return info.channel ? info.channel->shared_from_this() | 
|  | 17 | : std::shared_ptr<Channel>(); | 
|  | 18 | } | 
|  | 19 |  | 
|  | 20 | Message::Message() : replied_(true) {} | 
|  | 21 |  | 
|  | 22 | Message::Message(const MessageInfo& info) | 
|  | 23 | : service_{Service::GetFromMessageInfo(info)}, | 
|  | 24 | channel_{Channel::GetFromMessageInfo(info)}, | 
|  | 25 | info_{info}, | 
|  | 26 | replied_{IsImpulse()} { | 
|  | 27 | auto svc = service_.lock(); | 
|  | 28 | if (svc) | 
|  | 29 | state_ = svc->endpoint()->AllocateMessageState(); | 
|  | 30 | } | 
|  | 31 |  | 
|  | 32 | // C++11 specifies the move semantics for shared_ptr but not weak_ptr. This | 
|  | 33 | // means we have to manually implement the desired move semantics for Message. | 
| Chih-Hung Hsieh | 5bc849f | 2018-09-25 14:21:50 -0700 | [diff] [blame] | 34 | Message::Message(Message&& other) noexcept { *this = std::move(other); } | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 35 |  | 
| Chih-Hung Hsieh | 5bc849f | 2018-09-25 14:21:50 -0700 | [diff] [blame] | 36 | Message& Message::operator=(Message&& other) noexcept { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 37 | Destroy(); | 
|  | 38 | auto base = reinterpret_cast<std::uint8_t*>(&info_); | 
|  | 39 | std::fill(&base[0], &base[sizeof(info_)], 0); | 
|  | 40 | replied_ = true; | 
|  | 41 | std::swap(service_, other.service_); | 
|  | 42 | std::swap(channel_, other.channel_); | 
|  | 43 | std::swap(info_, other.info_); | 
|  | 44 | std::swap(state_, other.state_); | 
|  | 45 | std::swap(replied_, other.replied_); | 
|  | 46 | return *this; | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | Message::~Message() { Destroy(); } | 
|  | 50 |  | 
|  | 51 | void Message::Destroy() { | 
|  | 52 | auto svc = service_.lock(); | 
|  | 53 | if (svc) { | 
|  | 54 | if (!replied_) { | 
|  | 55 | ALOGE( | 
|  | 56 | "ERROR: Service \"%s\" failed to reply to message: op=%d pid=%d " | 
|  | 57 | "cid=%d\n", | 
|  | 58 | svc->name_.c_str(), info_.op, info_.pid, info_.cid); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 59 | svc->DefaultHandleMessage(*this); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 60 | } | 
|  | 61 | svc->endpoint()->FreeMessageState(state_); | 
|  | 62 | } | 
|  | 63 | state_ = nullptr; | 
|  | 64 | service_.reset(); | 
|  | 65 | channel_.reset(); | 
|  | 66 | } | 
|  | 67 |  | 
|  | 68 | const std::uint8_t* Message::ImpulseBegin() const { | 
|  | 69 | return reinterpret_cast<const std::uint8_t*>(info_.impulse); | 
|  | 70 | } | 
|  | 71 |  | 
|  | 72 | const std::uint8_t* Message::ImpulseEnd() const { | 
|  | 73 | return ImpulseBegin() + (IsImpulse() ? GetSendLength() : 0); | 
|  | 74 | } | 
|  | 75 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 76 | Status<size_t> Message::ReadVector(const struct iovec* vector, | 
|  | 77 | size_t vector_length) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 78 | PDX_TRACE_NAME("Message::ReadVector"); | 
|  | 79 | if (auto svc = service_.lock()) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 80 | return svc->endpoint()->ReadMessageData(this, vector, vector_length); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 81 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 82 | return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 83 | } | 
|  | 84 | } | 
|  | 85 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 86 | Status<void> Message::ReadVectorAll(const struct iovec* vector, | 
|  | 87 | size_t vector_length) { | 
|  | 88 | PDX_TRACE_NAME("Message::ReadVectorAll"); | 
|  | 89 | if (auto svc = service_.lock()) { | 
|  | 90 | const auto status = | 
|  | 91 | svc->endpoint()->ReadMessageData(this, vector, vector_length); | 
|  | 92 | if (!status) | 
|  | 93 | return status.error_status(); | 
|  | 94 | size_t size_to_read = 0; | 
|  | 95 | for (size_t i = 0; i < vector_length; i++) | 
|  | 96 | size_to_read += vector[i].iov_len; | 
|  | 97 | if (status.get() < size_to_read) | 
|  | 98 | return ErrorStatus{EIO}; | 
|  | 99 | return {}; | 
|  | 100 | } else { | 
|  | 101 | return ErrorStatus{ESHUTDOWN}; | 
|  | 102 | } | 
|  | 103 | } | 
|  | 104 |  | 
|  | 105 | Status<size_t> Message::Read(void* buffer, size_t length) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 106 | PDX_TRACE_NAME("Message::Read"); | 
|  | 107 | if (auto svc = service_.lock()) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 108 | const struct iovec vector = {buffer, length}; | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 109 | return svc->endpoint()->ReadMessageData(this, &vector, 1); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 110 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 111 | return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 112 | } | 
|  | 113 | } | 
|  | 114 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 115 | Status<size_t> Message::WriteVector(const struct iovec* vector, | 
|  | 116 | size_t vector_length) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 117 | PDX_TRACE_NAME("Message::WriteVector"); | 
|  | 118 | if (auto svc = service_.lock()) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 119 | return svc->endpoint()->WriteMessageData(this, vector, vector_length); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 120 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 121 | return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 122 | } | 
|  | 123 | } | 
|  | 124 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 125 | Status<void> Message::WriteVectorAll(const struct iovec* vector, | 
|  | 126 | size_t vector_length) { | 
|  | 127 | PDX_TRACE_NAME("Message::WriteVector"); | 
|  | 128 | if (auto svc = service_.lock()) { | 
|  | 129 | const auto status = | 
|  | 130 | svc->endpoint()->WriteMessageData(this, vector, vector_length); | 
|  | 131 | if (!status) | 
|  | 132 | return status.error_status(); | 
|  | 133 | size_t size_to_write = 0; | 
|  | 134 | for (size_t i = 0; i < vector_length; i++) | 
|  | 135 | size_to_write += vector[i].iov_len; | 
|  | 136 | if (status.get() < size_to_write) | 
|  | 137 | return ErrorStatus{EIO}; | 
|  | 138 | return {}; | 
|  | 139 | } else { | 
|  | 140 | return ErrorStatus{ESHUTDOWN}; | 
|  | 141 | } | 
|  | 142 | } | 
|  | 143 |  | 
|  | 144 | Status<size_t> Message::Write(const void* buffer, size_t length) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 145 | PDX_TRACE_NAME("Message::Write"); | 
|  | 146 | if (auto svc = service_.lock()) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 147 | const struct iovec vector = {const_cast<void*>(buffer), length}; | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 148 | return svc->endpoint()->WriteMessageData(this, &vector, 1); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 149 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 150 | return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 151 | } | 
|  | 152 | } | 
|  | 153 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 154 | Status<FileReference> Message::PushFileHandle(const LocalHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 155 | PDX_TRACE_NAME("Message::PushFileHandle"); | 
|  | 156 | if (auto svc = service_.lock()) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 157 | return svc->endpoint()->PushFileHandle(this, handle); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 158 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 159 | return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 160 | } | 
|  | 161 | } | 
|  | 162 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 163 | Status<FileReference> Message::PushFileHandle(const BorrowedHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 164 | PDX_TRACE_NAME("Message::PushFileHandle"); | 
|  | 165 | if (auto svc = service_.lock()) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 166 | return svc->endpoint()->PushFileHandle(this, handle); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 167 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 168 | return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 169 | } | 
|  | 170 | } | 
|  | 171 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 172 | Status<FileReference> Message::PushFileHandle(const RemoteHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 173 | PDX_TRACE_NAME("Message::PushFileHandle"); | 
|  | 174 | if (auto svc = service_.lock()) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 175 | return svc->endpoint()->PushFileHandle(this, handle); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 176 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 177 | return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 178 | } | 
|  | 179 | } | 
|  | 180 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 181 | Status<ChannelReference> Message::PushChannelHandle( | 
|  | 182 | const LocalChannelHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 183 | PDX_TRACE_NAME("Message::PushChannelHandle"); | 
|  | 184 | if (auto svc = service_.lock()) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 185 | return svc->endpoint()->PushChannelHandle(this, handle); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 186 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 187 | return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 188 | } | 
|  | 189 | } | 
|  | 190 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 191 | Status<ChannelReference> Message::PushChannelHandle( | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 192 | const BorrowedChannelHandle& handle) { | 
|  | 193 | PDX_TRACE_NAME("Message::PushChannelHandle"); | 
|  | 194 | if (auto svc = service_.lock()) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 195 | return svc->endpoint()->PushChannelHandle(this, handle); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 196 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 197 | return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 198 | } | 
|  | 199 | } | 
|  | 200 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 201 | Status<ChannelReference> Message::PushChannelHandle( | 
|  | 202 | const RemoteChannelHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 203 | PDX_TRACE_NAME("Message::PushChannelHandle"); | 
|  | 204 | if (auto svc = service_.lock()) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 205 | return svc->endpoint()->PushChannelHandle(this, handle); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 206 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 207 | return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 208 | } | 
|  | 209 | } | 
|  | 210 |  | 
|  | 211 | bool Message::GetFileHandle(FileReference ref, LocalHandle* handle) { | 
|  | 212 | PDX_TRACE_NAME("Message::GetFileHandle"); | 
|  | 213 | auto svc = service_.lock(); | 
|  | 214 | if (!svc) | 
|  | 215 | return false; | 
|  | 216 |  | 
|  | 217 | if (ref >= 0) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 218 | *handle = svc->endpoint()->GetFileHandle(this, ref); | 
|  | 219 | if (!handle->IsValid()) | 
|  | 220 | return false; | 
|  | 221 | } else { | 
|  | 222 | *handle = LocalHandle{ref}; | 
|  | 223 | } | 
|  | 224 | return true; | 
|  | 225 | } | 
|  | 226 |  | 
|  | 227 | bool Message::GetChannelHandle(ChannelReference ref, | 
|  | 228 | LocalChannelHandle* handle) { | 
|  | 229 | PDX_TRACE_NAME("Message::GetChannelHandle"); | 
|  | 230 | auto svc = service_.lock(); | 
|  | 231 | if (!svc) | 
|  | 232 | return false; | 
|  | 233 |  | 
|  | 234 | if (ref >= 0) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 235 | *handle = svc->endpoint()->GetChannelHandle(this, ref); | 
|  | 236 | if (!handle->valid()) | 
|  | 237 | return false; | 
|  | 238 | } else { | 
|  | 239 | *handle = LocalChannelHandle{nullptr, ref}; | 
|  | 240 | } | 
|  | 241 | return true; | 
|  | 242 | } | 
|  | 243 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 244 | Status<void> Message::Reply(int return_code) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 245 | PDX_TRACE_NAME("Message::Reply"); | 
|  | 246 | auto svc = service_.lock(); | 
|  | 247 | if (!replied_ && svc) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 248 | const auto ret = svc->endpoint()->MessageReply(this, return_code); | 
|  | 249 | replied_ = ret.ok(); | 
|  | 250 | return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 251 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 252 | return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 253 | } | 
|  | 254 | } | 
|  | 255 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 256 | Status<void> Message::ReplyFileDescriptor(unsigned int fd) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 257 | PDX_TRACE_NAME("Message::ReplyFileDescriptor"); | 
|  | 258 | auto svc = service_.lock(); | 
|  | 259 | if (!replied_ && svc) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 260 | const auto ret = svc->endpoint()->MessageReplyFd(this, fd); | 
|  | 261 | replied_ = ret.ok(); | 
|  | 262 | return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 263 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 264 | return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 265 | } | 
|  | 266 | } | 
|  | 267 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 268 | Status<void> Message::ReplyError(unsigned int error) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 269 | PDX_TRACE_NAME("Message::ReplyError"); | 
|  | 270 | auto svc = service_.lock(); | 
|  | 271 | if (!replied_ && svc) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 272 | const auto ret = | 
|  | 273 | svc->endpoint()->MessageReply(this, -static_cast<int>(error)); | 
|  | 274 | replied_ = ret.ok(); | 
|  | 275 | return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 276 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 277 | return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 278 | } | 
|  | 279 | } | 
|  | 280 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 281 | Status<void> Message::Reply(const LocalHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 282 | PDX_TRACE_NAME("Message::ReplyFileHandle"); | 
|  | 283 | auto svc = service_.lock(); | 
|  | 284 | if (!replied_ && svc) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 285 | Status<void> ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 286 |  | 
|  | 287 | if (handle) | 
|  | 288 | ret = svc->endpoint()->MessageReplyFd(this, handle.Get()); | 
|  | 289 | else | 
|  | 290 | ret = svc->endpoint()->MessageReply(this, handle.Get()); | 
|  | 291 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 292 | replied_ = ret.ok(); | 
|  | 293 | return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 294 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 295 | return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 296 | } | 
|  | 297 | } | 
|  | 298 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 299 | Status<void> Message::Reply(const BorrowedHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 300 | PDX_TRACE_NAME("Message::ReplyFileHandle"); | 
|  | 301 | auto svc = service_.lock(); | 
|  | 302 | if (!replied_ && svc) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 303 | Status<void> ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 304 |  | 
|  | 305 | if (handle) | 
|  | 306 | ret = svc->endpoint()->MessageReplyFd(this, handle.Get()); | 
|  | 307 | else | 
|  | 308 | ret = svc->endpoint()->MessageReply(this, handle.Get()); | 
|  | 309 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 310 | replied_ = ret.ok(); | 
|  | 311 | return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 312 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 313 | return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 314 | } | 
|  | 315 | } | 
|  | 316 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 317 | Status<void> Message::Reply(const RemoteHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 318 | PDX_TRACE_NAME("Message::ReplyFileHandle"); | 
|  | 319 | auto svc = service_.lock(); | 
|  | 320 | if (!replied_ && svc) { | 
| Greg Kaiser | fa1f420 | 2018-11-12 12:33:13 -0800 | [diff] [blame] | 321 | Status<void> ret = svc->endpoint()->MessageReply(this, handle.Get()); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 322 | replied_ = ret.ok(); | 
|  | 323 | return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 324 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 325 | return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 326 | } | 
|  | 327 | } | 
|  | 328 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 329 | Status<void> Message::Reply(const LocalChannelHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 330 | auto svc = service_.lock(); | 
|  | 331 | if (!replied_ && svc) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 332 | const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle); | 
|  | 333 | replied_ = ret.ok(); | 
|  | 334 | return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 335 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 336 | return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 337 | } | 
|  | 338 | } | 
|  | 339 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 340 | Status<void> Message::Reply(const BorrowedChannelHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 341 | auto svc = service_.lock(); | 
|  | 342 | if (!replied_ && svc) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 343 | const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle); | 
|  | 344 | replied_ = ret.ok(); | 
|  | 345 | return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 346 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 347 | return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 348 | } | 
|  | 349 | } | 
|  | 350 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 351 | Status<void> Message::Reply(const RemoteChannelHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 352 | auto svc = service_.lock(); | 
|  | 353 | if (!replied_ && svc) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 354 | const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle); | 
|  | 355 | replied_ = ret.ok(); | 
|  | 356 | return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 357 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 358 | return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 359 | } | 
|  | 360 | } | 
|  | 361 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 362 | Status<void> Message::ModifyChannelEvents(int clear_mask, int set_mask) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 363 | PDX_TRACE_NAME("Message::ModifyChannelEvents"); | 
|  | 364 | if (auto svc = service_.lock()) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 365 | return svc->endpoint()->ModifyChannelEvents(info_.cid, clear_mask, | 
|  | 366 | set_mask); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 367 | } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 368 | return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 369 | } | 
|  | 370 | } | 
|  | 371 |  | 
|  | 372 | Status<RemoteChannelHandle> Message::PushChannel( | 
|  | 373 | int flags, const std::shared_ptr<Channel>& channel, int* channel_id) { | 
|  | 374 | PDX_TRACE_NAME("Message::PushChannel"); | 
|  | 375 | if (auto svc = service_.lock()) { | 
|  | 376 | return svc->PushChannel(this, flags, channel, channel_id); | 
|  | 377 | } else { | 
|  | 378 | return ErrorStatus(ESHUTDOWN); | 
|  | 379 | } | 
|  | 380 | } | 
|  | 381 |  | 
|  | 382 | Status<RemoteChannelHandle> Message::PushChannel( | 
|  | 383 | Service* service, int flags, const std::shared_ptr<Channel>& channel, | 
|  | 384 | int* channel_id) { | 
|  | 385 | PDX_TRACE_NAME("Message::PushChannel"); | 
|  | 386 | return service->PushChannel(this, flags, channel, channel_id); | 
|  | 387 | } | 
|  | 388 |  | 
|  | 389 | Status<int> Message::CheckChannel(ChannelReference ref, | 
|  | 390 | std::shared_ptr<Channel>* channel) const { | 
|  | 391 | PDX_TRACE_NAME("Message::CheckChannel"); | 
|  | 392 | if (auto svc = service_.lock()) { | 
|  | 393 | return svc->CheckChannel(this, ref, channel); | 
|  | 394 | } else { | 
|  | 395 | return ErrorStatus(ESHUTDOWN); | 
|  | 396 | } | 
|  | 397 | } | 
|  | 398 |  | 
|  | 399 | Status<int> Message::CheckChannel(const Service* service, ChannelReference ref, | 
|  | 400 | std::shared_ptr<Channel>* channel) const { | 
|  | 401 | PDX_TRACE_NAME("Message::CheckChannel"); | 
|  | 402 | return service->CheckChannel(this, ref, channel); | 
|  | 403 | } | 
|  | 404 |  | 
|  | 405 | pid_t Message::GetProcessId() const { return info_.pid; } | 
|  | 406 |  | 
|  | 407 | pid_t Message::GetThreadId() const { return info_.tid; } | 
|  | 408 |  | 
|  | 409 | uid_t Message::GetEffectiveUserId() const { return info_.euid; } | 
|  | 410 |  | 
|  | 411 | gid_t Message::GetEffectiveGroupId() const { return info_.egid; } | 
|  | 412 |  | 
|  | 413 | int Message::GetChannelId() const { return info_.cid; } | 
|  | 414 |  | 
|  | 415 | int Message::GetMessageId() const { return info_.mid; } | 
|  | 416 |  | 
|  | 417 | int Message::GetOp() const { return info_.op; } | 
|  | 418 |  | 
|  | 419 | int Message::GetFlags() const { return info_.flags; } | 
|  | 420 |  | 
|  | 421 | size_t Message::GetSendLength() const { return info_.send_len; } | 
|  | 422 |  | 
|  | 423 | size_t Message::GetReceiveLength() const { return info_.recv_len; } | 
|  | 424 |  | 
|  | 425 | size_t Message::GetFileDescriptorCount() const { return info_.fd_count; } | 
|  | 426 |  | 
|  | 427 | std::shared_ptr<Channel> Message::GetChannel() const { return channel_.lock(); } | 
|  | 428 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 429 | Status<void> Message::SetChannel(const std::shared_ptr<Channel>& chan) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 430 | channel_ = chan; | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 431 | Status<void> status; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 432 | if (auto svc = service_.lock()) | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 433 | status = svc->SetChannel(info_.cid, chan); | 
|  | 434 | return status; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 435 | } | 
|  | 436 |  | 
|  | 437 | std::shared_ptr<Service> Message::GetService() const { return service_.lock(); } | 
|  | 438 |  | 
|  | 439 | const MessageInfo& Message::GetInfo() const { return info_; } | 
|  | 440 |  | 
|  | 441 | Service::Service(const std::string& name, std::unique_ptr<Endpoint> endpoint) | 
|  | 442 | : name_(name), endpoint_{std::move(endpoint)} { | 
|  | 443 | if (!endpoint_) | 
|  | 444 | return; | 
|  | 445 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 446 | const auto status = endpoint_->SetService(this); | 
|  | 447 | ALOGE_IF(!status, "Failed to set service context because: %s", | 
|  | 448 | status.GetErrorMessage().c_str()); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 449 | } | 
|  | 450 |  | 
|  | 451 | Service::~Service() { | 
|  | 452 | if (endpoint_) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 453 | const auto status = endpoint_->SetService(nullptr); | 
|  | 454 | ALOGE_IF(!status, "Failed to clear service context because: %s", | 
|  | 455 | status.GetErrorMessage().c_str()); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 456 | } | 
|  | 457 | } | 
|  | 458 |  | 
|  | 459 | std::shared_ptr<Service> Service::GetFromMessageInfo(const MessageInfo& info) { | 
|  | 460 | return info.service ? info.service->shared_from_this() | 
|  | 461 | : std::shared_ptr<Service>(); | 
|  | 462 | } | 
|  | 463 |  | 
|  | 464 | bool Service::IsInitialized() const { return endpoint_.get() != nullptr; } | 
|  | 465 |  | 
|  | 466 | std::shared_ptr<Channel> Service::OnChannelOpen(Message& /*message*/) { | 
|  | 467 | return nullptr; | 
|  | 468 | } | 
|  | 469 |  | 
|  | 470 | void Service::OnChannelClose(Message& /*message*/, | 
|  | 471 | const std::shared_ptr<Channel>& /*channel*/) {} | 
|  | 472 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 473 | Status<void> Service::SetChannel(int channel_id, | 
|  | 474 | const std::shared_ptr<Channel>& channel) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 475 | PDX_TRACE_NAME("Service::SetChannel"); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 476 | std::lock_guard<std::mutex> autolock(channels_mutex_); | 
|  | 477 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 478 | const auto status = endpoint_->SetChannel(channel_id, channel.get()); | 
|  | 479 | if (!status) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 480 | ALOGE("%s::SetChannel: Failed to set channel context: %s\n", name_.c_str(), | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 481 | status.GetErrorMessage().c_str()); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 482 |  | 
|  | 483 | // It's possible someone mucked with things behind our back by calling the C | 
|  | 484 | // API directly. Since we know the channel id isn't valid, make sure we | 
|  | 485 | // don't have it in the channels map. | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 486 | if (status.error() == ENOENT) | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 487 | channels_.erase(channel_id); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 488 | } else { | 
|  | 489 | if (channel != nullptr) | 
|  | 490 | channels_[channel_id] = channel; | 
|  | 491 | else | 
|  | 492 | channels_.erase(channel_id); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 493 | } | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 494 | return status; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 495 | } | 
|  | 496 |  | 
|  | 497 | std::shared_ptr<Channel> Service::GetChannel(int channel_id) const { | 
|  | 498 | PDX_TRACE_NAME("Service::GetChannel"); | 
|  | 499 | std::lock_guard<std::mutex> autolock(channels_mutex_); | 
|  | 500 |  | 
|  | 501 | auto search = channels_.find(channel_id); | 
|  | 502 | if (search != channels_.end()) | 
|  | 503 | return search->second; | 
|  | 504 | else | 
|  | 505 | return nullptr; | 
|  | 506 | } | 
|  | 507 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 508 | Status<void> Service::CloseChannel(int channel_id) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 509 | PDX_TRACE_NAME("Service::CloseChannel"); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 510 | std::lock_guard<std::mutex> autolock(channels_mutex_); | 
|  | 511 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 512 | const auto status = endpoint_->CloseChannel(channel_id); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 513 |  | 
|  | 514 | // Always erase the map entry, in case someone mucked with things behind our | 
|  | 515 | // back using the C API directly. | 
|  | 516 | channels_.erase(channel_id); | 
|  | 517 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 518 | return status; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 519 | } | 
|  | 520 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 521 | Status<void> Service::ModifyChannelEvents(int channel_id, int clear_mask, | 
|  | 522 | int set_mask) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 523 | PDX_TRACE_NAME("Service::ModifyChannelEvents"); | 
|  | 524 | return endpoint_->ModifyChannelEvents(channel_id, clear_mask, set_mask); | 
|  | 525 | } | 
|  | 526 |  | 
|  | 527 | Status<RemoteChannelHandle> Service::PushChannel( | 
|  | 528 | Message* message, int flags, const std::shared_ptr<Channel>& channel, | 
|  | 529 | int* channel_id) { | 
|  | 530 | PDX_TRACE_NAME("Service::PushChannel"); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 531 |  | 
|  | 532 | std::lock_guard<std::mutex> autolock(channels_mutex_); | 
|  | 533 |  | 
|  | 534 | int channel_id_temp = -1; | 
|  | 535 | Status<RemoteChannelHandle> ret = | 
|  | 536 | endpoint_->PushChannel(message, flags, channel.get(), &channel_id_temp); | 
|  | 537 | ALOGE_IF(!ret.ok(), "%s::PushChannel: Failed to push channel: %s", | 
|  | 538 | name_.c_str(), strerror(ret.error())); | 
|  | 539 |  | 
|  | 540 | if (channel && channel_id_temp != -1) | 
|  | 541 | channels_[channel_id_temp] = channel; | 
|  | 542 | if (channel_id) | 
|  | 543 | *channel_id = channel_id_temp; | 
|  | 544 |  | 
|  | 545 | return ret; | 
|  | 546 | } | 
|  | 547 |  | 
|  | 548 | Status<int> Service::CheckChannel(const Message* message, ChannelReference ref, | 
|  | 549 | std::shared_ptr<Channel>* channel) const { | 
|  | 550 | PDX_TRACE_NAME("Service::CheckChannel"); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 551 |  | 
|  | 552 | // Synchronization to maintain consistency between the kernel's channel | 
|  | 553 | // context pointer and the userspace channels_ map. Other threads may attempt | 
|  | 554 | // to modify the map at the same time, which could cause the channel context | 
|  | 555 | // pointer returned by the kernel to be invalid. | 
|  | 556 | std::lock_guard<std::mutex> autolock(channels_mutex_); | 
|  | 557 |  | 
|  | 558 | Channel* channel_context = nullptr; | 
|  | 559 | Status<int> ret = endpoint_->CheckChannel( | 
|  | 560 | message, ref, channel ? &channel_context : nullptr); | 
|  | 561 | if (ret && channel) { | 
|  | 562 | if (channel_context) | 
|  | 563 | *channel = channel_context->shared_from_this(); | 
|  | 564 | else | 
|  | 565 | *channel = nullptr; | 
|  | 566 | } | 
|  | 567 |  | 
|  | 568 | return ret; | 
|  | 569 | } | 
|  | 570 |  | 
|  | 571 | std::string Service::DumpState(size_t /*max_length*/) { return ""; } | 
|  | 572 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 573 | Status<void> Service::HandleMessage(Message& message) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 574 | return DefaultHandleMessage(message); | 
|  | 575 | } | 
|  | 576 |  | 
|  | 577 | void Service::HandleImpulse(Message& /*impulse*/) {} | 
|  | 578 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 579 | Status<void> Service::HandleSystemMessage(Message& message) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 580 | const MessageInfo& info = message.GetInfo(); | 
|  | 581 |  | 
|  | 582 | switch (info.op) { | 
|  | 583 | case opcodes::CHANNEL_OPEN: { | 
|  | 584 | ALOGD("%s::OnChannelOpen: pid=%d cid=%d\n", name_.c_str(), info.pid, | 
|  | 585 | info.cid); | 
|  | 586 | message.SetChannel(OnChannelOpen(message)); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 587 | return message.Reply(0); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 588 | } | 
|  | 589 |  | 
|  | 590 | case opcodes::CHANNEL_CLOSE: { | 
|  | 591 | ALOGD("%s::OnChannelClose: pid=%d cid=%d\n", name_.c_str(), info.pid, | 
|  | 592 | info.cid); | 
|  | 593 | OnChannelClose(message, Channel::GetFromMessageInfo(info)); | 
|  | 594 | message.SetChannel(nullptr); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 595 | return message.Reply(0); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 596 | } | 
|  | 597 |  | 
|  | 598 | case opcodes::REPORT_SYSPROP_CHANGE: | 
|  | 599 | ALOGD("%s:REPORT_SYSPROP_CHANGE: pid=%d cid=%d\n", name_.c_str(), | 
|  | 600 | info.pid, info.cid); | 
|  | 601 | OnSysPropChange(); | 
|  | 602 | android::report_sysprop_change(); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 603 | return message.Reply(0); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 604 |  | 
|  | 605 | case opcodes::DUMP_STATE: { | 
|  | 606 | ALOGD("%s:DUMP_STATE: pid=%d cid=%d\n", name_.c_str(), info.pid, | 
|  | 607 | info.cid); | 
|  | 608 | auto response = DumpState(message.GetReceiveLength()); | 
|  | 609 | const size_t response_size = response.size() < message.GetReceiveLength() | 
|  | 610 | ? response.size() | 
|  | 611 | : message.GetReceiveLength(); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 612 | const Status<size_t> status = | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 613 | message.Write(response.data(), response_size); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 614 | if (status && status.get() < response_size) | 
|  | 615 | return message.ReplyError(EIO); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 616 | else | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 617 | return message.Reply(status); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 618 | } | 
|  | 619 |  | 
|  | 620 | default: | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 621 | return ErrorStatus{EOPNOTSUPP}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 622 | } | 
|  | 623 | } | 
|  | 624 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 625 | Status<void> Service::DefaultHandleMessage(Message& message) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 626 | const MessageInfo& info = message.GetInfo(); | 
|  | 627 |  | 
|  | 628 | ALOGD_IF(TRACE, "Service::DefaultHandleMessage: pid=%d cid=%d op=%d\n", | 
|  | 629 | info.pid, info.cid, info.op); | 
|  | 630 |  | 
|  | 631 | switch (info.op) { | 
|  | 632 | case opcodes::CHANNEL_OPEN: | 
|  | 633 | case opcodes::CHANNEL_CLOSE: | 
|  | 634 | case opcodes::REPORT_SYSPROP_CHANGE: | 
|  | 635 | case opcodes::DUMP_STATE: | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 636 | return HandleSystemMessage(message); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 637 |  | 
|  | 638 | default: | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 639 | return message.ReplyError(EOPNOTSUPP); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 640 | } | 
|  | 641 | } | 
|  | 642 |  | 
|  | 643 | void Service::OnSysPropChange() {} | 
|  | 644 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 645 | Status<void> Service::ReceiveAndDispatch() { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 646 | Message message; | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 647 | const auto status = endpoint_->MessageReceive(&message); | 
|  | 648 | if (!status) { | 
|  | 649 | ALOGE("Failed to receive message: %s\n", status.GetErrorMessage().c_str()); | 
|  | 650 | return status; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 651 | } | 
|  | 652 |  | 
|  | 653 | std::shared_ptr<Service> service = message.GetService(); | 
|  | 654 |  | 
|  | 655 | if (!service) { | 
|  | 656 | ALOGE("Service::ReceiveAndDispatch: service context is NULL!!!\n"); | 
|  | 657 | // Don't block the sender indefinitely in this error case. | 
|  | 658 | endpoint_->MessageReply(&message, -EINVAL); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 659 | return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 660 | } | 
|  | 661 |  | 
|  | 662 | if (message.IsImpulse()) { | 
|  | 663 | service->HandleImpulse(message); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 664 | return {}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 665 | } else if (service->HandleSystemMessage(message)) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 666 | return {}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 667 | } else { | 
|  | 668 | return service->HandleMessage(message); | 
|  | 669 | } | 
|  | 670 | } | 
|  | 671 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 672 | Status<void> Service::Cancel() { return endpoint_->Cancel(); } | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 673 |  | 
|  | 674 | }  // namespace pdx | 
|  | 675 | }  // namespace android |