Merge "liboboe: fix symbol names for NDK"
diff --git a/include/media/OMXBuffer.h b/include/media/OMXBuffer.h
index 89b709c..aeb1765 100644
--- a/include/media/OMXBuffer.h
+++ b/include/media/OMXBuffer.h
@@ -24,12 +24,27 @@
 
 namespace android {
 
+class OMXBuffer;
+
+// This is needed temporarily for the OMX HIDL transition.
+namespace hardware { namespace media { namespace omx {
+namespace V1_0 {
+    struct CodecBuffer;
+namespace implementation {
+    inline bool wrapAs(::android::hardware::media::omx::V1_0::CodecBuffer* t,
+            ::android::OMXBuffer const& l);
+    inline bool convertTo(::android::OMXBuffer* l,
+            ::android::hardware::media::omx::V1_0::CodecBuffer const& t);
+}}}}}
+
 class GraphicBuffer;
 class IMemory;
 class MediaCodecBuffer;
 class NativeHandle;
-class OMXNodeInstance;
+struct OMXNodeInstance;
 
+// TODO: After complete HIDL transition, this class would be replaced by
+// CodecBuffer.
 class OMXBuffer {
 public:
     // sPreset is used in places where we are referring to a pre-registered
@@ -43,6 +58,10 @@
     // |codecBuffer|'s size (or 0 if |codecBuffer| is NULL).
     OMXBuffer(const sp<MediaCodecBuffer> &codecBuffer);
 
+    // Constructs a buffer of type kBufferTypePreset with a specified
+    // mRangeLength.
+    explicit OMXBuffer(OMX_U32 rangeLength);
+
     // Constructs a buffer of type kBufferTypeSharedMem.
     OMXBuffer(const sp<IMemory> &mem);
 
@@ -59,7 +78,15 @@
     ~OMXBuffer();
 
 private:
-    friend class OMXNodeInstance;
+    friend struct OMXNodeInstance;
+
+    // This is needed temporarily for OMX HIDL transition.
+    friend inline bool (::android::hardware::media::omx::V1_0::implementation::
+            wrapAs)(::android::hardware::media::omx::V1_0::CodecBuffer* t,
+            OMXBuffer const& l);
+    friend inline bool (::android::hardware::media::omx::V1_0::implementation::
+            convertTo)(OMXBuffer* l,
+            ::android::hardware::media::omx::V1_0::CodecBuffer const& t);
 
     enum BufferType {
         kBufferTypeInvalid = 0,
@@ -85,8 +112,12 @@
     // kBufferTypeNativeHandle
     sp<NativeHandle> mNativeHandle;
 
-    OMXBuffer(const OMXBuffer &);
-    OMXBuffer &operator=(const OMXBuffer &);
+    // Move assignment
+    OMXBuffer &operator=(OMXBuffer&&);
+
+    // Deleted copy constructor and assignment.
+    OMXBuffer(const OMXBuffer&) = delete;
+    OMXBuffer& operator=(const OMXBuffer&) = delete;
 };
 
 }  // namespace android
diff --git a/include/media/OMXFenceParcelable.h b/include/media/OMXFenceParcelable.h
index c9da301..f529301 100644
--- a/include/media/OMXFenceParcelable.h
+++ b/include/media/OMXFenceParcelable.h
@@ -21,6 +21,18 @@
 
 namespace android {
 
+struct OMXFenceParcelable;
+
+// This is needed temporarily for the OMX HIDL transition.
+namespace hardware {
+    struct hidl_handle;
+namespace media { namespace omx { namespace V1_0 { namespace implementation {
+    void wrapAs(::android::OMXFenceParcelable* l,
+            ::android::hardware::hidl_handle const& t);
+    bool convertTo(::android::OMXFenceParcelable* l,
+            ::android::hardware::hidl_handle const& t);
+}}}}}
+
 struct OMXFenceParcelable : public Parcelable {
     OMXFenceParcelable() : mFenceFd(-1) {}
     OMXFenceParcelable(int fenceFd) : mFenceFd(fenceFd) {}
@@ -36,6 +48,14 @@
     OMXFenceParcelable &operator=(const OMXFenceParcelable &);
 
     int mFenceFd;
+
+    // This is needed temporarily for OMX HIDL transition.
+    friend void (::android::hardware::media::omx::V1_0::implementation::
+            wrapAs)(OMXFenceParcelable* l,
+            ::android::hardware::hidl_handle const& t);
+    friend bool (::android::hardware::media::omx::V1_0::implementation::
+            convertTo)(OMXFenceParcelable* l,
+            ::android::hardware::hidl_handle const& t);
 };
 
 inline status_t OMXFenceParcelable::readFromParcel(const Parcel* parcel) {
diff --git a/include/media/audiohal/StreamHalInterface.h b/include/media/audiohal/StreamHalInterface.h
index 0772d8f..5296829 100644
--- a/include/media/audiohal/StreamHalInterface.h
+++ b/include/media/audiohal/StreamHalInterface.h
@@ -62,6 +62,19 @@
 
     virtual status_t dump(int fd) = 0;
 
+    // Start a stream operating in mmap mode.
+    virtual status_t start() = 0;
+
+    // Stop a stream operating in mmap mode.
+    virtual status_t stop() = 0;
+
+    // Retrieve information on the data buffer in mmap mode.
+    virtual status_t createMmapBuffer(int32_t minSizeFrames,
+                                      struct audio_mmap_buffer_info *info) = 0;
+
+    // Get current read/write position in the mmap buffer
+    virtual status_t getMmapPosition(struct audio_mmap_position *position) = 0;
+
   protected:
     // Subclasses can not be constructed directly by clients.
     StreamHalInterface() {}
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index c620e7c..7dc4e1d 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -14,7 +14,8 @@
 	libmedialogservice \
 	libradioservice \
 	libsoundtriggerservice \
-	libutils
+	libutils \
+	libhwbinder
 
 LOCAL_C_INCLUDES := \
 	frameworks/av/services/audioflinger \
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index 4a7a988..bcd0342 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -27,6 +27,10 @@
 #include <binder/IServiceManager.h>
 #include <utils/Log.h>
 
+// FIXME: remove when BUG 31748996 is fixed
+#include <hwbinder/IPCThreadState.h>
+#include <hwbinder/ProcessState.h>
+
 // from LOCAL_C_INCLUDES
 #include "AudioFlinger.h"
 #include "AudioPolicyService.h"
@@ -130,6 +134,10 @@
         RadioService::instantiate();
         SoundTriggerHwService::instantiate();
         ProcessState::self()->startThreadPool();
+
+// FIXME: remove when BUG 31748996 is fixed
+        android::hardware::ProcessState::self()->startThreadPool();
+
         IPCThreadState::self()->joinThreadPool();
     }
 }
diff --git a/media/libaudiohal/StreamHalHidl.cpp b/media/libaudiohal/StreamHalHidl.cpp
index 9383a36..3d63fea 100644
--- a/media/libaudiohal/StreamHalHidl.cpp
+++ b/media/libaudiohal/StreamHalHidl.cpp
@@ -31,6 +31,8 @@
 using ::android::hardware::audio::V2_0::ParameterValue;
 using ::android::hardware::audio::V2_0::Result;
 using ::android::hardware::audio::V2_0::TimeSpec;
+using ::android::hardware::audio::V2_0::MmapBufferInfo;
+using ::android::hardware::audio::V2_0::MmapPosition;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 
@@ -128,6 +130,51 @@
     return processReturn("dump", ret);
 }
 
+status_t StreamHalHidl::start() {
+    if (!mStream) return NO_INIT;
+    return processReturn("start", mStream->start());
+}
+
+status_t StreamHalHidl::stop() {
+    if (!mStream) return NO_INIT;
+    return processReturn("stop", mStream->stop());
+}
+
+status_t StreamHalHidl::createMmapBuffer(int32_t minSizeFrames,
+                                  struct audio_mmap_buffer_info *info) {
+    Result retval;
+    Return<void> ret = mStream->createMmapBuffer(
+            minSizeFrames,
+            [&](Result r, const MmapBufferInfo& hidlInfo) {
+                retval = r;
+                if (retval == Result::OK) {
+                    native_handle *handle = hidlInfo.sharedMemory->handle();
+                    if (handle->numFds > 0) {
+                        info->shared_memory_fd = dup(handle->data[0]);
+                        info->buffer_size_frames = hidlInfo.bufferSizeFrames;
+                        info->burst_size_frames = hidlInfo.burstSizeFrames;
+                        // info->shared_memory_address is not needed in HIDL context
+                        info->shared_memory_address = NULL;
+                    } else {
+                        retval = Result::NOT_INITIALIZED;
+                    }
+                }
+            });
+    return processReturn("createMmapBuffer", ret, retval);
+}
+
+status_t StreamHalHidl::getMmapPosition(struct audio_mmap_position *position) {
+    Result retval;
+    Return<void> ret = mStream->getMmapPosition(
+            [&](Result r, const MmapPosition& hidlPosition) {
+                retval = r;
+                if (retval == Result::OK) {
+                    position->time_nanoseconds = hidlPosition.timeNanoseconds;
+                    position->position_frames = hidlPosition.positionFrames;
+                }
+            });
+    return processReturn("getMmapPosition", ret, retval);
+}
 
 namespace {
 
diff --git a/media/libaudiohal/StreamHalHidl.h b/media/libaudiohal/StreamHalHidl.h
index e0a067e..377acb4 100644
--- a/media/libaudiohal/StreamHalHidl.h
+++ b/media/libaudiohal/StreamHalHidl.h
@@ -67,6 +67,19 @@
 
     virtual status_t dump(int fd);
 
+    // Start a stream operating in mmap mode.
+    virtual status_t start();
+
+    // Stop a stream operating in mmap mode.
+    virtual status_t stop();
+
+    // Retrieve information on the data buffer in mmap mode.
+    virtual status_t createMmapBuffer(int32_t minSizeFrames,
+                                      struct audio_mmap_buffer_info *info);
+
+    // Get current read/write position in the mmap buffer
+    virtual status_t getMmapPosition(struct audio_mmap_position *position);
+
   protected:
     // Subclasses can not be constructed directly by clients.
     explicit StreamHalHidl(IStream *stream);
diff --git a/media/libaudiohal/StreamHalLocal.cpp b/media/libaudiohal/StreamHalLocal.cpp
index 12a1222..61c8898 100644
--- a/media/libaudiohal/StreamHalLocal.cpp
+++ b/media/libaudiohal/StreamHalLocal.cpp
@@ -215,6 +215,26 @@
     return mStream->get_presentation_position(mStream, frames, timestamp);
 }
 
+status_t StreamOutHalLocal::start() {
+    if (mStream->start == NULL) return INVALID_OPERATION;
+    return mStream->start(mStream);
+}
+
+status_t StreamOutHalLocal::stop() {
+    if (mStream->stop == NULL) return INVALID_OPERATION;
+    return mStream->stop(mStream);
+}
+
+status_t StreamOutHalLocal::createMmapBuffer(int32_t minSizeFrames,
+                                  struct audio_mmap_buffer_info *info) {
+    if (mStream->create_mmap_buffer == NULL) return INVALID_OPERATION;
+    return mStream->create_mmap_buffer(mStream, minSizeFrames, info);
+}
+
+status_t StreamOutHalLocal::getMmapPosition(struct audio_mmap_position *position) {
+    if (mStream->get_mmap_position == NULL) return INVALID_OPERATION;
+    return mStream->get_mmap_position(mStream, position);
+}
 
 StreamInHalLocal::StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device)
         : StreamHalLocal(&stream->common, device), mStream(stream) {
@@ -255,4 +275,25 @@
     return mStream->get_capture_position(mStream, frames, time);
 }
 
+status_t StreamInHalLocal::start() {
+    if (mStream->start == NULL) return INVALID_OPERATION;
+    return mStream->start(mStream);
+}
+
+status_t StreamInHalLocal::stop() {
+    if (mStream->stop == NULL) return INVALID_OPERATION;
+    return mStream->stop(mStream);
+}
+
+status_t StreamInHalLocal::createMmapBuffer(int32_t minSizeFrames,
+                                  struct audio_mmap_buffer_info *info) {
+    if (mStream->create_mmap_buffer == NULL) return INVALID_OPERATION;
+    return mStream->create_mmap_buffer(mStream, minSizeFrames, info);
+}
+
+status_t StreamInHalLocal::getMmapPosition(struct audio_mmap_position *position) {
+    if (mStream->get_mmap_position == NULL) return INVALID_OPERATION;
+    return mStream->get_mmap_position(mStream, position);
+}
+
 } // namespace android
diff --git a/media/libaudiohal/StreamHalLocal.h b/media/libaudiohal/StreamHalLocal.h
index 1df18cc..fbb000a 100644
--- a/media/libaudiohal/StreamHalLocal.h
+++ b/media/libaudiohal/StreamHalLocal.h
@@ -57,6 +57,19 @@
 
     virtual status_t dump(int fd);
 
+    // Start a stream operating in mmap mode.
+    virtual status_t start() = 0;
+
+    // Stop a stream operating in mmap mode.
+    virtual status_t stop() = 0;
+
+    // Retrieve information on the data buffer in mmap mode.
+    virtual status_t createMmapBuffer(int32_t minSizeFrames,
+                                      struct audio_mmap_buffer_info *info) = 0;
+
+    // Get current read/write position in the mmap buffer
+    virtual status_t getMmapPosition(struct audio_mmap_position *position) = 0;
+
   protected:
     // Subclasses can not be constructed directly by clients.
     StreamHalLocal(audio_stream_t *stream, sp<DeviceHalLocal> device);
@@ -115,6 +128,19 @@
     // Return a recent count of the number of audio frames presented to an external observer.
     virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp);
 
+    // Start a stream operating in mmap mode.
+    virtual status_t start();
+
+    // Stop a stream operating in mmap mode.
+    virtual status_t stop();
+
+    // Retrieve information on the data buffer in mmap mode.
+    virtual status_t createMmapBuffer(int32_t minSizeFrames,
+                                      struct audio_mmap_buffer_info *info);
+
+    // Get current read/write position in the mmap buffer
+    virtual status_t getMmapPosition(struct audio_mmap_position *position);
+
   private:
     audio_stream_out_t *mStream;
     wp<StreamOutHalInterfaceCallback> mCallback;
@@ -147,6 +173,19 @@
     // the clock time associated with that frame count.
     virtual status_t getCapturePosition(int64_t *frames, int64_t *time);
 
+    // Start a stream operating in mmap mode.
+    virtual status_t start();
+
+    // Stop a stream operating in mmap mode.
+    virtual status_t stop();
+
+    // Retrieve information on the data buffer in mmap mode.
+    virtual status_t createMmapBuffer(int32_t minSizeFrames,
+                                      struct audio_mmap_buffer_info *info);
+
+    // Get current read/write position in the mmap buffer
+    virtual status_t getMmapPosition(struct audio_mmap_position *position);
+
   private:
     audio_stream_in_t *mStream;
 
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index 7776313..0f4f092 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -200,11 +200,16 @@
     for (size_t i = 0; i < tracks.size(); i++) {
         const String8 desc = trackDescriptions.itemAt(i);
         str.appendFormat("    track {%s} ", desc.string());
-        const sp<IMediaSource> source = tracks.itemAt(i).promote();
-        if (source == NULL) {
-            str.append(": deleted\n");
+        wp<IMediaSource> wSource = tracks.itemAt(i);
+        if (wSource == NULL) {
+            str.append(": null\n");
         } else {
-            str.appendFormat(": active\n");
+            const sp<IMediaSource> source = wSource.promote();
+            if (source == NULL) {
+                str.append(": deleted\n");
+            } else {
+                str.appendFormat(": active\n");
+            }
         }
     }
     return str;
@@ -223,9 +228,14 @@
         if (extractor != NULL && extractor == ex) {
             if (instance.tracks.size() > 5) {
                 instance.tracks.resize(5);
+                instance.trackDescriptions.resize(5);
             }
             instance.tracks.push_front(source);
-            instance.trackDescriptions.add(source->getFormat()->toString());
+            if (source != NULL) {
+                instance.trackDescriptions.push_front(source->getFormat()->toString());
+            } else {
+                instance.trackDescriptions.push_front(String8::empty());
+            }
             break;
         }
     }
diff --git a/media/libmedia/OMXBuffer.cpp b/media/libmedia/OMXBuffer.cpp
index 2834853..914cd5b 100644
--- a/media/libmedia/OMXBuffer.cpp
+++ b/media/libmedia/OMXBuffer.cpp
@@ -38,6 +38,11 @@
       mRangeLength(codecBuffer != NULL ? codecBuffer->size() : 0) {
 }
 
+OMXBuffer::OMXBuffer(OMX_U32 rangeLength)
+    : mBufferType(kBufferTypePreset),
+      mRangeLength(rangeLength) {
+}
+
 OMXBuffer::OMXBuffer(const sp<IMemory> &mem)
     : mBufferType(kBufferTypeSharedMem),
       mMem(mem) {
@@ -133,6 +138,15 @@
     return OK;
 }
 
