Loading services/camera/libcameraservice/device3/Camera3Device.cpp +66 −10 Original line number Diff line number Diff line Loading @@ -251,9 +251,11 @@ status_t Camera3Device::disconnect() { SET_ERR_L("Can't stop streaming"); // Continue to close device even in case of error } else { res = waitUntilStateThenRelock(/*active*/ false, kShutdownTimeout); nsecs_t maxExpectedDuration = getExpectedInFlightDurationLocked(); res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration); if (res != OK) { SET_ERR_L("Timeout waiting for HAL to drain"); SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)", maxExpectedDuration); // Continue to close device even in case of error } } Loading Loading @@ -309,6 +311,7 @@ status_t Camera3Device::disconnect() { { Mutex::Autolock l(mLock); mExpectedInflightDuration = 0; mInterface->clear(); mOutputStreams.clear(); mInputStream.clear(); Loading Loading @@ -1560,8 +1563,11 @@ status_t Camera3Device::waitUntilDrainedLocked() { return INVALID_OPERATION; } ALOGV("%s: Camera %s: Waiting until idle", __FUNCTION__, mId.string()); status_t res = waitUntilStateThenRelock(/*active*/ false, kShutdownTimeout); nsecs_t maxExpectedDuration = getExpectedInFlightDurationLocked(); ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.string(), maxExpectedDuration); status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration); if (res != OK) { SET_ERR_L("Error waiting for HAL to drain: %s (%d)", strerror(-res), res); Loading @@ -1581,11 +1587,13 @@ status_t Camera3Device::internalPauseAndWaitLocked() { mRequestThread->setPaused(true); mPauseStateNotify = true; ALOGV("%s: Camera %s: Internal wait until idle", __FUNCTION__, mId.string()); status_t res = waitUntilStateThenRelock(/*active*/ false, kShutdownTimeout); nsecs_t maxExpectedDuration = getExpectedInFlightDurationLocked(); ALOGV("%s: Camera %s: Internal wait until idle (% " PRIi64 " ns)", __FUNCTION__, mId.string(), maxExpectedDuration); status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration); if (res != OK) { SET_ERR_L("Can't idle device in %f seconds!", kShutdownTimeout/1e9); maxExpectedDuration/1e9); } return res; Loading Loading @@ -2352,13 +2360,13 @@ void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) { status_t Camera3Device::registerInFlight(uint32_t frameNumber, int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput, bool hasAppCallback) { bool hasAppCallback, nsecs_t maxExpectedDuration) { ATRACE_CALL(); Mutex::Autolock l(mInFlightLock); ssize_t res; res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput, hasAppCallback)); hasAppCallback, maxExpectedDuration)); if (res < 0) return res; if (mInFlightMap.size() == 1) { Loading @@ -2369,6 +2377,9 @@ status_t Camera3Device::registerInFlight(uint32_t frameNumber, } } Mutex::Autolock ml(mLock); mExpectedInflightDuration += maxExpectedDuration; return OK; } Loading @@ -2389,6 +2400,7 @@ void Camera3Device::returnOutputBuffers( } void Camera3Device::removeInFlightMapEntryLocked(int idx) { nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration; mInFlightMap.removeItemsAt(idx, 1); // Indicate idle inFlightMap to the status tracker Loading @@ -2399,6 +2411,8 @@ void Camera3Device::removeInFlightMapEntryLocked(int idx) { mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE); } } Mutex::Autolock l(mLock); mExpectedInflightDuration -= duration; } void Camera3Device::removeInFlightRequestIfReadyLocked(int idx) { Loading Loading @@ -3918,6 +3932,42 @@ bool Camera3Device::RequestThread::sendRequestsOneByOne() { return true; } nsecs_t Camera3Device::RequestThread::calculateMaxExpectedDuration(const camera_metadata_t *request) { nsecs_t maxExpectedDuration = kDefaultExpectedDuration; camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t(); find_camera_metadata_ro_entry(request, ANDROID_CONTROL_AE_MODE, &e); if (e.count == 0) return maxExpectedDuration; switch (e.data.u8[0]) { case ANDROID_CONTROL_AE_MODE_OFF: find_camera_metadata_ro_entry(request, ANDROID_SENSOR_EXPOSURE_TIME, &e); if (e.count > 0) { maxExpectedDuration = e.data.i64[0]; } find_camera_metadata_ro_entry(request, ANDROID_SENSOR_FRAME_DURATION, &e); if (e.count > 0) { maxExpectedDuration = std::max(e.data.i64[0], maxExpectedDuration); } break; default: find_camera_metadata_ro_entry(request, ANDROID_CONTROL_AE_TARGET_FPS_RANGE, &e); if (e.count > 1) { maxExpectedDuration = 1e9 / e.data.u8[0]; } break; } return maxExpectedDuration; } bool Camera3Device::RequestThread::threadLoop() { ATRACE_CALL(); status_t res; Loading Loading @@ -4138,7 +4188,8 @@ status_t Camera3Device::RequestThread::prepareHalRequests() { res = parent->registerInFlight(halRequest->frame_number, totalNumBuffers, captureRequest->mResultExtras, /*hasInput*/halRequest->input_buffer != NULL, hasCallback); hasCallback, calculateMaxExpectedDuration(halRequest->settings)); ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64 ", burstId = %" PRId32 ".", __FUNCTION__, Loading Loading @@ -4192,6 +4243,11 @@ bool Camera3Device::RequestThread::isStreamPending( return false; } nsecs_t Camera3Device::getExpectedInFlightDurationLocked() { return mExpectedInflightDuration > kMinInflightDuration ? mExpectedInflightDuration : kMinInflightDuration; } void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) { if (mNextRequests.empty()) { return; Loading services/camera/libcameraservice/device3/Camera3Device.h +23 −5 Original line number Diff line number Diff line Loading @@ -187,10 +187,11 @@ class Camera3Device : static const size_t kDumpLockAttempts = 10; static const size_t kDumpSleepDuration = 100000; // 0.10 sec static const nsecs_t kShutdownTimeout = 5000000000; // 5 sec static const nsecs_t kActiveTimeout = 500000000; // 500 ms static const size_t kInFlightWarnLimit = 30; static const size_t kInFlightWarnLimitHighSpeed = 256; // batch size 32 * pipe depth 8 static const nsecs_t kDefaultExpectedDuration = 100000000; // 100 ms static const nsecs_t kMinInflightDuration = 5000000000; // 5 s // SCHED_FIFO priority for request submission thread in HFR mode static const int kRequestThreadPriority = 1; Loading Loading @@ -776,6 +777,9 @@ class Camera3Device : // send request in mNextRequests to HAL in a batch. Return true = sucssess bool sendRequestsBatch(); // Calculate the expected maximum duration for a request nsecs_t calculateMaxExpectedDuration(const camera_metadata_t *request); wp<Camera3Device> mParent; wp<camera3::StatusTracker> mStatusTracker; sp<HalInterface> mInterface; Loading Loading @@ -877,6 +881,11 @@ class Camera3Device : // is not for constrained high speed recording, this flag will also be true. bool hasCallback; // Maximum expected frame duration for this request. // For manual captures, equal to the max of requested exposure time and frame duration // For auto-exposure modes, equal to 1/(lower end of target FPS range) nsecs_t maxExpectedDuration; // Default constructor needed by KeyedVector InFlightRequest() : shutterTimestamp(0), Loading @@ -885,11 +894,12 @@ class Camera3Device : haveResultMetadata(false), numBuffersLeft(0), hasInputBuffer(false), hasCallback(true) { hasCallback(true), maxExpectedDuration(kDefaultExpectedDuration) { } InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput, bool hasAppCallback) : bool hasAppCallback, nsecs_t maxDuration) : shutterTimestamp(0), sensorTimestamp(0), requestStatus(OK), Loading @@ -897,20 +907,28 @@ class Camera3Device : numBuffersLeft(numBuffers), resultExtras(extras), hasInputBuffer(hasInput), hasCallback(hasAppCallback) { hasCallback(hasAppCallback), maxExpectedDuration(maxDuration) { } }; // Map from frame number to the in-flight request state typedef KeyedVector<uint32_t, InFlightRequest> InFlightMap; nsecs_t mExpectedInflightDuration = 0; Mutex mInFlightLock; // Protects mInFlightMap InFlightMap mInFlightMap; int mInFlightStatusId; status_t registerInFlight(uint32_t frameNumber, int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput, bool callback); bool callback, nsecs_t maxExpectedDuration); /** * Returns the maximum expected time it'll take for all currently in-flight * requests to complete, based on their settings */ nsecs_t getExpectedInFlightDurationLocked(); /** * Tracking for idle detection Loading Loading
services/camera/libcameraservice/device3/Camera3Device.cpp +66 −10 Original line number Diff line number Diff line Loading @@ -251,9 +251,11 @@ status_t Camera3Device::disconnect() { SET_ERR_L("Can't stop streaming"); // Continue to close device even in case of error } else { res = waitUntilStateThenRelock(/*active*/ false, kShutdownTimeout); nsecs_t maxExpectedDuration = getExpectedInFlightDurationLocked(); res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration); if (res != OK) { SET_ERR_L("Timeout waiting for HAL to drain"); SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)", maxExpectedDuration); // Continue to close device even in case of error } } Loading Loading @@ -309,6 +311,7 @@ status_t Camera3Device::disconnect() { { Mutex::Autolock l(mLock); mExpectedInflightDuration = 0; mInterface->clear(); mOutputStreams.clear(); mInputStream.clear(); Loading Loading @@ -1560,8 +1563,11 @@ status_t Camera3Device::waitUntilDrainedLocked() { return INVALID_OPERATION; } ALOGV("%s: Camera %s: Waiting until idle", __FUNCTION__, mId.string()); status_t res = waitUntilStateThenRelock(/*active*/ false, kShutdownTimeout); nsecs_t maxExpectedDuration = getExpectedInFlightDurationLocked(); ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.string(), maxExpectedDuration); status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration); if (res != OK) { SET_ERR_L("Error waiting for HAL to drain: %s (%d)", strerror(-res), res); Loading @@ -1581,11 +1587,13 @@ status_t Camera3Device::internalPauseAndWaitLocked() { mRequestThread->setPaused(true); mPauseStateNotify = true; ALOGV("%s: Camera %s: Internal wait until idle", __FUNCTION__, mId.string()); status_t res = waitUntilStateThenRelock(/*active*/ false, kShutdownTimeout); nsecs_t maxExpectedDuration = getExpectedInFlightDurationLocked(); ALOGV("%s: Camera %s: Internal wait until idle (% " PRIi64 " ns)", __FUNCTION__, mId.string(), maxExpectedDuration); status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration); if (res != OK) { SET_ERR_L("Can't idle device in %f seconds!", kShutdownTimeout/1e9); maxExpectedDuration/1e9); } return res; Loading Loading @@ -2352,13 +2360,13 @@ void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) { status_t Camera3Device::registerInFlight(uint32_t frameNumber, int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput, bool hasAppCallback) { bool hasAppCallback, nsecs_t maxExpectedDuration) { ATRACE_CALL(); Mutex::Autolock l(mInFlightLock); ssize_t res; res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput, hasAppCallback)); hasAppCallback, maxExpectedDuration)); if (res < 0) return res; if (mInFlightMap.size() == 1) { Loading @@ -2369,6 +2377,9 @@ status_t Camera3Device::registerInFlight(uint32_t frameNumber, } } Mutex::Autolock ml(mLock); mExpectedInflightDuration += maxExpectedDuration; return OK; } Loading @@ -2389,6 +2400,7 @@ void Camera3Device::returnOutputBuffers( } void Camera3Device::removeInFlightMapEntryLocked(int idx) { nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration; mInFlightMap.removeItemsAt(idx, 1); // Indicate idle inFlightMap to the status tracker Loading @@ -2399,6 +2411,8 @@ void Camera3Device::removeInFlightMapEntryLocked(int idx) { mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE); } } Mutex::Autolock l(mLock); mExpectedInflightDuration -= duration; } void Camera3Device::removeInFlightRequestIfReadyLocked(int idx) { Loading Loading @@ -3918,6 +3932,42 @@ bool Camera3Device::RequestThread::sendRequestsOneByOne() { return true; } nsecs_t Camera3Device::RequestThread::calculateMaxExpectedDuration(const camera_metadata_t *request) { nsecs_t maxExpectedDuration = kDefaultExpectedDuration; camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t(); find_camera_metadata_ro_entry(request, ANDROID_CONTROL_AE_MODE, &e); if (e.count == 0) return maxExpectedDuration; switch (e.data.u8[0]) { case ANDROID_CONTROL_AE_MODE_OFF: find_camera_metadata_ro_entry(request, ANDROID_SENSOR_EXPOSURE_TIME, &e); if (e.count > 0) { maxExpectedDuration = e.data.i64[0]; } find_camera_metadata_ro_entry(request, ANDROID_SENSOR_FRAME_DURATION, &e); if (e.count > 0) { maxExpectedDuration = std::max(e.data.i64[0], maxExpectedDuration); } break; default: find_camera_metadata_ro_entry(request, ANDROID_CONTROL_AE_TARGET_FPS_RANGE, &e); if (e.count > 1) { maxExpectedDuration = 1e9 / e.data.u8[0]; } break; } return maxExpectedDuration; } bool Camera3Device::RequestThread::threadLoop() { ATRACE_CALL(); status_t res; Loading Loading @@ -4138,7 +4188,8 @@ status_t Camera3Device::RequestThread::prepareHalRequests() { res = parent->registerInFlight(halRequest->frame_number, totalNumBuffers, captureRequest->mResultExtras, /*hasInput*/halRequest->input_buffer != NULL, hasCallback); hasCallback, calculateMaxExpectedDuration(halRequest->settings)); ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64 ", burstId = %" PRId32 ".", __FUNCTION__, Loading Loading @@ -4192,6 +4243,11 @@ bool Camera3Device::RequestThread::isStreamPending( return false; } nsecs_t Camera3Device::getExpectedInFlightDurationLocked() { return mExpectedInflightDuration > kMinInflightDuration ? mExpectedInflightDuration : kMinInflightDuration; } void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) { if (mNextRequests.empty()) { return; Loading
services/camera/libcameraservice/device3/Camera3Device.h +23 −5 Original line number Diff line number Diff line Loading @@ -187,10 +187,11 @@ class Camera3Device : static const size_t kDumpLockAttempts = 10; static const size_t kDumpSleepDuration = 100000; // 0.10 sec static const nsecs_t kShutdownTimeout = 5000000000; // 5 sec static const nsecs_t kActiveTimeout = 500000000; // 500 ms static const size_t kInFlightWarnLimit = 30; static const size_t kInFlightWarnLimitHighSpeed = 256; // batch size 32 * pipe depth 8 static const nsecs_t kDefaultExpectedDuration = 100000000; // 100 ms static const nsecs_t kMinInflightDuration = 5000000000; // 5 s // SCHED_FIFO priority for request submission thread in HFR mode static const int kRequestThreadPriority = 1; Loading Loading @@ -776,6 +777,9 @@ class Camera3Device : // send request in mNextRequests to HAL in a batch. Return true = sucssess bool sendRequestsBatch(); // Calculate the expected maximum duration for a request nsecs_t calculateMaxExpectedDuration(const camera_metadata_t *request); wp<Camera3Device> mParent; wp<camera3::StatusTracker> mStatusTracker; sp<HalInterface> mInterface; Loading Loading @@ -877,6 +881,11 @@ class Camera3Device : // is not for constrained high speed recording, this flag will also be true. bool hasCallback; // Maximum expected frame duration for this request. // For manual captures, equal to the max of requested exposure time and frame duration // For auto-exposure modes, equal to 1/(lower end of target FPS range) nsecs_t maxExpectedDuration; // Default constructor needed by KeyedVector InFlightRequest() : shutterTimestamp(0), Loading @@ -885,11 +894,12 @@ class Camera3Device : haveResultMetadata(false), numBuffersLeft(0), hasInputBuffer(false), hasCallback(true) { hasCallback(true), maxExpectedDuration(kDefaultExpectedDuration) { } InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput, bool hasAppCallback) : bool hasAppCallback, nsecs_t maxDuration) : shutterTimestamp(0), sensorTimestamp(0), requestStatus(OK), Loading @@ -897,20 +907,28 @@ class Camera3Device : numBuffersLeft(numBuffers), resultExtras(extras), hasInputBuffer(hasInput), hasCallback(hasAppCallback) { hasCallback(hasAppCallback), maxExpectedDuration(maxDuration) { } }; // Map from frame number to the in-flight request state typedef KeyedVector<uint32_t, InFlightRequest> InFlightMap; nsecs_t mExpectedInflightDuration = 0; Mutex mInFlightLock; // Protects mInFlightMap InFlightMap mInFlightMap; int mInFlightStatusId; status_t registerInFlight(uint32_t frameNumber, int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput, bool callback); bool callback, nsecs_t maxExpectedDuration); /** * Returns the maximum expected time it'll take for all currently in-flight * requests to complete, based on their settings */ nsecs_t getExpectedInFlightDurationLocked(); /** * Tracking for idle detection Loading