Merge "Camera: fix FlashLightTest"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 34d040e..46a95c5 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -65,6 +65,8 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/liboboe*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj_arm/STATIC_LIBRARIES/liboboe*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj_arm/SHARED_LIBRARIES/liboboe*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/mediacodec)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/mediacodec.rc)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 60effe2..c53e6c3 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -56,17 +56,19 @@
 }
 
 status_t CameraStatus::writeToParcel(android::Parcel* parcel) const {
-    status_t res;
-    res = parcel->writeString8(cameraId);
+    auto res = parcel->writeString16(String16(cameraId));
     if (res != OK) return res;
+
     res = parcel->writeInt32(status);
     return res;
 }
 
 status_t CameraStatus::readFromParcel(const android::Parcel* parcel) {
-    status_t res;
-    res = parcel->readString8(&cameraId);
+    String16 tempCameraId;
+    auto res = parcel->readString16(&tempCameraId);
     if (res != OK) return res;
+    cameraId = String8(tempCameraId);
+
     res = parcel->readInt32(&status);
     return res;
 }
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 9f41403..1466222 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -228,11 +228,11 @@
 void CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
     native_handle_t* nativeHandle = native_handle_create(1, 0);
     if (!nativeHandle) {
-        ALOGE("setHeapBase(), failed to create native handle");
+        ALOGE("setSharedBufferBase(), failed to create native handle");
         return;
     }
     if (heap == NULL) {
-        ALOGE("setHeapBase(): heap is NULL");
+        ALOGE("setSharedBufferBase(): heap is NULL");
         return;
     }
     int fd = heap->getHeapID();
@@ -244,10 +244,6 @@
     ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
 }
 
-void CryptoHal::clearHeapBase(const sp<IMemoryHeap>& heap) {
-    mHeapBases.removeItem(heap->getBase());
-}
-
 status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* buffer) {
     ssize_t offset;
     size_t size;
@@ -261,8 +257,9 @@
         return UNEXPECTED_NULL;
     }
 
-    // memory must be in the declared heap
-    CHECK(mHeapBases.indexOfKey(heap->getBase()) >= 0);
+    if (mHeapBases.indexOfKey(heap->getBase()) < 0) {
+        setHeapBase(heap);
+    }
 
     buffer->bufferId = mHeapBases.valueFor(heap->getBase());
     buffer->offset = offset >= 0 ? offset : 0;
diff --git a/drm/libmediadrm/ICrypto.cpp b/drm/libmediadrm/ICrypto.cpp
index 7b70205..92c9548 100644
--- a/drm/libmediadrm/ICrypto.cpp
+++ b/drm/libmediadrm/ICrypto.cpp
@@ -36,8 +36,6 @@
     DECRYPT,
     NOTIFY_RESOLUTION,
     SET_MEDIADRM_SESSION,
-    SET_HEAP,
-    UNSET_HEAP,
 };
 
 struct BpCrypto : public BpInterface<ICrypto> {
@@ -179,23 +177,6 @@
         return reply.readInt32();
     }
 
-    virtual void setHeap(const sp<IMemoryHeap> &heap) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(heap));
-        remote()->transact(SET_HEAP, data, &reply);
-        return;
-    }
-
-    virtual void unsetHeap(const sp<IMemoryHeap>& heap) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(heap));
-        remote()->transact(UNSET_HEAP, data, &reply);
-        return;
-    }
-
-
 private:
     void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
         uint32_t size = reply.readInt32();
@@ -423,24 +404,6 @@
             return OK;
         }
 
-        case SET_HEAP:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            sp<IMemoryHeap> heap =
-                interface_cast<IMemoryHeap>(data.readStrongBinder());
-            setHeap(heap);
-            return OK;
-        }
-
-        case UNSET_HEAP:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            sp<IMemoryHeap> heap =
-                interface_cast<IMemoryHeap>(data.readStrongBinder());
-            unsetHeap(heap);
-            return OK;
-        }
-
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/include/ndk/NdkImage.h b/include/ndk/NdkImage.h
index 40c1699..3d1bacc 100644
--- a/include/ndk/NdkImage.h
+++ b/include/ndk/NdkImage.h
@@ -40,6 +40,10 @@
 
 #include "NdkMediaError.h"
 
+#if __ANDROID_API__ >= 26
+#include <android/hardware_buffer.h>
+#endif /* __ANDROID_API__ >= 26 */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -707,6 +711,53 @@
 
 #endif /* __ANDROID_API__ >= 24 */
 
+#if __ANDROID_API__ >= 26
+
+/*
+ * Return the image back the the system and delete the AImage object from memory asynchronously.
+ *
+ * <p>Similar to {@link AImage_delete}, do NOT use the image pointer after this method returns.
+ * However, the caller can still hold on to the {@link AHardwareBuffer} returned from this image and
+ * signal the release of the hardware buffer back to the {@link AImageReader}'s queue using
+ * releaseFenceFd.</p>
+ *
+ * @param image The {@link AImage} to be deleted.
+ * @param releaseFenceFd A sync fence fd defined in {@link sync.h}, which signals the release of
+ *         underlying {@link AHardwareBuffer}.
+ *
+ * @see sync.h
+ */
+void AImage_deleteAsync(AImage* image, int releaseFenceFd);
+
+/**
+ * Get the hardware buffer handle of the input image intended for GPU and/or hardware access.
+ *
+ * <p>Note that no reference on the returned {@link AHardwareBuffer} handle is acquired
+ * automatically. Once the {@link AImage} or the parent {@link AImageReader} is deleted, the
+ * {@link AHardwareBuffer} handle from previous {@link AImage_getHardwareBuffer} becomes
+ * invalid.</p>
+ *
+ * <p>If the caller ever needs to hold on a reference to the {@link AHardwareBuffer} handle after
+ * the {@link AImage} or the parent {@link AImageReader} is deleted, it must call {@link
+ * AHardwareBuffer_acquire} to acquire an extra reference, and call {@link AHardwareBuffer_release}
+ * once it has finished using it in order to properly deallocate the underlying memory managed by
+ * {@link AHardwareBuffer}. If the caller has acquired extra reference on an {@link AHardwareBuffer}
+ * returned from this function, it must also listen to {@link onBufferFreed} callback to be
+ * notified when the buffer is no longer used by {@link AImageReader}.</p>
+ *
+ * @param image the {@link AImage} of interest.
+ * @param outBuffer The memory area pointed to by buffer will contain the acquired AHardwareBuffer
+ *         handle.
+ * @return <ul>
+ *         <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ *         <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image or buffer is NULL</li></ul>
+ *
+ * @see AImageReader_ImageCallback
+ */
+media_status_t AImage_getHardwareBuffer(const AImage* image, /*out*/AHardwareBuffer** buffer);
+
+#endif /* __ANDROID_API__ >= 26 */
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/include/ndk/NdkImageReader.h b/include/ndk/NdkImageReader.h
index 8d72c28..a158da9 100644
--- a/include/ndk/NdkImageReader.h
+++ b/include/ndk/NdkImageReader.h
@@ -300,6 +300,127 @@
 
 #endif /* __ANDROID_API__ >= 24 */
 
+#if __ANDROID_API__ >= 26
+
+/**
+ * AImageReader constructor similar to {@link AImageReader_new} that takes an additional parameter
+ * for the consumer usage. All other parameters and the return values are identical to those passed
+ * to {@line AImageReader_new}.
+ *
+ * @param usage0 specifies how the consumer will access the AImage, using combination of the
+ *            AHARDWAREBUFFER_USAGE0 flags described in {@link hardware_buffer.h}.
+ *            Passing {@link AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN} is equivalent to calling
+ *            {@link AImageReader_new} with the same parameters. Note that consumers that do not
+ *            require CPU access to the buffer should omit {@link
+ *            AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN} to improve performance.
+ * @param usage1 specifies how the consumer will access the AImage, using combination of the
+ *            AHARDWAREBUFFER_USAGE1 flags described in {@link hardware_buffer.h}.
+ *
+ * @see AImage
+ * @see AImageReader_new
+ * @see AHardwareBuffer
+ */
+media_status_t AImageReader_newWithUsage(
+        int32_t width, int32_t height, int32_t format, uint64_t usage0,
+        uint64_t usage1, int32_t maxImages, /*out*/ AImageReader** reader);
+
+/*
+ * Acquire the next {@link AImage} from the image reader's queue asynchronously.
+ *
+ * <p>AImageReader acquire method similar to {@link AImageReader_acquireNextImage} that takes an
+ * additional parameter for the sync fence. All other parameters and the return values are
+ * identical to those passed to {@link AImageReader_acquireNextImage}.</p>
+ *
+ * @param acquireFenceFd A sync fence fd defined in {@link sync.h}, which is used to signal when the
+ *         buffer is ready to consume. When synchronization fence is not needed, fence will be set
+ *         to -1 and the {@link AImage} returned is ready for use immediately. Otherwise, user shall
+ *         use syscalls such as {@code poll()}, {@code epoll()}, {@code select()} to wait for the
+ *         fence fd to change status before attempting to access the {@link AImage} returned.
+ *
+ * @see sync.h
+ * @see sync_get_fence_info
+ */
+media_status_t AImageReader_acquireNextImageAsync(
+        AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd);
+
+/*
+ * Acquire the latest {@link AImage} from the image reader's queue asynchronously, dropping older
+ * images.
+ *
+ * <p>AImageReader acquire method similar to {@link AImageReader_acquireLatestImage} that takes an
+ * additional parameter for the sync fence. All other parameters and the return values are
+ * identical to those passed to {@link AImageReader_acquireLatestImage}.</p>
+ *
+ * @param acquireFenceFd A sync fence fd defined in {@link sync.h}, which is used to signal when the
+ *         buffer is ready to consume. When synchronization fence is not needed, fence will be set
+ *         to -1 and the {@link AImage} returned is ready for use immediately. Otherwise, user shall
+ *         use syscalls such as {@code poll()}, {@code epoll()}, {@code select()} to wait for the
+ *         fence fd to change status before attempting to access the {@link AImage} returned.
+ *
+ * @see sync.h
+ * @see sync_get_fence_info
+ */
+media_status_t AImageReader_acquireLatestImageAsync(
+        AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd);
+/**
+ * The definition of {@link AImageReader} buffer removed callback.
+ *
+ * @param context The optional application context provided by user in
+ *                {@link AImageReader_setBufferRemovedListener}.
+ * @param reader The {@link AImageReader} of interest.
+ * @param buffer The {@link AHardwareBuffer} that is being removed from this image reader.
+ */
+typedef void (*AImageReader_BufferRemovedCallback)(void* context,
+        AImageReader* reader,
+        AHardwareBuffer* buffer);
+
+typedef struct AImageReader_BufferRemovedListener {
+    /// optional application context.
+    void*                      context;
+
+    /**
+     * This callback is called when an old {@link AHardwareBuffer} is about to be removed from the
+     * image reader.
+     *
+     * <p>Note that registering this callback is optional unless the user holds on extra reference
+     * to {@link AHardwareBuffer} returned from {@link AImage_getHardwareBuffer} by calling {@link
+     * AHardwareBuffer_acquire} or creating external graphic objects, such as EglImage, from it.</p>
+     *
+     * <p>If the callback is registered, the {@link AImageReader} will hold on the last of its
+     * references to the {@link AHardwareBuffer} until this callback returns. User can use the
+     * callback to get notified that it becomes the last owner of the buffer. It is up to the user
+     * to decide to either 1) immediately release all of its references to the buffer; or 2) keep
+     * using the buffer and release it in future. Note that, if option 2 if used, user of this API
+     * is responsible to deallocate the buffer properly by calling {@link AHardwareBuffer_release}.
+     * </p>
+     *
+     * @see AHardwareBuffer_release
+     * @see AImage_getHardwareBuffer
+     */
+    AImageReader_BufferRemovedCallback onBufferRemoved;
+} AImageReader_BufferRemovedListener;
+
+/**
+ * Set the onBufferRemoved listener of this image reader.
+ *
+ * <p>Note that calling this method will replace previously registered listeners.</p>
+ *
+ * @param reader The image reader of interest.
+ * @param listener the {@link AImageReader_BufferRemovedListener} to be registered. Set this to
+ * NULL if application no longer needs to listen to buffer removed events.
+ *
+ * @return <ul>
+ *         <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ *         <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader is NULL.</li></ul>
+ *
+ * @see AImage_getHardwareBuffer
+ */
+media_status_t AImageReader_setBufferRemovedListener(
+        AImageReader* reader, AImageReader_BufferRemovedListener* listener);
+
+#endif /* __ANDROID_API__ >= 26 */
+
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/include/ndk/NdkMediaCodec.h b/include/ndk/NdkMediaCodec.h
index a63f39a..637bf9b 100644
--- a/include/ndk/NdkMediaCodec.h
+++ b/include/ndk/NdkMediaCodec.h
@@ -179,6 +179,78 @@
 media_status_t AMediaCodec_releaseOutputBufferAtTime(
         AMediaCodec *mData, size_t idx, int64_t timestampNs);
 
