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