Home | History | Annotate | Download | only in pdx
      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