| 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) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 321 |     Status<void> ret; | 
 | 322 |  | 
 | 323 |     if (handle) | 
 | 324 |       ret = svc->endpoint()->MessageReply(this, handle.Get()); | 
 | 325 |     else | 
 | 326 |       ret = svc->endpoint()->MessageReply(this, handle.Get()); | 
 | 327 |  | 
 | 328 |     replied_ = ret.ok(); | 
 | 329 |     return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 330 |   } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 331 |     return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 332 |   } | 
 | 333 | } | 
 | 334 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 335 | Status<void> Message::Reply(const LocalChannelHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 336 |   auto svc = service_.lock(); | 
 | 337 |   if (!replied_ && svc) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 338 |     const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle); | 
 | 339 |     replied_ = ret.ok(); | 
 | 340 |     return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 341 |   } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 342 |     return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 343 |   } | 
 | 344 | } | 
 | 345 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 346 | Status<void> Message::Reply(const BorrowedChannelHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 347 |   auto svc = service_.lock(); | 
 | 348 |   if (!replied_ && svc) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 349 |     const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle); | 
 | 350 |     replied_ = ret.ok(); | 
 | 351 |     return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 352 |   } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 353 |     return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 354 |   } | 
 | 355 | } | 
 | 356 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 357 | Status<void> Message::Reply(const RemoteChannelHandle& handle) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 358 |   auto svc = service_.lock(); | 
 | 359 |   if (!replied_ && svc) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 360 |     const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle); | 
 | 361 |     replied_ = ret.ok(); | 
 | 362 |     return ret; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 363 |   } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 364 |     return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 365 |   } | 
 | 366 | } | 
 | 367 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 368 | Status<void> Message::ModifyChannelEvents(int clear_mask, int set_mask) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 369 |   PDX_TRACE_NAME("Message::ModifyChannelEvents"); | 
 | 370 |   if (auto svc = service_.lock()) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 371 |     return svc->endpoint()->ModifyChannelEvents(info_.cid, clear_mask, | 
 | 372 |                                                 set_mask); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 373 |   } else { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 374 |     return ErrorStatus{ESHUTDOWN}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 375 |   } | 
 | 376 | } | 
 | 377 |  | 
 | 378 | Status<RemoteChannelHandle> Message::PushChannel( | 
 | 379 |     int flags, const std::shared_ptr<Channel>& channel, int* channel_id) { | 
 | 380 |   PDX_TRACE_NAME("Message::PushChannel"); | 
 | 381 |   if (auto svc = service_.lock()) { | 
 | 382 |     return svc->PushChannel(this, flags, channel, channel_id); | 
 | 383 |   } else { | 
 | 384 |     return ErrorStatus(ESHUTDOWN); | 
 | 385 |   } | 
 | 386 | } | 
 | 387 |  | 
 | 388 | Status<RemoteChannelHandle> Message::PushChannel( | 
 | 389 |     Service* service, int flags, const std::shared_ptr<Channel>& channel, | 
 | 390 |     int* channel_id) { | 
 | 391 |   PDX_TRACE_NAME("Message::PushChannel"); | 
 | 392 |   return service->PushChannel(this, flags, channel, channel_id); | 
 | 393 | } | 
 | 394 |  | 
 | 395 | Status<int> Message::CheckChannel(ChannelReference ref, | 
 | 396 |                                   std::shared_ptr<Channel>* channel) const { | 
 | 397 |   PDX_TRACE_NAME("Message::CheckChannel"); | 
 | 398 |   if (auto svc = service_.lock()) { | 
 | 399 |     return svc->CheckChannel(this, ref, channel); | 
 | 400 |   } else { | 
 | 401 |     return ErrorStatus(ESHUTDOWN); | 
 | 402 |   } | 
 | 403 | } | 
 | 404 |  | 
 | 405 | Status<int> Message::CheckChannel(const Service* service, ChannelReference ref, | 
 | 406 |                                   std::shared_ptr<Channel>* channel) const { | 
 | 407 |   PDX_TRACE_NAME("Message::CheckChannel"); | 
 | 408 |   return service->CheckChannel(this, ref, channel); | 
 | 409 | } | 
 | 410 |  | 
 | 411 | pid_t Message::GetProcessId() const { return info_.pid; } | 
 | 412 |  | 
 | 413 | pid_t Message::GetThreadId() const { return info_.tid; } | 
 | 414 |  | 
 | 415 | uid_t Message::GetEffectiveUserId() const { return info_.euid; } | 
 | 416 |  | 
 | 417 | gid_t Message::GetEffectiveGroupId() const { return info_.egid; } | 
 | 418 |  | 
 | 419 | int Message::GetChannelId() const { return info_.cid; } | 
 | 420 |  | 
 | 421 | int Message::GetMessageId() const { return info_.mid; } | 
 | 422 |  | 
 | 423 | int Message::GetOp() const { return info_.op; } | 
 | 424 |  | 
 | 425 | int Message::GetFlags() const { return info_.flags; } | 
 | 426 |  | 
 | 427 | size_t Message::GetSendLength() const { return info_.send_len; } | 
 | 428 |  | 
 | 429 | size_t Message::GetReceiveLength() const { return info_.recv_len; } | 
 | 430 |  | 
 | 431 | size_t Message::GetFileDescriptorCount() const { return info_.fd_count; } | 
 | 432 |  | 
 | 433 | std::shared_ptr<Channel> Message::GetChannel() const { return channel_.lock(); } | 
 | 434 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 435 | Status<void> Message::SetChannel(const std::shared_ptr<Channel>& chan) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 436 |   channel_ = chan; | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 437 |   Status<void> status; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 438 |   if (auto svc = service_.lock()) | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 439 |     status = svc->SetChannel(info_.cid, chan); | 
 | 440 |   return status; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 441 | } | 
 | 442 |  | 
 | 443 | std::shared_ptr<Service> Message::GetService() const { return service_.lock(); } | 
 | 444 |  | 
 | 445 | const MessageInfo& Message::GetInfo() const { return info_; } | 
 | 446 |  | 
 | 447 | Service::Service(const std::string& name, std::unique_ptr<Endpoint> endpoint) | 
 | 448 |     : name_(name), endpoint_{std::move(endpoint)} { | 
 | 449 |   if (!endpoint_) | 
 | 450 |     return; | 
 | 451 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 452 |   const auto status = endpoint_->SetService(this); | 
 | 453 |   ALOGE_IF(!status, "Failed to set service context because: %s", | 
 | 454 |            status.GetErrorMessage().c_str()); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 455 | } | 
 | 456 |  | 
 | 457 | Service::~Service() { | 
 | 458 |   if (endpoint_) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 459 |     const auto status = endpoint_->SetService(nullptr); | 
 | 460 |     ALOGE_IF(!status, "Failed to clear service context because: %s", | 
 | 461 |              status.GetErrorMessage().c_str()); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 462 |   } | 
 | 463 | } | 
 | 464 |  | 
 | 465 | std::shared_ptr<Service> Service::GetFromMessageInfo(const MessageInfo& info) { | 
 | 466 |   return info.service ? info.service->shared_from_this() | 
 | 467 |                       : std::shared_ptr<Service>(); | 
 | 468 | } | 
 | 469 |  | 
 | 470 | bool Service::IsInitialized() const { return endpoint_.get() != nullptr; } | 
 | 471 |  | 
 | 472 | std::shared_ptr<Channel> Service::OnChannelOpen(Message& /*message*/) { | 
 | 473 |   return nullptr; | 
 | 474 | } | 
 | 475 |  | 
 | 476 | void Service::OnChannelClose(Message& /*message*/, | 
 | 477 |                              const std::shared_ptr<Channel>& /*channel*/) {} | 
 | 478 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 479 | Status<void> Service::SetChannel(int channel_id, | 
 | 480 |                                  const std::shared_ptr<Channel>& channel) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 481 |   PDX_TRACE_NAME("Service::SetChannel"); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 482 |   std::lock_guard<std::mutex> autolock(channels_mutex_); | 
 | 483 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 484 |   const auto status = endpoint_->SetChannel(channel_id, channel.get()); | 
 | 485 |   if (!status) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 486 |     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] | 487 |           status.GetErrorMessage().c_str()); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 488 |  | 
 | 489 |     // It's possible someone mucked with things behind our back by calling the C | 
 | 490 |     // API directly. Since we know the channel id isn't valid, make sure we | 
 | 491 |     // don't have it in the channels map. | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 492 |     if (status.error() == ENOENT) | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 493 |       channels_.erase(channel_id); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 494 |   } else { | 
 | 495 |     if (channel != nullptr) | 
 | 496 |       channels_[channel_id] = channel; | 
 | 497 |     else | 
 | 498 |       channels_.erase(channel_id); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 499 |   } | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 500 |   return status; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 501 | } | 
 | 502 |  | 
 | 503 | std::shared_ptr<Channel> Service::GetChannel(int channel_id) const { | 
 | 504 |   PDX_TRACE_NAME("Service::GetChannel"); | 
 | 505 |   std::lock_guard<std::mutex> autolock(channels_mutex_); | 
 | 506 |  | 
 | 507 |   auto search = channels_.find(channel_id); | 
 | 508 |   if (search != channels_.end()) | 
 | 509 |     return search->second; | 
 | 510 |   else | 
 | 511 |     return nullptr; | 
 | 512 | } | 
 | 513 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 514 | Status<void> Service::CloseChannel(int channel_id) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 515 |   PDX_TRACE_NAME("Service::CloseChannel"); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 516 |   std::lock_guard<std::mutex> autolock(channels_mutex_); | 
 | 517 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 518 |   const auto status = endpoint_->CloseChannel(channel_id); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 519 |  | 
 | 520 |   // Always erase the map entry, in case someone mucked with things behind our | 
 | 521 |   // back using the C API directly. | 
 | 522 |   channels_.erase(channel_id); | 
 | 523 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 524 |   return status; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 525 | } | 
 | 526 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 527 | Status<void> Service::ModifyChannelEvents(int channel_id, int clear_mask, | 
 | 528 |                                           int set_mask) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 529 |   PDX_TRACE_NAME("Service::ModifyChannelEvents"); | 
 | 530 |   return endpoint_->ModifyChannelEvents(channel_id, clear_mask, set_mask); | 
 | 531 | } | 
 | 532 |  | 
 | 533 | Status<RemoteChannelHandle> Service::PushChannel( | 
 | 534 |     Message* message, int flags, const std::shared_ptr<Channel>& channel, | 
 | 535 |     int* channel_id) { | 
 | 536 |   PDX_TRACE_NAME("Service::PushChannel"); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 537 |  | 
 | 538 |   std::lock_guard<std::mutex> autolock(channels_mutex_); | 
 | 539 |  | 
 | 540 |   int channel_id_temp = -1; | 
 | 541 |   Status<RemoteChannelHandle> ret = | 
 | 542 |       endpoint_->PushChannel(message, flags, channel.get(), &channel_id_temp); | 
 | 543 |   ALOGE_IF(!ret.ok(), "%s::PushChannel: Failed to push channel: %s", | 
 | 544 |            name_.c_str(), strerror(ret.error())); | 
 | 545 |  | 
 | 546 |   if (channel && channel_id_temp != -1) | 
 | 547 |     channels_[channel_id_temp] = channel; | 
 | 548 |   if (channel_id) | 
 | 549 |     *channel_id = channel_id_temp; | 
 | 550 |  | 
 | 551 |   return ret; | 
 | 552 | } | 
 | 553 |  | 
 | 554 | Status<int> Service::CheckChannel(const Message* message, ChannelReference ref, | 
 | 555 |                                   std::shared_ptr<Channel>* channel) const { | 
 | 556 |   PDX_TRACE_NAME("Service::CheckChannel"); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 557 |  | 
 | 558 |   // Synchronization to maintain consistency between the kernel's channel | 
 | 559 |   // context pointer and the userspace channels_ map. Other threads may attempt | 
 | 560 |   // to modify the map at the same time, which could cause the channel context | 
 | 561 |   // pointer returned by the kernel to be invalid. | 
 | 562 |   std::lock_guard<std::mutex> autolock(channels_mutex_); | 
 | 563 |  | 
 | 564 |   Channel* channel_context = nullptr; | 
 | 565 |   Status<int> ret = endpoint_->CheckChannel( | 
 | 566 |       message, ref, channel ? &channel_context : nullptr); | 
 | 567 |   if (ret && channel) { | 
 | 568 |     if (channel_context) | 
 | 569 |       *channel = channel_context->shared_from_this(); | 
 | 570 |     else | 
 | 571 |       *channel = nullptr; | 
 | 572 |   } | 
 | 573 |  | 
 | 574 |   return ret; | 
 | 575 | } | 
 | 576 |  | 
 | 577 | std::string Service::DumpState(size_t /*max_length*/) { return ""; } | 
 | 578 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 579 | Status<void> Service::HandleMessage(Message& message) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 580 |   return DefaultHandleMessage(message); | 
 | 581 | } | 
 | 582 |  | 
 | 583 | void Service::HandleImpulse(Message& /*impulse*/) {} | 
 | 584 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 585 | Status<void> Service::HandleSystemMessage(Message& message) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 586 |   const MessageInfo& info = message.GetInfo(); | 
 | 587 |  | 
 | 588 |   switch (info.op) { | 
 | 589 |     case opcodes::CHANNEL_OPEN: { | 
 | 590 |       ALOGD("%s::OnChannelOpen: pid=%d cid=%d\n", name_.c_str(), info.pid, | 
 | 591 |             info.cid); | 
 | 592 |       message.SetChannel(OnChannelOpen(message)); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 593 |       return message.Reply(0); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 594 |     } | 
 | 595 |  | 
 | 596 |     case opcodes::CHANNEL_CLOSE: { | 
 | 597 |       ALOGD("%s::OnChannelClose: pid=%d cid=%d\n", name_.c_str(), info.pid, | 
 | 598 |             info.cid); | 
 | 599 |       OnChannelClose(message, Channel::GetFromMessageInfo(info)); | 
 | 600 |       message.SetChannel(nullptr); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 601 |       return message.Reply(0); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 602 |     } | 
 | 603 |  | 
 | 604 |     case opcodes::REPORT_SYSPROP_CHANGE: | 
 | 605 |       ALOGD("%s:REPORT_SYSPROP_CHANGE: pid=%d cid=%d\n", name_.c_str(), | 
 | 606 |             info.pid, info.cid); | 
 | 607 |       OnSysPropChange(); | 
 | 608 |       android::report_sysprop_change(); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 609 |       return message.Reply(0); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 610 |  | 
 | 611 |     case opcodes::DUMP_STATE: { | 
 | 612 |       ALOGD("%s:DUMP_STATE: pid=%d cid=%d\n", name_.c_str(), info.pid, | 
 | 613 |             info.cid); | 
 | 614 |       auto response = DumpState(message.GetReceiveLength()); | 
 | 615 |       const size_t response_size = response.size() < message.GetReceiveLength() | 
 | 616 |                                        ? response.size() | 
 | 617 |                                        : message.GetReceiveLength(); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 618 |       const Status<size_t> status = | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 619 |           message.Write(response.data(), response_size); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 620 |       if (status && status.get() < response_size) | 
 | 621 |         return message.ReplyError(EIO); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 622 |       else | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 623 |         return message.Reply(status); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 624 |     } | 
 | 625 |  | 
 | 626 |     default: | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 627 |       return ErrorStatus{EOPNOTSUPP}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 628 |   } | 
 | 629 | } | 
 | 630 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 631 | Status<void> Service::DefaultHandleMessage(Message& message) { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 632 |   const MessageInfo& info = message.GetInfo(); | 
 | 633 |  | 
 | 634 |   ALOGD_IF(TRACE, "Service::DefaultHandleMessage: pid=%d cid=%d op=%d\n", | 
 | 635 |            info.pid, info.cid, info.op); | 
 | 636 |  | 
 | 637 |   switch (info.op) { | 
 | 638 |     case opcodes::CHANNEL_OPEN: | 
 | 639 |     case opcodes::CHANNEL_CLOSE: | 
 | 640 |     case opcodes::REPORT_SYSPROP_CHANGE: | 
 | 641 |     case opcodes::DUMP_STATE: | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 642 |       return HandleSystemMessage(message); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 643 |  | 
 | 644 |     default: | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 645 |       return message.ReplyError(EOPNOTSUPP); | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 646 |   } | 
 | 647 | } | 
 | 648 |  | 
 | 649 | void Service::OnSysPropChange() {} | 
 | 650 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 651 | Status<void> Service::ReceiveAndDispatch() { | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 652 |   Message message; | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 653 |   const auto status = endpoint_->MessageReceive(&message); | 
 | 654 |   if (!status) { | 
 | 655 |     ALOGE("Failed to receive message: %s\n", status.GetErrorMessage().c_str()); | 
 | 656 |     return status; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 657 |   } | 
 | 658 |  | 
 | 659 |   std::shared_ptr<Service> service = message.GetService(); | 
 | 660 |  | 
 | 661 |   if (!service) { | 
 | 662 |     ALOGE("Service::ReceiveAndDispatch: service context is NULL!!!\n"); | 
 | 663 |     // Don't block the sender indefinitely in this error case. | 
 | 664 |     endpoint_->MessageReply(&message, -EINVAL); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 665 |     return ErrorStatus{EINVAL}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 666 |   } | 
 | 667 |  | 
 | 668 |   if (message.IsImpulse()) { | 
 | 669 |     service->HandleImpulse(message); | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 670 |     return {}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 671 |   } else if (service->HandleSystemMessage(message)) { | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 672 |     return {}; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 673 |   } else { | 
 | 674 |     return service->HandleMessage(message); | 
 | 675 |   } | 
 | 676 | } | 
 | 677 |  | 
| Alex Vakulenko | f0a7bd0 | 2017-03-31 18:06:19 -0700 | [diff] [blame] | 678 | Status<void> Service::Cancel() { return endpoint_->Cancel(); } | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 679 |  | 
 | 680 | }  // namespace pdx | 
 | 681 | }  // namespace android |