Merge "AudioTrack: Advance timestamp time during pause"
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 88c4e61..4e2b740 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -1056,6 +1056,10 @@
                                                     // after flush.
     int64_t                 mFramesWrittenServerOffset; // An offset to server frames due to
                                                     // restoring AudioTrack, or stop/start.
+                                                    // This offset is also used for static tracks.
+    int64_t                 mFramesWrittenAtRestore; // Frames written at restore point (or frames
+                                                    // delivered for static tracks).
+                                                    // -1 indicates no previous restore point.
 
     audio_output_flags_t    mFlags;                 // same as mOrigFlags, except for bits that may
                                                     // be denied by client or server, such as
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 68a65f0..3e05532 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -28,8 +28,8 @@
 }
 class ICameraRecordingProxy;
 class IMediaRecorderClient;
-class IGraphicBufferConsumer;
 class IGraphicBufferProducer;
+struct PersistentSurface;
 
 class IMediaRecorder: public IInterface
 {
@@ -60,7 +60,7 @@
     virtual status_t init() = 0;
     virtual status_t close() = 0;
     virtual status_t release() = 0;
-    virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+    virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() = 0;
 };
 
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 9790f84..311119b 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -19,8 +19,6 @@
 #define ANDROID_IOMX_H_
 
 #include <binder/IInterface.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/IGraphicBufferConsumer.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/List.h>
 #include <utils/String8.h>
@@ -34,8 +32,10 @@
 
 namespace android {
 
+class IGraphicBufferProducer;
 class IGraphicBufferSource;
 class IMemory;
+class IOMXBufferSource;
 class IOMXNode;
 class IOMXObserver;
 class NativeHandle;
@@ -61,9 +61,9 @@
             const char *name, const sp<IOMXObserver> &observer,
             sp<IOMXNode> *omxNode) = 0;
 
-    virtual status_t createPersistentInputSurface(
+    virtual status_t createInputSurface(
             sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferConsumer> *bufferConsumer) = 0;
+            sp<IGraphicBufferSource> *bufferSource) = 0;
 };
 
 class IOMXNode : public IInterface {
@@ -125,21 +125,8 @@
             OMX_U32 port_index,
             const sp<NativeHandle> &nativeHandle, buffer_id buffer) = 0;
 
-    // This will set *type to resulting metadata buffer type on OMX error (not on binder error) as
-    // well as on success.
-    virtual status_t createInputSurface(
-            OMX_U32 port_index, android_dataspace dataSpace,
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type = NULL) = 0;
-
-    // This will set *type to resulting metadata buffer type on OMX error (not on binder error) as
-    // well as on success.
     virtual status_t setInputSurface(
-            OMX_U32 port_index,
-            const sp<IGraphicBufferConsumer> &bufferConsumer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type) = 0;
+            const sp<IOMXBufferSource> &bufferSource) = 0;
 
     // Allocate an opaque buffer as a native handle. If component supports returning native
     // handles, those are returned in *native_handle. Otherwise, the allocated buffer is
@@ -150,12 +137,6 @@
             OMX_U32 port_index, size_t size, buffer_id *buffer,
             void **buffer_data, sp<NativeHandle> *native_handle) = 0;
 
-    // Allocate an OMX buffer of size |allotedSize|. Use |params| as the backup buffer, which
-    // may be larger.
-    virtual status_t allocateBufferWithBackup(
-            OMX_U32 port_index, const sp<IMemory> &params,
-            buffer_id *buffer, OMX_U32 allottedSize) = 0;
-
     virtual status_t freeBuffer(
             OMX_U32 port_index, buffer_id buffer) = 0;
 
@@ -189,6 +170,9 @@
             OMX_INDEXTYPE *index) = 0;
 
     virtual status_t dispatchMessage(const omx_message &msg) = 0;
