Merge "CameraProviderManager: Handle transaction errors, HAL process death"
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 1fda06c..e77a8ea 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -112,7 +112,7 @@
 Vector<sp<ICryptoFactory>> CryptoHal::makeCryptoFactories() {
     Vector<sp<ICryptoFactory>> factories;
 
-    auto manager = ::IServiceManager::getService("manager");
+    auto manager = ::IServiceManager::getService();
     if (manager != NULL) {
         manager->listByInterface(ICryptoFactory::descriptor,
                 [&factories](const hidl_vec<hidl_string> &registered) {
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 595b895..16035c0 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -200,7 +200,7 @@
 Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
     Vector<sp<IDrmFactory>> factories;
 
-    auto manager = ::IServiceManager::getService("manager");
+    auto manager = ::IServiceManager::getService();
 
     if (manager != NULL) {
         manager->listByInterface(IDrmFactory::descriptor,
diff --git a/include/media/omx/1.0/Conversion.h b/include/media/omx/1.0/Conversion.h
index ee83713..f3f8441 100644
--- a/include/media/omx/1.0/Conversion.h
+++ b/include/media/omx/1.0/Conversion.h
@@ -191,6 +191,19 @@
 }
 
 /**
+ * \brief Convert `Return<Status>` to `binder::Status`.
+ *
+ * \param[in] t The source `Return<Status>`.
+ * \return The corresponding `binder::Status`.
+ */
+// convert: Return<Status> -> ::android::binder::Status
+inline ::android::binder::Status toBinderStatus(
+        Return<Status> const& t) {
+    return ::android::binder::Status::fromStatusT(
+            t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) : UNKNOWN_ERROR);
+}
+
+/**
  * \brief Convert `Return<Status>` to `status_t`. This is for legacy binder
  * calls.
  *
diff --git a/include/media/omx/1.0/WGraphicBufferSource.h b/include/media/omx/1.0/WGraphicBufferSource.h
index 7c80c2e..0ca5f44 100644
--- a/include/media/omx/1.0/WGraphicBufferSource.h
+++ b/include/media/omx/1.0/WGraphicBufferSource.h
@@ -48,7 +48,6 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::sp;
-
 using ::android::IOMXNode;
 
 /**
@@ -60,7 +59,7 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-typedef ::android::IGraphicBufferSource LGraphicBufferSource;
+typedef ::android::binder::Status BnStatus;
 typedef ::android::BnGraphicBufferSource BnGraphicBufferSource;
 typedef ::android::hardware::media::omx::V1_0::IGraphicBufferSource
         TGraphicBufferSource;
@@ -68,36 +67,19 @@
 struct LWGraphicBufferSource : public BnGraphicBufferSource {
     sp<TGraphicBufferSource> mBase;
     LWGraphicBufferSource(sp<TGraphicBufferSource> const& base);
-    ::android::binder::Status configure(
+    BnStatus configure(
             const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
-    ::android::binder::Status setSuspend(bool suspend, int64_t timeUs) override;
-    ::android::binder::Status setRepeatPreviousFrameDelayUs(
+    BnStatus setSuspend(bool suspend, int64_t timeUs) override;
+    BnStatus setRepeatPreviousFrameDelayUs(
             int64_t repeatAfterUs) override;
-    ::android::binder::Status setMaxFps(float maxFps) override;
-    ::android::binder::Status setTimeLapseConfig(
+    BnStatus setMaxFps(float maxFps) override;
+    BnStatus setTimeLapseConfig(
             int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
-    ::android::binder::Status setStartTimeUs(int64_t startTimeUs) override;
-    ::android::binder::Status setStopTimeUs(int64_t stopTimeUs) override;
-    ::android::binder::Status setColorAspects(int32_t aspects) override;
-    ::android::binder::Status setTimeOffsetUs(int64_t timeOffsetsUs) override;
-    ::android::binder::Status signalEndOfInputStream() 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, int64_t timeUs) 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> setStopTimeUs(int64_t stopTimeUs) override;
-    Return<void> setColorAspects(const ColorAspects& aspects) override;
-    Return<void> setTimeOffsetUs(int64_t timeOffsetUs) override;
-    Return<void> signalEndOfInputStream() override;
+    BnStatus setStartTimeUs(int64_t startTimeUs) override;
+    BnStatus setStopTimeUs(int64_t stopTimeUs) override;
+    BnStatus setColorAspects(int32_t aspects) override;
+    BnStatus setTimeOffsetUs(int64_t timeOffsetsUs) override;
+    BnStatus signalEndOfInputStream() override;
 };
 
 }  // namespace utils
diff --git a/include/media/omx/1.0/WOmx.h b/include/media/omx/1.0/WOmx.h
index 4aaf470..9268bd6 100644
--- a/include/media/omx/1.0/WOmx.h
+++ b/include/media/omx/1.0/WOmx.h
@@ -70,18 +70,6 @@
             sp<::android::IGraphicBufferSource>* bufferSource) 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;
-    Return<void> createInputSurface(createInputSurface_cb _hidl_cb) override;
-
-};
-
 }  // namespace utils
 }  // namespace V1_0
 }  // namespace omx
diff --git a/include/ndk/NdkImage.h b/include/ndk/NdkImage.h
index 15eae40..40c1699 100644
--- a/include/ndk/NdkImage.h
+++ b/include/ndk/NdkImage.h
@@ -646,7 +646,9 @@
  *         <li>{@link AMEDIA_ERROR_UNSUPPORTED} if pixel stride is undefined for the format of input
  *                 image.</li>
  *         <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
- *                 image has been deleted.</li></ul>
+ *                 image has been deleted.</li>
+ *         <li>{@link AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE} if the {@link AImage} cannot be locked
+ *                 for CPU access.</li></ul>
  */
 media_status_t AImage_getPlanePixelStride(
         const AImage* image, int planeIdx, /*out*/int32_t* pixelStride);
@@ -671,7 +673,9 @@
  *         <li>{@link AMEDIA_ERROR_UNSUPPORTED} if row stride is undefined for the format of input
  *                 image.</li>
  *         <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
- *                 image has been deleted.</li></ul>
+ *                 image has been deleted.</li>
+ *         <li>{@link AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE} if the {@link AImage} cannot be locked
+ *                 for CPU access.</li></ul>
  */
 media_status_t AImage_getPlaneRowStride(
         const AImage* image, int planeIdx, /*out*/int32_t* rowStride);
@@ -693,7 +697,9 @@
  *         <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image, data or dataLength is NULL, or
  *                 planeIdx is out of the range of [0, numOfPlanes - 1].</li>
  *         <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
- *                 image has been deleted.</li></ul>
+ *                 image has been deleted.</li>
+ *         <li>{@link AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE} if the {@link AImage} cannot be locked
+ *                 for CPU access.</li></ul>
  */
 media_status_t AImage_getPlaneData(
         const AImage* image, int planeIdx,
diff --git a/include/ndk/NdkMediaError.h b/include/ndk/NdkMediaError.h
index fb00b1d..9709a6f 100644
--- a/include/ndk/NdkMediaError.h
+++ b/include/ndk/NdkMediaError.h
@@ -60,6 +60,9 @@
     AMEDIA_IMGREADER_ERROR_BASE          = -30000,
     AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE = AMEDIA_IMGREADER_ERROR_BASE - 1,
     AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED = AMEDIA_IMGREADER_ERROR_BASE - 2,
+    AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE   = AMEDIA_IMGREADER_ERROR_BASE - 3,
+    AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE = AMEDIA_IMGREADER_ERROR_BASE - 4,
+    AMEDIA_IMGREADER_IMAGE_NOT_LOCKED    = AMEDIA_IMGREADER_ERROR_BASE - 5,
 
 } media_status_t;
 
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 4c1fbd7..6c7cdde 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -66,7 +66,8 @@
 // ---------------------------------------------------------------------------
 
 AudioRecord::AudioRecord(const String16 &opPackageName)
-    : mActive(false), mStatus(NO_INIT), mOpPackageName(opPackageName), mSessionId(AUDIO_SESSION_ALLOCATE),
+    : mActive(false), mStatus(NO_INIT), mOpPackageName(opPackageName),
+      mSessionId(AUDIO_SESSION_ALLOCATE),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE), mPortId(AUDIO_PORT_HANDLE_NONE)
 {
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 1908f0e..5cd2789 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -554,7 +554,8 @@
                     "channel mask %#x frameCount %zu frameCountHAL %zu deviceId %d",
                     event == AUDIO_OUTPUT_CONFIG_CHANGED ? "output" : "input",
                     ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat,
-                    ioDesc->mChannelMask, ioDesc->mFrameCount, ioDesc->mFrameCountHAL, ioDesc->getDeviceId());
+                    ioDesc->mChannelMask, ioDesc->mFrameCount, ioDesc->mFrameCountHAL,
+                    ioDesc->getDeviceId());
 
         } break;
         }
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index f878be9..d590cb7 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -917,7 +917,8 @@
     }
 
     // Check resampler ratios are within bounds
