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    * Accessors to the pid of the last active client.
     63    */
     64   pid_t GetActiveProcessId() const { return client_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>
    116   inline Status<size_t> ReadVector(const iovec (&vector)[N]) {
    117     return ReadVector(vector, N);
    118   }
    119 
    120   template <size_t 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 
    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   }
    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>
    148   inline Status<void> ReadVectorAll(const iovec (&vector)[N]) {
    149     return ReadVectorAll(vector, N);
    150   }
    151 
    152   template <size_t 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>
    187   inline Status<void> Reply(const Status<T>& status) {
    188     return status ? Reply(status.get()) : ReplyError(status.error());
    189   }
    190 
    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>
    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>
    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    */
    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>
    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 
    335   bool replied() const { return replied_; }
    336   bool IsChannelExpired() const { return channel_.expired(); }
    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 
    345   const void* GetState() const { return state_; }
    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>
    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>
    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    */
    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>
    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>
    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    */
    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>
    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 
    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