Use tokens for IOmxNode.

Test: Mirroring, Camera, Photos, YouTube and Play Movies apps.
Bug: 35442034
Change-Id: I0e43ec57d0f37c71d41652fd9883b72650433e20
diff --git a/media/libmedia/omx/1.0/WGraphicBufferSource.cpp b/media/libmedia/omx/1.0/WGraphicBufferSource.cpp
new file mode 100644
index 0000000..247c540
--- /dev/null
+++ b/media/libmedia/omx/1.0/WGraphicBufferSource.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stagefright/foundation/ColorUtils.h>
+
+#include <media/omx/1.0/WGraphicBufferSource.h>
+#include <media/omx/1.0/WOmxNode.h>
+#include <media/omx/1.0/Conversion.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace utils {
+
+using android::ColorUtils;
+
+// LWGraphicBufferSource
+LWGraphicBufferSource::LWGraphicBufferSource(
+        sp<TGraphicBufferSource> const& base) : mBase(base) {
+}
+
+::android::binder::Status LWGraphicBufferSource::configure(
+        const sp<IOMXNode>& omxNode, int32_t dataSpace) {
+    sp<IOmxNode> hOmxNode = omxNode->getHalInterface();
+    return toBinderStatus(mBase->configure(
+            hOmxNode == nullptr ? new TWOmxNode(omxNode) : hOmxNode,
+            toHardwareDataspace(dataSpace)));
+}
+
+::android::binder::Status LWGraphicBufferSource::setSuspend(
+        bool suspend, int64_t timeUs) {
+    return toBinderStatus(mBase->setSuspend(suspend, timeUs));
+}
+
+::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::setStopTimeUs(
+        int64_t stopTimeUs) {
+    return toBinderStatus(mBase->setStopTimeUs(stopTimeUs));
+}
+
+::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());
+}
+
+// TWGraphicBufferSource
+TWGraphicBufferSource::TWGraphicBufferSource(
+        sp<LGraphicBufferSource> const& base) : mBase(base) {
+}
+
+Return<void> TWGraphicBufferSource::configure(
+        const sp<IOmxNode>& omxNode, Dataspace dataspace) {
+    mBase->configure(new LWOmxNode(omxNode), toRawDataspace(dataspace));
+    return Void();
+}
+
+Return<void> TWGraphicBufferSource::setSuspend(
+        bool suspend, int64_t timeUs) {
+    mBase->setSuspend(suspend, timeUs);
+    return Void();
+}
+
+Return<void> TWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
+        int64_t repeatAfterUs) {
+    mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs);
+    return Void();
+}
+
+Return<void> TWGraphicBufferSource::setMaxFps(float maxFps) {
+    mBase->setMaxFps(maxFps);
+    return Void();
+}
+
+Return<void> TWGraphicBufferSource::setTimeLapseConfig(
+        int64_t timePerFrameUs, int64_t timePerCaptureUs) {
+    mBase->setTimeLapseConfig(timePerFrameUs, timePerCaptureUs);
+    return Void();
+}
+
+Return<void> TWGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
+    mBase->setStartTimeUs(startTimeUs);
+    return Void();
+}
+
+Return<void> TWGraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
+    mBase->setStopTimeUs(stopTimeUs);
+    return Void();
+}
+
+Return<void> TWGraphicBufferSource::setColorAspects(
+        const ColorAspects& aspects) {
+    mBase->setColorAspects(toCompactColorAspects(aspects));
+    return Void();
+}
+
+Return<void> TWGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
+    mBase->setTimeOffsetUs(timeOffsetUs);
+    return Void();
+}
+
+Return<void> TWGraphicBufferSource::signalEndOfInputStream() {
+    mBase->signalEndOfInputStream();
+    return Void();
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
diff --git a/media/libmedia/omx/1.0/WOmx.cpp b/media/libmedia/omx/1.0/WOmx.cpp
new file mode 100644
index 0000000..39871f8
--- /dev/null
+++ b/media/libmedia/omx/1.0/WOmx.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/omx/1.0/WOmx.h>
+#include <media/omx/1.0/WOmxNode.h>
+#include <media/omx/1.0/WOmxObserver.h>
+#include <media/omx/1.0/WOmxBufferProducer.h>
+#include <media/omx/1.0/WGraphicBufferSource.h>
+#include <media/omx/1.0/Conversion.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace utils {
+
+// 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) {
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->createInputSurface(
+            [&fnStatus, bufferProducer, bufferSource] (
+                    Status status,
+                    sp<IOmxBufferProducer> const& tProducer,
+                    sp<IGraphicBufferSource> const& tSource) {
+                fnStatus = toStatusT(status);
+                *bufferProducer = new LWOmxBufferProducer(tProducer);
+                *bufferSource = new LWGraphicBufferSource(tSource);
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+// 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();
+}
+
+Return<void> TWOmx::createInputSurface(createInputSurface_cb _hidl_cb) {
+    sp<::android::IGraphicBufferProducer> lProducer;
+    sp<::android::IGraphicBufferSource> lSource;
+    status_t status = mBase->createInputSurface(&lProducer, &lSource);
+    _hidl_cb(toStatus(status),
+             new TWOmxBufferProducer(lProducer),
+             new TWGraphicBufferSource(lSource));
+    return Void();
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
diff --git a/media/libmedia/omx/1.0/WOmxBufferProducer.cpp b/media/libmedia/omx/1.0/WOmxBufferProducer.cpp
new file mode 100644
index 0000000..03499f2
--- /dev/null
+++ b/media/libmedia/omx/1.0/WOmxBufferProducer.cpp
@@ -0,0 +1,610 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "WOmxBufferProducer-utils"
+
+#include <utils/Log.h>
+
+#include <media/omx/1.0/WOmxBufferProducer.h>
+#include <media/omx/1.0/WOmxProducerListener.h>
+#include <media/omx/1.0/Conversion.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace utils {
+
+// TWOmxBufferProducer
+TWOmxBufferProducer::TWOmxBufferProducer(
+        sp<IGraphicBufferProducer> const& base):
+    mBase(base) {
+}
+
+Return<void> TWOmxBufferProducer::requestBuffer(
+        int32_t slot, requestBuffer_cb _hidl_cb) {
+    sp<GraphicBuffer> buf;
+    status_t status = mBase->requestBuffer(slot, &buf);
+    AnwBuffer anwBuffer;
+    wrapAs(&anwBuffer, *buf);
+    _hidl_cb(toStatus(status), anwBuffer);
+    return Void();
+}
+
+Return<Status> TWOmxBufferProducer::setMaxDequeuedBufferCount(
+        int32_t maxDequeuedBuffers) {
+    return toStatus(mBase->setMaxDequeuedBufferCount(
+            static_cast<int>(maxDequeuedBuffers)));
+}
+
+Return<Status> TWOmxBufferProducer::setAsyncMode(bool async) {
+    return toStatus(mBase->setAsyncMode(async));
+}
+
+Return<void> TWOmxBufferProducer::dequeueBuffer(
+        uint32_t width, uint32_t height,
+        PixelFormat format, uint32_t usage,
+        bool getFrameTimestamps, dequeueBuffer_cb _hidl_cb) {
+    int slot;
+    sp<Fence> fence;
+    ::android::FrameEventHistoryDelta outTimestamps;
+    status_t status = mBase->dequeueBuffer(
+            &slot, &fence,
+            width, height,
+            static_cast<::android::PixelFormat>(format), usage,
+            getFrameTimestamps ? &outTimestamps : nullptr);
+    hidl_handle tFence;
+    FrameEventHistoryDelta tOutTimestamps;
+
+    native_handle_t* nh = nullptr;
+    if ((fence == nullptr) || !wrapAs(&tFence, &nh, *fence)) {
+        ALOGE("TWOmxBufferProducer::dequeueBuffer - Invalid output fence");
+        _hidl_cb(toStatus(status),
+                 static_cast<int32_t>(slot),
+                 tFence,
+                 tOutTimestamps);
+        return Void();
+    }
+    std::vector<std::vector<native_handle_t*> > nhAA;
+    if (getFrameTimestamps && !wrapAs(&tOutTimestamps, &nhAA, outTimestamps)) {
+        ALOGE("TWOmxBufferProducer::dequeueBuffer - Invalid output timestamps");
+        _hidl_cb(toStatus(status),
+                 static_cast<int32_t>(slot),
+                 tFence,
+                 tOutTimestamps);
+        native_handle_delete(nh);
+        return Void();
+    }
+
+    _hidl_cb(toStatus(status),
+            static_cast<int32_t>(slot),
+            tFence,
+            tOutTimestamps);
+    native_handle_delete(nh);
+    if (getFrameTimestamps) {
+        for (auto& nhA : nhAA) {
+            for (auto& handle : nhA) {
+                native_handle_delete(handle);
+            }
+        }
+    }
+    return Void();
+}
+
+Return<Status> TWOmxBufferProducer::detachBuffer(int32_t slot) {
+    return toStatus(mBase->detachBuffer(slot));
+}
+
+Return<void> TWOmxBufferProducer::detachNextBuffer(
+        detachNextBuffer_cb _hidl_cb) {
+    sp<GraphicBuffer> outBuffer;
+    sp<Fence> outFence;
+    status_t status = mBase->detachNextBuffer(&outBuffer, &outFence);
+    AnwBuffer tBuffer;
+    hidl_handle tFence;
+
+    if (outBuffer == nullptr) {
+        ALOGE("TWOmxBufferProducer::detachNextBuffer - Invalid output buffer");
+        _hidl_cb(toStatus(status), tBuffer, tFence);
+        return Void();
+    }
+    wrapAs(&tBuffer, *outBuffer);
+    native_handle_t* nh = nullptr;
+    if ((outFence != nullptr) && !wrapAs(&tFence, &nh, *outFence)) {
+        ALOGE("TWOmxBufferProducer::detachNextBuffer - Invalid output fence");
+        _hidl_cb(toStatus(status), tBuffer, tFence);
+        return Void();
+    }
+
+    _hidl_cb(toStatus(status), tBuffer, tFence);
+    native_handle_delete(nh);
+    return Void();
+}
+
+Return<void> TWOmxBufferProducer::attachBuffer(
+        const AnwBuffer& buffer,
+        attachBuffer_cb _hidl_cb) {
+    int outSlot;
+    sp<GraphicBuffer> lBuffer = new GraphicBuffer();
+    if (!convertTo(lBuffer.get(), buffer)) {
+        ALOGE("TWOmxBufferProducer::attachBuffer - "
+                "Invalid input native window buffer");
+        _hidl_cb(toStatus(BAD_VALUE), -1);
+        return Void();
+    }
+    status_t status = mBase->attachBuffer(&outSlot, lBuffer);
+
+    _hidl_cb(toStatus(status), static_cast<int32_t>(outSlot));
+    return Void();
+}
+
+Return<void> TWOmxBufferProducer::queueBuffer(
+        int32_t slot, const QueueBufferInput& input,
+        queueBuffer_cb _hidl_cb) {
+    QueueBufferOutput tOutput;
+    IGraphicBufferProducer::QueueBufferInput lInput(
+            0, false, HAL_DATASPACE_UNKNOWN,
+            ::android::Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE,
+            0, ::android::Fence::NO_FENCE);
+    if (!convertTo(&lInput, input)) {
+        ALOGE("TWOmxBufferProducer::queueBuffer - Invalid input");
+        _hidl_cb(toStatus(BAD_VALUE), tOutput);
+        return Void();
+    }
+    IGraphicBufferProducer::QueueBufferOutput lOutput;
+    status_t status = mBase->queueBuffer(
+            static_cast<int>(slot), lInput, &lOutput);
+
+    std::vector<std::vector<native_handle_t*> > nhAA;
+    if (!wrapAs(&tOutput, &nhAA, lOutput)) {
+        ALOGE("TWOmxBufferProducer::queueBuffer - Invalid output");
+        _hidl_cb(toStatus(BAD_VALUE), tOutput);
+        return Void();
+    }
+
+    _hidl_cb(toStatus(status), tOutput);
+    for (auto& nhA : nhAA) {
+        for (auto& nh : nhA) {
+            native_handle_delete(nh);
+        }
+    }
+    return Void();
+}
+
+Return<Status> TWOmxBufferProducer::cancelBuffer(
+        int32_t slot, const hidl_handle& fence) {
+    sp<Fence> lFence = new Fence();
+    if (!convertTo(lFence.get(), fence)) {
+        ALOGE("TWOmxBufferProducer::cancelBuffer - Invalid input fence");
+        return toStatus(BAD_VALUE);
+    }
+    return toStatus(mBase->cancelBuffer(static_cast<int>(slot), lFence));
+}
+
+Return<void> TWOmxBufferProducer::query(int32_t what, query_cb _hidl_cb) {
+    int lValue;
+    int lReturn = mBase->query(static_cast<int>(what), &lValue);
+    _hidl_cb(static_cast<int32_t>(lReturn), static_cast<int32_t>(lValue));
+    return Void();
+}
+
+Return<void> TWOmxBufferProducer::connect(
+        const sp<IOmxProducerListener>& listener,
+        int32_t api, bool producerControlledByApp, connect_cb _hidl_cb) {
+    sp<IProducerListener> lListener = listener == nullptr ?
+            nullptr : new LWOmxProducerListener(listener);
+    IGraphicBufferProducer::QueueBufferOutput lOutput;
+    status_t status = mBase->connect(lListener,
+            static_cast<int>(api),
+            producerControlledByApp,
+            &lOutput);
+
+    QueueBufferOutput tOutput;
+    std::vector<std::vector<native_handle_t*> > nhAA;
+    if (!wrapAs(&tOutput, &nhAA, lOutput)) {
+        ALOGE("TWOmxBufferProducer::connect - Invalid output");
+        _hidl_cb(toStatus(status), tOutput);
+        return Void();
+    }
+
+    _hidl_cb(toStatus(status), tOutput);
+    for (auto& nhA : nhAA) {
+        for (auto& nh : nhA) {
+            native_handle_delete(nh);
+        }
+    }
+    return Void();
+}
+
+Return<Status> TWOmxBufferProducer::disconnect(
+        int32_t api, DisconnectMode mode) {
+    return toStatus(mBase->disconnect(
+            static_cast<int>(api),
+            toGuiDisconnectMode(mode)));
+}
+
+Return<Status> TWOmxBufferProducer::setSidebandStream(const hidl_handle& stream) {
+    return toStatus(mBase->setSidebandStream(NativeHandle::create(
+            native_handle_clone(stream), true)));
+}
+
+Return<void> TWOmxBufferProducer::allocateBuffers(
+        uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) {
+    mBase->allocateBuffers(
+            width, height,
+            static_cast<::android::PixelFormat>(format),
+            usage);
+    return Void();
+}
+
+Return<Status> TWOmxBufferProducer::allowAllocation(bool allow) {
+    return toStatus(mBase->allowAllocation(allow));
+}
+
+Return<Status> TWOmxBufferProducer::setGenerationNumber(uint32_t generationNumber) {
+    return toStatus(mBase->setGenerationNumber(generationNumber));
+}
+
+Return<void> TWOmxBufferProducer::getConsumerName(getConsumerName_cb _hidl_cb) {
+    _hidl_cb(mBase->getConsumerName().string());
+    return Void();
+}
+
+Return<Status> TWOmxBufferProducer::setSharedBufferMode(bool sharedBufferMode) {
+    return toStatus(mBase->setSharedBufferMode(sharedBufferMode));
+}
+
+Return<Status> TWOmxBufferProducer::setAutoRefresh(bool autoRefresh) {
+    return toStatus(mBase->setAutoRefresh(autoRefresh));
+}
+
+Return<Status> TWOmxBufferProducer::setDequeueTimeout(int64_t timeoutNs) {
+    return toStatus(mBase->setDequeueTimeout(timeoutNs));
+}
+
+Return<void> TWOmxBufferProducer::getLastQueuedBuffer(
+        getLastQueuedBuffer_cb _hidl_cb) {
+    sp<GraphicBuffer> lOutBuffer = new GraphicBuffer();
+    sp<Fence> lOutFence = new Fence();
+    float lOutTransformMatrix[16];
+    status_t status = mBase->getLastQueuedBuffer(
+            &lOutBuffer, &lOutFence, lOutTransformMatrix);
+
+    AnwBuffer tOutBuffer;
+    if (lOutBuffer != nullptr) {
+        wrapAs(&tOutBuffer, *lOutBuffer);
+    }
+    hidl_handle tOutFence;
+    native_handle_t* nh = nullptr;
+    if ((lOutFence == nullptr) || !wrapAs(&tOutFence, &nh, *lOutFence)) {
+        ALOGE("TWOmxBufferProducer::getLastQueuedBuffer - "
+                "Invalid output fence");
+        _hidl_cb(toStatus(status),
+                tOutBuffer,
+                tOutFence,
+                hidl_array<float, 16>());
+        return Void();
+    }
+    hidl_array<float, 16> tOutTransformMatrix(lOutTransformMatrix);
+
+    _hidl_cb(toStatus(status), tOutBuffer, tOutFence, tOutTransformMatrix);
+    native_handle_delete(nh);
+    return Void();
+}
+
+Return<void> TWOmxBufferProducer::getFrameTimestamps(
+        getFrameTimestamps_cb _hidl_cb) {
+    ::android::FrameEventHistoryDelta lDelta;
+    mBase->getFrameTimestamps(&lDelta);
+
+    FrameEventHistoryDelta tDelta;
+    std::vector<std::vector<native_handle_t*> > nhAA;
+    if (!wrapAs(&tDelta, &nhAA, lDelta)) {
+        ALOGE("TWOmxBufferProducer::getFrameTimestamps - "
+                "Invalid output frame timestamps");
+        _hidl_cb(tDelta);
+        return Void();
+    }
+
+    _hidl_cb(tDelta);
+    for (auto& nhA : nhAA) {
+        for (auto& nh : nhA) {
+            native_handle_delete(nh);
+        }
+    }
+    return Void();
+}
+
+Return<void> TWOmxBufferProducer::getUniqueId(getUniqueId_cb _hidl_cb) {
+    uint64_t outId;
+    status_t status = mBase->getUniqueId(&outId);
+    _hidl_cb(toStatus(status), outId);
+    return Void();
+}
+
+// LWOmxBufferProducer
+
+LWOmxBufferProducer::LWOmxBufferProducer(sp<IOmxBufferProducer> const& base) :
+    mBase(base) {
+}
+
+status_t LWOmxBufferProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
+    *buf = new GraphicBuffer();
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->requestBuffer(
+            static_cast<int32_t>(slot),
+            [&fnStatus, &buf] (Status status, AnwBuffer const& buffer) {
+                fnStatus = toStatusT(status);
+                if (!convertTo(buf->get(), buffer)) {
+                    fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
+                }
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxBufferProducer::setMaxDequeuedBufferCount(
+        int maxDequeuedBuffers) {
+    return toStatusT(mBase->setMaxDequeuedBufferCount(
+            static_cast<int32_t>(maxDequeuedBuffers)));
+}
+
+status_t LWOmxBufferProducer::setAsyncMode(bool async) {
+    return toStatusT(mBase->setAsyncMode(async));
+}
+
+status_t LWOmxBufferProducer::dequeueBuffer(
+        int* slot, sp<Fence>* fence,
+        uint32_t w, uint32_t h, ::android::PixelFormat format,
+        uint32_t usage, FrameEventHistoryDelta* outTimestamps) {
+    *fence = new Fence();
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->dequeueBuffer(
+            w, h, static_cast<PixelFormat>(format), usage,
+            outTimestamps != nullptr,
+            [&fnStatus, slot, fence, outTimestamps] (
+                    Status status,
+                    int32_t tSlot,
+                    hidl_handle const& tFence,
+                    IOmxBufferProducer::FrameEventHistoryDelta const& tTs) {
+                fnStatus = toStatusT(status);
+                *slot = tSlot;
+                if (!convertTo(fence->get(), tFence)) {
+                    ALOGE("LWOmxBufferProducer::dequeueBuffer - "
+                            "Invalid output fence");
+                    fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
+                }
+                if (outTimestamps && !convertTo(outTimestamps, tTs)) {
+                    ALOGE("LWOmxBufferProducer::dequeueBuffer - "
+                            "Invalid output timestamps");
+                    fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
+                }
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxBufferProducer::detachBuffer(int slot) {
+    return toStatusT(mBase->detachBuffer(static_cast<int>(slot)));
+}
+
+status_t LWOmxBufferProducer::detachNextBuffer(
+        sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
+    *outBuffer = new GraphicBuffer();
+    *outFence = new Fence();
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->detachNextBuffer(
+            [&fnStatus, outBuffer, outFence] (
+                    Status status,
+                    AnwBuffer const& tBuffer,
+                    hidl_handle const& tFence) {
+                fnStatus = toStatusT(status);
+                if (!convertTo(outFence->get(), tFence)) {
+                    ALOGE("LWOmxBufferProducer::detachNextBuffer - "
+                            "Invalid output fence");
+                    fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
+                }
+                if (!convertTo(outBuffer->get(), tBuffer)) {
+                    ALOGE("LWOmxBufferProducer::detachNextBuffer - "
+                            "Invalid output buffer");
+                    fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
+                }
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxBufferProducer::attachBuffer(
+        int* outSlot, const sp<GraphicBuffer>& buffer) {
+    AnwBuffer tBuffer;
+    wrapAs(&tBuffer, *buffer);
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->attachBuffer(tBuffer,
+            [&fnStatus, outSlot] (Status status, int32_t slot) {
+                fnStatus = toStatusT(status);
+                *outSlot = slot;
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxBufferProducer::queueBuffer(
+        int slot,
+        const QueueBufferInput& input,
+        QueueBufferOutput* output) {
+    IOmxBufferProducer::QueueBufferInput tInput;
+    native_handle_t* nh;
+    if (!wrapAs(&tInput, &nh, input)) {
+        ALOGE("LWOmxBufferProducer::queueBuffer - Invalid input");
+        return BAD_VALUE;
+    }
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->queueBuffer(slot, tInput,
+            [&fnStatus, output] (
+                    Status status,
+                    IOmxBufferProducer::QueueBufferOutput const& tOutput) {
+                fnStatus = toStatusT(status);
+                if (!convertTo(output, tOutput)) {
+                    ALOGE("LWOmxBufferProducer::queueBuffer - "
+                            "Invalid output");
+                    fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
+                }
+            }));
+    native_handle_delete(nh);
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxBufferProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
+    hidl_handle tFence;
+    native_handle_t* nh = nullptr;
+    if ((fence == nullptr) || !wrapAs(&tFence, &nh, *fence)) {
+        ALOGE("LWOmxBufferProducer::cancelBuffer - Invalid input fence");
+        return BAD_VALUE;
+    }
+
+    status_t status = toStatusT(mBase->cancelBuffer(
+            static_cast<int32_t>(slot), tFence));
+    native_handle_delete(nh);
+    return status;
+}
+
+int LWOmxBufferProducer::query(int what, int* value) {
+    int result;
+    status_t transStatus = toStatusT(mBase->query(
+            static_cast<int32_t>(what),
+            [&result, value] (int32_t tResult, int32_t tValue) {
+                result = static_cast<int>(tResult);
+                *value = static_cast<int>(tValue);
+            }));
+    return transStatus == NO_ERROR ? result : static_cast<int>(transStatus);
+}
+
+status_t LWOmxBufferProducer::connect(
+        const sp<IProducerListener>& listener, int api,
+        bool producerControlledByApp, QueueBufferOutput* output) {
+    sp<IOmxProducerListener> tListener = listener == nullptr ?
+            nullptr : new TWOmxProducerListener(listener);
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->connect(
+            tListener, static_cast<int32_t>(api), producerControlledByApp,
+            [&fnStatus, output] (
+                    Status status,
+                    IOmxBufferProducer::QueueBufferOutput const& tOutput) {
+                fnStatus = toStatusT(status);
+                if (!convertTo(output, tOutput)) {
+                    ALOGE("LWOmxBufferProducer::connect - Invalid output");
+                    fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
+                }
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+status_t LWOmxBufferProducer::disconnect(int api, DisconnectMode mode) {
+    return toStatusT(mBase->disconnect(
+            static_cast<int32_t>(api), toOmxDisconnectMode(mode)));
+}
+
+status_t LWOmxBufferProducer::setSidebandStream(
+        const sp<NativeHandle>& stream) {
+    return toStatusT(mBase->setSidebandStream(stream->handle()));
+}
+
+void LWOmxBufferProducer::allocateBuffers(uint32_t width, uint32_t height,
+        ::android::PixelFormat format, uint32_t usage) {
+    mBase->allocateBuffers(
+            width, height, static_cast<PixelFormat>(format), usage);
+}
+
+status_t LWOmxBufferProducer::allowAllocation(bool allow) {
+    return toStatusT(mBase->allowAllocation(allow));
+}
+
+status_t LWOmxBufferProducer::setGenerationNumber(uint32_t generationNumber) {
+    return toStatusT(mBase->setGenerationNumber(generationNumber));
+}
+
+String8 LWOmxBufferProducer::getConsumerName() const {
+    String8 lName;
+    mBase->getConsumerName([&lName] (hidl_string const& name) {
+                lName = name.c_str();
+            });
+    return lName;
+}
+
+status_t LWOmxBufferProducer::setSharedBufferMode(bool sharedBufferMode) {
+    return toStatusT(mBase->setSharedBufferMode(sharedBufferMode));
+}
+
+status_t LWOmxBufferProducer::setAutoRefresh(bool autoRefresh) {
+    return toStatusT(mBase->setAutoRefresh(autoRefresh));
+}
+
+status_t LWOmxBufferProducer::setDequeueTimeout(nsecs_t timeout) {
+    return toStatusT(mBase->setDequeueTimeout(static_cast<int64_t>(timeout)));
+}
+
+status_t LWOmxBufferProducer::getLastQueuedBuffer(
+        sp<GraphicBuffer>* outBuffer,
+        sp<Fence>* outFence,
+        float outTransformMatrix[16]) {
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->getLastQueuedBuffer(
+            [&fnStatus, outBuffer, outFence, &outTransformMatrix] (
+                    Status status,
+                    AnwBuffer const& buffer,
+                    hidl_handle const& fence,
+                    hidl_array<float, 16> const& transformMatrix) {
+                fnStatus = toStatusT(status);
+                *outBuffer = new GraphicBuffer();
+                if (!convertTo(outBuffer->get(), buffer)) {
+                    ALOGE("LWOmxBufferProducer::getLastQueuedBuffer - "
+                            "Invalid output buffer");
+                    fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
+                }
+                *outFence = new Fence();
+                if (!convertTo(outFence->get(), fence)) {
+                    ALOGE("LWOmxBufferProducer::getLastQueuedBuffer - "
+                            "Invalid output fence");
+                    fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
+                }
+                std::copy(transformMatrix.data(),
+                        transformMatrix.data() + 16,
+                        outTransformMatrix);
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+void LWOmxBufferProducer::getFrameTimestamps(FrameEventHistoryDelta* outDelta) {
+    mBase->getFrameTimestamps([outDelta] (
+            IOmxBufferProducer::FrameEventHistoryDelta const& tDelta) {
+                convertTo(outDelta, tDelta);
+            });
+}
+
+status_t LWOmxBufferProducer::getUniqueId(uint64_t* outId) const {
+    status_t fnStatus;
+    status_t transStatus = toStatusT(mBase->getUniqueId(
+            [&fnStatus, outId] (Status status, uint64_t id) {
+                fnStatus = toStatusT(status);
+                *outId = id;
+            }));
+    return transStatus == NO_ERROR ? fnStatus : transStatus;
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
diff --git a/media/libmedia/omx/1.0/WOmxBufferSource.cpp b/media/libmedia/omx/1.0/WOmxBufferSource.cpp
new file mode 100644
index 0000000..7cca5bd
--- /dev/null
+++ b/media/libmedia/omx/1.0/WOmxBufferSource.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/String8.h>
+
+#include <media/omx/1.0/WOmxBufferSource.h>
+#include <media/omx/1.0/Conversion.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace utils {
+
+// 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));
+    native_handle_close(fenceNh);
+    native_handle_delete(fenceNh);
+    return status;
+}
+
+// TWOmxBufferSource
+TWOmxBufferSource::TWOmxBufferSource(sp<IOMXBufferSource> const& base) :
+    mBase(base) {
+}
+
+Return<void> TWOmxBufferSource::onOmxExecuting() {
+    mBase->onOmxExecuting();
+    return Void();
+}
+
+Return<void> TWOmxBufferSource::onOmxIdle() {
+    mBase->onOmxIdle();
+    return Void();
+}
+
+Return<void> TWOmxBufferSource::onOmxLoaded() {
+    mBase->onOmxLoaded();
+    return Void();
+}
+
+Return<void> TWOmxBufferSource::onInputBufferAdded(uint32_t buffer) {
+    mBase->onInputBufferAdded(int32_t(buffer));
+    return Void();
+}
+
+Return<void> TWOmxBufferSource::onInputBufferEmptied(
+        uint32_t buffer, hidl_handle const& fence) {
+    OMXFenceParcelable fenceParcelable;
+    if (!convertTo(&fenceParcelable, fence)) {
+        return Void();
+    }
+    mBase->onInputBufferEmptied(int32_t(buffer), fenceParcelable);
+    return Void();
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
diff --git a/media/libmedia/omx/1.0/WOmxNode.cpp b/media/libmedia/omx/1.0/WOmxNode.cpp
new file mode 100644
index 0000000..b5186b5
--- /dev/null
+++ b/media/libmedia/omx/1.0/WOmxNode.cpp
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+
+#include <media/omx/1.0/WOmxNode.h>
+#include <media/omx/1.0/WOmxBufferSource.h>
+#include <media/omx/1.0/Conversion.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace utils {
+
+using ::android::hardware::Void;
+
+// LWOmxNode
+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);
+    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 = outSidebandHandle == nullptr ?
+                        nullptr : 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_close(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_close(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_close(nh);
+    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 toStatusT(mBase->setQuirks(static_cast<uint32_t>(quirks)));;
+}
+
+// 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& inParams) {
+    hidl_vec<uint8_t> params(inParams);
+    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>& inConfig) {
+    hidl_vec<uint8_t> config(inConfig);
+    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 = nullptr;
+    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,
+            dup(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),
+            dup(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 (!convertTo(&lMsg, tMsg)) {
+        return Status::BAD_VALUE;
+    }
+    return toStatus(mBase->dispatchMessage(lMsg));
+}
+
+Return<void> TWOmxNode::setQuirks(uint32_t quirks) {
+    mBase->setQuirks(static_cast<OMX_U32>(quirks));
+    return Void();
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
diff --git a/media/libmedia/omx/1.0/WOmxObserver.cpp b/media/libmedia/omx/1.0/WOmxObserver.cpp
new file mode 100644
index 0000000..fa0407f
--- /dev/null
+++ b/media/libmedia/omx/1.0/WOmxObserver.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "WOmxObserver-utils"
+
+#include <vector>
+
+#include <utils/Log.h>
+#include <cutils/native_handle.h>
+#include <binder/Binder.h>
+
+#include <media/omx/1.0/WOmxObserver.h>
+#include <media/omx/1.0/Conversion.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace utils {
+
+// 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;
+    }
+    auto transResult = mBase->onMessages(tMessages);
+    if (!transResult.isOk()) {
+        ALOGE("LWOmxObserver::onMessages - Transaction failed");
+    }
+    for (auto& handle : handles) {
+        native_handle_close(handle);
+        native_handle_delete(handle);
+    }
+}
+
+// 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{});
+        convertTo(&lMessages.back(), tMessages[i]);
+    }
+    mBase->onMessages(lMessages);
+    return Return<void>();
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
diff --git a/media/libmedia/omx/1.0/WOmxProducerListener.cpp b/media/libmedia/omx/1.0/WOmxProducerListener.cpp
new file mode 100644
index 0000000..3ee381f
--- /dev/null
+++ b/media/libmedia/omx/1.0/WOmxProducerListener.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/omx/1.0/WOmxProducerListener.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace utils {
+
+// TWOmxProducerListener
+TWOmxProducerListener::TWOmxProducerListener(
+        sp<IProducerListener> const& base):
+    mBase(base) {
+}
+
+Return<void> TWOmxProducerListener::onBufferReleased() {
+    mBase->onBufferReleased();
+    return Void();
+}
+
+Return<bool> TWOmxProducerListener::needsReleaseNotify() {
+    return mBase->needsReleaseNotify();
+}
+
+// LWOmxProducerListener
+LWOmxProducerListener::LWOmxProducerListener(
+        sp<IOmxProducerListener> const& base):
+    mBase(base) {
+}
+
+void LWOmxProducerListener::onBufferReleased() {
+    mBase->onBufferReleased();
+}
+
+bool LWOmxProducerListener::needsReleaseNotify() {
+    return static_cast<bool>(mBase->needsReleaseNotify());
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
+}  // namespace android