blob: 6d59ea707e546a359ce15efd8210007ad7d741be [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>
24#include <media/nbaio/roundup.h>
25
26namespace android {
27
28class NBLog {
29
30public:
31
32class Writer;
33class Reader;
34
35private:
36
37enum 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
46struct 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
53private:
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
72struct 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
80public:
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().
86class Timeline : public RefBase {
87public:
88#if 0
89 Timeline(size_t size, void *shared = NULL);
90 virtual ~Timeline();
91#endif
92
Glenn Kastenfb1fdc92013-07-10 17:03:19 -070093 // Input parameter 'size' is the desired size of the timeline in byte units.
94 // Returns the size rounded up to a power-of-2, plus the constant size overhead for indices.
Glenn Kasten11d8dfc2013-01-14 14:53:13 -080095 static size_t sharedSize(size_t size);
96
97#if 0
98private:
99 friend class Writer;
100 friend class Reader;
101
102 const size_t mSize; // circular buffer size in bytes, must be a power of 2
103 bool mOwn; // whether I own the memory at mShared
104 Shared* const mShared; // pointer to shared memory
105#endif
106};
107
108// ---------------------------------------------------------------------------
109
110// Writer is thread-safe with respect to Reader, but not with respect to multiple threads
111// calling Writer methods. If you need multi-thread safety for writing, use LockedWriter.
112class Writer : public RefBase {
113public:
114 Writer(); // dummy nop implementation without shared memory
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700115
116 // Input parameter 'size' is the desired size of the timeline in byte units.
117 // The size of the shared memory must be at least Timeline::sharedSize(size).
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800118 Writer(size_t size, void *shared);
119 Writer(size_t size, const sp<IMemory>& iMemory);
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700120
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800121 virtual ~Writer() { }
122
123 virtual void log(const char *string);
Glenn Kastenab7d72f2013-02-27 09:05:28 -0800124 virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800125 virtual void logvf(const char *fmt, va_list ap);
126 virtual void logTimestamp();
127 virtual void logTimestamp(const struct timespec& ts);
128
129 virtual bool isEnabled() const;
130
131 // return value for all of these is the previous isEnabled()
132 virtual bool setEnabled(bool enabled); // but won't enable if no shared memory
133 bool enable() { return setEnabled(true); }
134 bool disable() { return setEnabled(false); }
135
136 sp<IMemory> getIMemory() const { return mIMemory; }
137
138private:
139 void log(Event event, const void *data, size_t length);
140 void log(const Entry *entry, bool trusted = false);
141
142 const size_t mSize; // circular buffer size in bytes, must be a power of 2
143 Shared* const mShared; // raw pointer to shared memory
144 const sp<IMemory> mIMemory; // ref-counted version
145 int32_t mRear; // my private copy of mShared->mRear
146 bool mEnabled; // whether to actually log
147};
148
149// ---------------------------------------------------------------------------
150
151// Similar to Writer, but safe for multiple threads to call concurrently
152class LockedWriter : public Writer {
153public:
154 LockedWriter();
155 LockedWriter(size_t size, void *shared);
156
157 virtual void log(const char *string);
Glenn Kastenab7d72f2013-02-27 09:05:28 -0800158 virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800159 virtual void logvf(const char *fmt, va_list ap);
160 virtual void logTimestamp();
161 virtual void logTimestamp(const struct timespec& ts);
162
163 virtual bool isEnabled() const;
164 virtual bool setEnabled(bool enabled);
165
166private:
167 mutable Mutex mLock;
168};
169
170// ---------------------------------------------------------------------------
171
172class Reader : public RefBase {
173public:
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700174
175 // Input parameter 'size' is the desired size of the timeline in byte units.
176 // The size of the shared memory must be at least Timeline::sharedSize(size).
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800177 Reader(size_t size, const void *shared);
178 Reader(size_t size, const sp<IMemory>& iMemory);
Glenn Kastenfb1fdc92013-07-10 17:03:19 -0700179
Glenn Kasten11d8dfc2013-01-14 14:53:13 -0800180 virtual ~Reader() { }
181
182 void dump(int fd, size_t indent = 0);
183 bool isIMemory(const sp<IMemory>& iMemory) const;
184
185private:
186 const size_t mSize; // circular buffer size in bytes, must be a power of 2
187 const Shared* const mShared; // raw pointer to shared memory
188 const sp<IMemory> mIMemory; // ref-counted version
189 int32_t mFront; // index of oldest acknowledged Entry
190
191 static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
192};
193
194}; // class NBLog
195
196} // namespace android
197
198#endif // ANDROID_MEDIA_NBLOG_H