NBLog.h revision dcdfaecc1fa630a799e1fdb508a9b92da55abc36
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// * author entry of the thread that generated it (optional, present in merged log) 6340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// * TIMESTAMP entry 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: 92cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet iterator(const uint8_t *entry); 93cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet iterator(const iterator &other); 94cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 95cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet // dereference underlying entry 96cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet const entry& operator*() const; 97cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet const entry* operator->() const; 98cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet // advance to next entry 99cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet iterator& operator++(); // ++i 100cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet // back to previous entry 101cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet iterator& operator--(); // --i 102cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet bool operator!=(const iterator &other) const; 103cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet int operator-(const iterator &other) const; 104cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 105cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet bool hasConsistentLength() const; 106cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet void copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst) const; 107cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet void copyData(uint8_t *dst) const; 108cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 109cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet template<typename T> 110cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet inline const T& payload() { 111dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet return *reinterpret_cast<const T *>(ptr + offsetof(entry, data)); 112cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet } 113cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 114cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet private: 115cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet friend class FormatEntry; 116cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet const uint8_t *ptr; 117cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet }; 11840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 11940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // Entry's format string 120cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet const char* formatString() const; 12140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 12240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // Enrty's format string length 123cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet size_t formatStringLength() const; 12440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 12540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // Format arguments (excluding format string, timestamp and author) 126cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet iterator args() const; 12740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 12840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // get format entry timestamp 129cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet timespec timestamp() const; 13040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 13140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // entry's author index (-1 if none present) 132cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet // a Merger has a vector of Readers, author simply points to the index of the 133cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet // Reader that originated the entry 134cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet int author() const; 13540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 13640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // copy entry, adding author before timestamp, returns size of original entry 137cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet size_t copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const; 138cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 139cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet iterator begin() const; 140cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 14140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletprivate: 14240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // copies ordinary entry from src to dst, and returns length of entry 143cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet // size_t copyEntry(audio_utils_fifo_writer *dst, const iterator &it); 14440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet const uint8_t *mEntry; 14540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet}; 14640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 147cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet// --------------------------------------------------------------------------- 148cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 149cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet// representation of a single log entry in private memory 150cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Rouletstruct Entry { 151cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet Entry(Event event, const void *data, size_t length) 152cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet : mEvent(event), mLength(length), mData(data) { } 153cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet /*virtual*/ ~Entry() { } 154cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 155cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet int readAt(size_t offset) const; 156cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 157cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Rouletprivate: 158cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet friend class Writer; 159cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet Event mEvent; // event type 160cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet uint8_t mLength; // length of additional data, 0 <= mLength <= kMaxLength 161cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet const void *mData; // event type-specific data 162cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet static const size_t kMaxLength = 255; 163cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Rouletpublic: 164cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet // mEvent, mLength, mData[...], duplicate mLength 165cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet static const size_t kOverhead = sizeof(FormatEntry::entry) + sizeof(FormatEntry::ending); 166cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet // endind length of previous entry 167cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet static const size_t kPreviousLengthOffset = - sizeof(FormatEntry::ending) + 168cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet offsetof(FormatEntry::ending, length); 169cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet}; 170cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 17111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// representation of a single log entry in shared memory 17211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[0] mEvent 17311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[1] mLength 17411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[2] mData[0] 17511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ... 17611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[2+i] mData[i] 17711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ... 17811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[2+mLength-1] mData[mLength-1] 17911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[2+mLength] duplicate copy of mLength to permit reverse scan 18011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[3+mLength] start of next log entry 18111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 182fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet static void appendInt(String8 *body, const void *data); 183fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet static void appendFloat(String8 *body, const void *data); 184c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet static void appendPID(String8 *body, const void *data, size_t length); 185fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet static void appendTimestamp(String8 *body, const void *data); 18640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet static size_t fmtEntryLength(const uint8_t *data); 187fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 188535e161e2e404dffb8389dd331be0132704b6d82Glenn Kastenpublic: 189535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten 190535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten// Located in shared memory, must be POD. 191535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten// Exactly one process must explicitly call the constructor or use placement new. 192535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten// Since this is a POD, the destructor is empty and unnecessary to call it explicitly. 19311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenstruct Shared { 194535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten Shared() /* mRear initialized via default constructor */ { } 19511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten /*virtual*/ ~Shared() { } 19611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 197535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten audio_utils_fifo_index mRear; // index one byte past the end of most recent Entry 198535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten char mBuffer[0]; // circular buffer for entries 19911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 20011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 20111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic: 20211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 20311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 20411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 20511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// FIXME Timeline was intended to wrap Writer and Reader, but isn't actually used yet. 20611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// For now it is just a namespace for sharedSize(). 20711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Timeline : public RefBase { 20811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic: 20911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#if 0 21011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Timeline(size_t size, void *shared = NULL); 21111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual ~Timeline(); 21211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif 21311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 214fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // Input parameter 'size' is the desired size of the timeline in byte units. 215fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // Returns the size rounded up to a power-of-2, plus the constant size overhead for indices. 21611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten static size_t sharedSize(size_t size); 21711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 21811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#if 0 21911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate: 22011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten friend class Writer; 22111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten friend class Reader; 22211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 22311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten const size_t mSize; // circular buffer size in bytes, must be a power of 2 22411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten bool mOwn; // whether I own the memory at mShared 22511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Shared* const mShared; // pointer to shared memory 22611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif 22711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 22811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 22911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 23011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 23111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// Writer is thread-safe with respect to Reader, but not with respect to multiple threads 23211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// calling Writer methods. If you need multi-thread safety for writing, use LockedWriter. 23311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Writer : public RefBase { 23411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic: 23511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Writer(); // dummy nop implementation without shared memory 236fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten 237fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // Input parameter 'size' is the desired size of the timeline in byte units. 238fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // The size of the shared memory must be at least Timeline::sharedSize(size). 239535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten Writer(void *shared, size_t size); 240535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten Writer(const sp<IMemory>& iMemory, size_t size); 241fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten 242535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten virtual ~Writer(); 24311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 24411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void log(const char *string); 245ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); 24611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void logvf(const char *fmt, va_list ap); 24711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void logTimestamp(); 248fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logTimestamp(const struct timespec &ts); 249fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logInteger(const int x); 250fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logFloat(const float x); 251fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logPID(); 252fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logFormat(const char *fmt, ...); 253fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logVFormat(const char *fmt, va_list ap); 254fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logStart(const char *fmt); 255fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logEnd(); 256fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 25711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 25811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual bool isEnabled() const; 25911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 26011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten // return value for all of these is the previous isEnabled() 26111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual bool setEnabled(bool enabled); // but won't enable if no shared memory 26211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten bool enable() { return setEnabled(true); } 26311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten bool disable() { return setEnabled(false); } 26411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 26511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten sp<IMemory> getIMemory() const { return mIMemory; } 26611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 26711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate: 268535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten // 0 <= length <= kMaxLength 26911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten void log(Event event, const void *data, size_t length); 27011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten void log(const Entry *entry, bool trusted = false); 27111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 27211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Shared* const mShared; // raw pointer to shared memory 273535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten sp<IMemory> mIMemory; // ref-counted version, initialized in constructor and then const 274535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten audio_utils_fifo * const mFifo; // FIFO itself, 275535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten // non-NULL unless constructor fails 276535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten audio_utils_fifo_writer * const mFifoWriter; // used to write to FIFO, 277535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten // non-NULL unless dummy constructor used 27811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten bool mEnabled; // whether to actually log 279c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet 280c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet // cached pid and process name to use in %p format specifier 281c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet // total tag length is mPidTagSize and process name is not zero terminated 282c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet char *mPidTag; 283c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet size_t mPidTagSize; 28411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 28511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 28611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 28711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 28811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// Similar to Writer, but safe for multiple threads to call concurrently 28911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass LockedWriter : public Writer { 29011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic: 29111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten LockedWriter(); 292535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten LockedWriter(void *shared, size_t size); 29311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 29411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void log(const char *string); 295ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); 29611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void logvf(const char *fmt, va_list ap); 29711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void logTimestamp(); 298fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logTimestamp(const struct timespec &ts); 299fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logInteger(const int x); 300fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logFloat(const float x); 301fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logPID(); 302fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logStart(const char *fmt); 303fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet virtual void logEnd(); 30411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 30511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual bool isEnabled() const; 30611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual bool setEnabled(bool enabled); 30711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 30811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate: 30911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten mutable Mutex mLock; 31011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 31111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 31211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 31311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 31411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Reader : public RefBase { 31511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic: 316fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten 31740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // A snapshot of a readers buffer 31840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet class Snapshot { 31940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet public: 32040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet Snapshot() : mData(NULL), mAvail(0), mLost(0) {} 32140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 32240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet Snapshot(size_t bufferSize) : mData(new uint8_t[bufferSize]) {} 32340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 32440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet ~Snapshot() { delete[] mData; } 32540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 32640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // copy of the buffer 32740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet const uint8_t *data() const { return mData; } 32840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 32940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // amount of data available (given by audio_utils_fifo_reader) 33040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet size_t available() const { return mAvail; } 33140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 33240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // amount of data lost (given by audio_utils_fifo_reader) 33340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet size_t lost() const { return mLost; } 33440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 33540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet private: 33640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet friend class Reader; 33740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet const uint8_t *mData; 33840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet size_t mAvail; 33940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet size_t mLost; 34040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet }; 34140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 342fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // Input parameter 'size' is the desired size of the timeline in byte units. 343fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // The size of the shared memory must be at least Timeline::sharedSize(size). 344535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten Reader(const void *shared, size_t size); 345535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten Reader(const sp<IMemory>& iMemory, size_t size); 346fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten 347535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten virtual ~Reader(); 34811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 34940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // get snapshot of readers fifo buffer, effectively consuming the buffer 35040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet std::unique_ptr<Snapshot> getSnapshot(); 35140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // dump a particular snapshot of the reader 35240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet void dump(int fd, size_t indent, Snapshot & snap); 35340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // dump the current content of the reader's buffer 35440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet void dump(int fd, size_t indent = 0); 35540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet bool isIMemory(const sp<IMemory>& iMemory) const; 35611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 35711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate: 358535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten /*const*/ Shared* const mShared; // raw pointer to shared memory, actually const but not 359535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten // declared as const because audio_utils_fifo() constructor 360535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten sp<IMemory> mIMemory; // ref-counted version, assigned only in constructor 3614e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten int mFd; // file descriptor 3624e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten int mIndent; // indentation level 363535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten audio_utils_fifo * const mFifo; // FIFO itself, 364535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten // non-NULL unless constructor fails 365535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten audio_utils_fifo_reader * const mFifoReader; // used to read from FIFO, 366535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten // non-NULL unless constructor fails 3674e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten 3684e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten void dumpLine(const String8& timestamp, String8& body); 369cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 370cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet FormatEntry::iterator handleFormat(const FormatEntry &fmtEntry, 371cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet String8 *timestamp, 372cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet String8 *body); 37340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // dummy method for handling absent author entry 37440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet virtual size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body) { return 0; } 37511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 37611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps 37711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 37811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 37940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// Wrapper for a reader with a name. Contains a pointer to the reader and a pointer to the name 38040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletclass NamedReader { 38140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletpublic: 38240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet NamedReader() { mName[0] = '\0'; } // for Vector 38340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet NamedReader(const sp<NBLog::Reader>& reader, const char *name) : 38440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet mReader(reader) 38540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet { strlcpy(mName, name, sizeof(mName)); } 38640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet ~NamedReader() { } 38740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet const sp<NBLog::Reader>& reader() const { return mReader; } 38840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet const char* name() const { return mName; } 38940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 39040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletprivate: 39140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet sp<NBLog::Reader> mReader; 39240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet static const size_t kMaxName = 32; 39340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet char mName[kMaxName]; 39440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet}; 39540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 39640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// --------------------------------------------------------------------------- 39740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 39840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletclass Merger : public RefBase { 39940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletpublic: 40040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet Merger(const void *shared, size_t size); 40140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 40240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet virtual ~Merger() {} 40340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 40440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet void addReader(const NamedReader &reader); 40540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // TODO add removeReader 40640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet void merge(); 40740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet const std::vector<NamedReader> *getNamedReaders() const; 40840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletprivate: 40940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // vector of the readers the merger is supposed to merge from. 41040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // every reader reads from a writer's buffer 41140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet std::vector<NamedReader> mNamedReaders; 41240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet uint8_t *mBuffer; 41340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet Shared * const mShared; 41440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet std::unique_ptr<audio_utils_fifo> mFifo; 41540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet std::unique_ptr<audio_utils_fifo_writer> mFifoWriter; 41640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 41740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet static struct timespec getTimestamp(const uint8_t *data); 41840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet}; 41940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 42040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletclass MergeReader : public Reader { 42140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletpublic: 42240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet MergeReader(const void *shared, size_t size, Merger &merger); 42340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletprivate: 42440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet const std::vector<NamedReader> *mNamedReaders; 42540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // handle author entry by looking up the author's name and appending it to the body 42640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // returns number of bytes read from fmtEntry 42740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body); 42840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet}; 42940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 430dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet// MergeThread is a thread that contains a Merger. It works as a retriggerable one-shot: 431dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet// when triggered, it awakes for a lapse of time, during which it periodically merges; if 432dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet// retriggered, the timeout is reset. 433dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet// The thread is triggered on AudioFlinger binder activity. 434dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Rouletclass MergeThread : public Thread { 435dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Rouletpublic: 436dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet MergeThread(Merger &merger); 437dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet virtual ~MergeThread() override; 438dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 439dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet // Reset timeout and activate thread to merge periodically if it's idle 440dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet void wakeup(); 441dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 442dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet // Set timeout period until the merging thread goes idle again 443dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet void setTimeoutUs(int time); 444dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 445dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Rouletprivate: 446dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet virtual bool threadLoop() override; 447dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 448dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet // the merger who actually does the work of merging the logs 449dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet Merger& mMerger; 450dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 451dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet // mutex for the condition variable 452dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet Mutex mMutex; 453dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 454dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet // condition variable to activate merging on timeout >= 0 455dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet Condition mCond; 456dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 457dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet // time left until the thread blocks again (in microseconds) 458dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet int mTimeoutUs; 459dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 460dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet // merging period when the thread is awake 461dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet static const int kThreadSleepPeriodUs = 1000000 /*1s*/; 462dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 463dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet // initial timeout value when triggered 464dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet static const int kThreadWakeupPeriodUs = 3000000 /*3s*/; 465dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet}; 466dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 46711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; // class NBLog 46811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 46911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} // namespace android 47011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 47111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif // ANDROID_MEDIA_NBLOG_H 472