1 #ifndef ANDROID_PDX_SERVICE_H_ 2 #define ANDROID_PDX_SERVICE_H_ 3 4 #include <errno.h> 5 #include <log/log.h> 6 #include <sys/stat.h> 7 #include <sys/types.h> 8 #include <unistd.h> 9 10 #include <algorithm> 11 #include <memory> 12 #include <mutex> 13 #include <string> 14 #include <unordered_map> 15 #include <vector> 16 17 #include "pdx/channel_handle.h" 18 #include "pdx/file_handle.h" 19 #include "pdx/message_reader.h" 20 #include "pdx/message_writer.h" 21 #include "pdx/service_endpoint.h" 22 23 namespace android { 24 namespace pdx { 25 26 class Service; 27 28 namespace opcodes { 29 30 /* 31 * Reserved message opcodes used by libpdx. The reserved opcodes start at the 32 * max positive signed integer for the system and go down. 33 * In contrast, service opcodes start at zero and go up. This scheme leaves 34 * most of the positive integer space for services, a tiny fraction of the 35 * positive integer space for the framework, and the entire negative integer 36 * space for the kernel. 37 */ 38 #define PDX_OPCODE(name, n) name = ((-1U >> 1) - (n)) // 0x7fff..ffff - n 39 40 enum { 41 // System message sent when a new client channel is open. 42 CHANNEL_OPEN = -1, 43 // System message sent when a channel is closed. 44 CHANNEL_CLOSE = -2, 45 // Request the service to reload system properties. 46 PDX_OPCODE(REPORT_SYSPROP_CHANGE, 0), 47 // Request the service to dump state and return it in a text buffer. 48 PDX_OPCODE(DUMP_STATE, 1), 49 }; 50 51 } // namespace opcodes 52 53 /* 54 * Base class of service-side per-channel context classes. 55 */ 56 class Channel : public std::enable_shared_from_this<Channel> { 57 public: 58 Channel() {} 59 virtual ~Channel() {} 60 61 /* 62 * Utility to get a shared_ptr reference from the channel context pointer. 63 */ 64 static std::shared_ptr<Channel> GetFromMessageInfo(const MessageInfo& info); 65 }; 66 67 /* 68 * Message class represents an RPC message, and implicitly the blocked sender 69 * waiting for a response. Every message should get a reply, at some point 70 * (unless the endpoint is closed), to prevent clients from blocking 71 * indefinitely. In order to enforce this and prevent leaking message ids, 72 * Message automatically replies with an error to the client on destruction, 73 * unless one of two things happens: 74 * 75 * 1. The service calls one of the reply methods before the Message is 76 * destroyed. 77 * 2. The responsibility for the message is moved to another instance of 78 * Message, using either move construction or move assignment. 79 * 80 * The second case is useful for services that need to delay responding to a 81 * sender until a later time. In this situation the service can move the 82 * Message to another instance in a suitable data structure for later use. The 83 * moved-to Message then takes on the same behavior and responsibilities 84 * described above. 85 */ 86 class Message : public OutputResourceMapper, public InputResourceMapper { 87 public: 88 Message(); 89 Message(const MessageInfo& info); 90 ~Message(); 91 92 /* 93 * Message objects support move construction and assignment. 94 */ 95 Message(Message&& other); 96 Message& operator=(Message&& other); 97 98 /* 99 * Read/write payload, in either single buffer or iovec form. 100 */ 101 Status<size_t> ReadVector(const iovec* vector, size_t vector_length); 102 Status<size_t> Read(void* buffer, size_t length); 103 Status<size_t> WriteVector(const iovec* vector, size_t vector_length); 104 Status<size_t> Write(const void* buffer, size_t length); 105 106 template <size_t N> 107 inline Status<size_t> ReadVector(const iovec (&vector)[N]) { 108 return ReadVector(vector, N); 109 } 110 111 template <size_t N> 112 inline Status<size_t> WriteVector(const iovec (&vector)[N]) { 113 return WriteVector(vector, N); 114 } 115 116 // Helper functions to read/write all requested bytes, and return EIO if not 117 // all were read/written. 118 Status<void> ReadVectorAll(const iovec* vector, size_t vector_length); 119 Status<void> WriteVectorAll(const iovec* vector, size_t vector_length); 120 121 inline Status<void> ReadAll(void* buffer, size_t length) { 122 Status<size_t> status = Read(buffer, length); 123 if (status && status.get() < length) 124 status.SetError(EIO); 125 Status<void> ret; 126 ret.PropagateError(status); 127 return ret; 128 } 129 inline Status<void> WriteAll(const void* buffer, size_t length) { 130 Status<size_t> status = Write(buffer, length); 131 if (status && status.get() < length) 132 status.SetError(EIO); 133 Status<void> ret; 134 ret.PropagateError(status); 135 return ret; 136 } 137 138 template <size_t N> 139 inline Status<void> ReadVectorAll(const iovec (&vector)[N]) { 140 return ReadVectorAll(vector, N); 141 } 142 143 template <size_t N> 144 inline Status<void> WriteVectorAll(const iovec (&vector)[N]) { 145 return WriteVectorAll(vector, N); 146 } 147 148 // OutputResourceMapper 149 Status<FileReference> PushFileHandle(const LocalHandle& handle) override; 150 Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override; 151 Status<FileReference> PushFileHandle(const RemoteHandle& handle) override; 152 Status<ChannelReference> PushChannelHandle( 153 const LocalChannelHandle& handle) override; 154 Status<ChannelReference> PushChannelHandle( 155 const BorrowedChannelHandle& handle) override; 156 Status<ChannelReference> PushChannelHandle( 157 const RemoteChannelHandle& handle) override; 158 159 // InputResourceMapper 160 bool GetFileHandle(FileReference ref, LocalHandle* handle) override; 161 bool GetChannelHandle(ChannelReference ref, 162 LocalChannelHandle* handle) override; 163 164 /* 165 * Various ways to reply to a message. 166 */ 167 Status<void> Reply(int return_code); 168 Status<void> ReplyError(unsigned int error); 169 Status<void> ReplyFileDescriptor(unsigned int fd); 170 Status<void> Reply(const LocalHandle& handle); 171 Status<void> Reply(const BorrowedHandle& handle); 172 Status<void> Reply(const RemoteHandle& handle); 173 Status<void> Reply(const LocalChannelHandle& handle); 174 Status<void> Reply(const BorrowedChannelHandle& handle); 175 Status<void> Reply(const RemoteChannelHandle& handle); 176 177 template <typename T> 178 inline Status<void> Reply(const Status<T>& status) { 179 return status ? Reply(status.get()) : ReplyError(status.error()); 180 } 181 182 inline Status<void> Reply(const Status<void>& status) { 183 return status ? Reply(0) : ReplyError(status.error()); 184 } 185 186 /* 187 * Update the channel event bits with the given clear and set masks. 188 */ 189 Status<void> ModifyChannelEvents(int clear_mask, int set_mask); 190 191 /* 192 * Create a new channel and push it as a file descriptor to the client. See 193 * Service::PushChannel() for a detail description of this method's operation. 194 */ 195 Status<RemoteChannelHandle> PushChannel( 196 int flags, const std::shared_ptr<Channel>& channel, int* channel_id); 197 198 /* 199 * Create a new channel and push it as a file descriptor to the client. See 200 * Service::PushChannel() for a detail description of this method's operation. 201 */ 202 Status<RemoteChannelHandle> PushChannel( 203 Service* service, int flags, const std::shared_ptr<Channel>& channel, 204 int* channel_id); 205 206 /* 207 * Check whether the |ref| is a reference to channel to this service. 208 * If the channel reference in question is valid, the Channel object is 209 * returned in |channel| when non-nullptr. 210 * 211 * Return values: 212 * channel_id - id of the channel if the |ref| is a valid reference to 213 * this service's channel. 214 * Errors: 215 * EOPNOTSUPP - the file descriptor is not a channel or is a channel to 216 * another service. 217 * EBADF - the file descriptor is invalid. 218 * FAULT - |channel_id| or |channel| are non-nullptr and point to invalid 219 * memory addresses. 220 * EINVAL - the value of |ref| is invalid or the message id for this 221 * message is no longer valid. 222 */ 223 Status<int> CheckChannel(ChannelReference ref, 224 std::shared_ptr<Channel>* channel) const; 225 226 /* 227 * Overload of CheckChannel() that checks whether the channel reference is for 228 * a channel to the service |service|. 229 */ 230 Status<int> CheckChannel(const Service* service, ChannelReference ref, 231 std::shared_ptr<Channel>* channel) const; 232 233 /* 234 * Overload of CheckChannel() that automatically converts to shared pointers 235 * to types derived from Channel. 236 */ 237 template <class C> 238 Status<int> CheckChannel(ChannelReference ref, 239 std::shared_ptr<C>* channel) const { 240 std::shared_ptr<Channel> base_pointer; 241 const Status<int> ret = 242 CheckChannel(ref, channel ? &base_pointer : nullptr); 243 if (channel) 244 *channel = std::static_pointer_cast<C>(base_pointer); 245 return ret; 246 } 247 248 template <class C> 249 Status<int> CheckChannel(const Service* service, ChannelReference ref, 250 std::shared_ptr<C>* channel) const { 251 std::shared_ptr<Channel> base_pointer; 252 const Status<int> ret = 253 CheckChannel(service, ref, channel ? &base_pointer : nullptr); 254 if (channel) 255 *channel = std::static_pointer_cast<C>(base_pointer); 256 return ret; 257 } 258 259 /* 260 * MessageInfo accessors. 261 */ 262 pid_t GetProcessId() const; 263 pid_t GetThreadId() const; 264 uid_t GetEffectiveUserId() const; 265 gid_t GetEffectiveGroupId() const; 266 int GetChannelId() const; 267 int GetMessageId() const; 268 int GetOp() const; 269 int GetFlags() const; 270 size_t GetSendLength() const; 271 size_t GetReceiveLength() const; 272 size_t GetFileDescriptorCount() const; 273 274 /* 275 * Impulses are asynchronous and cannot be replied to. All impulses have this 276 * invalid message id. 277 */ 278 enum { IMPULSE_MESSAGE_ID = -1 }; 279 280 /* 281 * Returns true if this Message describes an asynchronous "impulse" message. 282 */ 283 bool IsImpulse() const { return GetMessageId() == IMPULSE_MESSAGE_ID; } 284 285 /* 286 * Returns a pointer to the impulse payload. Impulses are a maximum of 32 287 * bytes in size and the start of the impulse payload is guaranteed to be 288 * 8-byte aligned. Use GetSendLength() to determine the payload size. 289 */ 290 const std::uint8_t* ImpulseBegin() const; 291 292 /* 293 * Returns one byte past the end of the impulse payload, as conventional for 294 * STL iterators. 295 */ 296 const std::uint8_t* ImpulseEnd() const; 297 298 /* 299 * Get/set the Channel object for the channel associated 300 * with this message. It is up to the caller to synchronize 301 * these in multi-threaded services. 302 */ 303 std::shared_ptr<Channel> GetChannel() const; 304 Status<void> SetChannel(const std::shared_ptr<Channel>& channnel); 305 306 /* 307 * Get the Channel object for the channel associated with this message, 308 * automatically converted to the desired subclass of Channel. 309 */ 310 template <class C> 311 std::shared_ptr<C> GetChannel() const { 312 return std::static_pointer_cast<C>(GetChannel()); 313 } 314 315 /* 316 * Gets the service this message was received on. Returns nullptr if the 317 * service was destroyed. 318 */ 319 std::shared_ptr<Service> GetService() const; 320 321 /* 322 * Raw access to the MessageInfo for this message. 323 */ 324 const MessageInfo& GetInfo() const; 325 326 bool replied() const { return replied_; } 327 bool IsChannelExpired() const { return channel_.expired(); } 328 bool IsServiceExpired() const { return service_.expired(); } 329 330 /* 331 * Returns true if the message is non-empty; that is the message can be 332 * replied to using this instance. 333 */ 334 explicit operator bool() const { return !replied_; } 335 336 const void* GetState() const { return state_; } 337 void* GetState() { return state_; } 338 339 private: 340 friend class Service; 341 342 Message(const Message&) = delete; 343 void operator=(const Message&) = delete; 344 void Destroy(); 345 346 std::weak_ptr<Service> service_; 347 std::weak_ptr<Channel> channel_; 348 MessageInfo info_; 349 void* state_{nullptr}; 350 bool replied_; 351 }; 352 353 // Base class for RPC services. 354 class Service : public std::enable_shared_from_this<Service> { 355 public: 356 Service(const std::string& name, std::unique_ptr<Endpoint> endpoint); 357 virtual ~Service(); 358 359 /* 360 * Utility to get a shared_ptr reference from the service context pointer. 361 */ 362 static std::shared_ptr<Service> GetFromMessageInfo(const MessageInfo& info); 363 364 /* 365 * Returns whether initialization was successful. Subclasses that override 366 * this must call this base method and AND the results with their own. This 367 * method is not intended to do any initialization work itself, only to 368 * signal success or failure. 369 */ 370 virtual bool IsInitialized() const; 371 372 /* 373 * Called by defaultHandleMessage in response to a CHANNEL_OPEN message. 374 * This gives subclasses of Service a convenient hook to create per-channel 375 * context in the form of a Channel subclass. 376 * 377 * The Channel instance returned by this is used to set the channel context 378 * pointer for the channel that was just opened. 379 */ 380 virtual std::shared_ptr<Channel> OnChannelOpen(Message& message); 381 382 /* 383 * Called by defaultHandleMessage in response to a CHANNEL_CLOSE message. 384 * This give subclasses of Service a convenient hook to clean up per-channel 385 * context. 386 */ 387 virtual void OnChannelClose(Message& message, 388 const std::shared_ptr<Channel>& channel); 389 390 /* 391 * Set the channel context for the given channel. This keeps a reference to 392 * the Channel object until the channel is closed or another call replaces 393 * the current value. 394 */ 395 Status<void> SetChannel(int channel_id, 396 const std::shared_ptr<Channel>& channel); 397 398 /* 399 * Get the channel context for the given channel id. This method should be 400 * used sparingly because of the performance characteristics of the underlying 401 * map; it is intended for limited, non-critical path access from outside of 402 * message dispatch. In most cases lookup by id should be unnecessary in a 403 * properly designed service; Message::GetChannel() should be used instead 404 * whenever an operation is in the context of a message. 405 * 406 * Again, if you lookup a channel context object for a service by id in a 407 * message handling path for the same service, you're probably doing something 408 * wrong. 409 */ 410 std::shared_ptr<Channel> GetChannel(int channel_id) const; 411 412 /* 413 * Get a snapshot of the active channels for this service. This is the 414 * preferred way to access the set of channels because it avoids potential 415 * deadlocks and race conditions that may occur when operating on the channel 416 * map directly. However, it is more expensive than direct iteration because 417 * of dynamic memory allocation and shared pointer reference costs. 418 * 419 * Automatically converts returned items to shared pointers of the type 420 * std::shared_ptr<C>, where C is the subclass of Channel used by the service. 421 */ 422 template <class C> 423 std::vector<std::shared_ptr<C>> GetChannels() const { 424 std::lock_guard<std::mutex> autolock(channels_mutex_); 425 std::vector<std::shared_ptr<C>> items; 426 items.reserve(channels_.size()); 427 428 for (const auto& pair : channels_) { 429 items.push_back(std::static_pointer_cast<C>(pair.second)); 430 } 431 432 return items; 433 } 434 435 /* 436 * Close a channel, signaling the client file object and freeing the channel 437 * id. Once closed, the client side of the channel always returns the error 438 * ESHUTDOWN and signals the poll/epoll events POLLHUP and POLLFREE. 439 * 440 * The internal reference to the Channel instance associated with the channel 441 * is removed, which may result in the Channel object being freed. 442 * 443 * OnChannelClosed is not called in response to this method call. 444 */ 445 Status<void> CloseChannel(int channel_id); 446 447 /* 448 * Update the event bits for the given channel (given by id), using the 449 * given clear and set masks. 450 * 451 * This is useful for asynchronously signaling events that clients may be 452 * waiting for using select/poll/epoll. 453 */ 454 Status<void> ModifyChannelEvents(int channel_id, int clear_mask, 455 int set_mask); 456 457 /* 458 * Create a new channel and push it as a file descriptor to the process 459 * sending the |message|. |flags| may be set to O_NONBLOCK and/or 460 * O_CLOEXEC to control the initial behavior of the new file descriptor (the 461 * sending process may change these later using fcntl()). The internal Channel 462 * instance associated with this channel is set to |channel|, which may be 463 * nullptr. The new channel id allocated for this channel is returned in 464 * |channel_id|, which may also be nullptr if not needed. 465 * 466 * On success, returns the remote channel handle for the new channel in the 467 * sending process' handle space. This MUST be returned to the sender via 468 * Message::Reply(), Message::Write(), or Message::WriteVector(). 469 * 470 * On error, returns an errno code describing the cause of the error. 471 * 472 * Service::OnChannelCreate() is not called in response to the creation of the 473 * new channel. 474 */ 475 Status<RemoteChannelHandle> PushChannel( 476 Message* message, int flags, const std::shared_ptr<Channel>& channel, 477 int* channel_id); 478 479 /* 480 * Check whether the |ref| is a reference to a channel to this service. 481 * If the channel reference in question is valid, the Channel object is 482 * returned in |channel| when non-nullptr. 483 * 484 * Return values: 485 * channel_id - id of the channel if the channel reference. 486 * Errors: 487 * EOPNOTSUPP - the file descriptor is not a channel or is a channel to 488 * another service. 489 * EBADF - the file descriptor is invalid. 490 * FAULT - |channel_id| or |channel| are non-nullptr and point to invalid 491 * memory addresses. 492 * EINVAL - the value of |ref| is invalid or the message id for this 493 * message is no longer valid. 494 */ 495 Status<int> CheckChannel(const Message* message, ChannelReference ref, 496 std::shared_ptr<Channel>* channel) const; 497 498 /* 499 * Overload of CheckChannel() that automatically converts to shared pointers 500 * of types derived from Channel. 501 */ 502 template <class C> 503 Status<int> CheckChannel(const Message* message, ChannelReference ref, 504 std::shared_ptr<C>* channel) const { 505 std::shared_ptr<Channel> base_pointer; 506 const Status<int> ret = 507 CheckChannel(message, ref, channel ? &base_pointer : nullptr); 508 if (channel) 509 *channel = std::static_pointer_cast<C>(base_pointer); 510 return ret; 511 } 512 513 /* 514 * Handle a message. Subclasses override this to receive messages and decide 515 * how to dispatch them. 516 * 517 * The default implementation simply calls defaultHandleMessage(). 518 * Subclasses should call the same for any unrecognized message opcodes. 519 */ 520 virtual Status<void> HandleMessage(Message& message); 521 522 /* 523 * Handle an asynchronous message. Subclasses override this to receive 524 * asynchronous "impulse" messages. Impulses have a limited-size payload that 525 * is transferred upfront with the message description. 526 */ 527 virtual void HandleImpulse(Message& impulse); 528 529 /* 530 * The default message handler. It is important that all messages 531 * (eventually) get a reply. This method should be called by subclasses for 532 * any unrecognized opcodes or otherwise unhandled messages to prevent 533 * erroneous requests from blocking indefinitely. 534 * 535 * Provides default handling of CHANNEL_OPEN and CHANNEL_CLOSE, calling 536 * OnChannelOpen() and OnChannelClose(), respectively. 537 * 538 * For all other message opcodes, this method replies with ENOTSUP. 539 */ 540 Status<void> DefaultHandleMessage(Message& message); 541 542 /* 543 * Called when system properties have changed. Subclasses should implement 544 * this method if they need to handle when system properties change. 545 */ 546 virtual void OnSysPropChange(); 547 548 /* 549 * Get the endpoint for the service. 550 */ 551 Endpoint* endpoint() const { return endpoint_.get(); } 552 553 /* 554 * Cancels the endpoint, unblocking any receiver threads waiting in 555 * ReceiveAndDispatch(). 556 */ 557 Status<void> Cancel(); 558 559 /* 560 * Iterator type for Channel map iterators. 561 */ 562 using ChannelIterator = 563 std::unordered_map<int, std::shared_ptr<Channel>>::iterator; 564 565 /* 566 * Iterates over the Channel map and performs the action given by |action| on 567 * each channel map item (const ChannelIterator::value_type). 568 * |channels_mutex_| is not held; it is the responsibility of the caller to 569 * ensure serialization between threads that modify or iterate over the 570 * Channel map. 571 */ 572 template <class A> 573 void ForEachChannelUnlocked(A action) const { 574 std::for_each(channels_.begin(), channels_.end(), action); 575 } 576 577 /* 578 * Iterates over the Channel map and performs the action given by |action| on 579 * each channel map item (const ChannelIterator::value_type). 580 * |channels_mutex_| is held to serialize access to the map; care must be 581 * taken to avoid recursively acquiring the mutex, for example, by calling 582 * Service::{GetChannel,SetChannel,CloseChannel,PushChannel}() or 583 * Message::SetChannel() in the action. 584 */ 585 template <class A> 586 void ForEachChannel(A action) const { 587 std::lock_guard<std::mutex> autolock(channels_mutex_); 588 ForEachChannelUnlocked(action); 589 } 590 591 /* 592 * Subclasses of Service may override this method to provide a text string 593 * describing the state of the service. This method is called by 594 * HandleSystemMessage in response to the standard 595 * DUMP_STATE message. The string returned to the dump state client is 596 * truncated to |max_length| and reflects the maximum size the client can 597 * handle. 598 */ 599 virtual std::string DumpState(size_t max_length); 600 601 /* 602 * Receives a message on this Service instance's endpoint and dispatches it. 603 * If the endpoint is in blocking mode this call blocks until a message is 604 * received, a signal is delivered to this thread, or the service is canceled. 605 * If the endpoint is in non-blocking mode and a message is not pending this 606 * call returns immediately with ETIMEDOUT. 607 */ 608 Status<void> ReceiveAndDispatch(); 609 610 private: 611 friend class Message; 612 613 Status<void> HandleSystemMessage(Message& message); 614 615 Service(const Service&); 616 void operator=(const Service&) = delete; 617 618 const std::string name_; 619 std::unique_ptr<Endpoint> endpoint_; 620 621 /* 622 * Maintains references to active channels. 623 */ 624 mutable std::mutex channels_mutex_; 625 std::unordered_map<int, std::shared_ptr<Channel>> channels_; 626 }; 627 628 /* 629 * Utility base class for services. This template handles allocation and 630 * initialization checks, reducing boiler plate code. 631 */ 632 template <typename TYPE> 633 class ServiceBase : public Service { 634 public: 635 /* 636 * Static service allocation method that check for initialization errors. 637 * If errors are encountered these automatically clean up and return 638 * nullptr. 639 */ 640 template <typename... Args> 641 static inline std::shared_ptr<TYPE> Create(Args&&... args) { 642 std::shared_ptr<TYPE> service(new TYPE(std::forward<Args>(args)...)); 643 if (service->IsInitialized()) 644 return service; 645 else 646 return nullptr; 647 } 648 649 protected: 650 /* 651 * Shorthand for subclasses to refer to this base, particularly 652 * to call the base class constructor. 653 */ 654 typedef ServiceBase<TYPE> BASE; 655 656 ServiceBase(const std::string& name, std::unique_ptr<Endpoint> endpoint) 657 : Service(name, std::move(endpoint)) {} 658 }; 659 660 #ifndef STRINGIFY 661 #define STRINGIFY2(s) #s 662 #define STRINGIFY(s) STRINGIFY2(s) 663 #endif 664 665 #define PDX_ERROR_PREFIX "[" __FILE__ ":" STRINGIFY(__LINE__) "]" 666 667 /* 668 * Macros for replying to messages. Error handling can be tedious; 669 * these macros make things a little cleaner. 670 */ 671 #define CHECK_ERROR(cond, error, fmt, ...) \ 672 do { \ 673 if ((cond)) { \ 674 ALOGE(fmt, ##__VA_ARGS__); \ 675 goto error; \ 676 } \ 677 } while (0) 678 679 #define REPLY_ERROR(message, error, error_label) \ 680 do { \ 681 auto __status = message.ReplyError(error); \ 682 CHECK_ERROR(!__status, error_label, \ 683 PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \ 684 __status.GetErrorMessage().c_str()); \ 685 goto error_label; \ 686 } while (0) 687 688 #define REPLY_ERROR_RETURN(message, error, ...) \ 689 do { \ 690 auto __status = message.ReplyError(error); \ 691 ALOGE_IF(!__status, \ 692 PDX_ERROR_PREFIX " Failed to reply to message because: %s", \ 693 __status.GetErrorMessage().c_str()); \ 694 return __VA_ARGS__; \ 695 } while (0) 696 697 #define REPLY_MESSAGE(message, message_return_code, error_label) \ 698 do { \ 699 auto __status = message.Reply(message_return_code); \ 700 CHECK_ERROR(!__status, error_label, \ 701 PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \ 702 __status.GetErrorMessage().c_str()); \ 703 goto error_label; \ 704 } while (0) 705 706 #define REPLY_SUCCESS(message, message_return_code, error_label) \ 707 REPLY_MESSAGE(message, message_return_code, error_label) 708 709 #define REPLY_MESSAGE_RETURN(message, message_return_code, ...) \ 710 do { \ 711 auto __status = message.Reply(message_return_code); \ 712 ALOGE_IF(!__status, \ 713 PDX_ERROR_PREFIX " Failed to reply to message because: %s", \ 714 __status.GetErrorMessage().c_str()); \ 715 return __VA_ARGS__; \ 716 } while (0) 717 718 #define REPLY_SUCCESS_RETURN(message, message_return_code, ...) \ 719 REPLY_MESSAGE_RETURN(message, message_return_code, __VA_ARGS__) 720 721 #define REPLY_FD(message, push_fd, error_label) \ 722 do { \ 723 auto __status = message.ReplyFileDescriptor(push_fd); \ 724 CHECK_ERROR(!__status, error_label, \ 725 PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \ 726 __status.GetErrorMessage().c_str()); \ 727 goto error_label; \ 728 } while (0) 729 730 #define REPLY_FD_RETURN(message, push_fd, ...) \ 731 do { \ 732 auto __status = message.ReplyFileDescriptor(push_fd); \ 733 ALOGE_IF(__status < 0, \ 734 PDX_ERROR_PREFIX " Failed to reply to message because: %s", \ 735 __status.GetErrorMessage().c_str()); \ 736 return __VA_ARGS__; \ 737 } while (0) 738 739 } // namespace pdx 740 } // namespace android 741 742 #endif // ANDROID_PDX_SERVICE_H_ 743