Merge "Treblize audio policy xml config file location"
diff --git a/camera/cameraserver/Android.mk b/camera/cameraserver/Android.mk
index bdafff1..1548e64 100644
--- a/camera/cameraserver/Android.mk
+++ b/camera/cameraserver/Android.mk
@@ -23,6 +23,7 @@
 	libcameraservice \
 	liblog \
 	libutils \
+	libui \
 	libbinder \
 	android.hardware.camera.common@1.0 \
 	android.hardware.camera.provider@2.4 \
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index f1f3b01..5732613 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -95,17 +95,6 @@
 }
 
 
-static ::SharedBuffer toSharedBuffer(const sp<IMemory>& sharedBuffer) {
-    ssize_t offset;
-    size_t size;
-    sharedBuffer->getMemory(&offset, &size);
-
-    ::SharedBuffer buffer;
-    buffer.offset = offset >= 0 ? offset : 0;
-    buffer.size = size;
-    return buffer;
-}
-
 static String8 toString8(hidl_string hString) {
     return String8(hString.c_str());
 }
@@ -114,7 +103,7 @@
 CryptoHal::CryptoHal()
     : mFactory(makeCryptoFactory()),
       mInitCheck((mFactory == NULL) ? ERROR_UNSUPPORTED : NO_INIT),
-      mHeapBase(NULL) {
+      mNextBufferId(0) {
 }
 
 CryptoHal::~CryptoHal() {
@@ -206,20 +195,45 @@
  * size.  Once the heap base is established, shared memory buffers
  * are sent by providing an offset into the heap and a buffer size.
  */
-status_t CryptoHal::setHeapBase(const sp<IMemory>& sharedBuffer) {
-    sp<IMemoryHeap> heap = sharedBuffer->getMemory(NULL, NULL);
-    if (mHeapBase != heap->getBase()) {
-        int fd = heap->getHeapID();
-        native_handle_t* nativeHandle = native_handle_create(1, 0);
-        nativeHandle->data[0] = fd;
-        auto hidlHandle = hidl_handle(nativeHandle);
-        auto hidlMemory = hidl_memory("ashmem", hidlHandle, heap->getSize());
-        mHeapBase = heap->getBase();
-        Return<void> hResult = mPlugin->setSharedBufferBase(hidlMemory);
-        if (!hResult.isOk()) {
-            return DEAD_OBJECT;
-        }
+void CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
+    native_handle_t* nativeHandle = native_handle_create(1, 0);
+    if (!nativeHandle) {
+        ALOGE("setSharedBufferBase(), failed to create native handle");
+        return;
     }
+    if (heap == NULL) {
+        ALOGE("setSharedBufferBase(): heap is NULL");
+        return;
+    }
+    int fd = heap->getHeapID();
+    nativeHandle->data[0] = fd;
+    auto hidlHandle = hidl_handle(nativeHandle);
+    auto hidlMemory = hidl_memory("ashmem", hidlHandle, heap->getSize());
+    mHeapBases.add(heap->getBase(), mNextBufferId);
+    Return<void> hResult = mPlugin->setSharedBufferBase(hidlMemory, mNextBufferId++);
+    ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
+}
+
+status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* buffer) {
+    ssize_t offset;
+    size_t size;
+
+    if (memory == NULL && buffer == NULL) {
+        return UNEXPECTED_NULL;
+    }
+
+    sp<IMemoryHeap> heap = memory->getMemory(&offset, &size);
+    if (heap == NULL) {
+        return UNEXPECTED_NULL;
+    }
+
+    if (mHeapBases.indexOfKey(heap->getBase()) < 0) {
+        setHeapBase(heap);
+    }
+
+    buffer->bufferId = mHeapBases.valueFor(heap->getBase());
+    buffer->offset = offset >= 0 ? offset : 0;
+    buffer->size = size;
     return OK;
 }
 
@@ -234,9 +248,6 @@
         return mInitCheck;
     }
 
-    // Establish the base of the shared memory heap
-    setHeapBase(source);
-
     Mode hMode;
     switch(mode) {
     case CryptoPlugin::kMode_Unencrypted:
@@ -272,7 +283,11 @@
     ::DestinationBuffer hDestination;
     if (destination.mType == kDestinationTypeSharedMemory) {
         hDestination.type = BufferType::SHARED_MEMORY;
-        hDestination.nonsecureMemory = toSharedBuffer(destination.mSharedMemory);
+        status_t status = toSharedBuffer(destination.mSharedMemory,
+                &hDestination.nonsecureMemory);
+        if (status != OK) {
+            return status;
+        }
         secure = false;
     } else {
         hDestination.type = BufferType::NATIVE_HANDLE;
@@ -280,12 +295,17 @@
         secure = true;
     }
 
+    ::SharedBuffer hSource;
+    status_t status = toSharedBuffer(source, &hSource);
+    if (status != OK) {
+        return status;
+    }
 
     status_t err = UNKNOWN_ERROR;
     uint32_t bytesWritten = 0;
 
     Return<void> hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode,
-            hPattern, hSubSamples, toSharedBuffer(source), offset, hDestination,
+            hPattern, hSubSamples, hSource, offset, hDestination,
             [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
                 if (status == Status::OK) {
                     bytesWritten = hBytesWritten;
diff --git a/include/media/CryptoHal.h b/include/media/CryptoHal.h
index 1ace957..9d0c3e4 100644
--- a/include/media/CryptoHal.h
+++ b/include/media/CryptoHal.h
@@ -26,6 +26,8 @@
 
 #include "SharedLibrary.h"
 
+class IMemoryHeap;
+
 namespace android {
 
 struct CryptoHal : public BnCrypto {
@@ -70,7 +72,8 @@
      */
     status_t mInitCheck;
 
-    void *mHeapBase;
+    KeyedVector<void *, uint32_t> mHeapBases;
+    uint32_t mNextBufferId;
 
     sp<::android::hardware::drm::V1_0::ICryptoFactory>
             makeCryptoFactory();
@@ -78,7 +81,10 @@
             makeCryptoPlugin(const uint8_t uuid[16], const void *initData,
                 size_t size);
 
-    status_t setHeapBase(const sp<IMemory> &sharedBuffer);
+    void setHeapBase(const sp<IMemoryHeap>& heap);
+
+    status_t toSharedBuffer(const sp<IMemory>& memory,
+            ::android::hardware::drm::V1_0::SharedBuffer* buffer);
 
     DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
 };
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index d5aec3f..9d0341a 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -53,6 +53,7 @@
     virtual status_t setClientName(const String16& clientName) = 0;
     virtual status_t prepare() = 0;
     virtual status_t getMaxAmplitude(int* max) = 0;
+    virtual status_t getMetrics(Parcel *reply) = 0;
     virtual status_t start() = 0;
     virtual status_t stop() = 0;
     virtual status_t reset() = 0;
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index ec1d4b6..39b9ad4 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -19,9 +19,9 @@
 #define ANDROID_IOMX_H_
 
 #include <binder/IInterface.h>
-#include <gui/IGraphicBufferProducer.h>
 #include <utils/List.h>
 #include <utils/String8.h>
+#include <cutils/native_handle.h>
 
 #include <list>
 
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index c273da7..0b0f916 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -58,6 +58,7 @@
     virtual status_t close() = 0;
     virtual status_t reset() = 0;
     virtual status_t getMaxAmplitude(int *max) = 0;
+    virtual status_t getMetrics(Parcel *reply) = 0;
     virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
     virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0;
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index c2916be..071e7a1 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -249,6 +249,7 @@
     void        notify(int msg, int ext1, int ext2);
     status_t    setInputSurface(const sp<PersistentSurface>& surface);
     sp<IGraphicBufferProducer>     querySurfaceMediaSourceFromMediaServer();
+    status_t    getMetrics(Parcel *reply);
 
 private:
     void                    doCleanUp();
diff --git a/include/media/nbaio/NBLog.h b/include/media/nbaio/NBLog.h
index ff10b8c..043f15e 100644
--- a/include/media/nbaio/NBLog.h
+++ b/include/media/nbaio/NBLog.h
@@ -23,6 +23,8 @@
 #include <utils/Mutex.h>
 #include <audio_utils/fifo.h>
 
+#include <vector>
+
 namespace android {
 
 class String8;
@@ -40,14 +42,106 @@
     EVENT_RESERVED,
     EVENT_STRING,               // ASCII string, not NUL-terminated
     EVENT_TIMESTAMP,            // clock_gettime(CLOCK_MONOTONIC)
-    EVENT_INTEGER,
-    EVENT_FLOAT,
-    EVENT_PID,
+    EVENT_INTEGER,              // integer value entry
+    EVENT_FLOAT,                // floating point value entry
+    EVENT_PID,                  // process ID and process name
+    EVENT_AUTHOR,               // author index (present in merged logs) tracks entry's original log
     EVENT_START_FMT,            // logFormat start event: entry includes format string, following
                                 // entries contain format arguments
     EVENT_END_FMT,              // end of logFormat argument list
 };
 
+
+// ---------------------------------------------------------------------------
+// API for handling format entry operations
+
+// a formatted entry has the following structure:
+//    * START_FMT entry, containing the format string
+//    * author entry of the thread that generated it (optional, present in merged log)
+//    * TIMESTAMP entry
+//    * format arg1
+//    * format arg2
+//    * ...
+//    * END_FMT entry
+
+class FormatEntry {
+public:
+    // build a Format Entry starting in the given pointer
+    class iterator;
+    explicit FormatEntry(const uint8_t *entry);
+    explicit FormatEntry(const iterator &it);
+
+    // entry representation in memory
+    struct entry {
+        const uint8_t type;
+        const uint8_t length;
+        const uint8_t data[0];
+    };
+
+    // entry tail representation (after data)
+    struct ending {
+        uint8_t length;
+        uint8_t next[0];
+    };
+
+    // entry iterator
+    class iterator {
+    public:
+        iterator(const uint8_t *entry);
+        iterator(const iterator &other);
+
+        // dereference underlying entry
+        const entry&    operator*() const;
+        const entry*    operator->() const;
+        // advance to next entry
+        iterator&       operator++(); // ++i
+        // back to previous entry
+        iterator&       operator--(); // --i
+        bool            operator!=(const iterator &other) const;
+        int             operator-(const iterator &other) const;
+
+        bool            hasConsistentLength() const;
+        void            copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst) const;
+        void            copyData(uint8_t *dst) const;
+
+        template<typename T>
+        inline const T& payload() {
+            return *reinterpret_cast<const T *>(ptr + 2);
+        }
+
+    private:
+        friend class FormatEntry;
+        const uint8_t  *ptr;
+    };
+
+    // Entry's format string
+    const char* formatString() const;
+
+    // Enrty's format string length
+    size_t      formatStringLength() const;
+
+    // Format arguments (excluding format string, timestamp and author)
+    iterator    args() const;
+
+    // get format entry timestamp
+    timespec    timestamp() const;
+
+    // entry's author index (-1 if none present)
+    // a Merger has a vector of Readers, author simply points to the index of the
+    // Reader that originated the entry
+    int         author() const;
+
+    // copy entry, adding author before timestamp, returns size of original entry
+    size_t      copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const;
+
+    iterator    begin() const;
+
+private:
+    // copies ordinary entry from src to dst, and returns length of entry
+    // size_t      copyEntry(audio_utils_fifo_writer *dst, const iterator &it);
+    const uint8_t  *mEntry;
+};
+
 // ---------------------------------------------------------------------------
 
 // representation of a single log entry in private memory
@@ -65,7 +159,11 @@
     const void *mData;      // event type-specific data
     static const size_t kMaxLength = 255;
 public:
-    static const size_t kOverhead = 3;  // mEvent, mLength, mData[...], duplicate mLength
+    // mEvent, mLength, mData[...], duplicate mLength
+    static const size_t kOverhead = sizeof(FormatEntry::entry) + sizeof(FormatEntry::ending);
+    // endind length of previous entry
+    static const size_t kPreviousLengthOffset = - sizeof(FormatEntry::ending) +
+                                                offsetof(FormatEntry::ending, length);
 };
 
 // representation of a single log entry in shared memory
@@ -81,10 +179,9 @@
 
     static void    appendInt(String8 *body, const void *data);
     static void    appendFloat(String8 *body, const void *data);
-    static void    appendPID(String8 *body, const void *data);
-    static int     handleFormat(const char *fmt, size_t length, const uint8_t *data,
-                                String8 *timestamp, String8 *body);
+    static void    appendPID(String8 *body, const void *data, size_t length);
     static void    appendTimestamp(String8 *body, const void *data);
+    static size_t  fmtEntryLength(const uint8_t *data);
 
 public:
 
@@ -177,6 +274,11 @@
     audio_utils_fifo_writer * const mFifoWriter;    // used to write to FIFO,
                                                     // non-NULL unless dummy constructor used
     bool            mEnabled;   // whether to actually log
+
+    // cached pid and process name to use in %p format specifier
+    // total tag length is mPidTagSize and process name is not zero terminated
+    char   *mPidTag;
+    size_t  mPidTagSize;
 };
 
 // ---------------------------------------------------------------------------
@@ -210,6 +312,31 @@
 class Reader : public RefBase {
 public:
 
+    // A snapshot of a readers buffer
+    class Snapshot {
+    public:
+        Snapshot() : mData(NULL), mAvail(0), mLost(0) {}
+
+        Snapshot(size_t bufferSize) : mData(new uint8_t[bufferSize]) {}
+
+        ~Snapshot() { delete[] mData; }
+
+        // copy of the buffer
+        const uint8_t *data() const { return mData; }
+
+        // amount of data available (given by audio_utils_fifo_reader)
+        size_t   available() const { return mAvail; }
+
+        // amount of data lost (given by audio_utils_fifo_reader)
+        size_t   lost() const { return mLost; }
+
+    private:
+        friend class Reader;
+        const uint8_t *mData;
+        size_t         mAvail;
+        size_t         mLost;
+    };
+
     // Input parameter 'size' is the desired size of the timeline in byte units.
     // The size of the shared memory must be at least Timeline::sharedSize(size).
     Reader(const void *shared, size_t size);
@@ -217,8 +344,13 @@
 
     virtual ~Reader();
 
-    void    dump(int fd, size_t indent = 0);
-    bool    isIMemory(const sp<IMemory>& iMemory) const;
+    // get snapshot of readers fifo buffer, effectively consuming the buffer
+    std::unique_ptr<Snapshot> getSnapshot();
+    // dump a particular snapshot of the reader
+    void     dump(int fd, size_t indent, Snapshot & snap);
+    // dump the current content of the reader's buffer
+    void     dump(int fd, size_t indent = 0);
+    bool     isIMemory(const sp<IMemory>& iMemory) const;
 
 private:
     /*const*/ Shared* const mShared;    // raw pointer to shared memory, actually const but not
@@ -233,9 +365,66 @@
 
     void    dumpLine(const String8& timestamp, String8& body);
 
+    FormatEntry::iterator   handleFormat(const FormatEntry &fmtEntry,
+                                         String8 *timestamp,
+                                         String8 *body);
+    // dummy method for handling absent author entry
+    virtual size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body) { return 0; }
+
     static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
 };
 
+// Wrapper for a reader with a name. Contains a pointer to the reader and a pointer to the name
+class NamedReader {
+public:
+    NamedReader() { mName[0] = '\0'; } // for Vector
+    NamedReader(const sp<NBLog::Reader>& reader, const char *name) :
+        mReader(reader)
+        { strlcpy(mName, name, sizeof(mName)); }
+    ~NamedReader() { }
+    const sp<NBLog::Reader>&  reader() const { return mReader; }
+    const char*               name() const { return mName; }
+
+private:
+    sp<NBLog::Reader>   mReader;
+    static const size_t kMaxName = 32;
+    char                mName[kMaxName];
+};
+
+// ---------------------------------------------------------------------------
+
+class Merger : public RefBase {
+public:
+    Merger(const void *shared, size_t size);
+
+    virtual ~Merger() {}
+
+    void addReader(const NamedReader &reader);
+    // TODO add removeReader
+    void merge();
+    const std::vector<NamedReader> *getNamedReaders() const;
+private:
+    // vector of the readers the merger is supposed to merge from.
+    // every reader reads from a writer's buffer
+    std::vector<NamedReader> mNamedReaders;
+    uint8_t *mBuffer;
+    Shared * const mShared;
+    std::unique_ptr<audio_utils_fifo> mFifo;
+    std::unique_ptr<audio_utils_fifo_writer> mFifoWriter;
+
+    static struct timespec getTimestamp(const uint8_t *data);
+};
+
+class MergeReader : public Reader {
+public:
+    MergeReader(const void *shared, size_t size, Merger &merger);
+private:
+    const std::vector<NamedReader> *mNamedReaders;
+    // handle author entry by looking up the author's name and appending it to the body
+    // returns number of bytes read from fmtEntry
+    size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body);
+};
+
 };  // class NBLog
 
 }   // namespace android
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 90d9942..998716f 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -29,6 +29,7 @@
 #include <media/stagefright/SkipCutBuffer.h>
 #include <utils/NativeHandle.h>
 #include <OMX_Audio.h>