+OMXBuffer& OMXBuffer::operator=(OMXBuffer&& source) {
+    mBufferType = std::move(source.mBufferType);
+    mRangeLength = std::move(source.mRangeLength);
+    mMem = std::move(source.mMem);
+    mGraphicBuffer = std::move(source.mGraphicBuffer);
+    mNativeHandle = std::move(source.mNativeHandle);
+    return *this;
+}
+
 } // namespace android
 
 
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index 0df7da4..0434bab 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -51,7 +51,7 @@
 }
 
 ssize_t CallbackDataSource::readAt(off64_t offset, void* data, size_t size) {
-    if (mMemory == NULL) {
+    if (mMemory == NULL || data == NULL) {
         return -1;
     }
 
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index f9af5e1..87d7d3c 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -3992,7 +3992,12 @@
         return OK;
     }
     if (smplcnt > mCurrentSampleInfoAllocSize) {
-        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
+        uint8_t * newPtr =  (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
+        if (newPtr == NULL) {
+            ALOGE("failed to realloc %u -> %u", mCurrentSampleInfoAllocSize, smplcnt);
+            return NO_MEMORY;
+        }
+        mCurrentSampleInfoSizes = newPtr;
         mCurrentSampleInfoAllocSize = smplcnt;
     }
 
@@ -4031,6 +4036,7 @@
     if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
         uint64_t *newPtr = (uint64_t *)realloc(mCurrentSampleInfoOffsets, entrycount * 8);
         if (newPtr == NULL) {
+            ALOGE("failed to realloc %u -> %u", mCurrentSampleInfoOffsetsAllocSize, entrycount * 8);
             return NO_MEMORY;
         }
         mCurrentSampleInfoOffsets = newPtr;
diff --git a/media/libstagefright/omx/hal/1.0/Android.mk b/media/libstagefright/omx/hal/1.0/Android.mk
index b84d74b..1633486 100644
--- a/media/libstagefright/omx/hal/1.0/Android.mk
+++ b/media/libstagefright/omx/hal/1.0/Android.mk
@@ -4,19 +4,35 @@
 LOCAL_MODULE := android.hardware.media.omx@1.0-impl
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_SRC_FILES := \
-    GraphicBufferSource.cpp \
+    WGraphicBufferSource.cpp \
+    WOmx.cpp \
+    WOmxBufferSource.cpp \
+    WOmxNode.cpp \
+    WOmxObserver.cpp \
     Omx.cpp \
-    OmxBufferSource.cpp \
     OmxNode.cpp \
-    OmxObserver.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
+    libmedia \
+    libstagefright_foundation \
+    libstagefright_omx \
+    libui \
     libhidlbase \
     libhidltransport \
     libhwbinder \
     libutils \
+    libcutils \
+    libbinder \
     android.hardware.media.omx@1.0 \
     android.hardware.graphics.common@1.0 \
     android.hardware.media@1.0 \
+    android.hidl.base@1.0 \
+
+LOCAL_C_INCLUDES += \
+        $(TOP) \
+        $(TOP)/frameworks/av/include/media \
+        $(TOP)/frameworks/av/media/libstagefright/include \
+        $(TOP)/frameworks/native/include/media/hardware \
+        $(TOP)/frameworks/native/include/media/openmax
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/omx/hal/1.0/Conversion.h b/media/libstagefright/omx/hal/1.0/Conversion.h
new file mode 100644
index 0000000..44d2c84
--- /dev/null
+++ b/media/libstagefright/omx/hal/1.0/Conversion.h
@@ -0,0 +1,820 @@
+#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
+#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
+
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <unistd.h>
+#include <vector>
+#include <list>
+
+#include <frameworks/native/include/binder/Binder.h>
+#include <frameworks/native/include/binder/Status.h>
+
+#include <OMXFenceParcelable.h>
+#include <cutils/native_handle.h>
+
+#include <IOMX.h>
+#include <VideoAPI.h>
+#include <OMXBuffer.h>
+#include <android/IOMXBufferSource.h>
+#include <android/IGraphicBufferSource.h>
+
+#include <android/hardware/media/omx/1.0/types.h>
+#include <android/hardware/media/omx/1.0/IOmx.h>
+#include <android/hardware/media/omx/1.0/IOmxNode.h>
+#include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
+#include <android/hardware/media/omx/1.0/IOmxObserver.h>
+#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+using ::android::hardware::hidl_handle;
+using ::android::String8;
+using ::android::OMXFenceParcelable;
+
+using ::android::hardware::media::omx::V1_0::Message;
+using ::android::omx_message;
+
+using ::android::hardware::media::omx::V1_0::ColorAspects;
+
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
+
+using ::android::OMXBuffer;
+
+using ::android::hardware::media::omx::V1_0::IOmx;
+using ::android::IOMX;
+
+using ::android::hardware::media::omx::V1_0::IOmxNode;
+using ::android::IOMXNode;
+
+using ::android::hardware::media::omx::V1_0::IOmxObserver;
+using ::android::IOMXObserver;
+
+using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
+using ::android::IOMXBufferSource;
+
+// native_handle_t helper functions.
+
+/**
+ * \brief Take an fd and create a native handle containing only the given fd.
+ * The created handle will need to be deleted manually with
+ * `native_handle_delete()`.
+ *
+ * \param[in] fd The source file descriptor (of type `int`).
+ * \return The create `native_handle_t*` that contains the given \p fd. If the
+ * supplied \p fd is negative, the created native handle will contain no file
+ * descriptors.
+ *
+ * If the native handle cannot be created, the return value will be
+ * `nullptr`.
+ *
+ * This function does not duplicate the file descriptor.
+ */
+inline native_handle_t* native_handle_create_from_fd(int fd) {
+    if (fd < 0) {
+        return native_handle_create(0, 0);
+    }
+    native_handle_t* nh = native_handle_create(1, 0);
+    if (nh == nullptr) {
+        return nullptr;
+    }
+    nh->data[0] = fd;
+    return nh;
+}
+
+/**
+ * \brief Extract a file descriptor from a native handle.
+ *
+ * \param[in] nh The source `native_handle_t*`.
+ * \param[in] index The index of the file descriptor in \p nh to read from. This
+ * input has the default value of `0`.
+ * \return The `index`-th file descriptor in \p nh. If \p nh does not have
+ * enough file descriptors, the returned value will be `-1`.
+ *
+ * This function does not duplicate the file descriptor.
+ */
+inline int native_handle_read_fd(native_handle_t const* nh, int index = 0) {
+    return ((nh == nullptr) || (nh->numFds == 0) ||
+            (nh->numFds <= index) || (index < 0)) ?
+            -1 : nh->data[index];
+}
+
+/**
+ * Conversion functions
+ * ====================
+ *
+ * There are two main directions of conversion:
+ * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the
+ *   input. The wrapper has type `TargetType`.
+ * - `toTargetType(...)`: Create a standalone object of type `TargetType` that
+ *   corresponds to the input. The lifetime of the output does not depend on the
+ *   lifetime of the input.
+ * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType`
+ *   that cannot be copied and/or moved efficiently, or when there are multiple
+ *   output arguments.
+ * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for
+ *   `TargetType` that cannot be copied and/or moved efficiently, or when there
+ *   are multiple output arguments.
+ *
+ * `wrapIn()` and `convertTo()` functions will take output arguments before
+ * input arguments. Some of these functions might return a value to indicate
+ * success or error.
+ *
+ * In converting or wrapping something as a Treble type that contains a
+ * `hidl_handle`, `native_handle_t*` will need to be created and returned as
+ * an additional output argument, hence only `wrapIn()` or `convertTo()` would
+ * be available. The caller must call `native_handle_delete()` to deallocate the
+ * returned native handle when it is no longer needed.
+ *
+ * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do
+ * not perform duplication of file descriptors, while `toTargetType()` and
+ * `convertTo()` do.
+ */
+
+/**
+ * \brief Convert `binder::Status` to `hardware::Status`.
+ *
+ * \param[in] l The source `binder::Status`.
+ * \return The corresponding `hardware::Status`.
+ */
+// convert: ::android::binder::Status -> ::android::hardware::Status
+inline ::android::hardware::Status toHardwareStatus(
+        ::android::binder::Status const& l) {
+    if (l.exceptionCode() == ::android::binder::Status::EX_SERVICE_SPECIFIC) {
+        return ::android::hardware::Status::fromServiceSpecificError(
+                l.serviceSpecificErrorCode(),
+                l.exceptionMessage());
+    }
+    return ::android::hardware::Status::fromExceptionCode(
+            l.exceptionCode(),
+            l.exceptionMessage());
+}
+
+/**
+ * \brief Convert `hardware::Status` to `binder::Status`.
+ *
+ * \param[in] t The source `hardware::Status`.
+ * \return The corresponding `binder::Status`.
+ */
+// convert: ::android::hardware::Status -> ::android::binder::Status
+inline ::android::binder::Status toBinderStatus(
+        ::android::hardware::Status const& t) {
+    if (t.exceptionCode() == ::android::hardware::Status::EX_SERVICE_SPECIFIC) {
+        return ::android::binder::Status::fromServiceSpecificError(
+                t.serviceSpecificErrorCode(),
+                t.exceptionMessage());
+    }
+    return ::android::binder::Status::fromExceptionCode(
+            t.exceptionCode(),
+            t.exceptionMessage());
+}
+
+/**
+ * \brief Convert `hardware::Return<void>` to `binder::Status`.
+ *
+ * \param[in] t The source `hardware::Return<void>`.
+ * \return The corresponding `binder::Status`.
+ *
+ * This function simply calls `toBinderStatus(::android::hardware::Status
+ * const&)`.
+ */
+// convert: ::android::hardware::Return<void> -> ::android::binder::Status
+inline ::android::binder::Status toBinderStatus(Return<void> const& t) {
+    return toBinderStatus(t.getStatus());
+}
+
+/**
+ * \brief Convert `Return<Status>` to `status_t`. This is for legacy binder
+ * calls.
+ *
+ * \param[in] t The source `Return<Status>`.
+ * \return The corresponding `status_t`.
+ *
+ * This function first check if \p t has a transport error. If it does, then the
+ * return value is the transport error code. Otherwise, the return value is
+ * converted from `Status` contained inside \p t.
+ *
+ * Note:
+ * - This `Status` is omx-specific. It is defined in `types.hal`.
+ * - The name of this function is not `convert`.
+ */
+// convert: Status -> status_t
+inline status_t toStatusT(Return<Status> const& t) {
+    return t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) :
+            t.getStatus().transactionError();
+}
+
+/**
+ * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
+ *
+ * \param[in] t The source `Return<void>`.
+ * \return The corresponding `status_t`.
+ */
+// convert: Return<void> -> status_t
+inline status_t toStatusT(Return<void> const& t) {
+    return t.getStatus().transactionError();
+}
+
+/**
+ * \brief Convert `Status` to `status_t`. This is for legacy binder calls.
+ *
+ * \param[in] t The source `Status`.
+ * \return the corresponding `status_t`.
+ */
+// convert: Status -> status_t
+inline status_t toStatusT(Status const& t) {
+    return static_cast<status_t>(t);
+}
+
+/**
+ * \brief Convert `status_t` to `Status`.
+ *
+ * \param[in] l The source `status_t`.
+ * \return The corresponding `Status`.
+ */
+// convert: status_t -> Status
+inline Status toStatus(status_t l) {
+    return static_cast<Status>(l);
+}
+
+/**
+ * \brief Wrap `native_handle_t*` in `hidl_handle`.
+ *
+ * \param[in] nh The source `native_handle_t*`.
+ * \return The `hidl_handle` that points to \p nh.
+ */
+// wrap: native_handle_t* -> hidl_handle
+inline hidl_handle inHidlHandle(native_handle_t const* nh) {
+    return hidl_handle(nh);
+}
+
+/**
+ * \brief Wrap an `omx_message` and construct the corresponding `Message`.
+ *
+ * \param[out] t The wrapper of type `Message`.
+ * \param[out] nh The native_handle_t referred to by `t->fence`.
+ * \param[in] l The source `omx_message`.
+ * \return `true` if the wrapping is successful; `false` otherwise.
+ *
+ * Upon success, \p nh will be created to hold the file descriptor stored in
+ * `l.fenceFd`, and `t->fence` will point to \p nh. \p nh will need to be
+ * destroyed manually by `native_handle_delete()` when \p t is no longer needed.
+ *
+ * Upon failure, \p nh will not be created and will not need to be deleted. \p t
+ * will be invalid.
+ */
+// wrap, omx_message -> Message, native_handle_t*
+inline bool wrapAs(Message* t, native_handle_t** nh, omx_message const& l) {
+    *nh = native_handle_create_from_fd(l.fenceFd);
+    if (!*nh) {
+        return false;
+    }
+    t->fence = inHidlHandle(*nh);
+    switch (l.type) {
+        case omx_message::EVENT:
+            t->type = Message::Type::EVENT;
+            t->data.eventData.data1 = l.u.event_data.data1;
+            t->data.eventData.data2 = l.u.event_data.data2;
+            t->data.eventData.data3 = l.u.event_data.data3;
+            t->data.eventData.data4 = l.u.event_data.data4;
+            break;
+        case omx_message::EMPTY_BUFFER_DONE:
+            t->type = Message::Type::EMPTY_BUFFER_DONE;
+            t->data.bufferData.buffer = l.u.buffer_data.buffer;
+            break;
+        case omx_message::FILL_BUFFER_DONE:
+            t->type = Message::Type::FILL_BUFFER_DONE;
+            t->data.extendedBufferData.buffer = l.u.extended_buffer_data.buffer;
+            t->data.extendedBufferData.rangeOffset = l.u.extended_buffer_data.range_offset;
+            t->data.extendedBufferData.rangeLength = l.u.extended_buffer_data.range_length;
+            t->data.extendedBufferData.flags = l.u.extended_buffer_data.flags;
+            t->data.extendedBufferData.timestampUs = l.u.extended_buffer_data.timestamp;
+            break;
+        case omx_message::FRAME_RENDERED:
+            t->type = Message::Type::FRAME_RENDERED;
+            t->data.renderData.timestampUs = l.u.render_data.timestamp;
+            t->data.renderData.systemTimeNs = l.u.render_data.nanoTime;
+            break;
+        default:
+            native_handle_delete(*nh);
+            return false;
+    }
+    return true;
+}
+
+/**
+ * \brief Wrap a `Message` inside an `omx_message`.
+ *
+ * \param[out] l The wrapper of type `omx_message`.
+ * \param[in] t The source `Message`.
+ * \return `true` if the wrapping is successful; `false` otherwise.
+ */
+// wrap: Message -> omx_message
+inline bool wrapAs(omx_message* l, Message const& t) {
+    l->fenceFd = native_handle_read_fd(t.fence);
+    switch (t.type) {
+        case Message::Type::EVENT:
+            l->type = omx_message::EVENT;
+            l->u.event_data.data1 = t.data.eventData.data1;
+            l->u.event_data.data2 = t.data.eventData.data2;
+            l->u.event_data.data3 = t.data.eventData.data3;
+            l->u.event_data.data4 = t.data.eventData.data4;
+            break;
+        case Message::Type::EMPTY_BUFFER_DONE:
+            l->type = omx_message::EMPTY_BUFFER_DONE;
+            l->u.buffer_data.buffer = t.data.bufferData.buffer;
+            break;
+        case Message::Type::FILL_BUFFER_DONE:
+            l->type = omx_message::FILL_BUFFER_DONE;
+            l->u.extended_buffer_data.buffer = t.data.extendedBufferData.buffer;
+            l->u.extended_buffer_data.range_offset = t.data.extendedBufferData.rangeOffset;
+            l->u.extended_buffer_data.range_length = t.data.extendedBufferData.rangeLength;
+            l->u.extended_buffer_data.flags = t.data.extendedBufferData.flags;
+            l->u.extended_buffer_data.timestamp = t.data.extendedBufferData.timestampUs;
+            break;
+        case Message::Type::FRAME_RENDERED:
+            l->type = omx_message::FRAME_RENDERED;
+            l->u.render_data.timestamp = t.data.renderData.timestampUs;
+            l->u.render_data.nanoTime = t.data.renderData.systemTimeNs;
+            break;
+        default:
+            return false;
+    }
+    return true;
+}
+
+/**
+ * \brief Similar to `wrapTo(omx_message*, Message const&)`, but the output will
+ * have an extended lifetime.
+ *
+ * \param[out] l The output `omx_message`.
+ * \param[in] t The source `Message`.
+ * \return `true` if the conversion is successful; `false` otherwise.
+ *
+ * This function calls `wrapto()`, then attempts to clone the file descriptor
+ * for the fence if it is not `-1`. If the clone cannot be made, `false` will be
+ * returned.
+ */
+// convert: Message -> omx_message
+inline bool convertTo(omx_message* l, Message const& t) {
+    if (!wrapAs(l, t)) {
+        return false;
+    }
+    if (l->fenceFd == -1) {
+        return true;
+    }
+    l->fenceFd = dup(l->fenceFd);
+    return l->fenceFd != -1;
+}
+
+/**
+ * \brief Wrap an `OMXFenceParcelable` inside a `hidl_handle`.
+ *
+ * \param[out] t The wrapper of type `hidl_handle`.
+ * \param[out] nh The native handle created to hold the file descriptor inside
+ * \p l.
+ * \param[in] l The source `OMXFenceParcelable`, which essentially contains one
+ * file descriptor.
+ * \return `true` if \p t and \p nh are successfully created to wrap around \p
+ * l; `false` otherwise.
+ *
+ * On success, \p nh needs to be deleted by the caller with
+ * `native_handle_delete()` after \p t and \p nh are no longer needed.
+ *
+ * On failure, \p nh will not need to be deleted, and \p t will hold an invalid
+ * value.
+ */
+// wrap: OMXFenceParcelable -> hidl_handle, native_handle_t*
+inline bool wrapAs(hidl_handle* t, native_handle_t** nh,
+        OMXFenceParcelable const& l) {
+    *nh = native_handle_create_from_fd(l.get());
+    if (!*nh) {
+        return false;
+    }
+    *t = *nh;
+    return true;
+}
+
+/**
+ * \brief Wrap a `hidl_handle` inside an `OMXFenceParcelable`.
+ *
+ * \param[out] l The wrapper of type `OMXFenceParcelable`.
+ * \param[in] t The source `hidl_handle`.
+ */
+// wrap: hidl_handle -> OMXFenceParcelable
+inline void wrapAs(OMXFenceParcelable* l, hidl_handle const& t) {
+    l->mFenceFd = native_handle_read_fd(t);
+}
+
+/**
+ * \brief Convert a `hidl_handle` to `OMXFenceParcelable`. If `hidl_handle`
+ * contains file descriptors, the first file descriptor will be duplicated and
+ * stored in the output `OMXFenceParcelable`.
+ *
+ * \param[out] l The output `OMXFenceParcelable`.
+ * \param[in] t The input `hidl_handle`.
+ * \return `false` if \p t contains a valid file descriptor but duplication
+ * fails; `true` otherwise.
+ */
+// convert: hidl_handle -> OMXFenceParcelable
+inline bool convertTo(OMXFenceParcelable* l, hidl_handle const& t) {
+    int fd = native_handle_read_fd(t);
+    if (fd != -1) {
+        fd = dup(fd);
+        if (fd == -1) {
+            return false;
+        }
+    }
+    l->mFenceFd = fd;
+    return true;
+}
+
+/**
+ * \brief Convert `::android::ColorAspects` to `ColorAspects`.
+ *
+ * \param[in] l The source `::android::ColorAspects`.
+ * \return The corresponding `ColorAspects`.
+ */
+// convert: ::android::ColorAspects -> ColorAspects
+inline ColorAspects toHardwareColorAspects(::android::ColorAspects const& l) {
+    return ColorAspects{
+            static_cast<ColorAspects::Range>(l.mRange),
+            static_cast<ColorAspects::Primaries>(l.mPrimaries),
+            static_cast<ColorAspects::Transfer>(l.mTransfer),
+            static_cast<ColorAspects::MatrixCoeffs>(l.mMatrixCoeffs)};
+}
+
+/**
+ * \brief Convert `int32_t` to `ColorAspects`.
+ *
+ * \param[in] l The source `int32_t`.
+ * \return The corresponding `ColorAspects`.
+ */
+// convert: int32_t -> ColorAspects
+inline ColorAspects toHardwareColorAspects(int32_t l) {
+    return ColorAspects{
+            static_cast<ColorAspects::Range>((l >> 24) & 0xFF),
+            static_cast<ColorAspects::Primaries>((l >> 16) & 0xFF),
+            static_cast<ColorAspects::Transfer>(l & 0xFF),
+            static_cast<ColorAspects::MatrixCoeffs>((l >> 8) & 0xFF)};
+}
+
+/**
+ * \brief Convert `ColorAspects` to `::android::ColorAspects`.
+ *
+ * \param[in] t The source `ColorAspects`.
+ * \return The corresponding `::android::ColorAspects`.
+ */
+// convert: ColorAspects -> ::android::ColorAspects
+inline int32_t toCompactColorAspects(ColorAspects const& t) {
+    return static_cast<int32_t>(
+            (static_cast<uint32_t>(t.range) << 24) |
+            (static_cast<uint32_t>(t.primaries) << 16) |
+            (static_cast<uint32_t>(t.transfer)) |
+            (static_cast<uint32_t>(t.matrixCoeffs) << 8));
+}
+
+/**
+ * \brief Convert `int32_t` to `Dataspace`.
+ *
+ * \param[in] l The source `int32_t`.
+ * \result The corresponding `Dataspace`.
+ */
+// convert: int32_t -> Dataspace
+inline Dataspace toHardwareDataspace(int32_t l) {
+    return static_cast<Dataspace>(l);
+}
+
+/**
+ * \brief Convert `Dataspace` to `int32_t`.
+ *
+ * \param[in] t The source `Dataspace`.
+ * \result The corresponding `int32_t`.
+ */
+// convert: Dataspace -> int32_t
+inline int32_t toRawDataspace(Dataspace const& t) {
+    return static_cast<int32_t>(t);
+}
+
+/**
+ * \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`.
+ *
+ * \param[in] l The pointer to the beginning of the opaque buffer.
+ * \param[in] size The size of the buffer.
+ * \return A `hidl_vec<uint8_t>` that points to the buffer.
+ */
+// wrap: void*, size_t -> hidl_vec<uint8_t>
+inline hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) {
+    hidl_vec<uint8_t> t;
+    t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false);
+    return t;
+}
+
+/**
+ * \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer.
+ *
+ * \param[in] l The pointer to the beginning of the opaque buffer.
+ * \param[in] size The size of the buffer.
+ * \return A `hidl_vec<uint8_t>` that is a copy of the input buffer.
+ */
+// convert: void*, size_t -> hidl_vec<uint8_t>
+inline hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size) {
+    hidl_vec<uint8_t> t;
+    t.resize(size);
+    uint8_t const* src = static_cast<uint8_t const*>(l);
+    std::copy(src, src + size, t.data());
+    return t;
+}
+
+/**
+ * \brief Wrap `OMXBuffer` in `CodecBuffer`.
+ *
+ * \param[out] t The wrapper of type `CodecBuffer`.
+ * \param[in] l The source `OMXBuffer`.
+ * \return `true` if the wrapping is successful; `false` otherwise.
+ *
+ * TODO: Use HIDL's shared memory.
+ */
+// wrap: OMXBuffer -> CodecBuffer
+inline bool wrapAs(CodecBuffer* t, OMXBuffer const& l) {
+    switch (l.mBufferType) {
+        case OMXBuffer::kBufferTypeInvalid: {
+            t->type = CodecBuffer::Type::INVALID;
+            return true;
+        }
+        case OMXBuffer::kBufferTypePreset: {
+            t->type = CodecBuffer::Type::PRESET;
+            t->attr.preset.rangeLength = static_cast<uint32_t>(l.mRangeLength);
+            return true;
+        }
+        case OMXBuffer::kBufferTypeSharedMem: {
+            t->type = CodecBuffer::Type::SHARED_MEM;
+/* TODO: Use HIDL's shared memory.
+            ssize_t offset;
+            size_t size;
+            native_handle_t* handle;
+            sp<IMemoryHeap> memoryHeap = l.mMem->getMemory(&offset, &size);
+            t->attr.sharedMem.size = static_cast<uint32_t>(size);
+            t->attr.sharedMem.flags = static_cast<uint32_t>(memoryHeap->getFlags());
+            t->attr.sharedMem.offset = static_cast<uint32_t>(offset);
+            if (!convertFd2Handle(memoryHeap->getHeapID(), nh)) {
+                return false;
+            }
+            t->nativeHandle = hidl_handle(*nh);
+            return true;*/
+            return false;
+        }
+        case OMXBuffer::kBufferTypeANWBuffer: {
+            t->type = CodecBuffer::Type::ANW_BUFFER;
+            t->attr.anwBuffer.width = l.mGraphicBuffer->getWidth();
+            t->attr.anwBuffer.height = l.mGraphicBuffer->getHeight();
+            t->attr.anwBuffer.stride = l.mGraphicBuffer->getStride();
+            t->attr.anwBuffer.format = static_cast<PixelFormat>(l.mGraphicBuffer->getPixelFormat());
+            t->attr.anwBuffer.layerCount = l.mGraphicBuffer->getLayerCount();
+            t->attr.anwBuffer.usage = l.mGraphicBuffer->getUsage();
+            t->nativeHandle = hidl_handle(l.mGraphicBuffer->handle);
+            return true;
+        }
+        case OMXBuffer::kBufferTypeNativeHandle: {
+            t->type = CodecBuffer::Type::NATIVE_HANDLE;
+            t->nativeHandle = hidl_handle(l.mNativeHandle->handle());
+            return true;
+        }
+    }
+    return false;
+}
+
+/**
+ * \brief Convert `CodecBuffer` to `OMXBuffer`.
+ *
+ * \param[out] l The destination `OMXBuffer`.
+ * \param[in] t The source `CodecBuffer`.
+ * \return `true` if successful; `false` otherwise.
+ *
+ * TODO: Use HIDL's shared memory.
+ */
+// convert: CodecBuffer -> OMXBuffer
+inline bool convertTo(OMXBuffer* l, CodecBuffer const& t) {
+    switch (t.type) {
+        case CodecBuffer::Type::INVALID: {
+            *l = OMXBuffer();
+            return true;
+        }
+        case CodecBuffer::Type::PRESET: {
+            *l = OMXBuffer(t.attr.preset.rangeLength);
+            return true;
+        }
+        case CodecBuffer::Type::SHARED_MEM: {
+/* TODO: Use HIDL's memory.
+            *l = OMXBuffer();
+            return true;*/
+            return false;
+        }
+        case CodecBuffer::Type::ANW_BUFFER: {
+            *l = OMXBuffer(sp<GraphicBuffer>(new GraphicBuffer(
+                    t.attr.anwBuffer.width,
+                    t.attr.anwBuffer.height,
+                    static_cast<::android::PixelFormat>(
+                            t.attr.anwBuffer.format),
+                    t.attr.anwBuffer.layerCount,
+                    t.attr.anwBuffer.usage,
+                    t.attr.anwBuffer.stride,
+                    native_handle_clone(t.nativeHandle),
+                    true)));
+            return true;
+        }
+        case CodecBuffer::Type::NATIVE_HANDLE: {
+            *l = OMXBuffer(NativeHandle::create(
+                    native_handle_clone(t.nativeHandle), true));
+            return true;
+        }
+    }
+    return false;
+}
+
+/**
+ * \brief Convert `IOMX::ComponentInfo` to `IOmx::ComponentInfo`.
+ *
+ * \param[out] t The destination `IOmx::ComponentInfo`.
+ * \param[in] l The source `IOMX::ComponentInfo`.
+ */
+// convert: IOMX::ComponentInfo -> IOmx::ComponentInfo
+inline bool convertTo(IOmx::ComponentInfo* t, IOMX::ComponentInfo const& l) {
+    t->mName = l.mName.string();
+    t->mRoles.resize(l.mRoles.size());
+    size_t i = 0;
+    for (auto& role : l.mRoles) {
+        t->mRoles[i++] = role.string();
+    }
+    return true;
+}
+
+/**
+ * \brief Convert `IOmx::ComponentInfo` to `IOMX::ComponentInfo`.
+ *
+ * \param[out] l The destination `IOMX::ComponentInfo`.
+ * \param[in] t The source `IOmx::ComponentInfo`.
+ */
+// convert: IOmx::ComponentInfo -> IOMX::ComponentInfo
+inline bool convertTo(IOMX::ComponentInfo* l, IOmx::ComponentInfo const& t) {
+    l->mName = t.mName.c_str();
+    l->mRoles.clear();
+    for (size_t i = 0; i < t.mRoles.size(); ++i) {
+        l->mRoles.push_back(String8(t.mRoles[i].c_str()));
+    }
+    return true;
+}
+
+/**
+ * \brief Convert `OMX_BOOL` to `bool`.
+ *
+ * \param[in] l The source `OMX_BOOL`.
+ * \return The destination `bool`.
+ */
+// convert: OMX_BOOL -> bool
+inline bool toRawBool(OMX_BOOL l) {
+    return l == OMX_FALSE ? false : true;
+}
+
+/**
+ * \brief Convert `bool` to `OMX_BOOL`.
+ *
+ * \param[in] t The source `bool`.
+ * \return The destination `OMX_BOOL`.
+ */
+// convert: bool -> OMX_BOOL
+inline OMX_BOOL toEnumBool(bool t) {
+    return t ? OMX_TRUE : OMX_FALSE;
+}
+
+/**
+ * \brief Convert `OMX_COMMANDTYPE` to `uint32_t`.
+ *
+ * \param[in] l The source `OMX_COMMANDTYPE`.
+ * \return The underlying value of type `uint32_t`.
+ *
+ * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`.
+ */
+// convert: OMX_COMMANDTYPE -> uint32_t
+inline uint32_t toRawCommandType(OMX_COMMANDTYPE l) {
+    return static_cast<uint32_t>(l);
+}
+
+/**
+ * \brief Convert `uint32_t` to `OMX_COMMANDTYPE`.
+ *
+ * \param[in] t The source `uint32_t`.
+ * \return The corresponding enum value of type `OMX_COMMANDTYPE`.
+ *
+ * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`.
+ */
+// convert: uint32_t -> OMX_COMMANDTYPE
+inline OMX_COMMANDTYPE toEnumCommandType(uint32_t t) {
+    return static_cast<OMX_COMMANDTYPE>(t);
+}
+
+/**
+ * \brief Convert `OMX_INDEXTYPE` to `uint32_t`.
+ *
+ * \param[in] l The source `OMX_INDEXTYPE`.
+ * \return The underlying value of type `uint32_t`.
+ *
+ * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`.
+ */
+// convert: OMX_INDEXTYPE -> uint32_t
+inline uint32_t toRawIndexType(OMX_INDEXTYPE l) {
+    return static_cast<uint32_t>(l);
+}
+
+/**
+ * \brief Convert `uint32_t` to `OMX_INDEXTYPE`.
+ *
+ * \param[in] t The source `uint32_t`.
+ * \return The corresponding enum value of type `OMX_INDEXTYPE`.
+ *
+ * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`.
+ */
+// convert: uint32_t -> OMX_INDEXTYPE
+inline OMX_INDEXTYPE toEnumIndexType(uint32_t t) {
+    return static_cast<OMX_INDEXTYPE>(t);
+}
+
+/**
+ * \brief Convert `IOMX::PortMode` to `PortMode`.
+ *
+ * \param[in] l The source `IOMX::PortMode`.
+ * \return The destination `PortMode`.
+ */
+// convert: IOMX::PortMode -> PortMode
+inline PortMode toHardwarePortMode(IOMX::PortMode l) {
+    return static_cast<PortMode>(l);
+}
+
+/**
+ * \brief Convert `PortMode` to `IOMX::PortMode`.
+ *
+ * \param[in] t The source `PortMode`.
+ * \return The destination `IOMX::PortMode`.
+ */
+// convert: PortMode -> IOMX::PortMode
+inline IOMX::PortMode toIOMXPortMode(PortMode t) {
+    return static_cast<IOMX::PortMode>(t);
+}
+
+/**
+ * \brief Convert `OMX_TICKS` to `uint64_t`.
+ *
+ * \param[in] l The source `OMX_TICKS`.
+ * \return The destination `uint64_t`.
+ */
+// convert: OMX_TICKS -> uint64_t
+inline uint64_t toRawTicks(OMX_TICKS l) {
+#ifndef OMX_SKIP64BIT
+    return static_cast<uint64_t>(l);
+#else
+    return static_cast<uint64_t>(l.nLowPart) |
+            static_cast<uint64_t>(l.nHighPart << 32);
+#endif
+}
+
+/**
+ * \brief Convert 'uint64_t` to `OMX_TICKS`.
+ *
+ * \param[in] l The source `uint64_t`.
+ * \return The destination `OMX_TICKS`.
+ */
+// convert: uint64_t -> OMX_TICKS
+inline OMX_TICKS toOMXTicks(uint64_t t) {
+#ifndef OMX_SKIP64BIT
+    return static_cast<OMX_TICKS>(t);
+#else
+    return OMX_TICKS{
+            static_cast<uint32_t>(t & 0xFFFFFFFF),
+            static_cast<uint32_t>(t >> 32)};
+#endif
+}
+
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
diff --git a/media/libstagefright/omx/hal/1.0/GraphicBufferSource.cpp b/media/libstagefright/omx/hal/1.0/GraphicBufferSource.cpp
deleted file mode 100644
index 6a43883..0000000
--- a/media/libstagefright/omx/hal/1.0/GraphicBufferSource.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "GraphicBufferSource.h"
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace omx {
-namespace V1_0 {
-namespace implementation {
-
-// Methods from ::android::hardware::media::omx::V1_0::IGraphicBufferSource follow.
-Return<Status> GraphicBufferSource::configure(const sp<IOmxNode>& omxNode, Dataspace dataspace) {
-    // TODO implement
-    return ::android::hardware::media::omx::V1_0::Status {};
-}
-
-Return<Status> GraphicBufferSource::setSuspend(bool suspend) {
-    // TODO implement
-    return ::android::hardware::media::omx::V1_0::Status {};
-}
-
-Return<Status> GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) {
-    // TODO implement
-    return ::android::hardware::media::omx::V1_0::Status {};
-}
-
-Return<Status> GraphicBufferSource::setMaxFps(float maxFps) {
-    // TODO implement
-    return ::android::hardware::media::omx::V1_0::Status {};
-}
-
-Return<Status> GraphicBufferSource::setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) {
-    // TODO implement
-    return ::android::hardware::media::omx::V1_0::Status {};
-}
-
-Return<Status> GraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
-    // TODO implement
-    return ::android::hardware::media::omx::V1_0::Status {};
-}
-
-Return<Status> GraphicBufferSource::setColorAspects(const ColorAspects& aspects) {
-    // TODO implement
-    return ::android::hardware::media::omx::V1_0::Status {};
-}
-
-Return<Status> GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
-    // TODO implement
-    return ::android::hardware::media::omx::V1_0::Status {};
-}
-
-Return<Status> GraphicBufferSource::signalEndOfInputStream() {
-    // TODO implement
-    return ::android::hardware::media::omx::V1_0::Status {};
-}
-
-
-IGraphicBufferSource* HIDL_FETCH_IGraphicBufferSource(const char* /* name */) {
-    return new GraphicBufferSource();
-}
-
-} // namespace implementation
-}  // namespace V1_0
-}  // namespace omx
-}  // namespace media
-}  // namespace hardware
-}  // namespace android
diff --git a/media/libstagefright/omx/hal/1.0/GraphicBufferSource.h b/media/libstagefright/omx/hal/1.0/GraphicBufferSource.h
deleted file mode 100644
index fb8c89d..0000000
--- a/media/libstagefright/omx/hal/1.0/GraphicBufferSource.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__GRAPHICBUFFERSOURCE_H
-#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__GRAPHICBUFFERSOURCE_H
-
-#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace omx {
-namespace V1_0 {
-namespace implementation {
-
-using ::android::hardware::graphics::common::V1_0::Dataspace;
-using ::android::hardware::media::omx::V1_0::ColorAspects;
-using ::android::hardware::media::omx::V1_0::IGraphicBufferSource;
-using ::android::hardware::media::omx::V1_0::IOmxNode;
-using ::android::hardware::media::omx::V1_0::Status;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
-struct GraphicBufferSource : public IGraphicBufferSource {
-    // Methods from ::android::hardware::media::omx::V1_0::IGraphicBufferSource follow.
-    Return<Status> configure(const sp<IOmxNode>& omxNode, Dataspace dataspace) override;
-    Return<Status> setSuspend(bool suspend) override;
-    Return<Status> setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
-    Return<Status> setMaxFps(float maxFps) override;
-    Return<Status> setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
-    Return<Status> setStartTimeUs(int64_t startTimeUs) override;
-    Return<Status> setColorAspects(const ColorAspects& aspects) override;
-    Return<Status> setTimeOffsetUs(int64_t timeOffsetUs) override;
-    Return<Status> signalEndOfInputStream() override;
-
-};
-
-extern "C" IGraphicBufferSource* HIDL_FETCH_IGraphicBufferSource(const char* name);
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace omx
-}  // namespace media
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0__GRAPHICBUFFERSOURCE_H
diff --git a/media/libstagefright/omx/hal/1.0/Omx.cpp b/media/libstagefright/omx/hal/1.0/Omx.cpp
index 68040eb..cb23191 100644
--- a/media/libstagefright/omx/hal/1.0/Omx.cpp
+++ b/media/libstagefright/omx/hal/1.0/Omx.cpp
@@ -19,11 +19,13 @@
 }
 
 
