blob: 191f0cb42f3f4682813c6a25a7bad05455b0e99d [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
26namespace android {
27
Glenn Kasten4e01ef62013-07-11 14:29:59 -070028class String8;
29
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080030class 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)
Nicolas Rouletfe1e1442017-01-30 12:02:03 -080043 EVENT_INTEGER,
44 EVENT_FLOAT,
45 EVENT_PID,
46 EVENT_START_FMT, // logFormat start event: entry includes format string, following
47 // entries contain format arguments
48 EVENT_END_FMT, // end of logFormat argument list
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080049};
50
51// ---------------------------------------------------------------------------
52
53// representation of a single log entry in private memory
54struct Entry {
55 Entry(Event event, const void *data, size_t length)
56 : mEvent(event), mLength(length), mData(data) { }
57 /*virtual*/ ~Entry() { }
58
59 int readAt(size_t offset) const;
60
61private:
62 friend class Writer;
63 Event mEvent; // event type
Glenn Kasten535e1612016-12-05 12:19:36 -080064 uint8_t mLength; // length of additional data, 0 <= mLength <= kMaxLength
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080065 const void *mData; // event type-specific data
Glenn Kasten535e1612016-12-05 12:19:36 -080066 static const size_t kMaxLength = 255;
67public:
68 static const size_t kOverhead = 3; // mEvent, mLength, mData[...], duplicate mLength
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080069};
70
71// representation of a single log entry in shared memory
72// byte[0] mEvent
73// byte[1] mLength
74// byte[2] mData[0]
75// ...
76// byte[2+i] mData[i]
77// ...
78// byte[2+mLength-1] mData[mLength-1]
79// byte[2+mLength] duplicate copy of mLength to permit reverse scan
80// byte[3+mLength] start of next log entry
81
Nicolas Rouletfe1e1442017-01-30 12:02:03 -080082 static void appendInt(String8 *body, const void *data);
83 static void appendFloat(String8 *body, const void *data);
Nicolas Rouletc20cb502017-02-01 12:35:24 -080084 static void appendPID(String8 *body, const void *data, size_t length);
Nicolas Rouletfe1e1442017-01-30 12:02:03 -080085 static int handleFormat(const char *fmt, size_t length, const uint8_t *data,
86 String8 *timestamp, String8 *body);
87 static void appendTimestamp(String8 *body, const void *data);
88
Glenn Kasten535e1612016-12-05 12:19:36 -080089public:
90
91// Located in shared memory, must be POD.
92// Exactly one process must explicitly call the constructor or use placement new.
93// Since this is a POD, the destructor is empty and unnecessary to call it explicitly.
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080094struct Shared {
Glenn Kasten535e1612016-12-05 12:19:36 -080095 Shared() /* mRear initialized via default constructor */ { }
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080096 /*virtual*/ ~Shared() { }
97
Glenn Kasten535e1612016-12-05 12:19:36 -080098 audio_utils_fifo_index mRear; // index one byte past the end of most recent Entry
99 char mBuffer[0]; // circular buffer for entries
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800100};
101
102public:
103
104// ---------------------------------------------------------------------------
105
106// FIXME Timeline was intended to wrap Writer and Reader, but isn't actually used yet.
107// For now it is just a namespace for sharedSize().
108class Timeline : public RefBase {
109public:
110#if 0
111 Timeline(size_t size, void *shared = NULL);
112 virtual ~Timeline();
113#endif
114
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700115 // Input parameter 'size' is the desired size of the timeline in byte units.
116 // Returns the size rounded up to a power-of-2, plus the constant size overhead for indices.
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800117 static size_t sharedSize(size_t size);
118
119#if 0
120private:
121 friend class Writer;
122 friend class Reader;
123
124 const size_t mSize; // circular buffer size in bytes, must be a power of 2
125 bool mOwn; // whether I own the memory at mShared
126 Shared* const mShared; // pointer to shared memory
127#endif
128};
129
130// ---------------------------------------------------------------------------
131
132// Writer is thread-safe with respect to Reader, but not with respect to multiple threads
133// calling Writer methods. If you need multi-thread safety for writing, use LockedWriter.
134class Writer : public RefBase {
135public:
136 Writer(); // dummy nop implementation without shared memory
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700137
138 // Input parameter 'size' is the desired size of the timeline in byte units.
139 // The size of the shared memory must be at least Timeline::sharedSize(size).
Glenn Kasten535e1612016-12-05 12:19:36 -0800140 Writer(void *shared, size_t size);
141 Writer(const sp<IMemory>& iMemory, size_t size);
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700142
Glenn Kasten535e1612016-12-05 12:19:36 -0800143 virtual ~Writer();
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800144
145 virtual void log(const char *string);
Glenn Kastenab7d72f2013-02-27 09:05:28 -0800146 virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800147 virtual void logvf(const char *fmt, va_list ap);
148 virtual void logTimestamp();
Nicolas Rouletfe1e1442017-01-30 12:02:03 -0800149 virtual void logTimestamp(const struct timespec &ts);
150 virtual void logInteger(const int x);
151 virtual void logFloat(const float x);
152 virtual void logPID();
153 virtual void logFormat(const char *fmt, ...);
154 virtual void logVFormat(const char *fmt, va_list ap);
155 virtual void logStart(const char *fmt);
156 virtual void logEnd();
157
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800158
159 virtual bool isEnabled() const;
160
161 // return value for all of these is the previous isEnabled()
162 virtual bool setEnabled(bool enabled); // but won't enable if no shared memory
163 bool enable() { return setEnabled(true); }
164 bool disable() { return setEnabled(false); }
165
166 sp<IMemory> getIMemory() const { return mIMemory; }
167
168private:
Glenn Kasten535e1612016-12-05 12:19:36 -0800169 // 0 <= length <= kMaxLength
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800170 void log(Event event, const void *data, size_t length);
171 void log(const Entry *entry, bool trusted = false);
172
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800173 Shared* const mShared; // raw pointer to shared memory
Glenn Kasten535e1612016-12-05 12:19:36 -0800174 sp<IMemory> mIMemory; // ref-counted version, initialized in constructor and then const
175 audio_utils_fifo * const mFifo; // FIFO itself,
176 // non-NULL unless constructor fails
177 audio_utils_fifo_writer * const mFifoWriter; // used to write to FIFO,
178 // non-NULL unless dummy constructor used
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800179 bool mEnabled; // whether to actually log
Nicolas Rouletc20cb502017-02-01 12:35:24 -0800180
181 // cached pid and process name to use in %p format specifier
182 // total tag length is mPidTagSize and process name is not zero terminated
183 char *mPidTag;
184 size_t mPidTagSize;
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800185};
186
187// ---------------------------------------------------------------------------
188
189// Similar to Writer, but safe for multiple threads to call concurrently
190class LockedWriter : public Writer {
191public:
192 LockedWriter();
Glenn Kasten535e1612016-12-05 12:19:36 -0800193 LockedWriter(void *shared, size_t size);
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800194
195 virtual void log(const char *string);
Glenn Kastenab7d72f2013-02-27 09:05:28 -0800196 virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800197 virtual void logvf(const char *fmt, va_list ap);
198 virtual void logTimestamp();
Nicolas Rouletfe1e1442017-01-30 12:02:03 -0800199 virtual void logTimestamp(const struct timespec &ts);
200 virtual void logInteger(const int x);
201 virtual void logFloat(const float x);
202 virtual void logPID();
203 virtual void logStart(const char *fmt);
204 virtual void logEnd();
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800205
206 virtual bool isEnabled() const;
207 virtual bool setEnabled(bool enabled);
208
209private:
210 mutable Mutex mLock;
211};
212
213// ---------------------------------------------------------------------------
214
215class Reader : public RefBase {
216public:
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700217
218 // Input parameter 'size' is the desired size of the timeline in byte units.
219 // The size of the shared memory must be at least Timeline::sharedSize(size).
Glenn Kasten535e1612016-12-05 12:19:36 -0800220 Reader(const void *shared, size_t size);
221 Reader(const sp<IMemory>& iMemory, size_t size);
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700222
Glenn Kasten535e1612016-12-05 12:19:36 -0800223 virtual ~Reader();
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800224
225 void dump(int fd, size_t indent = 0);
226 bool isIMemory(const sp<IMemory>& iMemory) const;
227
228private:
Glenn Kasten535e1612016-12-05 12:19:36 -0800229 /*const*/ Shared* const mShared; // raw pointer to shared memory, actually const but not
230 // declared as const because audio_utils_fifo() constructor
231 sp<IMemory> mIMemory; // ref-counted version, assigned only in constructor
Glenn Kasten4e01ef62013-07-11 14:29:59 -0700232 int mFd; // file descriptor
233 int mIndent; // indentation level
Glenn Kasten535e1612016-12-05 12:19:36 -0800234 audio_utils_fifo * const mFifo; // FIFO itself,
235 // non-NULL unless constructor fails
236 audio_utils_fifo_reader * const mFifoReader; // used to read from FIFO,
237 // non-NULL unless constructor fails
Glenn Kasten4e01ef62013-07-11 14:29:59 -0700238
239 void dumpLine(const String8& timestamp, String8& body);
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800240
241 static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
242};
243
244}; // class NBLog
245
246} // namespace android
247
248#endif // ANDROID_MEDIA_NBLOG_H