blob: da809706d58fd83e4d7ad3ce12c421aa7f5ed21a [file] [log] [blame]
Glenn Kasten11d8dfc2013-01-14 14:53:13 -08001/*
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>
Glenn Kasten535e1612016-12-05 12:19:36 -080024#include <audio_utils/fifo.h>
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080025
Nicolas Roulet40a44982017-02-03 13:39:57 -080026#include <vector>
27
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080028namespace android {
29
Glenn Kasten4e01ef62013-07-11 14:29:59 -070030class String8;
31
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080032class NBLog {
33
34public:
35
36class Writer;
37class Reader;
38
39private:
40
41enum Event {
42 EVENT_RESERVED,
43 EVENT_STRING, // ASCII string, not NUL-terminated
44 EVENT_TIMESTAMP, // clock_gettime(CLOCK_MONOTONIC)
Nicolas Roulet40a44982017-02-03 13:39:57 -080045 EVENT_INTEGER, // integer value entry
46 EVENT_FLOAT, // floating point value entry
47 EVENT_PID, // process ID and process name
48 EVENT_AUTHOR, // author index (present in merged logs) tracks entry's original log
Nicolas Rouletfe1e1442017-01-30 12:02:03 -080049 EVENT_START_FMT, // logFormat start event: entry includes format string, following
50 // entries contain format arguments
51 EVENT_END_FMT, // end of logFormat argument list
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080052};
53
54// ---------------------------------------------------------------------------
55
56// representation of a single log entry in private memory
57struct Entry {
58 Entry(Event event, const void *data, size_t length)
59 : mEvent(event), mLength(length), mData(data) { }
60 /*virtual*/ ~Entry() { }
61
62 int readAt(size_t offset) const;
63
64private:
65 friend class Writer;
66 Event mEvent; // event type
Glenn Kasten535e1612016-12-05 12:19:36 -080067 uint8_t mLength; // length of additional data, 0 <= mLength <= kMaxLength
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080068 const void *mData; // event type-specific data
Glenn Kasten535e1612016-12-05 12:19:36 -080069 static const size_t kMaxLength = 255;
70public:
71 static const size_t kOverhead = 3; // mEvent, mLength, mData[...], duplicate mLength
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080072};
73
Nicolas Roulet40a44982017-02-03 13:39:57 -080074// ---------------------------------------------------------------------------
75// API for handling format entry operations
76
77// a formatted entry has the following structure:
78// * START_FMT entry, containing the format string
79// * author entry of the thread that generated it (optional, present in merged log)
80// * TIMESTAMP entry
81// * format arg1
82// * format arg2
83// * ...
84// * END_FMT entry
85
86class FormatEntry {
87public:
88 // build a Format Entry starting in the given pointer
89 explicit FormatEntry(const uint8_t *entry);
90
91 // Entry's format string
92 const char* formatString() const;
93
94 // Enrty's format string length
95 size_t formatStringLength() const;
96
97 // Format arguments (excluding format string, timestamp and author)
98 const uint8_t *args() const;
99
100 // get format entry timestamp
101 timespec timestamp() const;
102
103 // entry's author index (-1 if none present)
104 int author() const;
105
106 // copy entry, adding author before timestamp, returns size of original entry
107 // (intended for merger)
108 size_t copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const;
109private:
110 // copies ordinary entry from src to dst, and returns length of entry
111 size_t copyEntry(std::unique_ptr<audio_utils_fifo_writer> &dst, const uint8_t *src)
112 const;
113
114 const uint8_t *mEntry;
115};
116
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800117// representation of a single log entry in shared memory
118// byte[0] mEvent
119// byte[1] mLength
120// byte[2] mData[0]
121// ...
122// byte[2+i] mData[i]
123// ...
124// byte[2+mLength-1] mData[mLength-1]
125// byte[2+mLength] duplicate copy of mLength to permit reverse scan
126// byte[3+mLength] start of next log entry
127
Nicolas Rouletfe1e1442017-01-30 12:02:03 -0800128 static void appendInt(String8 *body, const void *data);
129 static void appendFloat(String8 *body, const void *data);
Nicolas Rouletc20cb502017-02-01 12:35:24 -0800130 static void appendPID(String8 *body, const void *data, size_t length);
Nicolas Rouletfe1e1442017-01-30 12:02:03 -0800131 static void appendTimestamp(String8 *body, const void *data);
Nicolas Roulet40a44982017-02-03 13:39:57 -0800132 static size_t fmtEntryLength(const uint8_t *data);
Nicolas Rouletfe1e1442017-01-30 12:02:03 -0800133
Glenn Kasten535e1612016-12-05 12:19:36 -0800134public:
135
136// Located in shared memory, must be POD.
137// Exactly one process must explicitly call the constructor or use placement new.
138// Since this is a POD, the destructor is empty and unnecessary to call it explicitly.
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800139struct Shared {
Glenn Kasten535e1612016-12-05 12:19:36 -0800140 Shared() /* mRear initialized via default constructor */ { }
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800141 /*virtual*/ ~Shared() { }
142
Glenn Kasten535e1612016-12-05 12:19:36 -0800143 audio_utils_fifo_index mRear; // index one byte past the end of most recent Entry
144 char mBuffer[0]; // circular buffer for entries
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800145};
146
147public:
148
149// ---------------------------------------------------------------------------
150
151// FIXME Timeline was intended to wrap Writer and Reader, but isn't actually used yet.
152// For now it is just a namespace for sharedSize().
153class Timeline : public RefBase {
154public:
155#if 0
156 Timeline(size_t size, void *shared = NULL);
157 virtual ~Timeline();
158#endif
159
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700160 // Input parameter 'size' is the desired size of the timeline in byte units.
161 // Returns the size rounded up to a power-of-2, plus the constant size overhead for indices.
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800162 static size_t sharedSize(size_t size);
163
164#if 0
165private:
166 friend class Writer;
167 friend class Reader;
168
169 const size_t mSize; // circular buffer size in bytes, must be a power of 2
170 bool mOwn; // whether I own the memory at mShared
171 Shared* const mShared; // pointer to shared memory
172#endif
173};
174
175// ---------------------------------------------------------------------------
176
177// Writer is thread-safe with respect to Reader, but not with respect to multiple threads
178// calling Writer methods. If you need multi-thread safety for writing, use LockedWriter.
179class Writer : public RefBase {
180public:
181 Writer(); // dummy nop implementation without shared memory
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700182
183 // Input parameter 'size' is the desired size of the timeline in byte units.
184 // The size of the shared memory must be at least Timeline::sharedSize(size).
Glenn Kasten535e1612016-12-05 12:19:36 -0800185 Writer(void *shared, size_t size);
186 Writer(const sp<IMemory>& iMemory, size_t size);
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700187
Glenn Kasten535e1612016-12-05 12:19:36 -0800188 virtual ~Writer();
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800189
190 virtual void log(const char *string);
Glenn Kastenab7d72f2013-02-27 09:05:28 -0800191 virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800192 virtual void logvf(const char *fmt, va_list ap);
193 virtual void logTimestamp();
Nicolas Rouletfe1e1442017-01-30 12:02:03 -0800194 virtual void logTimestamp(const struct timespec &ts);
195 virtual void logInteger(const int x);
196 virtual void logFloat(const float x);
197 virtual void logPID();
198 virtual void logFormat(const char *fmt, ...);
199 virtual void logVFormat(const char *fmt, va_list ap);
200 virtual void logStart(const char *fmt);
201 virtual void logEnd();
202
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800203
204 virtual bool isEnabled() const;
205
206 // return value for all of these is the previous isEnabled()
207 virtual bool setEnabled(bool enabled); // but won't enable if no shared memory
208 bool enable() { return setEnabled(true); }
209 bool disable() { return setEnabled(false); }
210
211 sp<IMemory> getIMemory() const { return mIMemory; }
212
213private:
Glenn Kasten535e1612016-12-05 12:19:36 -0800214 // 0 <= length <= kMaxLength
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800215 void log(Event event, const void *data, size_t length);
216 void log(const Entry *entry, bool trusted = false);
217
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800218 Shared* const mShared; // raw pointer to shared memory
Glenn Kasten535e1612016-12-05 12:19:36 -0800219 sp<IMemory> mIMemory; // ref-counted version, initialized in constructor and then const
220 audio_utils_fifo * const mFifo; // FIFO itself,
221 // non-NULL unless constructor fails
222 audio_utils_fifo_writer * const mFifoWriter; // used to write to FIFO,
223 // non-NULL unless dummy constructor used
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800224 bool mEnabled; // whether to actually log
Nicolas Rouletc20cb502017-02-01 12:35:24 -0800225
226 // cached pid and process name to use in %p format specifier
227 // total tag length is mPidTagSize and process name is not zero terminated
228 char *mPidTag;
229 size_t mPidTagSize;
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800230};
231
232// ---------------------------------------------------------------------------
233
234// Similar to Writer, but safe for multiple threads to call concurrently
235class LockedWriter : public Writer {
236public:
237 LockedWriter();
Glenn Kasten535e1612016-12-05 12:19:36 -0800238 LockedWriter(void *shared, size_t size);
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800239
240 virtual void log(const char *string);
Glenn Kastenab7d72f2013-02-27 09:05:28 -0800241 virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800242 virtual void logvf(const char *fmt, va_list ap);
243 virtual void logTimestamp();
Nicolas Rouletfe1e1442017-01-30 12:02:03 -0800244 virtual void logTimestamp(const struct timespec &ts);
245 virtual void logInteger(const int x);
246 virtual void logFloat(const float x);
247 virtual void logPID();
248 virtual void logStart(const char *fmt);
249 virtual void logEnd();
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800250
251 virtual bool isEnabled() const;
252 virtual bool setEnabled(bool enabled);
253
254private:
255 mutable Mutex mLock;
256};
257
258// ---------------------------------------------------------------------------
259
260class Reader : public RefBase {
261public:
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700262
Nicolas Roulet40a44982017-02-03 13:39:57 -0800263 // A snapshot of a readers buffer
264 class Snapshot {
265 public:
266 Snapshot() : mData(NULL), mAvail(0), mLost(0) {}
267
268 Snapshot(size_t bufferSize) : mData(new uint8_t[bufferSize]) {}
269
270 ~Snapshot() { delete[] mData; }
271
272 // copy of the buffer
273 const uint8_t *data() const { return mData; }
274
275 // amount of data available (given by audio_utils_fifo_reader)
276 size_t available() const { return mAvail; }
277
278 // amount of data lost (given by audio_utils_fifo_reader)
279 size_t lost() const { return mLost; }
280
281 private:
282 friend class Reader;
283 const uint8_t *mData;
284 size_t mAvail;
285 size_t mLost;
286 };
287
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700288 // Input parameter 'size' is the desired size of the timeline in byte units.
289 // The size of the shared memory must be at least Timeline::sharedSize(size).
Glenn Kasten535e1612016-12-05 12:19:36 -0800290 Reader(const void *shared, size_t size);
291 Reader(const sp<IMemory>& iMemory, size_t size);
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700292
Glenn Kasten535e1612016-12-05 12:19:36 -0800293 virtual ~Reader();
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800294
Nicolas Roulet40a44982017-02-03 13:39:57 -0800295 // get snapshot of readers fifo buffer, effectively consuming the buffer
296 std::unique_ptr<Snapshot> getSnapshot();
297 // dump a particular snapshot of the reader
298 void dump(int fd, size_t indent, Snapshot & snap);
299 // dump the current content of the reader's buffer
300 void dump(int fd, size_t indent = 0);
301 bool isIMemory(const sp<IMemory>& iMemory) const;
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800302
303private:
Glenn Kasten535e1612016-12-05 12:19:36 -0800304 /*const*/ Shared* const mShared; // raw pointer to shared memory, actually const but not
305 // declared as const because audio_utils_fifo() constructor
306 sp<IMemory> mIMemory; // ref-counted version, assigned only in constructor
Glenn Kasten4e01ef62013-07-11 14:29:59 -0700307 int mFd; // file descriptor
308 int mIndent; // indentation level
Glenn Kasten535e1612016-12-05 12:19:36 -0800309 audio_utils_fifo * const mFifo; // FIFO itself,
310 // non-NULL unless constructor fails
311 audio_utils_fifo_reader * const mFifoReader; // used to read from FIFO,
312 // non-NULL unless constructor fails
Glenn Kasten4e01ef62013-07-11 14:29:59 -0700313
314 void dumpLine(const String8& timestamp, String8& body);
Nicolas Roulet40a44982017-02-03 13:39:57 -0800315 int handleFormat(const FormatEntry &fmtEntry,
316 String8 *timestamp,
317 String8 *body);
318 // dummy method for handling absent author entry
319 virtual size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body) { return 0; }
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800320
321 static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
322};
323
Nicolas Roulet40a44982017-02-03 13:39:57 -0800324// Wrapper for a reader with a name. Contains a pointer to the reader and a pointer to the name
325class NamedReader {
326public:
327 NamedReader() { mName[0] = '\0'; } // for Vector
328 NamedReader(const sp<NBLog::Reader>& reader, const char *name) :
329 mReader(reader)
330 { strlcpy(mName, name, sizeof(mName)); }
331 ~NamedReader() { }
332 const sp<NBLog::Reader>& reader() const { return mReader; }
333 const char* name() const { return mName; }
334
335private:
336 sp<NBLog::Reader> mReader;
337 static const size_t kMaxName = 32;
338 char mName[kMaxName];
339};
340
341// ---------------------------------------------------------------------------
342
343class Merger : public RefBase {
344public:
345 Merger(const void *shared, size_t size);
346
347 virtual ~Merger() {}
348
349 void addReader(const NamedReader &reader);
350 // TODO add removeReader
351 void merge();
352 const std::vector<NamedReader> *getNamedReaders() const;
353private:
354 // vector of the readers the merger is supposed to merge from.
355 // every reader reads from a writer's buffer
356 std::vector<NamedReader> mNamedReaders;
357 uint8_t *mBuffer;
358 Shared * const mShared;
359 std::unique_ptr<audio_utils_fifo> mFifo;
360 std::unique_ptr<audio_utils_fifo_writer> mFifoWriter;
361
362 static struct timespec getTimestamp(const uint8_t *data);
363};
364
365class MergeReader : public Reader {
366public:
367 MergeReader(const void *shared, size_t size, Merger &merger);
368private:
369 const std::vector<NamedReader> *mNamedReaders;
370 // handle author entry by looking up the author's name and appending it to the body
371 // returns number of bytes read from fmtEntry
372 size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body);
373};
374
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800375}; // class NBLog
376
377} // namespace android
378
379#endif // ANDROID_MEDIA_NBLOG_H