@ -359,7 +359,18 @@ status_t Camera3OutputStream::configureQueueLocked() {
// Set dequeueBuffer/attachBuffer timeout if the consumer is not hw composer or hw texture.
// We need skip these cases as timeout will disable the non-blocking (async) mode.
if ( ! ( isConsumedByHWComposer ( ) | | isConsumedByHWTexture ( ) ) ) {
mConsumer - > setDequeueTimeout ( kDequeueBufferTimeout ) ;
if ( mUseBufferManager ) {
// When buffer manager is handling the buffer, we should have available buffers in
// buffer queue before we calls into dequeueBuffer because buffer manager is tracking
// free buffers.
// There are however some consumer side feature (ImageReader::discardFreeBuffers) that
// can discard free buffers without notifying buffer manager. We want the timeout to
// happen immediately here so buffer manager can try to update its internal state and
// try to allocate a buffer instead of waiting.
mConsumer - > setDequeueTimeout ( 0 ) ;
} else {
mConsumer - > setDequeueTimeout ( kDequeueBufferTimeout ) ;
}
}
return OK ;
@ -526,6 +537,8 @@ status_t Camera3OutputStream::getBufferLockedCommon(ANativeWindowBuffer** anb, i
if ( res ! = OK ) {
ALOGE ( " %s: Stream %d: Can't attach the output buffer to this surface: %s (%d) " ,
__FUNCTION__ , mId , strerror ( - res ) , res ) ;
checkRetAndSetAbandonedLocked ( res ) ;
return res ;
}
gotBufferFromManager = true ;
@ -562,33 +575,68 @@ status_t Camera3OutputStream::getBufferLockedCommon(ANativeWindowBuffer** anb, i
mDequeueBufferLatency . add ( dequeueStart , dequeueEnd ) ;
mLock . lock ( ) ;
if ( res ! = OK ) {
ALOGE ( " %s: Stream %d: Can't dequeue next output buffer: %s (%d) " ,
__FUNCTION__ , mId , strerror ( - res ) , res ) ;
// Only transition to STATE_ABANDONED from STATE_CONFIGURED. (If it is STATE_PREPARING,
// let prepareNextBuffer handle the error.)
if ( ( res = = NO_INIT | | res = = DEAD_OBJECT ) & & mState = = STATE_CONFIGURED ) {
mState = STATE_ABANDONED ;
if ( mUseBufferManager & & res = = TIMED_OUT ) {
checkRemovedBuffersLocked ( ) ;
sp < GraphicBuffer > gb ;
res = mBufferManager - > getBufferForStream (
getId ( ) , getStreamSetId ( ) , & gb , fenceFd , /*noFreeBuffer*/ true ) ;
if ( res = = OK ) {
// Attach this buffer to the bufferQueue: the buffer will be in dequeue state after
// a successful return.
* anb = gb . get ( ) ;
res = mConsumer - > attachBuffer ( * anb ) ;
gotBufferFromManager = true ;
ALOGV ( " Stream %d: Attached new buffer " , getId ( ) ) ;
if ( res ! = OK ) {
ALOGE ( " %s: Stream %d: Can't attach the output buffer to this surface: %s (%d) " ,
__FUNCTION__ , mId , strerror ( - res ) , res ) ;
checkRetAndSetAbandonedLocked ( res ) ;
return res ;
}
} else {
ALOGE ( " %s: Stream %d: Can't get next output buffer from buffer manager: "
" %s (%d) " , __FUNCTION__ , mId , strerror ( - res ) , res ) ;
return res ;
}
} else if ( res ! = OK ) {
ALOGE ( " %s: Stream %d: Can't dequeue next output buffer: %s (%d) " ,
__FUNCTION__ , mId , strerror ( - res ) , res ) ;
checkRetAndSetAbandonedLocked ( res ) ;
return res ;
}
}
if ( res = = OK ) {
std : : vector < sp < GraphicBuffer > > removedBuffers ;
res = mConsumer - > getAndFlushRemovedBuffers ( & removedBuffers ) ;
if ( res = = OK ) {
onBuffersRemovedLocked ( removedBuffers ) ;
checkRemovedBuffersLocked ( ) ;
}
if ( mUseBufferManager & & removedBuffers . size ( ) > 0 ) {
mBufferManager - > onBuffersRemoved ( getId ( ) , getStreamSetId ( ) , removedBuffers . size ( ) ) ;
}
return res ;
}
void Camera3OutputStream : : checkRemovedBuffersLocked ( bool notifyBufferManager ) {
std : : vector < sp < GraphicBuffer > > removedBuffers ;
status_t res = mConsumer - > getAndFlushRemovedBuffers ( & removedBuffers ) ;
if ( res = = OK ) {
onBuffersRemovedLocked ( removedBuffers ) ;
if ( notifyBufferManager & & mUseBufferManager & & removedBuffers . size ( ) > 0 ) {
mBufferManager - > onBuffersRemoved ( getId ( ) , getStreamSetId ( ) , removedBuffers . size ( ) ) ;
}
}
}
return res ;
void Camera3OutputStream : : checkRetAndSetAbandonedLocked ( status_t res ) {
// Only transition to STATE_ABANDONED from STATE_CONFIGURED. (If it is
// STATE_PREPARING, let prepareNextBuffer handle the error.)
if ( ( res = = NO_INIT | | res = = DEAD_OBJECT ) & & mState = = STATE_CONFIGURED ) {
mState = STATE_ABANDONED ;
}
}
status_t Camera3OutputStream : : disconnectLocked ( ) {
@ -803,11 +851,8 @@ status_t Camera3OutputStream::detachBufferLocked(sp<GraphicBuffer>* buffer, int*
}
}
std : : vector < sp < GraphicBuffer > > removedBuffers ;
res = mConsumer - > getAndFlushRemovedBuffers ( & removedBuffers ) ;
if ( res = = OK ) {
onBuffersRemovedLocked ( removedBuffers ) ;
}
// Here we assume detachBuffer is called by buffer manager so it doesn't need to be notified
checkRemovedBuffersLocked ( /*notifyBufferManager*/ false ) ;
return res ;
}