• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetFromMessageInfo(const MessageInfo & info)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 
Message()20 Message::Message() : replied_(true) {}
21 
Message(const MessageInfo & info)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.
Message(Message && other)34 Message::Message(Message&& other) { *this = std::move(other); }
35 
operator =(Message && other)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 
~Message()49 Message::~Message() { Destroy(); }
50 
Destroy()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 
ImpulseBegin() const68 const std::uint8_t* Message::ImpulseBegin() const {
69   return reinterpret_cast<const std::uint8_t*>(info_.impulse);
70 }
71 
ImpulseEnd() const72 const std::uint8_t* Message::ImpulseEnd() const {
73   return ImpulseBegin() + (IsImpulse() ? GetSendLength() : 0);
74 }
75 
ReadVector(const struct iovec * vector,size_t vector_length)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 
ReadVectorAll(const struct iovec * vector,size_t vector_length)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 
Read(void * buffer,size_t length)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 
WriteVector(const struct iovec * vector,size_t vector_length)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 
WriteVectorAll(const struct iovec * vector,size_t vector_length)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 
Write(const void * buffer,size_t length)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 
PushFileHandle(const LocalHandle & handle)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 
PushFileHandle(const BorrowedHandle & handle)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 
PushFileHandle(const RemoteHandle & handle)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 
PushChannelHandle(const LocalChannelHandle & handle)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 
PushChannelHandle(const BorrowedChannelHandle & handle)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 
PushChannelHandle(const RemoteChannelHandle & handle)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 
GetFileHandle(FileReference ref,LocalHandle * handle)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 
GetChannelHandle(ChannelReference ref,LocalChannelHandle * handle)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 
Reply(int return_code)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 
ReplyFileDescriptor(unsigned int fd)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 
ReplyError(unsigned int error)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 
Reply(const LocalHandle & handle)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 
Reply(const BorrowedHandle & handle)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 
Reply(const RemoteHandle & handle)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 
Reply(const LocalChannelHandle & handle)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 
Reply(const BorrowedChannelHandle & handle)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 
Reply(const RemoteChannelHandle & handle)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 
ModifyChannelEvents(int clear_mask,int set_mask)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 
PushChannel(int flags,const std::shared_ptr<Channel> & channel,int * channel_id)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 
PushChannel(Service * service,int flags,const std::shared_ptr<Channel> & channel,int * channel_id)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 
CheckChannel(ChannelReference ref,std::shared_ptr<Channel> * channel) const395 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 
CheckChannel(const Service * service,ChannelReference ref,std::shared_ptr<Channel> * channel) const405 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 
GetProcessId() const411 pid_t Message::GetProcessId() const { return info_.pid; }
412 
GetThreadId() const413 pid_t Message::GetThreadId() const { return info_.tid; }
414 
GetEffectiveUserId() const415 uid_t Message::GetEffectiveUserId() const { return info_.euid; }
416 
GetEffectiveGroupId() const417 gid_t Message::GetEffectiveGroupId() const { return info_.egid; }
418 
GetChannelId() const419 int Message::GetChannelId() const { return info_.cid; }
420 
GetMessageId() const421 int Message::GetMessageId() const { return info_.mid; }
422 
GetOp() const423 int Message::GetOp() const { return info_.op; }
424 
GetFlags() const425 int Message::GetFlags() const { return info_.flags; }
426 
GetSendLength() const427 size_t Message::GetSendLength() const { return info_.send_len; }
428 
GetReceiveLength() const429 size_t Message::GetReceiveLength() const { return info_.recv_len; }
430 
GetFileDescriptorCount() const431 size_t Message::GetFileDescriptorCount() const { return info_.fd_count; }
432 
GetChannel() const433 std::shared_ptr<Channel> Message::GetChannel() const { return channel_.lock(); }
434 
SetChannel(const std::shared_ptr<Channel> & chan)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 
GetService() const443 std::shared_ptr<Service> Message::GetService() const { return service_.lock(); }
444 
GetInfo() const445 const MessageInfo& Message::GetInfo() const { return info_; }
446 
Service(const std::string & name,std::unique_ptr<Endpoint> endpoint)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 
~Service()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 
GetFromMessageInfo(const MessageInfo & info)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 
IsInitialized() const470 bool Service::IsInitialized() const { return endpoint_.get() != nullptr; }
471 
OnChannelOpen(Message &)472 std::shared_ptr<Channel> Service::OnChannelOpen(Message& /*message*/) {
473   return nullptr;
474 }
475 
OnChannelClose(Message &,const std::shared_ptr<Channel> &)476 void Service::OnChannelClose(Message& /*message*/,
477                              const std::shared_ptr<Channel>& /*channel*/) {}
478 
SetChannel(int channel_id,const std::shared_ptr<Channel> & channel)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 
GetChannel(int channel_id) const503 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 
CloseChannel(int channel_id)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 
ModifyChannelEvents(int channel_id,int clear_mask,int set_mask)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 
PushChannel(Message * message,int flags,const std::shared_ptr<Channel> & channel,int * channel_id)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 
CheckChannel(const Message * message,ChannelReference ref,std::shared_ptr<Channel> * channel) const554 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 
DumpState(size_t)577 std::string Service::DumpState(size_t /*max_length*/) { return ""; }
578 
HandleMessage(Message & message)579 Status<void> Service::HandleMessage(Message& message) {
580   return DefaultHandleMessage(message);
581 }
582 
HandleImpulse(Message &)583 void Service::HandleImpulse(Message& /*impulse*/) {}
584 
HandleSystemMessage(Message & message)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 
DefaultHandleMessage(Message & message)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 
OnSysPropChange()649 void Service::OnSysPropChange() {}
650 
ReceiveAndDispatch()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 
Cancel()678 Status<void> Service::Cancel() { return endpoint_->Cancel(); }
679 
680 }  // namespace pdx
681 }  // namespace android
682