Home | History | Annotate | Download | only in nbaio
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // Non-blocking event logger intended for safe communication between processes via shared memory
     18 
     19 #ifndef ANDROID_MEDIA_NBLOG_H
     20 #define ANDROID_MEDIA_NBLOG_H
     21 
     22 #include <binder/IMemory.h>
     23 #include <utils/Mutex.h>
     24 #include <media/nbaio/roundup.h>
     25 
     26 namespace android {
     27 
     28 class String8;
     29 
     30 class NBLog {
     31 
     32 public:
     33 
     34 class Writer;
     35 class Reader;
     36 
     37 private:
     38 
     39 enum Event {
     40     EVENT_RESERVED,
     41     EVENT_STRING,               // ASCII string, not NUL-terminated
     42     EVENT_TIMESTAMP,            // clock_gettime(CLOCK_MONOTONIC)
     43 };
     44 
     45 // ---------------------------------------------------------------------------
     46 
     47 // representation of a single log entry in private memory
     48 struct Entry {
     49     Entry(Event event, const void *data, size_t length)
     50         : mEvent(event), mLength(length), mData(data) { }
     51     /*virtual*/ ~Entry() { }
     52 
     53     int     readAt(size_t offset) const;
     54 
     55 private:
     56     friend class Writer;
     57     Event       mEvent;     // event type
     58     size_t      mLength;    // length of additional data, 0 <= mLength <= 255
     59     const void *mData;      // event type-specific data
     60 };
     61 
     62 // representation of a single log entry in shared memory
     63 //  byte[0]             mEvent
     64 //  byte[1]             mLength
     65 //  byte[2]             mData[0]
     66 //  ...
     67 //  byte[2+i]           mData[i]
     68 //  ...
     69 //  byte[2+mLength-1]   mData[mLength-1]
     70 //  byte[2+mLength]     duplicate copy of mLength to permit reverse scan
     71 //  byte[3+mLength]     start of next log entry
     72 
     73 // located in shared memory
     74 struct Shared {
     75     Shared() : mRear(0) { }
     76     /*virtual*/ ~Shared() { }
     77 
     78     volatile int32_t mRear;     // index one byte past the end of most recent Entry
     79     char    mBuffer[0];         // circular buffer for entries
     80 };
     81 
     82 public:
     83 
     84 // ---------------------------------------------------------------------------
     85 
     86 // FIXME Timeline was intended to wrap Writer and Reader, but isn't actually used yet.
     87 // For now it is just a namespace for sharedSize().
     88 class Timeline : public RefBase {
     89 public:
     90 #if 0
     91     Timeline(size_t size, void *shared = NULL);
     92     virtual ~Timeline();
     93 #endif
     94 
     95     // Input parameter 'size' is the desired size of the timeline in byte units.
     96     // Returns the size rounded up to a power-of-2, plus the constant size overhead for indices.
     97     static size_t sharedSize(size_t size);
     98 
     99 #if 0
    100 private:
    101     friend class    Writer;
    102     friend class    Reader;
    103 
    104     const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
    105     bool            mOwn;       // whether I own the memory at mShared
    106     Shared* const   mShared;    // pointer to shared memory
    107 #endif
    108 };
    109 
    110 // ---------------------------------------------------------------------------
    111 
    112 // Writer is thread-safe with respect to Reader, but not with respect to multiple threads
    113 // calling Writer methods.  If you need multi-thread safety for writing, use LockedWriter.
    114 class Writer : public RefBase {
    115 public:
    116     Writer();                   // dummy nop implementation without shared memory
    117 
    118     // Input parameter 'size' is the desired size of the timeline in byte units.
    119     // The size of the shared memory must be at least Timeline::sharedSize(size).
    120     Writer(size_t size, void *shared);
    121     Writer(size_t size, const sp<IMemory>& iMemory);
    122 
    123     virtual ~Writer() { }
    124 
    125     virtual void    log(const char *string);
    126     virtual void    logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
    127     virtual void    logvf(const char *fmt, va_list ap);
    128     virtual void    logTimestamp();
    129     virtual void    logTimestamp(const struct timespec& ts);
    130 
    131     virtual bool    isEnabled() const;
    132 
    133     // return value for all of these is the previous isEnabled()
    134     virtual bool    setEnabled(bool enabled);   // but won't enable if no shared memory
    135             bool    enable()    { return setEnabled(true); }
    136             bool    disable()   { return setEnabled(false); }
    137 
    138     sp<IMemory>     getIMemory() const  { return mIMemory; }
    139 
    140 private:
    141     void    log(Event event, const void *data, size_t length);
    142     void    log(const Entry *entry, bool trusted = false);
    143 
    144     const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
    145     Shared* const   mShared;    // raw pointer to shared memory
    146     const sp<IMemory> mIMemory; // ref-counted version
    147     int32_t         mRear;      // my private copy of mShared->mRear
    148     bool            mEnabled;   // whether to actually log
    149 };
    150 
    151 // ---------------------------------------------------------------------------
    152 
    153 // Similar to Writer, but safe for multiple threads to call concurrently
    154 class LockedWriter : public Writer {
    155 public:
    156     LockedWriter();
    157     LockedWriter(size_t size, void *shared);
    158 
    159     virtual void    log(const char *string);
    160     virtual void    logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
    161     virtual void    logvf(const char *fmt, va_list ap);
    162     virtual void    logTimestamp();
    163     virtual void    logTimestamp(const struct timespec& ts);
    164 
    165     virtual bool    isEnabled() const;
    166     virtual bool    setEnabled(bool enabled);
    167 
    168 private:
    169     mutable Mutex   mLock;
    170 };
    171 
    172 // ---------------------------------------------------------------------------
    173 
    174 class Reader : public RefBase {
    175 public:
    176 
    177     // Input parameter 'size' is the desired size of the timeline in byte units.
    178     // The size of the shared memory must be at least Timeline::sharedSize(size).
    179     Reader(size_t size, const void *shared);
    180     Reader(size_t size, const sp<IMemory>& iMemory);
    181 
    182     virtual ~Reader() { }
    183 
    184     void    dump(int fd, size_t indent = 0);
    185     bool    isIMemory(const sp<IMemory>& iMemory) const;
    186 
    187 private:
    188     const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
    189     const Shared* const mShared; // raw pointer to shared memory
    190     const sp<IMemory> mIMemory; // ref-counted version
    191     int32_t     mFront;         // index of oldest acknowledged Entry
    192     int     mFd;                // file descriptor
    193     int     mIndent;            // indentation level
    194 
    195     void    dumpLine(const String8& timestamp, String8& body);
    196 
    197     static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
    198 };
    199 
    200 };  // class NBLog
    201 
    202 }   // namespace android
    203 
    204 #endif  // ANDROID_MEDIA_NBLOG_H
    205