• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
26 namespace android {
27 
28 class NBLog {
29 
30 public:
31 
32 class Writer;
33 class Reader;
34 
35 private:
36 
37 enum 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
46 struct Entry {
EntryEntry47     Entry(Event event, const void *data, size_t length)
48         : mEvent(event), mLength(length), mData(data) { }
~EntryEntry49     /*virtual*/ ~Entry() { }
50 
51     int     readAt(size_t offset) const;
52 
53 private:
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
72 struct Shared {
SharedShared73     Shared() : mRear(0) { }
~SharedShared74     /*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 
80 public:
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().
86 class Timeline : public RefBase {
87 public:
88 #if 0
89     Timeline(size_t size, void *shared = NULL);
90     virtual ~Timeline();
91 #endif
92 
93     // 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.
95     static size_t sharedSize(size_t size);
96 
97 #if 0
98 private:
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.
112 class Writer : public RefBase {
113 public:
114     Writer();                   // dummy nop implementation without shared memory
115 
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).
118     Writer(size_t size, void *shared);
119     Writer(size_t size, const sp<IMemory>& iMemory);
120 
~Writer()121     virtual ~Writer() { }
122 
123     virtual void    log(const char *string);
124     virtual void    logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
125     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
enable()133             bool    enable()    { return setEnabled(true); }
disable()134             bool    disable()   { return setEnabled(false); }
135 
getIMemory()136     sp<IMemory>     getIMemory() const  { return mIMemory; }
137 
138 private:
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
152 class LockedWriter : public Writer {
153 public:
154     LockedWriter();
155     LockedWriter(size_t size, void *shared);
156 
157     virtual void    log(const char *string);
158     virtual void    logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
159     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 
166 private:
167     mutable Mutex   mLock;
168 };
169 
170 // ---------------------------------------------------------------------------
171 
172 class Reader : public RefBase {
173 public:
174 
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).
177     Reader(size_t size, const void *shared);
178     Reader(size_t size, const sp<IMemory>& iMemory);
179 
~Reader()180     virtual ~Reader() { }
181 
182     void    dump(int fd, size_t indent = 0);
183     bool    isIMemory(const sp<IMemory>& iMemory) const;
184 
185 private:
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
199