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 String8; 29 30 class NBLog { 31 32 public: 33 34 class Writer; 35 class Reader; 36 37 private: 38 39 enum 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 48 struct Entry { EntryEntry49 Entry(Event event, const void *data, size_t length) 50 : mEvent(event), mLength(length), mData(data) { } ~EntryEntry51 /*virtual*/ ~Entry() { } 52 53 int readAt(size_t offset) const; 54 55 private: 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 74 struct Shared { SharedShared75 Shared() : mRear(0) { } ~SharedShared76 /*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 82 public: 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(). 88 class Timeline : public RefBase { 89 public: 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 100 private: 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. 114 class Writer : public RefBase { 115 public: 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 ~Writer()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 enable()135 bool enable() { return setEnabled(true); } disable()136 bool disable() { return setEnabled(false); } 137 getIMemory()138 sp<IMemory> getIMemory() const { return mIMemory; } 139 140 private: 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 154 class LockedWriter : public Writer { 155 public: 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 168 private: 169 mutable Mutex mLock; 170 }; 171 172 // --------------------------------------------------------------------------- 173 174 class Reader : public RefBase { 175 public: 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 ~Reader()182 virtual ~Reader() { } 183 184 void dump(int fd, size_t indent = 0); 185 bool isIMemory(const sp<IMemory>& iMemory) const; 186 187 private: 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