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

Commit f81b009d authored by Zhijun He's avatar Zhijun He Committed by Eino-Ville Talvala
Browse files

Camera3: don't let dequeueBuffer block indefinitely

The synchronous consumers (e.g. ImageReader) may be very slow when the
clients have computational intensive image processings. When system
load is high, these processing will be even much slower. This could
starve the producer side and then cause dequeue/attach buffer block
indefinitely. If clients intends to close the capture session, right
after a capture request is submitted, the waitUntil drain could be
blocked indefinitely if the capture request dequeue buffer call is
blocked indefinitely, as the request thread will never become idle until
the last dequeue buffer is done and the request is sent.This indefinite
getBuffer() blocking could easily trigger the waitUntilDrained 5s timeout
thus put the camera device into error state although there is nothing
bad happening in the HAL.

Introducing the timeout will avoid such bad situation. When consumer is
slow, there will be no new request being sent to HAL, as there is really
no new buffer available.

Bug:30404840
Change-Id: Ibf08d2745911203bce6f31130800707f36d7f985
parent bcd87f59
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3052,7 +3052,7 @@ bool Camera3Device::RequestThread::threadLoop() {
        mFlushLock.lock();
    }

    ALOGVV("%s: %d: submitting %d requests in a batch.", __FUNCTION__, __LINE__,
    ALOGVV("%s: %d: submitting %zu requests in a batch.", __FUNCTION__, __LINE__,
            mNextRequests.size());
    for (auto& nextRequest : mNextRequests) {
        // Submit request and block until ready for next one
+17 −0
Original line number Diff line number Diff line
@@ -435,6 +435,12 @@ status_t Camera3OutputStream::configureQueueLocked() {
                __FUNCTION__, mTransform, strerror(-res), res);
    }

    // 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);
    }

    /**
     * Camera3 Buffer manager is only supported by HAL3.3 onwards, as the older HALs requires
     * buffers to be statically allocated for internal static buffer registration, while the
@@ -633,6 +639,17 @@ bool Camera3OutputStream::isConsumedByHWComposer() const {
    return (usage & GRALLOC_USAGE_HW_COMPOSER) != 0;
}

bool Camera3OutputStream::isConsumedByHWTexture() const {
    uint32_t usage = 0;
    status_t res = getEndpointUsage(&usage);
    if (res != OK) {
        ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res);
        return false;
    }

    return (usage & GRALLOC_USAGE_HW_TEXTURE) != 0;
}

}; // namespace camera3

}; // namespace android
+8 −0
Original line number Diff line number Diff line
@@ -117,6 +117,11 @@ class Camera3OutputStream :
     */
    bool isConsumedByHWComposer() const;

    /**
     * Return if this output stream is consumed by hardware texture.
     */
    bool isConsumedByHWTexture() const;

    class BufferReleasedListener : public BnProducerListener {
        public:
          BufferReleasedListener(wp<Camera3OutputStream> parent) : mParent(parent) {}
@@ -160,6 +165,9 @@ class Camera3OutputStream :

    sp<Surface> mConsumer;
  private:

    static const nsecs_t       kDequeueBufferTimeout   = 1000000000; // 1 sec

    int               mTransform;

    virtual status_t  setTransformLocked(int transform);