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