+#include <hardware/gralloc.h>
 
 #define TRACK_BUFFER_TIMING     0
 
@@ -42,11 +43,20 @@
 struct DataConverter;
 
 // Treble shared memory
-namespace hidl { namespace memory { namespace V1_0 {
+namespace hidl {
+namespace allocator {
+namespace V1_0 {
 struct IAllocator;
+} // V1_0
+} // allocator
+namespace memory {
+namespace V1_0 {
 struct IMemory;
-}}};
-typedef hidl::memory::V1_0::IAllocator TAllocator;
+} // V1_0
+} // memory
+} // hidl
+
+typedef hidl::allocator::V1_0::IAllocator TAllocator;
 typedef hidl::memory::V1_0::IMemory TMemory;
 
 struct ACodec : public AHierarchicalStateMachine, public CodecBase {
diff --git a/include/media/stagefright/SurfaceUtils.h b/include/media/stagefright/SurfaceUtils.h
index 13d580c..a7747c7 100644
--- a/include/media/stagefright/SurfaceUtils.h
+++ b/include/media/stagefright/SurfaceUtils.h
@@ -33,6 +33,8 @@
         ANativeWindow *nativeWindow /* nonnull */,
         int width, int height, int format, int rotation, int usage, bool reconnect);
 status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */);
+status_t nativeWindowConnect(ANativeWindow *surface, const char *reason);
+status_t nativeWindowDisconnect(ANativeWindow *surface, const char *reason);
 
 } // namespace android
 
diff --git a/include/ndk/NdkMediaCodec.h b/include/ndk/NdkMediaCodec.h
index ad17321..a63f39a 100644
--- a/include/ndk/NdkMediaCodec.h
+++ b/include/ndk/NdkMediaCodec.h
@@ -29,8 +29,6 @@
 
 #include <sys/cdefs.h>
 
-#include <android/native_window.h>
-
 #include "NdkMediaCrypto.h"
 #include "NdkMediaError.h"
 #include "NdkMediaFormat.h"
@@ -39,6 +37,8 @@
 extern "C" {
 #endif
 
+struct ANativeWindow;
+
 #if __ANDROID_API__ >= 21
 
 struct AMediaCodec;
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index 7dc4e1d..63fa16b 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -12,6 +12,7 @@
 	libcutils \
 	liblog \
 	libmedialogservice \
+	libnbaio \
 	libradioservice \
 	libsoundtriggerservice \
 	libutils \
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index 4b0f6a2..9d42bce 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -5,4 +5,9 @@
     group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct
     ioprio rt 4
     writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
-    onrestart restart audio-hal-2-0
\ No newline at end of file
+    onrestart restart audio-hal-2-0
+
+on property:vts.native_server.on=1
+    stop audioserver
+on property:vts.native_server.on=0
+    start audioserver
diff --git a/media/libaudiohal/Android.mk b/media/libaudiohal/Android.mk
index 617eb35..286c6b7 100644
--- a/media/libaudiohal/Android.mk
+++ b/media/libaudiohal/Android.mk
@@ -45,6 +45,7 @@
     android.hardware.audio.common@2.0      \
     android.hardware.audio.common@2.0-util \
     android.hardware.audio.effect@2.0      \
+    android.hidl.allocator@1.0             \
     android.hidl.memory@1.0                \
     libmedia_helper  \
     libmediautils
diff --git a/media/libaudiohal/EffectBufferHalHidl.cpp b/media/libaudiohal/EffectBufferHalHidl.cpp
index 82b4a75..ce581f2 100644
--- a/media/libaudiohal/EffectBufferHalHidl.cpp
+++ b/media/libaudiohal/EffectBufferHalHidl.cpp
@@ -19,7 +19,7 @@
 #define LOG_TAG "EffectBufferHalHidl"
 //#define LOG_NDEBUG 0
 
-#include <android/hidl/memory/1.0/IAllocator.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
 #include <hidlmemory/mapping.h>
 #include <utils/Log.h>
 
@@ -28,7 +28,7 @@
 
 using ::android::hardware::Return;
 using ::android::hardware::Status;
-using ::android::hidl::memory::V1_0::IAllocator;
+using ::android::hidl::allocator::V1_0::IAllocator;
 
 namespace android {
 
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/EffectHalHidl.cpp
index 67022de..d17f8bd 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/EffectHalHidl.cpp
@@ -74,12 +74,33 @@
 }
 
 // static
+void EffectHalHidl::effectBufferConfigToHal(
+        const EffectBufferConfig& config, buffer_config_t* halConfig) {
+    halConfig->buffer.frameCount = 0;
+    halConfig->buffer.raw = NULL;
+    halConfig->samplingRate = config.samplingRateHz;
+    halConfig->channels = static_cast<uint32_t>(config.channels);
+    halConfig->bufferProvider.cookie = NULL;
+    halConfig->bufferProvider.getBuffer = NULL;
+    halConfig->bufferProvider.releaseBuffer = NULL;
+    halConfig->format = static_cast<uint8_t>(config.format);
+    halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
+    halConfig->mask = static_cast<uint8_t>(config.mask);
+}
+
+// static
 void EffectHalHidl::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) {
     effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg);
     effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg);
 }
 
 // static
