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

Commit 98be7e0f authored by Zhijun He's avatar Zhijun He Committed by The Android Automerger
Browse files

camera2/3: Fix deadlock take picture while preview callback

Acquiring mInputMutex before SharedParameters mutex in preview callback thread
causes circular locking dependency between callback thread and capture callback
thread.
Enforce the right lock ordering to break the dead lock.

Bug: 9323319
Change-Id: Iea2e025e4d9e29debcf74297c19930075017e179
parent e10dc92d
Loading
Loading
Loading
Loading
+88 −87
Original line number Diff line number Diff line
@@ -182,13 +182,6 @@ bool CallbackProcessor::threadLoop() {
    }

    do {
        Mutex::Autolock l(mInputMutex);
        if (mCallbackStreamId == NO_STREAM) {
            ALOGV("%s: Camera %d:No stream is available"
                    , __FUNCTION__, mId);
            break;
        }

        sp<Camera2Client> client = mClient.promote();
        if (client == 0) {
            res = discardNewCallback();
@@ -221,9 +214,22 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
    status_t res;

    sp<Camera2Heap> callbackHeap;
    bool useFlexibleYuv = false;
    int32_t previewFormat = 0;
    size_t heapIdx;

    {
        /* acquire SharedParameters before mMutex so we don't dead lock
            with Camera2Client code calling into StreamingProcessor */
        SharedParameters::Lock l(client->getParameters());
        Mutex::Autolock m(mInputMutex);
        CpuConsumer::LockedBuffer imgBuffer;
        if (mCallbackStreamId == NO_STREAM) {
            ALOGV("%s: Camera %d:No stream is available"
                    , __FUNCTION__, mId);
            return INVALID_OPERATION;
        }

        ALOGV("%s: Getting buffer", __FUNCTION__);
        res = mCallbackConsumer->lockNextBuffer(&imgBuffer);
        if (res != OK) {
@@ -236,11 +242,6 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
        ALOGV("%s: Camera %d: Preview callback available", __FUNCTION__,
                mId);

    bool useFlexibleYuv = false;
    int32_t previewFormat = 0;
    {
        SharedParameters::Lock l(client->getParameters());

        if ( l.mParameters.state != Parameters::PREVIEW
                && l.mParameters.state != Parameters::RECORD
                && l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
@@ -286,7 +287,6 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
            ALOGV("%s: clearing oneshot", __FUNCTION__);
            l.mParameters.previewCallbackOneShot = false;
        }
    }

        uint32_t destYStride = 0;
        uint32_t destCStride = 0;
@@ -365,6 +365,7 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {

        ALOGV("%s: Freeing buffer", __FUNCTION__);
        mCallbackConsumer->unlockBuffer(imgBuffer);
    }

    // Call outside parameter lock to allow re-entrancy from notification
    {