111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten/*
211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * Copyright (C) 2013 The Android Open Source Project
311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten *
411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * you may not use this file except in compliance with the License.
611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * You may obtain a copy of the License at
711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten *
811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten *
1011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * Unless required by applicable law or agreed to in writing, software
1111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
1211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * See the License for the specific language governing permissions and
1411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * limitations under the License.
1511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten */
1611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
1711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// Non-blocking event logger intended for safe communication between processes via shared memory
1811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
1911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#ifndef ANDROID_MEDIA_NBLOG_H
2011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#define ANDROID_MEDIA_NBLOG_H
2111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
2211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#include <binder/IMemory.h>
23535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten#include <audio_utils/fifo.h>
24dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet#include <utils/Mutex.h>
25dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet#include <utils/threads.h>
2611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
2740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet#include <vector>
2840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
2911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastennamespace android {
3011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
314e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kastenclass String8;
324e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten
3311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass NBLog {
3411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
3511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
3611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
3711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Writer;
3811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Reader;
3911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
4011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate:
4111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
4211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenenum Event {
4311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    EVENT_RESERVED,
4411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    EVENT_STRING,               // ASCII string, not NUL-terminated
45dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    // TODO: make timestamp optional
4611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    EVENT_TIMESTAMP,            // clock_gettime(CLOCK_MONOTONIC)
4740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    EVENT_INTEGER,              // integer value entry
4840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    EVENT_FLOAT,                // floating point value entry
4940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    EVENT_PID,                  // process ID and process name
5040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    EVENT_AUTHOR,               // author index (present in merged logs) tracks entry's original log
51fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    EVENT_START_FMT,            // logFormat start event: entry includes format string, following
52fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet                                // entries contain format arguments
53fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    EVENT_END_FMT,              // end of logFormat argument list
5411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
5511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
5611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
5740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// ---------------------------------------------------------------------------
5840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// API for handling format entry operations
5940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
6040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// a formatted entry has the following structure:
6140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet//    * START_FMT entry, containing the format string
6240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet//    * TIMESTAMP entry
631ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet//    * author entry of the thread that generated it (optional, present in merged log)
6440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet//    * format arg1
6540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet//    * format arg2
6640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet//    * ...
6740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet//    * END_FMT entry
6840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
6940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletclass FormatEntry {
7040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletpublic:
7140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // build a Format Entry starting in the given pointer
72cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    class iterator;
7340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    explicit FormatEntry(const uint8_t *entry);
74cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    explicit FormatEntry(const iterator &it);
75cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
76cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    // entry representation in memory
77cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    struct entry {
78cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        const uint8_t type;
79cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        const uint8_t length;
80cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        const uint8_t data[0];
81cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    };
82cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
83cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    // entry tail representation (after data)
84cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    struct ending {
85cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        uint8_t length;
86cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        uint8_t next[0];
87cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    };
88cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
89cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    // entry iterator
90cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    class iterator {
91cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    public:
926ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        iterator();
93cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        iterator(const uint8_t *entry);
94cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        iterator(const iterator &other);
95cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
96cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        // dereference underlying entry
97cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        const entry&    operator*() const;
98cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        const entry*    operator->() const;
99cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        // advance to next entry
100cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        iterator&       operator++(); // ++i
101cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        // back to previous entry
102cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        iterator&       operator--(); // --i
1036ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        iterator        next() const;
1046ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        iterator        prev() const;
105cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        bool            operator!=(const iterator &other) const;
106cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        int             operator-(const iterator &other) const;
107cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
108cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        bool            hasConsistentLength() const;
109cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        void            copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst) const;
110cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        void            copyData(uint8_t *dst) const;
111cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
112cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        template<typename T>
113cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        inline const T& payload() {
114dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet            return *reinterpret_cast<const T *>(ptr + offsetof(entry, data));
115cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        }
116cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
117cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    private:
118cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        friend class FormatEntry;
119cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        const uint8_t  *ptr;
120cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    };
12140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
12240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // Entry's format string
123cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    const char* formatString() const;
12440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
12540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // Enrty's format string length
126cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    size_t      formatStringLength() const;
12740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
12840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // Format arguments (excluding format string, timestamp and author)
129cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    iterator    args() const;
13040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
13140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // get format entry timestamp
132cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    timespec    timestamp() const;
13340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
13440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // entry's author index (-1 if none present)
135cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    // a Merger has a vector of Readers, author simply points to the index of the
136cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    // Reader that originated the entry
137cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    int         author() const;
13840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
13940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // copy entry, adding author before timestamp, returns size of original entry
1406ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet    iterator    copyWithAuthor(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const;
141cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
142cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    iterator    begin() const;
143cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
14440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletprivate:
14540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // copies ordinary entry from src to dst, and returns length of entry
146cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    // size_t      copyEntry(audio_utils_fifo_writer *dst, const iterator &it);
14740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    const uint8_t  *mEntry;
14840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet};
14940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
150cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet// ---------------------------------------------------------------------------
151cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
152cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet// representation of a single log entry in private memory
153cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Rouletstruct Entry {
154cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    Entry(Event event, const void *data, size_t length)
155cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet        : mEvent(event), mLength(length), mData(data) { }
156cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    /*virtual*/ ~Entry() { }
157cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
158cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    int     readAt(size_t offset) const;
159cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
160cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Rouletprivate:
161cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    friend class Writer;
162cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    Event       mEvent;     // event type
163cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    uint8_t     mLength;    // length of additional data, 0 <= mLength <= kMaxLength
164cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    const void *mData;      // event type-specific data
165cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    static const size_t kMaxLength = 255;
166cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Rouletpublic:
167cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    // mEvent, mLength, mData[...], duplicate mLength
168cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    static const size_t kOverhead = sizeof(FormatEntry::entry) + sizeof(FormatEntry::ending);
169cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    // endind length of previous entry
170cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    static const size_t kPreviousLengthOffset = - sizeof(FormatEntry::ending) +
171cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet                                                offsetof(FormatEntry::ending, length);
172cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet};
173cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
17411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// representation of a single log entry in shared memory
17511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[0]             mEvent
17611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[1]             mLength
17711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[2]             mData[0]
17811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  ...
17911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[2+i]           mData[i]
18011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  ...
18111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[2+mLength-1]   mData[mLength-1]
18211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[2+mLength]     duplicate copy of mLength to permit reverse scan
18311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[3+mLength]     start of next log entry
18411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
185fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    static void    appendInt(String8 *body, const void *data);
186fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    static void    appendFloat(String8 *body, const void *data);
187c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet    static void    appendPID(String8 *body, const void *data, size_t length);
188fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    static void    appendTimestamp(String8 *body, const void *data);
18940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    static size_t  fmtEntryLength(const uint8_t *data);
190fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet
191535e161e2e404dffb8389dd331be0132704b6d82Glenn Kastenpublic:
192535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten
193535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten// Located in shared memory, must be POD.
194535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten// Exactly one process must explicitly call the constructor or use placement new.
195535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten// Since this is a POD, the destructor is empty and unnecessary to call it explicitly.
19611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenstruct Shared {
197535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    Shared() /* mRear initialized via default constructor */ { }
19811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    /*virtual*/ ~Shared() { }
19911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
200535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    audio_utils_fifo_index  mRear;  // index one byte past the end of most recent Entry
201535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    char    mBuffer[0];             // circular buffer for entries
20211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
20311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
20411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
20511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
20611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ---------------------------------------------------------------------------
20711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
20811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// FIXME Timeline was intended to wrap Writer and Reader, but isn't actually used yet.
20911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// For now it is just a namespace for sharedSize().
21011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Timeline : public RefBase {
21111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
21211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#if 0
21311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Timeline(size_t size, void *shared = NULL);
21411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual ~Timeline();
21511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif
21611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
217fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten    // Input parameter 'size' is the desired size of the timeline in byte units.
218fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten    // Returns the size rounded up to a power-of-2, plus the constant size overhead for indices.
21911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    static size_t sharedSize(size_t size);
22011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
22111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#if 0
22211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate:
22311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    friend class    Writer;
22411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    friend class    Reader;
22511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
22611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
22711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    bool            mOwn;       // whether I own the memory at mShared
22811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Shared* const   mShared;    // pointer to shared memory
22911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif
23011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
23111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
23211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ---------------------------------------------------------------------------
23311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
23411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// Writer is thread-safe with respect to Reader, but not with respect to multiple threads
23511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// calling Writer methods.  If you need multi-thread safety for writing, use LockedWriter.
23611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Writer : public RefBase {
23711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
23811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Writer();                   // dummy nop implementation without shared memory
239fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten
240fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten    // Input parameter 'size' is the desired size of the timeline in byte units.
241fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten    // The size of the shared memory must be at least Timeline::sharedSize(size).
242535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    Writer(void *shared, size_t size);
243535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    Writer(const sp<IMemory>& iMemory, size_t size);
244fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten
245535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    virtual ~Writer();
24611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
24711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    log(const char *string);
248ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten    virtual void    logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
24911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logvf(const char *fmt, va_list ap);
25011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logTimestamp();
251fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logTimestamp(const struct timespec &ts);
252fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logInteger(const int x);
253fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logFloat(const float x);
254fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logPID();
255fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logFormat(const char *fmt, ...);
256fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logVFormat(const char *fmt, va_list ap);
257fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logStart(const char *fmt);
258fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logEnd();
259fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet
26011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
26111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual bool    isEnabled() const;
26211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
26311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    // return value for all of these is the previous isEnabled()
26411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual bool    setEnabled(bool enabled);   // but won't enable if no shared memory
26511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten            bool    enable()    { return setEnabled(true); }
26611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten            bool    disable()   { return setEnabled(false); }
26711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
26811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    sp<IMemory>     getIMemory() const  { return mIMemory; }
26911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
27011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate:
271535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    // 0 <= length <= kMaxLength
27211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    void    log(Event event, const void *data, size_t length);
27311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    void    log(const Entry *entry, bool trusted = false);
27411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
27511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Shared* const   mShared;    // raw pointer to shared memory
276535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    sp<IMemory>     mIMemory;   // ref-counted version, initialized in constructor and then const
277535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    audio_utils_fifo * const mFifo;                 // FIFO itself,
278535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten                                                    // non-NULL unless constructor fails
279535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    audio_utils_fifo_writer * const mFifoWriter;    // used to write to FIFO,
280535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten                                                    // non-NULL unless dummy constructor used
28111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    bool            mEnabled;   // whether to actually log
282c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet
283c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet    // cached pid and process name to use in %p format specifier
284c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet    // total tag length is mPidTagSize and process name is not zero terminated
285c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet    char   *mPidTag;
286c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet    size_t  mPidTagSize;
28711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
28811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
28911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ---------------------------------------------------------------------------
29011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
29111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// Similar to Writer, but safe for multiple threads to call concurrently
29211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass LockedWriter : public Writer {
29311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
29411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    LockedWriter();
295535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    LockedWriter(void *shared, size_t size);
29611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
29711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    log(const char *string);
298ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten    virtual void    logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
29911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logvf(const char *fmt, va_list ap);
30011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logTimestamp();
301fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logTimestamp(const struct timespec &ts);
302fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logInteger(const int x);
303fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logFloat(const float x);
304fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logPID();
305fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logStart(const char *fmt);
306fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet    virtual void    logEnd();
30711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
30811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual bool    isEnabled() const;
30911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual bool    setEnabled(bool enabled);
31011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
31111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate:
31211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    mutable Mutex   mLock;
31311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
31411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
31511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ---------------------------------------------------------------------------
31611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
31711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Reader : public RefBase {
31811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
319fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten
32040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // A snapshot of a readers buffer
32140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    class Snapshot {
32240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    public:
3236ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        Snapshot() : mData(NULL), mLost(0) {}
32440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
32540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet        Snapshot(size_t bufferSize) : mData(new uint8_t[bufferSize]) {}
32640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
32740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet        ~Snapshot() { delete[] mData; }
32840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
32940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet        // copy of the buffer
3306ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        uint8_t *data() const { return mData; }
33140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
33240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet        // amount of data lost (given by audio_utils_fifo_reader)
33340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet        size_t   lost() const { return mLost; }
33440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
3356ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        // iterator to beginning of readable segment of snapshot
3366ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        // data between begin and end has valid entries
3376ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        FormatEntry::iterator begin() { return mBegin; }
3386ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet
3396ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        // iterator to end of readable segment of snapshot
3406ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        FormatEntry::iterator end() { return mEnd; }
3416ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet
3426ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet
34340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    private:
34440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet        friend class Reader;
3456ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        uint8_t              *mData;
3466ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        size_t                mLost;
3476ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        FormatEntry::iterator mBegin;
3486ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet        FormatEntry::iterator mEnd;
34940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    };
35040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
351fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten    // Input parameter 'size' is the desired size of the timeline in byte units.
352fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten    // The size of the shared memory must be at least Timeline::sharedSize(size).
353535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    Reader(const void *shared, size_t size);
354535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    Reader(const sp<IMemory>& iMemory, size_t size);
355fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten
356535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    virtual ~Reader();
35711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
35840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // get snapshot of readers fifo buffer, effectively consuming the buffer
35940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    std::unique_ptr<Snapshot> getSnapshot();
36040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // dump a particular snapshot of the reader
36140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    void     dump(int fd, size_t indent, Snapshot & snap);
36240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // dump the current content of the reader's buffer
36340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    void     dump(int fd, size_t indent = 0);
36440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    bool     isIMemory(const sp<IMemory>& iMemory) const;
36511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
36611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate:
367535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    /*const*/ Shared* const mShared;    // raw pointer to shared memory, actually const but not
368535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten                                        // declared as const because audio_utils_fifo() constructor
369535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    sp<IMemory> mIMemory;       // ref-counted version, assigned only in constructor
3704e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten    int     mFd;                // file descriptor
3714e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten    int     mIndent;            // indentation level
372535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    audio_utils_fifo * const mFifo;                 // FIFO itself,
373535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten                                                    // non-NULL unless constructor fails
374535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten    audio_utils_fifo_reader * const mFifoReader;    // used to read from FIFO,
375535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten                                                    // non-NULL unless constructor fails
3764e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten
3774e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten    void    dumpLine(const String8& timestamp, String8& body);
378cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet
379cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet    FormatEntry::iterator   handleFormat(const FormatEntry &fmtEntry,
380cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet                                         String8 *timestamp,
381cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet                                         String8 *body);
38240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // dummy method for handling absent author entry
38340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    virtual size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body) { return 0; }
38411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
3856ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet    // Searches for the last entry of type <type> in the range [front, back)
3866ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet    // back has to be entry-aligned. Returns nullptr if none enconuntered.
3876ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet    static uint8_t *findLastEntryOfType(uint8_t *front, uint8_t *back, uint8_t type);
3886ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet
38911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
39011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
39111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
39240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// Wrapper for a reader with a name. Contains a pointer to the reader and a pointer to the name
39340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletclass NamedReader {
39440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletpublic:
39540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    NamedReader() { mName[0] = '\0'; } // for Vector
39640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    NamedReader(const sp<NBLog::Reader>& reader, const char *name) :
39740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet        mReader(reader)
39840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet        { strlcpy(mName, name, sizeof(mName)); }
39940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    ~NamedReader() { }
40040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    const sp<NBLog::Reader>&  reader() const { return mReader; }
40140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    const char*               name() const { return mName; }
40240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
40340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletprivate:
40440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    sp<NBLog::Reader>   mReader;
40540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    static const size_t kMaxName = 32;
40640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    char                mName[kMaxName];
40740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet};
40840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
40940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// ---------------------------------------------------------------------------
41040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
41140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletclass Merger : public RefBase {
41240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletpublic:
41340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    Merger(const void *shared, size_t size);
41440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
41540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    virtual ~Merger() {}
41640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
41740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    void addReader(const NamedReader &reader);
41840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // TODO add removeReader
41940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    void merge();
42040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    const std::vector<NamedReader> *getNamedReaders() const;
42140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletprivate:
42240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // vector of the readers the merger is supposed to merge from.
42340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // every reader reads from a writer's buffer
42440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    std::vector<NamedReader> mNamedReaders;
42540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    uint8_t *mBuffer;
42640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    Shared * const mShared;
42740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    std::unique_ptr<audio_utils_fifo> mFifo;
42840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    std::unique_ptr<audio_utils_fifo_writer> mFifoWriter;
42940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
43040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    static struct timespec getTimestamp(const uint8_t *data);
43140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet};
43240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
43340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletclass MergeReader : public Reader {
43440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletpublic:
43540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    MergeReader(const void *shared, size_t size, Merger &merger);
43640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletprivate:
43740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    const std::vector<NamedReader> *mNamedReaders;
43840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // handle author entry by looking up the author's name and appending it to the body
43940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    // returns number of bytes read from fmtEntry
44040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet    size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body);
44140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet};
44240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet
443dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet// MergeThread is a thread that contains a Merger. It works as a retriggerable one-shot:
444dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet// when triggered, it awakes for a lapse of time, during which it periodically merges; if
445dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet// retriggered, the timeout is reset.
446dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet// The thread is triggered on AudioFlinger binder activity.
447dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Rouletclass MergeThread : public Thread {
448dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Rouletpublic:
449dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    MergeThread(Merger &merger);
450dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    virtual ~MergeThread() override;
451dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet
452dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    // Reset timeout and activate thread to merge periodically if it's idle
453dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    void wakeup();
454dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet
455dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    // Set timeout period until the merging thread goes idle again
456dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    void setTimeoutUs(int time);
457dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet
458dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Rouletprivate:
459dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    virtual bool threadLoop() override;
460dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet
461dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    // the merger who actually does the work of merging the logs
462dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    Merger&     mMerger;
463dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet
464dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    // mutex for the condition variable
465dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    Mutex       mMutex;
466dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet
467dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    // condition variable to activate merging on timeout >= 0
468dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    Condition   mCond;
469dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet
470dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    // time left until the thread blocks again (in microseconds)
471dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    int         mTimeoutUs;
472dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet
473dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    // merging period when the thread is awake
474dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    static const int  kThreadSleepPeriodUs = 1000000 /*1s*/;
475dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet
476dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    // initial timeout value when triggered
477dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet    static const int  kThreadWakeupPeriodUs = 3000000 /*3s*/;
478dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet};
479dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet
48011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};  // class NBLog
48111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
48211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}   // namespace android
48311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
48411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif  // ANDROID_MEDIA_NBLOG_H
485