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