+/**
+ * Creates a Surface that can be used as the input to encoder, in place of input buffers
+ *
+ * This can only be called after the codec has been configured via
+ * AMediaCodec_configure(..); and before AMediaCodec_start() has been called.
+ *
+ * The application is responsible for releasing the surface by calling
+ * ANativeWindow_release() when done.
+ *
+ * For more details, see the Java documentation for MediaCodec.createInputSurface.
+ */
+media_status_t AMediaCodec_createInputSurface(
+        AMediaCodec *mData, ANativeWindow **surface);
+
+/**
+ * Creates a persistent Surface that can be used as the input to encoder
+ *
+ * Persistent surface can be reused by MediaCodec instances and can be set
+ * on a new instance via AMediaCodec_setInputSurface().
+ * A persistent surface can be connected to at most one instance of MediaCodec
+ * at any point in time.
+ *
+ * The application is responsible for releasing the surface by calling
+ * ANativeWindow_release() when done.
+ *
+ * For more details, see the Java documentation for MediaCodec.createPersistentInputSurface.
+ */
+media_status_t AMediaCodec_createPersistentInputSurface(
+        ANativeWindow **surface);
+
+/**
+ * Set a persistent-surface that can be used as the input to encoder, in place of input buffers
+ *
+ * The surface provided *must* be a persistent surface created via
+ * AMediaCodec_createPersistentInputSurface()
+ * This can only be called after the codec has been configured by calling
+ * AMediaCodec_configure(..); and before AMediaCodec_start() has been called.
+ *
+ * For more details, see the Java documentation for MediaCodec.setInputSurface.
+ */
+media_status_t AMediaCodec_setInputSurface(
+        AMediaCodec *mData, ANativeWindow *surface);
+
+/**
+ * Signal additional parameters to the codec instance.
+ *
+ * Parameters can be communicated only when the codec is running, i.e
+ * after AMediaCodec_start() has been called.
+ *
+ * NOTE: Some of these parameter changes may silently fail to apply.
+ */
+media_status_t AMediaCodec_setParameters(
+        AMediaCodec *mData, const AMediaFormat* params);
+
+/**
+ * Signals end-of-stream on input. Equivalent to submitting an empty buffer with
+ * AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM set.
+ *
+ * Returns AMEDIA_ERROR_INVALID_OPERATION when used with an encoder not in executing state
+ * or not receiving input from a Surface created by AMediaCodec_createInputSurface or
+ * AMediaCodec_createPersistentInputSurface.
+ *
+ * Returns the previous codec error if one exists.
+ *
+ * Returns AMEDIA_OK when completed succesfully.
+ *
+ * For more details, see the Java documentation for MediaCodec.signalEndOfInputStream.
+ */
+media_status_t AMediaCodec_signalEndOfInputStream(AMediaCodec *mData);
+
+
+
 typedef enum {
     AMEDIACODECRYPTOINFO_MODE_CLEAR = 0,
     AMEDIACODECRYPTOINFO_MODE_AES_CTR = 1,
diff --git a/include/ndk/NdkMediaError.h b/include/ndk/NdkMediaError.h
index 9709a6f..1b51364 100644
--- a/include/ndk/NdkMediaError.h
+++ b/include/ndk/NdkMediaError.h
@@ -45,6 +45,7 @@
     AMEDIA_ERROR_UNSUPPORTED           = AMEDIA_ERROR_BASE - 2,
     AMEDIA_ERROR_INVALID_OBJECT        = AMEDIA_ERROR_BASE - 3,
     AMEDIA_ERROR_INVALID_PARAMETER     = AMEDIA_ERROR_BASE - 4,
+    AMEDIA_ERROR_INVALID_OPERATION     = AMEDIA_ERROR_BASE - 5,
 
     AMEDIA_DRM_ERROR_BASE              = -20000,
     AMEDIA_DRM_NOT_PROVISIONED         = AMEDIA_DRM_ERROR_BASE - 1,
diff --git a/media/libaudiohal/DevicesFactoryHalHidl.cpp b/media/libaudiohal/DevicesFactoryHalHidl.cpp
index 758a5805..fc2645e 100644
--- a/media/libaudiohal/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/DevicesFactoryHalHidl.cpp
@@ -45,7 +45,8 @@
         // and thus have the same lifespan.
         mDevicesFactory->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
     } else {
-        LOG_ALWAYS_FATAL("Failed to obtain IDevicesFactory service");
+        ALOGE("Failed to obtain IDevicesFactory service, terminating process.");
+        exit(1);
     }
 }
 
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.cpp b/media/libaudiohal/EffectsFactoryHalHidl.cpp
index f7dbb9c..605c059 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/EffectsFactoryHalHidl.cpp
@@ -44,7 +44,10 @@
 
 EffectsFactoryHalHidl::EffectsFactoryHalHidl() : ConversionHelperHidl("EffectsFactory") {
     mEffectsFactory = IEffectsFactory::getService();
-    LOG_ALWAYS_FATAL_IF(mEffectsFactory == 0, "Failed to obtain IEffectsFactory service");
+    if (mEffectsFactory == 0) {
+        ALOGE("Failed to obtain IEffectsFactory service, terminating process.");
+        exit(1);
+    }
 }
 
 EffectsFactoryHalHidl::~EffectsFactoryHalHidl() {
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 0d8142d..8028969 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1345,6 +1345,7 @@
     case AUDIO_DEVICE_OUT_WIRED_HEADSET:
     case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+    case AUDIO_DEVICE_OUT_USB_HEADSET:
         return 0;
     default :
         return -EINVAL;
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index ccfd29c..f2844ed 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -531,6 +531,7 @@
         break;
     case AUDIO_DEVICE_OUT_WIRED_HEADSET:
     case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+    case AUDIO_DEVICE_OUT_USB_HEADSET:
     default:
         break;
     }
diff --git a/media/libmedia/include/Crypto.h b/media/libmedia/include/Crypto.h
index b68413d..ce08f98 100644
--- a/media/libmedia/include/Crypto.h
+++ b/media/libmedia/include/Crypto.h
@@ -55,9 +55,6 @@
             const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
             const DestinationBuffer &destination, AString *errorDetailMsg);
 
-    virtual void setHeap(const sp<IMemoryHeap>&) {}
-    virtual void unsetHeap(const sp<IMemoryHeap>&) {}
-
 private:
     mutable Mutex mLock;
 
diff --git a/media/libmedia/include/CryptoHal.h b/media/libmedia/include/CryptoHal.h
index d6214c2..28ade20 100644
--- a/media/libmedia/include/CryptoHal.h
+++ b/media/libmedia/include/CryptoHal.h
@@ -60,9 +60,6 @@
             const ICrypto::DestinationBuffer &destination,
             AString *errorDetailMsg);
 
-    virtual void setHeap(const sp<IMemoryHeap>& heap) { setHeapBase(heap); }
-    virtual void unsetHeap(const sp<IMemoryHeap>& heap) { clearHeapBase(heap); }
-
 private:
     mutable Mutex mLock;
 
@@ -85,7 +82,6 @@
             const uint8_t uuid[16], const void *initData, size_t size);
 
     void setHeapBase(const sp<IMemoryHeap>& heap);
-    void clearHeapBase(const sp<IMemoryHeap>& heap);
 
     status_t toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* buffer);
 
diff --git a/media/libmedia/include/ICrypto.h b/media/libmedia/include/ICrypto.h
index f83c846..8990f4b 100644
--- a/media/libmedia/include/ICrypto.h
+++ b/media/libmedia/include/ICrypto.h
@@ -27,7 +27,6 @@
 
 struct AString;
 class IMemory;
-class IMemoryHeap;
 
 struct ICrypto : public IInterface {
     DECLARE_META_INTERFACE(Crypto);
@@ -65,13 +64,6 @@
             const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
             const DestinationBuffer &destination, AString *errorDetailMsg) = 0;
 
