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

Commit 32ddc824 authored by Yin-Chia Yeh's avatar Yin-Chia Yeh Committed by android-build-merger
Browse files

Merge "Camera: use finer lock in external camera OutputThread" into pi-dev

am: aa91a992

Change-Id: I4ebc17f748c287a5416516126f2acfc118ba79f1
parents 34e4532e aa91a992
Loading
Loading
Loading
Loading
+71 −34
Original line number Original line Diff line number Diff line
@@ -51,10 +51,12 @@ constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to
                             // webcam showing temporarily ioctl failures.
                             // webcam showing temporarily ioctl failures.
constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 5 seconds
constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 5 seconds


// Constants for tryLock during dumpstate
static constexpr int kDumpLockRetries = 50;
static constexpr int kDumpLockSleep = 60000;

bool tryLock(Mutex& mutex)
bool tryLock(Mutex& mutex)
{
{
    static const int kDumpLockRetries = 50;
    static const int kDumpLockSleep = 60000;
    bool locked = false;
    bool locked = false;
    for (int i = 0; i < kDumpLockRetries; ++i) {
    for (int i = 0; i < kDumpLockRetries; ++i) {
        if (mutex.tryLock() == NO_ERROR) {
        if (mutex.tryLock() == NO_ERROR) {
@@ -66,6 +68,19 @@ bool tryLock(Mutex& mutex)
    return locked;
    return locked;
}
}


bool tryLock(std::mutex& mutex)
{
    bool locked = false;
    for (int i = 0; i < kDumpLockRetries; ++i) {
        if (mutex.try_lock()) {
            locked = true;
            break;
        }
        usleep(kDumpLockSleep);
    }
    return locked;
}

} // Anonymous namespace
} // Anonymous namespace


// Static instances
// Static instances
@@ -163,7 +178,6 @@ void ExternalCameraDeviceSession::dumpState(const native_handle_t* handle) {
    bool streaming = false;
    bool streaming = false;
    size_t v4L2BufferCount = 0;
    size_t v4L2BufferCount = 0;
    SupportedV4L2Format streamingFmt;
    SupportedV4L2Format streamingFmt;
    std::unordered_set<uint32_t>  inflightFrames;
    {
    {
        bool sessionLocked = tryLock(mLock);
        bool sessionLocked = tryLock(mLock);
        if (!sessionLocked) {
        if (!sessionLocked) {
@@ -172,12 +186,25 @@ void ExternalCameraDeviceSession::dumpState(const native_handle_t* handle) {
        streaming = mV4l2Streaming;
        streaming = mV4l2Streaming;
        streamingFmt = mV4l2StreamingFmt;
        streamingFmt = mV4l2StreamingFmt;
        v4L2BufferCount = mV4L2BufferCount;
        v4L2BufferCount = mV4L2BufferCount;
        inflightFrames = mInflightFrames;

        if (sessionLocked) {
        if (sessionLocked) {
            mLock.unlock();
            mLock.unlock();
        }
        }
    }
    }


    std::unordered_set<uint32_t>  inflightFrames;
    {
        bool iffLocked = tryLock(mInflightFramesLock);
        if (!iffLocked) {
            dprintf(fd,
                    "!! ExternalCameraDeviceSession mInflightFramesLock may be deadlocked !!\n");
        }
        inflightFrames = mInflightFrames;
        if (iffLocked) {
            mInflightFramesLock.unlock();
        }
    }

    dprintf(fd, "External camera %s V4L2 FD %d, cropping type %s, %s\n",
    dprintf(fd, "External camera %s V4L2 FD %d, cropping type %s, %s\n",
            mCameraId.c_str(), mV4l2Fd.get(),
            mCameraId.c_str(), mV4l2Fd.get(),
            (mCroppingType == VERTICAL) ? "vertical" : "horizontal",
            (mCroppingType == VERTICAL) ? "vertical" : "horizontal",
@@ -457,6 +484,7 @@ void ExternalCameraDeviceSession::cleanupInflightFences(
}
}


int ExternalCameraDeviceSession::waitForV4L2BufferReturnLocked(std::unique_lock<std::mutex>& lk) {
int ExternalCameraDeviceSession::waitForV4L2BufferReturnLocked(std::unique_lock<std::mutex>& lk) {
    ATRACE_CALL();
    std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec);
    std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec);
    mLock.unlock();
    mLock.unlock();
    auto st = mV4L2BufferReturned.wait_for(lk, timeout);
    auto st = mV4L2BufferReturned.wait_for(lk, timeout);
@@ -612,7 +640,10 @@ Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureReques
        halBuf.acquireFence = allFences[i];
        halBuf.acquireFence = allFences[i];
        halBuf.fenceTimeout = false;
        halBuf.fenceTimeout = false;
    }
    }
    {
        std::lock_guard<std::mutex> lk(mInflightFramesLock);
        mInflightFrames.insert(halReq->frameNumber);
        mInflightFrames.insert(halReq->frameNumber);
    }
    // Send request to OutputThread for the rest of processing
    // Send request to OutputThread for the rest of processing
    mOutputThread->submitRequest(halReq);
    mOutputThread->submitRequest(halReq);
    mFirstRequest = false;
    mFirstRequest = false;
@@ -670,7 +701,7 @@ Status ExternalCameraDeviceSession::processCaptureRequestError(


    // update inflight records
    // update inflight records
    {
    {
        Mutex::Autolock _l(mLock);
        std::lock_guard<std::mutex> lk(mInflightFramesLock);
        mInflightFrames.erase(req->frameNumber);
        mInflightFrames.erase(req->frameNumber);
    }
    }


@@ -724,7 +755,7 @@ Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptr<HalRequ


    // update inflight records
    // update inflight records
    {
    {
        Mutex::Autolock _l(mLock);
        std::lock_guard<std::mutex> lk(mInflightFramesLock);
        mInflightFrames.erase(req->frameNumber);
        mInflightFrames.erase(req->frameNumber);
    }
    }


@@ -2285,6 +2316,7 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t
        }
        }
    }
    }


    ATRACE_BEGIN("VIDIOC_DQBUF");
    v4l2_buffer buffer{};
    v4l2_buffer buffer{};
    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buffer.memory = V4L2_MEMORY_MMAP;
    buffer.memory = V4L2_MEMORY_MMAP;
@@ -2292,6 +2324,7 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t
        ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno));
        ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno));
        return ret;
        return ret;
    }
    }
    ATRACE_END();


    if (buffer.index >= mV4L2BufferCount) {
    if (buffer.index >= mV4L2BufferCount) {
        ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index);
        ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index);
