• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetFromMessageInfo(const MessageInfo & info)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 
Message()23 Message::Message() : replied_(true) {}
24 
Message(const MessageInfo & info)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.
Message(Message && other)37 Message::Message(Message&& other) { *this = std::move(other); }
38 
operator =(Message && other)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 
~Message()52 Message::~Message() { Destroy(); }
53 
Destroy()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 
ImpulseBegin() const71 const std::uint8_t* Message::ImpulseBegin() const {
72   return reinterpret_cast<const std::uint8_t*>(info_.impulse);
73 }
74 
ImpulseEnd() const75 const std::uint8_t* Message::ImpulseEnd() const {
76   return ImpulseBegin() + (IsImpulse() ? GetSendLength() : 0);
77 }
78 
ReadVector(const struct iovec * vector,size_t vector_length)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 
ReadVectorAll(const struct iovec * vector,size_t vector_length)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 
Read(void * buffer,size_t length)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 
WriteVector(const struct iovec * vector,size_t vector_length)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 
WriteVectorAll(const struct iovec * vector,size_t vector_length)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 
Write(const void * buffer,size_t length)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 
PushFileHandle(const LocalHandle & handle)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 
PushFileHandle(const BorrowedHandle & handle)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 
PushFileHandle(const RemoteHandle & handle)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 
PushChannelHandle(const LocalChannelHandle & handle)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 
PushChannelHandle(const BorrowedChannelHandle & handle)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 
PushChannelHandle(const RemoteChannelHandle & handle)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 
GetFileHandle(FileReference ref,LocalHandle * handle)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 
GetChannelHandle(ChannelReference ref,LocalChannelHandle * handle)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 
Reply(int return_code)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 
ReplyFileDescriptor(unsigned int fd)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 
ReplyError(unsigned int error)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 
Reply(const LocalHandle & handle)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 
Reply(const BorrowedHandle & handle)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 
Reply(const RemoteHandle & handle)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 
Reply(const LocalChannelHandle & handle)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 
Reply(const BorrowedChannelHandle & handle)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 
Reply(const RemoteChannelHandle & handle)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 
ModifyChannelEvents(int clear_mask,int set_mask)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 
PushChannel(int flags,const std::shared_ptr<Channel> & channel,int * channel_id)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 
PushChannel(Service * service,int flags,const std::shared_ptr<Channel> & channel,int * channel_id)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 
CheckChannel(ChannelReference ref,std::shared_ptr<Channel> * channel) const398 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 
CheckChannel(const Service * service,ChannelReference ref,std::shared_ptr<Channel> * channel) const408 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 
GetProcessId() const414 pid_t Message::GetProcessId() const { return info_.pid; }
415 
GetThreadId() const416 pid_t Message::GetThreadId() const { return info_.tid; }
417 
GetEffectiveUserId() const418 uid_t Message::GetEffectiveUserId() const { return info_.euid; }
419 
GetEffectiveGroupId() const420 gid_t Message::GetEffectiveGroupId() const { return info_.egid; }
421 
GetChannelId() const422 int Message::GetChannelId() const { return info_.cid; }
423 
GetMessageId() const424 int Message::GetMessageId() const { return info_.mid; }
425 
GetOp() const426 int Message::GetOp() const { return info_.op; }
427 
GetFlags() const428 int Message::GetFlags() const { return info_.flags; }
429 
GetSendLength() const430 size_t Message::GetSendLength() const { return info_.send_len; }
431 
GetReceiveLength() const432 size_t Message::GetReceiveLength() const { return info_.recv_len; }
433 
GetFileDescriptorCount() const434 size_t Message::GetFileDescriptorCount() const { return info_.fd_count; }
435 
GetChannel() const436 std::shared_ptr<Channel> Message::GetChannel() const { return channel_.lock(); }
437 
SetChannel(const std::shared_ptr<Channel> & chan)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 
GetService() const446 std::shared_ptr<Service> Message::GetService() const { return service_.lock(); }
447 
GetInfo() const448 const MessageInfo& Message::GetInfo() const { return info_; }
449 
Service(const std::string & name,std::unique_ptr<Endpoint> endpoint)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 
~Service()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 
GetFromMessageInfo(const MessageInfo & info)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 
IsInitialized() const473 bool Service::IsInitialized() const { return endpoint_.get() != nullptr; }
474 
OnChannelOpen(Message &)475 std::shared_ptr<Channel> Service::OnChannelOpen(Message& /*message*/) {
476   return nullptr;
477 }
478 
OnChannelClose(Message &,const std::shared_ptr<Channel> &)479 void Service::OnChannelClose(Message& /*message*/,
480                              const std::shared_ptr<Channel>& /*channel*/) {}
481 
SetChannel(int channel_id,const std::shared_ptr<Channel> & channel)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 
GetChannel(int channel_id) const506 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 
CloseChannel(int channel_id)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 
ModifyChannelEvents(int channel_id,int clear_mask,int set_mask)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 
PushChannel(Message * message,int flags,const std::shared_ptr<Channel> & channel,int * channel_id)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 
CheckChannel(const Message * message,ChannelReference ref,std::shared_ptr<Channel> * channel) const557 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 
DumpState(size_t)580 std::string Service::DumpState(size_t /*max_length*/) { return ""; }
581 
HandleMessage(Message & message)582 Status<void> Service::HandleMessage(Message& message) {
583   return DefaultHandleMessage(message);
584 }
585 
HandleImpulse(Message &)586 void Service::HandleImpulse(Message& /*impulse*/) {}
587 
HandleSystemMessage(Message & message)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 
DefaultHandleMessage(Message & message)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 
OnSysPropChange()652 void Service::OnSysPropChange() {}
653 
ReceiveAndDispatch()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 
Cancel()681 Status<void> Service::Cancel() { return endpoint_->Cancel(); }
682 
683 }  // namespace pdx
684 }  // namespace android
685