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

Commit 46910bdc authored by Eino-Ville Talvala's avatar Eino-Ville Talvala
Browse files

Camera2/3: Fix deadlock when starting recording before preview.

Move 3A notification synthesis for HAL3 devices from
Camera3Device::processCaptureResult to Camera2Client's
FrameProcessor. This will ensure that calls to processCaptureResult
from HAL can never block on Camera2Client internal mutexes.

Bug: 9923891
Change-Id: I5184649bf45c0807babe6b8c0e1239e959cd3480
parent a2520db0
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -445,6 +445,10 @@ status_t Camera2Device::setNotifyCallback(NotificationListener *listener) {
    return res;
}

bool Camera2Device::willNotify3A() {
    return true;
}

void Camera2Device::notificationCallback(int32_t msg_type,
        int32_t ext1,
        int32_t ext2,
+1 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ class Camera2Device: public CameraDeviceBase {
    virtual status_t createDefaultRequest(int templateId, CameraMetadata *request);
    virtual status_t waitUntilDrained();
    virtual status_t setNotifyCallback(NotificationListener *listener);
    virtual bool     willNotify3A();
    virtual status_t waitForNextFrame(nsecs_t timeout);
    virtual status_t getNextFrame(CameraMetadata *frame);
    virtual status_t triggerAutofocus(uint32_t id);
+7 −77
Original line number Diff line number Diff line
@@ -837,6 +837,10 @@ status_t Camera3Device::setNotifyCallback(NotificationListener *listener) {
    return OK;
}

bool Camera3Device::willNotify3A() {
    return false;
}

status_t Camera3Device::waitForNextFrame(nsecs_t timeout) {
    ATRACE_CALL();
    status_t res;
@@ -1235,13 +1239,6 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {

    }

    AlgState cur3aState;
    AlgState new3aState;
    int32_t aeTriggerId = 0;
    int32_t afTriggerId = 0;

    NotificationListener *listener = NULL;

    // Process the result metadata, if provided
    if (result->result != NULL) {
        Mutex::Autolock l(mOutputLock);
@@ -1280,59 +1277,6 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
                    " metadata for frame %d (%lld vs %lld respectively)",
                    frameNumber, timestamp, entry.data.i64[0]);
        }

        // Get 3A states from result metadata

        entry = captureResult.find(ANDROID_CONTROL_AE_STATE);
        if (entry.count == 0) {
            CLOGE("No AE state provided by HAL for frame %d!",
                    frameNumber);
        } else {
            new3aState.aeState =
                    static_cast<camera_metadata_enum_android_control_ae_state>(
                        entry.data.u8[0]);
        }

        entry = captureResult.find(ANDROID_CONTROL_AF_STATE);
        if (entry.count == 0) {
            CLOGE("No AF state provided by HAL for frame %d!",
                    frameNumber);
        } else {
            new3aState.afState =
                    static_cast<camera_metadata_enum_android_control_af_state>(
                        entry.data.u8[0]);
        }

        entry = captureResult.find(ANDROID_CONTROL_AWB_STATE);
        if (entry.count == 0) {
            CLOGE("No AWB state provided by HAL for frame %d!",
                    frameNumber);
        } else {
            new3aState.awbState =
                    static_cast<camera_metadata_enum_android_control_awb_state>(
                        entry.data.u8[0]);
        }

        entry = captureResult.find(ANDROID_CONTROL_AF_TRIGGER_ID);
        if (entry.count == 0) {
            CLOGE("No AF trigger ID provided by HAL for frame %d!",
                    frameNumber);
        } else {
            afTriggerId = entry.data.i32[0];
        }

        entry = captureResult.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
        if (entry.count == 0) {
            CLOGE("No AE precapture trigger ID provided by HAL"
                    " for frame %d!", frameNumber);
        } else {
            aeTriggerId = entry.data.i32[0];
        }

        listener = mListener;
        cur3aState = m3AState;

        m3AState = new3aState;
    } // scope for mOutputLock

    // Return completed buffers to their streams with the timestamp
@@ -1349,29 +1293,15 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
        }
    }

    // Finally, dispatch any 3A change events to listeners if we got metadata
    // Finally, signal any waiters for new frames

    if (result->result != NULL) {
        mResultSignal.signal();
    }

    if (result->result != NULL && listener != NULL) {
        if (new3aState.aeState != cur3aState.aeState) {
            ALOGVV("%s: AE state changed from 0x%x to 0x%x",
                    __FUNCTION__, cur3aState.aeState, new3aState.aeState);
            listener->notifyAutoExposure(new3aState.aeState, aeTriggerId);
        }
        if (new3aState.afState != cur3aState.afState) {
            ALOGVV("%s: AF state changed from 0x%x to 0x%x",
                    __FUNCTION__, cur3aState.afState, new3aState.afState);
            listener->notifyAutoFocus(new3aState.afState, afTriggerId);
        }
        if (new3aState.awbState != cur3aState.awbState) {
            listener->notifyAutoWhitebalance(new3aState.awbState, aeTriggerId);
        }
}

}


void Camera3Device::notify(const camera3_notify_msg *msg) {
    NotificationListener *listener;
+1 −12
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ class Camera3Device :
    virtual status_t waitUntilDrained();

    virtual status_t setNotifyCallback(NotificationListener *listener);
    virtual bool     willNotify3A();
    virtual status_t waitForNextFrame(nsecs_t timeout);
    virtual status_t getNextFrame(CameraMetadata *frame);

@@ -389,18 +390,6 @@ class Camera3Device :
    Condition              mResultSignal;
    NotificationListener  *mListener;

    struct AlgState {
        camera_metadata_enum_android_control_ae_state  aeState;
        camera_metadata_enum_android_control_af_state  afState;
        camera_metadata_enum_android_control_awb_state awbState;

        AlgState() :
                aeState(ANDROID_CONTROL_AE_STATE_INACTIVE),
                afState(ANDROID_CONTROL_AF_STATE_INACTIVE),
                awbState(ANDROID_CONTROL_AWB_STATE_INACTIVE) {
        }
    } m3AState;

    /**** End scope for mOutputLock ****/

    /**
+7 −0
Original line number Diff line number Diff line
@@ -155,6 +155,13 @@ class CameraDeviceBase : public virtual RefBase {
     */
    virtual status_t setNotifyCallback(NotificationListener *listener) = 0;

    /**
     * Whether the device supports calling notifyAutofocus, notifyAutoExposure,
     * and notifyAutoWhitebalance; if this returns false, the client must
     * synthesize these notifications from received frame metadata.
     */
    virtual bool     willNotify3A() = 0;

    /**
     * Wait for a new frame to be produced, with timeout in nanoseconds.
     * Returns TIMED_OUT when no frame produced within the specified duration
Loading