IOMX: add API for setPortMode

- Add setPortMode to centralize port mode configuration

- Remove storeMetaDataInBuffers and enableNativeBuffers. These are
  no longer exposed to the client. Metadata mode and native/secure
  buffer mode will be enabled by OMX as needed by the port mode.

- Move handling of legacy adpative experiment (legacy metadata mode)
  to OMX side. Legacy mode will now appear the same as non-metadata
  mode to client.

bug: 31399200

Change-Id: Iaf33bd7c30fab4acbc19e9fb8c19e322f9b4a0a0
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 839945c..ec1d4b6 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -52,6 +52,20 @@
         kFenceTimeoutMs = 1000
     };
 
+    enum PortMode {
+        kPortModePresetStart = 0,
+        kPortModePresetByteBuffer,
+        kPortModePresetANWBuffer,
+        kPortModePresetSecureBuffer,
+        kPortModePresetEnd,
+
+        kPortModeDynamicStart = 100,
+        kPortModeDynamicANWBuffer,      // uses metadata mode kMetadataBufferTypeANWBuffer
+                                        // or kMetadataBufferTypeGrallocSource
+        kPortModeDynamicNativeHandle,   // uses metadata mode kMetadataBufferTypeNativeHandleSource
+        kPortModeDynamicEnd,
+    };
+
     struct ComponentInfo {
         String8 mName;
         List<String8> mRoles;
@@ -90,10 +104,8 @@
     virtual status_t setConfig(
             OMX_INDEXTYPE index, const void *params, size_t size) = 0;
 
-    // This will set *type to previous metadata buffer type on OMX error (not on binder error), and
-    // new metadata buffer type on success.
-    virtual status_t storeMetaDataInBuffers(
-            OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type = NULL) = 0;
+    virtual status_t setPortMode(
+            OMX_U32 port_index, IOMX::PortMode mode) = 0;
 
     virtual status_t prepareForAdaptivePlayback(
             OMX_U32 portIndex, OMX_BOOL enable,
@@ -103,9 +115,6 @@
             OMX_U32 portIndex, OMX_BOOL tunneled,
             OMX_U32 audioHwSync, native_handle_t **sidebandHandle) = 0;
 
-    virtual status_t enableNativeBuffers(
-            OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) = 0;
-
     virtual status_t getGraphicBufferUsage(
             OMX_U32 port_index, OMX_U32* usage) = 0;
 
@@ -241,23 +250,6 @@
             uint32_t flags = 0);
 };
 
-struct CodecProfileLevel {
-    OMX_U32 mProfile;
-    OMX_U32 mLevel;
-};
-
-inline static const char *asString(MetadataBufferType i, const char *def = "??") {
-    using namespace android;
-    switch (i) {
-        case kMetadataBufferTypeCameraSource:   return "CameraSource";
-        case kMetadataBufferTypeGrallocSource:  return "GrallocSource";
-        case kMetadataBufferTypeANWBuffer:      return "ANWBuffer";
-        case kMetadataBufferTypeNativeHandleSource: return "NativeHandleSource";
-        case kMetadataBufferTypeInvalid:        return "Invalid";
-        default:                                return def;
-    }
-}
-
 }  // namespace android
 
 #endif  // ANDROID_IOMX_H_
diff --git a/include/media/OMXBuffer.h b/include/media/OMXBuffer.h
index 0322b73..89b709c 100644
--- a/include/media/OMXBuffer.h
+++ b/include/media/OMXBuffer.h
@@ -44,7 +44,7 @@
     OMXBuffer(const sp<MediaCodecBuffer> &codecBuffer);
 
     // Constructs a buffer of type kBufferTypeSharedMem.
-    OMXBuffer(const sp<IMemory> &mem, size_t allottedSize = 0);
+    OMXBuffer(const sp<IMemory> &mem);
 
     // Constructs a buffer of type kBufferTypeANWBuffer.
     OMXBuffer(const sp<GraphicBuffer> &gbuf);
@@ -78,7 +78,6 @@
 
     // kBufferTypeSharedMem
     sp<IMemory> mMem;
-    OMX_U32 mAllottedSize;
 
     // kBufferTypeANWBuffer
     sp<GraphicBuffer> mGraphicBuffer;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 13ceeb6..8fc2809 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -277,9 +277,7 @@
     bool mChannelMaskPresent;
     int32_t mChannelMask;
     unsigned mDequeueCounter;
-    MetadataBufferType mInputMetadataType;
-    MetadataBufferType mOutputMetadataType;
-    bool mLegacyAdaptiveExperiment;
+    IOMX::PortMode mPortMode[2];
     int32_t mMetadataBuffersToSubmit;
     size_t mNumUndequeuedBuffers;
     sp<DataConverter> mConverter[2];
@@ -303,6 +301,7 @@
     status_t freeBuffer(OMX_U32 portIndex, size_t i);
 
     status_t handleSetSurface(const sp<Surface> &surface);
+    status_t setPortMode(int32_t portIndex, IOMX::PortMode mode);
     status_t setupNativeWindowSizeFormatAndUsage(
             ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */,
             bool reconnect);
@@ -319,11 +318,11 @@
     BufferInfo *dequeueBufferFromNativeWindow();
 
     inline bool storingMetadataInDecodedBuffers() {
-        return mOutputMetadataType >= 0 && !mIsEncoder;
+        return (mPortMode[kPortIndexOutput] == IOMX::kPortModeDynamicANWBuffer) && !mIsEncoder;
     }
 