+// Methods from ::android::hidl::base::V1_0::IBase follow.
+
 IOmx* HIDL_FETCH_IOmx(const char* /* name */) {
     return new Omx();
 }
 
-} // namespace implementation
+}  // namespace implementation
 }  // namespace V1_0
 }  // namespace omx
 }  // namespace media
diff --git a/media/libstagefright/omx/hal/1.0/Omx.h b/media/libstagefright/omx/hal/1.0/Omx.h
index 02a0a01..5d06444 100644
--- a/media/libstagefright/omx/hal/1.0/Omx.h
+++ b/media/libstagefright/omx/hal/1.0/Omx.h
@@ -1,10 +1,12 @@
-#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMX_H
-#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMX_H
+#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0_OMX_H
+#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_OMX_H
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
+#include <IOMX.h>
+
 namespace android {
 namespace hardware {
 namespace media {
@@ -16,7 +18,9 @@
 using ::android::hardware::media::omx::V1_0::IOmxNode;
 using ::android::hardware::media::omx::V1_0::IOmxObserver;
 using ::android::hardware::media::omx::V1_0::Status;
+using ::android::hidl::base::V1_0::IBase;
 using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
@@ -28,6 +32,8 @@
     Return<void> listNodes(listNodes_cb _hidl_cb) override;
     Return<void> allocateNode(const hidl_string& name, const sp<IOmxObserver>& observer, allocateNode_cb _hidl_cb) override;
 
+    // Methods from ::android::hidl::base::V1_0::IBase follow.
+
 };
 
 extern "C" IOmx* HIDL_FETCH_IOmx(const char* name);
@@ -39,4 +45,4 @@
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMX_H
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_OMX_H
diff --git a/media/libstagefright/omx/hal/1.0/OmxBufferSource.cpp b/media/libstagefright/omx/hal/1.0/OmxBufferSource.cpp
deleted file mode 100644
index 2885d0d..0000000
--- a/media/libstagefright/omx/hal/1.0/OmxBufferSource.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include "OmxBufferSource.h"
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace omx {
-namespace V1_0 {
-namespace implementation {
-
-// Methods from ::android::hardware::media::omx::V1_0::IOmxBufferSource follow.
-Return<void> OmxBufferSource::onOmxExecuting() {
-    // TODO implement
-    return Void();
-}
-
-Return<void> OmxBufferSource::onOmxIdle() {
-    // TODO implement
-    return Void();
-}
-
-Return<void> OmxBufferSource::onOmxLoaded() {
-    // TODO implement
-    return Void();
-}
-
-Return<void> OmxBufferSource::onInputBufferAdded(uint32_t buffer) {
-    // TODO implement
-    return Void();
-}
-
-Return<void> OmxBufferSource::onInputBufferEmptied(uint32_t buffer, const hidl_handle& fence) {
-    // TODO implement
-    return Void();
-}
-
-
-IOmxBufferSource* HIDL_FETCH_IOmxBufferSource(const char* /* name */) {
-    return new OmxBufferSource();
-}
-
-} // namespace implementation
-}  // namespace V1_0
-}  // namespace omx
-}  // namespace media
-}  // namespace hardware
-}  // namespace android
diff --git a/media/libstagefright/omx/hal/1.0/OmxBufferSource.h b/media/libstagefright/omx/hal/1.0/OmxBufferSource.h
deleted file mode 100644
index 5e4855b..0000000
--- a/media/libstagefright/omx/hal/1.0/OmxBufferSource.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMXBUFFERSOURCE_H
-#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMXBUFFERSOURCE_H
-
-#include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace omx {
-namespace V1_0 {
-namespace implementation {
-
-using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
-struct OmxBufferSource : public IOmxBufferSource {
-    // Methods from ::android::hardware::media::omx::V1_0::IOmxBufferSource follow.
-    Return<void> onOmxExecuting() override;
-    Return<void> onOmxIdle() override;
-    Return<void> onOmxLoaded() override;
-    Return<void> onInputBufferAdded(uint32_t buffer) override;
-    Return<void> onInputBufferEmptied(uint32_t buffer, const hidl_handle& fence) override;
-
-};
-
-extern "C" IOmxBufferSource* HIDL_FETCH_IOmxBufferSource(const char* name);
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace omx
-}  // namespace media
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMXBUFFERSOURCE_H
diff --git a/media/libstagefright/omx/hal/1.0/OmxNode.cpp b/media/libstagefright/omx/hal/1.0/OmxNode.cpp
index ba0e722..08d1cd7 100644
--- a/media/libstagefright/omx/hal/1.0/OmxNode.cpp
+++ b/media/libstagefright/omx/hal/1.0/OmxNode.cpp
@@ -1,4 +1,9 @@
+#include <IOMX.h>
+#include <OMXNodeInstance.h>
 #include "OmxNode.h"
+#include "WOmxNode.h"
+#include "WOmxObserver.h"
+#include "Conversion.h"
 
 namespace android {
 namespace hardware {
@@ -13,7 +18,7 @@
     return ::android::hardware::media::omx::V1_0::Status {};
 }
 
-Return<Status> OmxNode::sendCommand(uint32_t cmd, const hidl_vec<uint8_t>& info) {
+Return<Status> OmxNode::sendCommand(uint32_t cmd, int32_t param) {
     // TODO implement
     return ::android::hardware::media::omx::V1_0::Status {};
 }
@@ -98,12 +103,11 @@
     return ::android::hardware::media::omx::V1_0::Status {};
 }
 
-
-IOmxNode* HIDL_FETCH_IOmxNode(const char* /* name */) {
-    return new OmxNode();
+OmxNode::OmxNode(OmxNodeOwner* owner, sp<IOmxObserver> const& observer, char const* name) {
+    mLNode = new OMXNodeInstance(owner, new LWOmxObserver(observer), name);
 }
 
-} // namespace implementation
+}  // namespace implementation
 }  // namespace V1_0
 }  // namespace omx
 }  // namespace media