-    /**
-     * Declare the heap that the shared memory source buffers passed
-     * to decrypt will be allocated from.
-     */
-    virtual void setHeap(const sp<IMemoryHeap>& heap) = 0;
-    virtual void unsetHeap(const sp<IMemoryHeap>& heap) = 0;
-
 private:
     DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
 };
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index c00a951..638eec3 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -465,6 +465,10 @@
     } else {
         // Legacy IOMX
         binder = sm->getService(String16("media.codec"));
+        if (binder == NULL) {
+           ALOGE("Unable to connect to media codec service");
+           return NO_INIT;
+        }
         mCodecDeathListener = new ServiceDeathNotifier(binder, listener,
                 MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
         binder->linkToDeath(mCodecDeathListener);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 621347d..66b64f8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -93,7 +93,7 @@
     mLooper->stop();
 
     // finalize any pending metrics, usually a no-op.
-    finalizeMetrics("destructor");
+    updateMetrics("destructor");
     logMetrics("destructor");
 
     if (mAnalyticsItem != NULL) {
@@ -511,11 +511,11 @@
     return OK;
 }
 
-void NuPlayerDriver::finalizeMetrics(const char *where) {
+void NuPlayerDriver::updateMetrics(const char *where) {
     if (where == NULL) {
         where = "unknown";
     }
-    ALOGV("finalizeMetrics(%p) from %s at state %d", this, where, mState);
+    ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
 
     // gather the final stats for this record
     Vector<sp<AMessage>> trackStats;
@@ -560,18 +560,16 @@
                 }
             }
         }
-
-        // getDuration() uses mLock for mutex -- careful where we use it.
-        int duration_ms = -1;
-        getDuration(&duration_ms);
-        if (duration_ms != -1) {
-            mAnalyticsItem->setInt64(kPlayerDuration, duration_ms);
-        }
-
-        if (mPlayingTimeUs > 0) {
-            mAnalyticsItem->setInt64(kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
-        }
     }
+
+    // always provide duration and playing time, even if they have 0/unknown values.
+
+    // getDuration() uses mLock for mutex -- careful where we use it.
+    int duration_ms = -1;
+    getDuration(&duration_ms);
+    mAnalyticsItem->setInt64(kPlayerDuration, duration_ms);
+
+    mAnalyticsItem->setInt64(kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
 }
 
 
@@ -605,7 +603,7 @@
 status_t NuPlayerDriver::reset() {
     ALOGD("reset(%p) at state %d", this, mState);
 
-    finalizeMetrics("reset");
+    updateMetrics("reset");
     logMetrics("reset");
 
     Mutex::Autolock autoLock(mLock);
@@ -731,7 +729,7 @@
     if (key == FOURCC('m','t','r','X')) {
         // mtrX -- a play on 'metrics' (not matrix)
         // gather current info all together, parcel it, and send it back
-        finalizeMetrics("api");
+        updateMetrics("api");
         mAnalyticsItem->writeToParcel(reply);
         return OK;
     }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 082f71a..c5ddcb0 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -137,7 +137,7 @@
     bool mLooping;
     bool mAutoLoop;
 
-    void finalizeMetrics(const char *where);
+    void updateMetrics(const char *where);
     void logMetrics(const char *where);
 
     status_t prepare_l();
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp
index 7936ad2..de38e7f 100644
--- a/media/libnbaio/NBLog.cpp
+++ b/media/libnbaio/NBLog.cpp
@@ -68,24 +68,32 @@
 
 NBLog::FormatEntry::iterator NBLog::FormatEntry::args() const {
     auto it = begin();
-    // Second entry can be author or timestamp. Skip author if present
-    if ((++it)->type == EVENT_AUTHOR) {
+    // skip start fmt
+    ++it;
+    // skip timestamp
+    ++it;
+    // Skip author if present
+    if (it->type == EVENT_AUTHOR) {
         ++it;
     }
-    return ++it;
+    return it;
 }
 
 timespec NBLog::FormatEntry::timestamp() const {
     auto it = begin();
-    if ((++it)->type != EVENT_TIMESTAMP) {
-        ++it;
-    }
+    // skip start fmt
+    ++it;
     return it.payload<timespec>();
 }
 
 pid_t NBLog::FormatEntry::author() const {
     auto it = begin();
-    if ((++it)->type == EVENT_AUTHOR) {
+    // skip start fmt
+    ++it;
+    // skip timestamp
+    ++it;
+    // if there is an author entry, return it, return -1 otherwise
+    if (it->type == EVENT_AUTHOR) {
         return it.payload<int>();
     }
     return -1;
@@ -96,6 +104,8 @@
     auto it = begin();
     // copy fmt start entry
     it.copyTo(dst);
+    // copy timestamp
+    (++it).copyTo(dst);
     // insert author entry
     size_t authorEntrySize = NBLog::Entry::kOverhead + sizeof(author);
     uint8_t authorEntry[authorEntrySize];
diff --git a/media/libnbaio/include/NBLog.h b/media/libnbaio/include/NBLog.h
index 7aaf298..59b77bd 100644
--- a/media/libnbaio/include/NBLog.h
+++ b/media/libnbaio/include/NBLog.h
@@ -59,8 +59,8 @@
 
 // a formatted entry has the following structure:
 //    * START_FMT entry, containing the format string
-//    * author entry of the thread that generated it (optional, present in merged log)
 //    * TIMESTAMP entry
+//    * author entry of the thread that generated it (optional, present in merged log)
 //    * format arg1
 //    * format arg2
 //    * ...
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 81eecaf..37e1546 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -551,7 +551,8 @@
       mCreateInputBuffersSuspended(false),
       mTunneled(false),
       mDescribeColorAspectsIndex((OMX_INDEXTYPE)0),
-      mDescribeHDRStaticInfoIndex((OMX_INDEXTYPE)0) {
+      mDescribeHDRStaticInfoIndex((OMX_INDEXTYPE)0),
+      mVendorExtensionsStatus(kExtensionsUnchecked) {
     mUninitializedState = new UninitializedState(this);
     mLoadedState = new LoadedState(this);
     mLoadedToIdleState = new LoadedToIdleState(this);
@@ -2216,13 +2217,16 @@
     int32_t maxInputSize;
     if (msg->findInt32("max-input-size", &maxInputSize)) {
         err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
+        err = OK; // ignore error
     } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
         err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
+        err = OK; // ignore error
     }
 
     int32_t priority;
     if (msg->findInt32("priority", &priority)) {
         err = setPriority(priority);
+        err = OK; // ignore error
     }
 
     int32_t rateInt = -1;
@@ -2233,6 +2237,14 @@
     }
     if (rateFloat > 0) {
         err = setOperatingRate(rateFloat, video);
+        err = OK; // ignore errors
+    }
+
+    if (err == OK) {
+        err = setVendorParameters(msg);
+        if (err != OK) {
+            return err;
+        }
     }
 
     // NOTE: both mBaseOutputFormat and mOutputFormat are outputFormat to signal first frame.
@@ -5106,7 +5118,7 @@
             return BAD_TYPE;
     }
 
-    return OK;
+    return getVendorParameters(portIndex, notify);
 }
 
 void ACodec::onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects &aspects) {
@@ -7176,7 +7188,362 @@
         err = OK; // ignore failure
     }
 
-    return err;
+    return setVendorParameters(params);
+}
+
+// Removes trailing tags matching |tag| from |key| (e.g. a settings name). |minLength| specifies
+// the minimum number of characters to keep in |key| (even if it has trailing tags).
+// (Used to remove trailing 'value' tags in settings names, e.g. to normalize
+// 'vendor.settingsX.value' to 'vendor.settingsX')
+static void removeTrailingTags(char *key, size_t minLength, const char *tag) {
+    size_t length = strlen(key);
+    size_t tagLength = strlen(tag);
+    while (length > minLength + tagLength
+            && !strcmp(key + length - tagLength, tag)
+            && key[length - tagLength - 1] == '.') {
+        length -= tagLength + 1;
+        key[length] = '\0';
+    }
+}
+
+/**
+ * Struct encompassing a vendor extension config structure and a potential error status (in case
+ * the structure is null). Used to iterate through vendor extensions.
+ */
+struct VendorExtension {
+    OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config;  // structure does not own config
+    status_t status;
+
+    // create based on an error status
+    VendorExtension(status_t s_ = NO_INIT) : config(nullptr), status(s_) { }
+
+    // create based on a successfully retrieved config structure
+    VendorExtension(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *c_) : config(c_), status(OK) { }
+};
+
+// class VendorExtensions;
+/**
+ * Forward iterator to enumerate vendor extensions supported by an OMX component.
+ */
+class VendorExtensionIterator {
+//private:
+    static constexpr size_t kLastIndex = ~(size_t)0; // last index marker
+
+    sp<IOMXNode> mNode;                   // component
+    size_t mIndex;                        // current android extension index
+    std::unique_ptr<uint8_t[]> mBacking;  // current extension's backing
+    VendorExtension mCurrent;             // current extension
+
+    VendorExtensionIterator(const sp<IOMXNode> &node, size_t index)
+        : mNode(node),
+          mIndex(index) {
+        mCurrent = retrieve();
+    }
+
+    friend class VendorExtensions;
+
+public:
+    // copy constructor
+    VendorExtensionIterator(const VendorExtensionIterator &it)
+        : VendorExtensionIterator(it.mNode, it.mIndex) { }
+
+    // retrieves the current extension pointed to by this iterator
+    VendorExtension retrieve() {
+        if (mIndex == kLastIndex) {
+            return NO_INIT;
+        }
+
+        // try with one param first, then retry if extension needs more than 1 param
+        for (size_t paramSizeUsed = 1;; ) {
+            if (paramSizeUsed > OMX_MAX_ANDROID_VENDOR_PARAMCOUNT) {
+                return BAD_VALUE; // this prevents overflow in the following formula
+            }
+
+            size_t size = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) +
+                (paramSizeUsed - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::param);
+            mBacking.reset(new uint8_t[size]);
+            if (!mBacking) {
+                return NO_MEMORY;
+            }
+
+            OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config =
+                reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(mBacking.get());
+
+            InitOMXParams(config);
+            config->nSize = size;
+            config->nIndex = mIndex;
+            config->nParamSizeUsed = paramSizeUsed;
+            status_t err = mNode->getConfig(
+                    (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension, config, size);
+            if (err == OK && config->nParamCount > paramSizeUsed && paramSizeUsed == 1) {
+                // reallocate if we need a bigger config
+                paramSizeUsed = config->nParamCount;
+                continue;
+            } else if (err == NOT_ENOUGH_DATA
+                   || (err != OK && mIndex == 0)) {
+                // stop iterator on no-more signal, or if index is not at all supported
+                mIndex = kLastIndex;
+                return NO_INIT;
+            } else if (err != OK) {
+                return err;
+            } else if (paramSizeUsed != config->nParamSizeUsed) {
+                return BAD_VALUE; // component shall not modify size of nParam
+            }
+
+            return config;
+        }
+    }
+
+    // returns extension pointed to by this iterator
+    VendorExtension operator*() {
+        return mCurrent;
+    }
+
+    // prefix increment: move to next extension
+    VendorExtensionIterator &operator++() { // prefix
+        if (mIndex != kLastIndex) {
+            ++mIndex;
+            mCurrent = retrieve();
+        }
+        return *this;
+    }
+
+    // iterator equality operators
+    bool operator==(const VendorExtensionIterator &o) {
+        return mNode == o.mNode && mIndex == o.mIndex;
+    }
+
+    bool operator!=(const VendorExtensionIterator &o) {
+        return !(*this == o);
+    }
+};
+
+/**
+ * Iterable container for vendor extensions provided by a component
+ */
+class VendorExtensions {
+//private:
+    sp<IOMXNode> mNode;
+
+public:
+    VendorExtensions(const sp<IOMXNode> &node)
+        : mNode(node) {
+    }
+
+    VendorExtensionIterator begin() {
+        return VendorExtensionIterator(mNode, 0);
+    }
+
+    VendorExtensionIterator end() {
+        return VendorExtensionIterator(mNode, VendorExtensionIterator::kLastIndex);
+    }
+};
+
+status_t ACodec::setVendorParameters(const sp<AMessage> &params) {
+    std::map<std::string, std::string> vendorKeys; // maps reduced name to actual name
+    constexpr char prefix[] = "vendor.";
+    constexpr size_t prefixLength = sizeof(prefix) - 1;
+    // longest possible vendor param name
+    char reducedKey[OMX_MAX_STRINGNAME_SIZE + OMX_MAX_STRINGVALUE_SIZE];
+
+    // identify all vendor keys to speed up search later and to detect vendor keys
+    for (size_t i = params->countEntries(); i; --i) {
+        AMessage::Type keyType;
+        const char* key = params->getEntryNameAt(i - 1, &keyType);
+        if (key != nullptr && !strncmp(key, prefix, prefixLength)
+                // it is safe to limit format keys to the max vendor param size as we only
+                // shorten parameter names by removing any trailing 'value' tags, and we
+                // already remove the vendor prefix.
+                && strlen(key + prefixLength) < sizeof(reducedKey)
+                && (keyType == AMessage::kTypeInt32
+                        || keyType == AMessage::kTypeInt64
+                        || keyType == AMessage::kTypeString)) {
+            strcpy(reducedKey, key + prefixLength);
+            removeTrailingTags(reducedKey, 0, "value");
+            auto existingKey = vendorKeys.find(reducedKey);
+            if (existingKey != vendorKeys.end()) {
+                ALOGW("[%s] vendor parameter '%s' aliases parameter '%s'",
+                        mComponentName.c_str(), key, existingKey->second.c_str());
+                // ignore for now
+            }
+            vendorKeys.emplace(reducedKey, key);
+        }
+    }
+
+    // don't bother component if we don't have vendor extensions as they may not have implemented
+    // the android vendor extension support, which will lead to unnecessary OMX failure logs.
+    if (vendorKeys.empty()) {
+        return OK;
+    }
+
+    char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) +
+            sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey)];
+
+    status_t finalError = OK;
+
+    // don't try again if component does not have vendor extensions
+    if (mVendorExtensionsStatus == kExtensionsNone) {
+        return OK;
+    }
+
+    for (VendorExtension ext : VendorExtensions(mOMXNode)) {
+        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config;
+        if (config == nullptr) {
+            return ext.status;
+        }
+
+        mVendorExtensionsStatus = kExtensionsExist;
+
+        config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name
+        strcpy(key, (const char *)config->cName);
+        size_t nameLength = strlen(key);
+        key[nameLength] = '.';
+
+        // don't set vendor extension if client has not provided any of its parameters
+        // or if client simply unsets parameters that are already unset
+        bool needToSet = false;
+        for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) {
+            // null-terminate param key
+            config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0';
+            strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey);
+            removeTrailingTags(key, nameLength, "value");
+            auto existingKey = vendorKeys.find(key);
+
+            // don't touch (e.g. change) parameters that are not specified by client
+            if (existingKey == vendorKeys.end()) {
+                continue;
+            }
+
+            bool wasSet = config->param[paramIndex].bSet;
+            switch (config->param[paramIndex].eValueType) {
+            case OMX_AndroidVendorValueInt32:
+            {
+                int32_t value;
+                config->param[paramIndex].bSet =
+                    (OMX_BOOL)params->findInt32(existingKey->second.c_str(), &value);
+                if (config->param[paramIndex].bSet) {
+                    config->param[paramIndex].nInt32 = value;
+                }
+                break;
+            }
+            case OMX_AndroidVendorValueInt64:
+            {
+                int64_t value;
+                config->param[paramIndex].bSet =
+                    (OMX_BOOL)params->findAsInt64(existingKey->second.c_str(), &value);
+                if (config->param[paramIndex].bSet) {
+                    config->param[paramIndex].nInt64 = value;
+                }
+                break;
+            }
+            case OMX_AndroidVendorValueString:
+            {
+                AString value;
+                config->param[paramIndex].bSet =
+                    (OMX_BOOL)params->findString(existingKey->second.c_str(), &value);
+                if (config->param[paramIndex].bSet) {
+                    strncpy((char *)config->param[paramIndex].cString, value.c_str(),
+                            sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cString));
+                }
+                break;
+            }
+            default:
+                ALOGW("[%s] vendor parameter '%s' is not a supported value",
+                        mComponentName.c_str(), key);
+                continue;
+            }
+            if (config->param[paramIndex].bSet || wasSet) {
+                needToSet = true;
+            }
+        }
+
+        if (needToSet) {
+            status_t err = mOMXNode->setConfig(
+                    (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension,
+                    config, config->nSize);
+            if (err != OK) {
+                key[nameLength] = '\0';
+                ALOGW("[%s] failed to set vendor extension '%s'", mComponentName.c_str(), key);
+                // try to set each extension, and return first failure
+                if (finalError == OK) {
+                    finalError = err;
+                }
+            }
+        }
+    }
+
+    if (mVendorExtensionsStatus == kExtensionsUnchecked) {
+        mVendorExtensionsStatus = kExtensionsNone;
+    }
+
+    return finalError;
+}
+
+status_t ACodec::getVendorParameters(OMX_U32 portIndex, sp<AMessage> &format) {
+    constexpr char prefix[] = "vendor.";
+    constexpr size_t prefixLength = sizeof(prefix) - 1;
+    char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) +
+            sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey) + prefixLength];
+    strcpy(key, prefix);
+
+    // don't try again if component does not have vendor extensions
+    if (mVendorExtensionsStatus == kExtensionsNone) {
+        return OK;
+    }
+
+    for (VendorExtension ext : VendorExtensions(mOMXNode)) {
+        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config;
+        if (config == nullptr) {
+            return ext.status;
+        }
+
+        mVendorExtensionsStatus = kExtensionsExist;
+
+        if (config->eDir != (portIndex == kPortIndexInput ? OMX_DirInput : OMX_DirOutput)) {
+            continue;
+        }
+
+        config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name
+        strcpy(key + prefixLength, (const char *)config->cName);
+        size_t nameLength = strlen(key);
+        key[nameLength] = '.';
+
+        for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) {
+            // null-terminate param key
+            config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0';
+            strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey);
+            removeTrailingTags(key, nameLength, "value");
+            if (config->param[paramIndex].bSet) {
+                switch (config->param[paramIndex].eValueType) {
+                case OMX_AndroidVendorValueInt32:
+                {
+                    format->setInt32(key, config->param[paramIndex].nInt32);
+                    break;
+                }
+                case OMX_AndroidVendorValueInt64:
+                {
+                    format->setInt64(key, config->param[paramIndex].nInt64);
+                    break;
+                }
+                case OMX_AndroidVendorValueString:
+                {
+                    config->param[paramIndex].cString[OMX_MAX_STRINGVALUE_SIZE - 1] = '\0';
+                    format->setString(key, (const char *)config->param[paramIndex].cString);
+                    break;
+                }
+                default:
+                    ALOGW("vendor parameter %s is not a supported value", key);
+                    continue;
+                }
+            }
+        }
+    }
+
+    if (mVendorExtensionsStatus == kExtensionsUnchecked) {
+        mVendorExtensionsStatus = kExtensionsNone;
+    }
+
+    return OK;
 }
 
 void ACodec::onSignalEndOfInputStream() {
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index 9cb0cdc..ecbbd03 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -39,12 +39,6 @@
 using BufferInfo = ACodecBufferChannel::BufferInfo;
 using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
 
-ACodecBufferChannel::~ACodecBufferChannel() {
-    if (mCrypto != nullptr && mDealer != nullptr) {
-        mCrypto->unsetHeap(mDealer->getMemoryHeap());
-    }
-}
-
 static BufferInfoIterator findClientBuffer(
         const std::shared_ptr<const std::vector<const BufferInfo>> &array,
         const sp<MediaCodecBuffer> &buffer) {
@@ -81,6 +75,9 @@
 }
 
 status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
+    if (mDealer != nullptr) {
+        return -ENOSYS;
+    }
     std::shared_ptr<const std::vector<const BufferInfo>> array(
             std::atomic_load(&mInputBuffers));
     BufferInfoIterator it = findClientBuffer(array, buffer);
@@ -100,7 +97,7 @@
         const uint8_t *iv, CryptoPlugin::Mode mode, CryptoPlugin::Pattern pattern,
         const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
         AString *errorDetailMsg) {
-    if (!hasCryptoOrDescrambler()) {
+    if (!hasCryptoOrDescrambler() || mDealer == nullptr) {
         return -ENOSYS;
     }
     std::shared_ptr<const std::vector<const BufferInfo>> array(
@@ -257,18 +254,6 @@
     }
 }
 
-sp<MemoryDealer> ACodecBufferChannel::makeMemoryDealer(size_t heapSize) {
-    sp<MemoryDealer> dealer;
-    if (mDealer != nullptr && mCrypto != nullptr) {
-        mCrypto->unsetHeap(mDealer->getMemoryHeap());
-    }
-    dealer = new MemoryDealer(heapSize, "ACodecBufferChannel");
-    if (mCrypto != nullptr) {
-        mCrypto->setHeap(dealer->getMemoryHeap());
-    }
-    return dealer;
-}
-
 void ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
     if (hasCryptoOrDescrambler()) {
         size_t totalSize = std::accumulate(
@@ -283,10 +268,8 @@
                 (size_t max, const BufferAndId& elem) {
                     return std::max(max, align(elem.mBuffer->capacity(), alignment));
                 });
-        size_t destinationBufferSize = maxSize;
-        size_t heapSize = totalSize + destinationBufferSize;
-        mDealer = makeMemoryDealer(heapSize);
-        mDecryptDestination = mDealer->allocate(destinationBufferSize);
+        mDealer = new MemoryDealer(totalSize + maxSize, "ACodecBufferChannel");
+        mDecryptDestination = mDealer->allocate(maxSize);
     }
     std::vector<const BufferInfo> inputBuffers;
     for (const BufferAndId &elem : array) {
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 1b0db33..b78aa75 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -240,6 +240,24 @@
     return false;
 }
 
+bool AMessage::findAsInt64(const char *name, int64_t *value) const {
+    size_t i = findItemIndex(name, strlen(name));
+    if (i < mNumItems) {
+        const Item *item = &mItems[i];
+        switch (item->mType) {
+            case kTypeInt64:
+                *value = (float)item->u.int64Value;
+                return true;
+            case kTypeInt32:
+                *value = (float)item->u.int32Value;
+                return true;
+            default:
+                return false;
+        }
+    }
+    return false;
+}
+
 bool AMessage::contains(const char *name) const {
     size_t i = findItemIndex(name, strlen(name));
     return i < mNumItems;
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index 3548f96..9b2e7fa 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -50,5 +50,9 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
+        cfi: true,
+        diag: {
+          cfi: true,
+        },
     },
 }