-    inline bool usingMetadataOnEncoderOutput() {
-        return mOutputMetadataType >= 0 && mIsEncoder;
+    inline bool usingSecureBufferOnEncoderOutput() {
+        return (mPortMode[kPortIndexOutput] == IOMX::kPortModePresetSecureBuffer) && mIsEncoder;
     }
 
     BufferInfo *findBufferByID(
@@ -494,8 +493,6 @@
 
     status_t setupErrorCorrectionParameters();
 
-    status_t initNativeWindow();
-
     // Returns true iff all buffers on the given port have status
     // OWNED_BY_US or OWNED_BY_NATIVE_WINDOW.
     bool allYourBuffersAreBelongToUs(OMX_U32 portIndex);
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 1a6d6b8..c1fe87f 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -37,19 +37,18 @@
     CONNECT = IBinder::FIRST_CALL_TRANSACTION,
     LIST_NODES,
     ALLOCATE_NODE,
+    CREATE_INPUT_SURFACE,
     FREE_NODE,
     SEND_COMMAND,
     GET_PARAMETER,
     SET_PARAMETER,
     GET_CONFIG,
     SET_CONFIG,
-    ENABLE_NATIVE_BUFFERS,
-    USE_BUFFER,
-    CREATE_INPUT_SURFACE,
+    SET_PORT_MODE,
     SET_INPUT_SURFACE,
-    STORE_META_DATA_IN_BUFFERS,
     PREPARE_FOR_ADAPTIVE_PLAYBACK,
     ALLOC_SECURE_BUFFER,
+    USE_BUFFER,
     FREE_BUFFER,
     FILL_BUFFER,
     EMPTY_BUFFER,
@@ -225,17 +224,15 @@
         return reply.readInt32();
     }
 
-    virtual status_t enableNativeBuffers(
-            OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
+    virtual status_t setPortMode(
+            OMX_U32 port_index, IOMX::PortMode mode) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeInt32(port_index);
-        data.writeInt32((uint32_t)graphic);
-        data.writeInt32((uint32_t)enable);
-        remote()->transact(ENABLE_NATIVE_BUFFERS, data, &reply);
+        data.writeInt32(mode);
+        remote()->transact(SET_PORT_MODE, data, &reply);
 
-        status_t err = reply.readInt32();
-        return err;
+        return reply.readInt32();
     }
 
     virtual status_t getGraphicBufferUsage(
@@ -294,25 +291,6 @@
         return err;
     }
 
-    virtual status_t storeMetaDataInBuffers(
-            OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
-        data.writeInt32(port_index);
-        data.writeInt32((int32_t)enable);
-        data.writeInt32(type == NULL ? kMetadataBufferTypeANWBuffer : *type);
-
-        remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
-
-        // read type even storeMetaDataInBuffers failed
-        int negotiatedType = reply.readInt32();
-        if (type != NULL) {
-            *type = (MetadataBufferType)negotiatedType;
-        }
-
-        return reply.readInt32();
-    }
-
     virtual status_t prepareForAdaptivePlayback(
             OMX_U32 port_index, OMX_BOOL enable,
             OMX_U32 max_width, OMX_U32 max_height) {
@@ -670,16 +648,12 @@
             return NO_ERROR;
         }
 
-        case ENABLE_NATIVE_BUFFERS:
+        case SET_PORT_MODE:
         {
             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
-
             OMX_U32 port_index = data.readInt32();
-            OMX_BOOL graphic = (OMX_BOOL)data.readInt32();
-            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
-
-            status_t err = enableNativeBuffers(port_index, graphic, enable);
-            reply->writeInt32(err);
+            IOMX::PortMode mode = (IOMX::PortMode) data.readInt32();
+            reply->writeInt32(setPortMode(port_index, mode));
 
             return NO_ERROR;
         }
@@ -734,22 +708,6 @@
             return NO_ERROR;
         }
 
