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 NBLog {
     29 
     30 public:
     31 
     32 class Writer;
     33 class Reader;
     34 
     35 private:
     36 
     37 enum Event {
     38     EVENT_RESERVED,
     39     EVENT_STRING,               // ASCII string, not NUL-terminated
     40     EVENT_TIMESTAMP,            // clock_gettime(CLOCK_MONOTONIC)
     41 };
     42 
     43 // ---------------------------------------------------------------------------
     44 
     45 // representation of a single log entry in private memory
     46 struct Entry {
     47     Entry(Event event, const void *data, size_t length)
     48         : mEvent(event), mLength(length), mData(data) { }
     49     /*virtual*/ ~Entry() { }
     50 
     51     int     readAt(size_t offset) const;
     52 
     53 private:
     54     friend class Writer;
     55     Event       mEvent;     // event type
     56     size_t      mLength;    // length of additional data, 0 <= mLength <= 255
     57     const void *mData;      // event type-specific data
     58 };
     59 
     60 // representation of a single log entry in shared memory
     61 //  byte[0]             mEvent
     62 //  byte[1]             mLength
     63 //  byte[2]             mData[0]
     64 //  ...
     65 //  byte[2+i]           mData[i]
     66 //  ...
     67 //  byte[2+mLength-1]   mData[mLength-1]
     68 //  byte[2+mLength]     duplicate copy of mLength to permit reverse scan
     69 //  byte[3+mLength]     start of next log entry
     70 
     71 // located in shared memory
     72 struct Shared {
     73     Shared() : mRear(0) { }
     74     /*virtual*/ ~Shared() { }
     75 
     76     volatile int32_t mRear;     // index one byte past the end of most recent Entry
     77     char    mBuffer[0];         // circular buffer for entries
     78 };
     79 
     80 public:
     81 
     82 // ---------------------------------------------------------------------------
     83 
     84 // FIXME Timeline was intended to wrap Writer and Reader, but isn't actually used yet.
     85 // For now it is just a namespace for sharedSize().
     86 class Timeline : public RefBase {
     87 public:
     88 #if 0
     89     Timeline(size_t size, void *shared = NULL);
     90     virtual ~Timeline();
     91 #endif
     92 
     93     // Input parameter 'size' is the desired size of the timeline in byte units.
     94     // Returns the size rounded up to a power-of-2, plus the constant size overhead for indices.
     95     static size_t sharedSize(size_t size);
     96 
     97 #if 0
     98 private:
     99     friend class    Writer;
    100     friend class    Reader;
    101 
    102     const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
    103     bool            mOwn;       // whether I own the memory at mShared
    104     Shared* const   mShared;    // pointer to shared memory
    105 #endif
    106 };
    107 
    108 // ---------------------------------------------------------------------------
    109 
    110 // Writer is thread-safe with respect to Reader, but not with respect to multiple threads
    111 // calling Writer methods.  If you need multi-thread safety for writing, use LockedWriter.
    112 class Writer : public RefBase {
    113 public:
    114     Writer();                   // dummy nop implementation without shared memory
    115 
    116     // Input parameter 'size' is the desired size of the timeline in byte units.
    117     // The size of the shared memory must be at least Timeline::sharedSize(size).
    118     Writer(size_t size, void *shared);
    119     Writer(size_t size, const sp<IMemory>& iMemory);
    120 
    121     virtual ~Writer() { }
    122 
    123     virtual void    log(const char *string);
    124     virtual void    logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
    125     virtual void    logvf(const char *fmt, va_list ap);
    126     virtual void    logTimestamp();
    127     virtual void    logTimestamp(const struct timespec& ts);
    128 
    129     virtual bool    isEnabled() const;
    130 
    131     // return value for all of these is the previous isEnabled()
    132     virtual bool    setEnabled(bool enabled);   // but won't enable if no shared memory
    133             bool    enable()    { return setEnabled(true); }
    134             bool    disable()   { return setEnabled(false); }
    135 
    136     sp<IMemory>     getIMemory() const  { return mIMemory; }
    137 
    138 private:
    139     void    log(Event event, const void *data, size_t length);
    140     void    log(const Entry *entry, bool trusted = false);
    141 
    142     const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
    143     Shared* const   mShared;    // raw pointer to shared memory
    144     const sp<IMemory> mIMemory; // ref-counted version
    145     int32_t         mRear;      // my private copy of mShared->mRear
    146     bool            mEnabled;   // whether to actually log
    147 };
    148 
    149 // ---------------------------------------------------------------------------
    150 
    151 // Similar to Writer, but safe for multiple threads to call concurrently
    152 class LockedWriter : public Writer {
    153 public:
    154     LockedWriter();
    155     LockedWriter(size_t size, void *shared);
    156 
    157     virtual void    log(const char *string);
    158     virtual void    logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
    159     virtual void    logvf(const char *fmt, va_list ap);
    160     virtual void    logTimestamp();
    161     virtual void    logTimestamp(const struct timespec& ts);
    162 
    163     virtual bool    isEnabled() const;
    164     virtual bool    setEnabled(bool enabled);
    165 
    166 private:
    167     mutable Mutex   mLock;
    168 };
    169 
    170 // ---------------------------------------------------------------------------
    171 
    172 class Reader : public RefBase {
    173 public:
    174 
    175     // Input parameter 'size' is the desired size of the timeline in byte units.
    176     // The size of the shared memory must be at least Timeline::sharedSize(size).
    177     Reader(size_t size, const void *shared);
    178     Reader(size_t size, const sp<IMemory>& iMemory);
    179 
    180     virtual ~Reader() { }
    181 
    182     void    dump(int fd, size_t indent = 0);
    183     bool    isIMemory(const sp<IMemory>& iMemory) const;
    184 
    185 private:
    186     const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
    187     const Shared* const mShared; // raw pointer to shared memory
    188     const sp<IMemory> mIMemory; // ref-counted version
    189     int32_t     mFront;         // index of oldest acknowledged Entry
    190 
    191     static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
    192 };
    193 
    194 };  // class NBLog
    195 
    196 }   // namespace android
    197 
    198 #endif  // ANDROID_MEDIA_NBLOG_H
    199