+
+    // TODO: this is temporary, will be removed when quirks move to OMX side
+    virtual status_t setQuirks(OMX_U32 quirks) = 0;
 };
 
 struct omx_message {
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 5195993..59dfd18 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -25,9 +25,8 @@
 namespace android {
 
 class ICameraRecordingProxy;
-class Surface;
-class IGraphicBufferConsumer;
 class IGraphicBufferProducer;
+struct PersistentSurface;
 
 struct MediaRecorderBase {
     MediaRecorderBase(const String16 &opPackageName)
@@ -59,7 +58,7 @@
     virtual status_t reset() = 0;
     virtual status_t getMaxAmplitude(int *max) = 0;
     virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
-    virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+    virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0;
 
 
diff --git a/include/media/audiohal/DeviceHalInterface.h b/include/media/audiohal/DeviceHalInterface.h
index b5767ef..2f7ed3a 100644
--- a/include/media/audiohal/DeviceHalInterface.h
+++ b/include/media/audiohal/DeviceHalInterface.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_HARDWARE_DEVICE_HAL_INTERFACE_H
 #define ANDROID_HARDWARE_DEVICE_HAL_INTERFACE_H
 
-#include <hardware/audio.h>
+#include <system/audio.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/String8.h>
diff --git a/include/media/audiohal/StreamHalInterface.h b/include/media/audiohal/StreamHalInterface.h
index 8f42fe7..0772d8f 100644
--- a/include/media/audiohal/StreamHalInterface.h
+++ b/include/media/audiohal/StreamHalInterface.h
@@ -17,8 +17,8 @@
 #ifndef ANDROID_HARDWARE_STREAM_HAL_INTERFACE_H
 #define ANDROID_HARDWARE_STREAM_HAL_INTERFACE_H
 
-#include <hardware/audio.h>
 #include <media/audiohal/EffectHalInterface.h>
+#include <system/audio.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/String8.h>
@@ -117,7 +117,7 @@
     virtual status_t supportsDrain(bool *supportsDrain) = 0;
 
     // Requests notification when data buffered by the driver/hardware has been played.
-    virtual status_t drain(audio_drain_type_t type) = 0;
+    virtual status_t drain(bool earlyNotify) = 0;
 
     // Notifies to the audio driver to flush the queued data.
     virtual status_t flush() = 0;
diff --git a/include/media/nbaio/AudioStreamInSource.h b/include/media/nbaio/AudioStreamInSource.h
index 2efff4a..508e0fe 100644
--- a/include/media/nbaio/AudioStreamInSource.h
+++ b/include/media/nbaio/AudioStreamInSource.h
@@ -17,7 +17,6 @@
 #ifndef ANDROID_AUDIO_STREAM_IN_SOURCE_H
 #define ANDROID_AUDIO_STREAM_IN_SOURCE_H
 
-#include <hardware/audio.h>
 #include "NBAIO.h"
 
 namespace android {
diff --git a/include/media/nbaio/AudioStreamOutSink.h b/include/media/nbaio/AudioStreamOutSink.h
index 3c59da2..56052a6 100644
--- a/include/media/nbaio/AudioStreamOutSink.h
+++ b/include/media/nbaio/AudioStreamOutSink.h
@@ -17,7 +17,6 @@
 #ifndef ANDROID_AUDIO_STREAM_OUT_SINK_H
 #define ANDROID_AUDIO_STREAM_OUT_SINK_H
 
-#include <hardware/audio.h>
 #include "NBAIO.h"
 
 namespace android {
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index cc1e1d0..c02742c 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -242,7 +242,6 @@
 
     AString mComponentName;
     uint32_t mFlags;
-    uint32_t mQuirks;
     sp<IOMX> mOMX;
     sp<IOMXNode> mOMXNode;
     int32_t mNodeGeneration;
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index 92a5593..13f82f0 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -36,6 +36,7 @@
 
 class MediaCodecBuffer;
 struct PersistentSurface;
+class Surface;
 
 struct CodecBase : public AHandler, /* static */ ColorUtils {
     enum {
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index 18b1955..f9a46a9 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -21,8 +21,7 @@
 #include <media/stagefright/foundation/AHandlerReflector.h>
 #include <media/stagefright/foundation/Mutexed.h>
 #include <media/stagefright/MediaSource.h>
-
-#include <gui/IGraphicBufferConsumer.h>
+#include <media/stagefright/PersistentSurface.h>
 
 namespace android {
 
@@ -44,7 +43,7 @@
             const sp<ALooper> &looper,
             const sp<AMessage> &format,
             const sp<MediaSource> &source,
-            const sp<IGraphicBufferConsumer> &consumer = NULL,
+            const sp<PersistentSurface> &persistentSurface = NULL,
             uint32_t flags = 0);
 
     bool isVideo() const { return mIsVideo; }
@@ -88,7 +87,7 @@
             const sp<ALooper> &looper,
             const sp<AMessage> &outputFormat,
             const sp<MediaSource> &source,
-            const sp<IGraphicBufferConsumer> &consumer,
+            const sp<PersistentSurface> &persistentSurface,
             uint32_t flags = 0);
 
     status_t onStart(MetaData *params);
@@ -121,7 +120,7 @@
     int32_t mEncoderDataSpace;
     sp<AMessage> mEncoderActivityNotify;
     sp<IGraphicBufferProducer> mGraphicBufferProducer;
-    sp<IGraphicBufferConsumer> mGraphicBufferConsumer;
+    sp<PersistentSurface> mPersistentSurface;
     List<MediaBuffer *> mInputBufferQueue;
     List<size_t> mAvailEncoderInputIndices;
     List<int64_t> mDecodingTimeQueue; // decoding time (us) for video
diff --git a/include/media/stagefright/PersistentSurface.h b/include/media/stagefright/PersistentSurface.h
index a35b9f1..d8b75a2 100644
--- a/include/media/stagefright/PersistentSurface.h
+++ b/include/media/stagefright/PersistentSurface.h
@@ -19,29 +19,46 @@
 #define PERSISTENT_SURFACE_H_
 
 #include <gui/IGraphicBufferProducer.h>
-#include <gui/IGraphicBufferConsumer.h>
+#include <android/IGraphicBufferSource.h>
 #include <media/stagefright/foundation/ABase.h>
+#include <binder/Parcel.h>
 
 namespace android {
 
 struct PersistentSurface : public RefBase {
+    PersistentSurface() {}
+
     PersistentSurface(
             const sp<IGraphicBufferProducer>& bufferProducer,
-            const sp<IGraphicBufferConsumer>& bufferConsumer) :
+            const sp<IGraphicBufferSource>& bufferSource) :
         mBufferProducer(bufferProducer),
-        mBufferConsumer(bufferConsumer) { }
+        mBufferSource(bufferSource) { }
 
     sp<IGraphicBufferProducer> getBufferProducer() const {
         return mBufferProducer;
     }
 
-    sp<IGraphicBufferConsumer> getBufferConsumer() const {
-        return mBufferConsumer;
+    sp<IGraphicBufferSource> getBufferSource() const {
+        return mBufferSource;
+    }
+
+    status_t writeToParcel(Parcel *parcel) const {
+        parcel->writeStrongBinder(IInterface::asBinder(mBufferProducer));
+        parcel->writeStrongBinder(IInterface::asBinder(mBufferSource));
+        return NO_ERROR;
+    }
+
+    status_t readFromParcel(const Parcel *parcel) {
+        mBufferProducer = interface_cast<IGraphicBufferProducer>(
+                parcel->readStrongBinder());
+        mBufferSource = interface_cast<IGraphicBufferSource>(
+                parcel->readStrongBinder());
+        return NO_ERROR;
     }
 
 private:
-    const sp<IGraphicBufferProducer> mBufferProducer;
-    const sp<IGraphicBufferConsumer> mBufferConsumer;
+    sp<IGraphicBufferProducer> mBufferProducer;
+    sp<IGraphicBufferSource> mBufferSource;
 
     DISALLOW_EVIL_CONSTRUCTORS(PersistentSurface);
 };
diff --git a/media/libaudiohal/DeviceHalLocal.h b/media/libaudiohal/DeviceHalLocal.h
index 6c15eb7..eba360c 100644
--- a/media/libaudiohal/DeviceHalLocal.h
+++ b/media/libaudiohal/DeviceHalLocal.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_HARDWARE_DEVICE_HAL_LOCAL_H
 #define ANDROID_HARDWARE_DEVICE_HAL_LOCAL_H
 
+#include <hardware/audio.h>
 #include <media/audiohal/DeviceHalInterface.h>
 
 namespace android {
diff --git a/media/libaudiohal/StreamHalLocal.cpp b/media/libaudiohal/StreamHalLocal.cpp
index 59314eb..12a1222 100644
--- a/media/libaudiohal/StreamHalLocal.cpp
+++ b/media/libaudiohal/StreamHalLocal.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "StreamHalLocal"
 //#define LOG_NDEBUG 0
 
+#include <hardware/audio.h>
 #include <utils/Log.h>
 
 #include "DeviceHalLocal.h"
@@ -199,9 +200,9 @@
     return OK;
 }
 
-status_t StreamOutHalLocal::drain(audio_drain_type_t type) {
+status_t StreamOutHalLocal::drain(bool earlyNotify) {
     if (mStream->drain == NULL) return INVALID_OPERATION;
-    return mStream->drain(mStream, type);
+    return mStream->drain(mStream, earlyNotify ? AUDIO_DRAIN_EARLY_NOTIFY : AUDIO_DRAIN_ALL);
 }
 
 status_t StreamOutHalLocal::flush() {
diff --git a/media/libaudiohal/StreamHalLocal.h b/media/libaudiohal/StreamHalLocal.h
index 5e6f41a..1df18cc 100644
--- a/media/libaudiohal/StreamHalLocal.h
+++ b/media/libaudiohal/StreamHalLocal.h
@@ -107,7 +107,7 @@
     virtual status_t supportsDrain(bool *supportsDrain);
 
     // Requests notification when data buffered by the driver/hardware has been played.
-    virtual status_t drain(audio_drain_type_t type);
+    virtual status_t drain(bool earlyNotify);
 
     // Notifies to the audio driver to flush the queued data.
     virtual status_t flush();
diff --git a/media/libcpustats/Android.mk b/media/libcpustats/Android.mk
index 57fe527..b2d73ee 100644
--- a/media/libcpustats/Android.mk
+++ b/media/libcpustats/Android.mk
@@ -8,6 +8,6 @@
 
 LOCAL_MODULE := libcpustats
 
-LOCAL_CFLAGS := -std=gnu++11 -Werror -Wall
+LOCAL_CFLAGS := -Werror -Wall
 
 include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libeffects/downmix/Android.mk b/media/libeffects/downmix/Android.mk
index e0ca8af..78601d5 100644
--- a/media/libeffects/downmix/Android.mk
+++ b/media/libeffects/downmix/Android.mk
@@ -20,5 +20,6 @@
 	$(call include-path-for, audio-utils)
 
 LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index 9823c55..6cbe78d 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -389,7 +389,6 @@
 
     downmix_module_t *pDwmModule = (downmix_module_t *) self;
     downmix_object_t *pDownmixer;
-    int retsize;
 
     if (pDwmModule == NULL || pDwmModule->context.state == DOWNMIX_STATE_UNINITIALIZED) {
         return -EINVAL;
diff --git a/media/libeffects/loudness/Android.mk b/media/libeffects/loudness/Android.mk
index 55d0611..3db4a79 100644
--- a/media/libeffects/loudness/Android.mk
+++ b/media/libeffects/loudness/Android.mk
@@ -8,6 +8,7 @@
 	dsp/core/dynamic_range_compression.cpp
 
 LOCAL_CFLAGS+= -O2 -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
diff --git a/media/libeffects/loudness/EffectLoudnessEnhancer.cpp b/media/libeffects/loudness/EffectLoudnessEnhancer.cpp
index a5a1a3f..11c6133 100644
--- a/media/libeffects/loudness/EffectLoudnessEnhancer.cpp
+++ b/media/libeffects/loudness/EffectLoudnessEnhancer.cpp
@@ -194,7 +194,6 @@
                          effect_handle_t *pHandle) {
     ALOGV("LELib_Create()");
     int ret;
-    int i;
 
     if (pHandle == NULL || uuid == NULL) {
         return -EINVAL;
@@ -311,7 +310,6 @@
         void *pCmdData, uint32_t *replySize, void *pReplyData) {
 
     LoudnessEnhancerContext * pContext = (LoudnessEnhancerContext *)self;
-    int retsize;
 
     if (pContext == NULL || pContext->mState == LOUDNESS_ENHANCER_STATE_UNINITIALIZED) {
         return -EINVAL;
diff --git a/media/libeffects/lvm/lib/Android.mk b/media/libeffects/lvm/lib/Android.mk
index bb56c75..afc87bb 100644
--- a/media/libeffects/lvm/lib/Android.mk
+++ b/media/libeffects/lvm/lib/Android.mk
@@ -120,6 +120,7 @@
     $(LOCAL_PATH)/StereoWidening/lib
 
 LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
 
 include $(BUILD_STATIC_LIBRARY)
 
@@ -177,4 +178,5 @@
     $(LOCAL_PATH)/Common/src
 
 LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
 include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
index 4e38e3d..9051587 100644
--- a/media/libeffects/lvm/wrapper/Android.mk
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -10,6 +10,7 @@
 	Bundle/EffectBundle.cpp
 
 LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
 
 LOCAL_MODULE:= libbundlewrapper
 
@@ -40,6 +41,7 @@
     Reverb/EffectReverb.cpp
 
 LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
 
 LOCAL_MODULE:= libreverbwrapper
 
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index d7b5f65..8aed146 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -501,8 +501,6 @@
 //----------------------------------------------------------------------------
 
 int LvmBundle_init(EffectContext *pContext){
-    int status;
-
     ALOGV("\tLvmBundle_init start");
 
     pContext->config.inputCfg.accessMode                    = EFFECT_BUFFER_ACCESS_READ;
@@ -716,7 +714,6 @@
                       int              frameCount,
                       EffectContext    *pContext){
 
-    LVM_ControlParams_t     ActiveParams;                           /* Current control Parameters */
     LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
     LVM_INT16               *pOutTmp;
 
@@ -1040,7 +1037,6 @@
 
 void LvmEffect_free(EffectContext *pContext){
     LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;         /* Function call status */
-    LVM_ControlParams_t     params;                        /* Control Parameters */
     LVM_MemTab_t            MemTab;
 
     /* Free the algorithm memory */
@@ -2007,8 +2003,6 @@
     int status = 0;
     int32_t *pParamTemp = (int32_t *)pParam;
     int32_t param = *pParamTemp++;
-    int32_t param2;
-    char *name;
 
     //ALOGV("\tBassBoost_getParameter start");
 
@@ -2125,7 +2119,6 @@
     int status = 0;
     int32_t *pParamTemp = (int32_t *)pParam;
     int32_t param = *pParamTemp++;
-    char *name;
 
     //ALOGV("\tVirtualizer_getParameter start");
 
@@ -2282,7 +2275,6 @@
                            uint32_t          *pValueSize,
                            void              *pValue){
     int status = 0;
-    int bMute = 0;
     int32_t *pParamTemp = (int32_t *)pParam;
     int32_t param = *pParamTemp++;
     int32_t param2;
@@ -2540,10 +2532,8 @@
                         uint32_t          *pValueSize,
                         void              *pValue){
     int status = 0;
-    int bMute = 0;
     int32_t *pParamTemp = (int32_t *)pParam;
     int32_t param = *pParamTemp++;;
-    char *name;
 
     //ALOGV("\tVolume_getParameter start");
 
@@ -2873,11 +2863,8 @@
                               audio_buffer_t         *inBuffer,
                               audio_buffer_t         *outBuffer){
     EffectContext * pContext = (EffectContext *) self;
-    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
     int    status = 0;
     int    processStatus = 0;
-    LVM_INT16   *in  = (LVM_INT16 *)inBuffer->raw;
-    LVM_INT16   *out = (LVM_INT16 *)outBuffer->raw;
 
 //ALOGV("\tEffect_process Start : Enabled = %d     Called = %d (%8d %8d %8d)",
 //pContext->pBundledContext->NumberEffectsEnabled,pContext->pBundledContext->NumberEffectsCalled,
@@ -3006,7 +2993,6 @@
                               uint32_t            *replySize,
                               void                *pReplyData){
     EffectContext * pContext = (EffectContext *) self;
-    int retsize;
 
     //ALOGV("\t\nEffect_command start");
 
@@ -3390,7 +3376,6 @@
             int16_t  leftdB, rightdB;
             int16_t  maxdB, pandB;
             int32_t  vol_ret[2] = {1<<24,1<<24}; // Apply no volume
-            int      status = 0;
             LVM_ControlParams_t     ActiveParams;           /* Current control Parameters */
             LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;  /* Function call status */
 
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index f7dcdda..f8b1a8e 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -326,6 +326,7 @@
     }                                         \
 }
 
+#if 0
 //----------------------------------------------------------------------------
 // MonoTo2I_32()
 //----------------------------------------------------------------------------
@@ -384,6 +385,7 @@
 
    return;
 }
+#endif
 
 static inline int16_t clamp16(int32_t sample)
 {
@@ -559,7 +561,6 @@
 void Reverb_free(ReverbContext *pContext){
 
     LVREV_ReturnStatus_en     LvmStatus=LVREV_SUCCESS;         /* Function call status */
-    LVREV_ControlParams_st    params;                        /* Control Parameters */
     LVREV_MemoryTable_st      MemTab;
 
     /* Free the algorithm memory */
@@ -708,8 +709,6 @@
 //----------------------------------------------------------------------------
 
 int Reverb_init(ReverbContext *pContext){
-    int status;
-
     ALOGV("\tReverb_init start");
 
     CHECK_ARG(pContext != NULL);
@@ -1542,7 +1541,6 @@
     int status = 0;
     int32_t *pParamTemp = (int32_t *)pParam;
     int32_t param = *pParamTemp++;
-    char *name;
     t_reverb_settings *pProperties;
 
     //ALOGV("\tReverb_getParameter start");
@@ -1898,7 +1896,6 @@
                               uint32_t            *replySize,
                               void                *pReplyData){
     android::ReverbContext * pContext = (android::ReverbContext *) self;
-    int retsize;
     LVREV_ControlParams_st    ActiveParams;              /* Current control Parameters */
     LVREV_ReturnStatus_en     LvmStatus=LVREV_SUCCESS;     /* Function call status */
 
diff --git a/media/libeffects/preprocessing/Android.mk b/media/libeffects/preprocessing/Android.mk
index bd67aa1..60030ac 100644
--- a/media/libeffects/preprocessing/Android.mk
+++ b/media/libeffects/preprocessing/Android.mk
@@ -28,5 +28,6 @@
     -DWEBRTC_POSIX
 
 LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index f48bac1..ccfd29c 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -933,7 +933,6 @@
 
 int Session_SetConfig(preproc_session_t *session, effect_config_t *config)
 {
-    uint32_t sr;
     uint32_t inCnl = audio_channel_count_from_in_mask(config->inputCfg.channels);
     uint32_t outCnl = audio_channel_count_from_in_mask(config->outputCfg.channels);
 
@@ -1153,7 +1152,6 @@
 preproc_session_t *PreProc_GetSession(int32_t procId, int32_t  sessionId, int32_t  ioId)
 {
     size_t i;
-    int free = -1;
     for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
         if (sSessions[i].io == ioId) {
             if (sSessions[i].createdMsk & (1 << procId)) {
@@ -1210,7 +1208,6 @@
                             audio_buffer_t    *outBuffer)
 {
     preproc_effect_t * effect = (preproc_effect_t *)self;
-    int    status = 0;
 
     if (effect == NULL){
         ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
@@ -1402,8 +1399,6 @@
                             void                *pReplyData)
 {
     preproc_effect_t * effect = (preproc_effect_t *) self;
-    int retsize;
-    int status;
 
     if (effect == NULL){
         return -EINVAL;
@@ -1777,7 +1772,6 @@
                                    audio_buffer_t    *outBuffer __unused)
 {
     preproc_effect_t * effect = (preproc_effect_t *)self;
-    int    status = 0;
 
     if (effect == NULL){
         ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
@@ -1926,7 +1920,6 @@
 
 int PreProcessingLib_Release(effect_handle_t interface)
 {
-    int status;
     ALOGV("EffectRelease start %p", interface);
     if (PreProc_Init() != 0) {
         return sInitStatus;
diff --git a/media/libeffects/proxy/Android.mk b/media/libeffects/proxy/Android.mk
index 2ba452e..0acf1c0 100644
--- a/media/libeffects/proxy/Android.mk
+++ b/media/libeffects/proxy/Android.mk
@@ -23,6 +23,7 @@
         EffectProxy.cpp
 
 LOCAL_CFLAGS+= -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
 
 LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libdl libeffects
 
diff --git a/media/libeffects/proxy/EffectProxy.cpp b/media/libeffects/proxy/EffectProxy.cpp
index 62d3fd3..b16a98b 100644
--- a/media/libeffects/proxy/EffectProxy.cpp
+++ b/media/libeffects/proxy/EffectProxy.cpp
@@ -44,12 +44,6 @@
 };
 
 
-static const effect_descriptor_t *const gDescriptors[] =
-{
-    &gProxyDescriptor,
-};
-
-
 int EffectProxyCreate(const effect_uuid_t *uuid,
                             int32_t             sessionId,
                             int32_t             ioId,
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index c92c543..ddcc565 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -7,6 +7,7 @@
 	EffectVisualizer.cpp
 
 LOCAL_CFLAGS+= -O2 -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 6ed9a43..4c71907 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -233,7 +233,6 @@
                          int32_t /*ioId*/,
                          effect_handle_t *pHandle) {
     int ret;
-    int i;
 
     if (pHandle == NULL || uuid == NULL) {
         return -EINVAL;
@@ -415,7 +414,6 @@
         void *pCmdData, uint32_t *replySize, void *pReplyData) {
 
     VisualizerContext * pContext = (VisualizerContext *)self;
-    int retsize;
 
     if (pContext == NULL || pContext->mState == VISUALIZER_STATE_UNINITIALIZED) {
         return -EINVAL;
@@ -602,9 +600,14 @@
     case VISUALIZER_CMD_MEASURE: {
         if (pReplyData == NULL || replySize == NULL ||
                 *replySize < (sizeof(int32_t) * MEASUREMENT_COUNT)) {
-            ALOGV("VISUALIZER_CMD_MEASURE() error *replySize %" PRIu32
-                    " < (sizeof(int32_t) * MEASUREMENT_COUNT) %" PRIu32, *replySize,
-                    uint32_t(sizeof(int32_t)) * MEASUREMENT_COUNT);
+            if (replySize == NULL) {
+                ALOGV("VISUALIZER_CMD_MEASURE() error replySize NULL");
+            } else {
+                ALOGV("VISUALIZER_CMD_MEASURE() error *replySize %" PRIu32
+                        " < (sizeof(int32_t) * MEASUREMENT_COUNT) %" PRIu32,
+                        *replySize,
+                        uint32_t(sizeof(int32_t)) * MEASUREMENT_COUNT);
+            }
             android_errorWriteLog(0x534e4554, "30229821");
             return -EINVAL;
         }
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 08b3af0..0b1bb2b 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -93,9 +93,14 @@
     $(TOP)/frameworks/native/include/media/openmax \
     $(TOP)/frameworks/av/include/media/ \
     $(TOP)/frameworks/av/media/libstagefright \
+    $(TOP)/frameworks/av/media/libmedia/aidl \
     $(call include-path-for, audio-effects) \
     $(call include-path-for, audio-utils)
 
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+    frameworks/av/include/media \
+    frameworks/av/media/libmedia/aidl
+
 LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
 LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 96fe907..516a558 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -546,6 +546,7 @@
     mUnderrunCountOffset = 0;
     mFramesWritten = 0;
     mFramesWrittenServerOffset = 0;
+    mFramesWrittenAtRestore = -1; // -1 is a unique initializer.
 
     return NO_ERROR;
 }
@@ -2188,10 +2189,12 @@
     mUnderrunCountOffset = getUnderrunCount_l();
 
     // save the old static buffer position
+    uint32_t staticPosition = 0;
     size_t bufferPosition = 0;
     int loopCount = 0;
     if (mStaticProxy != 0) {
         mStaticProxy->getBufferPositionAndLoopCount(&bufferPosition, &loopCount);
+        staticPosition = mStaticProxy->getPosition().unsignedValue();
     }
 
     mFlags = mOrigFlags;
@@ -2223,8 +2226,11 @@
         }
         if (mState == STATE_ACTIVE) {
             result = mAudioTrack->start();
-            mFramesWrittenServerOffset = mFramesWritten; // server resets to zero so we offset
         }
+        // server resets to zero so we offset
+        mFramesWrittenServerOffset =
+                mStaticProxy.get() != nullptr ? staticPosition : mFramesWritten;
+        mFramesWrittenAtRestore = mFramesWrittenServerOffset;
     }
     if (result != NO_ERROR) {
         ALOGW("restoreTrack_l() failed status %d", result);
@@ -2427,7 +2433,17 @@
             }
         }
         if (status == INVALID_OPERATION) {
-            status = WOULD_BLOCK;
+            // INVALID_OPERATION occurs when no timestamp has been issued by the server;
+            // other failures are signaled by a negative time.
+            // If we come out of FLUSHED or STOPPED where the position is known
+            // to be zero we convert this to WOULD_BLOCK (with the implicit meaning of
+            // "zero" for NuPlayer).  We don't convert for track restoration as position
+            // does not reset.
+            ALOGV("timestamp server offset:%lld restore frames:%lld",
+                    (long long)mFramesWrittenServerOffset, (long long)mFramesWrittenAtRestore);
+            if (mFramesWrittenServerOffset != mFramesWrittenAtRestore) {
+                status = WOULD_BLOCK;
+            }
         }
     }
     if (status != NO_ERROR) {
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index a6860e2..5599830 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -29,6 +29,7 @@
 #include <media/IMediaRecorder.h>
 #include <gui/Surface.h>
 #include <gui/IGraphicBufferProducer.h>
+#include <media/stagefright/PersistentSurface.h>
 
 namespace android {
 
@@ -79,12 +80,12 @@
         return reply.readInt32();
     }
 
-    status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface)
+    status_t setInputSurface(const sp<PersistentSurface>& surface)
     {
         ALOGV("setInputSurface(%p)", surface.get());
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(surface));
+        surface->writeToParcel(&data);
         remote()->transact(SET_INPUT_SURFACE, data, &reply);
         return reply.readInt32();
     }
@@ -490,8 +491,8 @@
         case SET_INPUT_SURFACE: {
             ALOGV("SET_INPUT_SURFACE");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
-            sp<IGraphicBufferConsumer> surface = interface_cast<IGraphicBufferConsumer>(
-                    data.readStrongBinder());
+            sp<PersistentSurface> surface = new PersistentSurface();
+            surface->readFromParcel(&data);
             reply->writeInt32(setInputSurface(surface));
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index fb05fef..1901d8c 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -27,7 +27,9 @@
 #include <media/openmax/OMX_IndexExt.h>
 #include <utils/NativeHandle.h>
 
+#include <gui/IGraphicBufferProducer.h>
 #include <android/IGraphicBufferSource.h>
+#include <android/IOMXBufferSource.h>
 
 namespace android {
 
@@ -45,12 +47,10 @@
     USE_BUFFER,
     USE_GRAPHIC_BUFFER,
     CREATE_INPUT_SURFACE,
-    CREATE_PERSISTENT_INPUT_SURFACE,
     SET_INPUT_SURFACE,
     STORE_META_DATA_IN_BUFFERS,
     PREPARE_FOR_ADAPTIVE_PLAYBACK,
     ALLOC_SECURE_BUFFER,
-    ALLOC_BUFFER_WITH_BACKUP,
     FREE_BUFFER,
     FILL_BUFFER,
     EMPTY_BUFFER,
@@ -62,6 +62,7 @@
     CONFIGURE_VIDEO_TUNNEL_MODE,
     UPDATE_NATIVE_HANDLE_IN_META,
     DISPATCH_MESSAGE,
+    SET_QUIRKS,
 };
 
 class BpOMX : public BpInterface<IOMX> {
@@ -111,13 +112,13 @@
         return err;
     }
 
-    virtual status_t createPersistentInputSurface(
+    virtual status_t createInputSurface(
             sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferConsumer> *bufferConsumer) {
+            sp<IGraphicBufferSource> *bufferSource) {
         Parcel data, reply;
         status_t err;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        err = remote()->transact(CREATE_PERSISTENT_INPUT_SURFACE, data, &reply);
+        err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
         if (err != OK) {
             ALOGW("binder transaction failed: %d", err);
             return err;
@@ -130,7 +131,7 @@
 
         *bufferProducer = IGraphicBufferProducer::asInterface(
                 reply.readStrongBinder());
-        *bufferConsumer = IGraphicBufferConsumer::asInterface(
+        *bufferSource = IGraphicBufferSource::asInterface(
                 reply.readStrongBinder());
 
         return err;
@@ -328,72 +329,21 @@
         return err;
     }
 
-    virtual status_t createInputSurface(
-            OMX_U32 port_index, android_dataspace dataSpace,
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type) {
-        Parcel data, reply;
-        status_t err;
-        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
-        data.writeInt32(port_index);
-        data.writeInt32(dataSpace);
-        err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
-        if (err != OK) {
-            ALOGW("binder transaction failed: %d", err);
-            return err;
-        }
-
-        // read type even if createInputSurface failed
-        int negotiatedType = reply.readInt32();
-        if (type != NULL) {
-            *type = (MetadataBufferType)negotiatedType;
-        }
-
-        err = reply.readInt32();
-        if (err != OK) {
-            return err;
-        }
-
-        *bufferProducer = IGraphicBufferProducer::asInterface(
-                reply.readStrongBinder());
-        *bufferSource = IGraphicBufferSource::asInterface(
-                reply.readStrongBinder());
-
-        return err;
-    }
-
     virtual status_t setInputSurface(
-            OMX_U32 port_index,
-            const sp<IGraphicBufferConsumer> &bufferConsumer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type) {
+            const sp<IOMXBufferSource> &bufferSource) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
-        status_t err;
-        data.writeInt32(port_index);
-        data.writeStrongBinder(IInterface::asBinder(bufferConsumer));
 
-        err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
+        data.writeStrongBinder(IInterface::asBinder(bufferSource));
+
+        status_t err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
 
         if (err != OK) {
             ALOGW("binder transaction failed: %d", err);
             return err;
         }
 
-        // read type even if setInputSurface failed
-        int negotiatedType = reply.readInt32();
-        if (type != NULL) {
-            *type = (MetadataBufferType)negotiatedType;
-        }
-
         err = reply.readInt32();
-        if (err != OK) {
-            return err;
-        }
-
-        *bufferSource = IGraphicBufferSource::asInterface(
-                reply.readStrongBinder());
 
         return err;
     }
@@ -478,28 +428,6 @@
         return err;
     }
 
-    virtual status_t allocateBufferWithBackup(
-            OMX_U32 port_index, const sp<IMemory> &params,
-            buffer_id *buffer, OMX_U32 allottedSize) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
-        data.writeInt32(port_index);
-        data.writeStrongBinder(IInterface::asBinder(params));
-        data.writeInt32(allottedSize);
-        remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
-
-        status_t err = reply.readInt32();
-        if (err != OK) {
-            *buffer = 0;
-
-            return err;
-        }
-
-        *buffer = (buffer_id)reply.readInt32();
-
-        return err;
-    }
-
     virtual status_t freeBuffer(
             OMX_U32 port_index, buffer_id buffer) {
         Parcel data, reply;
@@ -597,6 +525,16 @@
 
         return reply.readInt32();
     }
+
+    virtual status_t setQuirks(OMX_U32 quirks) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(quirks);
+
+        remote()->transact(SET_QUIRKS, data, &reply);
+
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
@@ -663,20 +601,19 @@
             return NO_ERROR;
         }
 
-        case CREATE_PERSISTENT_INPUT_SURFACE:
+        case CREATE_INPUT_SURFACE:
         {
             CHECK_OMX_INTERFACE(IOMX, data, reply);
 
             sp<IGraphicBufferProducer> bufferProducer;
-            sp<IGraphicBufferConsumer> bufferConsumer;
-            status_t err = createPersistentInputSurface(
-                    &bufferProducer, &bufferConsumer);
+            sp<IGraphicBufferSource> bufferSource;
+            status_t err = createInputSurface(&bufferProducer, &bufferSource);
 
             reply->writeInt32(err);
 
             if (err == OK) {
                 reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
-                reply->writeStrongBinder(IInterface::asBinder(bufferConsumer));
+                reply->writeStrongBinder(IInterface::asBinder(bufferSource));
             }
 
             return NO_ERROR;
@@ -909,62 +846,16 @@
             return NO_ERROR;
         }
 
-        case CREATE_INPUT_SURFACE:
-        {
-            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
-
-            OMX_U32 port_index = data.readInt32();
-            android_dataspace dataSpace = (android_dataspace)data.readInt32();
-
-            sp<IGraphicBufferProducer> bufferProducer;
-            sp<IGraphicBufferSource> bufferSource;
-            MetadataBufferType type = kMetadataBufferTypeInvalid;
-            status_t err = createInputSurface(
-                    port_index, dataSpace, &bufferProducer, &bufferSource, &type);
-
-            if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
-                android_errorWriteLog(0x534e4554, "26324358");
-            }
-
-            reply->writeInt32(type);
-            reply->writeInt32(err);
-
-            if (err == OK) {
-                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
-                reply->writeStrongBinder(IInterface::asBinder(bufferSource));
-            }
-
-            return NO_ERROR;
-        }
-
         case SET_INPUT_SURFACE:
         {
             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            OMX_U32 port_index = data.readInt32();
+            sp<IOMXBufferSource> bufferSource =
+                    interface_cast<IOMXBufferSource>(data.readStrongBinder());
 
-            sp<IGraphicBufferConsumer> bufferConsumer =
-                    interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());
-
-            sp<IGraphicBufferSource> bufferSource;
-            MetadataBufferType type = kMetadataBufferTypeInvalid;
-
-            status_t err = INVALID_OPERATION;
-            if (bufferConsumer == NULL) {
-                ALOGE("b/26392700");
-            } else {
-                err = setInputSurface(port_index, bufferConsumer, &bufferSource, &type);
-
-                if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
-                   android_errorWriteLog(0x534e4554, "26324358");
-                }
-            }
-
-            reply->writeInt32(type);
+            status_t err = setInputSurface(bufferSource);
             reply->writeInt32(err);
-            if (err == OK) {
-                reply->writeStrongBinder(IInterface::asBinder(bufferSource));
-            }
+
             return NO_ERROR;
         }
 
@@ -1050,34 +941,6 @@
             return NO_ERROR;
         }
 
-        case ALLOC_BUFFER_WITH_BACKUP:
-        {
-            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
-
-            OMX_U32 port_index = data.readInt32();
-            sp<IMemory> params =
-                interface_cast<IMemory>(data.readStrongBinder());
-            OMX_U32 allottedSize = data.readInt32();
-
-            if (params == NULL) {
-                ALOGE("b/26392700");
-                reply->writeInt32(INVALID_OPERATION);
-                return NO_ERROR;
-            }
-
-            buffer_id buffer;
-            status_t err = allocateBufferWithBackup(
-                    port_index, params, &buffer, allottedSize);
-
-            reply->writeInt32(err);
-
-            if (err == OK) {
-                reply->writeInt32((int32_t)buffer);
-            }
-
-            return NO_ERROR;
-        }
-
         case FREE_BUFFER:
         {
             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
@@ -1178,6 +1041,17 @@
             return NO_ERROR;
         }
 
+        case SET_QUIRKS:
+        {
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
+
+            OMX_U32 quirks = data.readInt32();
+
+            reply->writeInt32(setQuirks(quirks));
+
+            return NO_ERROR;
+        }
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/aidl/android/IGraphicBufferSource.aidl b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
index adbb75f..e9bf739 100644
--- a/media/libmedia/aidl/android/IGraphicBufferSource.aidl
+++ b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
@@ -16,12 +16,15 @@
 
 package android;
 
+import android.IOMXNode;
+
 /**
  * Binder interface for controlling a graphic buffer source.
  *
  * @hide
  */
 interface IGraphicBufferSource {
+    void configure(IOMXNode omxNode, int dataSpace);
     void setSuspend(boolean suspend);
     void setRepeatPreviousFrameDelayUs(long repeatAfterUs);
     void setMaxTimestampGapUs(long maxGapUs);
diff --git a/media/libmedia/aidl/android/IOMXNode.aidl b/media/libmedia/aidl/android/IOMXNode.aidl
new file mode 100644
index 0000000..ec87fd2
--- /dev/null
+++ b/media/libmedia/aidl/android/IOMXNode.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package android;
+
+/** @hide */
+interface IOMXNode {
+    // Stub for manual implementation
+}
diff --git a/media/libmedia/aidl/android/IOMXNode.h b/media/libmedia/aidl/android/IOMXNode.h
new file mode 100644
index 0000000..7b17614
--- /dev/null
+++ b/media/libmedia/aidl/android/IOMXNode.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/IOMX.h>
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 59c077a..6eb208c 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -361,7 +361,7 @@
         return INVALID_OPERATION;
     }
 
-    return mMediaRecorder->setInputSurface(surface->getBufferConsumer());
+    return mMediaRecorder->setInputSurface(surface);
 }
 
 status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index d011d70..94ceae4 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -52,7 +52,7 @@
     return ok;
 }
 
-status_t MediaRecorderClient::setInputSurface(const sp<IGraphicBufferConsumer>& surface)
+status_t MediaRecorderClient::setInputSurface(const sp<PersistentSurface>& surface)
 {
     ALOGV("setInputSurface");
     Mutex::Autolock lock(mLock);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index eceb653..12656cf 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -25,7 +25,6 @@
 class MediaRecorderBase;
 class MediaPlayerService;
 class ICameraRecordingProxy;
-class IGraphicBufferProducer;
 
 class MediaRecorderClient : public BnMediaRecorder
 {
@@ -73,7 +72,7 @@
     virtual     status_t   close();
     virtual     status_t   release();
     virtual     status_t   dump(int fd, const Vector<String16>& args);
-    virtual     status_t   setInputSurface(const sp<IGraphicBufferConsumer>& surface);
+    virtual     status_t   setInputSurface(const sp<PersistentSurface>& surface);
     virtual     sp<IGraphicBufferProducer> querySurfaceMediaSource();
 
 private:
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index a748b46..279bc86 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -45,6 +45,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MediaCodecSource.h>
+#include <media/stagefright/PersistentSurface.h>
 #include <media/MediaProfiles.h>
 #include <camera/CameraParameters.h>
 
@@ -248,7 +249,7 @@
 }
 
 status_t StagefrightRecorder::setInputSurface(
-        const sp<IGraphicBufferConsumer>& surface) {
+        const sp<PersistentSurface>& surface) {
     mPersistentSurface = surface;
 
     return OK;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 4dbd039..4c2e65c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -38,9 +38,6 @@
 class MetaData;
 struct AudioSource;
 class MediaProfiles;
-class IGraphicBufferConsumer;
-class IGraphicBufferProducer;
-class SurfaceMediaSource;
 struct ALooper;
 
 struct StagefrightRecorder : public MediaRecorderBase {
@@ -57,7 +54,7 @@
     virtual status_t setVideoFrameRate(int frames_per_second);
     virtual status_t setCamera(const sp<hardware::ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
     virtual status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
-    virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface);
+    virtual status_t setInputSurface(const sp<PersistentSurface>& surface);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
     virtual status_t setParameters(const String8 &params);
     virtual status_t setListener(const sp<IMediaRecorderClient> &listener);
@@ -78,7 +75,7 @@
     sp<hardware::ICamera> mCamera;
     sp<ICameraRecordingProxy> mCameraProxy;
     sp<IGraphicBufferProducer> mPreviewSurface;
-    sp<IGraphicBufferConsumer> mPersistentSurface;
+    sp<PersistentSurface> mPersistentSurface;
     sp<IMediaRecorderClient> mListener;
     String16 mClientName;
     uid_t mClientUid;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index ac49993..7178661 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1340,7 +1340,16 @@
     }
 
     sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
+    sp<MetaData> videoMeta = mSource->getFormatMeta(false /* audio */);
+    if (audioMeta == NULL && videoMeta == NULL) {
+        ALOGE("no metadata for either audio or video source");
+        mSource->stop();
+        mSourceStarted = false;
+        notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_MALFORMED);
+        return;
+    }
     ALOGV_IF(audioMeta == NULL, "no metadata for audio source");  // video only stream
+
     audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
     if (mAudioSink != NULL) {
         streamType = mAudioSink->getAudioStreamType();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index ffeea86..e4767ff 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -290,12 +290,8 @@
         return;
     }
 
-    sp<RefBase> obj;
-    bool hasBuffer = msg->findObject("buffer", &obj);
-    sp<MediaCodecBuffer> buffer;
-    if (hasBuffer) {
-        buffer = static_cast<MediaCodecBuffer *>(obj.get());
-    }
+    sp<ABuffer> buffer;
+    bool hasBuffer = msg->findBuffer("buffer", &buffer);
     if (buffer == NULL) {
         int32_t streamErr = ERROR_END_OF_STREAM;
         CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
@@ -324,10 +320,9 @@
     int32_t bufferSize = buffer->size();
     mCachedBytes += bufferSize;
 
+    int64_t timeUs = 0;
+    CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
     if (mSkipRenderingUntilMediaTimeUs >= 0) {
-        int64_t timeUs = 0;
-        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
-
         if (timeUs < mSkipRenderingUntilMediaTimeUs) {
             ALOGV("[%s] dropping buffer at time %lld as requested.",
                      mComponentName.c_str(), (long long)timeUs);
@@ -348,7 +343,10 @@
     reply->setInt32("generation", mBufferGeneration);
     reply->setInt32("size", bufferSize);
 
-    mRenderer->queueBuffer(true /* audio */, buffer, reply);
+    sp<MediaCodecBuffer> mcBuffer = new MediaCodecBuffer(nullptr, buffer);
+    mcBuffer->meta()->setInt64("timeUs", timeUs);
+
+    mRenderer->queueBuffer(true /* audio */, mcBuffer, reply);
 
     ++mPendingBuffersToDrain;
     ALOGV("onInputBufferFilled: #ToDrain = %zu, cachedBytes = %zu",
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index e4047c8..478de35 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -56,8 +56,6 @@
 #include "include/SharedMemoryBuffer.h"
 #include "omx/OMXUtils.h"
 
-#include <android/IGraphicBufferSource.h>
-
 namespace android {
 
 using binder::Status;
@@ -510,7 +508,6 @@
 
 ACodec::ACodec()
     : mSampleRate(0),
-      mQuirks(0),
       mNodeGeneration(0),
       mUsingNativeWindow(false),
       mNativeWindowUsageBits(0),
@@ -881,11 +878,6 @@
                 info.mRenderInfo = NULL;
                 info.mNativeHandle = NULL;
 
-                uint32_t requiresAllocateBufferBit =
-                    (portIndex == kPortIndexInput)
-                        ? kRequiresAllocateBufferOnInputPorts
-                        : kRequiresAllocateBufferOnOutputPorts;
-
                 if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) {
                     mem.clear();
 
@@ -909,11 +901,9 @@
                             new ABuffer(ptr != NULL ? ptr : (void *)native_handle_ptr, bufSize));
                     info.mNativeHandle = native_handle;
                     info.mCodecData = info.mData;
-                } else if (mQuirks & requiresAllocateBufferBit) {
-                    err = mOMXNode->allocateBufferWithBackup(
-                            portIndex, mem, &info.mBufferID, allottedSize);
                 } else {
-                    err = mOMXNode->useBuffer(portIndex, mem, &info.mBufferID, allottedSize);
+                    err = mOMXNode->useBuffer(
+                            portIndex, mem, &info.mBufferID, allottedSize);
                 }
 
                 if (mem != NULL) {
@@ -6233,7 +6223,6 @@
     mCodec->mNativeWindowUsageBits = 0;
     mCodec->mOMX.clear();
     mCodec->mOMXNode.clear();
-    mCodec->mQuirks = 0;
     mCodec->mFlags = 0;
     mCodec->mInputMetadataType = kMetadataBufferTypeInvalid;
     mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid;
@@ -6407,7 +6396,7 @@
         mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
     }
 
-    mCodec->mQuirks = quirks;
+    omxNode->setQuirks(quirks);
     mCodec->mOMX = omx;
     mCodec->mOMXNode = omxNode;
 
@@ -6568,7 +6557,25 @@
 }
 
 status_t ACodec::LoadedState::setupInputSurface() {
-    status_t err = OK;
+    if (mCodec->mGraphicBufferSource == NULL) {
+        return BAD_VALUE;
+    }
+
+    android_dataspace dataSpace;
+    status_t err =
+        mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
+    if (err != OK) {
+        ALOGE("Failed to get default data space");
+        return err;
+    }
+
+    err = statusFromBinderStatus(
+            mCodec->mGraphicBufferSource->configure(mCodec->mOMXNode, dataSpace));
+    if (err != OK) {
+        ALOGE("[%s] Unable to configure for node (err %d)",
+              mCodec->mComponentName.c_str(), err);
+        return err;
+    }
 
     if (mCodec->mRepeatFrameDelayUs > 0ll) {
         err = statusFromBinderStatus(
@@ -6664,30 +6671,20 @@
     sp<AMessage> notify = mCodec->mNotify->dup();
     notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
 
-    android_dataspace dataSpace;
-    status_t err =
-        mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
-    notify->setMessage("input-format", mCodec->mInputFormat);
-    notify->setMessage("output-format", mCodec->mOutputFormat);
-
     sp<IGraphicBufferProducer> bufferProducer;
-    if (err == OK) {
-        mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-        err = mCodec->mOMXNode->createInputSurface(
-                mCodec->kPortIndexInput, dataSpace,
-                &bufferProducer, &mCodec->mGraphicBufferSource,
-                &mCodec->mInputMetadataType);
-        // framework uses ANW buffers internally instead of gralloc handles
-        if (mCodec->mInputMetadataType == kMetadataBufferTypeGrallocSource) {
-            mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-        }
-    }
+    status_t err = mCodec->mOMX->createInputSurface(
+            &bufferProducer, &mCodec->mGraphicBufferSource);
 
     if (err == OK) {
         err = setupInputSurface();
     }
 
     if (err == OK) {
+        mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
+
+        notify->setMessage("input-format", mCodec->mInputFormat);
+        notify->setMessage("output-format", mCodec->mOutputFormat);
+
         notify->setObject("input-surface",
                 new BufferProducerWrapper(bufferProducer));
     } else {
@@ -6711,32 +6708,16 @@
     sp<RefBase> obj;
     CHECK(msg->findObject("input-surface", &obj));
     sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
+    mCodec->mGraphicBufferSource = surface->getBufferSource();
 
-    android_dataspace dataSpace;
-    status_t err =
-        mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
-    notify->setMessage("input-format", mCodec->mInputFormat);
-    notify->setMessage("output-format", mCodec->mOutputFormat);
+    status_t err = setupInputSurface();
 
     if (err == OK) {
         mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-        err = mCodec->mOMXNode->setInputSurface(
-                mCodec->kPortIndexInput,
-                surface->getBufferConsumer(),
-                &mCodec->mGraphicBufferSource,
-                &mCodec->mInputMetadataType);
-        // framework uses ANW buffers internally instead of gralloc handles
-        if (mCodec->mInputMetadataType == kMetadataBufferTypeGrallocSource) {
-            mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-        }
-    }
 
-    if (err == OK) {
-        surface->getBufferConsumer()->setDefaultBufferDataSpace(dataSpace);
-        err = setupInputSurface();
-    }
-
-    if (err != OK) {
+        notify->setMessage("input-format", mCodec->mInputFormat);
+        notify->setMessage("output-format", mCodec->mOutputFormat);
+    } else {
         // Can't use mCodec->signalError() here -- MediaCodec won't forward
         // the error through because it's in the "configured" state.  We
         // send a kWhatInputSurfaceAccepted with an error value instead.
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 6700352..d37e973 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -374,7 +374,6 @@
       mMdatFound(false),
       mDataSource(source),
       mInitCheck(NO_INIT),
-      mHasVideo(false),
       mHeaderTimescale(0),
       mIsQT(false),
       mFirstTrack(NULL),
@@ -545,11 +544,13 @@
     }
 
     if (mInitCheck == OK) {
-        if (mHasVideo) {
+        if (findTrackByMimePrefix("video/") != NULL) {
             mFileMetaData->setCString(
                     kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
-        } else {
+        } else if (findTrackByMimePrefix("audio/") != NULL) {
             mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
+        } else {
+            mFileMetaData->setCString(kKeyMIMEType, "application/octet-stream");
         }
     } else {
         mInitCheck = err;
@@ -1485,8 +1486,6 @@
         case FOURCC('h', 'v', 'c', '1'):
         case FOURCC('h', 'e', 'v', '1'):
         {
-            mHasVideo = true;
-
             uint8_t buffer[78];
             if (chunk_data_size < (ssize_t)sizeof(buffer)) {
                 // Basic VideoSampleEntry size.
@@ -1829,6 +1828,9 @@
         case FOURCC('b', 't', 'r', 't'):
         {
             *offset += chunk_size;
+            if (mLastTrack == NULL) {
+                return ERROR_MALFORMED;
+            }
 
             uint8_t buffer[12];
             if (chunk_data_size != sizeof(buffer)) {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index fc9f644..465ebc8 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -213,50 +213,24 @@
 // static
 sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() {
     OMXClient client;
-    CHECK_EQ(client.connect(), (status_t)OK);
+    if (client.connect() != OK) {
+        ALOGE("Failed to connect to OMX to create persistent input surface.");
+        return NULL;
+    }
+
     sp<IOMX> omx = client.interface();
 
-    const sp<IMediaCodecList> mediaCodecList = MediaCodecList::getInstance();
-    if (mediaCodecList == NULL) {
-        ALOGE("Failed to obtain MediaCodecList!");
-        return NULL; // if called from Java should raise IOException
-    }
-
-    AString tmp;
-    sp<AMessage> globalSettings = mediaCodecList->getGlobalSettings();
-    if (globalSettings == NULL || !globalSettings->findString(
-            kMaxEncoderInputBuffers, &tmp)) {
-        ALOGE("Failed to get encoder input buffer count!");
-        return NULL;
-    }
-
-    int32_t bufferCount = strtol(tmp.c_str(), NULL, 10);
-    if (bufferCount <= 0
-            || bufferCount > BufferQueue::MAX_MAX_ACQUIRED_BUFFERS) {
-        ALOGE("Encoder input buffer count is invalid!");
-        return NULL;
-    }
-
     sp<IGraphicBufferProducer> bufferProducer;
-    sp<IGraphicBufferConsumer> bufferConsumer;
+    sp<IGraphicBufferSource> bufferSource;
 
-    status_t err = omx->createPersistentInputSurface(
-            &bufferProducer, &bufferConsumer);
+    status_t err = omx->createInputSurface(&bufferProducer, &bufferSource);
 
     if (err != OK) {
         ALOGE("Failed to create persistent input surface.");
         return NULL;
     }
 
-    err = bufferConsumer->setMaxAcquiredBufferCount(bufferCount);
-
-    if (err != NO_ERROR) {
-        ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
-                bufferCount, err);
-        return NULL;
-    }
-
-    return new PersistentSurface(bufferProducer, bufferConsumer);
+    return new PersistentSurface(bufferProducer, bufferSource);
 }
 
 MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid)
@@ -1311,6 +1285,8 @@
                     status_t err = NO_ERROR;
                     sp<AMessage> response = new AMessage();
                     if (!msg->findInt32("err", &err)) {
+                        CHECK(msg->findMessage("input-format", &mInputFormat));
+                        CHECK(msg->findMessage("output-format", &mOutputFormat));
                         mHaveInputSurface = true;
                     } else {
                         response->setInt32("err", err);
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 1f869b1..93643c2 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -44,8 +44,6 @@
 
 namespace android {
 
-const char *kMaxEncoderInputBuffers = "max-video-encoder-input-buffers";
-
 static Mutex sInitMutex;
 
 static bool parseBoolean(const char *s) {
diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp
index 33795f3..095fc6a 100644
--- a/media/libstagefright/MediaCodecListOverrides.cpp
+++ b/media/libstagefright/MediaCodecListOverrides.cpp
@@ -127,61 +127,6 @@
     return format;
 }
 
-static size_t doProfileEncoderInputBuffers(
-        const AString &name, const AString &mime, const sp<MediaCodecInfo::Capabilities> &caps) {
-    ALOGV("doProfileEncoderInputBuffers: name %s, mime %s", name.c_str(), mime.c_str());
-
-    sp<AMessage> format = getMeasureFormat(true /* isEncoder */, mime, caps);
-    if (format == NULL) {
-        return 0;
-    }
-
-    format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
-    ALOGV("doProfileEncoderInputBuffers: format %s", format->debugString().c_str());
-
-    status_t err = OK;
-    sp<ALooper> looper = new ALooper;
-    looper->setName("MediaCodec_looper");
-    looper->start(
-            false /* runOnCallingThread */, false /* canCallJava */, ANDROID_PRIORITY_AUDIO);
-
-    sp<MediaCodec> codec = MediaCodec::CreateByComponentName(looper, name.c_str(), &err);
-    if (err != OK) {
-        ALOGE("Failed to create codec: %s", name.c_str());
-        return 0;
-    }
-
-    err = codec->configure(format, NULL, NULL, MediaCodec::CONFIGURE_FLAG_ENCODE);
-    if (err != OK) {
-        ALOGE("Failed to configure codec: %s with mime: %s", name.c_str(), mime.c_str());
-        codec->release();
-        return 0;
-    }
-
-    sp<IGraphicBufferProducer> bufferProducer;
-    err = codec->createInputSurface(&bufferProducer);
-    if (err != OK) {
-        ALOGE("Failed to create surface: %s with mime: %s", name.c_str(), mime.c_str());
-        codec->release();
-        return 0;
-    }
-
-    int minUndequeued = 0;
-    err = bufferProducer->query(
-            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeued);
-    if (err != OK) {
-        ALOGE("Failed to query NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS");
-        minUndequeued = 0;
-    }
-
-    err = codec->release();
-    if (err != OK) {
-        ALOGW("Failed to release codec: %s with mime: %s", name.c_str(), mime.c_str());
-    }
-
-    return minUndequeued;
-}
-
 static size_t doProfileCodecs(
         bool isEncoder, const AString &name, const AString &mime, const sp<MediaCodecInfo::Capabilities> &caps) {
     sp<AMessage> format = getMeasureFormat(isEncoder, mime, caps);
@@ -276,7 +221,6 @@
         bool forceToMeasure) {
     KeyedVector<AString, sp<MediaCodecInfo::Capabilities>> codecsNeedMeasure;
     AString supportMultipleSecureCodecs = "true";
-    size_t maxEncoderInputBuffers = 0;
     for (size_t i = 0; i < infos.size(); ++i) {
         const sp<MediaCodecInfo> info = infos[i];
         AString name = info->getCodecName();
@@ -319,21 +263,9 @@
                         supportMultipleSecureCodecs = "false";
                     }
                 }
-                if (info->isEncoder() && mimes[i].startsWith("video/")) {
-                    size_t encoderInputBuffers =
-                        doProfileEncoderInputBuffers(name, mimes[i], caps);
-                    if (encoderInputBuffers > maxEncoderInputBuffers) {
-                        maxEncoderInputBuffers = encoderInputBuffers;
-                    }
-                }
             }
         }
     }
-    if (maxEncoderInputBuffers > 0) {
-        char tmp[32];
-        sprintf(tmp, "%zu", maxEncoderInputBuffers);
-        global_results->add(kMaxEncoderInputBuffers, tmp);
-    }
     global_results->add(kPolicySupportsMultipleSecureCodecs, supportMultipleSecureCodecs);
 }
 
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 8391d76..de4d06f 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -20,7 +20,6 @@
 
 #include <inttypes.h>
 
-#include <gui/IGraphicBufferConsumer.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/Surface.h>
 #include <media/ICrypto.h>
@@ -36,7 +35,6 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/PersistentSurface.h>
 #include <media/stagefright/Utils.h>
 
 namespace android {
@@ -326,10 +324,10 @@
         const sp<ALooper> &looper,
         const sp<AMessage> &format,
         const sp<MediaSource> &source,
-        const sp<IGraphicBufferConsumer> &consumer,
+        const sp<PersistentSurface> &persistentSurface,
         uint32_t flags) {
-    sp<MediaCodecSource> mediaSource =
-            new MediaCodecSource(looper, format, source, consumer, flags);
+    sp<MediaCodecSource> mediaSource = new MediaCodecSource(
+            looper, format, source, persistentSurface, flags);
 
     if (mediaSource->init() == OK) {
         return mediaSource;
@@ -405,7 +403,7 @@
         const sp<ALooper> &looper,
         const sp<AMessage> &outputFormat,
         const sp<MediaSource> &source,
-        const sp<IGraphicBufferConsumer> &consumer,
+        const sp<PersistentSurface> &persistentSurface,
         uint32_t flags)
     : mLooper(looper),
       mOutputFormat(outputFormat),
@@ -418,7 +416,7 @@
       mSetEncoderFormat(false),
       mEncoderFormat(0),
       mEncoderDataSpace(0),
-      mGraphicBufferConsumer(consumer),
+      mPersistentSurface(persistentSurface),
       mInputBufferTimeOffsetUs(0),
       mFirstSampleSystemTimeUs(-1ll),
       mPausePending(false),
@@ -515,12 +513,11 @@
     if (mFlags & FLAG_USE_SURFACE_INPUT) {
         CHECK(mIsVideo);
 
-        if (mGraphicBufferConsumer != NULL) {
+        if (mPersistentSurface != NULL) {
             // When using persistent surface, we are only interested in the
             // consumer, but have to use PersistentSurface as a wrapper to
             // pass consumer over messages (similar to BufferProducerWrapper)
-            err = mEncoder->setInputSurface(
-                    new PersistentSurface(NULL, mGraphicBufferConsumer));
+            err = mEncoder->setInputSurface(mPersistentSurface);
         } else {
             err = mEncoder->createInputSurface(&mGraphicBufferProducer);
         }
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 773f3ed..65bb428 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -754,9 +754,9 @@
 
     if (numTracks == 1) {
         const char *fileMIME;
-        CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
 
-        if (!strcasecmp(fileMIME, "video/x-matroska")) {
+        if (meta->findCString(kKeyMIMEType, &fileMIME) &&
+                !strcasecmp(fileMIME, "video/x-matroska")) {
             sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
             const char *trackMIME;
             CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 6b57e6f..fa05886 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -93,7 +93,6 @@
 
     sp<DataSource> mDataSource;
     status_t mInitCheck;
-    bool mHasVideo;
     uint32_t mHeaderTimescale;
     bool mIsQT;
 
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index 2e62806..9edd0de 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -37,9 +37,9 @@
             const char *name, const sp<IOMXObserver> &observer,
             sp<IOMXNode> *omxNode);
 
-    virtual status_t createPersistentInputSurface(
+    virtual status_t createInputSurface(
             sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferConsumer> *bufferConsumer);
+            sp<IGraphicBufferSource> *bufferSource);
 
     virtual void binderDied(const wp<IBinder> &the_late_who);
 
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 640f840..d911508 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -25,7 +25,6 @@
 #include <utils/threads.h>
 
 namespace android {
-class IGraphicBufferSource;
 class IOMXBufferSource;
 class IOMXObserver;
 struct OMXMaster;
@@ -81,30 +80,13 @@
             OMX_U32 portIndex, const sp<NativeHandle> &nativeHandle,
             OMX::buffer_id buffer);
 
-    status_t createInputSurface(
-            OMX_U32 portIndex, android_dataspace dataSpace,
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type);
-
-    static status_t createPersistentInputSurface(
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferConsumer> *bufferConsumer);
-
     status_t setInputSurface(
-            OMX_U32 portIndex,
-            const sp<IGraphicBufferConsumer> &bufferConsumer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type);
+            const sp<IOMXBufferSource> &bufferSource);
 
     status_t allocateSecureBuffer(
             OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
             void **buffer_data, sp<NativeHandle> *native_handle);
 
-    status_t allocateBufferWithBackup(
-            OMX_U32 portIndex, const sp<IMemory> &params,
-            OMX::buffer_id *buffer, OMX_U32 allottedSize);
-
     status_t freeBuffer(OMX_U32 portIndex, OMX::buffer_id buffer);
 
     status_t fillBuffer(OMX::buffer_id buffer, int fenceFd);
@@ -122,6 +104,8 @@
     status_t getExtensionIndex(
             const char *parameterName, OMX_INDEXTYPE *index);
 
+    status_t setQuirks(OMX_U32 quirks);
+
     bool isSecure() const {
         return mIsSecure;
     }
@@ -150,6 +134,7 @@
     bool mQueriedProhibitedExtensions;
     SortedVector<OMX_INDEXTYPE> mProhibitedExtensions;
     bool mIsSecure;
+    uint32_t mQuirks;
 
     // Lock only covers mOMXBufferSource and mOMXOutputListener.  We can't always
     // use mLock because of rare instances where we'd end up locking it recursively.
@@ -251,14 +236,8 @@
     // buffer.)
     status_t updateGraphicBufferInMeta_l(
             OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
-            OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header, bool updateCodecBuffer);
+            OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header);
 
-    status_t createGraphicBufferSource(
-            OMX_U32 portIndex, android_dataspace dataSpace,
-            const sp<IGraphicBufferConsumer> &bufferConsumer,
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type);
     sp<IOMXBufferSource> getBufferSource();
     void setBufferSource(const sp<IOMXBufferSource> &bufferSource);
     // Called when omx_message::FILL_BUFFER_DONE is received. (Currently the
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 25bc41c..afb8173 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -31,93 +31,22 @@
 #include <ui/GraphicBuffer.h>
 #include <gui/BufferItem.h>
 #include <HardwareAPI.h>
+#include "omx/OMXUtils.h"
+#include <OMX_Component.h>
+#include <OMX_IndexExt.h>
 
 #include <inttypes.h>
 #include "FrameDropper.h"
 
 namespace android {
 
-GraphicBufferSource::PersistentProxyListener::PersistentProxyListener(
-        const wp<IGraphicBufferConsumer> &consumer,
-        const wp<ConsumerListener>& consumerListener) :
-    mConsumerListener(consumerListener),
-    mConsumer(consumer) {}
+static const OMX_U32 kPortIndexInput = 0;
 
-GraphicBufferSource::PersistentProxyListener::~PersistentProxyListener() {}
-
-void GraphicBufferSource::PersistentProxyListener::onFrameAvailable(
-        const BufferItem& item) {
-    sp<ConsumerListener> listener(mConsumerListener.promote());
-    if (listener != NULL) {
-        listener->onFrameAvailable(item);
-    } else {
-        sp<IGraphicBufferConsumer> consumer(mConsumer.promote());
-        if (consumer == NULL) {
-            return;
-        }
-        BufferItem bi;
-        status_t err = consumer->acquireBuffer(&bi, 0);
-        if (err != OK) {
-            ALOGE("PersistentProxyListener: acquireBuffer failed (%d)", err);
-            return;
-        }
-
-        err = consumer->detachBuffer(bi.mSlot);
-        if (err != OK) {
-            ALOGE("PersistentProxyListener: detachBuffer failed (%d)", err);
-            return;
-        }
-
-        err = consumer->attachBuffer(&bi.mSlot, bi.mGraphicBuffer);
-        if (err != OK) {
-            ALOGE("PersistentProxyListener: attachBuffer failed (%d)", err);
-            return;
-        }
-
-        err = consumer->releaseBuffer(bi.mSlot, 0,
-                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, bi.mFence);
-        if (err != OK) {
-            ALOGE("PersistentProxyListener: releaseBuffer failed (%d)", err);
-        }
-    }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onFrameReplaced(
-        const BufferItem& item) {
-    sp<ConsumerListener> listener(mConsumerListener.promote());
-    if (listener != NULL) {
-        listener->onFrameReplaced(item);
-    }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onBuffersReleased() {
-    sp<ConsumerListener> listener(mConsumerListener.promote());
-    if (listener != NULL) {
-        listener->onBuffersReleased();
-    }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onSidebandStreamChanged() {
-    sp<ConsumerListener> listener(mConsumerListener.promote());
-    if (listener != NULL) {
-        listener->onSidebandStreamChanged();
-    }
-}
-
-GraphicBufferSource::GraphicBufferSource(
-        const sp<IOMXNode> &omxNode,
-        uint32_t bufferWidth,
-        uint32_t bufferHeight,
-        uint32_t bufferCount,
-        uint32_t consumerUsage,
-        const sp<IGraphicBufferConsumer> &consumer) :
+GraphicBufferSource::GraphicBufferSource() :
     mInitCheck(UNKNOWN_ERROR),
-    mOMXNode(omxNode),
     mExecuting(false),
     mSuspended(false),
     mLastDataSpace(HAL_DATASPACE_UNKNOWN),
-    mIsPersistent(false),
-    mConsumer(consumer),
     mNumFramesAvailable(0),
     mNumBufferAcquired(0),
     mEndOfStream(false),
@@ -129,6 +58,7 @@
     mRepeatAfterUs(-1ll),
     mRepeatLastFrameGeneration(0),
     mRepeatLastFrameTimestamp(-1ll),
+    mRepeatLastFrameCount(0),
     mLatestBufferId(-1),
     mLatestBufferFrameNum(0),
     mLatestBufferFence(Fence::NO_FENCE),
@@ -138,48 +68,21 @@
     mPrevCaptureUs(-1ll),
     mPrevFrameUs(-1ll),
     mInputBufferTimeOffsetUs(0ll) {
+    ALOGV("GraphicBufferSource");
 
-    ALOGV("GraphicBufferSource w=%u h=%u c=%u",
-            bufferWidth, bufferHeight, bufferCount);
+    String8 name("GraphicBufferSource");
 
-    if (bufferWidth == 0 || bufferHeight == 0) {
-        ALOGE("Invalid dimensions %ux%u", bufferWidth, bufferHeight);
-        mInitCheck = BAD_VALUE;
-        return;
-    }
+    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+    mConsumer->setConsumerName(name);
 
-    if (mConsumer == NULL) {
-        String8 name("GraphicBufferSource");
-
-        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
-        mConsumer->setConsumerName(name);
-
-        // use consumer usage bits queried from encoder, but always add HW_VIDEO_ENCODER
-        // for backward compatibility.
-        consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
-        mConsumer->setConsumerUsageBits(consumerUsage);
-
-        mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount);
-        if (mInitCheck != NO_ERROR) {
-            ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
-                    bufferCount, mInitCheck);
-            return;
-        }
-    } else {
-        mIsPersistent = true;
-    }
-    mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
     // Note that we can't create an sp<...>(this) in a ctor that will not keep a
     // reference once the ctor ends, as that would cause the refcount of 'this'
     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
     // that's what we create.
-    wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
-    sp<IConsumerListener> proxy;
-    if (!mIsPersistent) {
-        proxy = new BufferQueue::ProxyConsumerListener(listener);
-    } else {
-        proxy = new PersistentProxyListener(mConsumer, listener);
-    }
+    wp<BufferQueue::ConsumerListener> listener =
+            static_cast<BufferQueue::ConsumerListener*>(this);
+    sp<IConsumerListener> proxy =
+            new BufferQueue::ProxyConsumerListener(listener);
 
     mInitCheck = mConsumer->consumerConnect(proxy, false);
     if (mInitCheck != NO_ERROR) {
@@ -194,15 +97,14 @@
 }
 
 GraphicBufferSource::~GraphicBufferSource() {
+    ALOGV("~GraphicBufferSource");
     if (mLatestBufferId >= 0) {
-        releaseBuffer(
-                mLatestBufferId, mLatestBufferFrameNum,
-                mBufferSlot[mLatestBufferId], mLatestBufferFence);
+        releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
     }
     if (mNumBufferAcquired != 0) {
         ALOGW("potential buffer leak (acquired %d)", mNumBufferAcquired);
     }
-    if (mConsumer != NULL && !mIsPersistent) {
+    if (mConsumer != NULL) {
         status_t err = mConsumer->consumerDisconnect();
         if (err != NO_ERROR) {
             ALOGW("consumerDisconnect failed: %d", err);
@@ -291,15 +193,33 @@
         mLooper.clear();
     }
 
-    ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d",
-            mNumFramesAvailable, mEndOfStream, mEndOfStreamSent);
+    ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d acquired=%d",
+            mNumFramesAvailable, mEndOfStream, mEndOfStreamSent, mNumBufferAcquired);
 
-    // Codec is no longer executing.  Discard all codec-related state.
+    // Codec is no longer executing.  Releasing all buffers to bq.
+    for (int i = (int)mCodecBuffers.size() - 1; i >= 0; --i) {
+        if (mCodecBuffers[i].mGraphicBuffer != NULL) {
+            int id = mCodecBuffers[i].mSlot;
+            if (id != mLatestBufferId) {
+                ALOGV("releasing buffer for codec: slot=%d, useCount=%d, latest=%d",
+                        id, mBufferUseCount[id], mLatestBufferId);
+                sp<Fence> fence = new Fence(-1);
+                releaseBuffer(id, mCodecBuffers[i].mFrameNumber, fence);
+                mBufferUseCount[id] = 0;
+            }
+        }
+    }
+    // Also release the latest buffer
+    if (mLatestBufferId >= 0) {
+        releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
+        mBufferUseCount[mLatestBufferId] = 0;
+        mLatestBufferId = -1;
+    }
+
     mCodecBuffers.clear();
-    // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries
-    //       are null; complain if not
-
+    mOMXNode.clear();
     mExecuting = false;
+
     return Status::ok();
 }
 
@@ -313,7 +233,7 @@
         return Status::fromServiceSpecificError(INVALID_OPERATION);
     }
 
-    ALOGV("addCodecBuffer id=%u", bufferID);
+    ALOGV("addCodecBuffer: bufferID=%u", bufferID);
 
     CodecBuffer codecBuffer;
     codecBuffer.mBufferID = bufferID;
@@ -336,14 +256,14 @@
     int cbi = findMatchingCodecBuffer_l(bufferID);
     if (cbi < 0) {
         // This should never happen.
-        ALOGE("codecBufferEmptied: buffer not recognized (id=%u)", bufferID);
+        ALOGE("codecBufferEmptied: buffer not recognized (bufferID=%u)", bufferID);
         if (fenceFd >= 0) {
             ::close(fenceFd);
         }
         return Status::fromServiceSpecificError(BAD_VALUE);
     }
 
-    ALOGV("codecBufferEmptied id=%u", bufferID);
+    ALOGV("codecBufferEmptied: bufferID=%u, cbi=%d", bufferID, cbi);
     CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
 
     // header->nFilledLen may not be the original value, so we can't compare
@@ -374,19 +294,19 @@
         mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
         mBufferUseCount[id]--;
 
-        ALOGV("codecBufferEmptied: slot=%d, cbi=%d, useCount=%d, handle=%p",
-                id, cbi, mBufferUseCount[id], mBufferSlot[id]->handle);
-
         if (mBufferUseCount[id] < 0) {
             ALOGW("mBufferUseCount for bq slot %d < 0 (=%d)", id, mBufferUseCount[id]);
             mBufferUseCount[id] = 0;
         }
         if (id != mLatestBufferId && mBufferUseCount[id] == 0) {
-            releaseBuffer(id, codecBuffer.mFrameNumber, mBufferSlot[id], fence);
+            releaseBuffer(id, codecBuffer.mFrameNumber, fence);
         }
+        ALOGV("codecBufferEmptied: slot=%d, cbi=%d, useCount=%d, acquired=%d, handle=%p",
+                id, cbi, mBufferUseCount[id], mNumBufferAcquired, mBufferSlot[id]->handle);
     } else {
-        ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
-                cbi);
+        ALOGV("codecBufferEmptied: no match for emptied buffer, "
+                "slot=%d, cbi=%d, useCount=%d, acquired=%d",
+                id, cbi, mBufferUseCount[id], mNumBufferAcquired);
         // we will not reuse codec buffer, so there is no need to wait for fence
     }
 
@@ -453,34 +373,19 @@
     ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu",
             mNumFramesAvailable);
     BufferItem item;
-    status_t err = mConsumer->acquireBuffer(&item, 0);
-    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
-        // shouldn't happen
-        ALOGW("fillCodecBuffer_l: frame was not available");
-        return false;
-    } else if (err != OK) {
-        // now what? fake end-of-stream?
-        ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
+    status_t err = acquireBuffer(&item);
+    if (err != OK) {
+        ALOGE("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
         return false;
     }
 
-    mNumBufferAcquired++;
     mNumFramesAvailable--;
 
-    // If this is the first time we're seeing this buffer, add it to our
-    // slot table.
-    if (item.mGraphicBuffer != NULL) {
-        ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mSlot);
-        mBufferSlot[item.mSlot] = item.mGraphicBuffer;
-        mBufferUseCount[item.mSlot] = 0;
-    }
-
     if (item.mDataSpace != mLastDataSpace) {
         onDataSpaceChanged_l(
                 item.mDataSpace, (android_pixel_format)mBufferSlot[item.mSlot]->getPixelFormat());
     }
 
-
     err = UNKNOWN_ERROR;
 
     // only submit sample if start time is unspecified, or sample
@@ -505,10 +410,18 @@
 
     if (err != OK) {
         ALOGV("submitBuffer_l failed, releasing bq slot %d", item.mSlot);
-        releaseBuffer(item.mSlot, item.mFrameNumber, item.mGraphicBuffer, item.mFence);
+        releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
     } else {
-        ALOGV("buffer submitted (bq %d, cbi %d)", item.mSlot, cbi);
-        setLatestBuffer_l(item, dropped);
+        // Don't set the last buffer id if we're not repeating,
+        // we'll be holding on to the last buffer for nothing.
+        if (mRepeatAfterUs > 0ll) {
+            setLatestBuffer_l(item);
+        }
+        if (!dropped) {
+            ++mBufferUseCount[item.mSlot];
+        }
+        ALOGV("buffer submitted: slot=%d, cbi=%d, useCount=%d, acquired=%d",
+                item.mSlot, cbi, mBufferUseCount[item.mSlot], mNumBufferAcquired);
     }
 
     return true;
@@ -577,24 +490,16 @@
     return true;
 }
 
-void GraphicBufferSource::setLatestBuffer_l(
-        const BufferItem &item, bool dropped) {
-    if (mLatestBufferId >= 0) {
-        if (mBufferUseCount[mLatestBufferId] == 0) {
-            releaseBuffer(mLatestBufferId, mLatestBufferFrameNum,
-                    mBufferSlot[mLatestBufferId], mLatestBufferFence);
-            // mLatestBufferFence will be set to new fence just below
-        }
+void GraphicBufferSource::setLatestBuffer_l(const BufferItem &item) {
+    if (mLatestBufferId >= 0 && mBufferUseCount[mLatestBufferId] == 0) {
+        releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
+        // mLatestBufferFence will be set to new fence just below
     }
 
     mLatestBufferId = item.mSlot;
     mLatestBufferFrameNum = item.mFrameNumber;
     mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
 
-    if (!dropped) {
-        ++mBufferUseCount[item.mSlot];
-    }
-
     ALOGV("setLatestBuffer_l: slot=%d, useCount=%d",
             item.mSlot, mBufferUseCount[item.mSlot]);
 
@@ -709,7 +614,7 @@
         return err;
     }
 
-    ALOGV("emptyGraphicBuffer succeeded, id=%u buf=%p bufhandle=%p",
+    ALOGV("emptyGraphicBuffer succeeded, bufferID=%u buf=%p bufhandle=%p",
             bufferID, buffer->getNativeBuffer(), buffer->handle);
     return OK;
 }
@@ -740,7 +645,7 @@
     if (err != OK) {
         ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
     } else {
-        ALOGV("submitEndOfInputStream_l: buffer submitted, id=%u cbi=%d",
+        ALOGV("submitEndOfInputStream_l: buffer submitted, bufferID=%u cbi=%d",
                 bufferID, cbi);
         mEndOfStreamSent = true;
     }
@@ -766,34 +671,39 @@
     return -1;
 }
 
+status_t GraphicBufferSource::acquireBuffer(BufferItem *bi) {
+    status_t err = mConsumer->acquireBuffer(bi, 0);
+    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
+        // shouldn't happen
+        ALOGW("acquireBuffer: frame was not available");
+        return err;
+    } else if (err != OK) {
+        ALOGW("acquireBuffer: failed with err=%d", err);
+        return err;
+    }
+    // If this is the first time we're seeing this buffer, add it to our
+    // slot table.
+    if (bi->mGraphicBuffer != NULL) {
+        ALOGV("acquireBuffer: setting mBufferSlot %d", bi->mSlot);
+        mBufferSlot[bi->mSlot] = bi->mGraphicBuffer;
+        mBufferUseCount[bi->mSlot] = 0;
+    }
+    mNumBufferAcquired++;
+    return OK;
+}
+
 /*
- * Releases an acquired buffer back to the consumer for either persistent
- * or non-persistent surfaces.
+ * Releases an acquired buffer back to the consumer.
  *
- * id: buffer slot to release (in persistent case the id might be changed)
+ * id: buffer slot to release
  * frameNum: frame number of the frame being released
- * buffer: GraphicBuffer pointer to release (note this must not be & as we
- *         will clear the original mBufferSlot in persistent case)
- *         Use NOLINT to supress warning on the copy of 'buffer'.
  * fence: fence of the frame being released
  */
 void GraphicBufferSource::releaseBuffer(
-        int &id, uint64_t frameNum,
-        const sp<GraphicBuffer> buffer, const sp<Fence> &fence) {  // NOLINT
+        int id, uint64_t frameNum, const sp<Fence> &fence) {
     ALOGV("releaseBuffer: slot=%d", id);
-    if (mIsPersistent) {
-        mConsumer->detachBuffer(id);
-        mBufferSlot[id] = NULL;
-
-        if (mConsumer->attachBuffer(&id, buffer) == OK) {
-            mConsumer->releaseBuffer(
-                    id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
-        }
-    } else {
-        mConsumer->releaseBuffer(
-                id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
-    }
-    id = -1; // invalidate id
+    mConsumer->releaseBuffer(
+            id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
     mNumBufferAcquired--;
 }
 
@@ -804,7 +714,7 @@
     ALOGV("onFrameAvailable exec=%d avail=%zu",
             mExecuting, mNumFramesAvailable);
 
-    if (mEndOfStream || mSuspended) {
+    if (mOMXNode == NULL || mEndOfStream || mSuspended) {
         if (mEndOfStream) {
             // This should only be possible if a new buffer was queued after
             // EOS was signaled, i.e. the app is misbehaving.
@@ -815,20 +725,11 @@
         }
 
         BufferItem item;
-        status_t err = mConsumer->acquireBuffer(&item, 0);
+        status_t err = acquireBuffer(&item);
         if (err == OK) {
-            mNumBufferAcquired++;
-
-            // If this is the first time we're seeing this buffer, add it to our
-            // slot table.
-            if (item.mGraphicBuffer != NULL) {
-                ALOGV("onFrameAvailable: setting mBufferSlot %d", item.mSlot);
-                mBufferSlot[item.mSlot] = item.mGraphicBuffer;
-                mBufferUseCount[item.mSlot] = 0;
-            }
-
-            releaseBuffer(item.mSlot, item.mFrameNumber,
-                    item.mGraphicBuffer, item.mFence);
+            releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
+        } else {
+            ALOGE("onFrameAvailable: acquireBuffer returned err=%d", err);
         }
         return;
     }
@@ -857,6 +758,18 @@
 
     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
         if ((slotMask & 0x01) != 0) {
+            // Last buffer (if set) is always acquired even if its use count
+            // is 0, because we could have skipped that frame but kept it for
+            // repeating. Otherwise a buffer is only acquired if use count>0.
+            if (mBufferSlot[i] != NULL &&
+                    (mBufferUseCount[i] > 0 || mLatestBufferId == i)) {
+                ALOGV("releasing acquired buffer: slot=%d, useCount=%d, latest=%d",
+                        i, mBufferUseCount[i], mLatestBufferId);
+                mNumBufferAcquired--;
+            }
+            if (mLatestBufferId == i) {
+                mLatestBufferId = -1;
+            }
             mBufferSlot[i] = NULL;
             mBufferUseCount[i] = 0;
         }
@@ -869,11 +782,99 @@
     ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
 }
 
-void GraphicBufferSource::setDefaultDataSpace(android_dataspace dataSpace) {
-    // no need for mutex as we are not yet running
-    ALOGD("setting dataspace: %#x", dataSpace);
-    mConsumer->setDefaultBufferDataSpace(dataSpace);
-    mLastDataSpace = dataSpace;
+Status GraphicBufferSource::configure(
+        const sp<IOMXNode>& omxNode, int32_t dataSpace) {
+    if (omxNode == NULL) {
+        return Status::fromServiceSpecificError(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(this);
+    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);
+    if (err != NO_ERROR) {
+        ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
+                def.nBufferCountActual, err);
+        return Status::fromServiceSpecificError(err);
+    }
+
+    {
+        Mutex::Autolock autoLock(mMutex);
+        mOMXNode = omxNode;
+
+        err = mConsumer->setDefaultBufferSize(
+                def.format.video.nFrameWidth,
+                def.format.video.nFrameHeight);
+        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);
+        }
+
+        consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
+        mConsumer->setConsumerUsageBits(consumerUsage);
+
+        // Sets the default buffer data space
+        ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumBufferAcquired);
+        mConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace);
+        mLastDataSpace = (android_dataspace)dataSpace;
+
+        mExecuting = false;
+        mSuspended = false;
+        mEndOfStream = false;
+        mEndOfStreamSent = false;
+        mMaxTimestampGapUs = -1ll;
+        mPrevOriginalTimeUs = -1ll;
+        mPrevModifiedTimeUs = -1ll;
+        mSkipFramesBeforeNs = -1ll;
+        mRepeatAfterUs = -1ll;
+        mRepeatLastFrameGeneration = 0;
+        mRepeatLastFrameTimestamp = -1ll;
+        mRepeatLastFrameCount = 0;
+        mLatestBufferId = -1;
+        mLatestBufferFrameNum = 0;
+        mLatestBufferFence = Fence::NO_FENCE;
+        mRepeatBufferDeferred = false;
+        mTimePerCaptureUs = -1ll;
+        mTimePerFrameUs = -1ll;
+        mPrevCaptureUs = -1ll;
+        mPrevFrameUs = -1ll;
+        mInputBufferTimeOffsetUs = 0;
+    }
+
+    return Status::ok();
 }
 
 Status GraphicBufferSource::setSuspend(bool suspend) {
@@ -886,22 +887,16 @@
 
         while (mNumFramesAvailable > 0) {
             BufferItem item;
-            status_t err = mConsumer->acquireBuffer(&item, 0);
+            status_t err = acquireBuffer(&item);
 
-            if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
-                // shouldn't happen.
-                ALOGW("suspend: frame was not available");
-                break;
-            } else if (err != OK) {
-                ALOGW("suspend: acquireBuffer returned err=%d", err);
+            if (err != OK) {
+                ALOGE("setSuspend: acquireBuffer returned err=%d", err);
                 break;
             }
 
-            ++mNumBufferAcquired;
             --mNumFramesAvailable;
 
-            releaseBuffer(item.mSlot, item.mFrameNumber,
-                    item.mGraphicBuffer, item.mFence);
+            releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
         }
         return Status::ok();
     }
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 88fab02..045a86a 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -58,14 +58,7 @@
                             public BnOMXBufferSource,
                             public BufferQueue::ConsumerListener {
 public:
-    GraphicBufferSource(
-            const sp<IOMXNode> &omxNode,
-            uint32_t bufferWidth,
-            uint32_t bufferHeight,
-            uint32_t bufferCount,
-            uint32_t consumerUsage,
-            const sp<IGraphicBufferConsumer> &consumer = NULL
-    );
+    GraphicBufferSource();
 
     virtual ~GraphicBufferSource();
 
@@ -81,9 +74,6 @@
         return mProducer;
     }
 
-    // Sets the default buffer data space
-    void setDefaultDataSpace(android_dataspace dataSpace);
-
     // This is called when OMX transitions to OMX_StateExecuting, which means
     // we can start handing it buffers.  If we already have buffers of data
     // sitting in the BufferQueue, this will send them to the codec.
@@ -108,6 +98,10 @@
     Status onInputBufferEmptied(
             int32_t bufferID, const OMXFenceParcelable& fenceParcel) override;
 
+    // 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;
+
     // This is called after the last input frame has been submitted.  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.
@@ -174,30 +168,6 @@
     void onSidebandStreamChanged() override;
 
 private:
-    // PersistentProxyListener is similar to BufferQueue::ProxyConsumerListener
-    // except that it returns (acquire/detach/re-attache/release) buffers
-    // in onFrameAvailable() if the actual consumer object is no longer valid.
-    //
-    // This class is used in persistent input surface case to prevent buffer
-    // loss when onFrameAvailable() is received while we don't have a valid
-    // consumer around.
-    class PersistentProxyListener : public BnConsumerListener {
-        public:
-            PersistentProxyListener(
-                    const wp<IGraphicBufferConsumer> &consumer,
-                    const wp<ConsumerListener>& consumerListener);
-            virtual ~PersistentProxyListener();
-            virtual void onFrameAvailable(const BufferItem& item) override;
-            virtual void onFrameReplaced(const BufferItem& item) override;
-            virtual void onBuffersReleased() override;
-            virtual void onSidebandStreamChanged() override;
-         private:
-            // mConsumerListener is a weak reference to the IConsumerListener.
-            wp<ConsumerListener> mConsumerListener;
-            // mConsumer is a weak reference to the IGraphicBufferConsumer, use
-            // a weak ref to avoid circular ref between mConsumer and this class
-            wp<IGraphicBufferConsumer> mConsumer;
-    };
 
     // Keep track of codec input buffers.  They may either be available
     // (mGraphicBuffer == NULL) or in use by the codec.
@@ -242,12 +212,13 @@
     // doing anything if we don't have a codec buffer available.
     void submitEndOfInputStream_l();
 
-    // Release buffer to the consumer
-    void releaseBuffer(
-            int &id, uint64_t frameNum,
-            const sp<GraphicBuffer> buffer, const sp<Fence> &fence);
+    // Acquire buffer from the consumer
+    status_t acquireBuffer(BufferItem *bi);
 
-    void setLatestBuffer_l(const BufferItem &item, bool dropped);
+    // Release buffer to the consumer
+    void releaseBuffer(int id, uint64_t frameNum, const sp<Fence> &fence);
+
+    void setLatestBuffer_l(const BufferItem &item);
     bool repeatLatestBuffer_l();
     bool getTimestamp(const BufferItem &item, int64_t *timeUs, int64_t *codecTimeUs);
 
@@ -274,7 +245,6 @@
     // Our BufferQueue interfaces. mProducer is passed to the producer through
     // getIGraphicBufferProducer, and mConsumer is used internally to retrieve
     // the buffers queued by the producer.
-    bool mIsPersistent;
     sp<IGraphicBufferProducer> mProducer;
     sp<IGraphicBufferConsumer> mConsumer;
 
@@ -340,7 +310,6 @@
 
     int64_t mInputBufferTimeOffsetUs;
 
-    MetadataBufferType mMetadataBufferType;
     ColorAspects mColorAspects;
 
     void onMessageReceived(const sp<AMessage> &msg);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 70b9c17..7907c62 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -27,6 +27,7 @@
 #include "../include/OMXNodeInstance.h"
 
 #include <media/stagefright/foundation/ADebug.h>
+#include "GraphicBufferSource.h"
 
 #include "OMXMaster.h"
 #include "OMXUtils.h"
@@ -154,11 +155,26 @@
     return StatusFromOMXError(err);
 }
 
-status_t OMX::createPersistentInputSurface(
+status_t OMX::createInputSurface(
         sp<IGraphicBufferProducer> *bufferProducer,
-        sp<IGraphicBufferConsumer> *bufferConsumer) {
-    return OMXNodeInstance::createPersistentInputSurface(
-            bufferProducer, bufferConsumer);
+        sp<IGraphicBufferSource> *bufferSource) {
+    if (bufferProducer == NULL || bufferSource == NULL) {
+        ALOGE("b/25884056");
+        return BAD_VALUE;
+    }
+
+    sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
+    status_t err = graphicBufferSource->initCheck();
+    if (err != OK) {
+        ALOGE("Failed to create persistent input surface: %s (%d)",
+                strerror(-err), err);
+        return err;
+    }
+
+    *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
+    *bufferSource = graphicBufferSource;
+
+    return OK;
 }
 
 }  // namespace android
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index b747895..ef18958 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -23,8 +23,6 @@
 #include "../include/OMXNodeInstance.h"
 #include "OMXMaster.h"
 #include "OMXUtils.h"
-#include "GraphicBufferSource.h"
-#include <android/IGraphicBufferSource.h>
 #include <android/IOMXBufferSource.h>
 
 #include <OMX_Component.h>
@@ -46,6 +44,15 @@
 static const OMX_U32 kPortIndexInput = 0;
 static const OMX_U32 kPortIndexOutput = 1;
 
+// Quirk still supported, even though deprecated
+enum Quirks {
+    kRequiresAllocateBufferOnInputPorts   = 1,
+    kRequiresAllocateBufferOnOutputPorts  = 2,
+
+    kQuirksMask = kRequiresAllocateBufferOnInputPorts
+                | kRequiresAllocateBufferOnOutputPorts,
+};
+
 #define CLOGW(fmt, ...) ALOGW("[%p:%s] " fmt, mHandle, mName, ##__VA_ARGS__)
 
 #define CLOG_ERROR_IF(cond, fn, err, fmt, ...) \
@@ -98,18 +105,16 @@
 
 struct BufferMeta {
     explicit BufferMeta(
-            const sp<IMemory> &mem, OMX_U32 portIndex, bool copyToOmx,
-            bool copyFromOmx, OMX_U8 *backup)
+            const sp<IMemory> &mem, OMX_U32 portIndex, bool copy, OMX_U8 *backup)
         : mMem(mem),
-          mCopyFromOmx(copyFromOmx),
-          mCopyToOmx(copyToOmx),
+          mCopyFromOmx(portIndex == kPortIndexOutput && copy),
+          mCopyToOmx(portIndex == kPortIndexInput && copy),
           mPortIndex(portIndex),
           mBackup(backup) {
     }
 
-    explicit BufferMeta(size_t size, OMX_U32 portIndex)
-        : mSize(size),
-          mCopyFromOmx(false),
+    explicit BufferMeta(OMX_U32 portIndex)
+        : mCopyFromOmx(false),
           mCopyToOmx(false),
           mPortIndex(portIndex),
           mBackup(NULL) {
@@ -129,7 +134,7 @@
         }
 
         // check component returns proper range
-        sp<ABuffer> codec = getBuffer(header, false /* backup */, true /* limit */);
+        sp<ABuffer> codec = getBuffer(header, true /* limit */);
 
         memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, codec->data(), codec->size());
     }
@@ -144,14 +149,9 @@
                 header->nFilledLen);
     }
 
-    // return either the codec or the backup buffer
-    sp<ABuffer> getBuffer(const OMX_BUFFERHEADERTYPE *header, bool backup, bool limit) {
-        sp<ABuffer> buf;
-        if (backup && mMem != NULL) {
-            buf = new ABuffer(mMem->pointer(), mMem->size());
-        } else {
-            buf = new ABuffer(header->pBuffer, header->nAllocLen);
-        }
+    // return the codec buffer
+    sp<ABuffer> getBuffer(const OMX_BUFFERHEADERTYPE *header, bool limit) {
+        sp<ABuffer> buf = new ABuffer(header->pBuffer, header->nAllocLen);
         if (limit) {
             if (header->nOffset + header->nFilledLen > header->nOffset
                     && header->nOffset + header->nFilledLen <= header->nAllocLen) {
@@ -183,7 +183,6 @@
     sp<GraphicBuffer> mGraphicBuffer;
     sp<NativeHandle> mNativeHandle;
     sp<IMemory> mMem;
-    size_t mSize;
     bool mCopyFromOmx;
     bool mCopyToOmx;
     OMX_U32 mPortIndex;
@@ -339,6 +338,7 @@
       mDying(false),
       mSailed(false),
       mQueriedProhibitedExtensions(false),
+      mQuirks(0),
       mBufferIDCount(0),
       mShouldRestorePts(false),
       mRestorePtsFailed(false)
@@ -480,6 +480,7 @@
     status_t err = mOwner->freeNode(this);
 
     mDispatcher.clear();
+    mOMXBufferSource.clear();
 
     mHandle = NULL;
     CLOG_IF_ERROR(freeNode, err, "");
@@ -907,43 +908,64 @@
         return BAD_VALUE;
     }
 
-    // metadata buffers are not connected cross process
-    // use a backup buffer instead of the actual buffer
     BufferMeta *buffer_meta;
-    bool useBackup = mMetadataType[portIndex] != kMetadataBufferTypeInvalid;
-    OMX_U8 *data = static_cast<OMX_U8 *>(params->pointer());
-    // allocate backup buffer
-    if (useBackup) {
-        data = new (std::nothrow) OMX_U8[allottedSize];
-        if (data == NULL) {
-            return NO_MEMORY;
-        }
-        memset(data, 0, allottedSize);
+    OMX_BUFFERHEADERTYPE *header;
+    OMX_ERRORTYPE err = OMX_ErrorNone;
+    bool isMetadata = mMetadataType[portIndex] != kMetadataBufferTypeInvalid;
 
-        // if we are not connecting the buffers, the sizes must match
-        if (allottedSize != params->size()) {
-            CLOG_ERROR(useBuffer, BAD_VALUE, SIMPLE_BUFFER(portIndex, (size_t)allottedSize, data));
-            delete[] data;
-            return BAD_VALUE;
-        }
+    uint32_t requiresAllocateBufferBit =
+        (portIndex == kPortIndexInput)
+            ? kRequiresAllocateBufferOnInputPorts
+            : kRequiresAllocateBufferOnOutputPorts;
 
+    if (mQuirks & requiresAllocateBufferBit) {
+        // metadata buffers are not connected cross process; only copy if not meta.
         buffer_meta = new BufferMeta(
-                params, portIndex, false /* copyToOmx */, false /* copyFromOmx */, data);
+                    params, portIndex, !isMetadata /* copy */, NULL /* data */);
+
+        err = OMX_AllocateBuffer(
+                mHandle, &header, portIndex, buffer_meta, allottedSize);
+
+        if (err != OMX_ErrorNone) {
+            CLOG_ERROR(allocateBuffer, err,
+                    SIMPLE_BUFFER(portIndex, (size_t)allottedSize, params->pointer()));
+        }
     } else {
-        buffer_meta = new BufferMeta(
-                params, portIndex, false /* copyToOmx */, false /* copyFromOmx */, NULL);
+        OMX_U8 *data = static_cast<OMX_U8 *>(params->pointer());
+
+        // metadata buffers are not connected cross process
+        // use a backup buffer instead of the actual buffer
+        if (isMetadata) {
+            // if we are not connecting the buffers, the sizes must match
+            if (allottedSize != params->size()) {
+                CLOG_ERROR(useBuffer, BAD_VALUE, SIMPLE_BUFFER(portIndex, (size_t)allottedSize, data));
+                return BAD_VALUE;
+            }
+
+            data = new (std::nothrow) OMX_U8[allottedSize];
+            if (data == NULL) {
+                return NO_MEMORY;
+            }
+            memset(data, 0, allottedSize);
+
+            buffer_meta = new BufferMeta(
+                    params, portIndex, false /* copy */, data);
+        } else {
+            buffer_meta = new BufferMeta(
+                    params, portIndex, false /* copy */, NULL);
+        }
+
+        err = OMX_UseBuffer(
+                mHandle, &header, portIndex, buffer_meta,
+                allottedSize, data);
+
+        if (err != OMX_ErrorNone) {
+            CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(
+                    portIndex, (size_t)allottedSize, data));
+        }
     }
 
-    OMX_BUFFERHEADERTYPE *header;
-
-    OMX_ERRORTYPE err = OMX_UseBuffer(
-            mHandle, &header, portIndex, buffer_meta,
-            allottedSize, data);
-
     if (err != OMX_ErrorNone) {
-        CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(
-                portIndex, (size_t)allottedSize, data));
-
         delete buffer_meta;
         buffer_meta = NULL;
 
@@ -1090,7 +1112,7 @@
 
 status_t OMXNodeInstance::updateGraphicBufferInMeta_l(
         OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
-        OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header, bool updateCodecBuffer) {
+        OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) {
     // No need to check |graphicBuffer| since NULL is valid for it as below.
     if (header == NULL) {
         ALOGE("b/25884056");
@@ -1102,14 +1124,9 @@
     }
 
     BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
-    sp<ABuffer> data = bufferMeta->getBuffer(
-            header, !updateCodecBuffer /* backup */, false /* limit */);
+    sp<ABuffer> data = bufferMeta->getBuffer(header, false /* limit */);
     bufferMeta->setGraphicBuffer(graphicBuffer);
     MetadataBufferType metaType = mMetadataType[portIndex];
-    // we use gralloc source only in the codec buffers
-    if (metaType == kMetadataBufferTypeGrallocSource && !updateCodecBuffer) {
-        metaType = kMetadataBufferTypeANWBuffer;
-    }
     if (metaType == kMetadataBufferTypeGrallocSource
             && data->capacity() >= sizeof(VideoGrallocMetadata)) {
         VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(data->data());
@@ -1138,10 +1155,9 @@
         OMX::buffer_id buffer) {
     Mutex::Autolock autoLock(mLock);
     OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
-    // update backup buffer for input, codec buffer for output
+
     return updateGraphicBufferInMeta_l(
-            portIndex, graphicBuffer, buffer, header,
-            true /* updateCodecBuffer */);
+            portIndex, graphicBuffer, buffer, header);
 }
 
 status_t OMXNodeInstance::updateNativeHandleInMeta(
@@ -1159,9 +1175,7 @@
     }
 
     BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
-    // update backup buffer
-    sp<ABuffer> data = bufferMeta->getBuffer(
-            header, false /* backup */, false /* limit */);
+    sp<ABuffer> data = bufferMeta->getBuffer(header, false /* limit */);
     bufferMeta->setNativeHandle(nativeHandle);
     if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource
             && data->capacity() >= sizeof(VideoNativeHandleMetadata)) {
@@ -1181,35 +1195,23 @@
     return OK;
 }
 
-status_t OMXNodeInstance::createGraphicBufferSource(
-        OMX_U32 portIndex, android_dataspace dataSpace,
-        const sp<IGraphicBufferConsumer> &bufferConsumer,
-        sp<IGraphicBufferProducer> *bufferProducer,
-        sp<IGraphicBufferSource> *bufferSource,
-        MetadataBufferType *type) {
+status_t OMXNodeInstance::setInputSurface(
+        const sp<IOMXBufferSource> &bufferSource) {
+    Mutex::Autolock autolock(mLock);
+
     status_t err;
 
     // only allow graphic source on input port, when there are no allocated buffers yet
-    if (portIndex != kPortIndexInput) {
-        android_errorWriteLog(0x534e4554, "29422020");
-        return BAD_VALUE;
-    } else if (mNumPortBuffers[portIndex] > 0) {
+    if (mNumPortBuffers[kPortIndexInput] > 0) {
         android_errorWriteLog(0x534e4554, "29422020");
         return INVALID_OPERATION;
     }
 
     if (getBufferSource() != NULL) {
-        if (portIndex < NELEM(mMetadataType) && type != NULL) {
-            *type = mMetadataType[portIndex];
-        }
         return ALREADY_EXISTS;
     }
 
-    // Input buffers will hold meta-data (ANativeWindowBuffer references).
-    if (type != NULL) {
-        *type = kMetadataBufferTypeANWBuffer;
-    }
-    err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, type);
+    err = storeMetaDataInBuffers_l(kPortIndexInput, OMX_TRUE, NULL);
     if (err != OK) {
         return err;
     }
@@ -1218,13 +1220,13 @@
     // codec was configured.
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
-    def.nPortIndex = portIndex;
+    def.nPortIndex = kPortIndexInput;
     OMX_ERRORTYPE oerr = OMX_GetParameter(
             mHandle, OMX_IndexParamPortDefinition, &def);
     if (oerr != OMX_ErrorNone) {
         OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
-        CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u",
-                asString(index), index, portString(portIndex), portIndex);
+        CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u", asString(index),
+                index, portString(kPortIndexInput), kPortIndexInput);
         return UNKNOWN_ERROR;
     }
 
@@ -1235,97 +1237,18 @@
         return INVALID_OPERATION;
     }
 
-    uint32_t usageBits;
-    oerr = OMX_GetParameter(
-            mHandle, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits);
-    if (oerr != OMX_ErrorNone) {
-        usageBits = 0;
-    }
-
-    sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource(
-            this,
-            def.format.video.nFrameWidth,
-            def.format.video.nFrameHeight,
-            def.nBufferCountActual,
-            usageBits,
-            bufferConsumer);
-
-    if ((err = graphicBufferSource->initCheck()) != OK) {
-        return err;
-    }
-    setBufferSource(graphicBufferSource);
-
-    if (bufferConsumer == NULL) {
-        graphicBufferSource->setDefaultDataSpace(dataSpace);
-    }
-
-    if (bufferProducer != NULL) {
-        *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
-    }
-
-    *bufferSource = graphicBufferSource;
-
-    return OK;
-}
-
-status_t OMXNodeInstance::createInputSurface(
-        OMX_U32 portIndex, android_dataspace dataSpace,
-        sp<IGraphicBufferProducer> *bufferProducer,
-        sp<IGraphicBufferSource> *bufferSource,
-        MetadataBufferType *type) {
-    if (bufferProducer == NULL) {
-        ALOGE("b/25884056");
+    if (def.format.video.nFrameWidth == 0
+            || def.format.video.nFrameHeight == 0) {
+        ALOGE("Invalid video dimension %ux%u",
+                def.format.video.nFrameWidth,
+                def.format.video.nFrameHeight);
         return BAD_VALUE;
     }
 
-    Mutex::Autolock autolock(mLock);
-    return createGraphicBufferSource(
-            portIndex, dataSpace, NULL /* bufferConsumer */,
-            bufferProducer, bufferSource, type);
-}
-
-//static
-status_t OMXNodeInstance::createPersistentInputSurface(
-        sp<IGraphicBufferProducer> *bufferProducer,
-        sp<IGraphicBufferConsumer> *bufferConsumer) {
-    if (bufferProducer == NULL || bufferConsumer == NULL) {
-        ALOGE("b/25884056");
-        return BAD_VALUE;
-    }
-    String8 name("GraphicBufferSource");
-
-    sp<IGraphicBufferProducer> producer;
-    sp<IGraphicBufferConsumer> consumer;
-    BufferQueue::createBufferQueue(&producer, &consumer);
-    consumer->setConsumerName(name);
-    consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
-
-    sp<BufferQueue::ProxyConsumerListener> proxy =
-        new BufferQueue::ProxyConsumerListener(NULL);
-    status_t err = consumer->consumerConnect(proxy, false);
-    if (err != NO_ERROR) {
-        ALOGE("Error connecting to BufferQueue: %s (%d)",
-                strerror(-err), err);
-        return err;
-    }
-
-    *bufferProducer = producer;
-    *bufferConsumer = consumer;
-
+    setBufferSource(bufferSource);
     return OK;
 }
 
-status_t OMXNodeInstance::setInputSurface(
-        OMX_U32 portIndex,
-        const sp<IGraphicBufferConsumer> &bufferConsumer,
-        sp<IGraphicBufferSource> *bufferSource,
-        MetadataBufferType *type) {
-    Mutex::Autolock autolock(mLock);
-    return createGraphicBufferSource(
-            portIndex, android_dataspace::HAL_DATASPACE_UNKNOWN,
-            bufferConsumer, NULL, bufferSource, type);
-}
-
 status_t OMXNodeInstance::allocateSecureBuffer(
         OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
         void **buffer_data, sp<NativeHandle> *native_handle) {
@@ -1342,7 +1265,7 @@
 
     Mutex::Autolock autoLock(mLock);
 
-    BufferMeta *buffer_meta = new BufferMeta(size, portIndex);
+    BufferMeta *buffer_meta = new BufferMeta(portIndex);
 
     OMX_BUFFERHEADERTYPE *header;
 
@@ -1384,60 +1307,6 @@
     return OK;
 }
 
-status_t OMXNodeInstance::allocateBufferWithBackup(
-        OMX_U32 portIndex, const sp<IMemory> &params,
-        OMX::buffer_id *buffer, OMX_U32 allottedSize) {
-    if (params == NULL || buffer == NULL) {
-        ALOGE("b/25884056");
-        return BAD_VALUE;
-    }
-
-    Mutex::Autolock autoLock(mLock);
-    if (allottedSize > params->size() || portIndex >= NELEM(mNumPortBuffers)) {
-        return BAD_VALUE;
-    }
-
-    // metadata buffers are not connected cross process; only copy if not meta
-    bool copy = mMetadataType[portIndex] == kMetadataBufferTypeInvalid;
-
-    BufferMeta *buffer_meta = new BufferMeta(
-            params, portIndex,
-            (portIndex == kPortIndexInput) && copy /* copyToOmx */,
-            (portIndex == kPortIndexOutput) && copy /* copyFromOmx */,
-            NULL /* data */);
-
-    OMX_BUFFERHEADERTYPE *header;
-
-    OMX_ERRORTYPE err = OMX_AllocateBuffer(
-            mHandle, &header, portIndex, buffer_meta, allottedSize);
-    if (err != OMX_ErrorNone) {
-        CLOG_ERROR(allocateBufferWithBackup, err,
-                SIMPLE_BUFFER(portIndex, (size_t)allottedSize, params->pointer()));
-        delete buffer_meta;
-        buffer_meta = NULL;
-
-        *buffer = 0;
-
-        return StatusFromOMXError(err);
-    }
-
-    CHECK_EQ(header->pAppPrivate, buffer_meta);
-
-    *buffer = makeBufferID(header);
-
-    addActiveBuffer(portIndex, *buffer);
-
-    sp<IOMXBufferSource> bufferSource(getBufferSource());
-    if (bufferSource != NULL && portIndex == kPortIndexInput) {
-        bufferSource->onInputBufferAdded(*buffer);
-    }
-
-    CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p :> %u@%p",
-            params->size(), params->pointer(), allottedSize, header->pBuffer));
-
-    return OK;
-}
-
 status_t OMXNodeInstance::freeBuffer(
         OMX_U32 portIndex, OMX::buffer_id buffer) {
     Mutex::Autolock autoLock(mLock);
@@ -1661,8 +1530,7 @@
     }
 
     status_t err = updateGraphicBufferInMeta_l(
-            kPortIndexInput, graphicBuffer, buffer, header,
-            true /* updateCodecBuffer */);
+            kPortIndexInput, graphicBuffer, buffer, header);
     if (err != OK) {
         CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER(
                 (intptr_t)header->pBuffer, header, fenceFd));
@@ -1732,7 +1600,17 @@
 
 status_t OMXNodeInstance::dispatchMessage(const omx_message &msg) {
     mDispatcher->post(msg, true /*realTime*/);
-    return OMX_ErrorNone;
+    return OK;
+}
+
+status_t OMXNodeInstance::setQuirks(OMX_U32 quirks) {
+    if (quirks & ~kQuirksMask) {
+        return BAD_VALUE;
+    }
+
+    mQuirks = quirks;
+
+    return OK;
 }
 
 bool OMXNodeInstance::handleMessage(omx_message &msg) {
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index a940c51..ea99e53 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -210,9 +210,9 @@
         buffer.mFlags = 0;
         CHECK(buffer.mMemory != NULL);
 
-        err = mOMXNode->allocateBufferWithBackup(
+        err = mOMXNode->useBuffer(
                 portIndex, buffer.mMemory, &buffer.mID, buffer.mMemory->size());
-        EXPECT_SUCCESS(err, "allocateBuffer");
+        EXPECT_SUCCESS(err, "useBuffer");
 
         buffers->push(buffer);
     }
diff --git a/radio/IRadioService.cpp b/radio/IRadioService.cpp
index 960aab4..be7d21e 100644
--- a/radio/IRadioService.cpp
+++ b/radio/IRadioService.cpp
@@ -88,7 +88,9 @@
         data.writeInt32(handle);
         data.writeStrongBinder(IInterface::asBinder(client));
         ALOGV("attach() config %p withAudio %d region %d type %d",
-              config == NULL ? 0 : config, withAudio, config->region, config->band.type);
+              config == NULL ? 0 : config, withAudio,
+              config == NULL ? 0 : config->region,
+              config == NULL ? 0 : config->band.type);
         if (config == NULL) {
             data.writeInt32(0);
         } else {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 6dfae52..c85d377 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -43,7 +43,6 @@
 #include <cutils/properties.h>
 
 #include <system/audio.h>
-#include <hardware/audio.h>
 
 #include "AudioMixer.h"
 #include "AudioFlinger.h"
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index d64e8db..890aa89 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -43,7 +43,6 @@
 #include <binder/MemoryDealer.h>
 
 #include <system/audio.h>
-#include <hardware/audio.h>
 #include <hardware/audio_policy.h>
 
 #include <media/audiohal/StreamHalInterface.h>
diff --git a/services/audioflinger/AudioHwDevice.cpp b/services/audioflinger/AudioHwDevice.cpp
index ee10f8d..28110a2 100644
--- a/services/audioflinger/AudioHwDevice.cpp
+++ b/services/audioflinger/AudioHwDevice.cpp
@@ -18,7 +18,7 @@
 #define LOG_TAG "AudioHwDevice"
 //#define LOG_NDEBUG 0
 
-#include <hardware/audio.h>
+#include <system/audio.h>
 #include <utils/Log.h>
 
 #include <audio_utils/spdif/SPDIFEncoder.h>
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/AudioHwDevice.h
index 995ac13..ebb8911 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/AudioHwDevice.h
@@ -22,7 +22,6 @@
 #include <stdlib.h>
 #include <sys/types.h>
 
-#include <hardware/audio.h>
 #include <media/audiohal/DeviceHalInterface.h>
 #include <utils/Errors.h>
 #include <system/audio.h>
diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp
index 3b8bc32..1d4b3fe 100644
--- a/services/audioflinger/AudioStreamOut.cpp
+++ b/services/audioflinger/AudioStreamOut.cpp
@@ -18,9 +18,9 @@
 #define LOG_TAG "AudioFlinger"
 //#define LOG_NDEBUG 0
 
-#include <hardware/audio.h>
 #include <media/audiohal/DeviceHalInterface.h>
 #include <media/audiohal/StreamHalInterface.h>
+#include <system/audio.h>
 #include <utils/Log.h>
 
 #include "AudioHwDevice.h"
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index c523ec5..b8d24a0 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -2028,15 +2028,49 @@
     }
 }
 
-bool AudioFlinger::EffectChain::hasSoftwareEffect() const
+void AudioFlinger::EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
+{
+    if ((*flags & AUDIO_OUTPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
+        *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
+    }
+    if ((*flags & AUDIO_OUTPUT_FLAG_FAST) != 0 && !isFastCompatible()) {
+        *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
+    }
+}
+
+void AudioFlinger::EffectChain::checkInputFlagCompatibility(audio_input_flags_t *flags) const
+{
+    if ((*flags & AUDIO_INPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
+        *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_RAW);
+    }
+    if ((*flags & AUDIO_INPUT_FLAG_FAST) != 0 && !isFastCompatible()) {
+        *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_FAST);
+    }
+}
+
+bool AudioFlinger::EffectChain::isRawCompatible() const
 {
     Mutex::Autolock _l(mLock);
-    for (size_t i = 0; i < mEffects.size(); i++) {
-        if (mEffects[i]->isImplementationSoftware()) {
-            return true;
+    for (const auto &effect : mEffects) {
+        if (effect->isProcessImplemented()) {
+            return false;
         }
     }
-    return false;
+    // Allow effects without processing.
+    return true;
+}
+
+bool AudioFlinger::EffectChain::isFastCompatible() const
+{
+    Mutex::Autolock _l(mLock);
+    for (const auto &effect : mEffects) {
+        if (effect->isProcessImplemented()
+                && effect->isImplementationSoftware()) {
+            return false;
+        }
+    }
+    // Allow effects without processing or hw accelerated effects.
+    return true;
 }
 
 // isCompatibleWithThread_l() must be called with thread->mLock held
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 53dbe4b..a19b7fd 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -328,7 +328,17 @@
 
     void syncHalEffectsState();
 
-    bool hasSoftwareEffect() const;
+    // flags is an ORed set of audio_output_flags_t which is updated on return.
+    void checkOutputFlagCompatibility(audio_output_flags_t *flags) const;
+
+    // flags is an ORed set of audio_input_flags_t which is updated on return.
+    void checkInputFlagCompatibility(audio_input_flags_t *flags) const;
+
+    // Is this EffectChain compatible with the RAW audio flag.
+    bool isRawCompatible() const;
+
+    // Is this EffectChain compatible with the FAST audio flag.
+    bool isFastCompatible() const;
 
     // isCompatibleWithThread_l() must be called with thread->mLock held
     bool isCompatibleWithThread_l(const sp<ThreadBase>& thread) const;
diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp
index b9260f8..a44ab2a 100644
--- a/services/audioflinger/SpdifStreamOut.cpp
+++ b/services/audioflinger/SpdifStreamOut.cpp
@@ -17,7 +17,7 @@
 
 #define LOG_TAG "AudioFlinger"
 //#define LOG_NDEBUG 0
-#include <hardware/audio.h>
+#include <system/audio.h>
 #include <utils/Log.h>
 
 #include <audio_utils/spdif/SPDIFEncoder.h>
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3b05c48..951a280 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -33,13 +33,13 @@
 #include <utils/Trace.h>
 
 #include <private/media/AudioTrackShared.h>
-#include <hardware/audio.h>
 #include <audio_effects/effect_ns.h>
 #include <audio_effects/effect_aec.h>
 #include <audio_utils/conversion.h>
 #include <audio_utils/primitives.h>
 #include <audio_utils/format.h>
 #include <audio_utils/minifloat.h>
+#include <system/audio.h>
 
 // NBAIO implementations
 #include <media/nbaio/AudioStreamInSource.h>
@@ -1925,34 +1925,19 @@
         // check compatibility with audio effects.
         { // scope for mLock
             Mutex::Autolock _l(mLock);
-            // do not accept RAW flag if post processing are present. Note that post processing on
-            // a fast mixer are necessarily hardware
-            sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_STAGE);
-            if (chain != 0) {
-                ALOGV_IF((*flags & AUDIO_OUTPUT_FLAG_RAW) != 0,
-                        "AUDIO_OUTPUT_FLAG_RAW denied: post processing effect present");
-                *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
-            }
-            // Do not accept FAST flag if software global effects are present
-            chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
-            if (chain != 0) {
-                ALOGV_IF((*flags & AUDIO_OUTPUT_FLAG_RAW) != 0,
-                        "AUDIO_OUTPUT_FLAG_RAW denied: global effect present");
-                *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
-                if (chain->hasSoftwareEffect()) {
-                    ALOGV("AUDIO_OUTPUT_FLAG_FAST denied: software global effect present");
-                    *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
-                }
-            }
-            // Do not accept FAST flag if the session has software effects
-            chain = getEffectChain_l(sessionId);
-            if (chain != 0) {
-                ALOGV_IF((*flags & AUDIO_OUTPUT_FLAG_RAW) != 0,
-                        "AUDIO_OUTPUT_FLAG_RAW denied: effect present on session");
-                *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
-                if (chain->hasSoftwareEffect()) {
-                    ALOGV("AUDIO_OUTPUT_FLAG_FAST denied: software effect present on session");
-                    *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
+            for (audio_session_t session : {
+                    AUDIO_SESSION_OUTPUT_STAGE,
+                    AUDIO_SESSION_OUTPUT_MIX,
+                    sessionId,
+                }) {
+                sp<EffectChain> chain = getEffectChain_l(session);
+                if (chain.get() != nullptr) {
+                    audio_output_flags_t old = *flags;
+                    chain->checkOutputFlagCompatibility(flags);
+                    if (old != *flags) {
+                        ALOGV("AUDIO_OUTPUT_FLAGS denied by effect, session=%d old=%#x new=%#x",
+                                (int)session, (int)old, (int)*flags);
+                    }
                 }
             }
         }
@@ -2750,9 +2735,7 @@
             ALOG_ASSERT(mCallbackThread != 0);
             mCallbackThread->setDraining(mDrainSequence);
         }
-        status_t result = mOutput->stream->drain(
-            (mMixerStatus == MIXER_DRAIN_TRACK) ? AUDIO_DRAIN_EARLY_NOTIFY
-                                                : AUDIO_DRAIN_ALL);
+        status_t result = mOutput->stream->drain(mMixerStatus == MIXER_DRAIN_TRACK);
         ALOGE_IF(result != OK, "Error when draining stream: %d", result);
     }
 }
@@ -6611,12 +6594,11 @@
           // Do not accept FAST flag if the session has software effects
           sp<EffectChain> chain = getEffectChain_l(sessionId);
           if (chain != 0) {
-              ALOGV_IF((*flags & AUDIO_INPUT_FLAG_RAW) != 0,
-                      "AUDIO_INPUT_FLAG_RAW denied: effect present on session");
-              *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_RAW);
-              if (chain->hasSoftwareEffect()) {
-                  ALOGV("AUDIO_INPUT_FLAG_FAST denied: software effect present on session");
-                  *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_FAST);
+              audio_input_flags_t old = *flags;
+              chain->checkInputFlagCompatibility(flags);
+              if (old != *flags) {
+                  ALOGV("AUDIO_INPUT_FLAGS denied by effect old=%#x new=%#x",
+                          (int)old, (int)*flags);
               }
           }
           ALOGV_IF((*flags & AUDIO_INPUT_FLAG_FAST) != 0,
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index c9652de..97a9c94 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -19,7 +19,7 @@
 #include <utils/RefBase.h>
 #include <media/AudioPolicy.h>
 #include <utils/KeyedVector.h>
-#include <hardware/audio.h>
+#include <system/audio.h>
 #include <utils/String8.h>
 
 namespace android {
diff --git a/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
index 424df84..8822927 100644
--- a/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
@@ -20,7 +20,7 @@
 #include <utils/KeyedVector.h>
 #include <utils/StrongPointer.h>
 #include <utils/SortedVector.h>
-#include <hardware/audio.h>
+#include <system/audio.h>
 
 namespace android {
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
index 10f0766..e7fcefc 100644
--- a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
+++ b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
@@ -18,7 +18,6 @@
 
 #include "IVolumeCurvesCollection.h"
 #include <policy.h>
-#include <hardware/audio.h>
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <utils/SortedVector.h>
diff --git a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
index a3536e5..e32d0d3 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
@@ -22,7 +22,7 @@
 #include "AudioGain.h"
 #include "IOProfile.h"
 #include "TypeConverter.h"
-#include <hardware/audio.h>
+#include <system/audio.h>
 #include <utils/Log.h>
 #include <cutils/misc.h>
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 8cbbf44..356aef1 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -20,8 +20,8 @@
 #include "HwModule.h"
 #include "IOProfile.h"
 #include "AudioGain.h"
-#include <hardware/audio.h>
 #include <policy.h>
+#include <system/audio.h>
 
 namespace android {
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 5dcd41c..a5746cc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -33,11 +33,11 @@
 #include <AudioPolicyEngineInstance.h>
 #include <cutils/properties.h>
 #include <utils/Log.h>
-#include <hardware/audio.h>
 #include <hardware/audio_effect.h>
 #include <media/AudioParameter.h>
 #include <media/AudioPolicyHelper.h>
 #include <soundtrigger/SoundTrigger.h>
+#include <system/audio.h>
 #include "AudioPolicyManager.h"
 #ifndef USE_XML_AUDIO_POLICY_CONF
 #include <ConfigParsingUtils.h>