@@ -2329,11 +2362,8 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t


void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) {
void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) {
    ATRACE_CALL();
    ATRACE_CALL();
    {
        // Release mLock before acquiring mV4l2BufferLock to avoid potential
        // deadlock
        Mutex::Autolock _l(mLock);
    frame->unmap();
    frame->unmap();
    ATRACE_BEGIN("VIDIOC_QBUF");
    v4l2_buffer buffer{};
    v4l2_buffer buffer{};
    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buffer.memory = V4L2_MEMORY_MMAP;
    buffer.memory = V4L2_MEMORY_MMAP;
@@ -2343,7 +2373,7 @@ void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) {
                frame->mBufferIndex, strerror(errno));
                frame->mBufferIndex, strerror(errno));
        return;
        return;
    }
    }
    }
    ATRACE_END();


    {
    {
        std::lock_guard<std::mutex> lk(mV4l2BufferLock);
        std::lock_guard<std::mutex> lk(mV4l2BufferLock);
@@ -2396,13 +2426,17 @@ Status ExternalCameraDeviceSession::configureStreams(
        return status;
        return status;
    }
    }


    Mutex::Autolock _l(mLock);

    {
        std::lock_guard<std::mutex> lk(mInflightFramesLock);
        if (!mInflightFrames.empty()) {
        if (!mInflightFrames.empty()) {
            ALOGE("%s: trying to configureStreams while there are still %zu inflight frames!",
            ALOGE("%s: trying to configureStreams while there are still %zu inflight frames!",
                    __FUNCTION__, mInflightFrames.size());
                    __FUNCTION__, mInflightFrames.size());
            return Status::INTERNAL_ERROR;
            return Status::INTERNAL_ERROR;
        }
        }
    }


    Mutex::Autolock _l(mLock);
    // Add new streams
    // Add new streams
    for (const auto& stream : config.streams) {
    for (const auto& stream : config.streams) {
        if (mStreamMap.count(stream.id) == 0) {
        if (mStreamMap.count(stream.id) == 0) {
@@ -2702,9 +2736,11 @@ status_t ExternalCameraDeviceSession::fillCaptureResult(
    const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;
    const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;
    UPDATE(md, ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);
    UPDATE(md, ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);


    bool afTrigger = mAfTrigger;
    bool afTrigger = false;
    {
        std::lock_guard<std::mutex> lk(mAfTriggerLock);
        afTrigger = mAfTrigger;
        if (md.exists(ANDROID_CONTROL_AF_TRIGGER)) {
        if (md.exists(ANDROID_CONTROL_AF_TRIGGER)) {
        Mutex::Autolock _l(mLock);
            camera_metadata_entry entry = md.find(ANDROID_CONTROL_AF_TRIGGER);
            camera_metadata_entry entry = md.find(ANDROID_CONTROL_AF_TRIGGER);
            if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) {
            if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) {
                mAfTrigger = afTrigger = true;
                mAfTrigger = afTrigger = true;
@@ -2712,6 +2748,7 @@ status_t ExternalCameraDeviceSession::fillCaptureResult(
                mAfTrigger = afTrigger = false;
                mAfTrigger = afTrigger = false;
            }
            }
        }
        }
    }


    // For USB camera, the USB camera handles everything and we don't have control
    // For USB camera, the USB camera handles everything and we don't have control
    // over AF. We only simply fake the AF metadata based on the request
    // over AF. We only simply fake the AF metadata based on the request
+6 −0
Original line number Original line Diff line number Diff line
@@ -300,6 +300,9 @@ protected:
    const std::vector<SupportedV4L2Format> mSupportedFormats;
    const std::vector<SupportedV4L2Format> mSupportedFormats;
    const CroppingType mCroppingType;
    const CroppingType mCroppingType;
    const std::string& mCameraId;
    const std::string& mCameraId;

    // Not protected by mLock, this is almost a const.
    // Setup in constructor, reset in close() after OutputThread is joined
    unique_fd mV4l2Fd;
    unique_fd mV4l2Fd;


    // device is closed either
    // device is closed either
@@ -327,6 +330,8 @@ protected:


    // Stream ID -> Camera3Stream cache
    // Stream ID -> Camera3Stream cache
    std::unordered_map<int, Stream> mStreamMap;
    std::unordered_map<int, Stream> mStreamMap;

    std::mutex mInflightFramesLock; // protect mInflightFrames
    std::unordered_set<uint32_t>  mInflightFrames;
    std::unordered_set<uint32_t>  mInflightFrames;


    // buffers currently circulating between HAL and camera service
    // buffers currently circulating between HAL and camera service
@@ -338,6 +343,7 @@ protected:
    // Stream ID -> circulating buffers map
    // Stream ID -> circulating buffers map
    std::map<int, CirculatingBuffers> mCirculatingBuffers;
    std::map<int, CirculatingBuffers> mCirculatingBuffers;


    std::mutex mAfTriggerLock; // protect mAfTrigger
    bool mAfTrigger = false;
    bool mAfTrigger = false;


    static HandleImporter sHandleImporter;
    static HandleImporter sHandleImporter;