Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2eddd660 authored by Eino-Ville Talvala's avatar Eino-Ville Talvala Committed by android-build-merger
Browse files

Merge "Camera3Device: Don't time out on long exposures" into oc-dr1-dev

am: 57cd4032

Change-Id: I494687696489d9e5ab57bd420dc6fb594bb392e7
parents 9fc83c5c 57cd4032
Loading
Loading
Loading
Loading
+66 −10
Original line number Diff line number Diff line
@@ -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
                }
            }
@@ -309,6 +311,7 @@ status_t Camera3Device::disconnect() {

    {
        Mutex::Autolock l(mLock);
        mExpectedInflightDuration = 0;
        mInterface->clear();
        mOutputStreams.clear();
        mInputStream.clear();
@@ -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);
@@ -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;
@@ -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) {
@@ -2369,6 +2377,9 @@ status_t Camera3Device::registerInFlight(uint32_t frameNumber,
        }
    }

    Mutex::Autolock ml(mLock);
    mExpectedInflightDuration += maxExpectedDuration;

    return OK;
}

@@ -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
@@ -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) {
@@ -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;
@@ -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__,
@@ -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;
+23 −5
Original line number Diff line number Diff line
@@ -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;

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