blob: 8fc417f9f2f9c050f7de2bb1a68dddabb2c30316 [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
93 static size_t sharedSize(size_t size);
94
95#if 0
96private:
97 friend class Writer;
98 friend class Reader;
99
100 const size_t mSize; // circular buffer size in bytes, must be a power of 2
101 bool mOwn; // whether I own the memory at mShared
102 Shared* const mShared; // pointer to shared memory
103#endif
104};
105
106// ---------------------------------------------------------------------------
107
108// Writer is thread-safe with respect to Reader, but not with respect to multiple threads
109// calling Writer methods. If you need multi-thread safety for writing, use LockedWriter.
110class Writer : public RefBase {
111public:
112 Writer(); // dummy nop implementation without shared memory
113 Writer(size_t size, void *shared);
114 Writer(size_t size, const sp<IMemory>& iMemory);
115 virtual ~Writer() { }
116
117 virtual void log(const char *string);
118 virtual void logf(const char *fmt, ...);
119 virtual void logvf(const char *fmt, va_list ap);
120 virtual void logTimestamp();
121 virtual void logTimestamp(const struct timespec& ts);
122
123 virtual bool isEnabled() const;
124
125 // return value for all of these is the previous isEnabled()
126 virtual bool setEnabled(bool enabled); // but won't enable if no shared memory
127 bool enable() { return setEnabled(true); }
128 bool disable() { return setEnabled(false); }
129
130 sp<IMemory> getIMemory() const { return mIMemory; }
131
132private:
133 void log(Event event, const void *data, size_t length);
134 void log(const Entry *entry, bool trusted = false);
135
136 const size_t mSize; // circular buffer size in bytes, must be a power of 2
137 Shared* const mShared; // raw pointer to shared memory
138 const sp<IMemory> mIMemory; // ref-counted version
139 int32_t mRear; // my private copy of mShared->mRear
140 bool mEnabled; // whether to actually log
141};
142
143// ---------------------------------------------------------------------------
144
145// Similar to Writer, but safe for multiple threads to call concurrently
146class LockedWriter : public Writer {
147public:
148 LockedWriter();
149 LockedWriter(size_t size, void *shared);
150
151 virtual void log(const char *string);
152 virtual void logf(const char *fmt, ...);
153 virtual void logvf(const char *fmt, va_list ap);
154 virtual void logTimestamp();
155 virtual void logTimestamp(const struct timespec& ts);
156
157 virtual bool isEnabled() const;
158 virtual bool setEnabled(bool enabled);
159
160private:
161 mutable Mutex mLock;
162};
163
164// ---------------------------------------------------------------------------
165
166class Reader : public RefBase {
167public:
168 Reader(size_t size, const void *shared);
169 Reader(size_t size, const sp<IMemory>& iMemory);
170 virtual ~Reader() { }
171
172 void dump(int fd, size_t indent = 0);
173 bool isIMemory(const sp<IMemory>& iMemory) const;
174
175private:
176 const size_t mSize; // circular buffer size in bytes, must be a power of 2
177 const Shared* const mShared; // raw pointer to shared memory
178 const sp<IMemory> mIMemory; // ref-counted version
179 int32_t mFront; // index of oldest acknowledged Entry
180
181 static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
182};
183
184}; // class NBLog
185
186} // namespace android
187
188#endif // ANDROID_MEDIA_NBLOG_H