diff --git a/media/libstagefright/include/ACodec.h b/media/libstagefright/include/ACodec.h
index 998716f..c57005d 100644
--- a/media/libstagefright/include/ACodec.h
+++ b/media/libstagefright/include/ACodec.h
@@ -304,6 +304,12 @@
 
     std::shared_ptr<ACodecBufferChannel> mBufferChannel;
 
+    enum {
+        kExtensionsUnchecked,
+        kExtensionsNone,
+        kExtensionsExist,
+    } mVendorExtensionsStatus;
+
     status_t setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode);
     status_t allocateBuffersOnPort(OMX_U32 portIndex);
     status_t freeBuffersOnPort(OMX_U32 portIndex);
@@ -549,6 +555,13 @@
     status_t requestIDRFrame();
     status_t setParameters(const sp<AMessage> &params);
 
+    // set vendor extension parameters specified in params that are supported by the codec
+    status_t setVendorParameters(const sp<AMessage> &params);
+
+    // get vendor extension parameters supported by the codec for a specific port and add it to
+    // |format|
+    status_t getVendorParameters(OMX_U32 portIndex, sp<AMessage> &format);
+
     // Send EOS on input stream.
     void onSignalEndOfInputStream();
 
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index b731666..02468c1 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -60,7 +60,7 @@
 
     ACodecBufferChannel(
             const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained);
