From 9a4768f7bfcd4654f93ad9b22eff87df493a9d5e Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Tue, 2 Aug 2016 07:07:05 -0700 Subject: [PATCH] DO NOT MERGE: IOMX: work against metadata buffer spoofing - Prohibit direct set/getParam/Settings for extensions meant for OMXNodeInstance alone. This disallows enabling metadata mode without the knowledge of OMXNodeInstance. - Do not share metadata mode buffers cross process. - Disallow setting up metadata mode/tunneling/input surface after first sendCommand. (Except to Idle for OMXCodec quirk.) - Disallow store-meta for input cross process. - Disallow emptyBuffer for surface input (via IOMX). - Fix checking for input surface. [backported from M] Bug: 29422020 Change-Id: I801c77b80e703903f62e42d76fd2e76a34e4bc8e --- include/media/IOMX.h | 4 +- media/libmedia/IOMX.cpp | 14 +- media/libstagefright/ACodec.cpp | 3 +- media/libstagefright/OMXClient.cpp | 13 +- media/libstagefright/include/OMX.h | 4 +- media/libstagefright/include/OMXNodeInstance.h | 13 +- media/libstagefright/omx/OMX.cpp | 8 +- media/libstagefright/omx/OMXNodeInstance.cpp | 199 ++++++++++++++++++++++--- 8 files changed, 215 insertions(+), 43 deletions(-) diff --git a/include/media/IOMX.h b/include/media/IOMX.h index 595e51f65b..6e4a4acf57 100644 --- a/include/media/IOMX.h +++ b/include/media/IOMX.h @@ -99,7 +99,7 @@ public: virtual status_t useBuffer( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer) = 0; + buffer_id *buffer, OMX_BOOL crossProcess = OMX_FALSE) = 0; virtual status_t useGraphicBuffer( node_id node, OMX_U32 port_index, @@ -125,7 +125,7 @@ public: virtual status_t allocateBufferWithBackup( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer) = 0; + buffer_id *buffer, OMX_BOOL crossProcess = OMX_FALSE) = 0; virtual status_t freeBuffer( node_id node, OMX_U32 port_index, buffer_id buffer) = 0; diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp index 75b99a61ce..d5a22e930c 100644 --- a/media/libmedia/IOMX.cpp +++ b/media/libmedia/IOMX.cpp @@ -245,7 +245,7 @@ public: virtual status_t useBuffer( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer) { + buffer_id *buffer, OMX_BOOL /* crossProcess */) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeInt32((int32_t)node); @@ -415,7 +415,7 @@ public: virtual status_t allocateBufferWithBackup( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer) { + buffer_id *buffer, OMX_BOOL /* crossProcess */) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeInt32((int32_t)node); @@ -754,7 +754,8 @@ status_t BnOMX::onTransact( interface_cast(data.readStrongBinder()); buffer_id buffer; - status_t err = useBuffer(node, port_index, params, &buffer); + status_t err = useBuffer( + node, port_index, params, &buffer, OMX_TRUE /* crossProcess */); reply->writeInt32(err); if (err == OK) { @@ -842,7 +843,10 @@ status_t BnOMX::onTransact( OMX_U32 port_index = data.readInt32(); OMX_BOOL enable = (OMX_BOOL)data.readInt32(); - status_t err = storeMetaDataInBuffers(node, port_index, enable); + status_t err = + // only control output metadata via Binder + port_index != 1 /* kOutputPortIndex */ ? BAD_VALUE : + storeMetaDataInBuffers(node, port_index, enable); reply->writeInt32(err); return NO_ERROR; @@ -924,7 +928,7 @@ status_t BnOMX::onTransact( buffer_id buffer; status_t err = allocateBufferWithBackup( - node, port_index, params, &buffer); + node, port_index, params, &buffer, OMX_TRUE /* crossProcess */); reply->writeInt32(err); diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index f6240200d1..aa0466d114 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -997,7 +997,8 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { VideoDecoderOutputMetaData *metaData = reinterpret_cast( oldest->mData->base()); - CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource); + // metaData is only readable if codec is in the same process + //CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource); ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)", oldest - &mBuffers[kPortIndexOutput][0], diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp index ca031aa68d..0341d0311d 100644 --- a/media/libstagefright/OMXClient.cpp +++ b/media/libstagefright/OMXClient.cpp @@ -90,7 +90,7 @@ struct MuxOMX : public IOMX { virtual status_t useBuffer( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer); + buffer_id *buffer, OMX_BOOL crossProcess); virtual status_t useGraphicBuffer( node_id node, OMX_U32 port_index, @@ -112,7 +112,7 @@ struct MuxOMX : public IOMX { virtual status_t allocateBufferWithBackup( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer); + buffer_id *buffer, OMX_BOOL crossProcess); virtual status_t freeBuffer( node_id node, OMX_U32 port_index, buffer_id buffer); @@ -314,8 +314,9 @@ status_t MuxOMX::getGraphicBufferUsage( status_t MuxOMX::useBuffer( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer) { - return getOMX(node)->useBuffer(node, port_index, params, buffer); + buffer_id *buffer, OMX_BOOL /* crossProcess */) { + return getOMX(node)->useBuffer( + node, port_index, params, buffer, OMX_FALSE /* crossProcess */); } status_t MuxOMX::useGraphicBuffer( @@ -353,9 +354,9 @@ status_t MuxOMX::allocateBuffer( status_t MuxOMX::allocateBufferWithBackup( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer) { + buffer_id *buffer, OMX_BOOL /* crossProcess */) { return getOMX(node)->allocateBufferWithBackup( - node, port_index, params, buffer); + node, port_index, params, buffer, OMX_FALSE /* crossProcess */); } status_t MuxOMX::freeBuffer( diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h index 2da5c6c5f0..829c38b593 100644 --- a/media/libstagefright/include/OMX.h +++ b/media/libstagefright/include/OMX.h @@ -81,7 +81,7 @@ public: virtual status_t useBuffer( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer); + buffer_id *buffer, OMX_BOOL crossProcess); virtual status_t useGraphicBuffer( node_id node, OMX_U32 port_index, @@ -103,7 +103,7 @@ public: virtual status_t allocateBufferWithBackup( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer); + buffer_id *buffer, OMX_BOOL crossProcess); virtual status_t freeBuffer( node_id node, OMX_U32 port_index, buffer_id buffer); diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h index ad50fafb85..616dda1a85 100644 --- a/media/libstagefright/include/OMXNodeInstance.h +++ b/media/libstagefright/include/OMXNodeInstance.h @@ -21,6 +21,7 @@ #include "OMX.h" #include +#include #include namespace android { @@ -68,7 +69,7 @@ struct OMXNodeInstance { status_t useBuffer( OMX_U32 portIndex, const sp ¶ms, - OMX::buffer_id *buffer); + OMX::buffer_id *buffer, OMX_BOOL crossProcess); status_t useGraphicBuffer( OMX_U32 portIndex, const sp &graphicBuffer, @@ -89,7 +90,7 @@ struct OMXNodeInstance { status_t allocateBufferWithBackup( OMX_U32 portIndex, const sp ¶ms, - OMX::buffer_id *buffer); + OMX::buffer_id *buffer, OMX_BOOL crossProcess); status_t freeBuffer(OMX_U32 portIndex, OMX::buffer_id buffer); @@ -133,6 +134,9 @@ private: OMX_HANDLETYPE mHandle; sp mObserver; bool mDying; + bool mSailed; // configuration is set (no more meta-mode changes) + bool mQueriedProhibitedExtensions; + SortedVector mProhibitedExtensions; bool mIsSecure; // Lock only covers mGraphicBufferSource. We can't always use mLock @@ -153,6 +157,9 @@ private: KeyedVector mBufferIDToBufferHeader; KeyedVector mBufferHeaderToBufferID; + // metadata mode tracking + bool mUsingMetadata[2]; + // For debug support char *mName; int DEBUG; @@ -177,6 +184,8 @@ private: OMX::buffer_id findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader); void invalidateBufferID(OMX::buffer_id buffer); + bool isProhibitedIndex_l(OMX_INDEXTYPE index); + status_t useGraphicBuffer2_l( OMX_U32 portIndex, const sp &graphicBuffer, OMX::buffer_id *buffer); diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp index f8a6f171e8..1faf724d76 100644 --- a/media/libstagefright/omx/OMX.cpp +++ b/media/libstagefright/omx/OMX.cpp @@ -361,9 +361,9 @@ status_t OMX::configureVideoTunnelMode( status_t OMX::useBuffer( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer) { + buffer_id *buffer, OMX_BOOL crossProcess) { return findInstance(node)->useBuffer( - port_index, params, buffer); + port_index, params, buffer, crossProcess); } status_t OMX::useGraphicBuffer( @@ -400,9 +400,9 @@ status_t OMX::allocateBuffer( status_t OMX::allocateBufferWithBackup( node_id node, OMX_U32 port_index, const sp ¶ms, - buffer_id *buffer) { + buffer_id *buffer, OMX_BOOL crossProcess) { return findInstance(node)->allocateBufferWithBackup( - port_index, params, buffer); + port_index, params, buffer, crossProcess); } status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) { diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index df7461cdca..f091b87735 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -100,26 +100,34 @@ static void InitOMXParams(T *params) { namespace android { struct BufferMeta { - BufferMeta(const sp &mem, OMX_U32 portIndex, bool is_backup = false) + BufferMeta( + const sp &mem, OMX_U32 portIndex, bool copyToOmx, + bool copyFromOmx, OMX_U8 *backup) : mMem(mem), - mIsBackup(is_backup), - mPortIndex(portIndex) { + mCopyFromOmx(copyFromOmx), + mCopyToOmx(copyToOmx), + mPortIndex(portIndex), + mBackup(backup) { } BufferMeta(size_t size, OMX_U32 portIndex) : mSize(size), - mIsBackup(false), - mPortIndex(portIndex) { + mCopyFromOmx(false), + mCopyToOmx(false), + mPortIndex(portIndex), + mBackup(NULL) { } BufferMeta(const sp &graphicBuffer, OMX_U32 portIndex) : mGraphicBuffer(graphicBuffer), - mIsBackup(false), - mPortIndex(portIndex) { + mCopyFromOmx(false), + mCopyToOmx(false), + mPortIndex(portIndex), + mBackup(NULL) { } void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { - if (!mIsBackup) { + if (!mCopyFromOmx) { return; } @@ -129,7 +137,7 @@ struct BufferMeta { } void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { - if (!mIsBackup) { + if (!mCopyToOmx) { return; } @@ -146,12 +154,18 @@ struct BufferMeta { return mPortIndex; } + ~BufferMeta() { + delete[] mBackup; + } + private: sp mGraphicBuffer; sp mMem; size_t mSize; - bool mIsBackup; + bool mCopyFromOmx; + bool mCopyToOmx; OMX_U32 mPortIndex; + OMX_U8 *mBackup; BufferMeta(const BufferMeta &); BufferMeta &operator=(const BufferMeta &); @@ -178,6 +192,8 @@ OMXNodeInstance::OMXNodeInstance( mHandle(NULL), mObserver(observer), mDying(false), + mSailed(false), + mQueriedProhibitedExtensions(false), mBufferIDCount(0) { mName = ADebug::GetDebugName(name); @@ -188,6 +204,8 @@ OMXNodeInstance::OMXNodeInstance( mNumPortBuffers[1] = 0; mDebugLevelBumpPendingBuffers[0] = 0; mDebugLevelBumpPendingBuffers[1] = 0; + mUsingMetadata[0] = false; + mUsingMetadata[1] = false; mIsSecure = AString(name).endsWith(".secure"); } @@ -345,7 +363,12 @@ status_t OMXNodeInstance::freeNode(OMXMaster *master) { status_t OMXNodeInstance::sendCommand( OMX_COMMANDTYPE cmd, OMX_S32 param) { - const sp& bufferSource(getGraphicBufferSource()); + if (cmd == OMX_CommandStateSet && param != OMX_StateIdle) { + // We do not support returning from unloaded state, so there are no configurations past + // first StateSet command. However, OMXCodec supports meta configuration past Stateset:Idle. + mSailed = true; + } + const sp bufferSource(getGraphicBufferSource()); if (bufferSource != NULL && cmd == OMX_CommandStateSet) { if (param == OMX_StateIdle) { // Initiating transition from Executing -> Idle @@ -378,10 +401,55 @@ status_t OMXNodeInstance::sendCommand( return StatusFromOMXError(err); } +bool OMXNodeInstance::isProhibitedIndex_l(OMX_INDEXTYPE index) { + // these extensions can only be used from OMXNodeInstance, not by clients directly. + static const char *restricted_extensions[] = { + "OMX.google.android.index.storeMetaDataInBuffers", + "OMX.google.android.index.prepareForAdaptivePlayback", + "OMX.google.android.index.configureVideoTunnelMode", + "OMX.google.android.index.useAndroidNativeBuffer2", + "OMX.google.android.index.useAndroidNativeBuffer", + "OMX.google.android.index.enableAndroidNativeBuffers", + "OMX.google.android.index.getAndroidNativeBufferUsage", + }; + + if ((index > OMX_IndexComponentStartUnused && index <= OMX_IndexParamStandardComponentRole) + || (index > OMX_IndexPortStartUnused && index <= OMX_IndexParamCompBufferSupplier) + || (index > OMX_IndexAudioStartUnused && index <= OMX_IndexConfigAudioChannelVolume) + || (index > OMX_IndexVideoStartUnused && index <= OMX_IndexConfigVideoNalSize) + || (index > OMX_IndexCommonStartUnused + && index <= OMX_IndexConfigCommonTransitionEffect) + || (index > (OMX_INDEXTYPE)OMX_IndexExtAudioStartUnused + && index <= (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3) + || (index > (OMX_INDEXTYPE)OMX_IndexExtVideoStartUnused + && index <= (OMX_INDEXTYPE)OMX_IndexParamSliceSegments) + || (index > (OMX_INDEXTYPE)OMX_IndexExtOtherStartUnused + && index <= (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion)) { + return false; + } + + if (!mQueriedProhibitedExtensions) { + for (size_t i = 0; i < NELEM(restricted_extensions); ++i) { + OMX_INDEXTYPE ext; + if (OMX_GetExtensionIndex(mHandle, (OMX_STRING)restricted_extensions[i], &ext) == OMX_ErrorNone) { + mProhibitedExtensions.add(ext); + } + } + mQueriedProhibitedExtensions = true; + } + + return mProhibitedExtensions.indexOf(index) >= 0; +} + status_t OMXNodeInstance::getParameter( OMX_INDEXTYPE index, void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); + if (isProhibitedIndex_l(index)) { + android_errorWriteLog(0x534e4554, "29422020"); + return BAD_INDEX; + } + OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; // some errors are expected for getParameter @@ -397,6 +465,11 @@ status_t OMXNodeInstance::setParameter( OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params); + if (isProhibitedIndex_l(index)) { + android_errorWriteLog(0x534e4554, "29422020"); + return BAD_INDEX; + } + OMX_ERRORTYPE err = OMX_SetParameter( mHandle, index, const_cast(params)); CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index); @@ -407,6 +480,11 @@ status_t OMXNodeInstance::getConfig( OMX_INDEXTYPE index, void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); + if (isProhibitedIndex_l(index)) { + android_errorWriteLog(0x534e4554, "29422020"); + return BAD_INDEX; + } + OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; // some errors are expected for getConfig @@ -422,6 +500,11 @@ status_t OMXNodeInstance::setConfig( OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params); + if (isProhibitedIndex_l(index)) { + android_errorWriteLog(0x534e4554, "29422020"); + return BAD_INDEX; + } + OMX_ERRORTYPE err = OMX_SetConfig( mHandle, index, const_cast(params)); CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index); @@ -507,6 +590,15 @@ status_t OMXNodeInstance::storeMetaDataInBuffers_l( OMX_BOOL enable, OMX_BOOL useGraphicBuffer, OMX_BOOL *usingGraphicBufferInMetadata) { + if (mSailed) { + android_errorWriteLog(0x534e4554, "29422020"); + return INVALID_OPERATION; + } + if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) { + android_errorWriteLog(0x534e4554, "26324358"); + return BAD_VALUE; + } + OMX_INDEXTYPE index; OMX_STRING name = const_cast( "OMX.google.android.index.storeMetaDataInBuffers"); @@ -541,6 +633,9 @@ status_t OMXNodeInstance::storeMetaDataInBuffers_l( // don't log loud error if component does not support metadata mode on the output if (err != OMX_ErrorNone) { *usingGraphicBufferInMetadata = OMX_FALSE; + if (enable) { + mUsingMetadata[portIndex] = false; + } if (err == OMX_ErrorUnsupportedIndex && portIndex == kPortIndexOutput) { CLOGW("component does not support metadata mode; using fallback"); } else if (xerr != OMX_ErrorNone) { @@ -549,6 +644,8 @@ status_t OMXNodeInstance::storeMetaDataInBuffers_l( CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d GB=%d", name, index, portString(portIndex), portIndex, enable, useGraphicBuffer); } + } else { + mUsingMetadata[portIndex] = enable; } return StatusFromOMXError(err); } @@ -557,6 +654,10 @@ status_t OMXNodeInstance::prepareForAdaptivePlayback( OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) { Mutex::Autolock autolock(mLock); + if (mSailed) { + android_errorWriteLog(0x534e4554, "29422020"); + return INVALID_OPERATION; + } CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u", portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight); @@ -587,6 +688,10 @@ status_t OMXNodeInstance::configureVideoTunnelMode( OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync, native_handle_t **sidebandHandle) { Mutex::Autolock autolock(mLock); + if (mSailed) { + android_errorWriteLog(0x534e4554, "29422020"); + return INVALID_OPERATION; + } CLOG_CONFIG(configureVideoTunnelMode, "%s:%u tun=%d sync=%u", portString(portIndex), portIndex, tunneled, audioHwSync); @@ -627,16 +732,39 @@ status_t OMXNodeInstance::configureVideoTunnelMode( status_t OMXNodeInstance::useBuffer( OMX_U32 portIndex, const sp ¶ms, - OMX::buffer_id *buffer) { + OMX::buffer_id *buffer, OMX_BOOL crossProcess) { Mutex::Autolock autoLock(mLock); + if (portIndex >= NELEM(mUsingMetadata)) { + return BAD_VALUE; + } + // We do not support metadata mode changes past buffer allocation + mSailed = true; + + // metadata buffers are not connected cross process + BufferMeta *buffer_meta; + bool isMeta = mUsingMetadata[portIndex]; + bool useBackup = crossProcess && isMeta; // use a backup buffer instead of the actual buffer + OMX_U8 *data = static_cast(params->pointer()); + // allocate backup buffer + if (useBackup) { + data = new (std::nothrow) OMX_U8[params->size()]; + if (data == NULL) { + return NO_MEMORY; + } + memset(data, 0, params->size()); - BufferMeta *buffer_meta = new BufferMeta(params, portIndex); + buffer_meta = new BufferMeta( + params, portIndex, false /* copyToOmx */, false /* copyFromOmx */, data); + } else { + buffer_meta = new BufferMeta( + params, portIndex, false /* copyFromOmx */, false /* copyToOmx */, NULL); + } OMX_BUFFERHEADERTYPE *header; OMX_ERRORTYPE err = OMX_UseBuffer( mHandle, &header, portIndex, buffer_meta, - params->size(), static_cast(params->pointer())); + params->size(), data); if (err != OMX_ErrorNone) { CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(portIndex, params->size(), params->pointer())); @@ -802,7 +930,16 @@ status_t OMXNodeInstance::createInputSurface( Mutex::Autolock autolock(mLock); status_t err; - const sp& surfaceCheck = getGraphicBufferSource(); + // only allow graphic source on input port, when there are no allocated buffers yet + if (portIndex != kPortIndexInput) { + android_errorWriteLog(0x534e4554, "29422020"); + return BAD_VALUE; + } else if (mNumPortBuffers[portIndex] > 0) { + android_errorWriteLog(0x534e4554, "29422020"); + return INVALID_OPERATION; + } + + const sp surfaceCheck = getGraphicBufferSource(); if (surfaceCheck != NULL) { return ALREADY_EXISTS; } @@ -866,6 +1003,8 @@ status_t OMXNodeInstance::allocateBuffer( OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer, void **buffer_data) { Mutex::Autolock autoLock(mLock); + // We do not support metadata mode changes past buffer allocation + mSailed = true; BufferMeta *buffer_meta = new BufferMeta(size, portIndex); @@ -902,10 +1041,23 @@ status_t OMXNodeInstance::allocateBuffer( status_t OMXNodeInstance::allocateBufferWithBackup( OMX_U32 portIndex, const sp ¶ms, - OMX::buffer_id *buffer) { + OMX::buffer_id *buffer, OMX_BOOL crossProcess) { Mutex::Autolock autoLock(mLock); + if (portIndex >= NELEM(mUsingMetadata)) { + return BAD_VALUE; + } + // We do not support metadata mode changes past buffer allocation + mSailed = true; + + // metadata buffers are not connected cross process + bool isMeta = mUsingMetadata[portIndex]; + bool copy = !(crossProcess && isMeta); - BufferMeta *buffer_meta = new BufferMeta(params, portIndex, true); + BufferMeta *buffer_meta = new BufferMeta( + params, portIndex, + (portIndex == kPortIndexInput) && copy /* copyToOmx */, + (portIndex == kPortIndexOutput) && copy /* copyFromOmx */, + NULL /* data */); OMX_BUFFERHEADERTYPE *header; @@ -924,6 +1076,7 @@ status_t OMXNodeInstance::allocateBufferWithBackup( } CHECK_EQ(header->pAppPrivate, buffer_meta); + memset(header->pBuffer, 0, header->nAllocLen); *buffer = makeBufferID(header); @@ -995,13 +1148,17 @@ status_t OMXNodeInstance::emptyBuffer( OMX_U32 flags, OMX_TICKS timestamp) { Mutex::Autolock autoLock(mLock); - OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput); - if (header == NULL) { - return BAD_VALUE; + // no emptybuffer if using input surface + if (getGraphicBufferSource() != NULL) { + android_errorWriteLog(0x534e4554, "29422020"); + return INVALID_OPERATION; } + + OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput); // rangeLength and rangeOffset must be a subset of the allocated data in the buffer. // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0. - if (rangeOffset > header->nAllocLen + if (header == NULL + || rangeOffset > header->nAllocLen || rangeLength > header->nAllocLen - rangeOffset) { return BAD_VALUE; } -- 2.11.0