Home | History | Annotate | Download | only in libpdx
      1 #include "pdx/service.h"
      2 
      3 #include <fcntl.h>
      4 #include <log/log.h>
      5 #include <utils/misc.h>
      6 
      7 #include <algorithm>
      8 #include <cstdint>
      9 
     10 #include <pdx/trace.h>
     11 
     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.
     34 Message::Message(Message&& other) { *this = std::move(other); }
     35 
     36 Message& Message::operator=(Message&& other) {
     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);
     59       svc->DefaultHandleMessage(*this);
     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 
     76 Status<size_t> Message::ReadVector(const struct iovec* vector,
     77                                    size_t vector_length) {
     78   PDX_TRACE_NAME("Message::ReadVector");
     79   if (auto svc = service_.lock()) {
     80     return svc->endpoint()->ReadMessageData(this, vector, vector_length);
     81   } else {
     82     return ErrorStatus{ESHUTDOWN};
     83   }
     84 }
     85 
     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) {
    106   PDX_TRACE_NAME("Message::Read");
    107   if (auto svc = service_.lock()) {
    108     const struct iovec vector = {buffer, length};
    109     return svc->endpoint()->ReadMessageData(this, &vector, 1);
    110   } else {
    111     return ErrorStatus{ESHUTDOWN};
    112   }
    113 }
    114 
    115 Status<size_t> Message::WriteVector(const struct iovec* vector,
    116                                     size_t vector_length) {
    117   PDX_TRACE_NAME("Message::WriteVector");
    118   if (auto svc = service_.lock()) {
    119     return svc->endpoint()->WriteMessageData(this, vector, vector_length);
    120   } else {
    121     return ErrorStatus{ESHUTDOWN};
    122   }
    123 }
    124 
    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) {
    145   PDX_TRACE_NAME("Message::Write");
    146   if (auto svc = service_.lock()) {
    147     const struct iovec vector = {const_cast<void*>(buffer), length};
    148     return svc->endpoint()->WriteMessageData(this, &vector, 1);
    149   } else {
    150     return ErrorStatus{ESHUTDOWN};
    151   }
    152 }
    153 
    154 Status<FileReference> Message::PushFileHandle(const LocalHandle& handle) {
    155   PDX_TRACE_NAME("Message::PushFileHandle");
    156   if (auto svc = service_.lock()) {
    157     return svc->endpoint()->PushFileHandle(this, handle);
    158   } else {
    159     return ErrorStatus{ESHUTDOWN};
    160   }
    161 }
    162 
    163 Status<FileReference> Message::PushFileHandle(const BorrowedHandle& handle) {
    164   PDX_TRACE_NAME("Message::PushFileHandle");
    165   if (auto svc = service_.lock()) {
    166     return svc->endpoint()->PushFileHandle(this, handle);
    167   } else {
    168     return ErrorStatus{ESHUTDOWN};
    169   }
    170 }
    171 
    172 Status<FileReference> Message::PushFileHandle(const RemoteHandle& handle) {
    173   PDX_TRACE_NAME("Message::PushFileHandle");
    174   if (auto svc = service_.lock()) {
    175     return svc->endpoint()->PushFileHandle(this, handle);
    176   } else {
    177     return ErrorStatus{ESHUTDOWN};
    178   }
    179 }
    180 
    181 Status<ChannelReference> Message::PushChannelHandle(
    182     const LocalChannelHandle& handle) {
    183   PDX_TRACE_NAME("Message::PushChannelHandle");
    184   if (auto svc = service_.lock()) {
    185     return svc->endpoint()->PushChannelHandle(this, handle);
    186   } else {
    187     return ErrorStatus{ESHUTDOWN};
    188   }
    189 }
    190 
    191 Status<ChannelReference> Message::PushChannelHandle(
    192     const BorrowedChannelHandle& handle) {
    193   PDX_TRACE_NAME("Message::PushChannelHandle");
    194   if (auto svc = service_.lock()) {
    195     return svc->endpoint()->PushChannelHandle(this, handle);
    196   } else {
    197     return ErrorStatus{ESHUTDOWN};
    198   }
    199 }
    200 
    201 Status<ChannelReference> Message::PushChannelHandle(
    202     const RemoteChannelHandle& handle) {
    203   PDX_TRACE_NAME("Message::PushChannelHandle");
    204   if (auto svc = service_.lock()) {
    205     return svc->endpoint()->PushChannelHandle(this, handle);
    206   } else {
    207     return ErrorStatus{ESHUTDOWN};
    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) {
    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) {
    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 
    244 Status<void> Message::Reply(int return_code) {
    245   PDX_TRACE_NAME("Message::Reply");
    246   auto svc = service_.lock();
    247   if (!replied_ && svc) {
    248     const auto ret = svc->endpoint()->MessageReply(this, return_code);
    249     replied_ = ret.ok();
    250     return ret;
    251   } else {
    252     return ErrorStatus{EINVAL};
    253   }
    254 }
    255 
    256 Status<void> Message::ReplyFileDescriptor(unsigned int fd) {
    257   PDX_TRACE_NAME("Message::ReplyFileDescriptor");
    258   auto svc = service_.lock();
    259   if (!replied_ && svc) {
    260     const auto ret = svc->endpoint()->MessageReplyFd(this, fd);
    261     replied_ = ret.ok();
    262     return ret;
    263   } else {
    264     return ErrorStatus{EINVAL};
    265   }
    266 }
    267 
    268 Status<void> Message::ReplyError(unsigned int error) {
    269   PDX_TRACE_NAME("Message::ReplyError");
    270   auto svc = service_.lock();
    271   if (!replied_ && svc) {
    272     const auto ret =
    273         svc->endpoint()->MessageReply(this, -static_cast<int>(error));
    274     replied_ = ret.ok();
    275     return ret;
    276   } else {
    277     return ErrorStatus{EINVAL};
    278   }
    279 }
    280 
    281 Status<void> Message::Reply(const LocalHandle& handle) {
    282   PDX_TRACE_NAME("Message::ReplyFileHandle");
    283   auto svc = service_.lock();
    284   if (!replied_ && svc) {
    285     Status<void> ret;
    286 
    287     if (handle)
    288       ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
    289     else
    290       ret = svc->endpoint()->MessageReply(this, handle.Get());
    291 
    292     replied_ = ret.ok();
    293     return ret;
    294   } else {
    295     return ErrorStatus{EINVAL};
    296   }
    297 }
    298 
    299 Status<void> Message::Reply(const BorrowedHandle& handle) {
    300   PDX_TRACE_NAME("Message::ReplyFileHandle");
    301   auto svc = service_.lock();
    302   if (!replied_ && svc) {
    303     Status<void> ret;
    304 
    305     if (handle)
    306       ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
    307     else
    308       ret = svc->endpoint()->MessageReply(this, handle.Get());
    309 
    310     replied_ = ret.ok();
    311     return ret;
    312   } else {
    313     return ErrorStatus{EINVAL};
    314   }
    315 }
    316 
    317 Status<void> Message::Reply(const RemoteHandle& handle) {
    318   PDX_TRACE_NAME("Message::ReplyFileHandle");
    319   auto svc = service_.lock();
    320   if (!replied_ && svc) {
    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;
    330   } else {
    331     return ErrorStatus{EINVAL};
    332   }
    333 }
    334 
    335 Status<void> Message::Reply(const LocalChannelHandle& handle) {
    336   auto svc = service_.lock();
    337   if (!replied_ && svc) {
    338     const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
    339     replied_ = ret.ok();
    340     return ret;
    341   } else {
    342     return ErrorStatus{EINVAL};
    343   }
    344 }
    345 
    346 Status<void> Message::Reply(const BorrowedChannelHandle& handle) {
    347   auto svc = service_.lock();
    348   if (!replied_ && svc) {
    349     const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
    350     replied_ = ret.ok();
    351     return ret;
    352   } else {
    353     return ErrorStatus{EINVAL};
    354   }
    355 }
    356 
    357 Status<void> Message::Reply(const RemoteChannelHandle& handle) {
    358   auto svc = service_.lock();
    359   if (!replied_ && svc) {
    360     const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
    361     replied_ = ret.ok();
    362     return ret;
    363   } else {
    364     return ErrorStatus{EINVAL};
    365   }
    366 }
    367 
    368 Status<void> Message::ModifyChannelEvents(int clear_mask, int set_mask) {
    369   PDX_TRACE_NAME("Message::ModifyChannelEvents");
    370   if (auto svc = service_.lock()) {
    371     return svc->endpoint()->ModifyChannelEvents(info_.cid, clear_mask,
    372                                                 set_mask);
    373   } else {
    374     return ErrorStatus{ESHUTDOWN};
    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 
    435 Status<void> Message::SetChannel(const std::shared_ptr<Channel>& chan) {
    436   channel_ = chan;
    437   Status<void> status;
    438   if (auto svc = service_.lock())
    439     status = svc->SetChannel(info_.cid, chan);
    440   return status;
    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 
    452   const auto status = endpoint_->SetService(this);
    453   ALOGE_IF(!status, "Failed to set service context because: %s",
    454            status.GetErrorMessage().c_str());
    455 }
    456 
    457 Service::~Service() {
    458   if (endpoint_) {
    459     const auto status = endpoint_->SetService(nullptr);
    460     ALOGE_IF(!status, "Failed to clear service context because: %s",
    461              status.GetErrorMessage().c_str());
    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 
    479 Status<void> Service::SetChannel(int channel_id,
    480                                  const std::shared_ptr<Channel>& channel) {
    481   PDX_TRACE_NAME("Service::SetChannel");
    482   std::lock_guard<std::mutex> autolock(channels_mutex_);
    483 
    484   const auto status = endpoint_->SetChannel(channel_id, channel.get());
    485   if (!status) {
    486     ALOGE("%s::SetChannel: Failed to set channel context: %s\n", name_.c_str(),
    487           status.GetErrorMessage().c_str());
    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.
    492     if (status.error() == ENOENT)
    493       channels_.erase(channel_id);
    494   } else {
    495     if (channel != nullptr)
    496       channels_[channel_id] = channel;
    497     else
    498       channels_.erase(channel_id);
    499   }
    500   return status;
    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 
    514 Status<void> Service::CloseChannel(int channel_id) {
    515   PDX_TRACE_NAME("Service::CloseChannel");
    516   std::lock_guard<std::mutex> autolock(channels_mutex_);
    517 
    518   const auto status = endpoint_->CloseChannel(channel_id);
    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 
    524   return status;
    525 }
    526 
    527 Status<void> Service::ModifyChannelEvents(int channel_id, int clear_mask,
    528                                           int set_mask) {
    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");
    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");
    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 
    579 Status<void> Service::HandleMessage(Message& message) {
    580   return DefaultHandleMessage(message);
    581 }
    582 
    583 void Service::HandleImpulse(Message& /*impulse*/) {}
    584 
    585 Status<void> Service::HandleSystemMessage(Message& message) {
    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));
    593       return message.Reply(0);
    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);
    601       return message.Reply(0);
    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();
    609       return message.Reply(0);
    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();
    618       const Status<size_t> status =
    619           message.Write(response.data(), response_size);
    620       if (status && status.get() < response_size)
    621         return message.ReplyError(EIO);
    622       else
    623         return message.Reply(status);
    624     }
    625 
    626     default:
    627       return ErrorStatus{EOPNOTSUPP};
    628   }
    629 }
    630 
    631 Status<void> Service::DefaultHandleMessage(Message& message) {
    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:
    642       return HandleSystemMessage(message);
    643 
    644     default:
    645       return message.ReplyError(EOPNOTSUPP);
    646   }
    647 }
    648 
    649 void Service::OnSysPropChange() {}
    650 
    651 Status<void> Service::ReceiveAndDispatch() {
    652   Message message;
    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;
    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);
    665     return ErrorStatus{EINVAL};
    666   }
    667 
    668   if (message.IsImpulse()) {
    669     service->HandleImpulse(message);
    670     return {};
    671   } else if (service->HandleSystemMessage(message)) {
    672     return {};
    673   } else {
    674     return service->HandleMessage(message);
    675   }
    676 }
    677 
    678 Status<void> Service::Cancel() { return endpoint_->Cancel(); }
    679 
    680 }  // namespace pdx
    681 }  // namespace android
    682