-    virtual ~ACodecBufferChannel();
+    virtual ~ACodecBufferChannel() = default;
 
     // BufferChannelBase interface
     virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
@@ -127,8 +127,6 @@
     std::shared_ptr<const std::vector<const BufferInfo>> mInputBuffers;
     std::shared_ptr<const std::vector<const BufferInfo>> mOutputBuffers;
 
-    sp<MemoryDealer> makeMemoryDealer(size_t heapSize);
-
     bool hasCryptoOrDescrambler() {
         return mCrypto != NULL || mDescrambler != NULL;
     }
diff --git a/media/libstagefright/include/foundation/AMessage.h b/media/libstagefright/include/foundation/AMessage.h
index 782f8e6..8580eb5 100644
--- a/media/libstagefright/include/foundation/AMessage.h
+++ b/media/libstagefright/include/foundation/AMessage.h
@@ -123,6 +123,9 @@
     bool findBuffer(const char *name, sp<ABuffer> *buffer) const;
     bool findMessage(const char *name, sp<AMessage> *obj) const;
 
+    // finds signed integer types cast to int64_t
+    bool findAsInt64(const char *name, int64_t *value) const;
+
     // finds any numeric type cast to a float
     bool findAsFloat(const char *name, float *value) const;
 
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 793ecb8..dae1ee9 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -379,7 +379,7 @@
     // the action are overridden by the last action. For the other cases, traverse
     // the Queue to find the newest action that with timestamp smaller or equal to
     // the buffer's timestamp. For example, an action queue like
-    // [pause, 1s], [resume 2us], [pause 3us], [resume 4us], [pause 5us].... Upon
+    // [pause 1us], [resume 2us], [pause 3us], [resume 4us], [pause 5us].... Upon
     // receiving a buffer with timestamp 3.5us, only the action [pause, 3us] needs
     // to be handled and [pause, 1us], [resume 2us] will be discarded.
     bool dropped = false;
