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