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