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. 1514316446402a2e4bc3daf407741e0bd021871928Sanna Catherine de Treville Wager * 1614316446402a2e4bc3daf407741e0bd021871928Sanna Catherine de Treville Wager * 1711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten */ 1811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 1911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#define LOG_TAG "NBLog" 2011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 21697a8a54a27d054efed7b47a6131a78b1388083eSanna Catherine de Treville Wager#include <algorithm> 22dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet#include <climits> 23201079a8f9ee7811c3ec5302712526428fb8de7eSanna Catherine de Treville Wager#include <deque> 24697a8a54a27d054efed7b47a6131a78b1388083eSanna Catherine de Treville Wager#include <fstream> 25697a8a54a27d054efed7b47a6131a78b1388083eSanna Catherine de Treville Wager#include <iostream> 26cced674a438191eb59b39816c79ccff6bf9c21fdSanna Catherine de Treville Wager#include <math.h> 27201079a8f9ee7811c3ec5302712526428fb8de7eSanna Catherine de Treville Wager#include <numeric> 28697a8a54a27d054efed7b47a6131a78b1388083eSanna Catherine de Treville Wager#include <vector> 2911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#include <stdarg.h> 3011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#include <stdint.h> 3111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#include <stdio.h> 3211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#include <string.h> 33c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet#include <sys/prctl.h> 3411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#include <time.h> 3511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#include <new> 36535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten#include <audio_utils/roundup.h> 378589ce7045fd4f5520aabbc773f00c7136925fd7Glenn Kasten#include <media/nblog/NBLog.h> 388589ce7045fd4f5520aabbc773f00c7136925fd7Glenn Kasten#include <media/nblog/PerformanceAnalysis.h> 398589ce7045fd4f5520aabbc773f00c7136925fd7Glenn Kasten#include <media/nblog/ReportPerformance.h> 40e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager#include <utils/CallStack.h> 4111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#include <utils/Log.h> 424e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten#include <utils/String8.h> 4311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 4440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet#include <queue> 45537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet#include <utility> 4640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 4711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastennamespace android { 4811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 492d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wagerint NBLog::Entry::copyEntryDataAt(size_t offset) const 5011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 512d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wager // FIXME This is too slow 5211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (offset == 0) 5311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return mEvent; 5411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten else if (offset == 1) 5511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return mLength; 5611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten else if (offset < (size_t) (mLength + 2)) 5711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return ((char *) mData)[offset - 2]; 5811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten else if (offset == (size_t) (mLength + 2)) 5911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return mLength; 6011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten else 6111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return 0; 6211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 6311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 6411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 6511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 66537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet/*static*/ 67537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletstd::unique_ptr<NBLog::AbstractEntry> NBLog::AbstractEntry::buildEntry(const uint8_t *ptr) { 68cced674a438191eb59b39816c79ccff6bf9c21fdSanna Catherine de Treville Wager const uint8_t type = EntryIterator(ptr)->type; 69537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet switch (type) { 70537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet case EVENT_START_FMT: 71537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet return std::make_unique<FormatEntry>(FormatEntry(ptr)); 72a8a8a47da86e181d835eab7f858d6b1d2c3a8357Sanna Catherine de Treville Wager case EVENT_AUDIO_STATE: 73537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet case EVENT_HISTOGRAM_ENTRY_TS: 74537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet return std::make_unique<HistogramEntry>(HistogramEntry(ptr)); 75537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet default: 76537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet ALOGW("Tried to create AbstractEntry of type %d", type); 77537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet return nullptr; 78537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet } 7940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 8040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 81537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::AbstractEntry::AbstractEntry(const uint8_t *entry) : mEntry(entry) { 82537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet} 83537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet 84537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet// --------------------------------------------------------------------------- 85cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 86dd92d7e37298d57be41f8ffd1bab6786cf8b74b9Sanna Catherine de Treville WagerNBLog::EntryIterator NBLog::FormatEntry::begin() const { 87dd92d7e37298d57be41f8ffd1bab6786cf8b74b9Sanna Catherine de Treville Wager return EntryIterator(mEntry); 88dd92d7e37298d57be41f8ffd1bab6786cf8b74b9Sanna Catherine de Treville Wager} 89dd92d7e37298d57be41f8ffd1bab6786cf8b74b9Sanna Catherine de Treville Wager 9040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletconst char *NBLog::FormatEntry::formatString() const { 91cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return (const char*) mEntry + offsetof(entry, data); 9240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 9340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 9440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletsize_t NBLog::FormatEntry::formatStringLength() const { 95cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return mEntry[offsetof(entry, length)]; 9640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 9740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 98537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::EntryIterator NBLog::FormatEntry::args() const { 99cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet auto it = begin(); 1001ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet // skip start fmt 1011ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet ++it; 1021ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet // skip timestamp 1031ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet ++it; 104bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet // skip hash 105bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet ++it; 1061ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet // Skip author if present 1071ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet if (it->type == EVENT_AUTHOR) { 108cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet ++it; 10940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet } 1101ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet return it; 11140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 11240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 113f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Rouletint64_t NBLog::FormatEntry::timestamp() const { 114cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet auto it = begin(); 1151ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet // skip start fmt 1161ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet ++it; 117f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet return it.payload<int64_t>(); 11840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 11940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 120bd0c6b47a93840e166f34308eb7660d81e949666Nicolas RouletNBLog::log_hash_t NBLog::FormatEntry::hash() const { 121bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet auto it = begin(); 122bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet // skip start fmt 123bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet ++it; 124bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet // skip timestamp 125bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet ++it; 126bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet // unaligned 64-bit read not supported 127bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet log_hash_t hash; 128bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet memcpy(&hash, it->data, sizeof(hash)); 129bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet return hash; 130bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet} 131bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet 132537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletint NBLog::FormatEntry::author() const { 133cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet auto it = begin(); 1341ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet // skip start fmt 1351ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet ++it; 1361ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet // skip timestamp 1371ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet ++it; 138bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet // skip hash 139bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet ++it; 1401ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet // if there is an author entry, return it, return -1 otherwise 1411ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet if (it->type == EVENT_AUTHOR) { 142cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return it.payload<int>(); 14340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet } 144cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return -1; 14540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 14640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 147537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::EntryIterator NBLog::FormatEntry::copyWithAuthor( 1486ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const { 1496ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet auto it = begin(); 15040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // copy fmt start entry 151cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet it.copyTo(dst); 1521ca75129a63a1064df311f7c33049d48ac8cdb2dNicolas Roulet // copy timestamp 1532d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wager (++it).copyTo(dst); // copy hash 154bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet (++it).copyTo(dst); 15540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // insert author entry 15640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet size_t authorEntrySize = NBLog::Entry::kOverhead + sizeof(author); 15740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet uint8_t authorEntry[authorEntrySize]; 158cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet authorEntry[offsetof(entry, type)] = EVENT_AUTHOR; 159cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet authorEntry[offsetof(entry, length)] = 160cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet authorEntry[authorEntrySize + NBLog::Entry::kPreviousLengthOffset] = 161cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet sizeof(author); 162cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet *(int*) (&authorEntry[offsetof(entry, data)]) = author; 16340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet dst->write(authorEntry, authorEntrySize); 16440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // copy rest of entries 165cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet while ((++it)->type != EVENT_END_FMT) { 166cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet it.copyTo(dst); 16740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet } 168cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet it.copyTo(dst); 169cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet ++it; 1706ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet return it; 171cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet} 172cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 173537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletvoid NBLog::EntryIterator::copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst) const { 174cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet size_t length = ptr[offsetof(entry, length)] + NBLog::Entry::kOverhead; 175cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet dst->write(ptr, length); 176cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet} 177cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 178537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletvoid NBLog::EntryIterator::copyData(uint8_t *dst) const { 179cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet memcpy((void*) dst, ptr + offsetof(entry, data), ptr[offsetof(entry, length)]); 180cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet} 181cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 182537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::EntryIterator::EntryIterator() 1836ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet : ptr(nullptr) {} 1846ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet 185537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::EntryIterator::EntryIterator(const uint8_t *entry) 186cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet : ptr(entry) {} 187cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 188537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::EntryIterator::EntryIterator(const NBLog::EntryIterator &other) 189cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet : ptr(other.ptr) {} 190cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 191537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletconst NBLog::entry& NBLog::EntryIterator::operator*() const { 192cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return *(entry*) ptr; 193cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet} 194cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 195537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletconst NBLog::entry* NBLog::EntryIterator::operator->() const { 196cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return (entry*) ptr; 197cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet} 198cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 199537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::EntryIterator& NBLog::EntryIterator::operator++() { 200cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet ptr += ptr[offsetof(entry, length)] + NBLog::Entry::kOverhead; 201cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return *this; 20240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 20340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 204537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::EntryIterator& NBLog::EntryIterator::operator--() { 205cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet ptr -= ptr[NBLog::Entry::kPreviousLengthOffset] + NBLog::Entry::kOverhead; 206cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return *this; 207cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet} 20840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 209537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::EntryIterator NBLog::EntryIterator::next() const { 210537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet EntryIterator aux(*this); 2116ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet return ++aux; 2126ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet} 2136ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet 214537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::EntryIterator NBLog::EntryIterator::prev() const { 215537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet EntryIterator aux(*this); 2166ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet return --aux; 2176ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet} 2186ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet 219537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletint NBLog::EntryIterator::operator-(const NBLog::EntryIterator &other) const { 220cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return ptr - other.ptr; 221cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet} 222cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 223537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletbool NBLog::EntryIterator::operator!=(const EntryIterator &other) const { 224cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return ptr != other.ptr; 225cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet} 226cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 227537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletbool NBLog::EntryIterator::hasConsistentLength() const { 228cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return ptr[offsetof(entry, length)] == ptr[ptr[offsetof(entry, length)] + 229cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet NBLog::Entry::kOverhead + NBLog::Entry::kPreviousLengthOffset]; 23040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 23140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 23240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// --------------------------------------------------------------------------- 23340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 234f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Rouletint64_t NBLog::HistogramEntry::timestamp() const { 235537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet return EntryIterator(mEntry).payload<HistTsEntry>().ts; 236537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet} 237537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet 238537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::log_hash_t NBLog::HistogramEntry::hash() const { 239537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet return EntryIterator(mEntry).payload<HistTsEntry>().hash; 240537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet} 241537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet 242537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletint NBLog::HistogramEntry::author() const { 243537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet EntryIterator it(mEntry); 244537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet if (it->length == sizeof(HistTsEntryWithAuthor)) { 245537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet return it.payload<HistTsEntryWithAuthor>().author; 246537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet } else { 247537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet return -1; 248537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet } 249537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet} 250537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet 251537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::EntryIterator NBLog::HistogramEntry::copyWithAuthor( 252537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const { 253537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet // Current histogram entry has {type, length, struct HistTsEntry, length}. 254537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet // We now want {type, length, struct HistTsEntryWithAuthor, length} 255537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet uint8_t buffer[Entry::kOverhead + sizeof(HistTsEntryWithAuthor)]; 256537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet // Copy content until the point we want to add the author 257537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet memcpy(buffer, mEntry, sizeof(entry) + sizeof(HistTsEntry)); 258537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet // Copy the author 259537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet *(int*) (buffer + sizeof(entry) + sizeof(HistTsEntry)) = author; 260537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet // Update lengths 261537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet buffer[offsetof(entry, length)] = sizeof(HistTsEntryWithAuthor); 2629ef855d02352613880d593a94dc6a1d74b363177Ivan Lozano buffer[offsetof(entry, data) + sizeof(HistTsEntryWithAuthor) + offsetof(ending, length)] 2639ef855d02352613880d593a94dc6a1d74b363177Ivan Lozano = sizeof(HistTsEntryWithAuthor); 264537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet // Write new buffer into FIFO 265537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet dst->write(buffer, sizeof(buffer)); 266537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet return EntryIterator(mEntry).next(); 267537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet} 268537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet 269537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet// --------------------------------------------------------------------------- 270537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet 27111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#if 0 // FIXME see note in NBLog.h 27211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn KastenNBLog::Timeline::Timeline(size_t size, void *shared) 27311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten : mSize(roundup(size)), mOwn(shared == NULL), 27411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten mShared((Shared *) (mOwn ? new char[sharedSize(size)] : shared)) 27511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 27611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten new (mShared) Shared; 27711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 27811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 27911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn KastenNBLog::Timeline::~Timeline() 28011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 28111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten mShared->~Shared(); 28211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (mOwn) { 28311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten delete[] (char *) mShared; 28411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 28511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 28611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif 28711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 28811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten/*static*/ 28911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastensize_t NBLog::Timeline::sharedSize(size_t size) 29011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 291ed99c2b5a99a8bfc163a6ffa0b767c82032b09b5Glenn Kasten // TODO fifo now supports non-power-of-2 buffer sizes, so could remove the roundup 29211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return sizeof(Shared) + roundup(size); 29311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 29411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 29511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 29611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 29711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn KastenNBLog::Writer::Writer() 298c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet : mShared(NULL), mFifo(NULL), mFifoWriter(NULL), mEnabled(false), mPidTag(NULL), mPidTagSize(0) 29911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 30011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 30111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 302535e161e2e404dffb8389dd331be0132704b6d82Glenn KastenNBLog::Writer::Writer(void *shared, size_t size) 303535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten : mShared((Shared *) shared), 304535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten mFifo(mShared != NULL ? 305535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten new audio_utils_fifo(size, sizeof(uint8_t), 306535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten mShared->mBuffer, mShared->mRear, NULL /*throttlesFront*/) : NULL), 307535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten mFifoWriter(mFifo != NULL ? new audio_utils_fifo_writer(*mFifo) : NULL), 308535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten mEnabled(mFifoWriter != NULL) 30911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 310c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet // caching pid and process name 311c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet pid_t id = ::getpid(); 312c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet char procName[16]; 313c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet int status = prctl(PR_GET_NAME, procName); 314c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet if (status) { // error getting process name 315c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet procName[0] = '\0'; 316c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet } 317c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet size_t length = strlen(procName); 318c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet mPidTagSize = length + sizeof(pid_t); 319c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet mPidTag = new char[mPidTagSize]; 320c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet memcpy(mPidTag, &id, sizeof(pid_t)); 321c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet memcpy(mPidTag + sizeof(pid_t), procName, length); 32211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 32311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 324535e161e2e404dffb8389dd331be0132704b6d82Glenn KastenNBLog::Writer::Writer(const sp<IMemory>& iMemory, size_t size) 325535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten : Writer(iMemory != 0 ? (Shared *) iMemory->pointer() : NULL, size) 32611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 327535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten mIMemory = iMemory; 328535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten} 329535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten 330535e161e2e404dffb8389dd331be0132704b6d82Glenn KastenNBLog::Writer::~Writer() 331535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten{ 332535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten delete mFifoWriter; 333535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten delete mFifo; 334c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet delete[] mPidTag; 33511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 33611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 33711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenvoid NBLog::Writer::log(const char *string) 33811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 33911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (!mEnabled) { 34011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return; 34111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 342fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet LOG_ALWAYS_FATAL_IF(string == NULL, "Attempted to log NULL string"); 34311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten size_t length = strlen(string); 344535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten if (length > Entry::kMaxLength) { 345535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten length = Entry::kMaxLength; 34611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 34711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten log(EVENT_STRING, string, length); 34811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 34911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 35011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenvoid NBLog::Writer::logf(const char *fmt, ...) 35111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 35211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (!mEnabled) { 35311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return; 35411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 35511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten va_list ap; 35611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten va_start(ap, fmt); 35711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Writer::logvf(fmt, ap); // the Writer:: is needed to avoid virtual dispatch for LockedWriter 35811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten va_end(ap); 35911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 36011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 36111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenvoid NBLog::Writer::logvf(const char *fmt, va_list ap) 36211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 36311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (!mEnabled) { 36411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return; 36511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 366535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten char buffer[Entry::kMaxLength + 1 /*NUL*/]; 36711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten int length = vsnprintf(buffer, sizeof(buffer), fmt, ap); 36811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (length >= (int) sizeof(buffer)) { 36911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten length = sizeof(buffer) - 1; 37011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten // NUL termination is not required 37111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten // buffer[length] = '\0'; 37211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 37311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (length >= 0) { 37411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten log(EVENT_STRING, buffer, length); 37511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 37611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 37711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 37811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenvoid NBLog::Writer::logTimestamp() 37911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 38011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (!mEnabled) { 38111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return; 38211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 383f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet int64_t ts = get_monotonic_ns(); 384f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet if (ts > 0) { 385fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet log(EVENT_TIMESTAMP, &ts, sizeof(ts)); 386f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet } else { 387f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet ALOGE("Failed to get timestamp"); 38811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 38911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 39011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 391f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Rouletvoid NBLog::Writer::logTimestamp(const int64_t ts) 39211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 39311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (!mEnabled) { 39411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return; 39511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 396fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet log(EVENT_TIMESTAMP, &ts, sizeof(ts)); 397fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 398fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 399fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::Writer::logInteger(const int x) 400fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 401fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (!mEnabled) { 402fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet return; 403fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 404fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet log(EVENT_INTEGER, &x, sizeof(x)); 405fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 406fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 407fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::Writer::logFloat(const float x) 408fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 409fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (!mEnabled) { 410fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet return; 411fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 412fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet log(EVENT_FLOAT, &x, sizeof(x)); 413fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 414fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 415fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::Writer::logPID() 416fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 417fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (!mEnabled) { 418fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet return; 419fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 420c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet log(EVENT_PID, mPidTag, mPidTagSize); 421fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 422fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 423fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::Writer::logStart(const char *fmt) 424fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 425fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (!mEnabled) { 426fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet return; 427fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 428fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet size_t length = strlen(fmt); 429fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (length > Entry::kMaxLength) { 430fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet length = Entry::kMaxLength; 431fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 432fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet log(EVENT_START_FMT, fmt, length); 433fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 434fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 435fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::Writer::logEnd() 436fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 437fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (!mEnabled) { 438fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet return; 439fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 440fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Entry entry = Entry(EVENT_END_FMT, NULL, 0); 441fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet log(&entry, true); 442fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 443fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 444bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Rouletvoid NBLog::Writer::logHash(log_hash_t hash) 445bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet{ 446bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet if (!mEnabled) { 447bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet return; 448bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet } 449bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet log(EVENT_HASH, &hash, sizeof(hash)); 450bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet} 451bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet 452a8a8a47da86e181d835eab7f858d6b1d2c3a8357Sanna Catherine de Treville Wagervoid NBLog::Writer::logEventHistTs(Event event, log_hash_t hash) 453537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet{ 454537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet if (!mEnabled) { 455537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet return; 456537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet } 457537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet HistTsEntry data; 458537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet data.hash = hash; 459f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet data.ts = get_monotonic_ns(); 460f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet if (data.ts > 0) { 461a8a8a47da86e181d835eab7f858d6b1d2c3a8357Sanna Catherine de Treville Wager log(event, &data, sizeof(data)); 462537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet } else { 463f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet ALOGE("Failed to get timestamp"); 464537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet } 465537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet} 466537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet 467bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Rouletvoid NBLog::Writer::logFormat(const char *fmt, log_hash_t hash, ...) 468fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 469fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (!mEnabled) { 470fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet return; 471fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 472fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 473fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet va_list ap; 474bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet va_start(ap, hash); 475bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet Writer::logVFormat(fmt, hash, ap); 476fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet va_end(ap); 477fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 478fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 479bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Rouletvoid NBLog::Writer::logVFormat(const char *fmt, log_hash_t hash, va_list argp) 480fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 481fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (!mEnabled) { 482fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet return; 483fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 484fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logStart(fmt); 485fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet int i; 486fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet double f; 487fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet char* s; 488f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet int64_t t; 489fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logTimestamp(); 490bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet Writer::logHash(hash); 491fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet for (const char *p = fmt; *p != '\0'; p++) { 492fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet // TODO: implement more complex formatting such as %.3f 493fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (*p != '%') { 494fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet continue; 495fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 496fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet switch(*++p) { 497fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case 's': // string 498fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet s = va_arg(argp, char *); 499fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::log(s); 500fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 501fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 502fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case 't': // timestamp 503f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet t = va_arg(argp, int64_t); 504fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logTimestamp(t); 505fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 506fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 507fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case 'd': // integer 508fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet i = va_arg(argp, int); 509fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logInteger(i); 510fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 511fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 512fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case 'f': // float 513fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet f = va_arg(argp, double); // float arguments are promoted to double in vararg lists 514fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logFloat((float)f); 515fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 516fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 517fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case 'p': // pid 518fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logPID(); 519fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 520fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 521fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet // the "%\0" case finishes parsing 522fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case '\0': 523fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet --p; 524fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 525fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 526c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet case '%': 527c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet break; 528c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet 529fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet default: 530fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet ALOGW("NBLog Writer parsed invalid format specifier: %c", *p); 531fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 532fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 533fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 534fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logEnd(); 53511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 53611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 53711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenvoid NBLog::Writer::log(Event event, const void *data, size_t length) 53811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 53911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (!mEnabled) { 54011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return; 54111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 542535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten if (data == NULL || length > Entry::kMaxLength) { 543535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten // TODO Perhaps it makes sense to display truncated data or at least a 544535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten // message that the data is too long? The current behavior can create 545535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten // a confusion for a programmer debugging their code. 54611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return; 54711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 548537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet // Ignore if invalid event 549537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet if (event == EVENT_RESERVED || event >= EVENT_UPPER_BOUND) { 55011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return; 55111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 5522d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wager Entry etr(event, data, length); 5532d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wager log(&etr, true /*trusted*/); 55411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 55511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 5562d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wagervoid NBLog::Writer::log(const NBLog::Entry *etr, bool trusted) 55711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 55811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (!mEnabled) { 55911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return; 56011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 56111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten if (!trusted) { 5622d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wager log(etr->mEvent, etr->mData, etr->mLength); 56311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return; 56411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 5652d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wager size_t need = etr->mLength + Entry::kOverhead; // mEvent, mLength, data[mLength], mLength 5662d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wager // need = number of bytes written to FIFO 567535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten 56811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten // FIXME optimize this using memcpy for the data part of the Entry. 56911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten // The Entry could have a method copyTo(ptr, offset, size) to optimize the copy. 5702d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wager // checks size of a single log Entry: type, length, data pointer and ending 571535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten uint8_t temp[Entry::kMaxLength + Entry::kOverhead]; 5722d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wager // write this data to temp array 573535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten for (size_t i = 0; i < need; i++) { 5742d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wager temp[i] = etr->copyEntryDataAt(i); 57511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 5762d1631eec3f4a5f8d43f5178246a6de31e47532dSanna Catherine de Treville Wager // write to circular buffer 577535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten mFifoWriter->write(temp, need); 57811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 57911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 58011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenbool NBLog::Writer::isEnabled() const 58111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 58211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return mEnabled; 58311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 58411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 58511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenbool NBLog::Writer::setEnabled(bool enabled) 58611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 58711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten bool old = mEnabled; 58811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten mEnabled = enabled && mShared != NULL; 58911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return old; 59011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 59111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 59211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 59311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 59411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn KastenNBLog::LockedWriter::LockedWriter() 59511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten : Writer() 59611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 59711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 59811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 599535e161e2e404dffb8389dd331be0132704b6d82Glenn KastenNBLog::LockedWriter::LockedWriter(void *shared, size_t size) 600535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten : Writer(shared, size) 60111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 60211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 60311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 60411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenvoid NBLog::LockedWriter::log(const char *string) 60511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 60611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Mutex::Autolock _l(mLock); 60711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Writer::log(string); 60811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 60911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 61011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenvoid NBLog::LockedWriter::logf(const char *fmt, ...) 61111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 61211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten // FIXME should not take the lock until after formatting is done 61311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Mutex::Autolock _l(mLock); 61411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten va_list ap; 61511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten va_start(ap, fmt); 61611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Writer::logvf(fmt, ap); 61711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten va_end(ap); 61811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 61911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 62011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenvoid NBLog::LockedWriter::logvf(const char *fmt, va_list ap) 62111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 62211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten // FIXME should not take the lock until after formatting is done 62311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Mutex::Autolock _l(mLock); 62411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Writer::logvf(fmt, ap); 62511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 62611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 62711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenvoid NBLog::LockedWriter::logTimestamp() 62811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 62911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten // FIXME should not take the lock until after the clock_gettime() syscall 63011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Mutex::Autolock _l(mLock); 63111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Writer::logTimestamp(); 63211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 63311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 634f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Rouletvoid NBLog::LockedWriter::logTimestamp(const int64_t ts) 63511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 63611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Mutex::Autolock _l(mLock); 63711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Writer::logTimestamp(ts); 63811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 63911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 640fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::LockedWriter::logInteger(const int x) 641fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 642fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Mutex::Autolock _l(mLock); 643fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logInteger(x); 644fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 645fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 646fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::LockedWriter::logFloat(const float x) 647fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 648fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Mutex::Autolock _l(mLock); 649fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logFloat(x); 650fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 651fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 652fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::LockedWriter::logPID() 653fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 654fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Mutex::Autolock _l(mLock); 655fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logPID(); 656fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 657fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 658fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::LockedWriter::logStart(const char *fmt) 659fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 660fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Mutex::Autolock _l(mLock); 661fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logStart(fmt); 662fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 663fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 664fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 665fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::LockedWriter::logEnd() 666fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet{ 667fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Mutex::Autolock _l(mLock); 668fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet Writer::logEnd(); 669fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 670fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 671bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Rouletvoid NBLog::LockedWriter::logHash(log_hash_t hash) 672bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet{ 673bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet Mutex::Autolock _l(mLock); 674bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet Writer::logHash(hash); 675bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet} 676bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet 67711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenbool NBLog::LockedWriter::isEnabled() const 67811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 67911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Mutex::Autolock _l(mLock); 68011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return Writer::isEnabled(); 68111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 68211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 68311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenbool NBLog::LockedWriter::setEnabled(bool enabled) 68411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 68511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Mutex::Autolock _l(mLock); 68611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten return Writer::setEnabled(enabled); 68711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 68811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 68911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 69011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 691537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletconst std::set<NBLog::Event> NBLog::Reader::startingTypes {NBLog::Event::EVENT_START_FMT, 692857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager NBLog::Event::EVENT_HISTOGRAM_ENTRY_TS, 693857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager NBLog::Event::EVENT_AUDIO_STATE}; 694537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletconst std::set<NBLog::Event> NBLog::Reader::endingTypes {NBLog::Event::EVENT_END_FMT, 695857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager NBLog::Event::EVENT_HISTOGRAM_ENTRY_TS, 696857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager NBLog::Event::EVENT_AUDIO_STATE}; 697a8a8a47da86e181d835eab7f858d6b1d2c3a8357Sanna Catherine de Treville Wager 698535e161e2e404dffb8389dd331be0132704b6d82Glenn KastenNBLog::Reader::Reader(const void *shared, size_t size) 699e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager : mFd(-1), mIndent(0), mLost(0), 700e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager mShared((/*const*/ Shared *) shared), /*mIMemory*/ 701535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten mFifo(mShared != NULL ? 702535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten new audio_utils_fifo(size, sizeof(uint8_t), 703535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten mShared->mBuffer, mShared->mRear, NULL /*throttlesFront*/) : NULL), 704d0dfe43a46bd1705c11b405f5f376524391bfb1aSanna Catherine de Treville Wager mFifoReader(mFifo != NULL ? new audio_utils_fifo_reader(*mFifo) : NULL) 70511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 70611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 70711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 708535e161e2e404dffb8389dd331be0132704b6d82Glenn KastenNBLog::Reader::Reader(const sp<IMemory>& iMemory, size_t size) 709535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten : Reader(iMemory != 0 ? (Shared *) iMemory->pointer() : NULL, size) 71011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 711535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten mIMemory = iMemory; 712535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten} 713535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten 714535e161e2e404dffb8389dd331be0132704b6d82Glenn KastenNBLog::Reader::~Reader() 715535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten{ 716535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten delete mFifoReader; 717535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten delete mFifo; 71811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 71911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 720537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletconst uint8_t *NBLog::Reader::findLastEntryOfTypes(const uint8_t *front, const uint8_t *back, 721537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet const std::set<Event> &types) { 7226ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet while (back + Entry::kPreviousLengthOffset >= front) { 723537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet const uint8_t *prev = back - back[Entry::kPreviousLengthOffset] - Entry::kOverhead; 724537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet if (prev < front || prev + prev[offsetof(entry, length)] + 7256ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet Entry::kOverhead != back) { 7266ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet 7276ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // prev points to an out of limits or inconsistent entry 7286ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet return nullptr; 7296ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet } 730537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet if (types.find((const Event) prev[offsetof(entry, type)]) != types.end()) { 7316ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet return prev; 7326ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet } 7336ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet back = prev; 7346ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet } 7356ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet return nullptr; // no entry found 7366ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet} 7376ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet 738e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager// Copies content of a Reader FIFO into its Snapshot 739e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager// The Snapshot has the same raw data, but represented as a sequence of entries 740e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager// and an EntryIterator making it possible to process the data. 74140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletstd::unique_ptr<NBLog::Reader::Snapshot> NBLog::Reader::getSnapshot() 74211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 743535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten if (mFifoReader == NULL) { 74440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet return std::unique_ptr<NBLog::Reader::Snapshot>(new Snapshot()); 74511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 74611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten // make a copy to avoid race condition with writer 747535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten size_t capacity = mFifo->capacity(); 748535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten 7496ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // This emulates the behaviour of audio_utils_fifo_reader::read, but without incrementing the 7506ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // reader index. The index is incremented after handling corruption, to after the last complete 7516ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // entry of the buffer 7526ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet size_t lost; 7536ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet audio_utils_iovec iovec[2]; 7546ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet ssize_t availToRead = mFifoReader->obtain(iovec, capacity, NULL /*timeout*/, &lost); 7556ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet if (availToRead <= 0) { 7566ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet return std::unique_ptr<NBLog::Reader::Snapshot>(new Snapshot()); 7576ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet } 7586ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet 7596ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet std::unique_ptr<Snapshot> snapshot(new Snapshot(availToRead)); 7606ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet memcpy(snapshot->mData, (const char *) mFifo->buffer() + iovec[0].mOffset, iovec[0].mLength); 7616ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet if (iovec[1].mLength > 0) { 7626ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet memcpy(snapshot->mData + (iovec[0].mLength), 7636ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet (const char *) mFifo->buffer() + iovec[1].mOffset, iovec[1].mLength); 7646ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet } 7656ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet 7666ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // Handle corrupted buffer 7676ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // Potentially, a buffer has corrupted data on both beginning (due to overflow) and end 7686ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // (due to incomplete format entry). But even if the end format entry is incomplete, 7696ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // it ends in a complete entry (which is not an END_FMT). So is safe to traverse backwards. 7706ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // TODO: handle client corruption (in the middle of a buffer) 7716ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet 772537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet const uint8_t *back = snapshot->mData + availToRead; 773537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet const uint8_t *front = snapshot->mData; 774535e161e2e404dffb8389dd331be0132704b6d82Glenn Kasten 7756ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // Find last END_FMT. <back> is sitting on an entry which might be the middle of a FormatEntry. 7766ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // We go backwards until we find an EVENT_END_FMT. 777537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet const uint8_t *lastEnd = findLastEntryOfTypes(front, back, endingTypes); 7786ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet if (lastEnd == nullptr) { 779537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet snapshot->mEnd = snapshot->mBegin = EntryIterator(front); 7806ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet } else { 7816ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // end of snapshot points to after last END_FMT entry 782537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet snapshot->mEnd = EntryIterator(lastEnd).next(); 7836ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // find first START_FMT 784537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet const uint8_t *firstStart = nullptr; 785537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet const uint8_t *firstStartTmp = snapshot->mEnd; 786537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet while ((firstStartTmp = findLastEntryOfTypes(front, firstStartTmp, startingTypes)) 7876ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet != nullptr) { 7886ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet firstStart = firstStartTmp; 7896ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet } 7906ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // firstStart is null if no START_FMT entry was found before lastEnd 7916ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet if (firstStart == nullptr) { 7926ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet snapshot->mBegin = snapshot->mEnd; 7936ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet } else { 794537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet snapshot->mBegin = EntryIterator(firstStart); 7956ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet } 7966ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet } 7976ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet 7986ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // advance fifo reader index to after last entry read. 7996ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet mFifoReader->release(snapshot->mEnd - front); 8006ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet 8016ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet snapshot->mLost = lost; 80240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet return snapshot; 8036ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet 80440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 80540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 806e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager// Takes raw content of the local merger FIFO, processes log entries, and 807e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager// writes the data to a map of class PerformanceAnalysis, based on their thread ID. 808e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wagervoid NBLog::MergeReader::getAndProcessSnapshot(NBLog::Reader::Snapshot &snapshot) 80940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet{ 8104e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten String8 timestamp, body; 811537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet 8126ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet for (auto entry = snapshot.begin(); entry != snapshot.end();) { 813cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet switch (entry->type) { 814fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case EVENT_START_FMT: 815cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet entry = handleFormat(FormatEntry(entry), ×tamp, &body); 816fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 817537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet case EVENT_HISTOGRAM_ENTRY_TS: { 818537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet HistTsEntryWithAuthor *data = (HistTsEntryWithAuthor *) (entry->data); 819537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet // TODO This memcpies are here to avoid unaligned memory access crash. 820537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet // There's probably a more efficient way to do it 821537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet log_hash_t hash; 822537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet memcpy(&hash, &(data->hash), sizeof(hash)); 823ad82aa66ff659a5a98fa5beebf16f7b053be47ddNicolas Roulet int64_t ts; 824ad82aa66ff659a5a98fa5beebf16f7b053be47ddNicolas Roulet memcpy(&ts, &data->ts, sizeof(ts)); 825857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager // TODO: hash for histogram ts and audio state need to match 826857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager // and correspond to audio production source file location 827857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager mThreadPerformanceAnalysis[data->author][0 /*hash*/].logTsEntry(ts); 828537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet ++entry; 829537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet break; 830537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet } 831a8a8a47da86e181d835eab7f858d6b1d2c3a8357Sanna Catherine de Treville Wager case EVENT_AUDIO_STATE: { 832e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager HistTsEntryWithAuthor *data = (HistTsEntryWithAuthor *) (entry->data); 833e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager // TODO This memcpies are here to avoid unaligned memory access crash. 834e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager // There's probably a more efficient way to do it 835d096517201332e03679c913e0d098c61ec6e4f0cSanna Catherine de Treville Wager log_hash_t hash; 836d096517201332e03679c913e0d098c61ec6e4f0cSanna Catherine de Treville Wager memcpy(&hash, &(data->hash), sizeof(hash)); 837857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager // TODO: remove ts if unused 838857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager int64_t ts; 839857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager memcpy(&ts, &data->ts, sizeof(ts)); 840857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager mThreadPerformanceAnalysis[data->author][0 /*hash*/].handleStateChange(); 841a8a8a47da86e181d835eab7f858d6b1d2c3a8357Sanna Catherine de Treville Wager ++entry; 842a8a8a47da86e181d835eab7f858d6b1d2c3a8357Sanna Catherine de Treville Wager break; 843a8a8a47da86e181d835eab7f858d6b1d2c3a8357Sanna Catherine de Treville Wager } 844fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case EVENT_END_FMT: 845fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet body.appendFormat("warning: got to end format event"); 8466ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet ++entry; 847fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 84811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten case EVENT_RESERVED: 84911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten default: 8506ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet body.appendFormat("warning: unexpected event %d", entry->type); 8516ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet ++entry; 85211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten break; 85311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten } 8549484bae02627b7827ac4e6f092923185ccfbf855Sanna Catherine de Treville Wager } 855e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager // FIXME: decide whether to print the warnings here or elsewhere 8569484bae02627b7827ac4e6f092923185ccfbf855Sanna Catherine de Treville Wager if (!body.isEmpty()) { 8579484bae02627b7827ac4e6f092923185ccfbf855Sanna Catherine de Treville Wager dumpLine(timestamp, body); 8584e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten } 85911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 86011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 861e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wagervoid NBLog::MergeReader::getAndProcessSnapshot() 86240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet{ 863e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager // get a snapshot, process it 86440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet std::unique_ptr<Snapshot> snap = getSnapshot(); 865e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager getAndProcessSnapshot(*snap); 86640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 86740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 868cf6c75a45416a90d2afdf42f0ac2f0b26f67839aSanna Catherine de Treville Wagervoid NBLog::MergeReader::dump(int fd, int indent) { 869857689453ed225e34488d4b02bd723dee8556606Sanna Catherine de Treville Wager // TODO: add a mutex around media.log dump 870cf6c75a45416a90d2afdf42f0ac2f0b26f67839aSanna Catherine de Treville Wager ReportPerformance::dump(fd, indent, mThreadPerformanceAnalysis); 871e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager} 872e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager 873e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager// Writes a string to the console 874fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::Reader::dumpLine(const String8 ×tamp, String8 &body) 8754e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten{ 8764e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten if (mFd >= 0) { 8778b5f642eb2364ea7fe46a5b3af51b48b58f12183Elliott Hughes dprintf(mFd, "%.*s%s %s\n", mIndent, "", timestamp.string(), body.string()); 8784e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten } else { 8794e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten ALOGI("%.*s%s %s", mIndent, "", timestamp.string(), body.string()); 8804e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten } 8814e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten body.clear(); 8824e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten} 8834e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten 88411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenbool NBLog::Reader::isIMemory(const sp<IMemory>& iMemory) const 88511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten{ 886481fb67a595f23c5b7f5be84b06db9b84a41a42fGlenn Kasten return iMemory != 0 && mIMemory != 0 && iMemory->pointer() == mIMemory->pointer(); 88711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} 88811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 8891c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten// --------------------------------------------------------------------------- 8901c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten 891fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::appendTimestamp(String8 *body, const void *data) { 892f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet int64_t ts; 893f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet memcpy(&ts, data, sizeof(ts)); 894f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet body->appendFormat("[%d.%03d]", (int) (ts / (1000 * 1000 * 1000)), 895f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet (int) ((ts / (1000 * 1000)) % 1000)); 896fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 897fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 898fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::appendInt(String8 *body, const void *data) { 899fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet int x = *((int*) data); 900fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet body->appendFormat("<%d>", x); 901fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 902fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 903fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Rouletvoid NBLog::appendFloat(String8 *body, const void *data) { 904fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet float f; 905fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet memcpy(&f, data, sizeof(float)); 906fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet body->appendFormat("<%f>", f); 907fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 908fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 909c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Rouletvoid NBLog::appendPID(String8 *body, const void* data, size_t length) { 910fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet pid_t id = *((pid_t*) data); 911c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet char * name = &((char*) data)[sizeof(pid_t)]; 912c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet body->appendFormat("<PID: %d, name: %.*s>", id, (int) (length - sizeof(pid_t)), name); 913fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 914fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 915f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas RouletString8 NBLog::bufferDump(const uint8_t *buffer, size_t size) 9162aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet{ 9172aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet String8 str; 9182aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet str.append("[ "); 9192aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet for(size_t i = 0; i < size; i++) 9202aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet { 921f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet str.appendFormat("%d ", buffer[i]); 9222aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet } 9232aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet str.append("]"); 9242aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet return str; 9252aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet} 9262aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet 927f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas RouletString8 NBLog::bufferDump(const EntryIterator &it) 9282aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet{ 929f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet return bufferDump(it, it->length + Entry::kOverhead); 9302aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet} 9312aedf3732cd36b69a892b6b46ba3b91682ae42b3Nicolas Roulet 932537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas RouletNBLog::EntryIterator NBLog::Reader::handleFormat(const FormatEntry &fmtEntry, 933cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet String8 *timestamp, 934cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet String8 *body) { 93540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // log timestamp 936f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet int64_t ts = fmtEntry.timestamp(); 937fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet timestamp->clear(); 938f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet timestamp->appendFormat("[%d.%03d]", (int) (ts / (1000 * 1000 * 1000)), 939f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet (int) ((ts / (1000 * 1000)) % 1000)); 94040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 941bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet // log unique hash 942bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet log_hash_t hash = fmtEntry.hash(); 943bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet // print only lower 16bit of hash as hex and line as int to reduce spam in the log 944bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet body->appendFormat("%.4X-%d ", (int)(hash >> 16) & 0xFFFF, (int) hash & 0xFFFF); 945bd0c6b47a93840e166f34308eb7660d81e949666Nicolas Roulet 94640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // log author (if present) 947cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet handleAuthor(fmtEntry, body); 94840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 94940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // log string 950537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet NBLog::EntryIterator arg = fmtEntry.args(); 95140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 95240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet const char* fmt = fmtEntry.formatString(); 95340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet size_t fmt_length = fmtEntry.formatStringLength(); 954fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 955fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet for (size_t fmt_offset = 0; fmt_offset < fmt_length; ++fmt_offset) { 956fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (fmt[fmt_offset] != '%') { 957fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet body->append(&fmt[fmt_offset], 1); // TODO optimize to write consecutive strings at once 958fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet continue; 959fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 960cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet // case "%%"" 961fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (fmt[++fmt_offset] == '%') { 962fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet body->append("%"); 963fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet continue; 964fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 965cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet // case "%\0" 966fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet if (fmt_offset == fmt_length) { 967fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet continue; 968fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 969fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 970cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet NBLog::Event event = (NBLog::Event) arg->type; 971cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet size_t length = arg->length; 972fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 973fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet // TODO check length for event type is correct 974fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 975cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet if (event == EVENT_END_FMT) { 976cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet break; 977cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet } 978cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet 979fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet // TODO: implement more complex formatting such as %.3f 980cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet const uint8_t *datum = arg->data; // pointer to the current event args 981fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet switch(fmt[fmt_offset]) 982fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet { 983fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case 's': // string 9844da7820be451847bad698ac0f687b964d9b5d34fNicolas Roulet ALOGW_IF(event != EVENT_STRING, 9854da7820be451847bad698ac0f687b964d9b5d34fNicolas Roulet "NBLog Reader incompatible event for string specifier: %d", event); 986fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet body->append((const char*) datum, length); 987fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 988fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 989fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case 't': // timestamp 9904da7820be451847bad698ac0f687b964d9b5d34fNicolas Roulet ALOGW_IF(event != EVENT_TIMESTAMP, 9914da7820be451847bad698ac0f687b964d9b5d34fNicolas Roulet "NBLog Reader incompatible event for timestamp specifier: %d", event); 992fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet appendTimestamp(body, datum); 993fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 994fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 995fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case 'd': // integer 9964da7820be451847bad698ac0f687b964d9b5d34fNicolas Roulet ALOGW_IF(event != EVENT_INTEGER, 9974da7820be451847bad698ac0f687b964d9b5d34fNicolas Roulet "NBLog Reader incompatible event for integer specifier: %d", event); 998fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet appendInt(body, datum); 999fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 1000fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 1001fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case 'f': // float 10024da7820be451847bad698ac0f687b964d9b5d34fNicolas Roulet ALOGW_IF(event != EVENT_FLOAT, 10034da7820be451847bad698ac0f687b964d9b5d34fNicolas Roulet "NBLog Reader incompatible event for float specifier: %d", event); 1004fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet appendFloat(body, datum); 1005fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 1006fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 1007fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet case 'p': // pid 10084da7820be451847bad698ac0f687b964d9b5d34fNicolas Roulet ALOGW_IF(event != EVENT_PID, 10094da7820be451847bad698ac0f687b964d9b5d34fNicolas Roulet "NBLog Reader incompatible event for pid specifier: %d", event); 1010c20cb50c1c14cd765874511872f087c875f43ed9Nicolas Roulet appendPID(body, datum, length); 1011fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet break; 1012fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 1013fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet default: 1014fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet ALOGW("NBLog Reader encountered unknown character %c", fmt[fmt_offset]); 1015fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 1016cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet ++arg; 101740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet } 1018cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet ALOGW_IF(arg->type != EVENT_END_FMT, "Expected end of format, got %d", arg->type); 1019cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet ++arg; 1020cd5dd016657b351d9c74dcdff87547a781108ccbNicolas Roulet return arg; 102140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 102240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 102340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas RouletNBLog::Merger::Merger(const void *shared, size_t size): 102440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet mShared((Shared *) shared), 102540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet mFifo(mShared != NULL ? 102640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet new audio_utils_fifo(size, sizeof(uint8_t), 102740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet mShared->mBuffer, mShared->mRear, NULL /*throttlesFront*/) : NULL), 102840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet mFifoWriter(mFifo != NULL ? new audio_utils_fifo_writer(*mFifo) : NULL) 102940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet {} 103040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 103140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletvoid NBLog::Merger::addReader(const NBLog::NamedReader &reader) { 1032e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager 10331c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten // FIXME This is called by binder thread in MediaLogService::registerWriter 10341c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten // but the access to shared variable mNamedReaders is not yet protected by a lock. 103540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet mNamedReaders.push_back(reader); 103640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 1037fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 103840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// items placed in priority queue during merge 103940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// composed by a timestamp and the index of the snapshot where the timestamp came from 104040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletstruct MergeItem 104140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet{ 1042f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet int64_t ts; 104340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet int index; 1044f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet MergeItem(int64_t ts, int index): ts(ts), index(index) {} 104540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet}; 104640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 104740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet// operators needed for priority queue in merge 1048f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet// bool operator>(const int64_t &t1, const int64_t &t2) { 1049f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet// return t1.tv_sec > t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec); 1050f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet// } 105140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 105240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletbool operator>(const struct MergeItem &i1, const struct MergeItem &i2) { 1053f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet return i1.ts > i2.ts || (i1.ts == i2.ts && i1.index > i2.index); 105440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 105540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 1056e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager// Merge registered readers, sorted by timestamp, and write data to a single FIFO in local memory 105740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Rouletvoid NBLog::Merger::merge() { 10581c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten // FIXME This is called by merge thread 10591c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten // but the access to shared variable mNamedReaders is not yet protected by a lock. 106040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet int nLogs = mNamedReaders.size(); 106140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet std::vector<std::unique_ptr<NBLog::Reader::Snapshot>> snapshots(nLogs); 1062537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet std::vector<NBLog::EntryIterator> offsets(nLogs); 106340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet for (int i = 0; i < nLogs; ++i) { 106440a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet snapshots[i] = mNamedReaders[i].reader()->getSnapshot(); 10656ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet offsets[i] = snapshots[i]->begin(); 106640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet } 106740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // initialize offsets 106840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // TODO custom heap implementation could allow to update top, improving performance 106940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // for bursty buffers 107040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet std::priority_queue<MergeItem, std::vector<MergeItem>, std::greater<MergeItem>> timestamps; 107140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet for (int i = 0; i < nLogs; ++i) 107240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet { 10736ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet if (offsets[i] != snapshots[i]->end()) { 1074f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet int64_t ts = AbstractEntry::buildEntry(offsets[i])->timestamp(); 10756ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet timestamps.emplace(ts, i); 107640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet } 1077fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet } 107840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 107940a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet while (!timestamps.empty()) { 108040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // find minimum timestamp 108140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet int index = timestamps.top().index; 10826ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet // copy it to the log, increasing offset 1083537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet offsets[index] = AbstractEntry::buildEntry(offsets[index])->copyWithAuthor(mFifoWriter, 1084537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet index); 108540a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet // update data structures 108640a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet timestamps.pop(); 10876ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet if (offsets[index] != snapshots[index]->end()) { 1088f42f15685ee622b1e341c8958f616c17801a1ad0Nicolas Roulet int64_t ts = AbstractEntry::buildEntry(offsets[index])->timestamp(); 10896ea1d7e449e5796068a4fcd7f22cad4316b0b8cfNicolas Roulet timestamps.emplace(ts, index); 109040a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet } 109140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet } 109240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 109340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 10941c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kastenconst std::vector<NBLog::NamedReader>& NBLog::Merger::getNamedReaders() const { 10951c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten // FIXME This is returning a reference to a shared variable that needs a lock 10961c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten return mNamedReaders; 109740a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet} 109840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 10991c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten// --------------------------------------------------------------------------- 11001c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten 110140a4498b967d000c93e8561db5fdd0488cc1d824Nicolas RouletNBLog::MergeReader::MergeReader(const void *shared, size_t size, Merger &merger) 110240a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet : Reader(shared, size), mNamedReaders(merger.getNamedReaders()) {} 110340a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet 1104537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Rouletvoid NBLog::MergeReader::handleAuthor(const NBLog::AbstractEntry &entry, String8 *body) { 1105537ad7dab88ee1b489331094a325726a26b8c1b1Nicolas Roulet int author = entry.author(); 11061c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten // FIXME Needs a lock 11071c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten const char* name = mNamedReaders[author].name(); 110840a4498b967d000c93e8561db5fdd0488cc1d824Nicolas Roulet body->appendFormat("%s: ", name); 1109fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet} 1110fe1e1449cadff4f946c33403aecc73b4b4a11e56Nicolas Roulet 11111c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten// --------------------------------------------------------------------------- 11121c446273e6ebfe55ef293a0b7e78525b1b40ce84Glenn Kasten 1113e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville WagerNBLog::MergeThread::MergeThread(NBLog::Merger &merger, NBLog::MergeReader &mergeReader) 1114dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet : mMerger(merger), 1115e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager mMergeReader(mergeReader), 1116dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet mTimeoutUs(0) {} 1117dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 1118dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas RouletNBLog::MergeThread::~MergeThread() { 1119dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet // set exit flag, set timeout to 0 to force threadLoop to exit and wait for the thread to join 1120dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet requestExit(); 1121dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet setTimeoutUs(0); 1122dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet join(); 1123dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet} 1124dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 1125dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Rouletbool NBLog::MergeThread::threadLoop() { 1126dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet bool doMerge; 1127dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet { 1128dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet AutoMutex _l(mMutex); 1129dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet // If mTimeoutUs is negative, wait on the condition variable until it's positive. 1130dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet // If it's positive, wait kThreadSleepPeriodUs and then merge 1131dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet nsecs_t waitTime = mTimeoutUs > 0 ? kThreadSleepPeriodUs * 1000 : LLONG_MAX; 1132dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet mCond.waitRelative(mMutex, waitTime); 1133dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet doMerge = mTimeoutUs > 0; 1134dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet mTimeoutUs -= kThreadSleepPeriodUs; 1135dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet } 1136dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet if (doMerge) { 1137e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager // Merge data from all the readers 1138dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet mMerger.merge(); 1139e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager // Process the data collected by mMerger and write it to PerformanceAnalysis 1140e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager // FIXME: decide whether to call getAndProcessSnapshot every time 1141e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager // or whether to have a separate thread that calls it with a lower frequency 1142e48652674ebd4047363a79d38a6018978087223eSanna Catherine de Treville Wager mMergeReader.getAndProcessSnapshot(); 1143dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet } 1144dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet return true; 1145dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet} 1146dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 1147dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Rouletvoid NBLog::MergeThread::wakeup() { 1148dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet setTimeoutUs(kThreadWakeupPeriodUs); 1149dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet} 1150dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 1151dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Rouletvoid NBLog::MergeThread::setTimeoutUs(int time) { 1152dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet AutoMutex _l(mMutex); 1153dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet mTimeoutUs = time; 1154dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet mCond.signal(); 1155dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet} 1156dcdfaecc1fa630a799e1fdb508a9b92da55abc36Nicolas Roulet 115711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} // namespace android 1158