nblog: split NBLog.cpp into multiple files

NBLog.cpp was deleted and split up into Entry.cpp, Merger.cpp,
Reader.cpp, Timeline.cpp, and Writer.cpp. NBLog.h was split up into
Entry.h, Events.h, Merger.h, Reader.h, Timeline.h, and Writer.h. NBLog.h
now includes all of these new headers except Merger.h, which is managed
exclusively by MediaLogService.

Other changes:
- changed NBLog from a class to a namespace
- changed NBLog::thread_info_t.type to enum and replaced magic numbers
- fixed some fragile build dependencies in libaudioclient and medialog

No other changes were made, and all functionalities that existed prior
to this commit remain the same.

Test: build, dumpsys media.log
Bug: 68148948
Change-Id: I1ce6dcb7b30d004f90584edfad7103a89f7bab0c
diff --git a/media/libnblog/Entry.cpp b/media/libnblog/Entry.cpp
new file mode 100644
index 0000000..e875639
--- /dev/null
+++ b/media/libnblog/Entry.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "NBLog"
+//#define LOG_NDEBUG 0
+
+#include <memory>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <audio_utils/fifo.h>
+#include <media/nblog/Entry.h>
+#include <media/nblog/Events.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace NBLog {
+
+int Entry::copyEntryDataAt(size_t offset) const
+{
+    // FIXME This is too slow
+    if (offset == 0) {
+        return mEvent;
+    } else if (offset == 1) {
+        return mLength;
+    } else if (offset < (size_t) (mLength + 2)) {
+        return (int) ((char *) mData)[offset - 2];
+    } else if (offset == (size_t) (mLength + 2)) {
+        return mLength;
+    } else {
+        return 0;   // FIXME is this an error?
+    }
+}
+
+EntryIterator::EntryIterator()   // Dummy initialization.
+    : mPtr(nullptr)
+{
+}
+
+EntryIterator::EntryIterator(const uint8_t *entry)
+    : mPtr(entry)
+{
+}
+
+EntryIterator::EntryIterator(const EntryIterator &other)
+    : mPtr(other.mPtr)
+{
+}
+
+const entry& EntryIterator::operator*() const
+{
+    return *(entry*) mPtr;
+}
+
+const entry* EntryIterator::operator->() const
+{
+    return (entry*) mPtr;
+}
+
+EntryIterator& EntryIterator::operator++()
+{
+    mPtr += mPtr[offsetof(entry, length)] + Entry::kOverhead;
+    return *this;
+}
+
+EntryIterator& EntryIterator::operator--()
+{
+    mPtr -= mPtr[Entry::kPreviousLengthOffset] + Entry::kOverhead;
+    return *this;
+}
+
+EntryIterator EntryIterator::next() const
+{
+    EntryIterator aux(*this);
+    return ++aux;
+}
+
+EntryIterator EntryIterator::prev() const
+{
+    EntryIterator aux(*this);
+    return --aux;
+}
+
+bool EntryIterator::operator!=(const EntryIterator &other) const
+{
+    return mPtr != other.mPtr;
+}
+
+int EntryIterator::operator-(const EntryIterator &other) const
+{
+    return mPtr - other.mPtr;
+}
+
+bool EntryIterator::hasConsistentLength() const
+{
+    return mPtr[offsetof(entry, length)] == mPtr[mPtr[offsetof(entry, length)] +
+        Entry::kOverhead + Entry::kPreviousLengthOffset];
+}
+
+void EntryIterator::copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst) const
+{
+    size_t length = mPtr[offsetof(entry, length)] + Entry::kOverhead;
+    dst->write(mPtr, length);
+}
+
+void EntryIterator::copyData(uint8_t *dst) const
+{
+    memcpy((void*) dst, mPtr + offsetof(entry, data), mPtr[offsetof(entry, length)]);
+}
+
+// ---------------------------------------------------------------------------
+
+std::unique_ptr<AbstractEntry> AbstractEntry::buildEntry(const uint8_t *ptr)
+{
+    if (ptr == nullptr) {
+        return nullptr;
+    }
+    const uint8_t type = EntryIterator(ptr)->type;
+    switch (type) {
+    case EVENT_FMT_START:
+        return std::make_unique<FormatEntry>(FormatEntry(ptr));
+    case EVENT_AUDIO_STATE:
+    case EVENT_HISTOGRAM_ENTRY_TS:
+        return std::make_unique<HistogramEntry>(HistogramEntry(ptr));
+    default:
+        ALOGW("Tried to create AbstractEntry of type %d", type);
+        return nullptr;
+    }
+}
+
+EntryIterator FormatEntry::begin() const
+{
+    return EntryIterator(mEntry);
+}
+
+const char *FormatEntry::formatString() const
+{
+    return (const char*) mEntry + offsetof(entry, data);
+}
+
+size_t FormatEntry::formatStringLength() const
+{
+    return mEntry[offsetof(entry, length)];
+}
+
+EntryIterator FormatEntry::args() const
+{
+    auto it = begin();
+    ++it; // skip start fmt
+    ++it; // skip timestamp
+    ++it; // skip hash
+    // Skip author if present
+    if (it->type == EVENT_FMT_AUTHOR) {
+        ++it;
+    }
+    return it;
+}
+
+int64_t FormatEntry::timestamp() const
+{
+    auto it = begin();
+    ++it; // skip start fmt
+    return it.payload<int64_t>();
+}
+
+log_hash_t FormatEntry::hash() const
+{
+    auto it = begin();
+    ++it; // skip start fmt
+    ++it; // skip timestamp
+    // unaligned 64-bit read not supported
+    log_hash_t hash;
+    memcpy(&hash, it->data, sizeof(hash));
+    return hash;
+}
+
+int FormatEntry::author() const
+{
+    auto it = begin();
+    ++it; // skip start fmt
+    ++it; // skip timestamp
+    ++it; // skip hash
+    // if there is an author entry, return it, return -1 otherwise
+    return it->type == EVENT_FMT_AUTHOR ? it.payload<int>() : -1;
+}
+
+EntryIterator FormatEntry::copyWithAuthor(
+        std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const
+{
+    auto it = begin();
+    it.copyTo(dst);     // copy fmt start entry
+    (++it).copyTo(dst); // copy timestamp
+    (++it).copyTo(dst); // copy hash
+    // insert author entry
+    size_t authorEntrySize = Entry::kOverhead + sizeof(author);
+    uint8_t authorEntry[authorEntrySize];
+    authorEntry[offsetof(entry, type)] = EVENT_FMT_AUTHOR;
+    authorEntry[offsetof(entry, length)] =
+        authorEntry[authorEntrySize + Entry::kPreviousLengthOffset] =
+        sizeof(author);
+    *(int*) (&authorEntry[offsetof(entry, data)]) = author;
+    dst->write(authorEntry, authorEntrySize);
+    // copy rest of entries
+    while ((++it)->type != EVENT_FMT_END) {
+        it.copyTo(dst);
+    }
+    it.copyTo(dst);
+    ++it;
+    return it;
+}
+
+int64_t HistogramEntry::timestamp() const
+{
+    return EntryIterator(mEntry).payload<HistTsEntry>().ts;
+}
+
+log_hash_t HistogramEntry::hash() const
+{
+    return EntryIterator(mEntry).payload<HistTsEntry>().hash;
+}
+
+int HistogramEntry::author() const
+{
+    EntryIterator it(mEntry);
+    return it->length == sizeof(HistTsEntryWithAuthor)
+            ? it.payload<HistTsEntryWithAuthor>().author : -1;
+}
+
+EntryIterator HistogramEntry::copyWithAuthor(
+        std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const
+{
+    // Current histogram entry has {type, length, struct HistTsEntry, length}.
+    // We now want {type, length, struct HistTsEntryWithAuthor, length}
+    uint8_t buffer[Entry::kOverhead + sizeof(HistTsEntryWithAuthor)];
+    // Copy content until the point we want to add the author
+    memcpy(buffer, mEntry, sizeof(entry) + sizeof(HistTsEntry));
+    // Copy the author
+    *(int*) (buffer + sizeof(entry) + sizeof(HistTsEntry)) = author;
+    // Update lengths
+    buffer[offsetof(entry, length)] = sizeof(HistTsEntryWithAuthor);
+    buffer[offsetof(entry, data) + sizeof(HistTsEntryWithAuthor) + offsetof(ending, length)]
+        = sizeof(HistTsEntryWithAuthor);
+    // Write new buffer into FIFO
+    dst->write(buffer, sizeof(buffer));
+    return EntryIterator(mEntry).next();
+}
+
+}   // namespace NBLog
+}   // namespace android