NBLog.h revision 4e01ef6b2f6d288b9aa83b5817adad02cecc429f
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 26namespace android { 27 28class String8; 29 30class NBLog { 31 32public: 33 34class Writer; 35class Reader; 36 37private: 38 39enum 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 48struct 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 55private: 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 74struct 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 82public: 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(). 88class Timeline : public RefBase { 89public: 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 100private: 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. 114class Writer : public RefBase { 115public: 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 140private: 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 154class LockedWriter : public Writer { 155public: 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 168private: 169 mutable Mutex mLock; 170}; 171 172// --------------------------------------------------------------------------- 173 174class Reader : public RefBase { 175public: 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 187private: 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