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