-        case STORE_META_DATA_IN_BUFFERS:
-        {
-            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
-
-            OMX_U32 port_index = data.readInt32();
-            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
-
-            MetadataBufferType type = (MetadataBufferType)data.readInt32();
-            status_t err = storeMetaDataInBuffers(port_index, enable, &type);
-
-            reply->writeInt32(type);
-            reply->writeInt32(err);
-
-            return NO_ERROR;
-        }
-
         case PREPARE_FOR_ADAPTIVE_PLAYBACK:
         {
             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
diff --git a/media/libmedia/OMXBuffer.cpp b/media/libmedia/OMXBuffer.cpp
index 0931872..2834853 100644
--- a/media/libmedia/OMXBuffer.cpp
+++ b/media/libmedia/OMXBuffer.cpp
@@ -38,10 +38,9 @@
       mRangeLength(codecBuffer != NULL ? codecBuffer->size() : 0) {
 }
 
-OMXBuffer::OMXBuffer(const sp<IMemory> &mem, size_t allottedSize)
+OMXBuffer::OMXBuffer(const sp<IMemory> &mem)
     : mBufferType(kBufferTypeSharedMem),
-      mMem(mem),
-      mAllottedSize(allottedSize ? : mem->size()) {
+      mMem(mem) {
 }
 
 OMXBuffer::OMXBuffer(const sp<GraphicBuffer> &gbuf)
@@ -68,11 +67,7 @@
 
         case kBufferTypeSharedMem:
         {
-            status_t err = parcel->writeStrongBinder(IInterface::asBinder(mMem));
-            if (err != NO_ERROR) {
-                return err;
-            }
-            return parcel->writeUint32(mAllottedSize);
+            return parcel->writeStrongBinder(IInterface::asBinder(mMem));
         }
 
         case kBufferTypeANWBuffer:
@@ -103,10 +98,7 @@
 
         case kBufferTypeSharedMem:
         {
-            sp<IMemory> params = interface_cast<IMemory>(parcel->readStrongBinder());
-
-            mMem = params;
-            mAllottedSize = parcel->readUint32();
+            mMem = interface_cast<IMemory>(parcel->readStrongBinder());
             break;
         }
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 094f5cc..69db709 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -526,9 +526,6 @@
       mChannelMaskPresent(false),
       mChannelMask(0),
       mDequeueCounter(0),
-      mInputMetadataType(kMetadataBufferTypeInvalid),
-      mOutputMetadataType(kMetadataBufferTypeInvalid),
-      mLegacyAdaptiveExperiment(false),
       mMetadataBuffersToSubmit(0),
       mNumUndequeuedBuffers(0),
       mRepeatFrameDelayUs(-1ll),
@@ -556,6 +553,9 @@
     mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
     mInputEOSResult = OK;
 
+    mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
+    mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
+
     memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
 
     changeState(mUninitializedState);
@@ -691,8 +691,7 @@
     int usageBits = 0;
     // no need to reconnect as we will not dequeue all buffers
     status_t err = setupNativeWindowSizeFormatAndUsage(
-            nativeWindow, &usageBits,
-            !storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment /* reconnect */);
+            nativeWindow, &usageBits, !storingMetadataInDecodedBuffers());
     if (err != OK) {
         return err;
     }
@@ -742,7 +741,6 @@
         const BufferInfo &info = buffers[i];
         // skip undequeued buffers for meta data mode
         if (storingMetadataInDecodedBuffers()
-                && !mLegacyAdaptiveExperiment
                 && info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
             ALOGV("skipping buffer");
             continue;
@@ -759,7 +757,7 @@
     }
 
     // cancel undequeued buffers to new surface
-    if (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment) {
+    if (!storingMetadataInDecodedBuffers()) {
         for (size_t i = 0; i < buffers.size(); ++i) {
             BufferInfo &info = buffers.editItemAt(i);
             if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
@@ -789,6 +787,21 @@
     return OK;
 }
 
+status_t ACodec::setPortMode(int32_t portIndex, IOMX::PortMode mode) {
+    status_t err = mOMXNode->setPortMode(portIndex, mode);
+    if (err != OK) {
+        ALOGE("[%s] setPortMode on %s to %s failed w/ err %d",
+                mComponentName.c_str(),
+                portIndex == kPortIndexInput ? "input" : "output",
+                asString(mode),
+                err);
+        return err;
+    }
+
+    mPortMode[portIndex] = mode;
+    return OK;
+}
+
 status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
 
@@ -797,7 +810,7 @@
 
     status_t err;
     if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
-        if (storingMetadataInDecodedBuffers() && !mLegacyAdaptiveExperiment) {
+        if (storingMetadataInDecodedBuffers()) {
             err = allocateOutputMetadataBuffers();
         } else {
             err = allocateOutputBuffersFromNativeWindow();
@@ -811,26 +824,17 @@
                 OMX_IndexParamPortDefinition, &def, sizeof(def));
 
         if (err == OK) {
-            MetadataBufferType type =
-                portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType;
+            const IOMX::PortMode &mode = mPortMode[portIndex];
             size_t bufSize = def.nBufferSize;
-            if (type == kMetadataBufferTypeANWBuffer) {
+            // Always allocate VideoNativeMetadata if using ANWBuffer.
+            // OMX might use gralloc source internally, but we don't share
+            // metadata buffer with OMX, OMX has its own headers.
+            if (mode == IOMX::kPortModeDynamicANWBuffer) {
                 bufSize = sizeof(VideoNativeMetadata);
-            } else if (type == kMetadataBufferTypeNativeHandleSource) {
+            } else if (mode == IOMX::kPortModeDynamicNativeHandle) {
                 bufSize = sizeof(VideoNativeHandleMetadata);
             }
 
-            // If using gralloc or native source input metadata buffers, allocate largest
-            // metadata size as we prefer to generate native source metadata, but component
-            // may require gralloc source. For camera source, allocate at least enough
-            // size for native metadata buffers.
-            size_t allottedSize = bufSize;
-            if (portIndex == kPortIndexInput && type == kMetadataBufferTypeANWBuffer) {
-                bufSize = max(sizeof(VideoGrallocMetadata), sizeof(VideoNativeMetadata));
-            } else if (portIndex == kPortIndexInput && type == kMetadataBufferTypeCameraSource) {
-                bufSize = max(bufSize, sizeof(VideoNativeMetadata));
-            }
-
             size_t conversionBufferSize = 0;
 
             sp<DataConverter> converter = mConverter[portIndex];
@@ -845,9 +849,9 @@
 
             size_t alignment = MemoryDealer::getAllocationAlignment();
 
-            ALOGV("[%s] Allocating %u buffers of size %zu/%zu (from %u using %s) on %s port",
+            ALOGV("[%s] Allocating %u buffers of size %zu (from %u using %s) on %s port",
                     mComponentName.c_str(),
-                    def.nBufferCountActual, bufSize, allottedSize, def.nBufferSize, asString(type),
+                    def.nBufferCountActual, bufSize, def.nBufferSize, asString(mode),
                     portIndex == kPortIndexInput ? "input" : "output");
 
             // verify buffer sizes to avoid overflow in align()
@@ -865,24 +869,21 @@
             }
 
             size_t totalSize = def.nBufferCountActual * (alignedSize + alignedConvSize);
-            mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
+            if (mode != IOMX::kPortModePresetSecureBuffer) {
+                mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
+            }
 
             const sp<AMessage> &format =
                     portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
             for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
-                sp<IMemory> mem = mDealer[portIndex]->allocate(bufSize);
-                if (mem == NULL || mem->pointer() == NULL) {
-                    return NO_MEMORY;
-                }
+                sp<IMemory> mem;
 
                 BufferInfo info;
                 info.mStatus = BufferInfo::OWNED_BY_US;
                 info.mFenceFd = -1;
                 info.mRenderInfo = NULL;
 
-                if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) {
-                    mem.clear();
-
+                if (mode == IOMX::kPortModePresetSecureBuffer) {
                     void *ptr = NULL;
                     sp<NativeHandle> native_handle;
                     err = mOMXNode->allocateSecureBuffer(
@@ -894,18 +895,20 @@
                             : new SecureBuffer(format, native_handle, bufSize);
                     info.mCodecData = info.mData;
                 } else {
-                    err = mOMXNode->useBuffer(portIndex,
-                            OMXBuffer(mem, allottedSize), &info.mBufferID);
-                }
+                    mem = mDealer[portIndex]->allocate(bufSize);
+                    if (mem == NULL || mem->pointer() == NULL) {
+                        return NO_MEMORY;
+                    }
 
-                if (mem != NULL) {
-                    info.mCodecData = new SharedMemoryBuffer(format, mem);
-                    info.mCodecRef = mem;
+                    err = mOMXNode->useBuffer(portIndex, mem, &info.mBufferID);
 
-                    if (type == kMetadataBufferTypeANWBuffer) {
+                    if (mode == IOMX::kPortModeDynamicANWBuffer) {
                         ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
                     }
 
+                    info.mCodecData = new SharedMemoryBuffer(format, mem);
+                    info.mCodecRef = mem;
+
                     // if we require conversion, allocate conversion buffer for client use;
                     // otherwise, reuse codec buffer
                     if (mConverter[portIndex] != NULL) {
@@ -1086,10 +1089,9 @@
 }
 
 status_t ACodec::allocateOutputBuffersFromNativeWindow() {
-    // This method only handles the non-metadata mode, or legacy metadata mode
-    // (where the headers for each buffer id will be fixed). Non-legacy metadata
-    // mode shouldn't go through this path.
-    CHECK(!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment);
+    // This method only handles the non-metadata mode (or simulating legacy
+    // mode with metadata, which is transparent to ACodec).
+    CHECK(!storingMetadataInDecodedBuffers());
 
     OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
     status_t err = configureOutputBuffersFromNativeWindow(
@@ -1126,10 +1128,8 @@
         // TODO: We shouln't need to create MediaCodecBuffer. In metadata mode
         //       OMX doesn't use the shared memory buffer, but some code still
         //       access info.mData. Create an ABuffer as a placeholder.
-        if (storingMetadataInDecodedBuffers()) {
-            info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
-            info.mCodecData = info.mData;
-        }
+        info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
+        info.mCodecData = info.mData;
 
         mBuffers[kPortIndexOutput].push(info);
 
@@ -1151,7 +1151,7 @@
     OMX_U32 cancelStart;
     OMX_U32 cancelEnd;
 
-    if (err != 0 || storingMetadataInDecodedBuffers()) {
+    if (err != OK) {
         // If an error occurred while dequeuing we need to cancel any buffers
         // that were dequeued. Also cancel all if we're in legacy metadata mode.
         cancelStart = 0;
@@ -1175,32 +1175,23 @@
     static_cast<Surface*>(mNativeWindow.get())
             ->getIGraphicBufferProducer()->allowAllocation(false);
 
-    if (storingMetadataInDecodedBuffers()) {
-        mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
-    }
-
     return err;
 }
 
 status_t ACodec::allocateOutputMetadataBuffers() {
-    CHECK(storingMetadataInDecodedBuffers() && !mLegacyAdaptiveExperiment);
+    CHECK(storingMetadataInDecodedBuffers());
 
     OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
     status_t err = configureOutputBuffersFromNativeWindow(
             &bufferCount, &bufferSize, &minUndequeuedBuffers,
             false /* preregister */);
-    if (err != 0)
+    if (err != OK)
         return err;
     mNumUndequeuedBuffers = minUndequeuedBuffers;
 
     ALOGV("[%s] Allocating %u meta buffers on output port",
          mComponentName.c_str(), bufferCount);
 
-    size_t bufSize = mOutputMetadataType == kMetadataBufferTypeANWBuffer ?
-            sizeof(struct VideoNativeMetadata) : sizeof(struct VideoGrallocMetadata);
-    size_t totalSize = bufferCount * align(bufSize, MemoryDealer::getAllocationAlignment());
-    mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec");
-
     for (OMX_U32 i = 0; i < bufferCount; i++) {
         BufferInfo info;
         info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
@@ -1209,23 +1200,14 @@
         info.mGraphicBuffer = NULL;
         info.mDequeuedAt = mDequeueCounter;
 
-        sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(bufSize);
-        if (mem == NULL || mem->pointer() == NULL) {
-            return NO_MEMORY;
-        }
-        if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
-            ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
-        }
-        info.mData = new SharedMemoryBuffer(mOutputFormat, mem);
-        info.mMemRef = mem;
+        info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
         info.mCodecData = info.mData;
-        info.mCodecRef = mem;
 
-        err = mOMXNode->useBuffer(kPortIndexOutput, mem, &info.mBufferID);
+        err = mOMXNode->useBuffer(kPortIndexOutput, OMXBuffer::sPreset, &info.mBufferID);
         mBuffers[kPortIndexOutput].push(info);
 
-        ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)",
-             mComponentName.c_str(), info.mBufferID, mem->pointer());
+        ALOGV("[%s] allocated meta buffer with ID %u",
+                mComponentName.c_str(), info.mBufferID);
     }
 
     mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
@@ -1401,7 +1383,7 @@
         // same is possible in meta mode, in which case, it will be treated
         // as a normal buffer, which is not desirable.
         // TODO: fix this.
-        if (!stale && (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment)) {
+        if (!stale && !storingMetadataInDecodedBuffers()) {
             ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf);
             stale = true;
         }
@@ -1432,12 +1414,6 @@
     // while loop above does not complete
     CHECK(storingMetadataInDecodedBuffers());
 
-    if (storingMetadataInDecodedBuffers() && mLegacyAdaptiveExperiment) {
-        // If we're here while running legacy experiment, we dequeued some
-        // unrecognized buffers, and the experiment can't continue.
-        ALOGE("Legacy experiment failed, drop back to metadata mode");
-        mLegacyAdaptiveExperiment = false;
-    }
     // discard buffer in LRU info and replace with new buffer
     oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
     oldest->mStatus = BufferInfo::OWNED_BY_US;
@@ -1445,23 +1421,10 @@
     mRenderTracker.untrackFrame(oldest->mRenderInfo);
     oldest->mRenderInfo = NULL;
 
-    if (mOutputMetadataType == kMetadataBufferTypeGrallocSource) {
-        VideoGrallocMetadata *grallocMeta =
-            reinterpret_cast<VideoGrallocMetadata *>(oldest->mCodecData->base());
-        ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
-                (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
-                mDequeueCounter - oldest->mDequeuedAt,
-                (void *)(uintptr_t)grallocMeta->pHandle,
-                oldest->mGraphicBuffer->handle, oldest->mCodecData->base());
-    } else if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
-        VideoNativeMetadata *nativeMeta =
-            reinterpret_cast<VideoNativeMetadata *>(oldest->mCodecData->base());
-        ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
-                (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
-                mDequeueCounter - oldest->mDequeuedAt,
-                (void *)(uintptr_t)nativeMeta->pBuffer,
-                oldest->mGraphicBuffer->getNativeBuffer(), oldest->mCodecData->base());
-    }
+    ALOGV("replaced oldest buffer #%u with age %u, graphicBuffer %p",
+            (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
+            mDequeueCounter - oldest->mDequeuedAt,
+            oldest->mGraphicBuffer->getNativeBuffer());
 
     updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest);
     return oldest;
@@ -1508,9 +1471,7 @@
     status_t err = OK;
 
     // there should not be any fences in the metadata
-    MetadataBufferType type =
-        portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType;
-    if (type == kMetadataBufferTypeANWBuffer && info->mCodecData != NULL
+    if (mPortMode[portIndex] == IOMX::kPortModeDynamicANWBuffer && info->mCodecData != NULL
             && info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
         int fenceFd = ((VideoNativeMetadata *)info->mCodecData->base())->nFenceFd;
         if (fenceFd >= 0) {
@@ -1569,7 +1530,7 @@
 
 status_t ACodec::fillBuffer(BufferInfo *info) {
     status_t err;
-    if (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment) {
+    if (!storingMetadataInDecodedBuffers()) {
         err = mOMXNode->fillBuffer(
             info->mBufferID, OMXBuffer::sPreset, info->mFenceFd);
     } else {
@@ -1611,8 +1572,8 @@
 
     mIsEncoder = encoder;
 
-    mInputMetadataType = kMetadataBufferTypeInvalid;
-    mOutputMetadataType = kMetadataBufferTypeInvalid;
+    mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
+    mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
 
     status_t err = setComponentRole(encoder /* isEncoder */, mime);
 
@@ -1639,18 +1600,18 @@
     if (encoder
             && msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
             && storeMeta != kMetadataBufferTypeInvalid) {
-        mInputMetadataType = (MetadataBufferType)storeMeta;
-        err = mOMXNode->storeMetaDataInBuffers(
-                kPortIndexInput, OMX_TRUE, &mInputMetadataType);
+        IOMX::PortMode mode;
+        if (storeMeta == kMetadataBufferTypeNativeHandleSource) {
+            mode = IOMX::kPortModeDynamicNativeHandle;
+        } else if (storeMeta == kMetadataBufferTypeANWBuffer ||
+                storeMeta == kMetadataBufferTypeGrallocSource) {
+            mode = IOMX::kPortModeDynamicANWBuffer;
+        } else {
+            return BAD_VALUE;
+        }
+        err = setPortMode(kPortIndexInput, mode);
         if (err != OK) {
-            ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
-                    mComponentName.c_str(), err);
-
             return err;
-        } else if (storeMeta == kMetadataBufferTypeANWBuffer
-                && mInputMetadataType == kMetadataBufferTypeGrallocSource) {
-            // IOMX translates ANWBuffers to gralloc source already.
-            mInputMetadataType = (MetadataBufferType)storeMeta;
         }
 
         uint32_t usageBits;
@@ -1695,12 +1656,14 @@
         OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
             && msg->findInt32("android._store-metadata-in-buffers-output", &storeMeta)
             && storeMeta != 0);
+        if (mFlags & kFlagIsSecure) {
+            enable = OMX_TRUE;
+        }
 
-        mOutputMetadataType = kMetadataBufferTypeNativeHandleSource;
-        err = mOMXNode->storeMetaDataInBuffers(kPortIndexOutput, enable, &mOutputMetadataType);
+        err = setPortMode(kPortIndexOutput, enable ?
+                IOMX::kPortModePresetSecureBuffer : IOMX::kPortModePresetByteBuffer);
         if (err != OK) {
-            ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
-                mComponentName.c_str(), err);
+            return err;
         }
 
         if (!msg->findInt64(
@@ -1737,7 +1700,6 @@
     bool haveNativeWindow = msg->findObject("native-window", &obj)
             && obj != NULL && video && !encoder;
     mUsingNativeWindow = haveNativeWindow;
-    mLegacyAdaptiveExperiment = false;
     if (video && !encoder) {
         inputFormat->setInt32("adaptive-playback", false);
 
@@ -1753,10 +1715,13 @@
 
         if (mFlags & kFlagIsSecure) {
             // use native_handles for secure input buffers
-            err = mOMXNode->enableNativeBuffers(
-                    kPortIndexInput, OMX_FALSE /* graphic */, OMX_TRUE);
-            ALOGI_IF(err != OK, "falling back to non-native_handles");
-            err = OK; // ignore error for now
+            err = setPortMode(kPortIndexInput, IOMX::kPortModePresetSecureBuffer);
+
+            if (err != OK) {
+                ALOGI("falling back to non-native_handles");
+                setPortMode(kPortIndexInput, IOMX::kPortModePresetByteBuffer);
+                err = OK; // ignore error for now
+            }
         }
     }
     if (haveNativeWindow) {
@@ -1828,14 +1793,8 @@
                 return err;
             }
 
-            // Always try to enable dynamic output buffers on native surface
-            mOutputMetadataType = kMetadataBufferTypeANWBuffer;
-            err = mOMXNode->storeMetaDataInBuffers(
-                    kPortIndexOutput, OMX_TRUE, &mOutputMetadataType);
+            err = setPortMode(kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer);
             if (err != OK) {
-                ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
-                        mComponentName.c_str(), err);
-
                 // if adaptive playback has been requested, try JB fallback
                 // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
                 // LARGE MEMORY REQUIREMENT
@@ -1877,15 +1836,15 @@
                         inputFormat->setInt32("adaptive-playback", true);
                     }
                 }
-                // allow failure
-                err = OK;
+                // Fall back to legacy mode (use fixed ANWBuffer)
+                err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer);
+                if (err != OK) {
+                    return err;
+                }
             } else {
-                ALOGV("[%s] storeMetaDataInBuffers succeeded",
-                        mComponentName.c_str());
+                ALOGV("[%s] setPortMode on output to %s succeeded",
+                        mComponentName.c_str(), asString(IOMX::kPortModeDynamicANWBuffer));
                 CHECK(storingMetadataInDecodedBuffers());
-                mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled(
-                        "legacy-adaptive", !msg->contains("no-experiments"));
-
                 inputFormat->setInt32("adaptive-playback", true);
             }
 
@@ -1930,13 +1889,6 @@
             mNativeWindow = static_cast<Surface *>(obj.get());
         }
 
-        // initialize native window now to get actual output format
-        // TODO: this is needed for some encoders even though they don't use native window
-        err = initNativeWindow();
-        if (err != OK) {
-            return err;
-        }
-
         // fallback for devices that do not handle flex-YUV for native buffers
         if (haveNativeWindow) {
             int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
@@ -1964,18 +1916,10 @@
                     mNativeWindowUsageBits = 0;
                     haveNativeWindow = false;
                     usingSwRenderer = true;
-                    if (storingMetadataInDecodedBuffers()) {
-                        err = mOMXNode->storeMetaDataInBuffers(
-                                kPortIndexOutput, OMX_FALSE, &mOutputMetadataType);
-                        mOutputMetadataType = kMetadataBufferTypeInvalid; // just in case
-                        // TODO: implement adaptive-playback support for bytebuffer mode.
-                        // This is done by SW codecs, but most HW codecs don't support it.
-                        inputFormat->setInt32("adaptive-playback", false);
-                    }
-                    if (err == OK) {
-                        err = mOMXNode->enableNativeBuffers(
-                                kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
-                    }
+                    // TODO: implement adaptive-playback support for bytebuffer mode.
+                    // This is done by SW codecs, but most HW codecs don't support it.
+                    err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
+                    inputFormat->setInt32("adaptive-playback", false);
                     if (mFlags & kFlagIsGrallocUsageProtected) {
                         // fallback is not supported for protected playback
                         err = PERMISSION_DENIED;
@@ -4525,15 +4469,6 @@
     return err;
 }
 
-status_t ACodec::initNativeWindow() {
-    if (mNativeWindow != NULL) {
-        return mOMXNode->enableNativeBuffers(kPortIndexOutput, OMX_TRUE /* graphic */, OMX_TRUE);
-    }
-
-    mOMXNode->enableNativeBuffers(kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
-    return OK;
-}
-
 size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
     size_t n = 0;
 
@@ -5634,7 +5569,6 @@
 
                 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
 
-                MetadataBufferType metaType = mCodec->mInputMetadataType;
                 int32_t isCSD = 0;
                 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
                     if (mCodec->mIsLegacyVP9Decoder) {
@@ -5644,7 +5578,6 @@
                         break;
                     }
                     flags |= OMX_BUFFERFLAG_CODECCONFIG;
-                    metaType = kMetadataBufferTypeInvalid;
                 }
 
                 if (eos) {
@@ -5710,15 +5643,17 @@
                 info->checkReadFence("onInputBufferFilled");
 
                 status_t err2 = OK;
-                switch (metaType) {
-                case kMetadataBufferTypeInvalid:
+                switch (mCodec->mPortMode[kPortIndexInput]) {
+                case IOMX::kPortModePresetByteBuffer:
+                case IOMX::kPortModePresetANWBuffer:
+                case IOMX::kPortModePresetSecureBuffer:
                     {
                         err2 = mCodec->mOMXNode->emptyBuffer(
                             bufferID, info->mCodecData, flags, timeUs, info->mFenceFd);
                     }
                     break;
 #ifndef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
-                case kMetadataBufferTypeNativeHandleSource:
+                case IOMX::kPortModeDynamicNativeHandle:
                     if (info->mCodecData->size() >= sizeof(VideoNativeHandleMetadata)) {
                         VideoNativeHandleMetadata *vnhmd =
                             (VideoNativeHandleMetadata*)info->mCodecData->base();
@@ -5728,7 +5663,7 @@
                             bufferID, handle, flags, timeUs, info->mFenceFd);
                     }
                     break;
-                case kMetadataBufferTypeANWBuffer:
+                case IOMX::kPortModeDynamicANWBuffer:
                     if (info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
                         VideoNativeMetadata *vnmd = (VideoNativeMetadata*)info->mCodecData->base();
                         sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
@@ -5740,7 +5675,8 @@
 #endif
                 default:
                     ALOGW("Can't marshall %s data in %zu sized buffers in %zu-bit mode",
-                            asString(metaType), info->mCodecData->size(),
+                            asString(mCodec->mPortMode[kPortIndexInput]),
+                            info->mCodecData->size(),
                             sizeof(buffer_handle_t) * 8);
                     err2 = ERROR_UNSUPPORTED;
                     break;
@@ -5927,17 +5863,15 @@
                 mCodec->addKeyFormatChangesToRenderBufferNotification(reply);
             }
 
-            if (mCodec->usingMetadataOnEncoderOutput()) {
+            if (mCodec->usingSecureBufferOnEncoderOutput()) {
                 native_handle_t *handle = NULL;
-                VideoNativeHandleMetadata &nativeMeta =
-                    *(VideoNativeHandleMetadata *)buffer->data();
-                if (buffer->size() >= sizeof(nativeMeta)
-                        && nativeMeta.eType == kMetadataBufferTypeNativeHandleSource) {
+                sp<SecureBuffer> secureBuffer = static_cast<SecureBuffer *>(buffer.get());
+                if (secureBuffer != NULL) {
 #ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
                     // handle is only valid on 32-bit/mediaserver process
                     handle = NULL;
 #else
-                    handle = (native_handle_t *)nativeMeta.pHandle;
+                    handle = (native_handle_t *)secureBuffer->getDestinationPointer();
 #endif
                 }
                 buffer->meta()->setPointer("handle", handle);
@@ -6176,8 +6110,8 @@
     mCodec->mOMX.clear();
     mCodec->mOMXNode.clear();
     mCodec->mFlags = 0;
-    mCodec->mInputMetadataType = kMetadataBufferTypeInvalid;
-    mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid;
+    mCodec->mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
+    mCodec->mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
     mCodec->mConverter[0].clear();
     mCodec->mConverter[1].clear();
     mCodec->mComponentName.clear();
@@ -6637,8 +6571,6 @@
     }
 
     if (err == OK) {
-        mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-
         notify->setMessage("input-format", mCodec->mInputFormat);
         notify->setMessage("output-format", mCodec->mOutputFormat);
 
@@ -6670,8 +6602,6 @@
     status_t err = setupInputSurface();
 
     if (err == OK) {
-        mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-
         notify->setMessage("input-format", mCodec->mInputFormat);
         notify->setMessage("output-format", mCodec->mOutputFormat);
     } else {
@@ -7851,8 +7781,8 @@
             // tunneled playback includes adaptive playback
             builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
                     | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
-        } else if (omxNode->storeMetaDataInBuffers(
-                kPortIndexOutput, OMX_TRUE) == OK ||
+        } else if (omxNode->setPortMode(
+                kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
                 omxNode->prepareForAdaptivePlayback(
                 kPortIndexOutput, OMX_TRUE,
                 1280 /* width */, 720 /* height */) == OK) {
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 85ee4ee..ab12a86 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -50,13 +50,10 @@
     status_t getConfig(OMX_INDEXTYPE index, void *params, size_t size);
     status_t setConfig(OMX_INDEXTYPE index, const void *params, size_t size);
 
-    status_t enableNativeBuffers(OMX_U32 portIndex, OMX_BOOL graphic, OMX_BOOL enable);
+    status_t setPortMode(OMX_U32 port_index, IOMX::PortMode mode);
 
     status_t getGraphicBufferUsage(OMX_U32 portIndex, OMX_U32* usage);
 
-    status_t storeMetaDataInBuffers(
-            OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type);
-
     status_t prepareForAdaptivePlayback(
             OMX_U32 portIndex, OMX_BOOL enable,
             OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight);
@@ -137,6 +134,8 @@
     KeyedVector<OMX::buffer_id, OMX_BUFFERHEADERTYPE *> mBufferIDToBufferHeader;
     KeyedVector<OMX_BUFFERHEADERTYPE *, OMX::buffer_id> mBufferHeaderToBufferID;
 
+    bool mLegacyAdaptiveExperiment;
+    IOMX::PortMode mPortMode[2];
     // metadata and secure buffer type tracking
     MetadataBufferType mMetadataType[2];
     enum SecureBufferType {
@@ -180,15 +179,11 @@
 
     bool isProhibitedIndex_l(OMX_INDEXTYPE index);
 
-    status_t useBuffer(
-            OMX_U32 portIndex, const sp<IMemory> &params,
-            OMX::buffer_id *buffer, OMX_U32 allottedSize);
-
     status_t useBuffer_l(
             OMX_U32 portIndex, const sp<IMemory> &params,
-            OMX::buffer_id *buffer, OMX_U32 allottedSize);
+            OMX::buffer_id *buffer);
 
-    status_t useGraphicBuffer(
+    status_t useGraphicBuffer_l(
             OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
             OMX::buffer_id *buffer);
 
@@ -200,16 +195,16 @@
             OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
             OMX::buffer_id *buffer);
 
-    status_t emptyBuffer(
+    status_t emptyBuffer_l(
             OMX::buffer_id buffer,
             OMX_U32 rangeOffset, OMX_U32 rangeLength,
             OMX_U32 flags, OMX_TICKS timestamp, int fenceFd);
 
-    status_t emptyGraphicBuffer(
+    status_t emptyGraphicBuffer_l(
             OMX::buffer_id buffer, const sp<GraphicBuffer> &graphicBuffer,
             OMX_U32 flags, OMX_TICKS timestamp, int fenceFd);
 
-    status_t emptyNativeHandleBuffer(
+    status_t emptyNativeHandleBuffer_l(
             OMX::buffer_id buffer, const sp<NativeHandle> &nativeHandle,
             OMX_U32 flags, OMX_TICKS timestamp, int fenceFd);
 
@@ -235,6 +230,9 @@
             OMX_IN OMX_PTR pAppData,
             OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
 
+    status_t enableNativeBuffers_l(
+            OMX_U32 portIndex, OMX_BOOL graphic, OMX_BOOL enable);
+
     status_t storeMetaDataInBuffers_l(
             OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type);
 
diff --git a/media/libstagefright/include/SimpleSoftOMXComponent.h b/media/libstagefright/include/SimpleSoftOMXComponent.h
index 591b38e..1d1f2bd 100644
--- a/media/libstagefright/include/SimpleSoftOMXComponent.h
+++ b/media/libstagefright/include/SimpleSoftOMXComponent.h
@@ -29,6 +29,11 @@
 
 struct ALooper;
 
+struct CodecProfileLevel {
+    OMX_U32 mProfile;
+    OMX_U32 mLevel;
+};
+
 struct SimpleSoftOMXComponent : public SoftOMXComponent {
     SimpleSoftOMXComponent(
             const char *name,
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index fdc9d7f..be4a932 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -356,9 +356,12 @@
     mDebugLevelBumpPendingBuffers[1] = 0;
     mMetadataType[0] = kMetadataBufferTypeInvalid;
     mMetadataType[1] = kMetadataBufferTypeInvalid;
+    mPortMode[0] = IOMX::kPortModePresetByteBuffer;
+    mPortMode[1] = IOMX::kPortModePresetByteBuffer;
     mSecureBufferType[0] = kSecureBufferTypeUnknown;
     mSecureBufferType[1] = kSecureBufferTypeUnknown;
     mIsSecure = AString(name).endsWith(".secure");
+    mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled("legacy-adaptive");
 }
 
 OMXNodeInstance::~OMXNodeInstance() {
@@ -650,7 +653,114 @@
     return StatusFromOMXError(err);
 }
 
-status_t OMXNodeInstance::enableNativeBuffers(
+status_t OMXNodeInstance::setPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (portIndex >= NELEM(mPortMode)) {
+        ALOGE("b/31385713, portIndex(%u)", portIndex);
+        android_errorWriteLog(0x534e4554, "31385713");
+        return BAD_VALUE;
+    }
+
+    CLOG_CONFIG(setPortMode, "%s(%d), port %d", asString(mode), mode, portIndex);
+
+    switch (mode) {
+    case IOMX::kPortModeDynamicANWBuffer:
+    {
+        if (portIndex == kPortIndexOutput) {
+            if (mLegacyAdaptiveExperiment) {
+                CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
+                        "not setting port mode to %s(%d) on output",
+                        asString(mode), mode);
+                return StatusFromOMXError(OMX_ErrorUnsupportedIndex);
+            }
+
+            status_t err = enableNativeBuffers_l(
+                    portIndex, OMX_TRUE /*graphic*/, OMX_TRUE);
+            if (err != OK) {
+                return err;
+            }
+        }
+        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
+        return storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL);
+    }
+
+    case IOMX::kPortModeDynamicNativeHandle:
+    {
+        if (portIndex != kPortIndexInput) {
+            CLOG_ERROR(setPortMode, BAD_VALUE,
+                    "%s(%d) mode is only supported on input port", asString(mode), mode);
+            return BAD_VALUE;
+        }
+        (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
+        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
+
+        MetadataBufferType metaType = kMetadataBufferTypeNativeHandleSource;
+        return storeMetaDataInBuffers_l(portIndex, OMX_TRUE, &metaType);
+    }
+
+    case IOMX::kPortModePresetSecureBuffer:
+    {
+        // Allow on both input and output.
+        (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
+        (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
+        return enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_TRUE);
+    }
+
+    case IOMX::kPortModePresetANWBuffer:
+    {
+        if (portIndex != kPortIndexOutput) {
+            CLOG_ERROR(setPortMode, BAD_VALUE,
+                    "%s(%d) mode is only supported on output port", asString(mode), mode);
+            return BAD_VALUE;
+        }
+
+        // Check if we're simulating legacy mode with metadata mode,
+        // if so, enable metadata mode.
+        if (mLegacyAdaptiveExperiment) {
+            if (storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL) == OK) {
+                CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
+                        "metdata mode enabled successfully");
+                return OK;
+            }
+
+            CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
+                    "unable to enable metadata mode on output");
+
+            mLegacyAdaptiveExperiment = false;
+        }
+
+        // Disable secure buffer and enable graphic buffer
+        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
+        status_t err = enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_TRUE);
+        if (err != OK) {
+            return err;
+        }
+
+        // Not running experiment, or metadata is not supported.
+        // Disable metadata mode and use legacy mode.
+        (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
+        return OK;
+    }
+
+    case IOMX::kPortModePresetByteBuffer:
+    {
+        // Disable secure buffer, native buffer and metadata.
+        (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
+        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
+        (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
+        return OK;
+    }
+
+    default:
+        break;
+    }
+
+    CLOG_ERROR(setPortMode, BAD_VALUE, "invalid port mode %d", mode);
+    return BAD_VALUE;
+}
+
+status_t OMXNodeInstance::enableNativeBuffers_l(
         OMX_U32 portIndex, OMX_BOOL graphic, OMX_BOOL enable) {
     if (portIndex >= NELEM(mSecureBufferType)) {
         ALOGE("b/31385713, portIndex(%u)", portIndex);
@@ -658,7 +768,6 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock autoLock(mLock);
     CLOG_CONFIG(enableNativeBuffers, "%s:%u%s, %d", portString(portIndex), portIndex,
                 graphic ? ", graphic" : "", enable);
     OMX_STRING name = const_cast<OMX_STRING>(
@@ -735,13 +844,6 @@
     return OK;
 }
 
-status_t OMXNodeInstance::storeMetaDataInBuffers(
-        OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
-    Mutex::Autolock autolock(mLock);
-    CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u en:%d", portString(portIndex), portIndex, enable);
-    return storeMetaDataInBuffers_l(portIndex, enable, type);
-}
-
 status_t OMXNodeInstance::storeMetaDataInBuffers_l(
         OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
     if (mSailed) {
@@ -832,6 +934,12 @@
     CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u",
             portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);
 
+    if (mLegacyAdaptiveExperiment) {
+        CLOG_INTERNAL(prepareForAdaptivePlayback,
+                "Legacy adaptive experiment: reporting success");
+        return OK;
+    }
+
     OMX_INDEXTYPE index;
     OMX_STRING name = const_cast<OMX_STRING>(
             "OMX.google.android.index.prepareForAdaptivePlayback");
@@ -902,43 +1010,62 @@
 }
 
 status_t OMXNodeInstance::useBuffer(
-        OMX_U32 portIndex,
-        const OMXBuffer &omxBuffer, OMX::buffer_id *buffer) {
-    // TODO: the allotted size is probably no longer needed.
-    if (omxBuffer.mBufferType == OMXBuffer::kBufferTypeSharedMem) {
-        return useBuffer(portIndex, omxBuffer.mMem, buffer, omxBuffer.mAllottedSize);
+        OMX_U32 portIndex, const OMXBuffer &omxBuffer, OMX::buffer_id *buffer) {
+    if (buffer == NULL) {
+        ALOGE("b/25884056");
+        return BAD_VALUE;
     }
 
-    if (omxBuffer.mBufferType == OMXBuffer::kBufferTypeANWBuffer) {
-        return useGraphicBuffer(portIndex, omxBuffer.mGraphicBuffer, buffer);
+    if (portIndex >= NELEM(mNumPortBuffers)) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+
+    switch (omxBuffer.mBufferType) {
+    case OMXBuffer::kBufferTypePreset:
+        return useBuffer_l(portIndex, NULL, buffer);
+
+    case OMXBuffer::kBufferTypeSharedMem:
+        return useBuffer_l(portIndex, omxBuffer.mMem, buffer);
+
+    case OMXBuffer::kBufferTypeANWBuffer:
+        return useGraphicBuffer_l(portIndex, omxBuffer.mGraphicBuffer, buffer);
+
+    default:
+        break;
     }
 
     return BAD_VALUE;
 }
 
-status_t OMXNodeInstance::useBuffer(
-        OMX_U32 portIndex, const sp<IMemory> &params,
-        OMX::buffer_id *buffer, OMX_U32 allottedSize) {
-    if (params == NULL || buffer == NULL) {
-        ALOGE("b/25884056");
-        return BAD_VALUE;
-    }
-
-    Mutex::Autolock autoLock(mLock);
-    if (allottedSize > params->size() || portIndex >= NELEM(mNumPortBuffers)) {
-        return BAD_VALUE;
-    }
-
-    return useBuffer_l(portIndex, params, buffer, allottedSize);
-}
-
 status_t OMXNodeInstance::useBuffer_l(
-        OMX_U32 portIndex, const sp<IMemory> &params,
-        OMX::buffer_id *buffer, OMX_U32 allottedSize) {
+        OMX_U32 portIndex, const sp<IMemory> &params, OMX::buffer_id *buffer) {
     BufferMeta *buffer_meta;
     OMX_BUFFERHEADERTYPE *header;
     OMX_ERRORTYPE err = OMX_ErrorNone;
     bool isMetadata = mMetadataType[portIndex] != kMetadataBufferTypeInvalid;
+
+    OMX_U32 allottedSize;
+    if (isMetadata) {
+        if (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource) {
+            allottedSize = sizeof(VideoGrallocMetadata);
+        } else if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer) {
+            allottedSize = sizeof(VideoNativeMetadata);
+        } else if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource) {
+            allottedSize = sizeof(VideoNativeHandleMetadata);
+        } else {
+            return BAD_VALUE;
+        }
+    } else {
+        // NULL params is allowed only in metadata mode.
+        if (params == NULL) {
+            ALOGE("b/25884056");
+            return BAD_VALUE;
+        }
+        allottedSize = params->size();
+    }
+
     bool isOutputGraphicMetadata = (portIndex == kPortIndexOutput) &&
             (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource ||
                     mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer);
@@ -968,13 +1095,6 @@
         // metadata buffers are not connected cross process
         // use a backup buffer instead of the actual buffer
         if (isMetadata) {
-            // TODO: this logic is very fishy, should it be removed?
-            // if we are not connecting the buffers, the sizes must match
-            if (params != NULL && allottedSize != params->size()) {
-                CLOG_ERROR(useBuffer, BAD_VALUE, SIMPLE_BUFFER(portIndex, (size_t)allottedSize, data));
-                return BAD_VALUE;
-            }
-
             data = new (std::nothrow) OMX_U8[allottedSize];
             if (data == NULL) {
                 return NO_MEMORY;
@@ -984,8 +1104,6 @@
             buffer_meta = new BufferMeta(
                     params, portIndex, false /* copy */, data);
         } else {
-            // NULL params is allowed only in metadata mode.
-            CHECK(params != NULL);
             data = static_cast<OMX_U8 *>(params->pointer());
 
             buffer_meta = new BufferMeta(
@@ -1083,14 +1201,13 @@
 // XXX: This function is here for backwards compatibility.  Once the OMX
 // implementations have been updated this can be removed and useGraphicBuffer2
 // can be renamed to useGraphicBuffer.
-status_t OMXNodeInstance::useGraphicBuffer(
+status_t OMXNodeInstance::useGraphicBuffer_l(
         OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
         OMX::buffer_id *buffer) {
     if (graphicBuffer == NULL || buffer == NULL) {
         ALOGE("b/25884056");
         return BAD_VALUE;
     }
-    Mutex::Autolock autoLock(mLock);
 
     // First, see if we're in metadata mode. We could be running an experiment to simulate
     // legacy behavior (preallocated buffers) on devices that supports meta.
@@ -1161,16 +1278,12 @@
         return BAD_VALUE;
     }
 
-    OMX_U32 allottedSize = 0;
-    if (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource) {
-        allottedSize = sizeof(VideoGrallocMetadata);
-    } else if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer) {
-        allottedSize = sizeof(VideoNativeMetadata);
-    } else {
+    if (mMetadataType[portIndex] != kMetadataBufferTypeGrallocSource &&
+            mMetadataType[portIndex] != kMetadataBufferTypeANWBuffer) {
         return BAD_VALUE;
     }
 
-    status_t err = useBuffer_l(portIndex, NULL, buffer, allottedSize);
+    status_t err = useBuffer_l(portIndex, NULL, buffer);
     if (err != OK) {
         return err;
     }
@@ -1443,29 +1556,32 @@
 status_t OMXNodeInstance::emptyBuffer(
         buffer_id buffer, const OMXBuffer &omxBuffer,
         OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
-    if (omxBuffer.mBufferType == OMXBuffer::kBufferTypePreset) {
-        return emptyBuffer(
+    Mutex::Autolock autoLock(mLock);
+
+    switch (omxBuffer.mBufferType) {
+    case OMXBuffer::kBufferTypePreset:
+        return emptyBuffer_l(
                 buffer, 0, omxBuffer.mRangeLength, flags, timestamp, fenceFd);
-    }
 
-    if (omxBuffer.mBufferType == OMXBuffer::kBufferTypeANWBuffer) {
-        return emptyGraphicBuffer(
+    case OMXBuffer::kBufferTypeANWBuffer:
+        return emptyGraphicBuffer_l(
                 buffer, omxBuffer.mGraphicBuffer, flags, timestamp, fenceFd);
-    }
 
-    if (omxBuffer.mBufferType == OMXBuffer::kBufferTypeNativeHandle) {
-        return emptyNativeHandleBuffer(
+    case OMXBuffer::kBufferTypeNativeHandle:
+        return emptyNativeHandleBuffer_l(
                 buffer, omxBuffer.mNativeHandle, flags, timestamp, fenceFd);
+
+    default:
+        break;
     }
 
     return BAD_VALUE;
 }
 
-status_t OMXNodeInstance::emptyBuffer(
+status_t OMXNodeInstance::emptyBuffer_l(
         OMX::buffer_id buffer,
         OMX_U32 rangeOffset, OMX_U32 rangeLength,
         OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
-    Mutex::Autolock autoLock(mLock);
 
     // no emptybuffer if using input surface
     if (getBufferSource() != NULL) {
@@ -1614,11 +1730,9 @@
 }
 
 // like emptyBuffer, but the data is already in header->pBuffer
-status_t OMXNodeInstance::emptyGraphicBuffer(
+status_t OMXNodeInstance::emptyGraphicBuffer_l(
         OMX::buffer_id buffer, const sp<GraphicBuffer> &graphicBuffer,
         OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
-    Mutex::Autolock autoLock(mLock);
-
     OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
     if (header == NULL) {
         ALOGE("b/25884056");
@@ -1688,11 +1802,9 @@
     return timestamp;
 }
 
-status_t OMXNodeInstance::emptyNativeHandleBuffer(
+status_t OMXNodeInstance::emptyNativeHandleBuffer_l(
         OMX::buffer_id buffer, const sp<NativeHandle> &nativeHandle,
         OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
-    Mutex::Autolock autoLock(mLock);
-
     OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
     if (header == NULL) {
         ALOGE("b/25884056");
@@ -1702,7 +1814,7 @@
     status_t err = updateNativeHandleInMeta_l(
             kPortIndexInput, nativeHandle, buffer, header);
     if (err != OK) {
-        CLOG_ERROR(emptyNativeHandleBuffer, err, FULL_BUFFER(
+        CLOG_ERROR(emptyNativeHandleBuffer_l, err, FULL_BUFFER(
                 (intptr_t)header->pBuffer, header, fenceFd));
         return err;
     }
diff --git a/media/libstagefright/omx/OMXUtils.h b/media/libstagefright/omx/OMXUtils.h
index 3f533ff..401d64b 100644
--- a/media/libstagefright/omx/OMXUtils.h
+++ b/media/libstagefright/omx/OMXUtils.h
@@ -51,6 +51,30 @@
         const sp<IOMXNode> &omxNode,
         DescribeColorFormat2Params &describeParams);
 
+inline static const char *asString(MetadataBufferType i, const char *def = "??") {
+    using namespace android;
+    switch (i) {
+        case kMetadataBufferTypeCameraSource:   return "CameraSource";
+        case kMetadataBufferTypeGrallocSource:  return "GrallocSource";
+        case kMetadataBufferTypeANWBuffer:      return "ANWBuffer";
+        case kMetadataBufferTypeNativeHandleSource: return "NativeHandleSource";
+        case kMetadataBufferTypeInvalid:        return "Invalid";
+        default:                                return def;
+    }
+}
+
+inline static const char *asString(IOMX::PortMode mode, const char *def = "??") {
+    using namespace android;
+    switch (mode) {
+        case IOMX::kPortModePresetByteBuffer:   return "PresetByteBuffer";
+        case IOMX::kPortModePresetANWBuffer:    return "PresetANWBuffer";
+        case IOMX::kPortModePresetSecureBuffer: return "PresetSecureBuffer";
+        case IOMX::kPortModeDynamicANWBuffer:   return "DynamicANWBuffer";
+        case IOMX::kPortModeDynamicNativeHandle:return "DynamicNativeHandle";
+        default:                                return def;
+    }
+}
+
 }  // namespace android
 
 #endif