|
|
@ -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);
|
|
|
|