-    if ((uint64_t)effectiveRate > (uint64_t)mSampleRate * (uint64_t)AUDIO_RESAMPLER_DOWN_RATIO_MAX) {
+    if ((uint64_t)effectiveRate > (uint64_t)mSampleRate *
+            (uint64_t)AUDIO_RESAMPLER_DOWN_RATIO_MAX) {
         ALOGV("setPlaybackRate(%f, %f) failed. Resample rate exceeds max accepted value",
                 playbackRate.mSpeed, playbackRate.mPitch);
         return BAD_VALUE;
@@ -1274,9 +1275,10 @@
                                            mFlags, mSelectedDeviceId, &mPortId);
 
     if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
-        ALOGE("Could not get audio output for session %d, stream type %d, usage %d, sample rate %u, format %#x,"
-              " channel mask %#x, flags %#x",
-              mSessionId, streamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask, mFlags);
+        ALOGE("Could not get audio output for session %d, stream type %d, usage %d, sample rate %u,"
+              " format %#x, channel mask %#x, flags %#x",
+              mSessionId, streamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask,
+              mFlags);
         return BAD_VALUE;
     }
     {
diff --git a/media/libaudiohal/ConversionHelperHidl.h b/media/libaudiohal/ConversionHelperHidl.h
index a991baf..c356f37 100644
--- a/media/libaudiohal/ConversionHelperHidl.h
+++ b/media/libaudiohal/ConversionHelperHidl.h
@@ -23,7 +23,6 @@
 
 using ::android::hardware::audio::V2_0::ParameterValue;
 using ::android::hardware::Return;
-using ::android::hardware::Status;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 
diff --git a/media/libaudiohal/DevicesFactoryHalHidl.cpp b/media/libaudiohal/DevicesFactoryHalHidl.cpp
index 9cbe018..6d73e2d 100644
--- a/media/libaudiohal/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/DevicesFactoryHalHidl.cpp
@@ -30,7 +30,6 @@
 using ::android::hardware::audio::V2_0::IDevice;
 using ::android::hardware::audio::V2_0::Result;
 using ::android::hardware::Return;
-using ::android::hardware::Status;
 
 namespace android {
 
diff --git a/media/libaudiohal/EffectBufferHalHidl.cpp b/media/libaudiohal/EffectBufferHalHidl.cpp
index ce581f2..d6a41a2 100644
--- a/media/libaudiohal/EffectBufferHalHidl.cpp
+++ b/media/libaudiohal/EffectBufferHalHidl.cpp
@@ -27,7 +27,6 @@
 #include "EffectBufferHalHidl.h"
 
 using ::android::hardware::Return;
-using ::android::hardware::Status;
 using ::android::hidl::allocator::V1_0::IAllocator;
 
 namespace android {
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/EffectHalHidl.cpp
index 539558d..0babfda 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/EffectHalHidl.cpp
@@ -36,7 +36,6 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::MQDescriptorSync;
 using ::android::hardware::Return;
-using ::android::hardware::Status;
 
 namespace android {
 
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.cpp b/media/libaudiohal/EffectsFactoryHalHidl.cpp
index 950f9dc..fd3e207 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/EffectsFactoryHalHidl.cpp
@@ -29,7 +29,6 @@
 using ::android::hardware::audio::effect::V2_0::IEffect;
 using ::android::hardware::audio::effect::V2_0::Result;
 using ::android::hardware::Return;
-using ::android::hardware::Status;
 
 namespace android {
 
diff --git a/media/libmedia/omx/1.0/WGraphicBufferSource.cpp b/media/libmedia/omx/1.0/WGraphicBufferSource.cpp
index 247c540..b4e2975 100644
--- a/media/libmedia/omx/1.0/WGraphicBufferSource.cpp
+++ b/media/libmedia/omx/1.0/WGraphicBufferSource.cpp
@@ -14,8 +14,6 @@
  * 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>
@@ -27,14 +25,12 @@
 namespace V1_0 {
 namespace utils {
 
-using android::ColorUtils;
-
 // LWGraphicBufferSource
 LWGraphicBufferSource::LWGraphicBufferSource(
         sp<TGraphicBufferSource> const& base) : mBase(base) {
 }
 
-::android::binder::Status LWGraphicBufferSource::configure(
+BnStatus LWGraphicBufferSource::configure(
         const sp<IOMXNode>& omxNode, int32_t dataSpace) {
     sp<IOmxNode> hOmxNode = omxNode->getHalInterface();
     return toBinderStatus(mBase->configure(
@@ -42,111 +38,51 @@
             toHardwareDataspace(dataSpace)));
 }
 
-::android::binder::Status LWGraphicBufferSource::setSuspend(
+BnStatus LWGraphicBufferSource::setSuspend(
         bool suspend, int64_t timeUs) {
     return toBinderStatus(mBase->setSuspend(suspend, timeUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
+BnStatus LWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
         int64_t repeatAfterUs) {
     return toBinderStatus(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::setMaxFps(float maxFps) {
+BnStatus LWGraphicBufferSource::setMaxFps(float maxFps) {
     return toBinderStatus(mBase->setMaxFps(maxFps));
 }
 
-::android::binder::Status LWGraphicBufferSource::setTimeLapseConfig(
+BnStatus LWGraphicBufferSource::setTimeLapseConfig(
         int64_t timePerFrameUs, int64_t timePerCaptureUs) {
     return toBinderStatus(mBase->setTimeLapseConfig(
             timePerFrameUs, timePerCaptureUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::setStartTimeUs(
+BnStatus LWGraphicBufferSource::setStartTimeUs(
         int64_t startTimeUs) {
     return toBinderStatus(mBase->setStartTimeUs(startTimeUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::setStopTimeUs(
+BnStatus LWGraphicBufferSource::setStopTimeUs(
         int64_t stopTimeUs) {
     return toBinderStatus(mBase->setStopTimeUs(stopTimeUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::setColorAspects(
+BnStatus LWGraphicBufferSource::setColorAspects(
         int32_t aspects) {
     return toBinderStatus(mBase->setColorAspects(
             toHardwareColorAspects(aspects)));
 }
 
-::android::binder::Status LWGraphicBufferSource::setTimeOffsetUs(
+BnStatus LWGraphicBufferSource::setTimeOffsetUs(
         int64_t timeOffsetsUs) {
     return toBinderStatus(mBase->setTimeOffsetUs(timeOffsetsUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::signalEndOfInputStream() {
+BnStatus 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
diff --git a/media/libmedia/omx/1.0/WOmx.cpp b/media/libmedia/omx/1.0/WOmx.cpp
index 39871f8..8e4e147 100644
--- a/media/libmedia/omx/1.0/WOmx.cpp
+++ b/media/libmedia/omx/1.0/WOmx.cpp
@@ -79,45 +79,6 @@
     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
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index 0e98db8..2892520 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -259,7 +259,7 @@
 
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
-    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+    if (mOffsetTableLength > 0 && options && options->getSeekTo(&seekTimeUs, &mode)) {
         size_t size;
         int64_t seekFrame = seekTimeUs / 20000ll;  // 20ms per frame.
         mCurrentTimeUs = seekFrame * 20000ll;
diff --git a/media/libstagefright/HevcUtils.cpp b/media/libstagefright/HevcUtils.cpp
index 718710a..7d463a9 100644
--- a/media/libstagefright/HevcUtils.cpp
+++ b/media/libstagefright/HevcUtils.cpp
@@ -45,16 +45,32 @@
 }
 
 status_t HevcParameterSets::addNalUnit(const uint8_t* data, size_t size) {
+    if (size < 1) {
+        ALOGE("empty NAL b/35467107");
+        return ERROR_MALFORMED;
+    }
     uint8_t nalUnitType = (data[0] >> 1) & 0x3f;
     status_t err = OK;
     switch (nalUnitType) {
         case 32:  // VPS
+            if (size < 2) {
+                ALOGE("invalid NAL/VPS size b/35467107");
+                return ERROR_MALFORMED;
+            }
             err = parseVps(data + 2, size - 2);
             break;
         case 33:  // SPS
+            if (size < 2) {
+                ALOGE("invalid NAL/SPS size b/35467107");
+                return ERROR_MALFORMED;
+            }
             err = parseSps(data + 2, size - 2);
             break;
         case 34:  // PPS
+            if (size < 2) {
+                ALOGE("invalid NAL/PPS size b/35467107");
+                return ERROR_MALFORMED;
+            }
             err = parsePps(data + 2, size - 2);
             break;
         case 39:  // Prefix SEI
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index ea3ed28..e3ca516 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -615,7 +615,7 @@
     }
 
     off64_t size;
-    if (mDurationUs >= 0 && mDataSource->getSize(&size) == OK) {
+    if (mDurationUs > 0 && mDataSource->getSize(&size) == OK) {
         *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
         return true;
     }
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 5f516cb..44415e2 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -16,6 +16,7 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "SoftAACEncoder2"
+#include <log/log.h>
 #include <utils/Log.h>
 
 #include "SoftAACEncoder2.h"
@@ -61,6 +62,7 @@
       mSentCodecSpecificData(false),
       mInputSize(0),
       mInputFrame(NULL),
+      mAllocatedFrameSize(0),
       mInputTimeUs(-1ll),
       mSawInputEOS(false),
       mSignalledError(false) {
@@ -510,6 +512,15 @@
 
         BufferInfo *outInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+        if (outHeader->nOffset + encInfo.confSize > outHeader->nAllocLen) {
+            ALOGE("b/34617444");
+            android_errorWriteLog(0x534e4554,"34617444");
+            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+            mSignalledError = true;
+            return;
+        }
+
         outHeader->nFilledLen = encInfo.confSize;
         outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
 
@@ -556,6 +567,15 @@
 
             if (mInputFrame == NULL) {
                 mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
+                mAllocatedFrameSize = numBytesPerInputFrame;
+            } else if (mAllocatedFrameSize != numBytesPerInputFrame) {
+                ALOGE("b/34621073: changed size from %d to %d",
+                        (int)mAllocatedFrameSize, (int)numBytesPerInputFrame);
+                android_errorWriteLog(0x534e4554,"34621073");
+                delete mInputFrame;
+                mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
+                mAllocatedFrameSize = numBytesPerInputFrame;
+
             }
 
             if (mInputSize == 0) {
@@ -706,6 +726,7 @@
     delete[] mInputFrame;
     mInputFrame = NULL;
     mInputSize = 0;
+    mAllocatedFrameSize = 0;
 
     mSentCodecSpecificData = false;
     mInputTimeUs = -1ll;
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h
index f1b81e1..123fd25 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h
@@ -62,6 +62,7 @@
     bool mSentCodecSpecificData;
     size_t mInputSize;
     int16_t *mInputFrame;
+    size_t mAllocatedFrameSize;
     int64_t mInputTimeUs;
 
     bool mSawInputEOS;
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mb_motion_comp.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
index fbc7be1..877723d 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
@@ -15,6 +15,10 @@
  * and limitations under the License.
  * -------------------------------------------------------------------
  */
+
+#define LOG_TAG "m4v_h263"
+#include <log/log.h>
+
 /*
 ------------------------------------------------------------------------------
  INPUT AND OUTPUT DEFINITIONS
@@ -236,6 +240,11 @@
 
     /* Pointer to previous luminance frame */
     c_prev  = prev->yChan;
+    if (!c_prev) {
+        ALOGE("b/35269635");
+        android_errorWriteLog(0x534e4554, "35269635");
+        return;
+    }
 
     pred_block = video->mblock->pred_block;
 
@@ -574,7 +583,14 @@
 
     /* zero motion compensation for previous frame */
     /*mby*width + mbx;*/
-    c_prev  = prev->yChan + offset;
+    c_prev  = prev->yChan;
+    if (!c_prev) {
+        ALOGE("b/35269635");
+        android_errorWriteLog(0x534e4554, "35269635");
+        return;
+    }
+    c_prev += offset;
+
     /*by*width_uv + bx;*/
     cu_prev = prev->uChan + (offset >> 2) + (xpos >> 2);
     /*by*width_uv + bx;*/
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
index c1720c6..8d5d071 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
@@ -15,6 +15,8 @@
  * and limitations under the License.
  * -------------------------------------------------------------------
  */
+#define LOG_TAG "pvdec_api"
+#include <log/log.h>
 #include "mp4dec_lib.h"
 #include "vlc_decode.h"
 #include "bitstream.h"
@@ -1335,6 +1337,11 @@
             }
         }
 
+        if (!video->prevVop->yChan) {
+            ALOGE("b/35269635");
+            android_errorWriteLog(0x534e4554, "35269635");
+            return PV_FALSE;
+        }
         oscl_memcpy(currVop->yChan, video->prevVop->yChan, (decCtrl->size*3) / 2);
 
         video->prevVop = prevVop;
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 9105084..8d1ad66 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -379,7 +379,7 @@
             flags &= ~1;
         }
 
-        if (flags & 2) {
+        if ((flags & 2) && (dataSize >= 2)) {
             // This file has "unsynchronization", so we have to replace occurrences
             // of 0xff 0x00 with just 0xff in order to get the real data.
 
@@ -395,11 +395,15 @@
                 mData[writeOffset++] = mData[readOffset++];
             }
             // move the remaining data following this frame
-            memmove(&mData[writeOffset], &mData[readOffset], oldSize - readOffset);
+            if (readOffset <= oldSize) {
+                memmove(&mData[writeOffset], &mData[readOffset], oldSize - readOffset);
+            } else {
+                ALOGE("b/34618607 (%zu %zu %zu %zu)", readOffset, writeOffset, oldSize, mSize);
+                android_errorWriteLog(0x534e4554, "34618607");
+            }
 
-            flags &= ~2;
         }
-
+        flags &= ~2;
         if (flags != prevFlags || iTunesHack) {
             WriteSyncsafeInteger(&mData[offset + 4], dataSize);
             mData[offset + 8] = flags >> 8;
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index f70f13b..9cba3d0 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES:=                     \
         FrameDropper.cpp              \
         GraphicBufferSource.cpp       \
+        BWGraphicBufferSource.cpp      \
         OMX.cpp                       \
         OMXMaster.cpp                 \
         OMXNodeInstance.cpp           \
diff --git a/media/libstagefright/omx/BWGraphicBufferSource.cpp b/media/libstagefright/omx/BWGraphicBufferSource.cpp
new file mode 100644
index 0000000..4e0f6dd
--- /dev/null
+++ b/media/libstagefright/omx/BWGraphicBufferSource.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "BWGraphicBufferSource"
+
+#include <OMX_Component.h>
+#include <OMX_IndexExt.h>
+
+#include <media/OMXBuffer.h>
+#include <IOMX.h>
+
+#include "OMXUtils.h"
+#include "BWGraphicBufferSource.h"
+
+namespace android {
+
+static const OMX_U32 kPortIndexInput = 0;
+
+struct BWGraphicBufferSource::BWOmxNodeWrapper : public IOmxNodeWrapper {
+    sp<IOMXNode> mOMXNode;
+
+    BWOmxNodeWrapper(const sp<IOMXNode> &omxNode): mOMXNode(omxNode) {
+    }
+
+    virtual status_t emptyBuffer(
+            int32_t bufferId, uint32_t flags,
+            const sp<GraphicBuffer> &buffer,
+            int64_t timestamp, int fenceFd) override {
+        return mOMXNode->emptyBuffer(bufferId, buffer, flags, timestamp, fenceFd);
+    }
+
+    virtual void dispatchDataSpaceChanged(
+            int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
+        omx_message msg;
+        msg.type = omx_message::EVENT;
+        msg.fenceFd = -1;
+        msg.u.event_data.event = OMX_EventDataSpaceChanged;
+        msg.u.event_data.data1 = dataSpace;
+        msg.u.event_data.data2 = aspects;
+        msg.u.event_data.data3 = pixelFormat;
+        mOMXNode->dispatchMessage(msg);
+    }
+};
+
+struct BWGraphicBufferSource::BWOMXBufferSource : public BnOMXBufferSource {
+    sp<GraphicBufferSource> mSource;
+
+    BWOMXBufferSource(const sp<GraphicBufferSource> &source): mSource(source) {
+    }
+
+    Status onOmxExecuting() override {
+        return mSource->onOmxExecuting();
+    }
+
+    Status onOmxIdle() override {
+        return mSource->onOmxIdle();
+    }
+
+    Status onOmxLoaded() override {
+        return mSource->onOmxLoaded();
+    }
+
+    Status onInputBufferAdded(int bufferId) override {
+        return mSource->onInputBufferAdded(bufferId);
+    }
+
+    Status onInputBufferEmptied(
+            int bufferId, const OMXFenceParcelable& fenceParcel) override {
+        return mSource->onInputBufferEmptied(bufferId, fenceParcel.get());
+    }
+};
+
+BWGraphicBufferSource::BWGraphicBufferSource(
+        sp<GraphicBufferSource> const& base) :
+    mBase(base),
+    mOMXBufferSource(new BWOMXBufferSource(base)) {
+}
+
+::android::binder::Status BWGraphicBufferSource::configure(
+        const sp<IOMXNode>& omxNode, int32_t dataSpace) {
+    // Do setInputSurface() first, the node will try to enable metadata
+    // mode on input, and does necessary error checking. If this fails,
+    // we can't use this input surface on the node.
+    status_t err = omxNode->setInputSurface(mOMXBufferSource);
+    if (err != NO_ERROR) {
+        ALOGE("Unable to set input surface: %d", err);
+        return Status::fromStatusT(err);
+    }
+
+    // use consumer usage bits queried from encoder, but always add
+    // HW_VIDEO_ENCODER for backward compatibility.
+    uint32_t consumerUsage;
+    if (omxNode->getParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+            &consumerUsage, sizeof(consumerUsage)) != OK) {
+        consumerUsage = 0;
+    }
+
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexInput;
+
+    err = omxNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
+    if (err != NO_ERROR) {
+        ALOGE("Failed to get port definition: %d", err);
+        return Status::fromStatusT(UNKNOWN_ERROR);
+    }
+
+    return Status::fromStatusT(mBase->configure(
+              new BWOmxNodeWrapper(omxNode),
+              dataSpace,
+              def.nBufferCountActual,
+              def.format.video.nFrameWidth,
+              def.format.video.nFrameHeight,
+              consumerUsage));
+}
+
+::android::binder::Status BWGraphicBufferSource::setSuspend(
+        bool suspend, int64_t timeUs) {
+    return Status::fromStatusT(mBase->setSuspend(suspend, timeUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
+        int64_t repeatAfterUs) {
+    return Status::fromStatusT(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::setMaxFps(float maxFps) {
+    return Status::fromStatusT(mBase->setMaxFps(maxFps));
+}
+
+::android::binder::Status BWGraphicBufferSource::setTimeLapseConfig(
+        int64_t timePerFrameUs, int64_t timePerCaptureUs) {
+    return Status::fromStatusT(mBase->setTimeLapseConfig(
+            timePerFrameUs, timePerCaptureUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::setStartTimeUs(
+        int64_t startTimeUs) {
+    return Status::fromStatusT(mBase->setStartTimeUs(startTimeUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::setStopTimeUs(
+        int64_t stopTimeUs) {
+    return Status::fromStatusT(mBase->setStopTimeUs(stopTimeUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::setColorAspects(
+        int32_t aspects) {
+    return Status::fromStatusT(mBase->setColorAspects(aspects));
+}
+
+::android::binder::Status BWGraphicBufferSource::setTimeOffsetUs(
+        int64_t timeOffsetsUs) {
+    return Status::fromStatusT(mBase->setTimeOffsetUs(timeOffsetsUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::signalEndOfInputStream() {
+    return Status::fromStatusT(mBase->signalEndOfInputStream());
+}
+
+}  // namespace android
diff --git a/media/libstagefright/omx/BWGraphicBufferSource.h b/media/libstagefright/omx/BWGraphicBufferSource.h
new file mode 100644
index 0000000..f1ce2af
--- /dev/null
+++ b/media/libstagefright/omx/BWGraphicBufferSource.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BWGRAPHIC_BUFFER_SOURCE_H_
+#define BWGRAPHIC_BUFFER_SOURCE_H_
+
+#include <binder/Binder.h>
+#include <binder/Status.h>
+#include <android/BnGraphicBufferSource.h>
+#include <android/BnOMXBufferSource.h>
+#include <IOMX.h>
+
+#include "GraphicBufferSource.h"
+#include "IOmxNodeWrapper.h"
+
+namespace android {
+
+using ::android::binder::Status;
+using ::android::BnGraphicBufferSource;
+using ::android::GraphicBufferSource;
+using ::android::IOMXNode;
+using ::android::sp;
+
+struct BWGraphicBufferSource : public BnGraphicBufferSource {
+    struct BWOMXBufferSource;
+    struct BWOmxNodeWrapper;
+
+    sp<GraphicBufferSource> mBase;
+    sp<IOMXBufferSource> mOMXBufferSource;
+
+    BWGraphicBufferSource(sp<GraphicBufferSource> const &base);
+
+    Status configure(
+            const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
+    Status setSuspend(bool suspend, int64_t timeUs) override;
+    Status setRepeatPreviousFrameDelayUs(
+            int64_t repeatAfterUs) override;
+    Status setMaxFps(float maxFps) override;
+    Status setTimeLapseConfig(
+            int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
+    Status setStartTimeUs(int64_t startTimeUs) override;
+    Status setStopTimeUs(int64_t stopTimeUs) override;
+    Status setColorAspects(int32_t aspects) override;
+    Status setTimeOffsetUs(int64_t timeOffsetsUs) override;
+    Status signalEndOfInputStream() override;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_WGRAPHICBUFFERSOURCE_H
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 2f457ac..793ecb8 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -41,37 +41,6 @@
 
 namespace android {
 
-static const OMX_U32 kPortIndexInput = 0;
-
-class GraphicBufferSource::OmxBufferSource : public BnOMXBufferSource {
-public:
-    GraphicBufferSource* mSource;
-
-    OmxBufferSource(GraphicBufferSource* source): mSource(source) {
-    }
-
-    Status onOmxExecuting() override {
-        return mSource->onOmxExecuting();
-    }
-
-    Status onOmxIdle() override {
-        return mSource->onOmxIdle();
-    }
-
-    Status onOmxLoaded() override {
-        return mSource->onOmxLoaded();
-    }
-
-    Status onInputBufferAdded(int bufferId) override {
-        return mSource->onInputBufferAdded(bufferId);
-    }
-
-    Status onInputBufferEmptied(
-            int bufferId, const OMXFenceParcelable& fenceParcel) override {
-        return mSource->onInputBufferEmptied(bufferId, fenceParcel);
-    }
-};
-
 GraphicBufferSource::GraphicBufferSource() :
     mInitCheck(UNKNOWN_ERROR),
     mExecuting(false),
@@ -97,8 +66,7 @@
     mTimePerFrameUs(-1ll),
     mPrevCaptureUs(-1ll),
     mPrevFrameUs(-1ll),
-    mInputBufferTimeOffsetUs(0ll),
-    mOmxBufferSource(new OmxBufferSource(this)) {
+    mInputBufferTimeOffsetUs(0ll) {
     ALOGV("GraphicBufferSource");
 
     String8 name("GraphicBufferSource");
@@ -122,7 +90,7 @@
         return;
     }
 
-    memset(&mColorAspects, 0, sizeof(mColorAspects));
+    memset(&mColorAspectsPacked, 0, sizeof(mColorAspectsPacked));
 
     CHECK(mInitCheck == NO_ERROR);
 }
@@ -273,9 +241,7 @@
 }
 
 Status GraphicBufferSource::onInputBufferEmptied(
-        int32_t bufferID, const OMXFenceParcelable &fenceParcel) {
-    int fenceFd = fenceParcel.get();
-
+        int32_t bufferID, int fenceFd) {
     Mutex::Autolock autoLock(mMutex);
     if (!mExecuting) {
         if (fenceFd >= 0) {
@@ -374,15 +340,7 @@
     mLastDataSpace = dataSpace;
 
     if (ColorUtils::convertDataSpaceToV0(dataSpace)) {
-        omx_message msg;
-        msg.type = omx_message::EVENT;
-        msg.fenceFd = -1;
-        msg.u.event_data.event = OMX_EventDataSpaceChanged;
-        msg.u.event_data.data1 = mLastDataSpace;
-        msg.u.event_data.data2 = ColorUtils::packToU32(mColorAspects);
-        msg.u.event_data.data3 = pixelFormat;
-
-        mOMXNode->dispatchMessage(msg);
+        mOMXNode->dispatchDataSpaceChanged(mLastDataSpace, mColorAspectsPacked, pixelFormat);
     }
 }
 
@@ -689,7 +647,7 @@
     int fenceID = item.mFence->isValid() ? item.mFence->dup() : -1;
 
     status_t err = mOMXNode->emptyBuffer(
-            bufferID, buffer, OMX_BUFFERFLAG_ENDOFFRAME, codecTimeUs, fenceID);
+            bufferID, OMX_BUFFERFLAG_ENDOFFRAME, buffer, codecTimeUs, fenceID);
 
     if (err != OK) {
         ALOGW("WARNING: emptyGraphicBuffer failed: 0x%x", err);
@@ -721,10 +679,8 @@
     CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
     IOMX::buffer_id bufferID = codecBuffer.mBufferID;
 
-    status_t err = mOMXNode->emptyBuffer(
-            bufferID, (sp<GraphicBuffer>)NULL,
-            OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
-            0 /* timestamp */, -1 /* fenceFd */);
+    status_t err = mOMXNode->emptyBuffer(bufferID,
+            OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS);
     if (err != OK) {
         ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
     } else {
@@ -865,65 +821,38 @@
     ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
 }
 
-Status GraphicBufferSource::configure(
-        const sp<IOMXNode>& omxNode, int32_t dataSpace) {
+status_t GraphicBufferSource::configure(
+        const sp<IOmxNodeWrapper>& omxNode,
+        int32_t dataSpace,
+        int32_t bufferCount,
+        uint32_t frameWidth,
+        uint32_t frameHeight,
+        uint32_t consumerUsage) {
     if (omxNode == NULL) {
-        return Status::fromServiceSpecificError(BAD_VALUE);
+        return BAD_VALUE;
     }
 
-    // Do setInputSurface() first, the node will try to enable metadata
-    // mode on input, and does necessary error checking. If this fails,
-    // we can't use this input surface on the node.
-    status_t err = omxNode->setInputSurface(mOmxBufferSource);
-    if (err != NO_ERROR) {
-        ALOGE("Unable to set input surface: %d", err);
-        return Status::fromServiceSpecificError(err);
-    }
-
-    // use consumer usage bits queried from encoder, but always add
-    // HW_VIDEO_ENCODER for backward compatibility.
-    uint32_t consumerUsage;
-    if (omxNode->getParameter(
-            (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
-            &consumerUsage, sizeof(consumerUsage)) != OK) {
-        consumerUsage = 0;
-    }
-
-    OMX_PARAM_PORTDEFINITIONTYPE def;
-    InitOMXParams(&def);
-    def.nPortIndex = kPortIndexInput;
-
-    err = omxNode->getParameter(
-            OMX_IndexParamPortDefinition, &def, sizeof(def));
-    if (err != NO_ERROR) {
-        ALOGE("Failed to get port definition: %d", err);
-        return Status::fromServiceSpecificError(UNKNOWN_ERROR);
-    }
 
     // Call setMaxAcquiredBufferCount without lock.
     // setMaxAcquiredBufferCount could call back to onBuffersReleased
     // if the buffer count change results in releasing of existing buffers,
     // which would lead to deadlock.
-    err = mConsumer->setMaxAcquiredBufferCount(def.nBufferCountActual);
+    status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
     if (err != NO_ERROR) {
         ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
-                def.nBufferCountActual, err);
-        return Status::fromServiceSpecificError(err);
+                bufferCount, err);
+        return err;
     }
 
     {
         Mutex::Autolock autoLock(mMutex);
         mOMXNode = omxNode;
 
-        err = mConsumer->setDefaultBufferSize(
-                def.format.video.nFrameWidth,
-                def.format.video.nFrameHeight);
+        err = mConsumer->setDefaultBufferSize(frameWidth, frameHeight);
         if (err != NO_ERROR) {
             ALOGE("Unable to set BQ default buffer size to %ux%u: %d",
-                    def.format.video.nFrameWidth,
-                    def.format.video.nFrameHeight,
-                    err);
-            return Status::fromServiceSpecificError(err);
+                    frameWidth, frameHeight, err);
+            return err;
         }
 
         consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
@@ -957,17 +886,17 @@
         mActionQueue.clear();
     }
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setSuspend(bool suspend, int64_t suspendStartTimeUs) {
+status_t GraphicBufferSource::setSuspend(bool suspend, int64_t suspendStartTimeUs) {
     ALOGV("setSuspend=%d at time %lld us", suspend, (long long)suspendStartTimeUs);
 
     Mutex::Autolock autoLock(mMutex);
 
     if (mStopTimeUs != -1) {
         ALOGE("setSuspend failed as STOP action is pending");
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     // Push the action to the queue.
@@ -977,12 +906,12 @@
         if (suspendStartTimeUs > currentSystemTimeUs) {
             ALOGE("setSuspend failed. %lld is larger than current system time %lld us",
                     (long long)suspendStartTimeUs, (long long)currentSystemTimeUs);
-            return Status::fromServiceSpecificError(INVALID_OPERATION);
+            return INVALID_OPERATION;
         }
         if (mLastActionTimeUs != -1 && suspendStartTimeUs < mLastActionTimeUs) {
             ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
                     (long long)suspendStartTimeUs, (long long)mLastActionTimeUs);
-            return Status::fromServiceSpecificError(INVALID_OPERATION);
+            return INVALID_OPERATION;
         }
         mLastActionTimeUs = suspendStartTimeUs;
         ActionItem action;
@@ -1007,7 +936,7 @@
 
                 releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
             }
-            return Status::ok();
+            return OK;
         } else {
 
             mSuspended = false;
@@ -1023,54 +952,54 @@
             }
         }
     }
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) {
+status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) {
     ALOGV("setRepeatPreviousFrameDelayUs: delayUs=%lld", (long long)repeatAfterUs);
 
     Mutex::Autolock autoLock(mMutex);
 
     if (mExecuting || repeatAfterUs <= 0ll) {
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     mRepeatAfterUs = repeatAfterUs;
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
+status_t GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
     Mutex::Autolock autoLock(mMutex);
 
     // timeOffsetUs must be negative for adjustment.
     if (timeOffsetUs >= 0ll) {
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     mInputBufferTimeOffsetUs = timeOffsetUs;
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setMaxFps(float maxFps) {
+status_t GraphicBufferSource::setMaxFps(float maxFps) {
     ALOGV("setMaxFps: maxFps=%lld", (long long)maxFps);
 
     Mutex::Autolock autoLock(mMutex);
 
     if (mExecuting) {
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     mFrameDropper = new FrameDropper();
     status_t err = mFrameDropper->setMaxFrameRate(maxFps);
     if (err != OK) {
         mFrameDropper.clear();
-        return Status::fromServiceSpecificError(err);
+        return err;
     }
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setStartTimeUs(int64_t skipFramesBeforeUs) {
+status_t GraphicBufferSource::setStartTimeUs(int64_t skipFramesBeforeUs) {
     ALOGV("setStartTimeUs: skipFramesBeforeUs=%lld", (long long)skipFramesBeforeUs);
 
     Mutex::Autolock autoLock(mMutex);
@@ -1078,16 +1007,16 @@
     mSkipFramesBeforeNs =
             (skipFramesBeforeUs > 0) ? (skipFramesBeforeUs * 1000) : -1ll;
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
+status_t GraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
     ALOGV("setStopTimeUs: %lld us", (long long)stopTimeUs);
     Mutex::Autolock autoLock(mMutex);
 
     if (mStopTimeUs != -1) {
         // Ignore if stop time has already been set
-        return Status::ok();
+        return OK;
     }
 
     // stopTimeUs must be smaller or equal to current systemTime.
@@ -1095,12 +1024,12 @@
     if (stopTimeUs > currentSystemTimeUs) {
         ALOGE("setStopTimeUs failed. %lld is larger than current system time %lld us",
             (long long)stopTimeUs, (long long)currentSystemTimeUs);
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
     if (mLastActionTimeUs != -1 && stopTimeUs < mLastActionTimeUs) {
         ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
             (long long)stopTimeUs, (long long)mLastActionTimeUs);
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
     mLastActionTimeUs = stopTimeUs;
     ActionItem action;
@@ -1108,45 +1037,46 @@
     action.mActionTimeUs = stopTimeUs;
     mActionQueue.push_back(action);
     mStopTimeUs = stopTimeUs;
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) {
+status_t GraphicBufferSource::setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) {
     ALOGV("setTimeLapseConfig: timePerFrameUs=%lld, timePerCaptureUs=%lld",
             (long long)timePerFrameUs, (long long)timePerCaptureUs);
 
     Mutex::Autolock autoLock(mMutex);
 
     if (mExecuting || timePerFrameUs <= 0ll || timePerCaptureUs <= 0ll) {
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     mTimePerFrameUs = timePerFrameUs;
     mTimePerCaptureUs = timePerCaptureUs;
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setColorAspects(int32_t aspectsPacked) {
+status_t GraphicBufferSource::setColorAspects(int32_t aspectsPacked) {
     Mutex::Autolock autoLock(mMutex);
-    mColorAspects = ColorUtils::unpackToColorAspects(aspectsPacked);
+    mColorAspectsPacked = aspectsPacked;
+    ColorAspects colorAspects = ColorUtils::unpackToColorAspects(aspectsPacked);
     ALOGD("requesting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s))",
-            mColorAspects.mRange, asString(mColorAspects.mRange),
-            mColorAspects.mPrimaries, asString(mColorAspects.mPrimaries),
-            mColorAspects.mMatrixCoeffs, asString(mColorAspects.mMatrixCoeffs),
-            mColorAspects.mTransfer, asString(mColorAspects.mTransfer));
+            colorAspects.mRange, asString(colorAspects.mRange),
+            colorAspects.mPrimaries, asString(colorAspects.mPrimaries),
+            colorAspects.mMatrixCoeffs, asString(colorAspects.mMatrixCoeffs),
+            colorAspects.mTransfer, asString(colorAspects.mTransfer));
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::signalEndOfInputStream() {
+status_t GraphicBufferSource::signalEndOfInputStream() {
     Mutex::Autolock autoLock(mMutex);
     ALOGV("signalEndOfInputStream: exec=%d avail=%zu eos=%d",
             mExecuting, mNumFramesAvailable, mEndOfStream);
 
     if (mEndOfStream) {
         ALOGE("EOS was already signaled");
-        return Status::fromStatusT(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     // Set the end-of-stream flag.  If no frames are pending from the
@@ -1163,7 +1093,7 @@
         submitEndOfInputStream_l();
     }
 
-    return Status::ok();
+    return OK;
 }
 
 void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 475548e..371c5ed 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -32,6 +32,8 @@
 #include <android/BnGraphicBufferSource.h>
 #include <android/BnOMXBufferSource.h>
 
+#include "IOmxNodeWrapper.h"
+
 namespace android {
 
 using ::android::binder::Status;
@@ -54,8 +56,7 @@
  * before the codec is in the "executing" state, so we need to queue
  * things up until we're ready to go.
  */
-class GraphicBufferSource : public BnGraphicBufferSource,
-                            public BufferQueue::ConsumerListener {
+class GraphicBufferSource : public BufferQueue::ConsumerListener {
 public:
     GraphicBufferSource();
 
@@ -95,24 +96,30 @@
     // Called from OnEmptyBufferDone.  If we have a BQ buffer available,
     // fill it with a new frame of data; otherwise, just mark it as available.
     Status onInputBufferEmptied(
-            int32_t bufferID, const OMXFenceParcelable& fenceParcel);
+            int32_t bufferID, int fenceFd);
 
     // Configure the buffer source to be used with an OMX node with the default
     // data space.
-    Status configure(const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
+    status_t configure(
+        const sp<IOmxNodeWrapper> &omxNode,
+        int32_t dataSpace,
+        int32_t bufferCount,
+        uint32_t frameWidth,
+        uint32_t frameHeight,
+        uint32_t consumerUsage);
 
     // This is called after the last input frame has been submitted or buffer
     // timestamp is greater or equal than stopTimeUs. We need to submit an empty
     // buffer with the EOS flag set.  If we don't have a codec buffer ready,
     // we just set the mEndOfStream flag.
-    Status signalEndOfInputStream() override;
+    status_t signalEndOfInputStream();
 
     // If suspend is true, all incoming buffers (including those currently
     // in the BufferQueue) with timestamp larger than timeUs will be discarded
     // until the suspension is lifted. If suspend is false, all incoming buffers
     // including those currently in the BufferQueue) with timestamp larger than
     // timeUs will be processed. timeUs uses SYSTEM_TIME_MONOTONIC time base.
-    Status setSuspend(bool suspend, int64_t timeUs) override;
+    status_t setSuspend(bool suspend, int64_t timeUs);
 
     // Specifies the interval after which we requeue the buffer previously
     // queued to the encoder. This is useful in the case of surface flinger
@@ -121,30 +128,30 @@
     // the decoder on the remote end would be unable to decode the latest frame.
     // This API must be called before transitioning the encoder to "executing"
     // state and once this behaviour is specified it cannot be reset.
-    Status setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
+    status_t setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs);
 
     // Sets the input buffer timestamp offset.
     // When set, the sample's timestamp will be adjusted with the timeOffsetUs.
-    Status setTimeOffsetUs(int64_t timeOffsetUs) override;
+    status_t setTimeOffsetUs(int64_t timeOffsetUs);
 
     // When set, the max frame rate fed to the encoder will be capped at maxFps.
-    Status setMaxFps(float maxFps) override;
+    status_t setMaxFps(float maxFps);
 
     // Sets the time lapse (or slow motion) parameters.
     // When set, the sample's timestamp will be modified to playback framerate,
     // and capture timestamp will be modified to capture rate.
-    Status setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
+    status_t setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs);
 
     // Sets the start time us (in system time), samples before which should
     // be dropped and not submitted to encoder
-    Status setStartTimeUs(int64_t startTimeUs) override;
+    status_t setStartTimeUs(int64_t startTimeUs);
 
     // Sets the stop time us (in system time), samples after which should be dropped
     // and not submitted to encoder. timeUs uses SYSTEM_TIME_MONOTONIC time base.
-    Status setStopTimeUs(int64_t stopTimeUs) override;
+    status_t setStopTimeUs(int64_t stopTimeUs);
 
     // Sets the desired color aspects, e.g. to be used when producer does not specify a dataspace.
-    Status setColorAspects(int32_t aspectsPacked) override;
+    status_t setColorAspects(int32_t aspectsPacked);
 
 protected:
     // BufferQueue::ConsumerListener interface, called when a new frame of
@@ -229,8 +236,8 @@
     // Used to report constructor failure.
     status_t mInitCheck;
 
-    // Pointer back to the IOMXNode that created us.  We send buffers here.
-    sp<IOMXNode> mOMXNode;
+    // Pointer back to the Omx node that created us.  We send buffers here.
+    sp<IOmxNodeWrapper> mOMXNode;
 
     // Set by omxExecuting() / omxIdling().
     bool mExecuting;
@@ -328,10 +335,7 @@
 
     int64_t mInputBufferTimeOffsetUs;
 
-    ColorAspects mColorAspects;
-
-    class OmxBufferSource;
-    sp<OmxBufferSource> mOmxBufferSource;
+    int32_t mColorAspectsPacked;
 
     void onMessageReceived(const sp<AMessage> &msg);
 
diff --git a/media/libstagefright/omx/IOmxNodeWrapper.h b/media/libstagefright/omx/IOmxNodeWrapper.h
new file mode 100644
index 0000000..cd44e67
--- /dev/null
+++ b/media/libstagefright/omx/IOmxNodeWrapper.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IOMX_NODE_WRAPPER_SOURCE_H_
+#define IOMX_NODE_WRAPPER_SOURCE_H_
+
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+#include <ui/GraphicBuffer.h>
+
+#include <stdint.h>
+
+namespace android {
+
+struct IOmxNodeWrapper : public RefBase {
+    virtual status_t emptyBuffer(
+            int32_t bufferId, uint32_t flags,
+            const sp<GraphicBuffer> &buffer = nullptr,
+            int64_t timestamp = 0, int fenceFd = -1) = 0;
+    virtual void dispatchDataSpaceChanged(
+            int32_t dataSpace, int32_t aspects, int32_t pixelFormat) = 0;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_WGRAPHICBUFFERSOURCE_H
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 80c125c..bf1418f 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -27,7 +27,7 @@
 #include "../include/OMXNodeInstance.h"
 
 #include <media/stagefright/foundation/ADebug.h>
-#include "GraphicBufferSource.h"
+#include "BWGraphicBufferSource.h"
 
 #include "OMXMaster.h"
 #include "OMXUtils.h"
@@ -174,7 +174,7 @@
     }
 
     *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
-    *bufferSource = graphicBufferSource;
+    *bufferSource = new BWGraphicBufferSource(graphicBufferSource);
 
     return OK;
 }
diff --git a/media/libstagefright/omx/hal/1.0/impl/Android.mk b/media/libstagefright/omx/hal/1.0/impl/Android.mk
index 09424b5..79cb1fa 100644
--- a/media/libstagefright/omx/hal/1.0/impl/Android.mk
+++ b/media/libstagefright/omx/hal/1.0/impl/Android.mk
@@ -4,7 +4,6 @@
 LOCAL_MODULE := android.hardware.media.omx@1.0-impl
 LOCAL_SRC_FILES := \
     WGraphicBufferSource.cpp \
-    WOmx.cpp \
     WOmxBufferProducer.cpp \
     WOmxBufferSource.cpp \
     WOmxNode.cpp \
diff --git a/media/libstagefright/omx/hal/1.0/impl/Conversion.h b/media/libstagefright/omx/hal/1.0/impl/Conversion.h
index 117d1c8..a6fed2e 100644
--- a/media/libstagefright/omx/hal/1.0/impl/Conversion.h
+++ b/media/libstagefright/omx/hal/1.0/impl/Conversion.h
@@ -611,6 +611,37 @@
 }
 
 /**
+ * \brief Wrap `GraphicBuffer` in `CodecBuffer`.
+ *
+ * \param[out] t The wrapper of type `CodecBuffer`.
+ * \param[in] l The source `GraphicBuffer`.
+ */
+// wrap: OMXBuffer -> CodecBuffer
+inline CodecBuffer *wrapAs(CodecBuffer *t, sp<GraphicBuffer> const& graphicBuffer) {
+    t->sharedMemory = hidl_memory();
+    t->nativeHandle = hidl_handle();
+    t->type = CodecBuffer::Type::ANW_BUFFER;
+    if (graphicBuffer == nullptr) {
+        t->attr.anwBuffer.width = 0;
+        t->attr.anwBuffer.height = 0;
+        t->attr.anwBuffer.stride = 0;
+        t->attr.anwBuffer.format = static_cast<PixelFormat>(1);
+        t->attr.anwBuffer.layerCount = 0;
+        t->attr.anwBuffer.usage = 0;
+        return t;
+    }
+    t->attr.anwBuffer.width = graphicBuffer->getWidth();
+    t->attr.anwBuffer.height = graphicBuffer->getHeight();
+    t->attr.anwBuffer.stride = graphicBuffer->getStride();
+    t->attr.anwBuffer.format = static_cast<PixelFormat>(
+            graphicBuffer->getPixelFormat());
+    t->attr.anwBuffer.layerCount = graphicBuffer->getLayerCount();
+    t->attr.anwBuffer.usage = graphicBuffer->getUsage();
+    t->nativeHandle = graphicBuffer->handle;
+    return t;
+}
+
+/**
  * \brief Wrap `OMXBuffer` in `CodecBuffer`.
  *
  * \param[out] t The wrapper of type `CodecBuffer`.
@@ -642,24 +673,7 @@
             return false;
         }
         case OMXBuffer::kBufferTypeANWBuffer: {
-            t->type = CodecBuffer::Type::ANW_BUFFER;
-            if (l.mGraphicBuffer == nullptr) {
-                t->attr.anwBuffer.width = 0;
-                t->attr.anwBuffer.height = 0;
-                t->attr.anwBuffer.stride = 0;
-                t->attr.anwBuffer.format = static_cast<PixelFormat>(1);
-                t->attr.anwBuffer.layerCount = 0;
-                t->attr.anwBuffer.usage = 0;
-                return true;
-            }
-            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 = l.mGraphicBuffer->handle;
+            wrapAs(t, l.mGraphicBuffer);
             return true;
         }
         case OMXBuffer::kBufferTypeNativeHandle: {
diff --git a/media/libstagefright/omx/hal/1.0/impl/Omx.cpp b/media/libstagefright/omx/hal/1.0/impl/Omx.cpp
index a9f29e9..0ef7c8c 100644
--- a/media/libstagefright/omx/hal/1.0/impl/Omx.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/Omx.cpp
@@ -123,7 +123,6 @@
 
 Return<void> Omx::createInputSurface(createInputSurface_cb _hidl_cb) {
     sp<::android::IGraphicBufferProducer> bufferProducer;
-    sp<::android::IGraphicBufferSource> bufferSource;
 
     sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
     status_t err = graphicBufferSource->initCheck();
@@ -135,11 +134,10 @@
         return Void();
     }
     bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
-    bufferSource = graphicBufferSource;
 
     _hidl_cb(toStatus(OK),
             new TWOmxBufferProducer(bufferProducer),
-            new TWGraphicBufferSource(bufferSource));
+            new TWGraphicBufferSource(graphicBufferSource));
     return Void();
 }
 
diff --git a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
index 884e87b..3c2face 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
@@ -14,8 +14,15 @@
  * limitations under the License.
  */
 
-#include <stagefright/foundation/ColorUtils.h>
+//#define LOG_NDEBUG 0
+#define LOG_TAG "TWGraphicBufferSource"
 
+#include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
+#include <android/hardware/media/omx/1.0/IOmxNode.h>
+#include <OMX_Component.h>
+#include <OMX_IndexExt.h>
+
+#include "omx/OMXUtils.h"
 #include "WGraphicBufferSource.h"
 #include "WOmxNode.h"
 #include "Conversion.h"
@@ -27,122 +34,187 @@
 namespace V1_0 {
 namespace implementation {
 
-using android::ColorUtils;
+static const OMX_U32 kPortIndexInput = 0;
 
-// LWGraphicBufferSource
-LWGraphicBufferSource::LWGraphicBufferSource(
-        sp<TGraphicBufferSource> const& base) : mBase(base) {
-}
+struct TWGraphicBufferSource::TWOmxNodeWrapper : public IOmxNodeWrapper {
+    sp<IOmxNode> mOmxNode;
 
-::android::binder::Status LWGraphicBufferSource::configure(
-        const sp<IOMXNode>& omxNode, int32_t dataSpace) {
-    return toBinderStatus(mBase->configure(
-            new TWOmxNode(omxNode), toHardwareDataspace(dataSpace)));
-}
+    TWOmxNodeWrapper(const sp<IOmxNode> &omxNode): mOmxNode(omxNode) {
+    }
 
-::android::binder::Status LWGraphicBufferSource::setSuspend(
-        bool suspend, int64_t timeUs) {
-    return toBinderStatus(mBase->setSuspend(suspend, timeUs));
-}
+    virtual status_t emptyBuffer(
+            int32_t bufferId, uint32_t flags,
+            const sp<GraphicBuffer> &buffer,
+            int64_t timestamp, int fenceFd) override {
+        CodecBuffer tBuffer;
+        native_handle_t* fenceNh = native_handle_create_from_fd(fenceFd);
+        status_t err = toStatusT(mOmxNode->emptyBuffer(
+              bufferId,
+              *wrapAs(&tBuffer, buffer),
+              flags,
+              toRawTicks(timestamp),
+              fenceNh));
+        native_handle_close(fenceNh);
+        native_handle_delete(fenceNh);
+        return err;
+    }
 
-::android::binder::Status LWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
-        int64_t repeatAfterUs) {
-    return toBinderStatus(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
-}
+    virtual void dispatchDataSpaceChanged(
+            int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
+        Message tMsg;
+        tMsg.type = Message::Type::EVENT;
+        tMsg.fence = native_handle_create(0, 0);
+        tMsg.data.eventData.event = uint32_t(OMX_EventDataSpaceChanged);
+        tMsg.data.eventData.data1 = dataSpace;
+        tMsg.data.eventData.data2 = aspects;
+        tMsg.data.eventData.data3 = pixelFormat;
+        mOmxNode->dispatchMessage(tMsg);
+    }
+};
 
-::android::binder::Status LWGraphicBufferSource::setMaxFps(float maxFps) {
-    return toBinderStatus(mBase->setMaxFps(maxFps));
-}
+struct TWGraphicBufferSource::TWOmxBufferSource : public IOmxBufferSource {
+    sp<GraphicBufferSource> mSource;
 
-::android::binder::Status LWGraphicBufferSource::setTimeLapseConfig(
-        int64_t timePerFrameUs, int64_t timePerCaptureUs) {
-    return toBinderStatus(mBase->setTimeLapseConfig(
-            timePerFrameUs, timePerCaptureUs));
-}
+    TWOmxBufferSource(const sp<GraphicBufferSource> &source): mSource(source) {
+    }
 
-::android::binder::Status LWGraphicBufferSource::setStartTimeUs(
-        int64_t startTimeUs) {
-    return toBinderStatus(mBase->setStartTimeUs(startTimeUs));
-}
+    Return<void> onOmxExecuting() override {
+        mSource->onOmxExecuting();
+        return Void();
+    }
 
-::android::binder::Status LWGraphicBufferSource::setStopTimeUs(
-        int64_t stopTimeUs) {
-    return toBinderStatus(mBase->setStopTimeUs(stopTimeUs));
-}
+    Return<void> onOmxIdle() override {
+        mSource->onOmxIdle();
+        return Void();
+    }
 
-::android::binder::Status LWGraphicBufferSource::setColorAspects(
-        int32_t aspects) {
-    return toBinderStatus(mBase->setColorAspects(
-            toHardwareColorAspects(aspects)));
-}
+    Return<void> onOmxLoaded() override {
+        mSource->onOmxLoaded();
+        return Void();
+    }
 
-::android::binder::Status LWGraphicBufferSource::setTimeOffsetUs(
-        int64_t timeOffsetsUs) {
-    return toBinderStatus(mBase->setTimeOffsetUs(timeOffsetsUs));
-}
+    Return<void> onInputBufferAdded(uint32_t bufferId) override {
+        mSource->onInputBufferAdded(static_cast<int32_t>(bufferId));
+        return Void();
+    }
 
-::android::binder::Status LWGraphicBufferSource::signalEndOfInputStream() {
-    return toBinderStatus(mBase->signalEndOfInputStream());
-}
+    Return<void> onInputBufferEmptied(
+            uint32_t bufferId, hidl_handle const& tFence) override {
+        mSource->onInputBufferEmptied(
+                static_cast<int32_t>(bufferId),
+                native_handle_read_fd(tFence));
+        return Void();
+    }
+};
 
 // TWGraphicBufferSource
 TWGraphicBufferSource::TWGraphicBufferSource(
-        sp<LGraphicBufferSource> const& base) : mBase(base) {
+        sp<GraphicBufferSource> const& base) :
+    mBase(base),
+    mOmxBufferSource(new TWOmxBufferSource(base)) {
 }
 
-Return<void> TWGraphicBufferSource::configure(
+Return<Status> TWGraphicBufferSource::configure(
         const sp<IOmxNode>& omxNode, Dataspace dataspace) {
-    mBase->configure(new LWOmxNode(omxNode), toRawDataspace(dataspace));
-    return Void();
+    if (omxNode == NULL) {
+        return toStatus(BAD_VALUE);
+    }
+
+    // Do setInputSurface() first, the node will try to enable metadata
+    // mode on input, and does necessary error checking. If this fails,
+    // we can't use this input surface on the node.
+    Return<Status> err(omxNode->setInputSurface(mOmxBufferSource));
+    status_t fnStatus = toStatusT(err);
+    if (fnStatus != NO_ERROR) {
+        ALOGE("Unable to set input surface: %d", fnStatus);
+        return err;
+    }
+
+    // use consumer usage bits queried from encoder, but always add
+    // HW_VIDEO_ENCODER for backward compatibility.
+    uint32_t  consumerUsage;
+    void *_params = &consumerUsage;
+    uint8_t *params = static_cast<uint8_t*>(_params);
+    fnStatus = UNKNOWN_ERROR;
+    IOmxNode::getParameter_cb _hidl_cb(
+            [&fnStatus, &params](Status status, hidl_vec<uint8_t> const& outParams) {
+                fnStatus = toStatusT(status);
+                std::copy(
+                        outParams.data(),
+                        outParams.data() + outParams.size(),
+                        params);
+            });
+    omxNode->getParameter(
+            static_cast<uint32_t>(OMX_IndexParamConsumerUsageBits),
+            inHidlBytes(&consumerUsage, sizeof(consumerUsage)),
+            _hidl_cb);
+    if (fnStatus != OK) {
+        consumerUsage = 0;
+    }
+
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexInput;
+
+    _params = &def;
+    params = static_cast<uint8_t*>(_params);
+    omxNode->getParameter(
+            static_cast<uint32_t>(OMX_IndexParamPortDefinition),
+            inHidlBytes(&def, sizeof(def)),
+            _hidl_cb);
+    if (fnStatus != NO_ERROR) {
+        ALOGE("Failed to get port definition: %d", fnStatus);
+        return toStatus(fnStatus);
+    }
+
+
+    return toStatus(mBase->configure(
+            new TWOmxNodeWrapper(omxNode),
+            toRawDataspace(dataspace),
+            def.nBufferCountActual,
+            def.format.video.nFrameWidth,
+            def.format.video.nFrameHeight,
+            consumerUsage));
 }
 
-Return<void> TWGraphicBufferSource::setSuspend(
+Return<Status> TWGraphicBufferSource::setSuspend(
         bool suspend, int64_t timeUs) {
-    mBase->setSuspend(suspend, timeUs);
-    return Void();
+    return toStatus(mBase->setSuspend(suspend, timeUs));
 }
 
-Return<void> TWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
+Return<Status> TWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
         int64_t repeatAfterUs) {
-    mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs);
-    return Void();
+    return toStatus(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
 }
 
-Return<void> TWGraphicBufferSource::setMaxFps(float maxFps) {
-    mBase->setMaxFps(maxFps);
-    return Void();
+Return<Status> TWGraphicBufferSource::setMaxFps(float maxFps) {
+    return toStatus(mBase->setMaxFps(maxFps));
 }
 
-Return<void> TWGraphicBufferSource::setTimeLapseConfig(
+Return<Status> TWGraphicBufferSource::setTimeLapseConfig(
         int64_t timePerFrameUs, int64_t timePerCaptureUs) {
-    mBase->setTimeLapseConfig(timePerFrameUs, timePerCaptureUs);
-    return Void();
+    return toStatus(mBase->setTimeLapseConfig(timePerFrameUs, timePerCaptureUs));
 }
 
-Return<void> TWGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
-    mBase->setStartTimeUs(startTimeUs);
-    return Void();
+Return<Status> TWGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
+    return toStatus(mBase->setStartTimeUs(startTimeUs));
 }
 
-Return<void> TWGraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
-    mBase->setStopTimeUs(stopTimeUs);
-    return Void();
+Return<Status> TWGraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
+    return toStatus(mBase->setStopTimeUs(stopTimeUs));
 }
 
-Return<void> TWGraphicBufferSource::setColorAspects(
+Return<Status> TWGraphicBufferSource::setColorAspects(
         const ColorAspects& aspects) {
-    mBase->setColorAspects(toCompactColorAspects(aspects));
-    return Void();
+    return toStatus(mBase->setColorAspects(toCompactColorAspects(aspects)));
 }
 
-Return<void> TWGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
-    mBase->setTimeOffsetUs(timeOffsetUs);
-    return Void();
+Return<Status> TWGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
+    return toStatus(mBase->setTimeOffsetUs(timeOffsetUs));
 }
 
-Return<void> TWGraphicBufferSource::signalEndOfInputStream() {
-    mBase->signalEndOfInputStream();
-    return Void();
+Return<Status> TWGraphicBufferSource::signalEndOfInputStream() {
+    return toStatus(mBase->signalEndOfInputStream());
 }
 
 }  // namespace implementation
diff --git a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h
index bd60c46..8cf11ca 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h
+++ b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h
@@ -20,15 +20,16 @@
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
-#include <media/IOMX.h>
-#include <binder/Binder.h>
-
+#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
+#include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <android/hardware/graphics/common/1.0/types.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
 
 #include <android/BnGraphicBufferSource.h>
 
+#include "../../../GraphicBufferSource.h"
+
 namespace android {
 namespace hardware {
 namespace media {
@@ -36,10 +37,12 @@
 namespace V1_0 {
 namespace implementation {
 
+using ::android::GraphicBufferSource;
 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::hidl::base::V1_0::IBase;
 using ::android::hardware::hidl_array;
 using ::android::hardware::hidl_memory;
@@ -60,44 +63,28 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-typedef ::android::IGraphicBufferSource LGraphicBufferSource;
-typedef ::android::BnGraphicBufferSource BnGraphicBufferSource;
 typedef ::android::hardware::media::omx::V1_0::IGraphicBufferSource
         TGraphicBufferSource;
 
-struct LWGraphicBufferSource : public BnGraphicBufferSource {
-    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, int64_t timeUs) 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 setStopTimeUs(int64_t stopTimeUs) override;
-    ::android::binder::Status setColorAspects(int32_t aspects) override;
-    ::android::binder::Status setTimeOffsetUs(int64_t timeOffsetsUs) override;
-    ::android::binder::Status signalEndOfInputStream() override;
-};
-
 struct TWGraphicBufferSource : public TGraphicBufferSource {
-    sp<LGraphicBufferSource> mBase;
-    TWGraphicBufferSource(sp<LGraphicBufferSource> const& base);
-    Return<void> configure(
+    struct TWOmxNodeWrapper;
+    struct TWOmxBufferSource;
+    sp<GraphicBufferSource> mBase;
+    sp<IOmxBufferSource> mOmxBufferSource;
+
+    TWGraphicBufferSource(sp<GraphicBufferSource> const& base);
+    Return<Status> configure(
             const sp<IOmxNode>& omxNode, Dataspace dataspace) override;
-    Return<void> setSuspend(bool suspend, int64_t timeUs) override;
-    Return<void> setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
-    Return<void> setMaxFps(float maxFps) override;
-    Return<void> setTimeLapseConfig(
+    Return<Status> setSuspend(bool suspend, int64_t timeUs) 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<void> setStartTimeUs(int64_t startTimeUs) override;
-    Return<void> setStopTimeUs(int64_t stopTimeUs) override;
-    Return<void> setColorAspects(const ColorAspects& aspects) override;
-    Return<void> setTimeOffsetUs(int64_t timeOffsetUs) override;
-    Return<void> signalEndOfInputStream() override;
+    Return<Status> setStartTimeUs(int64_t startTimeUs) override;
+    Return<Status> setStopTimeUs(int64_t stopTimeUs) override;
+    Return<Status> setColorAspects(const ColorAspects& aspects) override;
+    Return<Status> setTimeOffsetUs(int64_t timeOffsetUs) override;
+    Return<Status> signalEndOfInputStream() override;
 };
 
 }  // namespace implementation
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmx.cpp b/media/libstagefright/omx/hal/1.0/impl/WOmx.cpp
deleted file mode 100644
index da1c23d..0000000
--- a/media/libstagefright/omx/hal/1.0/impl/WOmx.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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 "WOmx.h"
-#include "WOmxNode.h"
-#include "WOmxObserver.h"
-#include "WOmxBufferProducer.h"
-#include "WGraphicBufferSource.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) {
-    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 implementation
-}  // namespace V1_0
-}  // namespace omx
-}  // namespace media
-}  // namespace hardware
-}  // namespace android
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmx.h b/media/libstagefright/omx/hal/1.0/impl/WOmx.h
deleted file mode 100644
index 3cb002e..0000000
--- a/media/libstagefright/omx/hal/1.0/impl/WOmx.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMX_H
-#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMX_H
-
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-#include "../../../../include/OMXNodeInstance.h"
-
-#include <android/hardware/media/omx/1.0/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;
-using ::android::BnOMX;
-
-/**
- * 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 BnOMX {
-    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;
-};
-
-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;
-    Return<void> createInputSurface(createInputSurface_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/ndk/Android.mk b/media/ndk/Android.mk
index 74729e4..67b0ab1 100644
--- a/media/ndk/Android.mk
+++ b/media/ndk/Android.mk
@@ -34,9 +34,12 @@
 
 LOCAL_C_INCLUDES := \
     bionic/libc/private \
+    external/piex \
     frameworks/base/core/jni \
+    frameworks/base/media/jni \
     frameworks/av/include/ndk \
-    system/media/camera/include
+    system/media/camera/include \
+    $(call include-path-for, libhardware)/hardware \
 
 LOCAL_CFLAGS += -fvisibility=hidden -D EXPORT='__attribute__ ((visibility ("default")))'
 
@@ -45,7 +48,9 @@
 LOCAL_SHARED_LIBRARIES := \
     libbinder \
     libmedia \
+    libmedia_jni \
     libmediadrm \
+    libskia \
     libstagefright \
     libstagefright_foundation \
     liblog \
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index 40900ad..6c9a644 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -22,6 +22,8 @@
 #include "NdkImagePriv.h"
 #include "NdkImageReaderPriv.h"
 
+#include <android_media_Utils.h>
+#include <android_runtime/android_hardware_HardwareBuffer.h>
 #include <utils/Log.h>
 #include "hardware/camera3.h"
 
@@ -29,11 +31,11 @@
 
 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
 
-AImage::AImage(AImageReader* reader, int32_t format,
-        CpuConsumer::LockedBuffer* buffer, int64_t timestamp,
+AImage::AImage(AImageReader* reader, int32_t format, uint64_t usage,
+        BufferItem* buffer, int64_t timestamp,
         int32_t width, int32_t height, int32_t numPlanes) :
-        mReader(reader), mFormat(format),
-        mBuffer(buffer), mTimestamp(timestamp),
+        mReader(reader), mFormat(format), mUsage(usage),
+        mBuffer(buffer), mLockedBuffer(nullptr), mTimestamp(timestamp),
         mWidth(width), mHeight(height), mNumPlanes(numPlanes) {
 }
 
@@ -66,6 +68,7 @@
     // Should have been set to nullptr in releaseImageLocked
     // Set to nullptr here for extra safety only
     mBuffer = nullptr;
+    mLockedBuffer = nullptr;
     mIsClosed = true;
 }
 
@@ -169,8 +172,80 @@
     return AMEDIA_OK;
 }
 
+media_status_t AImage::lockImage() {
+    if (mBuffer == nullptr || mBuffer->mGraphicBuffer == nullptr) {
+        LOG_ALWAYS_FATAL("%s: AImage %p has no buffer.", __FUNCTION__, this);
+        return AMEDIA_ERROR_INVALID_OBJECT;
+    }
+
+    if ((mUsage & AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN) == 0) {
+        ALOGE("%s: AImage %p does not have any software read usage bits set, usage=%" PRIu64 "",
+              __FUNCTION__, this, mUsage);
+        return AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE;
+    }
+
+    if (mLockedBuffer != nullptr) {
+        // Return immediately if the image has already been locked.
+        return AMEDIA_OK;
+    }
+
+    auto lockedBuffer = std::make_unique<CpuConsumer::LockedBuffer>();
+
+    uint64_t producerUsage;
+    uint64_t consumerUsage;
+    android_hardware_HardwareBuffer_convertToGrallocUsageBits(
+            &producerUsage, &consumerUsage, mUsage, 0);
+
+    status_t ret =
+            lockImageFromBuffer(mBuffer, consumerUsage, mBuffer->mFence->dup(), lockedBuffer.get());
+    if (ret != OK) {
+        ALOGE("%s: AImage %p failed to lock, error=%d", __FUNCTION__, this, ret);
+        return AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE;
+    }
+
+    ALOGV("%s: Successfully locked the image %p.", __FUNCTION__, this);
+    mLockedBuffer = std::move(lockedBuffer);
+
+    return AMEDIA_OK;
+}
+
+media_status_t AImage::unlockImageIfLocked(int* fenceFd) {
+    if (fenceFd == nullptr) {
+        LOG_ALWAYS_FATAL("%s: fenceFd cannot be null.", __FUNCTION__);
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+
+    if (mBuffer == nullptr || mBuffer->mGraphicBuffer == nullptr) {
+        LOG_ALWAYS_FATAL("%s: AImage %p has no buffer.", __FUNCTION__, this);
+        return AMEDIA_ERROR_INVALID_OBJECT;
+    }
+
+    if (mLockedBuffer == nullptr) {
+        // This image hasn't been locked yet, no need to unlock.
+        *fenceFd = -1;
+        return AMEDIA_OK;
+    }
+
+    // No fence by default.
+    int releaseFenceFd = -1;
+    status_t res = mBuffer->mGraphicBuffer->unlockAsync(&releaseFenceFd);
+    if (res != OK) {
+        ALOGE("%s unlock buffer failed on iamge %p.", __FUNCTION__, this);
+        *fenceFd = -1;
+        return AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE;
+    }
+
+    *fenceFd = releaseFenceFd;
+    return AMEDIA_OK;
+}
+
 media_status_t
 AImage::getPlanePixelStride(int planeIdx, /*out*/int32_t* pixelStride) const {
+    if (mLockedBuffer == nullptr) {
+        ALOGE("%s: buffer not locked.", __FUNCTION__);
+        return AMEDIA_IMGREADER_IMAGE_NOT_LOCKED;
+    }
+
     if (planeIdx < 0 || planeIdx >= mNumPlanes) {
         ALOGE("Error: planeIdx %d out of bound [0,%d]",
                 planeIdx, mNumPlanes - 1);
@@ -183,10 +258,10 @@
         ALOGE("%s: image %p has been closed!", __FUNCTION__, this);
         return AMEDIA_ERROR_INVALID_OBJECT;
     }
-    int32_t fmt = mBuffer->flexFormat;
+    int32_t fmt = mLockedBuffer->flexFormat;
     switch (fmt) {
         case HAL_PIXEL_FORMAT_YCbCr_420_888:
-            *pixelStride = (planeIdx == 0) ? 1 : mBuffer->chromaStep;
+            *pixelStride = (planeIdx == 0) ? 1 : mLockedBuffer->chromaStep;
             return AMEDIA_OK;
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
             *pixelStride = (planeIdx == 0) ? 1 : 2;
@@ -226,6 +301,11 @@
 
 media_status_t
 AImage::getPlaneRowStride(int planeIdx, /*out*/int32_t* rowStride) const {
+    if (mLockedBuffer == nullptr) {
+        ALOGE("%s: buffer not locked.", __FUNCTION__);
+        return AMEDIA_IMGREADER_IMAGE_NOT_LOCKED;
+    }
+
     if (planeIdx < 0 || planeIdx >= mNumPlanes) {
         ALOGE("Error: planeIdx %d out of bound [0,%d]",
                 planeIdx, mNumPlanes - 1);
@@ -238,54 +318,58 @@
         ALOGE("%s: image %p has been closed!", __FUNCTION__, this);
         return AMEDIA_ERROR_INVALID_OBJECT;
     }
-    int32_t fmt = mBuffer->flexFormat;
+    int32_t fmt = mLockedBuffer->flexFormat;
     switch (fmt) {
         case HAL_PIXEL_FORMAT_YCbCr_420_888:
-            *rowStride = (planeIdx == 0) ? mBuffer->stride : mBuffer->chromaStride;
+            *rowStride = (planeIdx == 0) ? mLockedBuffer->stride
+                                         : mLockedBuffer->chromaStride;
             return AMEDIA_OK;
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-            *rowStride = mBuffer->width;
+            *rowStride = mLockedBuffer->width;
             return AMEDIA_OK;
         case HAL_PIXEL_FORMAT_YV12:
-            if (mBuffer->stride % 16) {
-                ALOGE("Stride %d is not 16 pixel aligned!", mBuffer->stride);
+            if (mLockedBuffer->stride % 16) {
+                ALOGE("Stride %d is not 16 pixel aligned!", mLockedBuffer->stride);
                 return AMEDIA_ERROR_UNKNOWN;
             }
-            *rowStride = (planeIdx == 0) ? mBuffer->stride : ALIGN(mBuffer->stride / 2, 16);
+            *rowStride = (planeIdx == 0) ? mLockedBuffer->stride
+                                         : ALIGN(mLockedBuffer->stride / 2, 16);
             return AMEDIA_OK;
         case HAL_PIXEL_FORMAT_RAW10:
         case HAL_PIXEL_FORMAT_RAW12:
             // RAW10 and RAW12 are used for 10-bit and 12-bit raw data, they are single plane
-            *rowStride = mBuffer->stride;
+            *rowStride = mLockedBuffer->stride;
             return AMEDIA_OK;
         case HAL_PIXEL_FORMAT_Y8:
-            if (mBuffer->stride % 16) {
-                ALOGE("Stride %d is not 16 pixel aligned!", mBuffer->stride);
+            if (mLockedBuffer->stride % 16) {
+                ALOGE("Stride %d is not 16 pixel aligned!",
+                      mLockedBuffer->stride);
                 return AMEDIA_ERROR_UNKNOWN;
             }
-            *rowStride = mBuffer->stride;
+            *rowStride = mLockedBuffer->stride;
             return AMEDIA_OK;
         case HAL_PIXEL_FORMAT_Y16:
         case HAL_PIXEL_FORMAT_RAW16:
             // In native side, strides are specified in pixels, not in bytes.
             // Single plane 16bpp bayer data. even width/height,
             // row stride multiple of 16 pixels (32 bytes)
-            if (mBuffer->stride % 16) {
-                ALOGE("Stride %d is not 16 pixel aligned!", mBuffer->stride);
+            if (mLockedBuffer->stride % 16) {
+                ALOGE("Stride %d is not 16 pixel aligned!",
+                      mLockedBuffer->stride);
                 return AMEDIA_ERROR_UNKNOWN;
             }
-            *rowStride = mBuffer->stride * 2;
+            *rowStride = mLockedBuffer->stride * 2;
             return AMEDIA_OK;
         case HAL_PIXEL_FORMAT_RGB_565:
-            *rowStride = mBuffer->stride * 2;
+            *rowStride = mLockedBuffer->stride * 2;
             return AMEDIA_OK;
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
-            *rowStride = mBuffer->stride * 4;
+            *rowStride = mLockedBuffer->stride * 4;
             return AMEDIA_OK;
         case HAL_PIXEL_FORMAT_RGB_888:
             // Single plane, 24bpp.
-            *rowStride = mBuffer->stride * 3;
+            *rowStride = mLockedBuffer->stride * 3;
             return AMEDIA_OK;
         case HAL_PIXEL_FORMAT_BLOB:
         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
@@ -300,13 +384,13 @@
 
 uint32_t
 AImage::getJpegSize() const {
-    if (mBuffer == nullptr) {
+    if (mLockedBuffer == nullptr) {
         LOG_ALWAYS_FATAL("Error: buffer is null");
     }
 
     uint32_t size = 0;
-    uint32_t width = mBuffer->width;
-    uint8_t* jpegBuffer = mBuffer->data;
+    uint32_t width = mLockedBuffer->width;
+    uint8_t* jpegBuffer = mLockedBuffer->data;
 
     // First check for JPEG transport header at the end of the buffer
     uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob));
@@ -334,6 +418,11 @@
 
 media_status_t
 AImage::getPlaneData(int planeIdx,/*out*/uint8_t** data, /*out*/int* dataLength) const {
+    if (mLockedBuffer == nullptr) {
+        ALOGE("%s: buffer not locked.", __FUNCTION__);
+        return AMEDIA_IMGREADER_IMAGE_NOT_LOCKED;
+    }
+
     if (planeIdx < 0 || planeIdx >= mNumPlanes) {
         ALOGE("Error: planeIdx %d out of bound [0,%d]",
                 planeIdx, mNumPlanes - 1);
@@ -352,140 +441,154 @@
     uint8_t* cr = nullptr;
     uint8_t* pData = nullptr;
     int bytesPerPixel = 0;
-    int32_t fmt = mBuffer->flexFormat;
+    int32_t fmt = mLockedBuffer->flexFormat;
 
     switch (fmt) {
         case HAL_PIXEL_FORMAT_YCbCr_420_888:
-            pData = (planeIdx == 0) ? mBuffer->data :
-                    (planeIdx == 1) ? mBuffer->dataCb : mBuffer->dataCr;
+            pData = (planeIdx == 0) ? mLockedBuffer->data
+                                    : (planeIdx == 1) ? mLockedBuffer->dataCb
+                                                      : mLockedBuffer->dataCr;
             // only map until last pixel
             if (planeIdx == 0) {
-                dataSize = mBuffer->stride * (mBuffer->height - 1) + mBuffer->width;
+                dataSize = mLockedBuffer->stride * (mLockedBuffer->height - 1) +
+                           mLockedBuffer->width;
             } else {
-                dataSize = mBuffer->chromaStride * (mBuffer->height / 2 - 1) +
-                        mBuffer->chromaStep * (mBuffer->width / 2 - 1) + 1;
+                dataSize =
+                    mLockedBuffer->chromaStride *
+                        (mLockedBuffer->height / 2 - 1) +
+                    mLockedBuffer->chromaStep * (mLockedBuffer->width / 2 - 1) +
+                    1;
             }
             break;
         // NV21
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-            cr = mBuffer->data + (mBuffer->stride * mBuffer->height);
+            cr = mLockedBuffer->data +
+                 (mLockedBuffer->stride * mLockedBuffer->height);
             cb = cr + 1;
             // only map until last pixel
-            ySize = mBuffer->width * (mBuffer->height - 1) + mBuffer->width;
-            cSize = mBuffer->width * (mBuffer->height / 2 - 1) + mBuffer->width - 1;
-
-            pData = (planeIdx == 0) ? mBuffer->data :
-                    (planeIdx == 1) ? cb : cr;
+            ySize = mLockedBuffer->width * (mLockedBuffer->height - 1) +
+                    mLockedBuffer->width;
+            cSize = mLockedBuffer->width * (mLockedBuffer->height / 2 - 1) +
+                    mLockedBuffer->width - 1;
+            pData = (planeIdx == 0) ? mLockedBuffer->data
+                                    : (planeIdx == 1) ? cb : cr;
             dataSize = (planeIdx == 0) ? ySize : cSize;
             break;
         case HAL_PIXEL_FORMAT_YV12:
             // Y and C stride need to be 16 pixel aligned.
-            if (mBuffer->stride % 16) {
-                ALOGE("Stride %d is not 16 pixel aligned!", mBuffer->stride);
+            if (mLockedBuffer->stride % 16) {
+                ALOGE("Stride %d is not 16 pixel aligned!",
+                      mLockedBuffer->stride);
                 return AMEDIA_ERROR_UNKNOWN;
             }
 
-            ySize = mBuffer->stride * mBuffer->height;
-            cStride = ALIGN(mBuffer->stride / 2, 16);
-            cr = mBuffer->data + ySize;
-            cSize = cStride * mBuffer->height / 2;
+            ySize = mLockedBuffer->stride * mLockedBuffer->height;
+            cStride = ALIGN(mLockedBuffer->stride / 2, 16);
+            cr = mLockedBuffer->data + ySize;
+            cSize = cStride * mLockedBuffer->height / 2;
             cb = cr + cSize;
 
-            pData = (planeIdx == 0) ? mBuffer->data :
-                    (planeIdx == 1) ? cb : cr;
+            pData = (planeIdx == 0) ? mLockedBuffer->data
+                                    : (planeIdx == 1) ? cb : cr;
             dataSize = (planeIdx == 0) ? ySize : cSize;
             break;
         case HAL_PIXEL_FORMAT_Y8:
             // Single plane, 8bpp.
 
-            pData = mBuffer->data;
-            dataSize = mBuffer->stride * mBuffer->height;
+            pData = mLockedBuffer->data;
+            dataSize = mLockedBuffer->stride * mLockedBuffer->height;
             break;
         case HAL_PIXEL_FORMAT_Y16:
             bytesPerPixel = 2;
 
-            pData = mBuffer->data;
-            dataSize = mBuffer->stride * mBuffer->height * bytesPerPixel;
+            pData = mLockedBuffer->data;
+            dataSize =
+                mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel;
             break;
         case HAL_PIXEL_FORMAT_BLOB:
             // Used for JPEG data, height must be 1, width == size, single plane.
-            if (mBuffer->height != 1) {
-                ALOGE("Jpeg should have height value one but got %d", mBuffer->height);
+            if (mLockedBuffer->height != 1) {
+                ALOGE("Jpeg should have height value one but got %d",
+                      mLockedBuffer->height);
                 return AMEDIA_ERROR_UNKNOWN;
             }
 
-            pData = mBuffer->data;
+            pData = mLockedBuffer->data;
             dataSize = getJpegSize();
             break;
         case HAL_PIXEL_FORMAT_RAW16:
             // Single plane 16bpp bayer data.
             bytesPerPixel = 2;
-            pData = mBuffer->data;
-            dataSize = mBuffer->stride * mBuffer->height * bytesPerPixel;
+            pData = mLockedBuffer->data;
+            dataSize =
+                mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel;
             break;
         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
             // Used for RAW_OPAQUE data, height must be 1, width == size, single plane.
-            if (mBuffer->height != 1) {
-                ALOGE("RAW_OPAQUE should have height value one but got %d", mBuffer->height);
+            if (mLockedBuffer->height != 1) {
+                ALOGE("RAW_OPAQUE should have height value one but got %d",
+                      mLockedBuffer->height);
                 return AMEDIA_ERROR_UNKNOWN;
             }
-            pData = mBuffer->data;
-            dataSize = mBuffer->width;
+            pData = mLockedBuffer->data;
+            dataSize = mLockedBuffer->width;
             break;
         case HAL_PIXEL_FORMAT_RAW10:
             // Single plane 10bpp bayer data.
-            if (mBuffer->width % 4) {
-                ALOGE("Width is not multiple of 4 %d", mBuffer->width);
+            if (mLockedBuffer->width % 4) {
+                ALOGE("Width is not multiple of 4 %d", mLockedBuffer->width);
                 return AMEDIA_ERROR_UNKNOWN;
             }
-            if (mBuffer->height % 2) {
-                ALOGE("Height is not multiple of 2 %d", mBuffer->height);
+            if (mLockedBuffer->height % 2) {
+                ALOGE("Height is not multiple of 2 %d", mLockedBuffer->height);
                 return AMEDIA_ERROR_UNKNOWN;
             }
-            if (mBuffer->stride < (mBuffer->width * 10 / 8)) {
+            if (mLockedBuffer->stride < (mLockedBuffer->width * 10 / 8)) {
                 ALOGE("stride (%d) should be at least %d",
-                        mBuffer->stride, mBuffer->width * 10 / 8);
+                        mLockedBuffer->stride, mLockedBuffer->width * 10 / 8);
                 return AMEDIA_ERROR_UNKNOWN;
             }
-            pData = mBuffer->data;
-            dataSize = mBuffer->stride * mBuffer->height;
+            pData = mLockedBuffer->data;
+            dataSize = mLockedBuffer->stride * mLockedBuffer->height;
             break;
         case HAL_PIXEL_FORMAT_RAW12:
             // Single plane 10bpp bayer data.
-            if (mBuffer->width % 4) {
-                ALOGE("Width is not multiple of 4 %d", mBuffer->width);
+            if (mLockedBuffer->width % 4) {
+                ALOGE("Width is not multiple of 4 %d", mLockedBuffer->width);
                 return AMEDIA_ERROR_UNKNOWN;
             }
-            if (mBuffer->height % 2) {
-                ALOGE("Height is not multiple of 2 %d", mBuffer->height);
+            if (mLockedBuffer->height % 2) {
+                ALOGE("Height is not multiple of 2 %d", mLockedBuffer->height);
                 return AMEDIA_ERROR_UNKNOWN;
             }
-            if (mBuffer->stride < (mBuffer->width * 12 / 8)) {
+            if (mLockedBuffer->stride < (mLockedBuffer->width * 12 / 8)) {
                 ALOGE("stride (%d) should be at least %d",
-                        mBuffer->stride, mBuffer->width * 12 / 8);
+                        mLockedBuffer->stride, mLockedBuffer->width * 12 / 8);
                 return AMEDIA_ERROR_UNKNOWN;
             }
-            pData = mBuffer->data;
-            dataSize = mBuffer->stride * mBuffer->height;
+            pData = mLockedBuffer->data;
+            dataSize = mLockedBuffer->stride * mLockedBuffer->height;
             break;
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
             // Single plane, 32bpp.
             bytesPerPixel = 4;
-            pData = mBuffer->data;
-            dataSize = mBuffer->stride * mBuffer->height * bytesPerPixel;
+            pData = mLockedBuffer->data;
+            dataSize =
+                mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel;
             break;
         case HAL_PIXEL_FORMAT_RGB_565:
             // Single plane, 16bpp.
             bytesPerPixel = 2;
-            pData = mBuffer->data;
-            dataSize = mBuffer->stride * mBuffer->height * bytesPerPixel;
+            pData = mLockedBuffer->data;
+            dataSize =
+                mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel;
             break;
         case HAL_PIXEL_FORMAT_RGB_888:
             // Single plane, 24bpp.
             bytesPerPixel = 3;
-            pData = mBuffer->data;
-            dataSize = mBuffer->stride * mBuffer->height * bytesPerPixel;
+            pData = mLockedBuffer->data;
+            dataSize = mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel;
             break;
         default:
             ALOGE("Pixel format: 0x%x is unsupported", fmt);
@@ -602,6 +705,12 @@
                 __FUNCTION__, image, pixelStride);
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
+    media_status_t ret = const_cast<AImage*>(image)->lockImage();
+    if (ret != AMEDIA_OK) {
+        ALOGE("%s: failed to lock buffer for CPU access. image %p, error=%d.",
+              __FUNCTION__, image, ret);
+        return ret;
+    }
     return image->getPlanePixelStride(planeIdx, pixelStride);
 }
 
@@ -614,6 +723,12 @@
                 __FUNCTION__, image, rowStride);
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
+    media_status_t ret = const_cast<AImage*>(image)->lockImage();
+    if (ret != AMEDIA_OK) {
+        ALOGE("%s: failed to lock buffer for CPU access. image %p, error=%d.",
+              __FUNCTION__, image, ret);
+        return ret;
+    }
     return image->getPlaneRowStride(planeIdx, rowStride);
 }
 
@@ -627,5 +742,11 @@
                 __FUNCTION__, image, data, dataLength);
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
+    media_status_t ret = const_cast<AImage*>(image)->lockImage();
+    if (ret != AMEDIA_OK) {
+        ALOGE("%s: failed to lock buffer for CPU access. image %p, error=%d.",
+              __FUNCTION__, image, ret);
+        return ret;
+    }
     return image->getPlaneData(planeIdx, data, dataLength);
 }
diff --git a/media/ndk/NdkImagePriv.h b/media/ndk/NdkImagePriv.h
index 89d2b7c..e01dcc7 100644
--- a/media/ndk/NdkImagePriv.h
+++ b/media/ndk/NdkImagePriv.h
@@ -21,6 +21,7 @@
 #include <utils/Log.h>
 #include <utils/StrongPointer.h>
 
+#include <gui/BufferItem.h>
 #include <gui/CpuConsumer.h>
 
 #include "NdkImageReaderPriv.h"
@@ -31,9 +32,9 @@
 
 // TODO: this only supports ImageReader
 struct AImage {
-    AImage(AImageReader* reader, int32_t format,
-            CpuConsumer::LockedBuffer* buffer, int64_t timestamp,
-            int32_t width, int32_t height, int32_t numPlanes);
+    AImage(AImageReader* reader, int32_t format, uint64_t usage,
+           BufferItem* buffer, int64_t timestamp,
+           int32_t width, int32_t height, int32_t numPlanes);
 
     // free all resources while keeping object alive. Caller must obtain reader lock
     void close();
@@ -54,6 +55,9 @@
     media_status_t getNumPlanes(/*out*/int32_t* numPlanes) const;
     media_status_t getTimestamp(/*out*/int64_t* timestamp) const;
 
+    media_status_t lockImage();
+    media_status_t unlockImageIfLocked(/*out*/int* fenceFd);
+
     media_status_t getPlanePixelStride(int planeIdx, /*out*/int32_t* pixelStride) const;
     media_status_t getPlaneRowStride(int planeIdx, /*out*/int32_t* rowStride) const;
     media_status_t getPlaneData(int planeIdx,/*out*/uint8_t** data, /*out*/int* dataLength) const;
@@ -69,7 +73,9 @@
     // When reader is close, AImage will only accept close API call
     wp<AImageReader>           mReader;
     const int32_t              mFormat;
-    CpuConsumer::LockedBuffer* mBuffer;
+    const uint64_t             mUsage;  // AHARDWAREBUFFER_USAGE0* flags.
+    BufferItem*                mBuffer;
+    std::unique_ptr<CpuConsumer::LockedBuffer> mLockedBuffer;
     const int64_t              mTimestamp;
     const int32_t              mWidth;
     const int32_t              mHeight;
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index ab3829e..e580dae 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -24,7 +24,9 @@
 
 #include <cutils/atomic.h>
 #include <utils/Log.h>
+#include <android_media_Utils.h>
 #include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_hardware_HardwareBuffer.h>
 
 using namespace android;
 
@@ -36,6 +38,7 @@
     }
 }
 
+const int32_t AImageReader::kDefaultUsage = AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN;
 const char* AImageReader::kCallbackFpKey = "Callback";
 const char* AImageReader::kContextKey    = "Context";
 
@@ -151,10 +154,18 @@
     }
 }
 
-AImageReader::AImageReader(int32_t width, int32_t height, int32_t format, int32_t maxImages) :
-        mWidth(width), mHeight(height), mFormat(format), mMaxImages(maxImages),
-        mNumPlanes(getNumPlanesForFormat(format)),
-        mFrameListener(new FrameListener(this)) {}
+AImageReader::AImageReader(int32_t width,
+                           int32_t height,
+                           int32_t format,
+                           uint64_t usage,
+                           int32_t maxImages)
+    : mWidth(width),
+      mHeight(height),
+      mFormat(format),
+      mUsage(usage),
+      mMaxImages(maxImages),
+      mNumPlanes(getNumPlanesForFormat(format)),
+      mFrameListener(new FrameListener(this)) {}
 
 media_status_t
 AImageReader::init() {
@@ -162,42 +173,44 @@
     mHalFormat = android_view_Surface_mapPublicFormatToHalFormat(publicFormat);
     mHalDataSpace = android_view_Surface_mapPublicFormatToHalDataspace(publicFormat);
 
+    uint64_t producerUsage;
+    uint64_t consumerUsage;
+    android_hardware_HardwareBuffer_convertToGrallocUsageBits(
+            &producerUsage, &consumerUsage, mUsage, 0);
+
     sp<IGraphicBufferProducer> gbProducer;
     sp<IGraphicBufferConsumer> gbConsumer;
     BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
 
-    sp<CpuConsumer> cpuConsumer;
-    String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d",
-            mWidth, mHeight, mFormat, mMaxImages, getpid(),
-            createProcessUniqueId());
+    String8 consumerName = String8::format(
+            "ImageReader-%dx%df%xu%" PRIu64 "m%d-%d-%d", mWidth, mHeight, mFormat, mUsage,
+            mMaxImages, getpid(), createProcessUniqueId());
 
-    cpuConsumer = new CpuConsumer(gbConsumer, mMaxImages, /*controlledByApp*/true);
-    if (cpuConsumer == nullptr) {
-        ALOGE("Failed to allocate CpuConsumer");
+    mBufferItemConsumer =
+            new BufferItemConsumer(gbConsumer, consumerUsage, mMaxImages, /*controlledByApp*/ true);
+    if (mBufferItemConsumer == nullptr) {
+        ALOGE("Failed to allocate BufferItemConsumer");
         return AMEDIA_ERROR_UNKNOWN;
     }
 
-    mCpuConsumer = cpuConsumer;
-    mCpuConsumer->setName(consumerName);
     mProducer = gbProducer;
-
-    sp<ConsumerBase> consumer = cpuConsumer;
-    consumer->setFrameAvailableListener(mFrameListener);
+    mBufferItemConsumer->setName(consumerName);
+    mBufferItemConsumer->setFrameAvailableListener(mFrameListener);
 
     status_t res;
-    res = cpuConsumer->setDefaultBufferSize(mWidth, mHeight);
+    res = mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
     if (res != OK) {
-        ALOGE("Failed to set CpuConsumer buffer size");
+        ALOGE("Failed to set BufferItemConsumer buffer size");
         return AMEDIA_ERROR_UNKNOWN;
     }
-    res = cpuConsumer->setDefaultBufferFormat(mHalFormat);
+    res = mBufferItemConsumer->setDefaultBufferFormat(mHalFormat);
     if (res != OK) {
-        ALOGE("Failed to set CpuConsumer buffer format");
+        ALOGE("Failed to set BufferItemConsumer buffer format");
         return AMEDIA_ERROR_UNKNOWN;
     }
-    res = cpuConsumer->setDefaultBufferDataSpace(mHalDataSpace);
+    res = mBufferItemConsumer->setDefaultBufferDataSpace(mHalDataSpace);
     if (res != OK) {
-        ALOGE("Failed to set CpuConsumer buffer dataSpace");
+        ALOGE("Failed to set BufferItemConsumer buffer dataSpace");
         return AMEDIA_ERROR_UNKNOWN;
     }
 
@@ -209,7 +222,7 @@
     mWindow = static_cast<ANativeWindow*>(mSurface.get());
 
     for (int i = 0; i < mMaxImages; i++) {
-        CpuConsumer::LockedBuffer* buffer = new CpuConsumer::LockedBuffer;
+        BufferItem* buffer = new BufferItem;
         mBuffers.push_back(buffer);
     }
 
@@ -248,133 +261,136 @@
         image->close();
     }
 
-    // Delete LockedBuffers
+    // Delete Buffer Items
     for (auto it = mBuffers.begin();
               it != mBuffers.end(); it++) {
         delete *it;
     }
 
-    if (mCpuConsumer != nullptr) {
-        mCpuConsumer->abandon();
-        mCpuConsumer->setFrameAvailableListener(nullptr);
+    if (mBufferItemConsumer != nullptr) {
+        mBufferItemConsumer->abandon();
+        mBufferItemConsumer->setFrameAvailableListener(nullptr);
     }
 }
 
 media_status_t
-AImageReader::acquireCpuConsumerImageLocked(/*out*/AImage** image) {
+AImageReader::acquireImageLocked(/*out*/AImage** image) {
     *image = nullptr;
-    CpuConsumer::LockedBuffer* buffer = getLockedBufferLocked();
+    BufferItem* buffer = getBufferItemLocked();
     if (buffer == nullptr) {
         ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
             " maxImages buffers");
         return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED;
     }
 
-    status_t res = mCpuConsumer->lockNextBuffer(buffer);
+    status_t res = mBufferItemConsumer->acquireBuffer(buffer, 0);
     if (res != NO_ERROR) {
-        returnLockedBufferLocked(buffer);
-        if (res != BAD_VALUE /*no buffers*/) {
-            if (res == NOT_ENOUGH_DATA) {
+        returnBufferItemLocked(buffer);
+        if (res != BufferQueue::NO_BUFFER_AVAILABLE) {
+            if (res == INVALID_OPERATION) {
                 return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED;
             } else {
-                ALOGE("%s Fail to lockNextBuffer with error: %d ",
-                      __FUNCTION__, res);
+                ALOGE("%s: Acquire image failed with some unknown error: %s (%d)",
+                      __FUNCTION__, strerror(-res), res);
                 return AMEDIA_ERROR_UNKNOWN;
             }
         }
         return AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE;
     }
 
-    if (buffer->flexFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
-        ALOGE("NV21 format is not supported by AImageReader");
-        return AMEDIA_ERROR_UNSUPPORTED;
-    }
+    const int bufferWidth = getBufferWidth(buffer);
+    const int bufferHeight = getBufferHeight(buffer);
+    const int bufferFmt = buffer->mGraphicBuffer->getPixelFormat();
 
-    // Check if the left-top corner of the crop rect is origin, we currently assume this point is
-    // zero, will revist this once this assumption turns out problematic.
-    Point lt = buffer->crop.leftTop();
-    if (lt.x != 0 || lt.y != 0) {
-        ALOGE("crop left top corner [%d, %d] need to be at origin", lt.x, lt.y);
-        return AMEDIA_ERROR_UNKNOWN;
-    }
+    const int readerWidth = mWidth;
+    const int readerHeight = mHeight;
+    const int readerFmt = mHalFormat;
 
-    // Check if the producer buffer configurations match what ImageReader configured.
-    int outputWidth = getBufferWidth(buffer);
-    int outputHeight = getBufferHeight(buffer);
-
-    int readerFmt = mHalFormat;
-    int readerWidth = mWidth;
-    int readerHeight = mHeight;
-
-    if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) && (readerFmt != HAL_PIXEL_FORMAT_BLOB) &&
-            (readerWidth != outputWidth || readerHeight != outputHeight)) {
-        ALOGW("%s: Producer buffer size: %dx%d, doesn't match AImageReader configured size: %dx%d",
-                __FUNCTION__, outputWidth, outputHeight, readerWidth, readerHeight);
-    }
-
-    int bufFmt = buffer->format;
-    if (readerFmt == HAL_PIXEL_FORMAT_YCbCr_420_888) {
-        bufFmt = buffer->flexFormat;
-    }
-
-    if (readerFmt != bufFmt) {
-        if (readerFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt ==
-                HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) {
-            // Special casing for when producer switches to a format compatible with flexible YUV
-            // (HAL_PIXEL_FORMAT_YCbCr_420_888).
-            mHalFormat = bufFmt;
-            ALOGD("%s: Overriding buffer format YUV_420_888 to %x.", __FUNCTION__, bufFmt);
-        } else {
-            // Return the buffer to the queue.
-            mCpuConsumer->unlockBuffer(*buffer);
-            returnLockedBufferLocked(buffer);
-
-            ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
-                    buffer->format, readerFmt);
-
+    // Check if the producer buffer configurations match what AImageReader configured. Add some
+    // extra checks for non-opaque formats.
+    if (!isFormatOpaque(readerFmt)) {
+        // Check if the left-top corner of the crop rect is origin, we currently assume this point
+        // is zero, will revisit this once this assumption turns out problematic.
+        Point lt = buffer->mCrop.leftTop();
+        if (lt.x != 0 || lt.y != 0) {
+            ALOGE("Crop left top corner [%d, %d] not at origin", lt.x, lt.y);
             return AMEDIA_ERROR_UNKNOWN;
         }
+
+        // Check if the producer buffer configurations match what ImageReader configured.
+        if ((bufferFmt != HAL_PIXEL_FORMAT_BLOB) && (readerFmt != HAL_PIXEL_FORMAT_BLOB) &&
+                (readerWidth != bufferWidth || readerHeight != bufferHeight)) {
+            ALOGW("%s: Buffer size: %dx%d, doesn't match AImageReader configured size: %dx%d",
+                    __FUNCTION__, bufferWidth, bufferHeight, readerWidth, readerHeight);
+        }
+
+        if (readerFmt != bufferFmt) {
+            if (readerFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && isPossiblyYUV(bufferFmt)) {
+                // Special casing for when producer switches to a format compatible with flexible
+                // YUV.
+                mHalFormat = bufferFmt;
+                ALOGD("%s: Overriding buffer format YUV_420_888 to 0x%x.", __FUNCTION__, bufferFmt);
+            } else {
+                // Return the buffer to the queue. No need to provide fence, as this buffer wasn't
+                // used anywhere yet.
+                mBufferItemConsumer->releaseBuffer(*buffer);
+                returnBufferItemLocked(buffer);
+
+                ALOGE("%s: Output buffer format: 0x%x, ImageReader configured format: 0x%x",
+                        __FUNCTION__, bufferFmt, readerFmt);
+
+                return AMEDIA_ERROR_UNKNOWN;
+            }
+        }
     }
 
     if (mHalFormat == HAL_PIXEL_FORMAT_BLOB) {
-        *image = new AImage(this, mFormat, buffer, buffer->timestamp,
+        *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp,
                             readerWidth, readerHeight, mNumPlanes);
     } else {
-        *image = new AImage(this, mFormat, buffer, buffer->timestamp,
-                            outputWidth, outputHeight, mNumPlanes);
+        *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp,
+                            bufferWidth, bufferHeight, mNumPlanes);
     }
     mAcquiredImages.push_back(*image);
     return AMEDIA_OK;
 }
 
-CpuConsumer::LockedBuffer*
-AImageReader::getLockedBufferLocked() {
+BufferItem*
+AImageReader::getBufferItemLocked() {
     if (mBuffers.empty()) {
         return nullptr;
     }
-    // Return a LockedBuffer pointer and remove it from the list
+    // Return a BufferItem pointer and remove it from the list
     auto it = mBuffers.begin();
-    CpuConsumer::LockedBuffer* buffer = *it;
+    BufferItem* buffer = *it;
     mBuffers.erase(it);
     return buffer;
 }
 
 void
-AImageReader::returnLockedBufferLocked(CpuConsumer::LockedBuffer* buffer) {
+AImageReader::returnBufferItemLocked(BufferItem* buffer) {
     mBuffers.push_back(buffer);
 }
 
 void
 AImageReader::releaseImageLocked(AImage* image) {
-    CpuConsumer::LockedBuffer* buffer = image->mBuffer;
+    BufferItem* buffer = image->mBuffer;
     if (buffer == nullptr) {
         // This should not happen, but is not fatal
         ALOGW("AImage %p has no buffer!", image);
         return;
     }
 
-    mCpuConsumer->unlockBuffer(*buffer);
-    returnLockedBufferLocked(buffer);
+    int fenceFd = -1;
+    media_status_t ret = image->unlockImageIfLocked(&fenceFd);
+    if (ret < 0) {
+        ALOGW("%s: AImage %p is cannot be unlocked.", __FUNCTION__, image);
+        return;
+    }
+
+    sp<Fence> releaseFence = fenceFd > 0 ? new Fence(fenceFd) : Fence::NO_FENCE;
+    mBufferItemConsumer->releaseBuffer(*buffer, releaseFence);
+    returnBufferItemLocked(buffer);
     image->mBuffer = nullptr;
 
     bool found = false;
@@ -395,29 +411,31 @@
 }
 
 int
-AImageReader::getBufferWidth(CpuConsumer::LockedBuffer* buffer) {
-    if (buffer == nullptr) return -1;
+AImageReader::getBufferWidth(BufferItem* buffer) {
+    if (buffer == NULL) return -1;
 
-    if (!buffer->crop.isEmpty()) {
-        return buffer->crop.getWidth();
+    if (!buffer->mCrop.isEmpty()) {
+        return buffer->mCrop.getWidth();
     }
-    return buffer->width;
+
+    return buffer->mGraphicBuffer->getWidth();
 }
 
 int
-AImageReader::getBufferHeight(CpuConsumer::LockedBuffer* buffer) {
-    if (buffer == nullptr) return -1;
+AImageReader::getBufferHeight(BufferItem* buffer) {
+    if (buffer == NULL) return -1;
 
-    if (!buffer->crop.isEmpty()) {
-        return buffer->crop.getHeight();
+    if (!buffer->mCrop.isEmpty()) {
+        return buffer->mCrop.getHeight();
     }
-    return buffer->height;
+
+    return buffer->mGraphicBuffer->getHeight();
 }
 
 media_status_t
 AImageReader::acquireNextImage(/*out*/AImage** image) {
     Mutex::Autolock _l(mLock);
-    return acquireCpuConsumerImageLocked(image);
+    return acquireImageLocked(image);
 }
 
 media_status_t
@@ -429,12 +447,12 @@
     *image = nullptr;
     AImage* prevImage = nullptr;
     AImage* nextImage = nullptr;
-    media_status_t ret = acquireCpuConsumerImageLocked(&prevImage);
+    media_status_t ret = acquireImageLocked(&prevImage);
     if (prevImage == nullptr) {
         return ret;
     }
     for (;;) {
-        ret = acquireCpuConsumerImageLocked(&nextImage);
+        ret = acquireImageLocked(&nextImage);
         if (nextImage == nullptr) {
             *image = prevImage;
             return AMEDIA_OK;
@@ -464,6 +482,12 @@
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
 
+    if (maxImages > BufferQueueDefs::NUM_BUFFER_SLOTS) {
+        ALOGE("%s: max outstanding image count (%d) cannot be larget than %d.",
+              __FUNCTION__, maxImages, BufferQueueDefs::NUM_BUFFER_SLOTS);
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+
     if (!AImageReader::isSupportedFormat(format)) {
         ALOGE("%s: format %d is not supported by AImageReader",
                 __FUNCTION__, format);
@@ -475,8 +499,10 @@
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
 
-    //*reader = new AImageReader(width, height, format, maxImages);
-    AImageReader* tmpReader = new AImageReader(width, height, format, maxImages);
+    // Set consumer usage to AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN by default so that
+    // AImageReader_new behaves as if it's backed by CpuConsumer.
+    AImageReader* tmpReader = new AImageReader(
+        width, height, format, AImageReader::kDefaultUsage, maxImages);
     if (tmpReader == nullptr) {
         ALOGE("%s: AImageReader allocation failed", __FUNCTION__);
         return AMEDIA_ERROR_UNKNOWN;
@@ -565,7 +591,7 @@
 media_status_t AImageReader_acquireNextImage(AImageReader* reader, /*out*/AImage** image) {
     ALOGV("%s", __FUNCTION__);
     if (reader == nullptr || image == nullptr) {
-        ALOGE("%s: invalid argument. reader %p, maxImages %p",
+        ALOGE("%s: invalid argument. reader %p, image %p",
                 __FUNCTION__, reader, image);
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
@@ -576,7 +602,7 @@
 media_status_t AImageReader_acquireLatestImage(AImageReader* reader, /*out*/AImage** image) {
     ALOGV("%s", __FUNCTION__);
     if (reader == nullptr || image == nullptr) {
-        ALOGE("%s: invalid argument. reader %p, maxImages %p",
+        ALOGE("%s: invalid argument. reader %p, image %p",
                 __FUNCTION__, reader, image);
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index 8b540fa..8becb1d 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -25,7 +25,8 @@
 #include <utils/Mutex.h>
 #include <utils/StrongPointer.h>
 
-#include <gui/CpuConsumer.h>
+#include <gui/BufferItem.h>
+#include <gui/BufferItemConsumer.h>
 #include <gui/Surface.h>
 
 #include <media/stagefright/foundation/ALooper.h>
@@ -48,11 +49,16 @@
 
 struct AImageReader : public RefBase {
   public:
+    static const int32_t kDefaultUsage;
 
     static bool isSupportedFormat(int32_t format);
     static int getNumPlanesForFormat(int32_t format);
 
-    AImageReader(int32_t width, int32_t height, int32_t format, int32_t maxImages);
+    AImageReader(int32_t width,
+                 int32_t height,
+                 int32_t format,
+                 uint64_t usage,
+                 int32_t maxImages);
     ~AImageReader();
 
     // Inintialize AImageReader, uninitialized or failed to initialize AImageReader
@@ -68,22 +74,24 @@
     int32_t        getWidth()     const { return mWidth; };
     int32_t        getHeight()    const { return mHeight; };
     int32_t        getFormat()    const { return mFormat; };
+    uint64_t       getUsage()     const { return mUsage; };
     int32_t        getMaxImages() const { return mMaxImages; };
 
-
   private:
 
     friend struct AImage; // for grabing reader lock
 
-    media_status_t acquireCpuConsumerImageLocked(/*out*/AImage** image);
-    CpuConsumer::LockedBuffer* getLockedBufferLocked();
-    void returnLockedBufferLocked(CpuConsumer::LockedBuffer* buffer);
+    BufferItem* getBufferItemLocked();
+    void returnBufferItemLocked(BufferItem* buffer);
+
+    // Called by AImageReader_acquireXXX to acquire a Buffer and setup AImage.
+    media_status_t acquireImageLocked(/*out*/AImage** image);
 
     // Called by AImage to close image
     void releaseImageLocked(AImage* image);
 
-    static int getBufferWidth(CpuConsumer::LockedBuffer* buffer);
-    static int getBufferHeight(CpuConsumer::LockedBuffer* buffer);
+    static int getBufferWidth(BufferItem* buffer);
+    static int getBufferHeight(BufferItem* buffer);
 
     media_status_t setImageListenerLocked(AImageReader_ImageListener* listener);
 
@@ -102,12 +110,15 @@
     };
     sp<CallbackHandler> mHandler;
     sp<ALooper>         mCbLooper; // Looper thread where callbacks actually happen on
+    List<BufferItem*>   mBuffers;
 
-    List<CpuConsumer::LockedBuffer*> mBuffers;
     const int32_t mWidth;
     const int32_t mHeight;
     const int32_t mFormat;
+    const uint64_t mUsage;
     const int32_t mMaxImages;
+
+    // TODO(jwcai) Seems completely unused in AImageReader class.
     const int32_t mNumPlanes;
 
     struct FrameListener : public ConsumerBase::FrameAvailableListener {
@@ -130,7 +141,7 @@
 
     sp<IGraphicBufferProducer> mProducer;
     sp<Surface>                mSurface;
-    sp<CpuConsumer>            mCpuConsumer;
+    sp<BufferItemConsumer>     mBufferItemConsumer;
     sp<ANativeWindow>          mWindow;
 
     List<AImage*>              mAcquiredImages;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index c0918d4..7eb179a 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -292,7 +292,8 @@
                                             sessionId,
                                             &streamType, client.clientUid,
                                             &fullConfig,
-                                            (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT),
+                                            (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
+                                                    AUDIO_OUTPUT_FLAG_DIRECT),
                                             *deviceId, &portId);
     } else {
         ret = AudioSystem::getInputForAttr(attr, &io,
@@ -2017,7 +2018,8 @@
                                   uint32_t *latencyMs,
                                   audio_output_flags_t flags)
 {
-    ALOGI("openOutput() this %p, module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, flags %x",
+    ALOGI("openOutput() this %p, module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, "
+              "flags %x",
               this, module,
               (devices != NULL) ? *devices : 0,
               config->sample_rate,
@@ -2115,13 +2117,13 @@
             if (mPlaybackThreads.size()) {
                 PlaybackThread *dstThread = checkPlaybackThread_l(mPlaybackThreads.keyAt(0));
                 if (dstThread != NULL) {
-                    // audioflinger lock is held here so the acquisition order of thread locks does not
-                    // matter
+                    // audioflinger lock is held so order of thread lock acquisition doesn't matter
                     Mutex::Autolock _dl(dstThread->mLock);
                     Mutex::Autolock _sl(playbackThread->mLock);
                     Vector< sp<EffectChain> > effectChains = playbackThread->getEffectChains_l();
                     for (size_t i = 0; i < effectChains.size(); i ++) {
-                        moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(), dstThread, true);
+                        moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(),
+                                dstThread, true);
                     }
                 }
             }
@@ -2293,7 +2295,8 @@
                                           inHwDev, inputStream,
                                           primaryOutputDevice_l(), devices, mSystemReady);
             mMmapThreads.add(*input, thread);
-            ALOGV("openInput_l() created mmap capture thread: ID %d thread %p", *input, thread.get());
+            ALOGV("openInput_l() created mmap capture thread: ID %d thread %p", *input,
+                    thread.get());
             return thread;
         } else {
 #ifdef TEE_SINK
@@ -2399,7 +2402,7 @@
                 }
             }
             if (chain != 0) {
-                // first check if a record thread is already opened with a client on the same session.
+                // first check if a record thread is already opened with a client on same session.
                 // This should only happen in case of overlap between one thread tear down and the
                 // creation of its replacement
                 size_t i;
@@ -2416,7 +2419,7 @@
                         break;
                     }
                 }
-                // put the chain aside if we could not find a record thread with the same session id.
+                // put the chain aside if we could not find a record thread with the same session id
                 if (i == mRecordThreads.size()) {
                     putOrphanEffectChain_l(chain);
                 }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index b79f09e..fca840b 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -593,7 +593,8 @@
         virtual status_t createMmapBuffer(int32_t minSizeFrames,
                                           struct audio_mmap_buffer_info *info);
         virtual status_t getMmapPosition(struct audio_mmap_position *position);
-        virtual status_t start(const MmapStreamInterface::Client& client, audio_port_handle_t *handle);
+        virtual status_t start(const MmapStreamInterface::Client& client,
+                                         audio_port_handle_t *handle);
         virtual status_t stop(audio_port_handle_t handle);
         virtual status_t standby();
 
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 7182f32..103e7f8 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -37,7 +37,7 @@
 #include <cpustats/ThreadCpuUsage.h>
 #endif
 #endif
-#include <audio_utils/conversion.h>
+#include <audio_utils/mono_blend.h>
 #include <audio_utils/format.h>
 #include <media/AudioMixer.h>
 #include "FastMixer.h"
diff --git a/services/audioflinger/FastMixerState.cpp b/services/audioflinger/FastMixerState.cpp
index ad471fb..36d8eef 100644
--- a/services/audioflinger/FastMixerState.cpp
+++ b/services/audioflinger/FastMixerState.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "FastMixerState"
+//#define LOG_NDEBUG 0
+
 #include <cutils/properties.h>
 #include "FastMixerState.h"
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 14ff6ee..54e07c0 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -36,7 +36,7 @@
 
 #include <private/media/AudioTrackShared.h>
 #include <private/android_filesystem_config.h>
-#include <audio_utils/conversion.h>
+#include <audio_utils/mono_blend.h>
 #include <audio_utils/primitives.h>
 #include <audio_utils/format.h>
 #include <audio_utils/minifloat.h>
@@ -5603,7 +5603,7 @@
                         ALOGV("OffloadThread: BUFFER TIMEOUT: remove(%d) from active list",
                                 track->name());
                         tracksToRemove->add(track);
-                        // indicate to client process that the track was disabled because of underrun;
+                        // tell client process that the track was disabled because of underrun;
                         // it will then automatically call start() when data is available
                         track->disable();
                     }
@@ -7219,7 +7219,8 @@
     // Over-allocate beyond mRsmpInFramesP2 to permit a HAL read past end of buffer
     mRsmpInFramesOA = mRsmpInFramesP2 + mFrameCount - 1;
     (void)posix_memalign(&mRsmpInBuffer, 32, mRsmpInFramesOA * mFrameSize);
-    memset(mRsmpInBuffer, 0, mRsmpInFramesOA * mFrameSize); // if posix_memalign fails, will segv here.
+    // if posix_memalign fails, will segv here.
+    memset(mRsmpInBuffer, 0, mRsmpInFramesOA * mFrameSize);
 
     // AudioRecord mSampleRate and mChannelCount are constant due to AudioRecord API constraints.
     // But if thread's mSampleRate or mChannelCount changes, how will that affect active tracks?
@@ -7463,7 +7464,8 @@
     return mThread->getMmapPosition(position);
 }
 
-status_t AudioFlinger::MmapThreadHandle::start(const MmapStreamInterface::Client& client, audio_port_handle_t *handle)
+status_t AudioFlinger::MmapThreadHandle::start(const MmapStreamInterface::Client& client,
+        audio_port_handle_t *handle)
 
 {
     if (mThread == 0) {
@@ -8073,8 +8075,8 @@
         return BAD_VALUE;
     }
     if (isOutput() && ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
-        ALOGW("checkEffectCompatibility_l(): pre processing effect %s created on playback mmap thread",
-              desc->name);
+        ALOGW("checkEffectCompatibility_l(): pre processing effect %s created on playback mmap "
+              "thread", desc->name);
         return BAD_VALUE;
     }
 
@@ -8306,7 +8308,8 @@
 {
     MmapThread::dumpInternals(fd, args);
 
-    dprintf(fd, "  Stream type: %d Stream volume: %f HAL volume: %f Stream mute %d\n", mStreamType, mStreamVolume, mHalVolFloat, mStreamMute);
+    dprintf(fd, "  Stream type: %d Stream volume: %f HAL volume: %f Stream mute %d\n",
+            mStreamType, mStreamVolume, mHalVolFloat, mStreamMute);
     dprintf(fd, "  Master volume: %f Master mute %d\n", mMasterVolume, mMasterMute);
 }
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index aec7794..4318a11 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -620,7 +620,7 @@
         }
     } else {
         status_t res = mCameraProviderManager->getCameraCharacteristics(
-                String16::std_string(cameraId), cameraInfo);
+                String8(cameraId).string(), cameraInfo);
         if (res != OK) {
             return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera "
                     "characteristics for device %s: %s (%d)", String8(cameraId).string(),
@@ -687,14 +687,14 @@
     } else {
         status_t res;
         hardware::hidl_version maxVersion{0,0};
-        res = mCameraProviderManager->getHighestSupportedVersion(String8::std_string(cameraId),
+        res = mCameraProviderManager->getHighestSupportedVersion(cameraId.string(),
                 &maxVersion);
         if (res != OK) return -1;
         deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());
 
         hardware::CameraInfo info;
         if (facing) {
-            res = mCameraProviderManager->getCameraInfo(String8::std_string(cameraId), &info);
+            res = mCameraProviderManager->getCameraInfo(cameraId.string(), &info);
             if (res != OK) return -1;
             *facing = info.facing;
         }
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 3e4e631..b52c0d8 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -80,7 +80,7 @@
 
     ALOGI("Opening camera %s", mName.string());
 
-    status_t ret = manager->openSession(String8::std_string(mName), this, &mHidlDevice);
+    status_t ret = manager->openSession(mName.string(), this, &mHidlDevice);
     if (ret != OK) {
         ALOGE("%s: openSession failed! %s (%d)", __FUNCTION__, strerror(-ret), ret);
     }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 4d5abed..60c716f 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -183,7 +183,7 @@
 
     sp<ICameraDeviceSession> session;
     ATRACE_BEGIN("CameraHal::openSession");
-    status_t res = manager->openSession(String8::std_string(mId), this,
+    status_t res = manager->openSession(mId.string(), this,
             /*out*/ &session);
     ATRACE_END();
     if (res != OK) {
@@ -191,7 +191,7 @@
         return res;
     }
 
-    res = manager->getCameraCharacteristics(String8::std_string(mId), &mDeviceInfo);
+    res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
     if (res != OK) {
         SET_ERR_L("Could not retrive camera characteristics: %s (%d)", strerror(-res), res);
         session->close();
diff --git a/services/radio/RadioHalHidl.h b/services/radio/RadioHalHidl.h
index 38e181a..f98420d 100644
--- a/services/radio/RadioHalHidl.h
+++ b/services/radio/RadioHalHidl.h
@@ -29,7 +29,6 @@
 
 namespace android {
 
-using android::hardware::Status;
 using android::hardware::Return;
 using android::hardware::broadcastradio::V1_0::Result;
 using android::hardware::broadcastradio::V1_0::IBroadcastRadio;