+void EffectHalHidl::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
+    effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg);
+    effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg);
+}
+
+// static
 status_t EffectHalHidl::analyzeResult(const Result& result) {
     switch (result) {
         case Result::OK: return OK;
@@ -193,6 +214,8 @@
     // Special cases.
     if (cmdCode == EFFECT_CMD_SET_CONFIG || cmdCode == EFFECT_CMD_SET_CONFIG_REVERSE) {
         return setConfigImpl(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+    } else if (cmdCode == EFFECT_CMD_GET_CONFIG || cmdCode == EFFECT_CMD_GET_CONFIG_REVERSE) {
+        return getConfigImpl(cmdCode, replySize, pReplyData);
     }
 
     // Common case.
@@ -235,6 +258,34 @@
     return ret.isOk() ? analyzeResult(ret) : FAILED_TRANSACTION;
 }
 
+status_t EffectHalHidl::getConfigImpl(
+        uint32_t cmdCode, uint32_t *replySize, void *pReplyData) {
+    if (replySize == NULL || *replySize != sizeof(effect_config_t) || pReplyData == NULL) {
+        return BAD_VALUE;
+    }
+    status_t result = FAILED_TRANSACTION;
+    Return<void> ret;
+    if (cmdCode == EFFECT_CMD_GET_CONFIG) {
+        ret = mEffect->getConfig([&] (Result r, const EffectConfig &hidlConfig) {
+            result = analyzeResult(r);
+            if (r == Result::OK) {
+                effectConfigToHal(hidlConfig, static_cast<effect_config_t*>(pReplyData));
+            }
+        });
+    } else {
+        ret = mEffect->getConfigReverse([&] (Result r, const EffectConfig &hidlConfig) {
+            result = analyzeResult(r);
+            if (r == Result::OK) {
+                effectConfigToHal(hidlConfig, static_cast<effect_config_t*>(pReplyData));
+            }
+        });
+    }
+    if (!ret.isOk()) {
+        result = FAILED_TRANSACTION;
+    }
+    return result;
+}
+
 status_t EffectHalHidl::setConfigImpl(
         uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) {
     if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) ||
diff --git a/media/libaudiohal/EffectHalHidl.h b/media/libaudiohal/EffectHalHidl.h
index d6a8791..c8db36f 100644
--- a/media/libaudiohal/EffectHalHidl.h
+++ b/media/libaudiohal/EffectHalHidl.h
@@ -79,7 +79,10 @@
     static status_t analyzeResult(const hardware::audio::effect::V2_0::Result& result);
     static void effectBufferConfigFromHal(
             const buffer_config_t& halConfig, EffectBufferConfig* config);
+    static void effectBufferConfigToHal(
+            const EffectBufferConfig& config, buffer_config_t* halConfig);
     static void effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config);
+    static void effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig);
 
     // Can not be constructed directly by clients.
     EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId);
@@ -87,6 +90,7 @@
     // The destructor automatically releases the effect.
     virtual ~EffectHalHidl();
 
+    status_t getConfigImpl(uint32_t cmdCode, uint32_t *replySize, void *pReplyData);
     status_t prepareForProcessing();
     status_t processImpl(uint32_t mqFlag);
     status_t setConfigImpl(
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.cpp b/media/libaudiohal/EffectsFactoryHalHidl.cpp
index ad12654..0ec9f9e 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/EffectsFactoryHalHidl.cpp
@@ -17,7 +17,7 @@
 #define LOG_TAG "EffectsFactoryHalHidl"
 //#define LOG_NDEBUG 0
 
-#include <android/hidl/memory/1.0/IAllocator.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
 #include <cutils/native_handle.h>
 #include <hidl/ServiceManagement.h>
 #include <media/EffectsFactoryApi.h>
@@ -50,7 +50,7 @@
     // TODO: Waiting should not be needed (b/34772726).
     // Also remove include of IAllocator.h and ServiceManagement.h
     android::hardware::details::waitForHwService(
-            hidl::memory::V1_0::IAllocator::descriptor, "ashmem");
+            hidl::allocator::V1_0::IAllocator::descriptor, "ashmem");
 }
 
 EffectsFactoryHalHidl::~EffectsFactoryHalHidl() {
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 5730c76..5282352 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -59,7 +59,9 @@
     SET_LISTENER,
     SET_CLIENT_NAME,
     PAUSE,
-    RESUME
+    RESUME,
+    GET_METRICS,
+
 };
 
 class BpMediaRecorder: public BpInterface<IMediaRecorder>
@@ -261,6 +263,18 @@
         return reply.readInt32();
     }
 
+    status_t getMetrics(Parcel* reply)
+    {
+        ALOGV("getMetrics");
+        Parcel data;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        status_t ret = remote()->transact(GET_METRICS, data, reply);
+        if (ret == NO_ERROR) {
+            return OK;
+        }
+        return UNKNOWN_ERROR;
+    }
+
     status_t start()
     {
         ALOGV("start");
@@ -397,6 +411,11 @@
             reply->writeInt32(ret);
             return NO_ERROR;
         } break;
+        case GET_METRICS: {
+            ALOGV("GET_METRICS");
+            status_t ret = getMetrics(reply);
+            return ret;
+        } break;
         case SET_VIDEO_SOURCE: {
             ALOGV("SET_VIDEO_SOURCE");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 3d466b1..67939b2 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -25,8 +25,9 @@
 #include <media/IOMX.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/openmax/OMX_IndexExt.h>
-#include <utils/NativeHandle.h>
 #include <media/OMXBuffer.h>
+#include <utils/NativeHandle.h>
+#include <gui/IGraphicBufferProducer.h>
 
 #include <android/IGraphicBufferSource.h>
 #include <android/IOMXBufferSource.h>
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index dbe4b3b..4405930 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -513,6 +513,17 @@
     return ret;
 }
 
