@ -364,100 +364,103 @@ status_t Camera3Device::disconnect() {
status_t Camera3Device : : disconnectImpl ( ) {
status_t Camera3Device : : disconnectImpl ( ) {
ATRACE_CALL ( ) ;
ATRACE_CALL ( ) ;
Mutex : : Autolock il ( mInterfaceLock ) ;
ALOGI ( " %s: E " , __FUNCTION__ ) ;
ALOGI ( " %s: E " , __FUNCTION__ ) ;
status_t res = OK ;
status_t res = OK ;
std : : vector < wp < Camera3StreamInterface > > streams ;
std : : vector < wp < Camera3StreamInterface > > streams ;
nsecs_t maxExpectedDuration = getExpectedInFlightDuration ( ) ;
{
{
Mutex : : Autolock l ( mLock ) ;
Mutex : : Autolock il ( mInterfaceLock ) ;
if ( mStatus = = STATUS_UNINITIALIZED ) return res ;
nsecs_t maxExpectedDuration = getExpectedInFlightDuration ( ) ;
{
Mutex : : Autolock l ( mLock ) ;
if ( mStatus = = STATUS_UNINITIALIZED ) return res ;
if ( mStatus = = STATUS_ACTIVE | |
if ( mStatus = = STATUS_ACTIVE | |
( mStatus = = STATUS_ERROR & & mRequestThread ! = NULL ) ) {
( mStatus = = STATUS_ERROR & & mRequestThread ! = NULL ) ) {
res = mRequestThread - > clearRepeatingRequests ( ) ;
res = mRequestThread - > clearRepeatingRequests ( ) ;
if ( res ! = OK ) {
SET_ERR_L ( " Can't stop streaming " ) ;
// Continue to close device even in case of error
} else {
res = waitUntilStateThenRelock ( /*active*/ false , maxExpectedDuration ) ;
if ( res ! = OK ) {
if ( res ! = OK ) {
SET_ERR_L ( " Timeout waiting for HAL to drain (% " PRIi64 " ns) " ,
SET_ERR_L ( " Can't stop streaming " ) ;
maxExpectedDuration ) ;
// Continue to close device even in case of error
// Continue to close device even in case of error
} else {
res = waitUntilStateThenRelock ( /*active*/ false , maxExpectedDuration ) ;
if ( res ! = OK ) {
SET_ERR_L ( " Timeout waiting for HAL to drain (% " PRIi64 " ns) " ,
maxExpectedDuration ) ;
// Continue to close device even in case of error
}
}
}
}
}
}
if ( mStatus = = STATUS_ERROR ) {
if ( mStatus = = STATUS_ERROR ) {
CLOGE ( " Shutting down in an error state " ) ;
CLOGE ( " Shutting down in an error state " ) ;
}
}
if ( mStatusTracker ! = NULL ) {
if ( mStatusTracker ! = NULL ) {
mStatusTracker - > requestExit ( ) ;
mStatusTracker - > requestExit ( ) ;
}
}
if ( mRequestThread ! = NULL ) {
if ( mRequestThread ! = NULL ) {
mRequestThread - > requestExit ( ) ;
mRequestThread - > requestExit ( ) ;
}
}
streams . reserve ( mOutputStreams . size ( ) + ( mInputStream ! = nullptr ? 1 : 0 ) ) ;
streams . reserve ( mOutputStreams . size ( ) + ( mInputStream ! = nullptr ? 1 : 0 ) ) ;
for ( size_t i = 0 ; i < mOutputStreams . size ( ) ; i + + ) {
for ( size_t i = 0 ; i < mOutputStreams . size ( ) ; i + + ) {
streams . push_back ( mOutputStreams [ i ] ) ;
streams . push_back ( mOutputStreams [ i ] ) ;
}
}
if ( mInputStream ! = nullptr ) {
if ( mInputStream ! = nullptr ) {
streams . push_back ( mInputStream ) ;
streams . push_back ( mInputStream ) ;
}
}
}
}
}
// Joining done without holding mLock and mInterfaceLock, otherwise deadlocks may ensue
// Joining done without holding mLock, otherwise deadlocks may ensue
// as the threads try to access parent state (b/143513518)
// as the threads try to access parent state
if ( mRequestThread ! = NULL & & mStatus ! = STATUS_ERROR ) {
if ( mRequestThread ! = NULL & & mStatus ! = STATUS_ERROR ) {
// HAL may be in a bad state, so waiting for request thread
// HAL may be in a bad state, so waiting for request thread
// (which may be stuck in the HAL processCaptureRequest call)
// (which may be stuck in the HAL processCaptureRequest call)
// could be dangerous.
// could be dangerous.
// give up mInterfaceLock here and then lock it again. Could this lead
// to other deadlocks
mRequestThread - > join ( ) ;
mRequestThread - > join ( ) ;
}
}
if ( mStatusTracker ! = NULL ) {
mStatusTracker - > join ( ) ;
}
HalInterface * interface ;
{
{
Mutex : : Autolock l ( mLock ) ;
Mutex : : Autolock il ( mInterfaceLock ) ;
mRequestThread . clear ( ) ;
if ( mStatusTracker ! = NULL ) {
Mutex : : Autolock stLock ( mTrackerLock ) ;
mStatusTracker - > join ( ) ;
mStatusTracker . clear ( ) ;
}
interface = mInterface . get ( ) ;
}
// Call close without internal mutex held, as the HAL close may need to
HalInterface * interface ;
// wait on assorted callbacks,etc, to complete before it can return.
{
interface - > close ( ) ;
Mutex : : Autolock l ( mLock ) ;
mRequestThread . clear ( ) ;
Mutex : : Autolock stLock ( mTrackerLock ) ;
mStatusTracker . clear ( ) ;
interface = mInterface . get ( ) ;
}
flushInflightRequests ( ) ;
// Call close without internal mutex held, as the HAL close may need to
// wait on assorted callbacks,etc, to complete before it can return.
interface - > close ( ) ;
{
flushInflightRequests ( ) ;
Mutex : : Autolock l ( mLock ) ;
mInterface - > clear ( ) ;
mOutputStreams . clear ( ) ;
mInputStream . clear ( ) ;
mDeletedStreams . clear ( ) ;
mBufferManager . clear ( ) ;
internalUpdateStatusLocked ( STATUS_UNINITIALIZED ) ;
}
for ( auto & weakStream : streams ) {
{
sp < Camera3StreamInterface > stream = weakStream . promote ( ) ;
Mutex : : Autolock l ( mLock ) ;
if ( stream ! = nullptr ) {
mInterface - > clear ( ) ;
ALOGE ( " %s: Stream %d leaked! strong reference (%d)! " ,
mOutputStreams . clear ( ) ;
__FUNCTION__ , stream - > getId ( ) , stream - > getStrongCount ( ) - 1 ) ;
mInputStream . clear ( ) ;
mDeletedStreams . clear ( ) ;
mBufferManager . clear ( ) ;
internalUpdateStatusLocked ( STATUS_UNINITIALIZED ) ;
}
}
}
for ( auto & weakStream : streams ) {
sp < Camera3StreamInterface > stream = weakStream . promote ( ) ;
if ( stream ! = nullptr ) {
ALOGE ( " %s: Stream %d leaked! strong reference (%d)! " ,
__FUNCTION__ , stream - > getId ( ) , stream - > getStrongCount ( ) - 1 ) ;
}
}
}
ALOGI ( " %s: X " , __FUNCTION__ ) ;
ALOGI ( " %s: X " , __FUNCTION__ ) ;
return res ;
return res ;
}
}
@ -1768,9 +1771,7 @@ void Camera3Device::internalUpdateStatusLocked(Status status) {
}
}
void Camera3Device : : pauseStateNotify ( bool enable ) {
void Camera3Device : : pauseStateNotify ( bool enable ) {
// We must not hold mInterfaceLock here since this function is called from
Mutex : : Autolock il ( mInterfaceLock ) ;
// RequestThread::threadLoop and holding mInterfaceLock could lead to
// deadlocks (http://b/143513518)
Mutex : : Autolock l ( mLock ) ;
Mutex : : Autolock l ( mLock ) ;
mPauseStateNotify = enable ;
mPauseStateNotify = enable ;
@ -2340,9 +2341,7 @@ bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams) {
ATRACE_CALL ( ) ;
ATRACE_CALL ( ) ;
bool ret = false ;
bool ret = false ;
// We must not hold mInterfaceLock here since this function is called from
Mutex : : Autolock il ( mInterfaceLock ) ;
// RequestThread::threadLoop and holding mInterfaceLock could lead to
// deadlocks (http://b/143513518)
nsecs_t maxExpectedDuration = getExpectedInFlightDuration ( ) ;
nsecs_t maxExpectedDuration = getExpectedInFlightDuration ( ) ;
Mutex : : Autolock l ( mLock ) ;
Mutex : : Autolock l ( mLock ) ;