blob: 1297b5132962221bdba38d5967a3b736a7b102b5 [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 Kasten53dbe772015-01-06 10:46:38 -080024#include <audio_utils/roundup.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)
43};
44
45// ---------------------------------------------------------------------------
46
47// representation of a single log entry in private memory
48struct Entry {
49 Entry(Event event, const void *data, size_t length)
50 : mEvent(event), mLength(length), mData(data) { }
51 /*virtual*/ ~Entry() { }
52
53 int readAt(size_t offset) const;
54
55private:
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
74struct Shared {
75 Shared() : mRear(0) { }
76 /*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
82public:
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().
88class Timeline : public RefBase {
89public:
90#if 0
91 Timeline(size_t size, void *shared = NULL);
92 virtual ~Timeline();
93#endif
94
Glenn Kastenfb1fdc92013-07-10 17:03:19 -070095 // 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.
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080097 static size_t sharedSize(size_t size);
98
99#if 0
100private:
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.
114class Writer : public RefBase {
115public:
116 Writer(); // dummy nop implementation without shared memory
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700117
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).
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800120 Writer(size_t size, void *shared);
121 Writer(size_t size, const sp<IMemory>& iMemory);
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700122
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800123 virtual ~Writer() { }
124
125 virtual void log(const char *string);
Glenn Kastenab7d72f2013-02-27 09:05:28 -0800126 virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800127 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
135 bool enable() { return setEnabled(true); }
136 bool disable() { return setEnabled(false); }
137
138 sp<IMemory> getIMemory() const { return mIMemory; }
139
140private:
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
154class LockedWriter : public Writer {
155public:
156 LockedWriter();
157 LockedWriter(size_t size, void *shared);
158
159 virtual void log(const char *string);
Glenn Kastenab7d72f2013-02-27 09:05:28 -0800160 virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800161 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
168private:
169 mutable Mutex mLock;
170};
171
172// ---------------------------------------------------------------------------
173
174class Reader : public RefBase {
175public:
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700176
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).
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800179 Reader(size_t size, const void *shared);
180 Reader(size_t size, const sp<IMemory>& iMemory);
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700181
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800182 virtual ~Reader() { }
183
184 void dump(int fd, size_t indent = 0);
185 bool isIMemory(const sp<IMemory>& iMemory) const;
186
187private:
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
Glenn Kasten4e01ef62013-07-11 14:29:59 -0700192 int mFd; // file descriptor
193 int mIndent; // indentation level
194
195 void dumpLine(const String8& timestamp, String8& body);
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800196
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