+status_t MediaRecorder::getMetrics(Parcel *reply) {
+
+    ALOGV("getMetrics");
+
+    status_t ret = mMediaRecorder->getMetrics(reply);
+    if (OK != ret) {
+        ALOGE("getMetrics failed: %d", ret);
+    }
+    return ret;
+}
+
 status_t MediaRecorder::start()
 {
     ALOGV("start");
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index dbc7e21..a8b6c66 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -60,6 +60,7 @@
 #include <media/stagefright/Utils.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooperRoster.h>
+#include <media/stagefright/SurfaceUtils.h>
 #include <mediautils/BatteryNotifier.h>
 
 #include <memunreachable/memunreachable.h>
@@ -903,11 +904,11 @@
 
 void MediaPlayerService::Client::disconnectNativeWindow() {
     if (mConnectedWindow != NULL) {
-        status_t err = native_window_api_disconnect(mConnectedWindow.get(),
-                NATIVE_WINDOW_API_MEDIA);
+        status_t err = nativeWindowDisconnect(
+                mConnectedWindow.get(), "disconnectNativeWindow");
 
         if (err != OK) {
-            ALOGW("native_window_api_disconnect returned an error: %s (%d)",
+            ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
                     strerror(-err), err);
         }
     }
@@ -929,8 +930,7 @@
     sp<ANativeWindow> anw;
     if (bufferProducer != NULL) {
         anw = new Surface(bufferProducer, true /* controlledByApp */);
-        status_t err = native_window_api_connect(anw.get(),
-                NATIVE_WINDOW_API_MEDIA);
+        status_t err = nativeWindowConnect(anw.get(), "setVideoSurfaceTexture");
 
         if (err != OK) {
             ALOGE("setVideoSurfaceTexture failed: %d", err);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 763f509..c00a951 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -238,6 +238,17 @@
     return mRecorder->getMaxAmplitude(max);
 }
 
+status_t MediaRecorderClient::getMetrics(Parcel* reply)
+{
+    ALOGV("MediaRecorderClient::getMetrics");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        ALOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->getMetrics(reply);
+}
+
 status_t MediaRecorderClient::start()
 {
     ALOGV("start");
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 101b8f6..7868a91 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -79,6 +79,7 @@
     virtual     status_t   setClientName(const String16& clientName);
     virtual     status_t   prepare();
     virtual     status_t   getMaxAmplitude(int* max);
+    virtual     status_t   getMetrics(Parcel* reply);
     virtual     status_t   start();
     virtual     status_t   stop();
     virtual     status_t   reset();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 170659a..73570c8 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -30,6 +30,7 @@
 #include <binder/IServiceManager.h>
 
 #include <media/IMediaPlayerService.h>
+#include <media/MediaAnalyticsItem.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -65,6 +66,10 @@
 static const float kMinTypicalDisplayRefreshingRate = kTypicalDisplayRefreshingRate / 2;
 static const int kMaxNumVideoTemporalLayers = 8;
 
+// key for media statistics
+static const char *kKeyRecorder = "recorder";
+// attrs for media statistics
+//
 // To collect the encoder usage for the battery app
 static void addBatteryData(uint32_t params) {
     sp<IBinder> binder =
@@ -85,6 +90,8 @@
       mStarted(false) {
 
     ALOGV("Constructor");
+
+    mAnalyticsDirty = false;
     reset();
 }
 
@@ -95,6 +102,80 @@
     if (mLooper != NULL) {
         mLooper->stop();
     }
+
+    // log the current record, provided it has some information worth recording
+    if (mAnalyticsDirty && mAnalyticsItem != NULL) {
+        updateMetrics();
+        if (mAnalyticsItem->count() > 0) {
+            mAnalyticsItem->setFinalized(true);
+            mAnalyticsItem->selfrecord();
+        }
+        delete mAnalyticsItem;
+        mAnalyticsItem = NULL;
+    }
+}
+
+void StagefrightRecorder::updateMetrics() {
+    ALOGV("updateMetrics");
+
+    // we'll populate the values from the raw fields.
+    // (NOT going to populate as we go through the various set* ops)
+
+    // TBD mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
+    // TBD mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
+    // TBD mVideoEncoder  = VIDEO_ENCODER_DEFAULT;
+    mAnalyticsItem->setInt32("ht", mVideoHeight);
+    mAnalyticsItem->setInt32("wid", mVideoWidth);
+    mAnalyticsItem->setInt32("frame-rate", mFrameRate);
+    mAnalyticsItem->setInt32("video-bitrate", mVideoBitRate);
+    mAnalyticsItem->setInt32("audio-samplerate", mSampleRate);
+    mAnalyticsItem->setInt32("audio-channels", mAudioChannels);
+    mAnalyticsItem->setInt32("audio-bitrate", mAudioBitRate);
+    // TBD mInterleaveDurationUs = 0;
+    mAnalyticsItem->setInt32("video-iframe-interval", mIFramesIntervalSec);
+    // TBD mAudioSourceNode = 0;
+    // TBD mUse64BitFileOffset = false;
+    mAnalyticsItem->setInt32("movie-timescale", mMovieTimeScale);
+    mAnalyticsItem->setInt32("audio-timescale", mAudioTimeScale);
+    mAnalyticsItem->setInt32("video-timescale", mVideoTimeScale);
+    // TBD mCameraId        = 0;
+    // TBD mStartTimeOffsetMs = -1;
+    mAnalyticsItem->setInt32("video-encoder-profile", mVideoEncoderProfile);
+    mAnalyticsItem->setInt32("video-encoder-level", mVideoEncoderLevel);
+    // TBD mMaxFileDurationUs = 0;
+    // TBD mMaxFileSizeBytes = 0;
+    // TBD mTrackEveryTimeDurationUs = 0;
+    mAnalyticsItem->setInt32("capture-fpsenable", mCaptureFpsEnable);
+    mAnalyticsItem->setInt32("capture-fps", mCaptureFps);
+    // TBD mTimeBetweenCaptureUs = -1;
+    // TBD mCameraSourceTimeLapse = NULL;
+    // TBD mMetaDataStoredInVideoBuffers = kMetadataBufferTypeInvalid;
+    // TBD mEncoderProfiles = MediaProfiles::getInstance();
+    mAnalyticsItem->setInt32("rotation", mRotationDegrees);
+    // PII mLatitudex10000 = -3600000;
+    // PII mLongitudex10000 = -3600000;
+    // TBD mTotalBitRate = 0;
+
+    // TBD: some duration information (capture, paused)
+    //
+
+}
+
+void StagefrightRecorder::resetMetrics() {
+    ALOGV("resetMetrics");
+    // flush anything we have, restart the record
+    if (mAnalyticsDirty && mAnalyticsItem != NULL) {
+        updateMetrics();
+        if (mAnalyticsItem->count() > 0) {
+            mAnalyticsItem->setFinalized(true);
+            mAnalyticsItem->selfrecord();
+        }
+        delete mAnalyticsItem;
+        mAnalyticsItem = NULL;
+    }
+    mAnalyticsItem = new MediaAnalyticsItem(kKeyRecorder);
+    (void) mAnalyticsItem->generateSessionID();
+    mAnalyticsDirty = false;
 }
 
 status_t StagefrightRecorder::init() {
@@ -387,6 +468,7 @@
 
     // Additional check on the sample rate will be performed later.
     mSampleRate = sampleRate;
+
     return OK;
 }
 
@@ -399,6 +481,7 @@
 
     // Additional check on the number of channels will be performed later.
     mAudioChannels = channels;
+
     return OK;
 }
 
@@ -930,6 +1013,7 @@
     }
 
     if ((status == OK) && (!mStarted)) {
+        mAnalyticsDirty = true;
         mStarted = true;
 
         uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted;
@@ -1899,6 +1983,9 @@
         err = mWriter->stop();
         mWriter.clear();
     }
+
+    resetMetrics();
+
     mTotalPausedDurationUs = 0;
     mPauseStartTimeUs = 0;
 
@@ -2002,6 +2089,23 @@
     return OK;
 }
 
+status_t StagefrightRecorder::getMetrics(Parcel *reply) {
+    ALOGD("StagefrightRecorder::getMetrics");
+
+    if (reply == NULL) {
+        ALOGE("Null pointer argument");
+        return BAD_VALUE;
+    }
+
+    if (mAnalyticsItem == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    updateMetrics();
+    mAnalyticsItem->writeToParcel(reply);
+    return OK;
+}
+
 status_t StagefrightRecorder::dump(
         int fd, const Vector<String16>& args) const {
     ALOGV("dump");
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index b7d0b0e..38377d2 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -18,6 +18,7 @@
 
 #define STAGEFRIGHT_RECORDER_H_
 
+#include <media/MediaAnalyticsItem.h>
 #include <media/MediaRecorderBase.h>
 #include <camera/CameraParameters.h>
 #include <utils/String8.h>
@@ -67,6 +68,7 @@
     virtual status_t close();
     virtual status_t reset();
     virtual status_t getMaxAmplitude(int *max);
+    virtual status_t getMetrics(Parcel *reply);
     virtual status_t dump(int fd, const Vector<String16> &args) const;
     // Querying a SurfaceMediaSourcer
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const;
@@ -85,6 +87,11 @@
     int mOutputFd;
     sp<AudioSource> mAudioSourceNode;
 
+    MediaAnalyticsItem *mAnalyticsItem;
+    bool mAnalyticsDirty;
+    void resetMetrics();
+    void updateMetrics();
+
     audio_source_t mAudioSource;
     video_source mVideoSource;
     output_format mOutputFormat;
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index 8686560..56c558d 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -35,6 +35,7 @@
 
 LOCAL_SHARED_LIBRARIES :=       \
     libbinder                   \
+    libui                       \
     libmedia                    \
     libmediadrm                 \
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index e800d13..50d5343 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -199,7 +199,8 @@
       mSourceStarted(false),
       mPaused(false),
       mPausedByClient(true),
-      mPausedForBuffering(false) {
+      mPausedForBuffering(false),
+      mIsDrmProtected(false) {
     clearFlushComplete();
 }
 
@@ -1145,12 +1146,6 @@
                     case SHUTTING_DOWN_DECODER:
                         break; // Wait for shutdown to complete.
                     case FLUSHED:
-                        // Both secure audio/video now. Legacy Widevine did it for secure video.
-                        // Widevine source reads must stop before releasing the video decoder.
-                        if (mSource != NULL && mIsDrmProtected) {
-                            mSource->stop();
-                            mSourceStarted = false;
-                        }
                         getDecoder(audio)->initiateShutdown(); // In the middle of a seek.
                         *flushing = SHUTTING_DOWN_DECODER;     // Shut down.
                         break;
@@ -1574,12 +1569,6 @@
             *state = SHUTTING_DOWN_DECODER;
 
             ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video");
-            // Both secure audio/video now. Legacy Widevine did it for secure video only.
-            // Widevine source reads must stop before releasing the video decoder.
-            if (mSource != NULL && mIsDrmProtected) {
-                mSource->stop();
-                mSourceStarted = false;
-            }
             getDecoder(audio)->initiateShutdown();
             break;
         }
@@ -2724,7 +2713,11 @@
     // TODO change to ALOGV
     ALOGD("onReleaseDrm ");
 
-    mIsDrmProtected = true;
+    if (!mIsDrmProtected) {
+        ALOGW("onReleaseDrm: Unexpected. mIsDrmProtected is already false.");
+    }
+
+    mIsDrmProtected = false;
 
     status_t status;
     if (mCrypto != NULL) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 5689e95..9a2224e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -37,7 +37,7 @@
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
-
+#include <media/stagefright/SurfaceUtils.h>
 #include <gui/Surface.h>
 
 #include "avc_utils.h"
@@ -232,21 +232,21 @@
                 //
                 // at this point MediaPlayerService::client has already connected to the
                 // surface, which MediaCodec does not expect
-                err = native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+                err = nativeWindowDisconnect(surface.get(), "kWhatSetVideoSurface(surface)");
                 if (err == OK) {
                     err = mCodec->setSurface(surface);
                     ALOGI_IF(err, "codec setSurface returned: %d", err);
                     if (err == OK) {
                         // reconnect to the old surface as MPS::Client will expect to
                         // be able to disconnect from it.
-                        (void)native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
+                        (void)nativeWindowConnect(mSurface.get(), "kWhatSetVideoSurface(mSurface)");
                         mSurface = surface;
                     }
                 }
                 if (err != OK) {
                     // reconnect to the new surface on error as MPS::Client will expect to
                     // be able to disconnect from it.
-                    (void)native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+                    (void)nativeWindowConnect(surface.get(), "kWhatSetVideoSurface(err)");
                 }
             }
 
@@ -313,8 +313,7 @@
     status_t err;
     if (mSurface != NULL) {
         // disconnect from surface as MediaCodec will reconnect
-        err = native_window_api_disconnect(
-                mSurface.get(), NATIVE_WINDOW_API_MEDIA);
+        err = nativeWindowDisconnect(mSurface.get(), "onConfigure");
         // We treat this as a warning, as this is a preparatory step.
         // Codec will try to connect to the surface, which is where
         // any error signaling will occur.
@@ -510,8 +509,7 @@
 
         if (mSurface != NULL) {
             // reconnect to surface as MediaCodec disconnected from it
-            status_t error =
-                    native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
+            status_t error = nativeWindowConnect(mSurface.get(), "onShutdown");
             ALOGW_IF(error != NO_ERROR,
                     "[%s] failed to connect to native window, error=%d",
                     mComponentName.c_str(), error);
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp
index 7c2523d..f480c16 100644
--- a/media/libnbaio/NBLog.cpp
+++ b/media/libnbaio/NBLog.cpp
@@ -21,6 +21,7 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/prctl.h>
 #include <time.h>
 #include <new>
 #include <audio_utils/roundup.h>
@@ -28,6 +29,8 @@
 #include <utils/Log.h>
 #include <utils/String8.h>
 
+#include <queue>
+
 namespace android {
 
 int NBLog::Entry::readAt(size_t offset) const
@@ -47,6 +50,120 @@
 
 // ---------------------------------------------------------------------------
 
+NBLog::FormatEntry::FormatEntry(const uint8_t *entry) : mEntry(entry) {
+    ALOGW_IF(entry[offsetof(struct entry, type)] != EVENT_START_FMT,
+        "Created format entry with invalid event type %d", entry[offsetof(struct entry, type)]);
+}
+
+NBLog::FormatEntry::FormatEntry(const NBLog::FormatEntry::iterator &it) : FormatEntry(it.ptr) {}
+
+const char *NBLog::FormatEntry::formatString() const {
+    return (const char*) mEntry + offsetof(entry, data);
+}
+
+size_t NBLog::FormatEntry::formatStringLength() const {
+    return mEntry[offsetof(entry, length)];
+}
+
+NBLog::FormatEntry::iterator NBLog::FormatEntry::args() const {
+    auto it = begin();
+    // Second entry can be author or timestamp. Skip author if present
+    if ((++it)->type == EVENT_AUTHOR) {
+        ++it;
+    }
+    return ++it;
+}
+
+timespec NBLog::FormatEntry::timestamp() const {
+    auto it = begin();
+    if ((++it)->type != EVENT_TIMESTAMP) {
+        ++it;
+    }
+    return it.payload<timespec>();
+}
+
+pid_t NBLog::FormatEntry::author() const {
+    auto it = begin();
+    if ((++it)->type == EVENT_AUTHOR) {
+        return it.payload<int>();
+    }
+    return -1;
+}
+
+size_t NBLog::FormatEntry::copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const {
+    auto it = this->begin();
+    // copy fmt start entry
+    it.copyTo(dst);
+    // insert author entry
+    size_t authorEntrySize = NBLog::Entry::kOverhead + sizeof(author);
+    uint8_t authorEntry[authorEntrySize];
+    authorEntry[offsetof(entry, type)] = EVENT_AUTHOR;
+    authorEntry[offsetof(entry, length)] =
+        authorEntry[authorEntrySize + NBLog::Entry::kPreviousLengthOffset] =
+        sizeof(author);
+    *(int*) (&authorEntry[offsetof(entry, data)]) = author;
+    dst->write(authorEntry, authorEntrySize);
+    // copy rest of entries
+    while ((++it)->type != EVENT_END_FMT) {
+        it.copyTo(dst);
+    }
+    it.copyTo(dst);
+    ++it;
+    return it - this->begin();
+}
+
+void NBLog::FormatEntry::iterator::copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst) const {
+    size_t length = ptr[offsetof(entry, length)] + NBLog::Entry::kOverhead;
+    dst->write(ptr, length);
+}
+
+void NBLog::FormatEntry::iterator::copyData(uint8_t *dst) const {
+    memcpy((void*) dst, ptr + offsetof(entry, data), ptr[offsetof(entry, length)]);
+}
+
+NBLog::FormatEntry::iterator NBLog::FormatEntry::begin() const {
+    return iterator(mEntry);
+}
+
+NBLog::FormatEntry::iterator::iterator(const uint8_t *entry)
+    : ptr(entry) {}
+
+NBLog::FormatEntry::iterator::iterator(const NBLog::FormatEntry::iterator &other)
+    : ptr(other.ptr) {}
+
+const NBLog::FormatEntry::entry& NBLog::FormatEntry::iterator::operator*() const {
+    return *(entry*) ptr;
+}
+
+const NBLog::FormatEntry::entry* NBLog::FormatEntry::iterator::operator->() const {
+    return (entry*) ptr;
+}
+
+NBLog::FormatEntry::iterator& NBLog::FormatEntry::iterator::operator++() {
+    ptr += ptr[offsetof(entry, length)] + NBLog::Entry::kOverhead;
+    return *this;
+}
+
+NBLog::FormatEntry::iterator& NBLog::FormatEntry::iterator::operator--() {
+    ptr -= ptr[NBLog::Entry::kPreviousLengthOffset] + NBLog::Entry::kOverhead;
+    return *this;
+}
+
+int NBLog::FormatEntry::iterator::operator-(const NBLog::FormatEntry::iterator &other) const {
+    return ptr - other.ptr;
+}
+
+bool NBLog::FormatEntry::iterator::operator!=(const iterator &other) const {
+    return ptr != other.ptr;
+}
+
+bool NBLog::FormatEntry::iterator::hasConsistentLength() const {
+    return ptr[offsetof(entry, length)] == ptr[ptr[offsetof(entry, length)] +
+        NBLog::Entry::kOverhead + NBLog::Entry::kPreviousLengthOffset];
+}
+
+// ---------------------------------------------------------------------------
+
 #if 0   // FIXME see note in NBLog.h
 NBLog::Timeline::Timeline(size_t size, void *shared)
     : mSize(roundup(size)), mOwn(shared == NULL),
@@ -74,7 +191,7 @@
 // ---------------------------------------------------------------------------
 
 NBLog::Writer::Writer()
-    : mShared(NULL), mFifo(NULL), mFifoWriter(NULL), mEnabled(false)
+    : mShared(NULL), mFifo(NULL), mFifoWriter(NULL), mEnabled(false), mPidTag(NULL), mPidTagSize(0)
 {
 }
 
@@ -86,6 +203,18 @@
       mFifoWriter(mFifo != NULL ? new audio_utils_fifo_writer(*mFifo) : NULL),
       mEnabled(mFifoWriter != NULL)
 {
+    // caching pid and process name
+    pid_t id = ::getpid();
+    char procName[16];
+    int status = prctl(PR_GET_NAME, procName);
+    if (status) {  // error getting process name
+        procName[0] = '\0';
+    }
+    size_t length = strlen(procName);
+    mPidTagSize = length + sizeof(pid_t);
+    mPidTag = new char[mPidTagSize];
+    memcpy(mPidTag, &id, sizeof(pid_t));
+    memcpy(mPidTag + sizeof(pid_t), procName, length);
 }
 
 NBLog::Writer::Writer(const sp<IMemory>& iMemory, size_t size)
@@ -98,6 +227,7 @@
 {
     delete mFifoWriter;
     delete mFifo;
+    delete[] mPidTag;
 }
 
 void NBLog::Writer::log(const char *string)
@@ -181,15 +311,7 @@
     if (!mEnabled) {
         return;
     }
-    pid_t id = ::getpid();
-    // TODO: append process name to pid
-    // const char* path = sprintf("/proc/%d/status", id);
-    // FILE* f = fopen(path);
-    // size_t length = 30
-    // char buffer[length];
-    // getline(&buffer, &length, f);
-    // char* pidTag = sprintf("")
-    log(EVENT_PID, &id, sizeof(pid_t));
+    log(EVENT_PID, mPidTag, mPidTagSize);
 }
 
 void NBLog::Writer::logStart(const char *fmt)
@@ -271,10 +393,12 @@
             --p;
             break;
 
+        case '%':
+            break;
+
         default:
             ALOGW("NBLog Writer parsed invalid format specifier: %c", *p);
             break;
-        // the '%' case is handled using the formatted string in the reader
         }
     }
     Writer::logEnd();
@@ -455,53 +579,53 @@
     delete mFifo;
 }
 
