service.cpp revision 4fe60582f314e381098f8f3bc2e39c5880e9243a
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#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 681