diff --git a/media/libstagefright/omx/hal/1.0/OmxNode.h b/media/libstagefright/omx/hal/1.0/OmxNode.h
index dd9e5b4..e05e107 100644
--- a/media/libstagefright/omx/hal/1.0/OmxNode.h
+++ b/media/libstagefright/omx/hal/1.0/OmxNode.h
@@ -1,10 +1,13 @@
-#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMXNODE_H
-#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMXNODE_H
+#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0_OMXNODE_H
+#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_OMXNODE_H
 
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
+#include <android/hardware/media/omx/1.0/IOmxObserver.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
+#include <OMXNodeInstance.h>
+
 namespace android {
 namespace hardware {
 namespace media {
@@ -15,20 +18,34 @@
 using ::android::hardware::media::omx::V1_0::CodecBuffer;
 using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
 using ::android::hardware::media::omx::V1_0::IOmxNode;
+using ::android::hardware::media::omx::V1_0::IOmxObserver;
 using ::android::hardware::media::omx::V1_0::Message;
 using ::android::hardware::media::omx::V1_0::PortMode;
 using ::android::hardware::media::omx::V1_0::Status;
+using ::android::hidl::base::V1_0::IBase;
 using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::sp;
 
+using ::android::OMXNodeInstance;
+using ::android::OmxNodeOwner;
+
+/**
+ * Wrapper classes for conversion
+ * ==============================
+ *
+ * Naming convention:
+ * - LW = Legacy Wrapper --- It wraps a Treble object inside a legacy object.
+ * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
+ */
+
 struct OmxNode : public IOmxNode {
-    // Methods from ::android::hardware::media::omx::V1_0::IOmxNode follow.
     Return<Status> freeNode() override;
-    Return<Status> sendCommand(uint32_t cmd, const hidl_vec<uint8_t>& info) override;
+    Return<Status> sendCommand(uint32_t cmd, int32_t param) override;
     Return<void> getParameter(uint32_t index, const hidl_vec<uint8_t>& inParams, getParameter_cb _hidl_cb) override;
     Return<Status> setParameter(uint32_t index, const hidl_vec<uint8_t>& params) override;
     Return<void> getConfig(uint32_t index, const hidl_vec<uint8_t>& inConfig, getConfig_cb _hidl_cb) override;
@@ -46,10 +63,11 @@
     Return<void> getExtensionIndex(const hidl_string& parameterName, getExtensionIndex_cb _hidl_cb) override;
     Return<Status> dispatchMessage(const Message& msg) override;
 
+    OmxNode(OmxNodeOwner* owner, sp<IOmxObserver> const& observer, char const* name);
+protected:
+    sp<OMXNodeInstance> mLNode;
 };
 
-extern "C" IOmxNode* HIDL_FETCH_IOmxNode(const char* name);
-
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace omx
@@ -57,4 +75,4 @@
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMXNODE_H
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_OMXNODE_H
diff --git a/media/libstagefright/omx/hal/1.0/OmxObserver.cpp b/media/libstagefright/omx/hal/1.0/OmxObserver.cpp
deleted file mode 100644
index 4e946cd..0000000
--- a/media/libstagefright/omx/hal/1.0/OmxObserver.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "OmxObserver.h"
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace omx {
-namespace V1_0 {
-namespace implementation {
-
-// Methods from ::android::hardware::media::omx::V1_0::IOmxObserver follow.
-Return<void> OmxObserver::onMessages(const hidl_vec<Message>& messages) {
-    // TODO implement
-    return Void();
-}
-
-
-IOmxObserver* HIDL_FETCH_IOmxObserver(const char* /* name */) {
-    return new OmxObserver();
-}
-
-} // namespace implementation
-}  // namespace V1_0
-}  // namespace omx
-}  // namespace media
-}  // namespace hardware
-}  // namespace android
diff --git a/media/libstagefright/omx/hal/1.0/OmxObserver.h b/media/libstagefright/omx/hal/1.0/OmxObserver.h
deleted file mode 100644
index 630cae3..0000000
--- a/media/libstagefright/omx/hal/1.0/OmxObserver.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMXOBSERVER_H
-#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMXOBSERVER_H
-
-#include <android/hardware/media/omx/1.0/IOmxObserver.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace omx {
-namespace V1_0 {
-namespace implementation {
-
-using ::android::hardware::media::omx::V1_0::IOmxObserver;
-using ::android::hardware::media::omx::V1_0::Message;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
-struct OmxObserver : public IOmxObserver {
-    // Methods from ::android::hardware::media::omx::V1_0::IOmxObserver follow.
-    Return<void> onMessages(const hidl_vec<Message>& messages) override;
-
-};
-
-extern "C" IOmxObserver* HIDL_FETCH_IOmxObserver(const char* name);
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace omx
-}  // namespace media
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0__OMXOBSERVER_H
diff --git a/media/libstagefright/omx/hal/1.0/WGraphicBufferSource.cpp b/media/libstagefright/omx/hal/1.0/WGraphicBufferSource.cpp
new file mode 100644
index 0000000..0ec31f2
--- /dev/null
+++ b/media/libstagefright/omx/hal/1.0/WGraphicBufferSource.cpp
@@ -0,0 +1,124 @@
+#include "WGraphicBufferSource.h"
+#include "Conversion.h"
+#include "WOmxNode.h"
+#include <stagefright/foundation/ColorUtils.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+using android::ColorUtils;
+
+// LWGraphicBufferSource
+LWGraphicBufferSource::LWGraphicBufferSource(
+        sp<TGraphicBufferSource> const& base) : mBase(base) {
+}
+
+::android::binder::Status LWGraphicBufferSource::configure(
+        const sp<IOMXNode>& omxNode, int32_t dataSpace) {
+    return toBinderStatus(mBase->configure(
+            new TWOmxNode(omxNode), toHardwareDataspace(dataSpace)));
+}
+
+::android::binder::Status LWGraphicBufferSource::setSuspend(bool suspend) {
+    return toBinderStatus(mBase->setSuspend(suspend));
+}
+
+::android::binder::Status LWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
+        int64_t repeatAfterUs) {
+    return toBinderStatus(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
+}
+
+::android::binder::Status LWGraphicBufferSource::setMaxFps(float maxFps) {
+    return toBinderStatus(mBase->setMaxFps(maxFps));
+}
+
+::android::binder::Status LWGraphicBufferSource::setTimeLapseConfig(
+        int64_t timePerFrameUs, int64_t timePerCaptureUs) {
+    return toBinderStatus(mBase->setTimeLapseConfig(
+            timePerFrameUs, timePerCaptureUs));
+}
+
+::android::binder::Status LWGraphicBufferSource::setStartTimeUs(
+        int64_t startTimeUs) {
+    return toBinderStatus(mBase->setStartTimeUs(startTimeUs));
+}
+
+::android::binder::Status LWGraphicBufferSource::setColorAspects(
+        int32_t aspects) {
+    return toBinderStatus(mBase->setColorAspects(
+            toHardwareColorAspects(aspects)));
+}
+
+::android::binder::Status LWGraphicBufferSource::setTimeOffsetUs(
+        int64_t timeOffsetsUs) {
+    return toBinderStatus(mBase->setTimeOffsetUs(timeOffsetsUs));
+}
+
+::android::binder::Status LWGraphicBufferSource::signalEndOfInputStream() {
+    return toBinderStatus(mBase->signalEndOfInputStream());
+}
+
+::android::IBinder* LWGraphicBufferSource::onAsBinder() {
+    return nullptr;
+}
+
+// TWGraphicBufferSource
+TWGraphicBufferSource::TWGraphicBufferSource(
+        sp<LGraphicBufferSource> const& base) : mBase(base) {
+}
+
+Return<void> TWGraphicBufferSource::configure(
+        const sp<IOmxNode>& omxNode, Dataspace dataspace) {
+    return toHardwareStatus(mBase->configure(
+            new LWOmxNode(omxNode),
+            toRawDataspace(dataspace)));
+}
+
+Return<void> TWGraphicBufferSource::setSuspend(bool suspend) {
+    return toHardwareStatus(mBase->setSuspend(suspend));
+}
+
+Return<void> TWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
+        int64_t repeatAfterUs) {
+    return toHardwareStatus(mBase->setRepeatPreviousFrameDelayUs(
+            repeatAfterUs));
+}
+
+Return<void> TWGraphicBufferSource::setMaxFps(float maxFps) {
+    return toHardwareStatus(mBase->setMaxFps(maxFps));
+}
+
+Return<void> TWGraphicBufferSource::setTimeLapseConfig(
+        int64_t timePerFrameUs, int64_t timePerCaptureUs) {
+    return toHardwareStatus(mBase->setTimeLapseConfig(
+            timePerFrameUs, timePerCaptureUs));
+}
+
+Return<void> TWGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
+    return toHardwareStatus(mBase->setStartTimeUs(startTimeUs));
+}
+
+Return<void> TWGraphicBufferSource::setColorAspects(
+        const ColorAspects& aspects) {
+    return toHardwareStatus(mBase->setColorAspects(toCompactColorAspects(
+            aspects)));
+}
+
+Return<void> TWGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
+    return toHardwareStatus(mBase->setTimeOffsetUs(timeOffsetUs));
+}
+
+Return<void> TWGraphicBufferSource::signalEndOfInputStream() {
+    return toHardwareStatus(mBase->signalEndOfInputStream());
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
diff --git a/media/libstagefright/omx/hal/1.0/WGraphicBufferSource.h b/media/libstagefright/omx/hal/1.0/WGraphicBufferSource.h
new file mode 100644
index 0000000..66977ad
--- /dev/null
+++ b/media/libstagefright/omx/hal/1.0/WGraphicBufferSource.h
@@ -0,0 +1,92 @@
+#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0_WGRAPHICBUFFERSOURCE_H
+#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_WGRAPHICBUFFERSOURCE_H
+
+#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <frameworks/native/include/binder/Binder.h>
+#include <IOMX.h>
+#include <android/IGraphicBufferSource.h>
+#include <android/hardware/media/omx/1.0/IOmxNode.h>
+
+#include <android/hardware/graphics/common/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+using ::android::hardware::media::omx::V1_0::ColorAspects;
+using ::android::hardware::media::omx::V1_0::IGraphicBufferSource;
+using ::android::hardware::media::omx::V1_0::IOmxNode;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+using ::android::IOMXNode;
+
+/**
+ * Wrapper classes for conversion
+ * ==============================
+ *
+ * Naming convention:
+ * - LW = Legacy Wrapper --- It wraps a Treble object inside a legacy object.
+ * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
+ */
+
+typedef ::android::IGraphicBufferSource LGraphicBufferSource;
+typedef ::android::hardware::media::omx::V1_0::IGraphicBufferSource
+        TGraphicBufferSource;
+
+struct LWGraphicBufferSource : public LGraphicBufferSource {
+    sp<TGraphicBufferSource> mBase;
+    LWGraphicBufferSource(sp<TGraphicBufferSource> const& base);
+    ::android::binder::Status configure(
+            const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
+    ::android::binder::Status setSuspend(bool suspend) override;
+    ::android::binder::Status setRepeatPreviousFrameDelayUs(
+            int64_t repeatAfterUs) override;
+    ::android::binder::Status setMaxFps(float maxFps) override;
+    ::android::binder::Status setTimeLapseConfig(
+            int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
+    ::android::binder::Status setStartTimeUs(int64_t startTimeUs) override;
+    ::android::binder::Status setColorAspects(int32_t aspects) override;
+    ::android::binder::Status setTimeOffsetUs(int64_t timeOffsetsUs) override;
+    ::android::binder::Status signalEndOfInputStream() override;
+protected:
+    ::android::IBinder* onAsBinder() override;
+};
+
+struct TWGraphicBufferSource : public TGraphicBufferSource {
+    sp<LGraphicBufferSource> mBase;
+    TWGraphicBufferSource(sp<LGraphicBufferSource> const& base);
+    Return<void> configure(
+            const sp<IOmxNode>& omxNode, Dataspace dataspace) override;
+    Return<void> setSuspend(bool suspend) override;
+    Return<void> setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
+    Return<void> setMaxFps(float maxFps) override;
+    Return<void> setTimeLapseConfig(
+            int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
+    Return<void> setStartTimeUs(int64_t startTimeUs) override;
+    Return<void> setColorAspects(const ColorAspects& aspects) override;
+    Return<void> setTimeOffsetUs(int64_t timeOffsetUs) override;
+    Return<void> signalEndOfInputStream() override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_WGRAPHICBUFFERSOURCE_H
diff --git a/media/libstagefright/omx/hal/1.0/WOmx.cpp b/media/libstagefright/omx/hal/1.0/WOmx.cpp
new file mode 100644
index 0000000..25bcfe9
--- /dev/null
+++ b/media/libstagefright/omx/hal/1.0/WOmx.cpp
@@ -0,0 +1,95 @@
+#include "WOmx.h"
+#include "WOmxNode.h"
+#include "WOmxObserver.h"
+#include "Conversion.h"
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+// LWOmx
+LWOmx::LWOmx(sp<IOmx> const& base) : mBase(base) {
+}
+
+status_t LWOmx::listNodes(List<IOMX::ComponentInfo>* list) {
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->listNodes(
+            [&fnStatus, list](
+                    Status status,
+                    hidl_vec<IOmx::ComponentInfo> const& nodeList) {
+                fnStatus = toStatusT(status);
+                list->clear();
+                for (size_t i = 0; i < nodeList.size(); ++i) {
+                    auto newInfo = list->insert(
+                            list->end(), IOMX::ComponentInfo());
+                    convertTo(&*newInfo, nodeList[i]);
+                }
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmx::allocateNode(
+        char const* name,
+        sp<IOMXObserver> const& observer,
+        sp<IOMXNode>* omxNode) {
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->allocateNode(
+            name, new TWOmxObserver(observer),
+            [&fnStatus, omxNode](Status status, sp<IOmxNode> const& node) {
+                fnStatus = toStatusT(status);
+                *omxNode = new LWOmxNode(node);
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmx::createInputSurface(
+        sp<::android::IGraphicBufferProducer>* /* bufferProducer */,
+        sp<::android::IGraphicBufferSource>* /* bufferSource */) {
+    // TODO: Implement.
+    return INVALID_OPERATION;
+}
+
+::android::IBinder* LWOmx::onAsBinder() {
+    return nullptr;
+}
+
+// TWOmx
+TWOmx::TWOmx(sp<IOMX> const& base) : mBase(base) {
+}
+
+Return<void> TWOmx::listNodes(listNodes_cb _hidl_cb) {
+    List<IOMX::ComponentInfo> lList;
+    Status status = toStatus(mBase->listNodes(&lList));
+
+    hidl_vec<IOmx::ComponentInfo> tList;
+    tList.resize(lList.size());
+    size_t i = 0;
+    for (auto const& lInfo : lList) {
+        convertTo(&(tList[i++]), lInfo);
+    }
+    _hidl_cb(status, tList);
+    return Void();
+}
+
+Return<void> TWOmx::allocateNode(
+        const hidl_string& name,
+        const sp<IOmxObserver>& observer,
+        allocateNode_cb _hidl_cb) {
+    sp<IOMXNode> omxNode;
+    Status status = toStatus(mBase->allocateNode(
+            name, new LWOmxObserver(observer), &omxNode));
+    _hidl_cb(status, new TWOmxNode(omxNode));
+    return Void();
+}
+
+// TODO: Add createInputSurface().
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
diff --git a/media/libstagefright/omx/hal/1.0/WOmx.h b/media/libstagefright/omx/hal/1.0/WOmx.h
new file mode 100644
index 0000000..b07c4f2
--- /dev/null
+++ b/media/libstagefright/omx/hal/1.0/WOmx.h
@@ -0,0 +1,75 @@
+#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMX_H
+#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMX_H
+
+#include <android/hardware/media/omx/1.0/IOmx.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <IOMX.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::media::omx::V1_0::IOmx;
+using ::android::hardware::media::omx::V1_0::IOmxNode;
+using ::android::hardware::media::omx::V1_0::IOmxObserver;
+using ::android::hardware::media::omx::V1_0::Status;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+using ::android::List;
+using ::android::IOMX;
+
+/**
+ * Wrapper classes for conversion
+ * ==============================
+ *
+ * Naming convention:
+ * - LW = Legacy Wrapper --- It wraps a Treble object inside a legacy object.
+ * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
+ */
+
+struct LWOmx : public IOMX {
+    sp<IOmx> mBase;
+    LWOmx(sp<IOmx> const& base);
+    status_t listNodes(List<IOMX::ComponentInfo>* list) override;
+    status_t allocateNode(
+            char const* name,
+            sp<IOMXObserver> const& observer,
+            sp<IOMXNode>* omxNode) override;
+    status_t createInputSurface(
+            sp<::android::IGraphicBufferProducer>* bufferProducer,
+            sp<::android::IGraphicBufferSource>* bufferSource) override;
+protected:
+    ::android::IBinder* onAsBinder() override;
+};
+
+struct TWOmx : public IOmx {
+    sp<IOMX> mBase;
+    TWOmx(sp<IOMX> const& base);
+    Return<void> listNodes(listNodes_cb _hidl_cb) override;
+    Return<void> allocateNode(
+            const hidl_string& name,
+            const sp<IOmxObserver>& observer,
+            allocateNode_cb _hidl_cb) override;
+
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMX_H
diff --git a/media/libstagefright/omx/hal/1.0/WOmxBufferSource.cpp b/media/libstagefright/omx/hal/1.0/WOmxBufferSource.cpp
new file mode 100644
index 0000000..79eb1be
--- /dev/null
+++ b/media/libstagefright/omx/hal/1.0/WOmxBufferSource.cpp
@@ -0,0 +1,95 @@
+#include "WOmxBufferSource.h"
+#include "Conversion.h"
+#include <utils/String8.h>
+#include <cutils/native_handle.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+// LWOmxBufferSource
+LWOmxBufferSource::LWOmxBufferSource(sp<IOmxBufferSource> const& base) :
+    mBase(base) {
+}
+
+::android::binder::Status LWOmxBufferSource::onOmxExecuting() {
+    return toBinderStatus(mBase->onOmxExecuting());
+}
+
+::android::binder::Status LWOmxBufferSource::onOmxIdle() {
+    return toBinderStatus(mBase->onOmxIdle());
+}
+
+::android::binder::Status LWOmxBufferSource::onOmxLoaded() {
+    return toBinderStatus(mBase->onOmxLoaded());
+}
+
+::android::binder::Status LWOmxBufferSource::onInputBufferAdded(
+        int32_t bufferId) {
+    return toBinderStatus(mBase->onInputBufferAdded(
+            static_cast<uint32_t>(bufferId)));
+}
+
+::android::binder::Status LWOmxBufferSource::onInputBufferEmptied(
+        int32_t bufferId, OMXFenceParcelable const& fenceParcel) {
+    hidl_handle fence;
+    native_handle_t* fenceNh;
+    if (!wrapAs(&fence, &fenceNh, fenceParcel)) {
+        return ::android::binder::Status::fromExceptionCode(
+                ::android::binder::Status::EX_BAD_PARCELABLE,
+                "Invalid fence");
+    }
+    ::android::binder::Status status = toBinderStatus(
+            mBase->onInputBufferEmptied(
+            static_cast<uint32_t>(bufferId), fence));
+    if (native_handle_delete(fenceNh) != 0) {
+        return ::android::binder::Status::fromExceptionCode(
+                ::android::binder::Status::EX_NULL_POINTER,
+                "Cannot delete native handle");
+    }
+    return status;
+}
+
+::android::IBinder* LWOmxBufferSource::onAsBinder() {
+    return nullptr;
+}
+
+// TWOmxBufferSource
+TWOmxBufferSource::TWOmxBufferSource(sp<IOMXBufferSource> const& base) :
+    mBase(base) {
+}
+
+Return<void> TWOmxBufferSource::onOmxExecuting() {
+    return toHardwareStatus(mBase->onOmxExecuting());
+}
+
+Return<void> TWOmxBufferSource::onOmxIdle() {
+    return toHardwareStatus(mBase->onOmxIdle());
+}
+
+Return<void> TWOmxBufferSource::onOmxLoaded() {
+    return toHardwareStatus(mBase->onOmxLoaded());
+}
+
+Return<void> TWOmxBufferSource::onInputBufferAdded(uint32_t buffer) {
+    return toHardwareStatus(mBase->onInputBufferAdded(
+            static_cast<int32_t>(buffer)));
+}
+
+Return<void> TWOmxBufferSource::onInputBufferEmptied(
+        uint32_t buffer, hidl_handle const& fence) {
+    OMXFenceParcelable fenceParcelable;
+    wrapAs(&fenceParcelable, fence);
+    return toHardwareStatus(mBase->onInputBufferEmptied(
+            static_cast<int32_t>(buffer), fenceParcelable));
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
diff --git a/media/libstagefright/omx/hal/1.0/WOmxBufferSource.h b/media/libstagefright/omx/hal/1.0/WOmxBufferSource.h
new file mode 100644
index 0000000..3ba9453
--- /dev/null
+++ b/media/libstagefright/omx/hal/1.0/WOmxBufferSource.h
@@ -0,0 +1,74 @@
+#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMXBUFFERSOURCE_H
+#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMXBUFFERSOURCE_H
+
+#include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <frameworks/native/include/binder/Binder.h>
+#include <android/IOMXBufferSource.h>
+#include <OMXFenceParcelable.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+using ::android::OMXFenceParcelable;
+using ::android::IOMXBufferSource;
+
+/**
+ * Wrapper classes for conversion
+ * ==============================
+ *
+ * Naming convention:
+ * - LW = Legacy Wrapper --- It wraps a Treble object inside a legacy object.
+ * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
+ */
+
+struct LWOmxBufferSource : public IOMXBufferSource {
+    sp<IOmxBufferSource> mBase;
+    LWOmxBufferSource(sp<IOmxBufferSource> const& base);
+    ::android::binder::Status onOmxExecuting() override;
+    ::android::binder::Status onOmxIdle() override;
+    ::android::binder::Status onOmxLoaded() override;
+    ::android::binder::Status onInputBufferAdded(int32_t bufferID) override;
+    ::android::binder::Status onInputBufferEmptied(
+            int32_t bufferID, OMXFenceParcelable const& fenceParcel) override;
+protected:
+    ::android::IBinder* onAsBinder() override;
+};
+
+struct TWOmxBufferSource : public IOmxBufferSource {
+    sp<IOMXBufferSource> mBase;
+    TWOmxBufferSource(sp<IOMXBufferSource> const& base);
+    Return<void> onOmxExecuting() override;
+    Return<void> onOmxIdle() override;
+    Return<void> onOmxLoaded() override;
+    Return<void> onInputBufferAdded(uint32_t buffer) override;
+    Return<void> onInputBufferEmptied(
+            uint32_t buffer, hidl_handle const& fence) override;
+};
+
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMXBUFFERSOURCE_H
diff --git a/media/libstagefright/omx/hal/1.0/WOmxNode.cpp b/media/libstagefright/omx/hal/1.0/WOmxNode.cpp
new file mode 100644
index 0000000..0e781d8
--- /dev/null
+++ b/media/libstagefright/omx/hal/1.0/WOmxNode.cpp
@@ -0,0 +1,421 @@
+#include <IOMX.h>
+#include <OMXNodeInstance.h>
+#include "WOmxNode.h"
+#include "WOmxBufferSource.h"
+#include "Conversion.h"
+
+#include <algorithm>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Void;
+
+// LWOmxNode
+LWOmxNode::LWOmxNode(sp<IOmxNode> const& base) : mBase(base) {
+}
+
+status_t LWOmxNode::freeNode() {
+    return toStatusT(mBase->freeNode());
+}
+
+status_t LWOmxNode::sendCommand(
+        OMX_COMMANDTYPE cmd, OMX_S32 param) {
+    return toStatusT(mBase->sendCommand(
+            toRawCommandType(cmd), param));
+}
+
+status_t LWOmxNode::getParameter(
+        OMX_INDEXTYPE index, void *params, size_t size) {
+    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->getParameter(
+            toRawIndexType(index),
+            tParams,
+            [&fnStatus, params, size](
+                    Status status, hidl_vec<uint8_t> const& outParams) {
+                fnStatus = toStatusT(status);
+                std::copy(
+                        outParams.data(),
+                        outParams.data() + outParams.size(),
+                        static_cast<uint8_t*>(params));
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxNode::setParameter(
+        OMX_INDEXTYPE index, const void *params, size_t size) {
+    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
+    tParams = inHidlBytes(params, size);
+    return toStatusT(mBase->setParameter(
+            toRawIndexType(index), tParams));
+}
+
+status_t LWOmxNode::getConfig(
+        OMX_INDEXTYPE index, void *params, size_t size) {
+    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->getConfig(
+            toRawIndexType(index),
+            tParams,
+            [&fnStatus, params, size](
+                    Status status, hidl_vec<uint8_t> const& outParams) {
+                fnStatus = toStatusT(status);
+                std::copy(
+                        outParams.data(),
+                        outParams.data() + size,
+                        static_cast<uint8_t*>(params));
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxNode::setConfig(
+        OMX_INDEXTYPE index, const void *params, size_t size) {
+    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
+    return toStatusT(mBase->setConfig(toRawIndexType(index), tParams));
+}
+
+status_t LWOmxNode::setPortMode(
+        OMX_U32 port_index, IOMX::PortMode mode) {
+    return toStatusT(mBase->setPortMode(port_index, toHardwarePortMode(mode)));
+}
+
+status_t LWOmxNode::prepareForAdaptivePlayback(
+        OMX_U32 portIndex, OMX_BOOL enable,
+        OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
+    return toStatusT(mBase->prepareForAdaptivePlayback(
+            portIndex, toRawBool(enable), maxFrameWidth, maxFrameHeight));
+}
+
+status_t LWOmxNode::configureVideoTunnelMode(
+        OMX_U32 portIndex, OMX_BOOL tunneled,
+        OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->configureVideoTunnelMode(
+            portIndex,
+            toRawBool(tunneled),
+            audioHwSync,
+            [&fnStatus, sidebandHandle](
+                    Status status, hidl_handle const& outSidebandHandle) {
+                fnStatus = toStatusT(status);
+                *sidebandHandle = native_handle_clone(outSidebandHandle);
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxNode::getGraphicBufferUsage(
+        OMX_U32 portIndex, OMX_U32* usage) {
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->getGraphicBufferUsage(
+            portIndex,
+            [&fnStatus, usage](
+                    Status status, uint32_t outUsage) {
+                fnStatus = toStatusT(status);
+                *usage = outUsage;
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxNode::setInputSurface(
+        const sp<IOMXBufferSource> &bufferSource) {
+    return toStatusT(mBase->setInputSurface(
+            new TWOmxBufferSource(bufferSource)));
+}
+
+status_t LWOmxNode::allocateSecureBuffer(
+        OMX_U32 portIndex, size_t size, buffer_id *buffer,
+        void **buffer_data, sp<NativeHandle> *native_handle) {
+    *buffer_data = nullptr;
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->allocateSecureBuffer(
+            portIndex,
+            static_cast<uint64_t>(size),
+            [&fnStatus, buffer, buffer_data, native_handle](
+                    Status status,
+                    uint32_t outBuffer,
+                    hidl_handle const& outNativeHandle) {
+                fnStatus = toStatusT(status);
+                *buffer = outBuffer;
+                *native_handle = NativeHandle::create(
+                        native_handle_clone(outNativeHandle), true);
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxNode::useBuffer(
+        OMX_U32 portIndex, const OMXBuffer &omxBuffer, buffer_id *buffer) {
+    CodecBuffer codecBuffer;
+    if (!wrapAs(&codecBuffer, omxBuffer)) {
+        return BAD_VALUE;
+    }
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->useBuffer(
+            portIndex,
+            codecBuffer,
+            [&fnStatus, buffer](Status status, uint32_t outBuffer) {
+                fnStatus = toStatusT(status);
+                *buffer = outBuffer;
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxNode::freeBuffer(
+        OMX_U32 portIndex, buffer_id buffer) {
+    return toStatusT(mBase->freeBuffer(portIndex, buffer));
+}
+
+status_t LWOmxNode::fillBuffer(
+        buffer_id buffer, const OMXBuffer &omxBuffer, int fenceFd) {
+    CodecBuffer codecBuffer;
+    if (!wrapAs(&codecBuffer, omxBuffer)) {
+        return BAD_VALUE;
+    }
+    native_handle_t* fenceNh = native_handle_create_from_fd(fenceFd);
+    if (!fenceNh) {
+        return NO_MEMORY;
+    }
+    status_t status = toStatusT(mBase->fillBuffer(
+            buffer, codecBuffer, fenceNh));
+    native_handle_delete(fenceNh);
+    return status;
+}
+
+status_t LWOmxNode::emptyBuffer(
+        buffer_id buffer, const OMXBuffer &omxBuffer,
+        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
+    CodecBuffer codecBuffer;
+    if (!wrapAs(&codecBuffer, omxBuffer)) {
+        return BAD_VALUE;
+    }
+    native_handle_t* fenceNh = native_handle_create_from_fd(fenceFd);
+    if (!fenceNh) {
+        return NO_MEMORY;
+    }
+    status_t status = toStatusT(mBase->emptyBuffer(
+            buffer,
+            codecBuffer,
+            flags,
+            toRawTicks(timestamp),
+            fenceNh));
+    native_handle_delete(fenceNh);
+    return status;
+}
+status_t LWOmxNode::getExtensionIndex(
+        const char *parameter_name,
+        OMX_INDEXTYPE *index) {
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->getExtensionIndex(
+            hidl_string(parameter_name),
+            [&fnStatus, index](Status status, uint32_t outIndex) {
+                fnStatus = toStatusT(status);
+                *index = toEnumIndexType(outIndex);
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxNode::dispatchMessage(const omx_message &lMsg) {
+    Message tMsg;
+    native_handle_t* nh;
+    if (!wrapAs(&tMsg, &nh, lMsg)) {
+        return NO_MEMORY;
+    }
+    status_t status = toStatusT(mBase->dispatchMessage(tMsg));
+    native_handle_delete(nh);
+    return status;
+}
+
+// TODO: this is temporary, will be removed when quirks move to OMX side.
+status_t LWOmxNode::setQuirks(OMX_U32 /* quirks */) {
+    return NO_ERROR;
+}
+
+::android::IBinder* LWOmxNode::onAsBinder() {
+    return nullptr;
+}
+
+// TWOmxNode
+TWOmxNode::TWOmxNode(sp<IOMXNode> const& base) : mBase(base) {
+}
+
+Return<Status> TWOmxNode::freeNode() {
+    return toStatus(mBase->freeNode());
+}
+
+Return<Status> TWOmxNode::sendCommand(uint32_t cmd, int32_t param) {
+    return toStatus(mBase->sendCommand(toEnumCommandType(cmd), param));
+}
+
+Return<void> TWOmxNode::getParameter(
+        uint32_t index, hidl_vec<uint8_t> const& inParams,
+        getParameter_cb _hidl_cb) {
+    hidl_vec<uint8_t> params(inParams);
+    Status status = toStatus(mBase->getParameter(
+            toEnumIndexType(index),
+            static_cast<void*>(params.data()),
+            params.size()));
+    _hidl_cb(status, params);
+    return Void();
+}
+
+Return<Status> TWOmxNode::setParameter(
+        uint32_t index, hidl_vec<uint8_t> const& params) {
+    return toStatus(mBase->setParameter(
+            toEnumIndexType(index),
+            static_cast<void const*>(params.data()),
+            params.size()));
+}
+
+Return<void> TWOmxNode::getConfig(
+        uint32_t index, const hidl_vec<uint8_t>& inConfig,
+        getConfig_cb _hidl_cb) {
+    hidl_vec<uint8_t> config(inConfig);
+    Status status = toStatus(mBase->getConfig(
+            toEnumIndexType(index),
+            static_cast<void*>(config.data()),
+            config.size()));
+    _hidl_cb(status, config);
+    return Void();
+}
+
+Return<Status> TWOmxNode::setConfig(
+        uint32_t index, const hidl_vec<uint8_t>& config) {
+    return toStatus(mBase->setConfig(
+            toEnumIndexType(index),
+            static_cast<void const*>(config.data()),
+            config.size()));
+}
+
+Return<Status> TWOmxNode::setPortMode(uint32_t portIndex, PortMode mode) {
+    return toStatus(mBase->setPortMode(portIndex, toIOMXPortMode(mode)));
+}
+
+Return<Status> TWOmxNode::prepareForAdaptivePlayback(
+        uint32_t portIndex, bool enable,
+        uint32_t maxFrameWidth, uint32_t maxFrameHeight) {
+    return toStatus(mBase->prepareForAdaptivePlayback(
+            portIndex,
+            toEnumBool(enable),
+            maxFrameWidth,
+            maxFrameHeight));
+}
+
+Return<void> TWOmxNode::configureVideoTunnelMode(
+        uint32_t portIndex, bool tunneled, uint32_t audioHwSync,
+        configureVideoTunnelMode_cb _hidl_cb) {
+    native_handle_t* sidebandHandle;
+    Status status = toStatus(mBase->configureVideoTunnelMode(
+            portIndex,
+            toEnumBool(tunneled),
+            audioHwSync,
+            &sidebandHandle));
+    _hidl_cb(status, hidl_handle(sidebandHandle));
+    return Void();
+}
+
+Return<void> TWOmxNode::getGraphicBufferUsage(
+        uint32_t portIndex, getGraphicBufferUsage_cb _hidl_cb) {
+    OMX_U32 usage;
+    Status status = toStatus(mBase->getGraphicBufferUsage(
+            portIndex, &usage));
+    _hidl_cb(status, usage);
+    return Void();
+}
+
+Return<Status> TWOmxNode::setInputSurface(
+        const sp<IOmxBufferSource>& bufferSource) {
+    return toStatus(mBase->setInputSurface(new LWOmxBufferSource(
+            bufferSource)));
+}
+
+Return<void> TWOmxNode::allocateSecureBuffer(
+        uint32_t portIndex, uint64_t size,
+        allocateSecureBuffer_cb _hidl_cb) {
+    IOMX::buffer_id buffer;
+    void* bufferData;
+    sp<NativeHandle> nativeHandle;
+    Status status = toStatus(mBase->allocateSecureBuffer(
+            portIndex,
+            static_cast<size_t>(size),
+            &buffer,
+            &bufferData,
+            &nativeHandle));
+    _hidl_cb(status, buffer, nativeHandle->handle());
+    return Void();
+}
+
+Return<void> TWOmxNode::useBuffer(
+        uint32_t portIndex, const CodecBuffer& codecBuffer,
+        useBuffer_cb _hidl_cb) {
+    IOMX::buffer_id buffer;
+    OMXBuffer omxBuffer;
+    if (!convertTo(&omxBuffer, codecBuffer)) {
+        _hidl_cb(Status::BAD_VALUE, 0);
+        return Void();
+    }
+    Status status = toStatus(mBase->useBuffer(
+            portIndex, omxBuffer, &buffer));
+    _hidl_cb(status, buffer);
+    return Void();
+}
+
+Return<Status> TWOmxNode::freeBuffer(uint32_t portIndex, uint32_t buffer) {
+    return toStatus(mBase->freeBuffer(portIndex, buffer));
+}
+
+Return<Status> TWOmxNode::fillBuffer(
+        uint32_t buffer, const CodecBuffer& codecBuffer,
+        const hidl_handle& fence) {
+    OMXBuffer omxBuffer;
+    if (!convertTo(&omxBuffer, codecBuffer)) {
+        return Status::BAD_VALUE;
+    }
+    return toStatus(mBase->fillBuffer(
+            buffer,
+            omxBuffer,
+            native_handle_read_fd(fence)));
+}
+
+Return<Status> TWOmxNode::emptyBuffer(
+        uint32_t buffer, const CodecBuffer& codecBuffer, uint32_t flags,
+        uint64_t timestampUs, const hidl_handle& fence) {
+    OMXBuffer omxBuffer;
+    if (!convertTo(&omxBuffer, codecBuffer)) {
+        return Status::BAD_VALUE;
+    }
+    return toStatus(mBase->emptyBuffer(
+            buffer,
+            omxBuffer,
+            flags,
+            toOMXTicks(timestampUs),
+            native_handle_read_fd(fence)));
+}
+
+Return<void> TWOmxNode::getExtensionIndex(
+        const hidl_string& parameterName,
+        getExtensionIndex_cb _hidl_cb) {
+    OMX_INDEXTYPE index;
+    Status status = toStatus(mBase->getExtensionIndex(
+            parameterName, &index));
+    _hidl_cb(status, toRawIndexType(index));
+    return Void();
+}
+
+Return<Status> TWOmxNode::dispatchMessage(const Message& tMsg) {
+    omx_message lMsg;
+    if (!wrapAs(&lMsg, tMsg)) {
+        return Status::BAD_VALUE;
+    }
+    return toStatus(mBase->dispatchMessage(lMsg));
+}
+
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
diff --git a/media/libstagefright/omx/hal/1.0/WOmxNode.h b/media/libstagefright/omx/hal/1.0/WOmxNode.h
new file mode 100644
index 0000000..3a459d6
--- /dev/null
+++ b/media/libstagefright/omx/hal/1.0/WOmxNode.h
@@ -0,0 +1,149 @@
+#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMXNODE_H
+#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMXNODE_H
+
+#include <android/hardware/media/omx/1.0/IOmxNode.h>
+#include <android/hardware/media/omx/1.0/IOmxObserver.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <utils/Errors.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::media::omx::V1_0::CodecBuffer;
+using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
+using ::android::hardware::media::omx::V1_0::IOmxNode;
+using ::android::hardware::media::omx::V1_0::IOmxObserver;
+using ::android::hardware::media::omx::V1_0::Message;
+using ::android::hardware::media::omx::V1_0::PortMode;
+using ::android::hardware::media::omx::V1_0::Status;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+/**
+ * Wrapper classes for conversion
+ * ==============================
+ *
+ * Naming convention:
+ * - LW = Legacy Wrapper --- It wraps a Treble object inside a legacy object.
+ * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
+ */
+
+struct LWOmxNode : public IOMXNode {
+    sp<IOmxNode> mBase;
+    LWOmxNode(sp<IOmxNode> const& base);
+    status_t freeNode() override;
+    status_t sendCommand(
+            OMX_COMMANDTYPE cmd, OMX_S32 param) override;
+    status_t getParameter(
+            OMX_INDEXTYPE index, void *params, size_t size) override;
+    status_t setParameter(
+            OMX_INDEXTYPE index, const void *params, size_t size) override;
+    status_t getConfig(
+            OMX_INDEXTYPE index, void *params, size_t size) override;
+    status_t setConfig(
+            OMX_INDEXTYPE index, const void *params, size_t size) override;
+    status_t setPortMode(
+            OMX_U32 port_index, IOMX::PortMode mode) override;
+    status_t prepareForAdaptivePlayback(
+            OMX_U32 portIndex, OMX_BOOL enable,
+            OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) override;
+    status_t configureVideoTunnelMode(
+            OMX_U32 portIndex, OMX_BOOL tunneled,
+            OMX_U32 audioHwSync, native_handle_t **sidebandHandle) override;
+    status_t getGraphicBufferUsage(
+            OMX_U32 port_index, OMX_U32* usage) override;
+    status_t setInputSurface(
+            const sp<IOMXBufferSource> &bufferSource) override;
+    status_t allocateSecureBuffer(
+            OMX_U32 port_index, size_t size, buffer_id *buffer,
+            void **buffer_data, sp<NativeHandle> *native_handle) override;
+    status_t useBuffer(
+            OMX_U32 port_index, const OMXBuffer &omxBuf,
+            buffer_id *buffer) override;
+    status_t freeBuffer(
+            OMX_U32 port_index, buffer_id buffer) override;
+    status_t fillBuffer(
+            buffer_id buffer, const OMXBuffer &omxBuf,
+            int fenceFd = -1) override;
+    status_t emptyBuffer(
+            buffer_id buffer, const OMXBuffer &omxBuf,
+            OMX_U32 flags, OMX_TICKS timestamp, int fenceFd = -1) override;
+    status_t getExtensionIndex(
+            const char *parameter_name,
+            OMX_INDEXTYPE *index) override;
+    status_t dispatchMessage(const omx_message &msg) override;
+
+    // TODO: this is temporary, will be removed when quirks move to OMX side.
+    status_t setQuirks(OMX_U32 quirks) override;
+protected:
+    ::android::IBinder* onAsBinder() override;
+};
+
+struct TWOmxNode : public IOmxNode {
+    sp<IOMXNode> mBase;
+    TWOmxNode(sp<IOMXNode> const& base);
+
+    Return<Status> freeNode() override;
+    Return<Status> sendCommand(uint32_t cmd, int32_t param) override;
+    Return<void> getParameter(
+            uint32_t index, hidl_vec<uint8_t> const& inParams,
+            getParameter_cb _hidl_cb) override;
+    Return<Status> setParameter(
+            uint32_t index, hidl_vec<uint8_t> const& params) override;
+    Return<void> getConfig(
+            uint32_t index, hidl_vec<uint8_t> const& inConfig,
+            getConfig_cb _hidl_cb) override;
+    Return<Status> setConfig(
+            uint32_t index, hidl_vec<uint8_t> const& config) override;
+    Return<Status> setPortMode(uint32_t portIndex, PortMode mode) override;
+    Return<Status> prepareForAdaptivePlayback(
+            uint32_t portIndex, bool enable,
+            uint32_t maxFrameWidth, uint32_t maxFrameHeight) override;
+    Return<void> configureVideoTunnelMode(
+            uint32_t portIndex, bool tunneled, uint32_t audioHwSync,
+            configureVideoTunnelMode_cb _hidl_cb) override;
+    Return<void> getGraphicBufferUsage(
+            uint32_t portIndex,
+            getGraphicBufferUsage_cb _hidl_cb) override;
+    Return<Status> setInputSurface(
+            sp<IOmxBufferSource> const& bufferSource) override;
+    Return<void> allocateSecureBuffer(
+            uint32_t portIndex, uint64_t size,
+            allocateSecureBuffer_cb _hidl_cb) override;
+    Return<void> useBuffer(
+            uint32_t portIndex, CodecBuffer const& codecBuffer,
+            useBuffer_cb _hidl_cb) override;
+    Return<Status> freeBuffer(uint32_t portIndex, uint32_t buffer) override;
+    Return<Status> fillBuffer(
+            uint32_t buffer, CodecBuffer const& codecBuffer,
+            const hidl_handle& fence) override;
+    Return<Status> emptyBuffer(
+            uint32_t buffer, CodecBuffer const& codecBuffer,
+            uint32_t flags, uint64_t timestampUs,
+            hidl_handle const& fence) override;
+    Return<void> getExtensionIndex(
+            hidl_string const& parameterName,
+            getExtensionIndex_cb _hidl_cb) override;
+    Return<Status> dispatchMessage(Message const& msg) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMXNODE_H
diff --git a/media/libstagefright/omx/hal/1.0/WOmxObserver.cpp b/media/libstagefright/omx/hal/1.0/WOmxObserver.cpp
new file mode 100644
index 0000000..f3ad8d3
--- /dev/null
+++ b/media/libstagefright/omx/hal/1.0/WOmxObserver.cpp
@@ -0,0 +1,59 @@
+#include "WOmxObserver.h"
+
+#include <vector>
+
+#include <cutils/native_handle.h>
+#include <frameworks/native/include/binder/Binder.h>
+
+#include "Conversion.h"
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+// LWOmxObserver
+LWOmxObserver::LWOmxObserver(sp<IOmxObserver> const& base) : mBase(base) {
+}
+
+void LWOmxObserver::onMessages(std::list<omx_message> const& lMessages) {
+    hidl_vec<Message> tMessages;
+    std::vector<native_handle_t*> handles(lMessages.size());
+    tMessages.resize(lMessages.size());
+    size_t i = 0;
+    for (auto const& message : lMessages) {
+        wrapAs(&tMessages[i], &handles[i], message);
+        ++i;
+    }
+    mBase->onMessages(tMessages);
+    for (auto& handle : handles) {
+        native_handle_delete(handle);
+    }
+}
+
+::android::IBinder* LWOmxObserver::onAsBinder() {
+    return nullptr;
+}
+
+// TWOmxObserver
+TWOmxObserver::TWOmxObserver(sp<IOMXObserver> const& base) : mBase(base) {
+}
+
+Return<void> TWOmxObserver::onMessages(const hidl_vec<Message>& tMessages) {
+    std::list<omx_message> lMessages;
+    for (size_t i = 0; i < tMessages.size(); ++i) {
+        lMessages.push_back(omx_message{});
+        wrapAs(&lMessages.back(), tMessages[i]);
+    }
+    mBase->onMessages(lMessages);
+    return Return<void>();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
diff --git a/media/libstagefright/omx/hal/1.0/WOmxObserver.h b/media/libstagefright/omx/hal/1.0/WOmxObserver.h
new file mode 100644
index 0000000..c8ab296
--- /dev/null
+++ b/media/libstagefright/omx/hal/1.0/WOmxObserver.h
@@ -0,0 +1,62 @@
+#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMXOBSERVER_H
+#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMXOBSERVER_H
+
+#include <android/hardware/media/omx/1.0/IOmxObserver.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <IOMX.h>
+#include <list>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::media::omx::V1_0::IOmxObserver;
+using ::android::hardware::media::omx::V1_0::Message;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+using ::android::IOMXObserver;
+using ::android::omx_message;
+
+/**
+ * Wrapper classes for conversion
+ * ==============================
+ *
+ * Naming convention:
+ * - LW = Legacy Wrapper --- It wraps a Treble object inside a legacy object.
+ * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
+ */
+
+struct LWOmxObserver : public IOMXObserver {
+    sp<IOmxObserver> mBase;
+    LWOmxObserver(sp<IOmxObserver> const& base);
+    void onMessages(std::list<omx_message> const& lMessages) override;
+protected:
+    ::android::IBinder* onAsBinder() override;
+};
+
+struct TWOmxObserver : public IOmxObserver {
+    sp<IOMXObserver> mBase;
+    TWOmxObserver(sp<IOMXObserver> const& base);
+    Return<void> onMessages(const hidl_vec<Message>& tMessages) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMXOBSERVER_H
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 08d94c4..ec58475 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -20,6 +20,7 @@
 
 #include "Configuration.h"
 #include <deque>
+#include <map>
 #include <stdint.h>
 #include <sys/types.h>
 #include <limits.h>
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 128eaba..ff96b86 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1308,6 +1308,24 @@
     ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
             cmdCode, mHasControl, mEffect.unsafe_get());
 
+    if (cmdCode == EFFECT_CMD_ENABLE) {
+        if (*replySize < sizeof(int)) {
+            android_errorWriteLog(0x534e4554, "32095713");
+            return BAD_VALUE;
+        }
+        *(int *)pReplyData = NO_ERROR;
+        *replySize = sizeof(int);
+        return enable();
+    } else if (cmdCode == EFFECT_CMD_DISABLE) {
+        if (*replySize < sizeof(int)) {
+            android_errorWriteLog(0x534e4554, "32095713");
+            return BAD_VALUE;
+        }
+        *(int *)pReplyData = NO_ERROR;
+        *replySize = sizeof(int);
+        return disable();
+    }
+
     AutoMutex _l(mLock);
     sp<EffectModule> effect = mEffect.promote();
     if (effect == 0 || mDisconnected) {
@@ -1323,11 +1341,17 @@
 
     // handle commands that are not forwarded transparently to effect engine
     if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
+        if (*replySize < sizeof(int)) {
+            android_errorWriteLog(0x534e4554, "32095713");
+            return BAD_VALUE;
+        }
+        *(int *)pReplyData = NO_ERROR;
+        *replySize = sizeof(int);
+
         // No need to trylock() here as this function is executed in the binder thread serving a
         // particular client process:  no risk to block the whole media server process or mixer
         // threads if we are stuck here
         Mutex::Autolock _l(mCblk->lock);
-
         // keep local copy of index in case of client corruption b/32220769
         const uint32_t clientIndex = mCblk->clientIndex;
         const uint32_t serverIndex = mCblk->serverIndex;
@@ -1390,12 +1414,6 @@
         mCblk->serverIndex = 0;
         mCblk->clientIndex = 0;
         return status;
-    } else if (cmdCode == EFFECT_CMD_ENABLE) {
-        *(int *)pReplyData = NO_ERROR;
-        return enable();
-    } else if (cmdCode == EFFECT_CMD_DISABLE) {
-        *(int *)pReplyData = NO_ERROR;
-        return disable();
     }
 
     return effect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 85d2335..a06eacf 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -508,8 +508,7 @@
         mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id),
         // mName will be set by concrete (non-virtual) subclass
         mDeathRecipient(new PMDeathRecipient(this)),
-        mSystemReady(systemReady),
-        mNotifiedBatteryStart(false)
+        mSystemReady(systemReady)
 {
     memset(&mPatch, 0, sizeof(struct audio_patch));
 }
@@ -850,10 +849,10 @@
     }
 }
 
-void AudioFlinger::ThreadBase::acquireWakeLock(int uid)
+void AudioFlinger::ThreadBase::acquireWakeLock()
 {
     Mutex::Autolock _l(mLock);
-    acquireWakeLock_l(uid);
+    acquireWakeLock_l();
 }
 
 String16 AudioFlinger::ThreadBase::getWakeLockTag()
@@ -875,37 +874,23 @@
     }
 }
 
-void AudioFlinger::ThreadBase::acquireWakeLock_l(int uid)
+void AudioFlinger::ThreadBase::acquireWakeLock_l()
 {
     getPowerManager_l();
     if (mPowerManager != 0) {
         sp<IBinder> binder = new BBinder();
-        status_t status;
-        if (uid >= 0) {
-            status = mPowerManager->acquireWakeLockWithUid(POWERMANAGER_PARTIAL_WAKE_LOCK,
-                    binder,
-                    getWakeLockTag(),
-                    String16("audioserver"),
-                    uid,
-                    true /* FIXME force oneway contrary to .aidl */);
-        } else {
-            status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
+        // Uses AID_AUDIOSERVER for wakelock.  updateWakeLockUids_l() updates with client uids.
+        status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
                     binder,
                     getWakeLockTag(),
                     String16("audioserver"),
                     true /* FIXME force oneway contrary to .aidl */);
-        }
         if (status == NO_ERROR) {
             mWakeLockToken = binder;
         }
         ALOGV("acquireWakeLock_l() %s status %d", mThreadName, status);
     }
 
-    if (!mNotifiedBatteryStart) {
-        // TODO: call this function for each track when it becomes active.
-        BatteryNotifier::getInstance().noteStartAudio(AID_AUDIOSERVER);
-        mNotifiedBatteryStart = true;
-    }
     gBoottime.acquire(mWakeLockToken);
     mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] =
             gBoottime.getBoottimeOffset();
@@ -928,12 +913,6 @@
         }
         mWakeLockToken.clear();
     }
-
-    if (mNotifiedBatteryStart) {
-        // TODO: call this function for each track when it becomes inactive.
-        BatteryNotifier::getInstance().noteStopAudio(AID_AUDIOSERVER);
-        mNotifiedBatteryStart = false;
-    }
 }
 
 void AudioFlinger::ThreadBase::getPowerManager_l() {
@@ -952,6 +931,15 @@
 
 void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector<int> &uids) {
     getPowerManager_l();
+
+#if !LOG_NDEBUG
+    std::stringstream s;
+    for (int uid : uids) {
+        s << uid << " ";
+    }
+    ALOGD("updateWakeLockUids_l %s uids:%s", mThreadName, s.str().c_str());
+#endif
+
     if (mWakeLockToken == NULL) { // token may be NULL if AudioFlinger::systemReady() not called.
         if (mSystemReady) {
             ALOGE("no wake lock to update, but system ready!");
@@ -1534,6 +1522,73 @@
     mPendingConfigEvents.clear();
 }
 
+template <typename T>
+ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::add(const sp<T> &track) {
+    ssize_t index = mActiveTracks.indexOf(track);
+    if (index >= 0) {
+        ALOGW("ActiveTracks<T>::add track %p already there", track.get());
+        return index;
+    }
+    mActiveTracksGeneration++;
+    mLatestActiveTrack = track;
+    ++mBatteryCounter[track->uid()].second;
+    return mActiveTracks.add(track);
+}
+
+template <typename T>
+ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::remove(const sp<T> &track) {
+    ssize_t index = mActiveTracks.remove(track);
+    if (index < 0) {
+        ALOGW("ActiveTracks<T>::remove nonexistent track %p", track.get());
+        return index;
+    }
+    mActiveTracksGeneration++;
+    --mBatteryCounter[track->uid()].second;
+    // mLatestActiveTrack is not cleared even if is the same as track.
+    return index;
+}
+
+template <typename T>
+void AudioFlinger::ThreadBase::ActiveTracks<T>::clear() {
+    for (const sp<T> &track : mActiveTracks) {
+        BatteryNotifier::getInstance().noteStopAudio(track->uid());
+    }
+    mLastActiveTracksGeneration = mActiveTracksGeneration;
+    mActiveTracks.clear();
+    mLatestActiveTrack.clear();
+    mBatteryCounter.clear();
+}
+
+template <typename T>
+void AudioFlinger::ThreadBase::ActiveTracks<T>::updatePowerState(
+        sp<ThreadBase> thread, bool force) {
+    // Updates ActiveTracks client uids to the thread wakelock.
+    if (mActiveTracksGeneration != mLastActiveTracksGeneration || force) {
+        thread->updateWakeLockUids_l(getWakeLockUids());
+        mLastActiveTracksGeneration = mActiveTracksGeneration;
+    }
+
+    // Updates BatteryNotifier uids
+    for (auto it = mBatteryCounter.begin(); it != mBatteryCounter.end();) {
+        const uid_t uid = it->first;
+        ssize_t &previous = it->second.first;
+        ssize_t &current = it->second.second;
+        if (current > 0) {
+            if (previous == 0) {
+                BatteryNotifier::getInstance().noteStartAudio(uid);
+            }
+            previous = current;
+            ++it;
+        } else if (current == 0) {
+            if (previous > 0) {
+                BatteryNotifier::getInstance().noteStopAudio(uid);
+            }
+            it = mBatteryCounter.erase(it); // std::map<> is stable on iterator erase.
+        } else /* (current < 0) */ {
+            LOG_ALWAYS_FATAL("negative battery count %zd", current);
+        }
+    }
+}
 
 // ----------------------------------------------------------------------------
 //      Playback
@@ -1560,7 +1615,6 @@
         mSuspended(0), mBytesWritten(0),
         mFramesWritten(0),
         mSuspendedFrames(0),
-        mActiveTracksGeneration(0),
         // mStreamTypes[] initialized in constructor body
         mOutput(output),
         mLastWriteTime(-1), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
@@ -1680,8 +1734,8 @@
         result.append(buffer);
         Track::appendDumpHeader(result);
         for (size_t i = 0; i < numactive; ++i) {
-            sp<Track> track = mActiveTracks[i].promote();
-            if (track != 0 && mTracks.indexOf(track) < 0) {
+            sp<Track> track = mActiveTracks[i];
+            if (mTracks.indexOf(track) < 0) {
                 track->dump(buffer, SIZE, true);
                 result.append(buffer);
             }
@@ -2085,9 +2139,6 @@
         track->mResetDone = false;
         track->mPresentationCompleteFrames = 0;
         mActiveTracks.add(track);
-        mWakeLockUids.add(track->uid());
-        mActiveTracksGeneration++;
-        mLatestActiveTrack = track;
         sp<EffectChain> chain = getEffectChain_l(track->sessionId());
         if (chain != 0) {
             ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(),
@@ -2639,6 +2690,11 @@
             sp<Track> track = mTracks[i];
             track->invalidate();
         }
+        // Clear ActiveTracks to update BatteryNotifier in case active tracks remain.
+        // After we exit there are no more track changes sent to BatteryNotifier
+        // because that requires an active threadLoop.
+        // TODO: should we decActiveTrackCnt() of the cleared track effect chain?
+        mActiveTracks.clear();
     }
 }
 
@@ -2731,11 +2787,7 @@
         }
 
         // indicate all active tracks in the chain
-        for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
-            sp<Track> track = mActiveTracks[i].promote();
-            if (track == 0) {
-                continue;
-            }
+        for (const sp<Track> &track : mActiveTracks) {
             if (session == track->sessionId()) {
                 ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
                 chain->incActiveTrackCnt();
@@ -2782,11 +2834,7 @@
         if (chain == mEffectChains[i]) {
             mEffectChains.removeAt(i);
             // detach all active tracks from the chain
-            for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
-                sp<Track> track = mActiveTracks[i].promote();
-                if (track == 0) {
-                    continue;
-                }
+            for (const sp<Track> &track : mActiveTracks) {
                 if (session == track->sessionId()) {
                     ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
                             chain.get(), session);
@@ -2863,8 +2911,6 @@
     // FIXME could this be made local to while loop?
     writeFrames = 0;
 
-    int lastGeneration = 0;
-
     cacheParameters_l();
     mSleepTimeUs = mIdleSleepTimeUs;
 
@@ -2962,10 +3008,9 @@
                     mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = mLastWriteTime == -1
                             ? systemTime() : mLastWriteTime;
                 }
-                const size_t size = mActiveTracks.size();
-                for (size_t i = 0; i < size; ++i) {
-                    sp<Track> t = mActiveTracks[i].promote();
-                    if (t != 0 && !t->isFastTrack()) {
+
+                for (const sp<Track> &t : mActiveTracks) {
+                    if (!t->isFastTrack()) {
                         t->updateTrackFrameInfo(
                                 t->mAudioTrackServerProxy->framesReleased(),
                                 mFramesWritten,
@@ -2986,8 +3031,6 @@
                 if (!keepWakeLock()) {
                     releaseWakeLock_l();
                     released = true;
-                    mWakeLockUids.clear();
-                    mActiveTracksGeneration++;
                 }
                 ALOGV("wait async completion");
                 mWaitWorkCV.wait(mLock);
@@ -3021,8 +3064,6 @@
                     }
 
                     releaseWakeLock_l();
-                    mWakeLockUids.clear();
-                    mActiveTracksGeneration++;
                     // wait until we have something to do...
                     ALOGV("%s going to sleep", myName.string());
                     mWaitWorkCV.wait(mLock);
@@ -3047,12 +3088,7 @@
             // mMixerStatusIgnoringFastTracks is also updated internally
             mMixerStatus = prepareTracks_l(&tracksToRemove);
 
-            // compare with previously applied list
-            if (lastGeneration != mActiveTracksGeneration) {
-                // update wakelock
-                updateWakeLockUids_l(mWakeLockUids);
-                lastGeneration = mActiveTracksGeneration;
-            }
+            mActiveTracks.updatePowerState(this);
 
             // prevent any changes in effect chain list and in each effect chain
             // during mixing and effect process as the audio buffers could be deleted
@@ -3270,8 +3306,6 @@
     }
 
     releaseWakeLock();
-    mWakeLockUids.clear();
-    mActiveTracksGeneration++;
 
     ALOGV("Thread %p type %d exiting", this, mType);
     return false;
@@ -3285,8 +3319,6 @@
         for (size_t i=0 ; i<count ; i++) {
             const sp<Track>& track = tracksToRemove.itemAt(i);
             mActiveTracks.remove(track);
-            mWakeLockUids.remove(track->uid());
-            mActiveTracksGeneration++;
             ALOGV("removeTracks_l removing track on session %d", track->sessionId());
             sp<EffectChain> chain = getEffectChain_l(track->sessionId());
             if (chain != 0) {
@@ -3918,10 +3950,7 @@
     mEffectBufferValid = false; // mEffectBuffer has no valid data until tracks found.
 
     for (size_t i=0 ; i<count ; i++) {
-        const sp<Track> t = mActiveTracks[i].promote();
-        if (t == 0) {
-            continue;
-        }
+        const sp<Track> t = mActiveTracks[i];
 
         // this const just means the local variable doesn't change
         Track* const track = t.get();
@@ -4417,11 +4446,7 @@
         size_t i = __builtin_ctz(resetMask);
         ALOG_ASSERT(i < count);
         resetMask &= ~(1 << i);
-        sp<Track> t = mActiveTracks[i].promote();
-        if (t == 0) {
-            continue;
-        }
-        Track* track = t.get();
+        sp<Track> track = mActiveTracks[i];
         ALOG_ASSERT(track->isFastTrack() && track->isStopped());
         track->reset();
     }
@@ -4731,7 +4756,7 @@
 void AudioFlinger::DirectOutputThread::onAddNewTrack_l()
 {
     sp<Track> previousTrack = mPreviousTrack.promote();
-    sp<Track> latestTrack = mLatestActiveTrack.promote();
+    sp<Track> latestTrack = mActiveTracks.getLatest();
 
     if (previousTrack != 0 && latestTrack != 0) {
         if (mType == DIRECT) {
@@ -4757,13 +4782,7 @@
     bool doHwResume = false;
 
     // find out which tracks need to be processed
-    for (size_t i = 0; i < count; i++) {
-        sp<Track> t = mActiveTracks[i].promote();
-        // The track died recently
-        if (t == 0) {
-            continue;
-        }
-
+    for (const sp<Track> &t : mActiveTracks) {
         if (t->isInvalid()) {
             ALOGW("An invalidated track shouldn't be in active list");
             tracksToRemove->add(t);
@@ -4778,7 +4797,7 @@
         // In theory an older track could underrun and restart after the new one starts
         // but as we only care about the transition phase between two tracks on a
         // direct output, it is not a problem to ignore the underrun case.
-        sp<Track> l = mLatestActiveTrack.promote();
+        sp<Track> l = mActiveTracks.getLatest();
         bool last = l.get() == track;
 
         if (track->isPausing()) {
@@ -5312,12 +5331,7 @@
     ALOGV("OffloadThread::prepareTracks_l active tracks %zu", count);
 
     // find out which tracks need to be processed
-    for (size_t i = 0; i < count; i++) {
-        sp<Track> t = mActiveTracks[i].promote();
-        // The track died recently
-        if (t == 0) {
-            continue;
-        }
+    for (const sp<Track> &t : mActiveTracks) {
         Track* const track = t.get();
 #ifdef VERY_VERY_VERBOSE_LOGGING
         audio_track_cblk_t* cblk = track->cblk();
@@ -5326,7 +5340,7 @@
         // In theory an older track could underrun and restart after the new one starts
         // but as we only care about the transition phase between two tracks on a
         // direct output, it is not a problem to ignore the underrun case.
-        sp<Track> l = mLatestActiveTrack.promote();
+        sp<Track> l = mActiveTracks.getLatest();
         bool last = l.get() == track;
 
         if (track->isInvalid()) {
@@ -5785,7 +5799,7 @@
 #endif
                                          ) :
     ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady),
-    mInput(input), mActiveTracksGen(0), mRsmpInBuffer(NULL),
+    mInput(input), mRsmpInBuffer(NULL),
     // mRsmpInFrames, mRsmpInFramesP2, and mRsmpInFramesOA are set by readInputParameters_l()
     mRsmpInRear(0)
 #ifdef TEE_SINK
@@ -5943,25 +5957,9 @@
 
 reacquire_wakelock:
     sp<RecordTrack> activeTrack;
-    int activeTracksGen;
     {
         Mutex::Autolock _l(mLock);
-        size_t size = mActiveTracks.size();
-        activeTracksGen = mActiveTracksGen;
-        if (size > 0) {
-            // FIXME an arbitrary choice
-            activeTrack = mActiveTracks[0];
-            acquireWakeLock_l(activeTrack->uid());
-            if (size > 1) {
-                SortedVector<int> tmp;
-                for (size_t i = 0; i < size; i++) {
-                    tmp.add(mActiveTracks[i]->uid());
-                }
-                updateWakeLockUids_l(tmp);
-            }
-        } else {
-            acquireWakeLock_l(-1);
-        }
+        acquireWakeLock_l();
     }
 
     // used to request a deferred sleep, to be executed later while mutex is unlocked
@@ -6013,15 +6011,6 @@
                 goto reacquire_wakelock;
             }
 
-            if (mActiveTracksGen != activeTracksGen) {
-                activeTracksGen = mActiveTracksGen;
-                SortedVector<int> tmp;
-                for (size_t i = 0; i < size; i++) {
-                    tmp.add(mActiveTracks[i]->uid());
-                }
-                updateWakeLockUids_l(tmp);
-            }
-
             bool doBroadcast = false;
             bool allStopped = true;
             for (size_t i = 0; i < size; ) {
@@ -6034,7 +6023,6 @@
                     }
                     removeTrack_l(activeTrack);
                     mActiveTracks.remove(activeTrack);
-                    mActiveTracksGen++;
                     size--;
                     continue;
                 }
@@ -6044,7 +6032,6 @@
 
                 case TrackBase::PAUSING:
                     mActiveTracks.remove(activeTrack);
-                    mActiveTracksGen++;
                     doBroadcast = true;
                     size--;
                     continue;
@@ -6084,6 +6071,8 @@
                 }
             }
 
+            mActiveTracks.updatePowerState(this);
+
             if (allStopped) {
                 standbyIfNotAlreadyInStandby();
             }
@@ -6382,7 +6371,6 @@
             track->invalidate();
         }
         mActiveTracks.clear();
-        mActiveTracksGen++;
         mStartStopCond.broadcast();
     }
 
@@ -6637,7 +6625,6 @@
         //      or using a separate command thread
         recordTrack->mState = TrackBase::STARTING_1;
         mActiveTracks.add(recordTrack);
-        mActiveTracksGen++;
         status_t status = NO_ERROR;
         if (recordTrack->isExternalTrack()) {
             mLock.unlock();
@@ -6646,7 +6633,6 @@
             // FIXME should verify that recordTrack is still in mActiveTracks
             if (status != NO_ERROR) {
                 mActiveTracks.remove(recordTrack);
-                mActiveTracksGen++;
                 recordTrack->clearSyncStartEvent();
                 ALOGV("RecordThread::start error %d", status);
                 return status;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 4eafc38..547cfd1 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -403,8 +403,8 @@
                     effect_uuid_t mType;    // effect type UUID
                 };
 
-                void        acquireWakeLock(int uid = -1);
-                virtual void acquireWakeLock_l(int uid = -1);
+                void        acquireWakeLock();
+                virtual void acquireWakeLock_l();
                 void        releaseWakeLock();
                 void        releaseWakeLock_l();
                 void        updateWakeLockUids_l(const SortedVector<int> &uids);
@@ -481,8 +481,92 @@
                 static const size_t     kLogSize = 4 * 1024;
                 sp<NBLog::Writer>       mNBLogWriter;
                 bool                    mSystemReady;
-                bool                    mNotifiedBatteryStart;
                 ExtendedTimestamp       mTimestamp;
+
+                // ActiveTracks is a sorted vector of track type T representing the
+                // active tracks of threadLoop() to be considered by the locked prepare portion.
+                // ActiveTracks should be accessed with the ThreadBase lock held.
+                //
+                // During processing and I/O, the threadLoop does not hold the lock;
+                // hence it does not directly use ActiveTracks.  Care should be taken
+                // to hold local strong references or defer removal of tracks
+                // if the threadLoop may still be accessing those tracks due to mix, etc.
+                //
+                // This class updates power information appropriately.
+                //
+
+                template <typename T>
+                class ActiveTracks {
+                public:
+                    ActiveTracks()
+                        : mActiveTracksGeneration(0)
+                        , mLastActiveTracksGeneration(0)
+                    { }
+
+                    ~ActiveTracks() {
+                        ALOGW_IF(!mActiveTracks.isEmpty(),
+                                "ActiveTracks should be empty in destructor");
+                    }
+                    // returns the last track added (even though it may have been
+                    // subsequently removed from ActiveTracks).
+                    //
+                    // Used for DirectOutputThread to ensure a flush is called when transitioning
+                    // to a new track (even though it may be on the same session).
+                    // Used for OffloadThread to ensure that volume and mixer state is
+                    // taken from the latest track added.
+                    //
+                    // The latest track is saved with a weak pointer to prevent keeping an
+                    // otherwise useless track alive. Thus the function will return nullptr
+                    // if the latest track has subsequently been removed and destroyed.
+                    sp<T> getLatest() {
+                        return mLatestActiveTrack.promote();
+                    }
+
+                    // SortedVector methods
+                    ssize_t         add(const sp<T> &track);
+                    ssize_t         remove(const sp<T> &track);
+                    size_t          size() const {
+                        return mActiveTracks.size();
+                    }
+                    ssize_t         indexOf(const sp<T>& item) {
+                        return mActiveTracks.indexOf(item);
+                    }
+                    sp<T>           operator[](size_t index) const {
+                        return mActiveTracks[index];
+                    }
+                    typename SortedVector<sp<T>>::iterator begin() {
+                        return mActiveTracks.begin();
+                    }
+                    typename SortedVector<sp<T>>::iterator end() {
+                        return mActiveTracks.end();
+                    }
+
+                    // Due to Binder recursion optimization, clear() and updatePowerState()
+                    // cannot be called from a Binder thread because they may call back into
+                    // the original calling process (system server) for BatteryNotifier
+                    // (which requires a Java environment that may not be present).
+                    // Hence, call clear() and updatePowerState() only from the
+                    // ThreadBase thread.
+                    void            clear();
+                    // periodically called in the threadLoop() to update power state uids.
+                    void            updatePowerState(sp<ThreadBase> thread, bool force = false);
+
+                private:
+                    SortedVector<int> getWakeLockUids() {
+                        SortedVector<int> wakeLockUids;
+                        for (const sp<T> &track : mActiveTracks) {
+                            wakeLockUids.add(track->uid());
+                        }
+                        return wakeLockUids; // moved by underlying SharedBuffer
+                    }
+
+                    std::map<uid_t, std::pair<ssize_t /* previous */, ssize_t /* current */>>
+                                        mBatteryCounter;
+                    SortedVector<sp<T>> mActiveTracks;
+                    int                 mActiveTracksGeneration;
+                    int                 mLastActiveTracksGeneration;
+                    wp<T>               mLatestActiveTrack; // latest track added to ActiveTracks
+                };
 };
 
 // --- PlaybackThread ---
@@ -561,6 +645,10 @@
     virtual     void        preExit();
 
     virtual     bool        keepWakeLock() const { return true; }
+    virtual     void        acquireWakeLock_l() {
+                                ThreadBase::acquireWakeLock_l();
+                                mActiveTracks.updatePowerState(this, true /* force */);
+                            }
 
 public:
 
@@ -734,10 +822,7 @@
     bool                            mMasterMute;
                 void        setMasterMute_l(bool muted) { mMasterMute = muted; }
 protected:
-    SortedVector< wp<Track> >       mActiveTracks;  // FIXME check if this could be sp<>
-    SortedVector<int>               mWakeLockUids;
-    int                             mActiveTracksGeneration;
-    wp<Track>                       mLatestActiveTrack; // latest track added to mActiveTracks
+    ActiveTracks<Track>     mActiveTracks;
 
     // Allocate a track name for a given channel mask.
     //   Returns name >= 0 if successful, -1 on failure.
@@ -975,8 +1060,8 @@
     virtual     uint32_t    suspendSleepTimeUs() const;
     virtual     void        cacheParameters_l();
 
-    virtual void acquireWakeLock_l(int uid = -1) {
-        PlaybackThread::acquireWakeLock_l(uid);
+    virtual void acquireWakeLock_l() {
+        PlaybackThread::acquireWakeLock_l();
         if (hasFastMixer()) {
             mFastMixer->setBoottimeOffset(
                     mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME]);
@@ -1416,6 +1501,11 @@
     virtual status_t    checkEffectCompatibility_l(const effect_descriptor_t *desc,
                                                    audio_session_t sessionId);
 
+    virtual void        acquireWakeLock_l() {
+                            ThreadBase::acquireWakeLock_l();
+                            mActiveTracks.updatePowerState(this, true /* force */);
+                        }
+
 private:
             // Enter standby if not already in standby, and set mStandby flag
             void    standbyIfNotAlreadyInStandby();
@@ -1427,9 +1517,8 @@
             SortedVector < sp<RecordTrack> >    mTracks;
             // mActiveTracks has dual roles:  it indicates the current active track(s), and
             // is used together with mStartStopCond to indicate start()/stop() progress
-            SortedVector< sp<RecordTrack> >     mActiveTracks;
-            // generation counter for mActiveTracks
-            int                                 mActiveTracksGen;
+            ActiveTracks<RecordTrack>           mActiveTracks;
+
             Condition                           mStartStopCond;
 
             // resampler converts input at HAL Hz to output at AudioRecord client Hz
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index a1420ff..7cd2b81 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -79,9 +79,7 @@
 LOCAL_SHARED_LIBRARIES += libmedia_helper
 
 ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
-LOCAL_STATIC_LIBRARIES += libxml2
-
-LOCAL_SHARED_LIBRARIES += libicuuc
+LOCAL_SHARED_LIBRARIES += libicuuc libxml2
 
 LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
 endif #ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
index 02118c4..7968103 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.mk
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -41,9 +41,7 @@
 
 LOCAL_SRC_FILES += src/Serializer.cpp
 
-LOCAL_STATIC_LIBRARIES += libxml2
-
-LOCAL_SHARED_LIBRARIES += libicuuc
+LOCAL_SHARED_LIBRARIES += libicuuc libxml2
 
 LOCAL_C_INCLUDES += \
     $(TOPDIR)external/libxml2/include \
diff --git a/services/audiopolicy/engineconfigurable/Android.mk b/services/audiopolicy/engineconfigurable/Android.mk
index 341357c..5b43347 100644
--- a/services/audiopolicy/engineconfigurable/Android.mk
+++ b/services/audiopolicy/engineconfigurable/Android.mk
@@ -42,8 +42,7 @@
 
 LOCAL_STATIC_LIBRARIES := \
     libaudiopolicypfwwrapper \
-    libaudiopolicycomponents \
-    libxml2
+    libaudiopolicycomponents
 
 LOCAL_SHARED_LIBRARIES := \
     liblog \
@@ -52,7 +51,8 @@
     liblog \
     libaudioutils \
     libparameter \
-    libmedia_helper
+    libmedia_helper \
+    libxml2
 
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
index 8d51293..9b0442e 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
@@ -48,7 +48,7 @@
 
     virtual void info(const string &log)
     {
-        ALOGD("policy-parameter-manager: %s", log.c_str());
+        ALOGV("policy-parameter-manager: %s", log.c_str());
     }
     virtual void warning(const string &log)
     {
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
index 47dc545..b37b379 100644
--- a/services/audiopolicy/enginedefault/Android.mk
+++ b/services/audiopolicy/enginedefault/Android.mk
@@ -36,7 +36,6 @@
 
 LOCAL_STATIC_LIBRARIES := \
     libaudiopolicycomponents \
-    libxml2
 
 LOCAL_SHARED_LIBRARIES += \
     liblog \