-void NBLog::Reader::dump(int fd, size_t indent)
+std::unique_ptr<NBLog::Reader::Snapshot> NBLog::Reader::getSnapshot()
 {
     if (mFifoReader == NULL) {
-        return;
+        return std::unique_ptr<NBLog::Reader::Snapshot>(new Snapshot());
     }
     // make a copy to avoid race condition with writer
     size_t capacity = mFifo->capacity();
 
-    // TODO Stack-based allocation of large objects may fail.
-    //      Currently the log buffers are a page or two, which should be safe.
-    //      But if the log buffers ever get a lot larger,
-    //      then change this to allocate from heap when necessary.
-    static size_t kReasonableStackObjectSize = 32768;
-    ALOGW_IF(capacity > kReasonableStackObjectSize, "Stack-based allocation of object may fail");
-    uint8_t copy[capacity];
+    std::unique_ptr<Snapshot> snapshot(new Snapshot(capacity));
 
-    size_t lost;
-    ssize_t actual = mFifoReader->read(copy, capacity, NULL /*timeout*/, &lost);
+    ssize_t actual = mFifoReader->read((void*) snapshot->mData, capacity, NULL /*timeout*/,
+                                       &(snapshot->mLost));
     ALOG_ASSERT(actual <= capacity);
-    size_t avail = actual > 0 ? (size_t) actual : 0;
-    size_t i = avail;
-    Event event;
-    size_t length;
+    snapshot->mAvail = actual > 0 ? (size_t) actual : 0;
+    return snapshot;
+}
+
+void NBLog::Reader::dump(int fd, size_t indent, NBLog::Reader::Snapshot &snapshot)
+{
+    NBLog::FormatEntry::iterator entry(snapshot.data() + snapshot.available());
+    NBLog::FormatEntry::iterator prevEntry = entry;
+    --prevEntry;
+    NBLog::FormatEntry::iterator start(snapshot.data());
+
     struct timespec ts;
     time_t maxSec = -1;
-    while (i >= Entry::kOverhead) {
-        length = copy[i - 1];
-        if (length + Entry::kOverhead > i || copy[i - length - 2] != length) {
+    while (entry - start >= (int) Entry::kOverhead) {
+        if (prevEntry - start < 0 || !prevEntry.hasConsistentLength()) {
             break;
         }
-        event = (Event) copy[i - length - Entry::kOverhead];
-        if (event == EVENT_TIMESTAMP) {
-            if (length != sizeof(struct timespec)) {
+        if (prevEntry->type == EVENT_TIMESTAMP) {
+            if (prevEntry->length != sizeof(struct timespec)) {
                 // corrupt
                 break;
             }
-            memcpy(&ts, &copy[i - length - 1], sizeof(struct timespec));
+            prevEntry.copyData((uint8_t*) &ts);
             if (ts.tv_sec > maxSec) {
                 maxSec = ts.tv_sec;
             }
         }
-        i -= length + Entry::kOverhead;
+        --entry;
+        --prevEntry;
     }
     mFd = fd;
     mIndent = indent;
     String8 timestamp, body;
-    lost += i;
+    size_t lost = snapshot.lost() + (entry - start);
     if (lost > 0) {
         body.appendFormat("warning: lost %zu bytes worth of events", lost);
         // TODO timestamp empty here, only other choice to wait for the first timestamp event in the
@@ -517,30 +641,29 @@
         timestamp.appendFormat("[%*s]", (int) width + 4, "");
     }
     bool deferredTimestamp = false;
-    while (i < avail) {
-        event = (Event) copy[i];
-        length = copy[i + 1];
-        const void *data = &copy[i + 2];
-        size_t advance = length + Entry::kOverhead;
-        switch (event) {
+    NBLog::FormatEntry::iterator end(snapshot.data() + snapshot.available());
+
+    while (entry != end) {
+        switch (entry->type) {
+#if 0
         case EVENT_STRING:
-            body.appendFormat("%.*s", (int) length, (const char *) data);
+            body.appendFormat("%.*s", (int) entry.length(), entry.data());
             break;
         case EVENT_TIMESTAMP: {
             // already checked that length == sizeof(struct timespec);
-            memcpy(&ts, data, sizeof(struct timespec));
+            entry.copyData((const uint8_t*) &ts);
             long prevNsec = ts.tv_nsec;
             long deltaMin = LONG_MAX;
             long deltaMax = -1;
             long deltaTotal = 0;
-            size_t j = i;
+            auto aux(entry);
             for (;;) {
-                j += sizeof(struct timespec) + 3 /*Entry::kOverhead?*/;
-                if (j >= avail || (Event) copy[j] != EVENT_TIMESTAMP) {
+                ++aux;
+                if (end - aux >= 0 || aux.type() != EVENT_TIMESTAMP) {
                     break;
                 }
                 struct timespec tsNext;
-                memcpy(&tsNext, &copy[j + 2], sizeof(struct timespec));
+                aux.copyData((const uint8_t*) &tsNext);
                 if (tsNext.tv_sec != ts.tv_sec) {
                     break;
                 }
@@ -557,7 +680,7 @@
                 deltaTotal += delta;
                 prevNsec = tsNext.tv_nsec;
             }
-            size_t n = (j - i) / (sizeof(struct timespec) + 3 /*Entry::kOverhead?*/);
+            size_t n = (aux - entry) / (sizeof(struct timespec) + 3 /*Entry::kOverhead?*/);
             if (deferredTimestamp) {
                 dumpLine(timestamp, body);
                 deferredTimestamp = false;
@@ -568,36 +691,37 @@
                         (int) ts.tv_sec, (int) (ts.tv_nsec / 1000000),
                         (int) ((ts.tv_nsec + deltaTotal) / 1000000),
                         (int) (deltaMin / 1000000), (int) (deltaMax / 1000000));
-                i = j;
-                advance = 0;
+                entry = aux;
+                // advance = 0;
                 break;
             }
             timestamp.appendFormat("[%d.%03d]", (int) ts.tv_sec,
                     (int) (ts.tv_nsec / 1000000));
             deferredTimestamp = true;
-            } break;
+            }
+            break;
         case EVENT_INTEGER:
-            appendInt(&body, data);
+            appendInt(&body, entry.data());
             break;
         case EVENT_FLOAT:
-            appendFloat(&body, data);
+            appendFloat(&body, entry.data());
             break;
         case EVENT_PID:
-            appendPID(&body, data);
+            appendPID(&body, entry.data(), entry.length());
             break;
+#endif
         case EVENT_START_FMT:
-            advance += handleFormat((const char*) &copy[i + 2], length,
-                                    &copy[i + Entry::kOverhead + length], &timestamp, &body);
+            // right now, this is the only supported case
+            entry = handleFormat(FormatEntry(entry), &timestamp, &body);
             break;
         case EVENT_END_FMT:
             body.appendFormat("warning: got to end format event");
             break;
         case EVENT_RESERVED:
         default:
-            body.appendFormat("warning: unknown event %d", event);
+            body.appendFormat("warning: unknown event %d", entry->type);
             break;
         }
-        i += advance;
 
         if (!body.isEmpty()) {
             dumpLine(timestamp, body);
@@ -609,6 +733,13 @@
     }
 }
 
+void NBLog::Reader::dump(int fd, size_t indent)
+{
+    // get a snapshot, dump it
+    std::unique_ptr<Snapshot> snap = getSnapshot();
+    dump(fd, indent, *snap);
+}
+
 void NBLog::Reader::dumpLine(const String8 &timestamp, String8 &body)
 {
     if (mFd >= 0) {
@@ -642,86 +773,189 @@
     body->appendFormat("<%f>", f);
 }
 
-void NBLog::appendPID(String8 *body, const void* data) {
+void NBLog::appendPID(String8 *body, const void* data, size_t length) {
     pid_t id = *((pid_t*) data);
-    body->appendFormat("<PID: %d>", id);
+    char * name = &((char*) data)[sizeof(pid_t)];
+    body->appendFormat("<PID: %d, name: %.*s>", id, (int) (length - sizeof(pid_t)), name);
 }
 
-int NBLog::handleFormat(const char *fmt, size_t fmt_length, const uint8_t *data,
-                        String8 *timestamp, String8 *body) {
-    if (data[0] != EVENT_TIMESTAMP) {
-        ALOGW("NBLog Reader Expected timestamp event %d, got %d", EVENT_TIMESTAMP, data[0]);
-    }
-    struct timespec ts;
-    memcpy(&ts, &data[2], sizeof(ts));
+NBLog::FormatEntry::iterator NBLog::Reader::handleFormat(const FormatEntry &fmtEntry,
+                                                         String8 *timestamp,
+                                                         String8 *body) {
+    // log timestamp
+    struct timespec ts = fmtEntry.timestamp();
     timestamp->clear();
     timestamp->appendFormat("[%d.%03d]", (int) ts.tv_sec,
                     (int) (ts.tv_nsec / 1000000));
-    size_t data_offset = Entry::kOverhead + sizeof ts;
+
+    // log author (if present)
+    handleAuthor(fmtEntry, body);
+
+    // log string
+    NBLog::FormatEntry::iterator arg = fmtEntry.args();
+
+    const char* fmt = fmtEntry.formatString();
+    size_t fmt_length = fmtEntry.formatStringLength();
 
     for (size_t fmt_offset = 0; fmt_offset < fmt_length; ++fmt_offset) {
         if (fmt[fmt_offset] != '%') {
             body->append(&fmt[fmt_offset], 1); // TODO optimize to write consecutive strings at once
             continue;
         }
+        // case "%%""
         if (fmt[++fmt_offset] == '%') {
             body->append("%");
             continue;
         }
+        // case "%\0"
         if (fmt_offset == fmt_length) {
             continue;
         }
 
-        NBLog::Event event = (NBLog::Event) data[data_offset];
-        size_t length = data[data_offset + 1];
+        NBLog::Event event = (NBLog::Event) arg->type;
+        size_t length = arg->length;
 
         // TODO check length for event type is correct
-        if(length != data[data_offset + length + 2]) {
-            ALOGW("NBLog Reader recieved different lengths %zu and %d for event %d", length,
-                  data[data_offset + length + 2], event);
+        if (!arg.hasConsistentLength()) {
+            // TODO: corrupt, resync buffer
             body->append("<invalid entry>");
             ++fmt_offset;
             continue;
         }
 
+        if (event == EVENT_END_FMT) {
+            break;
+        }
+
         // TODO: implement more complex formatting such as %.3f
-        void * datum = (void*) &data[data_offset + 2]; // pointer to the current event data
+        const uint8_t *datum = arg->data; // pointer to the current event args
         switch(fmt[fmt_offset])
         {
         case 's': // string
-            ALOGW_IF(event != EVENT_STRING, "NBLog Reader incompatible event for string specifier: %d", event);
+            ALOGW_IF(event != EVENT_STRING,
+                "NBLog Reader incompatible event for string specifier: %d", event);
             body->append((const char*) datum, length);
             break;
 
         case 't': // timestamp
-            ALOGW_IF(event != EVENT_TIMESTAMP, "NBLog Reader incompatible event for timestamp specifier: %d", event);
+            ALOGW_IF(event != EVENT_TIMESTAMP,
+                "NBLog Reader incompatible event for timestamp specifier: %d", event);
             appendTimestamp(body, datum);
             break;
 
         case 'd': // integer
-            ALOGW_IF(event != EVENT_INTEGER, "NBLog Reader incompatible event for integer specifier: %d", event);
+            ALOGW_IF(event != EVENT_INTEGER,
+                "NBLog Reader incompatible event for integer specifier: %d", event);
             appendInt(body, datum);
-
             break;
 
         case 'f': // float
-            ALOGW_IF(event != EVENT_FLOAT, "NBLog Reader incompatible event for float specifier: %d", event);
+            ALOGW_IF(event != EVENT_FLOAT,
+                "NBLog Reader incompatible event for float specifier: %d", event);
             appendFloat(body, datum);
             break;
 
         case 'p': // pid
-            ALOGW_IF(event != EVENT_PID, "NBLog Reader incompatible event for pid specifier: %d", event);
-            appendPID(body, datum);
+            ALOGW_IF(event != EVENT_PID,
+                "NBLog Reader incompatible event for pid specifier: %d", event);
+            appendPID(body, datum, length);
             break;
 
         default:
             ALOGW("NBLog Reader encountered unknown character %c", fmt[fmt_offset]);
         }
-
-        data_offset += length + Entry::kOverhead;
-
+        ++arg;
     }
-    return data_offset + Entry::kOverhead; // data offset + size of END_FMT event
+    ALOGW_IF(arg->type != EVENT_END_FMT, "Expected end of format, got %d", arg->type);
+    ++arg;
+    return arg;
+}
+
+// ---------------------------------------------------------------------------
+
+NBLog::Merger::Merger(const void *shared, size_t size):
+      mBuffer(NULL),
+      mShared((Shared *) shared),
+      mFifo(mShared != NULL ?
+        new audio_utils_fifo(size, sizeof(uint8_t),
+            mShared->mBuffer, mShared->mRear, NULL /*throttlesFront*/) : NULL),
+      mFifoWriter(mFifo != NULL ? new audio_utils_fifo_writer(*mFifo) : NULL)
+      {}
+
+void NBLog::Merger::addReader(const NBLog::NamedReader &reader) {
+    mNamedReaders.push_back(reader);
+}
+
+// items placed in priority queue during merge
+// composed by a timestamp and the index of the snapshot where the timestamp came from
+struct MergeItem
+{
+    struct timespec ts;
+    int index;
+    MergeItem(struct timespec ts, int index): ts(ts), index(index) {}
+};
+
+// operators needed for priority queue in merge
+bool operator>(const struct timespec &t1, const struct timespec &t2) {
+    return t1.tv_sec > t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec);
+}
+
+bool operator>(const struct MergeItem &i1, const struct MergeItem &i2) {
+    return i1.ts > i2.ts ||
+        (i1.ts.tv_sec == i2.ts.tv_sec && i1.ts.tv_nsec == i2.ts.tv_nsec && i1.index > i2.index);
+}
+
+// Merge registered readers, sorted by timestamp
+void NBLog::Merger::merge() {
+    int nLogs = mNamedReaders.size();
+    std::vector<std::unique_ptr<NBLog::Reader::Snapshot>> snapshots(nLogs);
+    for (int i = 0; i < nLogs; ++i) {
+        snapshots[i] = mNamedReaders[i].reader()->getSnapshot();
+    }
+    // initialize offsets
+    std::vector<size_t> offsets(nLogs, 0);
+    // TODO custom heap implementation could allow to update top, improving performance
+    // for bursty buffers
+    std::priority_queue<MergeItem, std::vector<MergeItem>, std::greater<MergeItem>> timestamps;
+    for (int i = 0; i < nLogs; ++i)
+    {
+        if (snapshots[i]->available() > 0) {
+            timespec ts = FormatEntry(snapshots[i]->data()).timestamp();
+            MergeItem item(ts, i);
+            timestamps.push(item);
+        }
+    }
+
+    while (!timestamps.empty()) {
+        // find minimum timestamp
+        int index = timestamps.top().index;
+        // copy it to the log
+        size_t length = FormatEntry(snapshots[index]->data() + offsets[index]).copyTo(
+            mFifoWriter, index);
+        // update data structures
+        offsets[index] += length;
+        ALOGW_IF(offsets[index] > snapshots[index]->available(), "Overflown snapshot capacity");
+        timestamps.pop();
+        if (offsets[index] != snapshots[index]->available()) {
+            timespec ts = FormatEntry(snapshots[index]->data() + offsets[index]).timestamp();
+            MergeItem item(ts, index);
+            timestamps.emplace(item);
+        }
+    }
+}
+
+const std::vector<NBLog::NamedReader> *NBLog::Merger::getNamedReaders() const {
+    return &mNamedReaders;
+}
+
+NBLog::MergeReader::MergeReader(const void *shared, size_t size, Merger &merger)
+    : Reader(shared, size), mNamedReaders(merger.getNamedReaders()) {}
+
+size_t NBLog::MergeReader::handleAuthor(const NBLog::FormatEntry &fmtEntry, String8 *body) {
+    int author = fmtEntry.author();
+    const char* name = (*mNamedReaders)[author].name();
+    body->appendFormat("%s: ", name);
+    return NBLog::Entry::kOverhead + sizeof(author);
 }
 
 }   // namespace android
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 3f56725..78f28ae 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -61,7 +61,7 @@
 #include "include/SharedMemoryBuffer.h"
 #include "omx/OMXUtils.h"
 
-#include <android/hidl/memory/1.0/IAllocator.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include "omx/hal/1.0/utils/WOmxNode.h"
 
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 410dbc9..d044754 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -115,6 +115,7 @@
         libRScpp \
         libhidlbase \
         libhidlmemory \
+        android.hidl.allocator@1.0 \
         android.hidl.memory@1.0 \
         android.hardware.media.omx@1.0 \
         android.hardware.media.omx@1.0-utils \
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index cbd5802..03010ab 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2914,7 +2914,7 @@
             return ALREADY_EXISTS;
         }
 
-        err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+        err = nativeWindowConnect(surface.get(), "connectToSurface");
         if (err == OK) {
             // Require a fresh set of buffers after each connect by using a unique generation
             // number. Rely on the fact that max supported process id by Linux is 2^22.
@@ -2929,12 +2929,12 @@
             // This is needed as the consumer may be holding onto stale frames that it can reattach
             // to this surface after disconnect/connect, and those free frames would inherit the new
             // generation number. Disconnecting after setting a unique generation prevents this.
-            native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
-            err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+            nativeWindowDisconnect(surface.get(), "connectToSurface(reconnect)");
+            err = nativeWindowConnect(surface.get(), "connectToSurface(reconnect)");
         }
 
         if (err != OK) {
-            ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
+            ALOGE("nativeWindowConnect returned an error: %s (%d)", strerror(-err), err);
         }
     }
     // do not return ALREADY_EXISTS unless surfaces are the same
@@ -2946,9 +2946,9 @@
     if (mSurface != NULL) {
         // Resetting generation is not technically needed, but there is no need to keep it either
         mSurface->setGenerationNumber(0);
-        err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
+        err = nativeWindowDisconnect(mSurface.get(), "disconnectFromSurface");
         if (err != OK) {
-            ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
+            ALOGW("nativeWindowDisconnect returned an error: %s (%d)", strerror(-err), err);
         }
         // assume disconnected even on error
         mSurface.clear();
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index 568837a..82e959e 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -31,15 +31,15 @@
 
     // In some cases we need to reconnect so that we can dequeue all buffers
     if (reconnect) {
-        err = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+        err = nativeWindowDisconnect(nativeWindow, "setNativeWindowSizeFormatAndUsage");
         if (err != NO_ERROR) {
-            ALOGE("native_window_api_disconnect failed: %s (%d)", strerror(-err), -err);
+            ALOGE("nativeWindowDisconnect failed: %s (%d)", strerror(-err), -err);
             return err;
         }
 
-        err = native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+        err = nativeWindowConnect(nativeWindow, "setNativeWindowSizeFormatAndUsage");
         if (err != NO_ERROR) {
-            ALOGE("native_window_api_connect failed: %s (%d)", strerror(-err), -err);
+            ALOGE("nativeWindowConnect failed: %s (%d)", strerror(-err), -err);
             return err;
         }
     }
@@ -127,7 +127,7 @@
     // We need to reconnect to the ANativeWindow as a CPU client to ensure that
     // no frames get dropped by SurfaceFlinger assuming that these are video
     // frames.
-    err = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+    err = nativeWindowDisconnect(nativeWindow, "pushBlankBuffersToNativeWindow");
     if (err != NO_ERROR) {
         ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", strerror(-err), -err);
         return err;
@@ -136,7 +136,7 @@
     err = native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_CPU);
     if (err != NO_ERROR) {
         ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
-        (void)native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+        (void)nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err)");
         return err;
     }
 
@@ -219,7 +219,7 @@
         }
     }
 
-    err2 = native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+    err2 = nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err2)");
     if (err2 != NO_ERROR) {
         ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
         if (err == NO_ERROR) {
@@ -230,5 +230,22 @@
     return err;
 }
 
+status_t nativeWindowConnect(ANativeWindow *surface, const char *reason) {
+    ALOGD("connecting to surface %p, reason %s", surface, reason);
+
+    status_t err = native_window_api_connect(surface, NATIVE_WINDOW_API_MEDIA);
+    ALOGE_IF(err != OK, "Failed to connect to surface %p, err %d", surface, err);
+
+    return err;
+}
+
+status_t nativeWindowDisconnect(ANativeWindow *surface, const char *reason) {
+    ALOGD("disconnecting from surface %p, reason %s", surface, reason);
+
+    status_t err = native_window_api_disconnect(surface, NATIVE_WINDOW_API_MEDIA);
+    ALOGE_IF(err != OK, "Failed to disconnect from surface %p, err %d", surface, err);
+
+    return err;
+}
 }  // namespace android
 
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
index 9e7a3be..b057ffe 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -30,7 +30,6 @@
 #include <media/stagefright/Utils.h>
 #include <OMX_IndexExt.h>
 #include <OMX_VideoExt.h>
-#include <ui/Rect.h>
 
 #include "ih264_typedefs.h"
 #include "iv2.h"
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index d5a26d3..6d4cb69 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -30,8 +30,6 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
-#include <ui/Rect.h>
-#include <ui/GraphicBufferMapper.h>
 
 #include "SoftMPEG4Encoder.h"
 
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
index ba74740..1e82727 100644
--- a/media/libstagefright/colorconversion/Android.mk
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -10,6 +10,9 @@
         $(TOP)/hardware/msm7k \
         $(TOP)/external/libyuv/files/include
 
+LOCAL_SHARED_LIBRARIES := \
+        libui \
+
 LOCAL_STATIC_LIBRARIES := \
         libyuv_static \
 
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index bbc4d26..54487b3 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -24,7 +24,8 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <system/window.h>
 #include <ui/GraphicBufferMapper.h>
-#include <gui/IGraphicBufferProducer.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/Rect.h>
 
 namespace android {
 
diff --git a/media/libstagefright/filters/Android.mk b/media/libstagefright/filters/Android.mk
index 830d2aa..07b2eb8 100644
--- a/media/libstagefright/filters/Android.mk
+++ b/media/libstagefright/filters/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 
 LOCAL_SHARED_LIBRARIES := \
+        libgui \
         libmedia \
         libhidlmemory \
 
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index f7bd3f2..0557d95 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -29,12 +29,13 @@
     shared_libs: [
         "libbinder",
         "libutils",
+        "libui",
         "libcutils",
         "liblog",
         "libpowermanager",
     ],
 
-    export_shared_lib_headers: ["libbinder"],
+    export_shared_lib_headers: ["libbinder", "libui"],
 
     cflags: [
         "-Wno-multichar",
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index c7e60ca..8e08d15 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -30,6 +30,7 @@
 #include <android/hidl/memory/1.0/IMemory.h>
 
 namespace android {
+class GraphicBuffer;
 class IOMXBufferSource;
 class IOMXObserver;
 struct OMXMaster;
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index adf846a..c49403d 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -30,8 +30,8 @@
 #include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 
-#include <ui/GraphicBuffer.h>
 #include <ui/GraphicBufferMapper.h>
+#include <ui/Rect.h>
 
 #include <OMX_IndexExt.h>
 
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp b/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp
index ecd1db5..433a8b8 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "WOmxObserver-impl"
 #include "WOmxObserver.h"
 
 #include <vector>
@@ -43,7 +44,10 @@
         wrapAs(&tMessages[i], &handles[i], message);
         ++i;
     }
-    mBase->onMessages(tMessages);
+    auto transResult = mBase->onMessages(tMessages);
+    if (!transResult.isOk()) {
+        ALOGE("LWOmxObserver::onMessages transaction failed");
+    }
     for (auto& handle : handles) {
         native_handle_close(handle);
         native_handle_delete(handle);
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp b/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp
index db971f8..bab6a09 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "WOmxObserver-utils"
 #include "WOmxObserver.h"
 
 #include <vector>
@@ -43,7 +44,10 @@
         wrapAs(&tMessages[i], &handles[i], message);
         ++i;
     }
-    mBase->onMessages(tMessages);
+    auto transResult = mBase->onMessages(tMessages);
+    if (!transResult.isOk()) {
+        ALOGE("LWOmxObserver::onMessages transaction failed");
+    }
     for (auto& handle : handles) {
         native_handle_close(handle);
         native_handle_delete(handle);
diff --git a/media/libstagefright/omx/tests/OMXHarness.h b/media/libstagefright/omx/tests/OMXHarness.h
index 022707f..94a37da 100644
--- a/media/libstagefright/omx/tests/OMXHarness.h
+++ b/media/libstagefright/omx/tests/OMXHarness.h
@@ -24,7 +24,7 @@
 #include <utils/threads.h>
 
 #include <binder/MemoryDealer.h>
-#include <android/hidl/memory/1.0/IAllocator.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <OMX_Component.h>
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3989f95..8bf1688 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3041,12 +3041,12 @@
             }
 #if 0
             // logFormat example
-            if (!(z % 100)) {
+            if (z % 100 == 0) {
                 timespec ts;
                 clock_gettime(CLOCK_MONOTONIC, &ts);
-                LOGF("This is an integer %d, this is a float %f, this is my "
+                LOGT("This is an integer %d, this is a float %f, this is my "
                     "pid %p %% %s %t", 42, 3.14, "and this is a timestamp", ts);
-                LOGF("A deceptive null-terminated string %\0");
+                LOGT("A deceptive null-terminated string %\0");
             }
             ++z;
 #endif
diff --git a/services/audioflinger/TypedLogger.cpp b/services/audioflinger/TypedLogger.cpp
index b5b1bc5..e08f6f6 100644
--- a/services/audioflinger/TypedLogger.cpp
+++ b/services/audioflinger/TypedLogger.cpp
@@ -1,19 +1,19 @@
 /*
-*
-* Copyright 2017, 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.
-*/
+ *
+ * Copyright 2017, 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 "AudioFlinger"
 //#define LOG_NDEBUG 0
@@ -22,4 +22,6 @@
 #include <pthread.h>
 #include "TypedLogger.h"
 
-thread_local android::NBLog::Writer *logWriterTLS;
+namespace android {
+thread_local NBLog::Writer *logWriterTLS;
+}
diff --git a/services/audioflinger/TypedLogger.h b/services/audioflinger/TypedLogger.h
index 2d71ab4..0b23c7c 100644
--- a/services/audioflinger/TypedLogger.h
+++ b/services/audioflinger/TypedLogger.h
@@ -1,29 +1,30 @@
 /*
-*
-* Copyright 2017, 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.
-*/
+ *
+ * Copyright 2017, 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.
+ */
 
-#ifndef TYPED_LOGGER_H
-#define TYPED_LOGGER_H
+#ifndef ANDROID_TYPED_LOGGER_H
+#define ANDROID_TYPED_LOGGER_H
 
 #include <media/nbaio/NBLog.h>
+#define LOGT(fmt, ...) logWriterTLS->logFormat(fmt, ##__VA_ARGS__) // TODO: check null pointer
 
+namespace android {
 extern "C" {
-    extern thread_local android::NBLog::Writer *logWriterTLS;
+extern thread_local NBLog::Writer *logWriterTLS;
 }
+} // namespace android
 
-#define LOGF(fmt, ...) logWriterTLS->logFormat(fmt, ##__VA_ARGS__)
-
-#endif
\ No newline at end of file
+#endif // ANDROID_TYPED_LOGGER_H
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.h b/services/camera/libcameraservice/gui/RingBufferConsumer.h
index 28dc5d5..2bafe4a 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.h
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.h
@@ -19,18 +19,16 @@
 
 #include <gui/BufferItem.h>
 #include <gui/ConsumerBase.h>
+#include <gui/BufferQueue.h>
 
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
 #include <utils/List.h>
 
 #define ANDROID_GRAPHICS_RINGBUFFERCONSUMER_JNI_ID "mRingBufferConsumer"
 
 namespace android {
 
+class String8;
+
 /**
  * The RingBufferConsumer maintains a ring buffer of BufferItem objects,
  * (which are 'acquired' as long as they are part of the ring buffer, and
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index cb14bb5..6dcc35c 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SHARED_LIBRARIES := \
     libmedia \
     libbinder \
+    libgui \
     libutils \
     liblog \
     libstagefright_omx
@@ -26,6 +27,7 @@
     libmediacodecservice \
     libbinder \
     libutils \
+    libgui \
     liblog \
     libbase \
     libavservices_minijail \
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index ab2f925..4c81436 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -26,7 +26,7 @@
 
 namespace android {
 
-static const char kDeadlockedString[] = "MediaLogService may be deadlocked\n";
+// static const char kDeadlockedString[] = "MediaLogService may be deadlocked\n";
 
 void MediaLogService::registerWriter(const sp<IMemory>& shared, size_t size, const char *name)
 {
@@ -36,9 +36,10 @@
         return;
     }
     sp<NBLog::Reader> reader(new NBLog::Reader(shared, size));
-    NamedReader namedReader(reader, name);
+    NBLog::NamedReader namedReader(reader, name);
     Mutex::Autolock _l(mLock);
     mNamedReaders.add(namedReader);
+    mMerger.addReader(namedReader);
 }
 
 void MediaLogService::unregisterWriter(const sp<IMemory>& shared)
@@ -81,7 +82,8 @@
         return NO_ERROR;
     }
 
-    Vector<NamedReader> namedReaders;
+#if 0
+    Vector<NBLog::NamedReader> namedReaders;
     {
         bool locked = dumpTryLock(mLock);
 
@@ -95,19 +97,23 @@
             }
             return NO_ERROR;
         }
-        namedReaders = mNamedReaders;
+            // namedReaders = mNamedReaders;
+            // for (size_t i = 0; i < namedReaders.size(); i++) {
+            //     const NBLog::NamedReader& namedReader = namedReaders[i];
+            //     if (fd >= 0) {
+            //         dprintf(fd, "\n%s:\n", namedReader.name());
+            //     } else {
+            //         ALOGI("%s:", namedReader.name());
+            //     }
+            //     namedReader.reader()->dump(fd, 0 /*indent*/);
+            // }
+
         mLock.unlock();
     }
+#endif
 
-    for (size_t i = 0; i < namedReaders.size(); i++) {
-        const NamedReader& namedReader = namedReaders[i];
-        if (fd >= 0) {
-            dprintf(fd, "\n%s:\n", namedReader.name());
-        } else {
-            ALOGI("%s:", namedReader.name());
-        }
-        namedReader.reader()->dump(fd, 0 /*indent*/);
-    }
+    mMerger.merge();
+    mMergeReader.dump(fd);
     return NO_ERROR;
 }
 
diff --git a/services/medialog/MediaLogService.h b/services/medialog/MediaLogService.h
index c9bf2eb..e934844 100644
--- a/services/medialog/MediaLogService.h
+++ b/services/medialog/MediaLogService.h
@@ -27,8 +27,13 @@
 {
     friend class BinderService<MediaLogService>;    // for MediaLogService()
 public:
-    MediaLogService() : BnMediaLogService() { }
-    virtual ~MediaLogService() { }
+    MediaLogService() :
+        BnMediaLogService(),
+        mMergerShared((NBLog::Shared*) malloc(NBLog::Timeline::sharedSize(kMergeBufferSize))),
+        mMerger(mMergerShared, kMergeBufferSize),
+        mMergeReader(mMergerShared, kMergeBufferSize, mMerger)
+    {ALOGI("Nico creating MergeReader");}
+    virtual ~MediaLogService() { free(mMergerShared); }
     virtual void onFirstRef() { }
 
     static const char*  getServiceName() { return "media.log"; }
@@ -47,23 +52,16 @@
     // Internal dump
     static const int kDumpLockRetries = 50;
     static const int kDumpLockSleepUs = 20000;
+    static const size_t kMergeBufferSize = 16 * 1024; // TODO determine good value for this
     static bool dumpTryLock(Mutex& mutex);
 
     Mutex               mLock;
-    class NamedReader {
-    public:
-        NamedReader() : mReader(0) { mName[0] = '\0'; } // for Vector
-        NamedReader(const sp<NBLog::Reader>& reader, const char *name) : mReader(reader)
-            { strlcpy(mName, name, sizeof(mName)); }
-        ~NamedReader() { }
-        const sp<NBLog::Reader>&  reader() const { return mReader; }
-        const char*               name() const { return mName; }
-    private:
-        sp<NBLog::Reader>   mReader;
-        static const size_t kMaxName = 32;
-        char                mName[kMaxName];
-    };
-    Vector<NamedReader> mNamedReaders;
+
+    Vector<NBLog::NamedReader> mNamedReaders;
+
+    NBLog::Shared *mMergerShared;
+    NBLog::Merger mMerger;
+    NBLog::MergeReader mMergeReader;
 };
 
 }   // namespace android
diff --git a/services/minijail/minijail.cpp b/services/minijail/minijail.cpp
index 7b61ae8..f213287 100644
--- a/services/minijail/minijail.cpp
+++ b/services/minijail/minijail.cpp
@@ -53,20 +53,19 @@
     return pipefd[0];
 }
 
-int SetUpMinijail(const std::string& base_policy_path, const std::string& additional_policy_path)
+void SetUpMinijail(const std::string& base_policy_path, const std::string& additional_policy_path)
 {
     // No seccomp policy defined for this architecture.
     if (access(base_policy_path.c_str(), R_OK) == -1) {
         LOG(WARNING) << "No seccomp policy defined for this architecture.";
-        return 0;
+        return;
     }
 
     std::string base_policy_content;
     std::string additional_policy_content;
     if (!base::ReadFileToString(base_policy_path, &base_policy_content,
                                 false /* follow_symlinks */)) {
-        LOG(ERROR) << "Could not read base policy file '" << base_policy_path << "'";
-        return -1;
+        LOG(FATAL) << "Could not read base policy file '" << base_policy_path << "'";
     }
 
     if (additional_policy_path.length() > 0 &&
@@ -78,14 +77,12 @@
 
     base::unique_fd policy_fd(WritePolicyToPipe(base_policy_content, additional_policy_content));
     if (policy_fd.get() == -1) {
-        LOG(ERROR) << "Could not write seccomp policy to fd";
-        return -1;
+        LOG(FATAL) << "Could not write seccomp policy to fd";
     }
 
     ScopedMinijail jail{minijail_new()};
     if (!jail) {
-        LOG(ERROR) << "Failed to create minijail.";
-        return -1;
+        LOG(FATAL) << "Failed to create minijail.";
     }
 
     minijail_no_new_privs(jail.get());
@@ -94,6 +91,5 @@
     // Transfer ownership of |policy_fd|.
     minijail_parse_seccomp_filters_from_fd(jail.get(), policy_fd.release());
     minijail_enter(jail.get());
-    return 0;
 }
 }
diff --git a/services/minijail/minijail.h b/services/minijail/minijail.h
index 3d6db37..c8a2149 100644
--- a/services/minijail/minijail.h
+++ b/services/minijail/minijail.h
@@ -20,8 +20,7 @@
 namespace android {
 int WritePolicyToPipe(const std::string& base_policy_content,
                       const std::string& additional_policy_content);
-int SetUpMinijail(const std::string& base_policy_path,
-                  const std::string& additional_policy_path);
+void SetUpMinijail(const std::string& base_policy_path, const std::string& additional_policy_path);
 }
 
 #endif  // AV_SERVICES_MINIJAIL_MINIJAIL