@@ -398,15 +398,14 @@
         }
 
         if (!done) {
+            // Find the newest action that with timestamp smaller than itemTimeUs. Then
+            // remove all the actions before and include the newest action.
             List<ActionItem>::iterator it = mActionQueue.begin();
-            while(it != mActionQueue.end()) {
+            while (it != mActionQueue.end() && it->mActionTimeUs <= itemTimeUs) {
                 nextAction = *it;
-                mActionQueue.erase(it);
-                if (nextAction.mActionTimeUs > itemTimeUs) {
-                    break;
-                }
                 ++it;
             }
+            mActionQueue.erase(mActionQueue.begin(), it);
 
             CHECK(itemTimeUs >= nextAction.mActionTimeUs);
             switch (nextAction.mAction) {
diff --git a/media/libstagefright/omx/OMXUtils.cpp b/media/libstagefright/omx/OMXUtils.cpp
index 38aad39..ee6d1d5 100644
--- a/media/libstagefright/omx/OMXUtils.cpp
+++ b/media/libstagefright/omx/OMXUtils.cpp
@@ -32,9 +32,13 @@
     switch (err) {
         case OMX_ErrorNone:
             return OK;
+        case OMX_ErrorNoMore:
+            return NOT_ENOUGH_DATA;
         case OMX_ErrorUnsupportedSetting:
         case OMX_ErrorUnsupportedIndex:
             return ERROR_UNSUPPORTED; // this is a media specific error
+        case OMX_ErrorBadParameter:
+            return BAD_VALUE;
         case OMX_ErrorInsufficientResources:
             return NO_MEMORY;
         case OMX_ErrorInvalidComponentName:
diff --git a/media/ndk/Android.mk b/media/ndk/Android.mk
index 67b0ab1..0984ca4 100644
--- a/media/ndk/Android.mk
+++ b/media/ndk/Android.mk
@@ -38,6 +38,8 @@
     frameworks/base/core/jni \
     frameworks/base/media/jni \
     frameworks/av/include/ndk \
+    frameworks/native/include \
+    frameworks/native/include/media/openmax \
     system/media/camera/include \
     $(call include-path-for, libhardware)/hardware \
 
@@ -56,10 +58,12 @@
     liblog \
     libutils \
     libcutils \
+    libandroid \
     libandroid_runtime \
     libbinder \
     libgui \
     libui \
+    libandroid \
 
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index 6c9a644..95fdf36 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -31,10 +31,10 @@
 
 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
 
-AImage::AImage(AImageReader* reader, int32_t format, uint64_t usage,
+AImage::AImage(AImageReader* reader, int32_t format, uint64_t usage0, uint64_t usage1,
         BufferItem* buffer, int64_t timestamp,
         int32_t width, int32_t height, int32_t numPlanes) :
-        mReader(reader), mFormat(format), mUsage(usage),
+        mReader(reader), mFormat(format), mUsage0(usage0), mUsage1(usage1),
         mBuffer(buffer), mLockedBuffer(nullptr), mTimestamp(timestamp),
         mWidth(width), mHeight(height), mNumPlanes(numPlanes) {
 }
@@ -54,7 +54,7 @@
 }
 
 void
-AImage::close() {
+AImage::close(int releaseFenceFd) {
     Mutex::Autolock _l(mLock);
     if (mIsClosed) {
         return;
@@ -64,7 +64,7 @@
         LOG_ALWAYS_FATAL("Error: AImage not closed before AImageReader close!");
         return;
     }
-    reader->releaseImageLocked(this);
+    reader->releaseImageLocked(this, releaseFenceFd);
     // Should have been set to nullptr in releaseImageLocked
     // Set to nullptr here for extra safety only
     mBuffer = nullptr;
@@ -178,9 +178,9 @@
         return AMEDIA_ERROR_INVALID_OBJECT;
     }
 
-    if ((mUsage & AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN) == 0) {
+    if ((mUsage0 & AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN) == 0) {
         ALOGE("%s: AImage %p does not have any software read usage bits set, usage=%" PRIu64 "",
-              __FUNCTION__, this, mUsage);
+              __FUNCTION__, this, mUsage0);
         return AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE;
     }
 
@@ -194,7 +194,7 @@
     uint64_t producerUsage;
     uint64_t consumerUsage;
     android_hardware_HardwareBuffer_convertToGrallocUsageBits(
-            &producerUsage, &consumerUsage, mUsage, 0);
+            &producerUsage, &consumerUsage, mUsage0, mUsage1);
 
     status_t ret =
             lockImageFromBuffer(mBuffer, consumerUsage, mBuffer->mFence->dup(), lockedBuffer.get());
@@ -600,12 +600,31 @@
     return AMEDIA_OK;
 }
 
+media_status_t
+AImage::getHardwareBuffer(/*out*/AHardwareBuffer** buffer) const {
+    if (mBuffer == nullptr || mBuffer->mGraphicBuffer == nullptr) {
+        ALOGE("%s: AImage %p has no buffer.", __FUNCTION__, this);
+        return AMEDIA_ERROR_INVALID_OBJECT;
+    }
+
+    // TODO(jwcai) Someone from Android graphics team stating this should just be a static_cast.
+    *buffer = reinterpret_cast<AHardwareBuffer*>(mBuffer->mGraphicBuffer.get());
+    return AMEDIA_OK;
+}
+
 EXPORT
 void AImage_delete(AImage* image) {
     ALOGV("%s", __FUNCTION__);
+    AImage_deleteAsync(image, -1);
+    return;
+}
+
+EXPORT
+void AImage_deleteAsync(AImage* image, int releaseFenceFd) {
+    ALOGV("%s", __FUNCTION__);
     if (image != nullptr) {
         image->lockReader();
-        image->close();
+        image->close(releaseFenceFd);
         image->unlockReader();
         if (!image->isClosed()) {
             LOG_ALWAYS_FATAL("Image close failed!");
@@ -750,3 +769,15 @@
     }
     return image->getPlaneData(planeIdx, data, dataLength);
 }
+
+EXPORT
+media_status_t AImage_getHardwareBuffer(
+    const AImage* image, /*out*/AHardwareBuffer** buffer) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (image == nullptr || buffer == nullptr) {
+        ALOGE("%s: bad argument. image %p buffer %p", __FUNCTION__, image, buffer);
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+    return image->getHardwareBuffer(buffer);
+}
diff --git a/media/ndk/NdkImagePriv.h b/media/ndk/NdkImagePriv.h
index e01dcc7..1fcb495 100644
--- a/media/ndk/NdkImagePriv.h
+++ b/media/ndk/NdkImagePriv.h
@@ -32,12 +32,13 @@
 
 // TODO: this only supports ImageReader
 struct AImage {
-    AImage(AImageReader* reader, int32_t format, uint64_t usage,
+    AImage(AImageReader* reader, int32_t format, uint64_t usage0, uint64_t usage1,
            BufferItem* buffer, int64_t timestamp,
            int32_t width, int32_t height, int32_t numPlanes);
 
     // free all resources while keeping object alive. Caller must obtain reader lock
-    void close();
+    void close() { close(-1); }
+    void close(int releaseFenceFd);
 
     // Remove from object memory. Must be called after close
     void free();
@@ -61,6 +62,7 @@
     media_status_t getPlanePixelStride(int planeIdx, /*out*/int32_t* pixelStride) const;
     media_status_t getPlaneRowStride(int planeIdx, /*out*/int32_t* rowStride) const;
     media_status_t getPlaneData(int planeIdx,/*out*/uint8_t** data, /*out*/int* dataLength) const;
+    media_status_t getHardwareBuffer(/*out*/AHardwareBuffer** buffer) const;
 
   private:
     // AImage should be deleted through free() API.
@@ -73,7 +75,8 @@
     // When reader is close, AImage will only accept close API call
     wp<AImageReader>           mReader;
     const int32_t              mFormat;
-    const uint64_t             mUsage;  // AHARDWAREBUFFER_USAGE0* flags.
+    const uint64_t             mUsage0;  // AHARDWAREBUFFER_USAGE0* flags.
+    const uint64_t             mUsage1;  // AHARDWAREBUFFER_USAGE1* flags.
     BufferItem*                mBuffer;
     std::unique_ptr<CpuConsumer::LockedBuffer> mLockedBuffer;
     const int64_t              mTimestamp;
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index e580dae..c0aee90 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -38,9 +38,9 @@
     }
 }
 
-const int32_t AImageReader::kDefaultUsage = AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN;
 const char* AImageReader::kCallbackFpKey = "Callback";
 const char* AImageReader::kContextKey    = "Context";
+const char* AImageReader::kGraphicBufferKey = "GraphicBuffer";
 
 bool
 AImageReader::isSupportedFormat(int32_t format) {
@@ -117,6 +117,45 @@
     return AMEDIA_OK;
 }
 
+void
+AImageReader::BufferRemovedListener::onBufferFreed(const wp<GraphicBuffer>& graphicBuffer) {
+    Mutex::Autolock _l(mLock);
+    sp<AImageReader> reader = mReader.promote();
+    if (reader == nullptr) {
+        ALOGW("A frame is available after AImageReader closed!");
+        return; // reader has been closed
+    }
+    if (mListener.onBufferRemoved == nullptr) {
+        return; // No callback registered
+    }
+
+    sp<GraphicBuffer> gBuffer = graphicBuffer.promote();
+    if (gBuffer == nullptr) {
+        ALOGW("A buffer being freed has gone away!");
+        return; // buffer is already destroyed
+    }
+
+    sp<AMessage> msg = new AMessage(AImageReader::kWhatBufferRemoved, reader->mHandler);
+    msg->setPointer(
+        AImageReader::kCallbackFpKey, (void*) mListener.onBufferRemoved);
+    msg->setPointer(AImageReader::kContextKey, mListener.context);
+    msg->setObject(AImageReader::kGraphicBufferKey, gBuffer);
+    msg->post();
+}
+
+media_status_t
+AImageReader::BufferRemovedListener::setBufferRemovedListener(
+    AImageReader_BufferRemovedListener* listener) {
+    Mutex::Autolock _l(mLock);
+    if (listener == nullptr) {
+        mListener.context = nullptr;
+        mListener.onBufferRemoved = nullptr;
+    } else {
+        mListener = *listener;
+    }
+    return AMEDIA_OK;
+}
+
 media_status_t
 AImageReader::setImageListenerLocked(AImageReader_ImageListener* listener) {
     return mFrameListener->setImageListener(listener);
@@ -128,9 +167,50 @@
     return setImageListenerLocked(listener);
 }
 
+media_status_t
+AImageReader::setBufferRemovedListenerLocked(AImageReader_BufferRemovedListener* listener) {
+    return mBufferRemovedListener->setBufferRemovedListener(listener);
+}
+
+media_status_t
+AImageReader::setBufferRemovedListener(AImageReader_BufferRemovedListener* listener) {
+    Mutex::Autolock _l(mLock);
+    return setBufferRemovedListenerLocked(listener);
+}
+
 void AImageReader::CallbackHandler::onMessageReceived(
         const sp<AMessage> &msg) {
     switch (msg->what()) {
+        case kWhatBufferRemoved:
+        {
+            AImageReader_BufferRemovedCallback onBufferRemoved;
+            void* context;
+            bool found = msg->findPointer(kCallbackFpKey, (void**) &onBufferRemoved);
+            if (!found || onBufferRemoved == nullptr) {
+                ALOGE("%s: Cannot find onBufferRemoved callback fp!", __FUNCTION__);
+                return;
+            }
+            found = msg->findPointer(kContextKey, &context);
+            if (!found) {
+                ALOGE("%s: Cannot find callback context!", __FUNCTION__);
+                return;
+            }
+            sp<RefBase> bufferToFree;
+            found = msg->findObject(kGraphicBufferKey, &bufferToFree);
+            if (!found || bufferToFree == nullptr) {
+                ALOGE("%s: Cannot find the buffer to free!", __FUNCTION__);
+                return;
+            }
+
+            // TODO(jwcai) Someone from Android graphics team stating this should just be a
+            // static_cast.
+            AHardwareBuffer* outBuffer = reinterpret_cast<AHardwareBuffer*>(bufferToFree.get());
+
+            // At this point, bufferToFree holds the last reference to the GraphicBuffer owned by
+            // this AImageReader, and the reference will be gone once this function returns.
+            (*onBufferRemoved)(context, mReader, outBuffer);
+            break;
+        }
         case kWhatImageAvailable:
         {
             AImageReader_ImageCallback onImageAvailable;
@@ -157,15 +237,18 @@
 AImageReader::AImageReader(int32_t width,
                            int32_t height,
                            int32_t format,
-                           uint64_t usage,
+                           uint64_t usage0,
+                           uint64_t usage1,
                            int32_t maxImages)
     : mWidth(width),
       mHeight(height),
       mFormat(format),
-      mUsage(usage),
+      mUsage0(usage0),
+      mUsage1(usage1),
       mMaxImages(maxImages),
       mNumPlanes(getNumPlanesForFormat(format)),
-      mFrameListener(new FrameListener(this)) {}
+      mFrameListener(new FrameListener(this)),
+      mBufferRemovedListener(new BufferRemovedListener(this)) {}
 
 media_status_t
 AImageReader::init() {
@@ -176,18 +259,19 @@
     uint64_t producerUsage;
     uint64_t consumerUsage;
     android_hardware_HardwareBuffer_convertToGrallocUsageBits(
-            &producerUsage, &consumerUsage, mUsage, 0);
+            &producerUsage, &consumerUsage, mUsage0, mUsage1);
+    mHalUsage = consumerUsage;
 
     sp<IGraphicBufferProducer> gbProducer;
     sp<IGraphicBufferConsumer> gbConsumer;
     BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
 
-    String8 consumerName = String8::format(
-            "ImageReader-%dx%df%xu%" PRIu64 "m%d-%d-%d", mWidth, mHeight, mFormat, mUsage,
-            mMaxImages, getpid(), createProcessUniqueId());
+    String8 consumerName = String8::format("ImageReader-%dx%df%xu%" PRIu64 "u%" PRIu64 "m%d-%d-%d",
+            mWidth, mHeight, mFormat, mUsage0, mUsage1, mMaxImages, getpid(),
+            createProcessUniqueId());
 
     mBufferItemConsumer =
-            new BufferItemConsumer(gbConsumer, consumerUsage, mMaxImages, /*controlledByApp*/ true);
+            new BufferItemConsumer(gbConsumer, mHalUsage, mMaxImages, /*controlledByApp*/ true);
     if (mBufferItemConsumer == nullptr) {
         ALOGE("Failed to allocate BufferItemConsumer");
         return AMEDIA_ERROR_UNKNOWN;
@@ -196,6 +280,7 @@
     mProducer = gbProducer;
     mBufferItemConsumer->setName(consumerName);
     mBufferItemConsumer->setFrameAvailableListener(mFrameListener);
+    mBufferItemConsumer->setBufferFreedListener(mBufferRemovedListener);
 
     status_t res;
     res = mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
@@ -247,6 +332,9 @@
     AImageReader_ImageListener nullListener = {nullptr, nullptr};
     setImageListenerLocked(&nullListener);
 
+    AImageReader_BufferRemovedListener nullBufferRemovedListener = {nullptr, nullptr};
+    setBufferRemovedListenerLocked(&nullBufferRemovedListener);
+
     if (mCbLooper != nullptr) {
         mCbLooper->unregisterHandler(mHandler->id());
         mCbLooper->stop();
@@ -274,7 +362,7 @@
 }
 
 media_status_t
-AImageReader::acquireImageLocked(/*out*/AImage** image) {
+AImageReader::acquireImageLocked(/*out*/AImage** image, /*out*/int* acquireFenceFd) {
     *image = nullptr;
     BufferItem* buffer = getBufferItemLocked();
     if (buffer == nullptr) {
@@ -283,7 +371,10 @@
         return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED;
     }
 
-    status_t res = mBufferItemConsumer->acquireBuffer(buffer, 0);
+    // When the output paramter fence is not NULL, we are acquiring the image asynchronously.
+    bool waitForFence = acquireFenceFd == nullptr;
+    status_t res = mBufferItemConsumer->acquireBuffer(buffer, 0, waitForFence);
+
     if (res != NO_ERROR) {
         returnBufferItemLocked(buffer);
         if (res != BufferQueue::NO_BUFFER_AVAILABLE) {
@@ -301,10 +392,12 @@
     const int bufferWidth = getBufferWidth(buffer);
     const int bufferHeight = getBufferHeight(buffer);
     const int bufferFmt = buffer->mGraphicBuffer->getPixelFormat();
+    const int bufferUsage = buffer->mGraphicBuffer->getUsage();
 
     const int readerWidth = mWidth;
     const int readerHeight = mHeight;
     const int readerFmt = mHalFormat;
+    const int readerUsage = mHalUsage;
 
     // Check if the producer buffer configurations match what AImageReader configured. Add some
     // extra checks for non-opaque formats.
@@ -324,6 +417,13 @@
                     __FUNCTION__, bufferWidth, bufferHeight, readerWidth, readerHeight);
         }
 
+        // Check if the buffer usage is a super set of reader's usage bits, aka all usage bits that
+        // ImageReader requested has been supported from the producer side.
+        ALOGD_IF((readerUsage | bufferUsage) != bufferUsage,
+                "%s: Producer buffer usage: %x, doesn't cover all usage bits AImageReader "
+                "configured: %x",
+                __FUNCTION__, bufferUsage, readerUsage);
+
         if (readerFmt != bufferFmt) {
             if (readerFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && isPossiblyYUV(bufferFmt)) {
                 // Special casing for when producer switches to a format compatible with flexible
@@ -345,13 +445,19 @@
     }
 
     if (mHalFormat == HAL_PIXEL_FORMAT_BLOB) {
-        *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp,
-                            readerWidth, readerHeight, mNumPlanes);
+        *image = new AImage(this, mFormat, mUsage0, mUsage1, buffer, buffer->mTimestamp,
+                readerWidth, readerHeight, mNumPlanes);
     } else {
-        *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp,
-                            bufferWidth, bufferHeight, mNumPlanes);
+        *image = new AImage(this, mFormat, mUsage0, mUsage1, buffer, buffer->mTimestamp,
+                bufferWidth, bufferHeight, mNumPlanes);
     }
     mAcquiredImages.push_back(*image);
+
+    // When the output paramter fence is not NULL, we are acquiring the image asynchronously.
+    if (acquireFenceFd != nullptr) {
+        *acquireFenceFd = buffer->mFence->dup();
+    }
+
     return AMEDIA_OK;
 }
 
@@ -373,7 +479,7 @@
 }
 
 void
-AImageReader::releaseImageLocked(AImage* image) {
+AImageReader::releaseImageLocked(AImage* image, int releaseFenceFd) {
     BufferItem* buffer = image->mBuffer;
     if (buffer == nullptr) {
         // This should not happen, but is not fatal
@@ -381,15 +487,17 @@
         return;
     }
 
-    int fenceFd = -1;
-    media_status_t ret = image->unlockImageIfLocked(&fenceFd);
+    int unlockFenceFd = -1;
+    media_status_t ret = image->unlockImageIfLocked(&unlockFenceFd);
     if (ret < 0) {
         ALOGW("%s: AImage %p is cannot be unlocked.", __FUNCTION__, image);
         return;
     }
 
-    sp<Fence> releaseFence = fenceFd > 0 ? new Fence(fenceFd) : Fence::NO_FENCE;
-    mBufferItemConsumer->releaseBuffer(*buffer, releaseFence);
+    sp<Fence> unlockFence = unlockFenceFd > 0 ? new Fence(unlockFenceFd) : Fence::NO_FENCE;
+    sp<Fence> releaseFence = releaseFenceFd > 0 ? new Fence(releaseFenceFd) : Fence::NO_FENCE;
+    sp<Fence> bufferFence = Fence::merge("AImageReader", unlockFence, releaseFence);
+    mBufferItemConsumer->releaseBuffer(*buffer, bufferFence);
     returnBufferItemLocked(buffer);
     image->mBuffer = nullptr;
 
@@ -433,13 +541,13 @@
 }
 
 media_status_t
-AImageReader::acquireNextImage(/*out*/AImage** image) {
+AImageReader::acquireNextImage(/*out*/AImage** image, /*out*/int* acquireFenceFd) {
     Mutex::Autolock _l(mLock);
-    return acquireImageLocked(image);
+    return acquireImageLocked(image, acquireFenceFd);
 }
 
 media_status_t
-AImageReader::acquireLatestImage(/*out*/AImage** image) {
+AImageReader::acquireLatestImage(/*out*/AImage** image, /*out*/int* acquireFenceFd) {
     if (image == nullptr) {
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
@@ -447,17 +555,26 @@
     *image = nullptr;
     AImage* prevImage = nullptr;
     AImage* nextImage = nullptr;
-    media_status_t ret = acquireImageLocked(&prevImage);
+    media_status_t ret = acquireImageLocked(&prevImage, acquireFenceFd);
     if (prevImage == nullptr) {
         return ret;
     }
     for (;;) {
-        ret = acquireImageLocked(&nextImage);
+        ret = acquireImageLocked(&nextImage, acquireFenceFd);
         if (nextImage == nullptr) {
             *image = prevImage;
             return AMEDIA_OK;
         }
-        prevImage->close();
+
+        if (acquireFenceFd == nullptr) {
+            // No need for release fence here since the prevImage is unused and acquireImageLocked
+            // has already waited for acquired fence to be signaled.
+            prevImage->close();
+        } else {
+            // Use the acquire fence as release fence, so that producer can wait before trying to
+            // refill the buffer.
+            prevImage->close(*acquireFenceFd);
+        }
         prevImage->free();
         prevImage = nextImage;
         nextImage = nullptr;
@@ -469,6 +586,15 @@
         int32_t width, int32_t height, int32_t format, int32_t maxImages,
         /*out*/AImageReader** reader) {
     ALOGV("%s", __FUNCTION__);
+    return AImageReader_newWithUsage(
+            width, height, format, AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN, 0, maxImages, reader);
+}
+
+EXPORT
+media_status_t AImageReader_newWithUsage(
+        int32_t width, int32_t height, int32_t format, uint64_t usage0, uint64_t usage1,
+        int32_t maxImages, /*out*/ AImageReader** reader) {
+    ALOGV("%s", __FUNCTION__);
 
     if (width < 1 || height < 1) {
         ALOGE("%s: image dimension must be positive: w:%d h:%d",
@@ -499,10 +625,8 @@
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
 
-    // Set consumer usage to AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN by default so that
-    // AImageReader_new behaves as if it's backed by CpuConsumer.
     AImageReader* tmpReader = new AImageReader(
-        width, height, format, AImageReader::kDefaultUsage, maxImages);
+        width, height, format, usage0, usage1, maxImages);
     if (tmpReader == nullptr) {
         ALOGE("%s: AImageReader allocation failed", __FUNCTION__);
         return AMEDIA_ERROR_UNKNOWN;
@@ -590,23 +714,37 @@
 EXPORT
 media_status_t AImageReader_acquireNextImage(AImageReader* reader, /*out*/AImage** image) {
     ALOGV("%s", __FUNCTION__);
-    if (reader == nullptr || image == nullptr) {
-        ALOGE("%s: invalid argument. reader %p, image %p",
-                __FUNCTION__, reader, image);
-        return AMEDIA_ERROR_INVALID_PARAMETER;
-    }
-    return reader->acquireNextImage(image);
+    return AImageReader_acquireNextImageAsync(reader, image, nullptr);
 }
 
 EXPORT
 media_status_t AImageReader_acquireLatestImage(AImageReader* reader, /*out*/AImage** image) {
     ALOGV("%s", __FUNCTION__);
+    return AImageReader_acquireLatestImageAsync(reader, image, nullptr);
+}
+
+EXPORT
+media_status_t AImageReader_acquireNextImageAsync(
+    AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd) {
+    ALOGV("%s", __FUNCTION__);
     if (reader == nullptr || image == nullptr) {
         ALOGE("%s: invalid argument. reader %p, image %p",
                 __FUNCTION__, reader, image);
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
-    return reader->acquireLatestImage(image);
+    return reader->acquireNextImage(image, acquireFenceFd);
+}
+
+EXPORT
+media_status_t AImageReader_acquireLatestImageAsync(
+    AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd) {
+    ALOGV("%s", __FUNCTION__);
+    if (reader == nullptr || image == nullptr) {
+        ALOGE("%s: invalid argument. reader %p, image %p",
+                __FUNCTION__, reader, image);
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+    return reader->acquireLatestImage(image, acquireFenceFd);
 }
 
 EXPORT
@@ -621,3 +759,16 @@
     reader->setImageListener(listener);
     return AMEDIA_OK;
 }
+
+EXPORT
+media_status_t AImageReader_setBufferRemovedListener(
+    AImageReader* reader, AImageReader_BufferRemovedListener* listener) {
+    ALOGV("%s", __FUNCTION__);
+    if (reader == nullptr) {
+        ALOGE("%s: invalid argument! reader %p", __FUNCTION__, reader);
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+
+    reader->setBufferRemovedListener(listener);
+    return AMEDIA_OK;
+}
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index 8becb1d..a233ec8 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -49,15 +49,14 @@
 
 struct AImageReader : public RefBase {
   public:
-    static const int32_t kDefaultUsage;
-
     static bool isSupportedFormat(int32_t format);
     static int getNumPlanesForFormat(int32_t format);
 
     AImageReader(int32_t width,
                  int32_t height,
                  int32_t format,
-                 uint64_t usage,
+                 uint64_t usage0,
+                 uint64_t usage1,
                  int32_t maxImages);
     ~AImageReader();
 
@@ -66,15 +65,15 @@
     media_status_t init();
 
     media_status_t setImageListener(AImageReader_ImageListener* listener);
+    media_status_t setBufferRemovedListener(AImageReader_BufferRemovedListener* listener);
 
-    media_status_t acquireNextImage(/*out*/AImage** image);
-    media_status_t acquireLatestImage(/*out*/AImage** image);
+    media_status_t acquireNextImage(/*out*/AImage** image, /*out*/int* fenceFd);
+    media_status_t acquireLatestImage(/*out*/AImage** image, /*out*/int* fenceFd);
 
     ANativeWindow* getWindow()    const { return mWindow.get(); };
     int32_t        getWidth()     const { return mWidth; };
     int32_t        getHeight()    const { return mHeight; };
     int32_t        getFormat()    const { return mFormat; };
-    uint64_t       getUsage()     const { return mUsage; };
     int32_t        getMaxImages() const { return mMaxImages; };
 
   private:
@@ -85,22 +84,25 @@
     void returnBufferItemLocked(BufferItem* buffer);
 
     // Called by AImageReader_acquireXXX to acquire a Buffer and setup AImage.
-    media_status_t acquireImageLocked(/*out*/AImage** image);
+    media_status_t acquireImageLocked(/*out*/AImage** image, /*out*/int* fenceFd);
 
     // Called by AImage to close image
-    void releaseImageLocked(AImage* image);
+    void releaseImageLocked(AImage* image, int releaseFenceFd);
 
     static int getBufferWidth(BufferItem* buffer);
     static int getBufferHeight(BufferItem* buffer);
 
     media_status_t setImageListenerLocked(AImageReader_ImageListener* listener);
+    media_status_t setBufferRemovedListenerLocked(AImageReader_BufferRemovedListener* listener);
 
     // definition of handler and message
     enum {
-        kWhatImageAvailable
+        kWhatBufferRemoved,
+        kWhatImageAvailable,
     };
     static const char* kCallbackFpKey;
     static const char* kContextKey;
+    static const char* kGraphicBufferKey;
     class CallbackHandler : public AHandler {
       public:
         CallbackHandler(AImageReader* reader) : mReader(reader) {}
@@ -115,7 +117,8 @@
     const int32_t mWidth;
     const int32_t mHeight;
     const int32_t mFormat;
-    const uint64_t mUsage;
+    const uint64_t mUsage0;  // AHARDWAREBUFFER_USAGE0* flags.
+    const uint64_t mUsage1;  // AHARDWAREBUFFER_USAGE1* flags.
     const int32_t mMaxImages;
 
     // TODO(jwcai) Seems completely unused in AImageReader class.
@@ -136,8 +139,24 @@
     };
     sp<FrameListener> mFrameListener;
 
+    struct BufferRemovedListener : public BufferItemConsumer::BufferFreedListener {
+      public:
+        explicit BufferRemovedListener(AImageReader* parent) : mReader(parent) {}
+
+        void onBufferFreed(const wp<GraphicBuffer>& graphicBuffer) override;
+
+        media_status_t setBufferRemovedListener(AImageReader_BufferRemovedListener* listener);
+
+       private:
+        AImageReader_BufferRemovedListener mListener = {nullptr, nullptr};
+        wp<AImageReader>           mReader;
+        Mutex                      mLock;
+    };
+    sp<BufferRemovedListener> mBufferRemovedListener;
+
     int mHalFormat;
     android_dataspace mHalDataSpace;
+    uint64_t mHalUsage;
 
     sp<IGraphicBufferProducer> mProducer;
     sp<Surface>                mSurface;
diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp
index 22c90e2..6d02cf1 100644
--- a/media/ndk/NdkMediaCodec.cpp
+++ b/media/ndk/NdkMediaCodec.cpp
@@ -31,9 +31,11 @@
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
 
+#include <media/stagefright/PersistentSurface.h>
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/MediaCodecBuffer.h>
+#include <android/native_window.h>
 
 using namespace android;
 
@@ -54,6 +56,18 @@
     kWhatStopActivityNotifications,
 };
 
+struct AMediaCodecPersistentSurface : public Surface {
+    sp<PersistentSurface> mPersistentSurface;
+    AMediaCodecPersistentSurface(
+            const sp<IGraphicBufferProducer>& igbp,
+            const sp<PersistentSurface>& ps)
+            : Surface(igbp) {
+        mPersistentSurface = ps;
+    }
+    virtual ~AMediaCodecPersistentSurface() {
+        //mPersistentSurface ref will be let go off here
+    }
+};
 
 class CodecHandler: public AHandler {
 private:
@@ -377,6 +391,94 @@
     return translate_error(mData->mCodec->setSurface(surface));
 }
 
+EXPORT
+media_status_t AMediaCodec_createInputSurface(AMediaCodec *mData, ANativeWindow **surface) {
+    if (surface == NULL || mData == NULL) {
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+    *surface = NULL;
+
+    sp<IGraphicBufferProducer> igbp = NULL;
+    status_t err = mData->mCodec->createInputSurface(&igbp);
+    if (err != NO_ERROR) {
+        return translate_error(err);
+    }
+
+    *surface = new Surface(igbp);
+    ANativeWindow_acquire(*surface);
+    return AMEDIA_OK;
+}
+
+EXPORT
+media_status_t AMediaCodec_createPersistentInputSurface(ANativeWindow **surface) {
+    if (surface == NULL) {
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+    *surface = NULL;
+
+    sp<PersistentSurface> ps = MediaCodec::CreatePersistentInputSurface();
+    if (ps == NULL) {
+        return AMEDIA_ERROR_UNKNOWN;
+    }
+
+    sp<IGraphicBufferProducer> igbp = ps->getBufferProducer();
+    if (igbp == NULL) {
+        return AMEDIA_ERROR_UNKNOWN;
+    }
+
+    *surface = new AMediaCodecPersistentSurface(igbp, ps);
+    ANativeWindow_acquire(*surface);
+
+    return AMEDIA_OK;
+}
+
+EXPORT
+media_status_t AMediaCodec_setInputSurface(
+        AMediaCodec *mData, ANativeWindow *surface) {
+
+    if (surface == NULL || mData == NULL) {
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+
+    AMediaCodecPersistentSurface *aMediaPersistentSurface =
+            static_cast<AMediaCodecPersistentSurface *>(surface);
+    if (aMediaPersistentSurface->mPersistentSurface == NULL) {
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+
+    return translate_error(mData->mCodec->setInputSurface(
+            aMediaPersistentSurface->mPersistentSurface));
+}
+
+EXPORT
+media_status_t AMediaCodec_setParameters(
+        AMediaCodec *mData, const AMediaFormat* params) {
+    if (params == NULL || mData == NULL) {
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+    sp<AMessage> nativeParams;
+    AMediaFormat_getFormat(params, &nativeParams);
+    ALOGV("setParameters: %s", nativeParams->debugString(0).c_str());
+
+    return translate_error(mData->mCodec->setParameters(nativeParams));
+}
+
+EXPORT
+media_status_t AMediaCodec_signalEndOfInputStream(AMediaCodec *mData) {
+
+    if (mData == NULL) {
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+
+    status_t err = mData->mCodec->signalEndOfInputStream();
+    if (err == INVALID_OPERATION) {
+        return AMEDIA_ERROR_INVALID_OPERATION;
+    }
+
+    return translate_error(err);
+
+}
+
 //EXPORT
 media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback,
         void *userdata) {
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 7db4d06..d7ad370 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -1,7 +1,9 @@
 LIBMEDIANDK {
   global:
     AImageReader_acquireLatestImage; # introduced=24
+    AImageReader_acquireLatestImageAsync; # introduced=26
     AImageReader_acquireNextImage; # introduced=24
+    AImageReader_acquireNextImageAsync; # introduced=26
     AImageReader_delete; # introduced=24
     AImageReader_getFormat; # introduced=24
     AImageReader_getHeight; # introduced=24
@@ -9,10 +11,14 @@
     AImageReader_getWidth; # introduced=24
     AImageReader_getWindow; # introduced=24
     AImageReader_new; # introduced=24
+    AImageReader_newWithUsage; # introduced=26
+    AImageReader_setBufferRemovedListener; # introduced=26
     AImageReader_setImageListener; # introduced=24
     AImage_delete; # introduced=24
+    AImage_deleteAsync; # introduced=26
     AImage_getCropRect; # introduced=24
     AImage_getFormat; # introduced=24
+    AImage_getHardwareBuffer; # introduced=26
     AImage_getHeight; # introduced=24
     AImage_getNumberOfPlanes; # introduced=24
     AImage_getPlaneData; # introduced=24
@@ -69,6 +75,11 @@
     AMediaCodec_releaseOutputBuffer;
     AMediaCodec_releaseOutputBufferAtTime;
     AMediaCodec_setOutputSurface; # introduced=24
+    AMediaCodec_setParameters; # introduced=26
+    AMediaCodec_setInputSurface; # introduced=26
+    AMediaCodec_createInputSurface; # introduced=26
+    AMediaCodec_signalEndOfInputStream; # introduced=26
+    AMediaCodec_createPersistentInputSurface; # introduced=26
     AMediaCodec_start;
     AMediaCodec_stop;
     AMediaCrypto_delete;
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
index d091179..1239fe0 100644
--- a/services/audiopolicy/common/include/Volume.h
+++ b/services/audiopolicy/common/include/Volume.h
@@ -124,16 +124,16 @@
         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+        case AUDIO_DEVICE_OUT_USB_HEADSET:
             return DEVICE_CATEGORY_HEADSET;
         case AUDIO_DEVICE_OUT_LINE:
         case AUDIO_DEVICE_OUT_AUX_DIGITAL:
-            /*USB?  Remote submix?*/
+        case AUDIO_DEVICE_OUT_USB_DEVICE:
             return DEVICE_CATEGORY_EXT_MEDIA;
         case AUDIO_DEVICE_OUT_SPEAKER:
         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
         case AUDIO_DEVICE_OUT_USB_ACCESSORY:
-        case AUDIO_DEVICE_OUT_USB_DEVICE:
         case AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
         default:
             return DEVICE_CATEGORY_SPEAKER;
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 4ab7604..096ffd1 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -356,6 +356,8 @@
             if (device) break;
             device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
             if (device) break;
+            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
+            if (device) break;
             device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
             if (device) break;
             if (!isInCall()) {
@@ -509,6 +511,9 @@
             device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
         }
         if (device2 == AUDIO_DEVICE_NONE) {
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
+        }
+        if (device2 == AUDIO_DEVICE_NONE) {
             device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
         }
         if (device2 == AUDIO_DEVICE_NONE) {
@@ -591,6 +596,8 @@
         device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
     } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
         device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
+        device = AUDIO_DEVICE_IN_USB_HEADSET;
     } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
         device = AUDIO_DEVICE_IN_USB_DEVICE;
     } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
@@ -621,6 +628,8 @@
         default:    // FORCE_NONE
             if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
                 device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
+                device = AUDIO_DEVICE_IN_USB_HEADSET;
             } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
                 device = AUDIO_DEVICE_IN_USB_DEVICE;
             } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
@@ -646,6 +655,8 @@
             device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
             device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
+            device = AUDIO_DEVICE_IN_USB_HEADSET;
         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
             device = AUDIO_DEVICE_IN_USB_DEVICE;
         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 7634664..ce6354d 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -5160,7 +5160,8 @@
     if ((device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
             AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
             AUDIO_DEVICE_OUT_WIRED_HEADSET |
-            AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) &&
+            AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
+            AUDIO_DEVICE_OUT_USB_HEADSET)) &&
         ((stream_strategy == STRATEGY_SONIFICATION)
                 || (stream_strategy == STRATEGY_SONIFICATION_RESPECTFUL)
                 || (stream == AUDIO_STREAM_SYSTEM)
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 4428f75..a77a90b7 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -867,23 +867,22 @@
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
-    if (dataSpace != streamInfo.dataSpace) {
-        String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
-                 mCameraIdStr.string(), dataSpace, streamInfo.dataSpace);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
-    }
-    //At the native side, there isn't a way to check whether 2 surfaces come from the same
-    //surface class type. Use usage flag to approximate the comparison. Treat
-    //different preview surface usage flags as the same.
-    int32_t previewUsageMask =
-            GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_HW_COMPOSER;
-    if ((consumerUsage & ~previewUsageMask) != (streamInfo.consumerUsage & ~previewUsageMask)) {
-        String8 msg = String8::format(
-                "Camera %s:Surface usage flag doesn't match 0x%x vs 0x%x",
-                mCameraIdStr.string(), consumerUsage, streamInfo.consumerUsage);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+        if (dataSpace != streamInfo.dataSpace) {
+            String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
+                    mCameraIdStr.string(), dataSpace, streamInfo.dataSpace);
+            ALOGE("%s: %s", __FUNCTION__, msg.string());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        }
+        //At the native side, there isn't a way to check whether 2 surfaces come from the same
+        //surface class type. Use usage flag to approximate the comparison.
+        if (consumerUsage != streamInfo.consumerUsage) {
+            String8 msg = String8::format(
+                    "Camera %s:Surface usage flag doesn't match 0x%x vs 0x%x",
+                    mCameraIdStr.string(), consumerUsage, streamInfo.consumerUsage);
+            ALOGE("%s: %s", __FUNCTION__, msg.string());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        }
     }
     return binder::Status::ok();
 }
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index bf6af86..869e93a 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -461,9 +461,9 @@
     } else if (res == NO_MEMORY) {
         SP_LOGV("%s: No free buffers", __FUNCTION__);
         return;
-    } else {
-        LOG_ALWAYS_FATAL_IF(res != NO_ERROR,
-                "detaching buffer from output failed (%d)", res);
+    } else if (res != OK) {
+        SP_LOGE("%s: detaching buffer from output failed (%d)", __FUNCTION__, res);
+        return;
     }
 
     BufferTracker& tracker = *(mBuffers[buffer->getId()]);
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index 5cb7f92..8eb4aa0 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -41,9 +41,11 @@
     $(TOP)/frameworks/av/media/libstagefright \
     $(TOP)/frameworks/av/media/libstagefright/include \
     $(TOP)/frameworks/native/include/media/openmax
-LOCAL_MODULE := mediacodec
+LOCAL_MODULE := android.hardware.media.omx@1.0-service
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_PROPRIETARY_MODULE := true
 LOCAL_32_BIT_ONLY := true
-LOCAL_INIT_RC := mediacodec.rc
+LOCAL_INIT_RC := android.hardware.media.omx@1.0-service.rc
 include $(BUILD_EXECUTABLE)
 
 # service seccomp policy
diff --git a/services/mediacodec/mediacodec.rc b/services/mediacodec/android.hardware.media.omx@1.0-service.rc
similarity index 63%
rename from services/mediacodec/mediacodec.rc
rename to services/mediacodec/android.hardware.media.omx@1.0-service.rc
index d78e0a4..ec51d65 100644
--- a/services/mediacodec/mediacodec.rc
+++ b/services/mediacodec/android.hardware.media.omx@1.0-service.rc
@@ -1,4 +1,4 @@
-service mediacodec /system/bin/mediacodec
+service mediacodec /vendor/bin/hw/android.hardware.media.omx@1.0-service
     class main
     user mediacodec
     group camera drmrpc mediadrm
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
index 19016cd..2ce6cf8 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
@@ -51,3 +51,7 @@
 getdents64: 1
 pipe2: 1
 ppoll: 1
+
+# Required by AddressSanitizer
+gettid: 1
+sched_yield: 1