• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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