Home | History | Annotate | Download | only in app
      1 //
      2 // Copyright 2005 The Android Open Source Project
      3 //
      4 // High-level message stream that sits on top of a pair of Pipes.  Useful
      5 // for inter-process communication, e.g. between "simulator" and "runtime".
      6 //
      7 // All messages are sent in packets:
      8 //  +00 16-bit length (of everything that follows), little-endian
      9 //  +02 8-bit message type
     10 //  +03 (reserved, must be zero)
     11 //  +04 message body
     12 //
     13 #ifndef _LIBS_UTILS_MESSAGE_STREAM_H
     14 #define _LIBS_UTILS_MESSAGE_STREAM_H
     15 
     16 #ifdef HAVE_ANDROID_OS
     17 #error DO NOT USE THIS FILE IN THE DEVICE BUILD
     18 #endif
     19 
     20 #include "Pipe.h"
     21 #include <stdlib.h>
     22 #include <cutils/uio.h>
     23 
     24 // Defined in LogBundle.h.
     25 struct android_LogBundle;
     26 
     27 namespace android {
     28 
     29 /*
     30  * A single message, which can be filled out and sent, or filled with
     31  * received data.
     32  *
     33  * Message objects are reusable.
     34  */
     35 class Message {
     36 public:
     37     Message(void)
     38         : mCleanup(kCleanupUnknown)
     39         { reset(); }
     40     ~Message(void) { reset(); }
     41 
     42     /* values for message type byte */
     43     typedef enum MessageType {
     44         kTypeUnknown = 0,
     45         kTypeRaw,           // chunk of raw data
     46         kTypeConfig,        // send a name=value pair to peer
     47         kTypeCommand,       // simple command w/arg
     48         kTypeCommandExt,    // slightly more complicated command
     49         kTypeLogBundle,     // multi-part log message
     50     } MessageType;
     51 
     52     /* what to do with data when we're done */
     53     typedef enum Cleanup {
     54         kCleanupUnknown = 0,
     55         kCleanupNoDelete,   // do not delete data when object destroyed
     56         kCleanupDelete,     // delete with "delete[]"
     57     } Cleanup;
     58 
     59     /*
     60      * Stuff raw data into the object.  The caller can use the "cleanup"
     61      * parameter to decide whether or not the Message object owns the data.
     62      */
     63     void setRaw(const unsigned char* data, int len, Cleanup cleanup);
     64 
     65     /*
     66      * Send a "name=value" pair.
     67      */
     68     void setConfig(const char* name, const char* value);
     69 
     70     /*
     71      * Send a command/arg pair.
     72      */
     73     void setCommand(int cmd, int arg);
     74     void setCommandExt(int cmd, int arg0, int arg1, int arg2);
     75 
     76     /*
     77      * Send a multi-part log message.
     78      */
     79     void setLogBundle(const android_LogBundle* pBundle);
     80 
     81     /*
     82      * Simple accessors.
     83      */
     84     MessageType getType(void) const { return mType; }
     85     const unsigned char* getData(void) const { return mData; }
     86     int getLength(void) const { return mLength; }
     87 
     88     /*
     89      * Not-so-simple accessors.  These coerce the raw data into an object.
     90      *
     91      * The data returned by these may not outlive the Message, so make
     92      * copies if you plan to use them long-term.
     93      */
     94     bool getConfig(const char** pName, const char** pValue);
     95     bool getCommand(int* pCmd, int* pArg);
     96     bool getLogBundle(android_LogBundle* pBundle);
     97 
     98     /*
     99      * Read or write this message on the specified pipe.
    100      *
    101      * If "wait" is true, read() blocks until a message arrives.  Only
    102      * one thread should be reading at a time.
    103      */
    104     bool read(Pipe* pPipe, bool wait);
    105     bool write(Pipe* pPipe) const;
    106 
    107 private:
    108     Message& operator=(const Message&);     // not defined
    109     Message(const Message&);                // not defined
    110 
    111     void reset(void) {
    112         if (mCleanup == kCleanupDelete)
    113             delete[] mData;
    114 
    115         mType = kTypeUnknown;
    116         mCleanup = kCleanupNoDelete;
    117         mData = NULL;
    118         mLength = -1;
    119     }
    120 
    121     MessageType     mType;
    122     Cleanup         mCleanup;
    123     unsigned char*  mData;
    124     int             mLength;
    125     struct iovec    mVec;
    126 };
    127 
    128 
    129 /*
    130  * Abstraction of higher-level communication channel.
    131  *
    132  * This may be used from multiple threads simultaneously.  Blocking on
    133  * the read pipe from multiple threads will have unpredictable behavior.
    134  *
    135  * Does not take ownership of the pipes passed in to init().
    136  */
    137 class MessageStream {
    138 public:
    139     MessageStream(void)
    140         : mReadPipe(NULL), mWritePipe(NULL)
    141         {}
    142     ~MessageStream(void) {}
    143 
    144     /*
    145      * Initialize object and exchange greetings.  "initateHello" determines
    146      * whether we send "Hello" or block waiting for it to arrive.  Usually
    147      * the "parent" initiates.
    148      */
    149     bool init(Pipe* readPipe, Pipe* writePipe, bool initiateHello);
    150 
    151     bool isReady(void) const { return mReadPipe != NULL && mWritePipe != NULL; }
    152 
    153     /*
    154      * Send a message immediately.
    155      */
    156     bool send(const Message* pMsg) { return pMsg->write(mWritePipe); }
    157 
    158     /*
    159      * Receive a message.
    160      */
    161     bool recv(Message* pMsg, bool wait) { return pMsg->read(mReadPipe, wait); }
    162 
    163     /*
    164      * Close communication pipes.  Further attempts to send or receive
    165      * will fail.  Note this doesn't actually "close" the pipes, because
    166      * we don't own them.
    167      */
    168     void close(void) { mReadPipe = mWritePipe = NULL; }
    169 
    170     /*
    171      * Get our incoming traffic pipe.  This is useful on Linux systems
    172      * because it allows access to the file descriptor which can be used
    173      * in a select() call.
    174      */
    175     Pipe* getReadPipe(void) { return mReadPipe; }
    176 
    177 private:
    178     enum {
    179         kHelloMsg       = 0x4e303047,       // 'N00G'
    180         kHelloAckMsg    = 0x31455221,       // '1ER!'
    181     };
    182 
    183     /* communication pipes; note we don't own these */
    184     Pipe*   mReadPipe;
    185     Pipe*   mWritePipe;
    186 };
    187 
    188 }; // namespace android
    189 
    190 #endif // _LIBS_UTILS_MESSAGE_STREAM_H
    191