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     static size_t sharedSize(size_t size);
     94 
     95 #if 0
     96 private:
     97     friend class    Writer;
     98     friend class    Reader;
     99 
    100     const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
    101     bool            mOwn;       // whether I own the memory at mShared
    102     Shared* const   mShared;    // pointer to shared memory
    103 #endif
    104 };
    105 
    106 // ---------------------------------------------------------------------------
    107 
    108 // Writer is thread-safe with respect to Reader, but not with respect to multiple threads
    109 // calling Writer methods.  If you need multi-thread safety for writing, use LockedWriter.
    110 class Writer : public RefBase {
    111 public:
    112     Writer();                   // dummy nop implementation without shared memory
    113     Writer(size_t size, void *shared);
    114     Writer(size_t size, const sp<IMemory>& iMemory);
    115     virtual ~Writer() { }
    116 
    117     virtual void    log(const char *string);
    118     virtual void    logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
    119     virtual void    logvf(const char *fmt, va_list ap);
    120     virtual void    logTimestamp();
    121     virtual void    logTimestamp(const struct timespec& ts);
    122 
    123     virtual bool    isEnabled() const;
    124 
    125     // return value for all of these is the previous isEnabled()
    126     virtual bool    setEnabled(bool enabled);   // but won't enable if no shared memory
    127             bool    enable()    { return setEnabled(true); }
    128             bool    disable()   { return setEnabled(false); }
    129 
    130     sp<IMemory>     getIMemory() const  { return mIMemory; }
    131 
    132 private:
    133     void    log(Event event, const void *data, size_t length);
    134     void    log(const Entry *entry, bool trusted = false);
    135 
    136     const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
    137     Shared* const   mShared;    // raw pointer to shared memory
    138     const sp<IMemory> mIMemory; // ref-counted version
    139     int32_t         mRear;      // my private copy of mShared->mRear
    140     bool            mEnabled;   // whether to actually log
    141 };
    142 
    143 // ---------------------------------------------------------------------------
    144 
    145 // Similar to Writer, but safe for multiple threads to call concurrently
    146 class LockedWriter : public Writer {
    147 public:
    148     LockedWriter();
    149     LockedWriter(size_t size, void *shared);
    150 
    151     virtual void    log(const char *string);
    152     virtual void    logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
    153     virtual void    logvf(const char *fmt, va_list ap);
    154     virtual void    logTimestamp();
    155     virtual void    logTimestamp(const struct timespec& ts);
    156 
    157     virtual bool    isEnabled() const;
    158     virtual bool    setEnabled(bool enabled);
    159 
    160 private:
    161     mutable Mutex   mLock;
    162 };
    163 
    164 // ---------------------------------------------------------------------------
    165 
    166 class Reader : public RefBase {
    167 public:
    168     Reader(size_t size, const void *shared);
    169     Reader(size_t size, const sp<IMemory>& iMemory);
    170     virtual ~Reader() { }
    171 
    172     void    dump(int fd, size_t indent = 0);
    173     bool    isIMemory(const sp<IMemory>& iMemory) const;
    174 
    175 private:
    176     const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
    177     const Shared* const mShared; // raw pointer to shared memory
    178     const sp<IMemory> mIMemory; // ref-counted version
    179     int32_t     mFront;         // index of oldest acknowledged Entry
    180 
    181     static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
    182 };
    183 
    184 };  // class NBLog
    185 
    186 }   // namespace android
    187 
    188 #endif  // ANDROID_MEDIA_NBLOG_H
    189