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