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

Commit 37964cbb authored by Chien-Yu Chen's avatar Chien-Yu Chen Committed by Android (Google) Code Review
Browse files

Merge "Camera3Device: Send partial results seperately" into nyc-dev

parents 98783a37 5cd8d64b
Loading
Loading
Loading
Loading
+71 −41
Original line number Diff line number Diff line
@@ -53,7 +53,13 @@ FrameProcessor::FrameProcessor(wp<CameraDeviceBase> device,
        // Check if lens is fixed-focus
        if (l.mParameters.focusMode == Parameters::FOCUS_MODE_FIXED) {
            m3aState.afMode = ANDROID_CONTROL_AF_MODE_OFF;
        } else {
            m3aState.afMode = ANDROID_CONTROL_AF_MODE_AUTO;
        }
        m3aState.awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;
        m3aState.aeState = ANDROID_CONTROL_AE_STATE_INACTIVE;
        m3aState.afState = ANDROID_CONTROL_AF_STATE_INACTIVE;
        m3aState.awbState = ANDROID_CONTROL_AWB_STATE_INACTIVE;
    }
}

@@ -253,80 +259,99 @@ status_t FrameProcessor::process3aState(const CaptureResult &frame,
    if (frameNumber <= mLast3AFrameNumber) {
        ALOGV("%s: Already sent 3A for frame number %d, skipping",
                __FUNCTION__, frameNumber);

        // Remove the entry if there is one for this frame number in mPending3AStates.
        mPending3AStates.removeItem(frameNumber);
        return OK;
    }

    mLast3AFrameNumber = frameNumber;
    AlgState pendingState;

    // Get 3A states from result metadata
    bool gotAllStates = true;
    ssize_t index = mPending3AStates.indexOfKey(frameNumber);
    if (index != NAME_NOT_FOUND) {
        pendingState = mPending3AStates.valueAt(index);
    }

    AlgState new3aState;
    // Update 3A states from the result.
    bool gotAllStates = true;

    // TODO: Also use AE mode, AE trigger ID
    gotAllStates &= updatePendingState<uint8_t>(metadata, ANDROID_CONTROL_AF_MODE,
            &pendingState.afMode, frameNumber, cameraId);

    gotAllStates &= get3aResult<uint8_t>(metadata, ANDROID_CONTROL_AF_MODE,
            &new3aState.afMode, frameNumber, cameraId);
    gotAllStates &= updatePendingState<uint8_t>(metadata, ANDROID_CONTROL_AWB_MODE,
            &pendingState.awbMode, frameNumber, cameraId);

    gotAllStates &= get3aResult<uint8_t>(metadata, ANDROID_CONTROL_AWB_MODE,
            &new3aState.awbMode, frameNumber, cameraId);
    gotAllStates &= updatePendingState<uint8_t>(metadata, ANDROID_CONTROL_AE_STATE,
            &pendingState.aeState, frameNumber, cameraId);

    gotAllStates &= get3aResult<uint8_t>(metadata, ANDROID_CONTROL_AE_STATE,
            &new3aState.aeState, frameNumber, cameraId);
    gotAllStates &= updatePendingState<uint8_t>(metadata, ANDROID_CONTROL_AF_STATE,
            &pendingState.afState, frameNumber, cameraId);

    gotAllStates &= get3aResult<uint8_t>(metadata, ANDROID_CONTROL_AF_STATE,
            &new3aState.afState, frameNumber, cameraId);

    gotAllStates &= get3aResult<uint8_t>(metadata, ANDROID_CONTROL_AWB_STATE,
            &new3aState.awbState, frameNumber, cameraId);
    gotAllStates &= updatePendingState<uint8_t>(metadata, ANDROID_CONTROL_AWB_STATE,
            &pendingState.awbState, frameNumber, cameraId);

    if (client->getCameraDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_2) {
        new3aState.afTriggerId = frame.mResultExtras.afTriggerId;
        new3aState.aeTriggerId = frame.mResultExtras.precaptureTriggerId;
        pendingState.afTriggerId = frame.mResultExtras.afTriggerId;
        pendingState.aeTriggerId = frame.mResultExtras.precaptureTriggerId;
    } else {
        gotAllStates &= get3aResult<int32_t>(metadata, ANDROID_CONTROL_AF_TRIGGER_ID,
                 &new3aState.afTriggerId, frameNumber, cameraId);
        gotAllStates &= updatePendingState<int32_t>(metadata,
                ANDROID_CONTROL_AF_TRIGGER_ID, &pendingState.afTriggerId, frameNumber, cameraId);

        gotAllStates &= get3aResult<int32_t>(metadata, ANDROID_CONTROL_AE_PRECAPTURE_ID,
                 &new3aState.aeTriggerId, frameNumber, cameraId);
        gotAllStates &= updatePendingState<int32_t>(metadata,
            ANDROID_CONTROL_AE_PRECAPTURE_ID, &pendingState.aeTriggerId, frameNumber, cameraId);
    }

    if (!gotAllStates) return BAD_VALUE;
    if (!gotAllStates) {
        // If not all states are received, put the pending state to mPending3AStates.
        if (index == NAME_NOT_FOUND) {
            mPending3AStates.add(frameNumber, pendingState);
        } else {
            mPending3AStates.replaceValueAt(index, pendingState);
        }
        return NOT_ENOUGH_DATA;
    }

    if (new3aState.aeState != m3aState.aeState) {
    // Once all 3A states are received, notify the client about 3A changes.
    if (pendingState.aeState != m3aState.aeState) {
        ALOGV("%s: Camera %d: AE state %d->%d",
                __FUNCTION__, cameraId,
                m3aState.aeState, new3aState.aeState);
        client->notifyAutoExposure(new3aState.aeState, new3aState.aeTriggerId);
                m3aState.aeState, pendingState.aeState);
        client->notifyAutoExposure(pendingState.aeState, pendingState.aeTriggerId);
    }

    if (new3aState.afState != m3aState.afState ||
        new3aState.afMode != m3aState.afMode ||
        new3aState.afTriggerId != m3aState.afTriggerId) {
    if (pendingState.afState != m3aState.afState ||
        pendingState.afMode != m3aState.afMode ||
        pendingState.afTriggerId != m3aState.afTriggerId) {
        ALOGV("%s: Camera %d: AF state %d->%d. AF mode %d->%d. Trigger %d->%d",
                __FUNCTION__, cameraId,
                m3aState.afState, new3aState.afState,
                m3aState.afMode, new3aState.afMode,
                m3aState.afTriggerId, new3aState.afTriggerId);
        client->notifyAutoFocus(new3aState.afState, new3aState.afTriggerId);
                m3aState.afState, pendingState.afState,
                m3aState.afMode, pendingState.afMode,
                m3aState.afTriggerId, pendingState.afTriggerId);
        client->notifyAutoFocus(pendingState.afState, pendingState.afTriggerId);
    }
    if (new3aState.awbState != m3aState.awbState ||
        new3aState.awbMode != m3aState.awbMode) {
    if (pendingState.awbState != m3aState.awbState ||
        pendingState.awbMode != m3aState.awbMode) {
        ALOGV("%s: Camera %d: AWB state %d->%d. AWB mode %d->%d",
                __FUNCTION__, cameraId,
                m3aState.awbState, new3aState.awbState,
                m3aState.awbMode, new3aState.awbMode);
        client->notifyAutoWhitebalance(new3aState.awbState,
                new3aState.aeTriggerId);
                m3aState.awbState, pendingState.awbState,
                m3aState.awbMode, pendingState.awbMode);
        client->notifyAutoWhitebalance(pendingState.awbState,
                pendingState.aeTriggerId);
    }

    if (index != NAME_NOT_FOUND) {
        mPending3AStates.removeItemsAt(index);
    }

    m3aState = new3aState;
    m3aState = pendingState;
    mLast3AFrameNumber = frameNumber;

    return OK;
}

template<typename Src, typename T>
bool FrameProcessor::get3aResult(const CameraMetadata& result, int32_t tag,
bool FrameProcessor::updatePendingState(const CameraMetadata& result, int32_t tag,
        T* value, int32_t frameNumber, int cameraId) {
    camera_metadata_ro_entry_t entry;
    if (value == NULL) {
@@ -335,9 +360,14 @@ bool FrameProcessor::get3aResult(const CameraMetadata& result, int32_t tag,
        return false;
    }

    // Already got the value for this tag.
    if (*value != static_cast<T>(NOT_SET)) {
        return true;
    }

    entry = result.find(tag);
    if (entry.count == 0) {
        ALOGE("%s: Camera %d: No %s provided by HAL for frame %d!",
        ALOGV("%s: Camera %d: No %s provided by HAL for frame %d in this result!",
                __FUNCTION__, cameraId,
                get_camera_metadata_tag_name(tag), frameNumber);
        return false;
+16 −9
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@ class FrameProcessor : public FrameProcessorBase {
    ~FrameProcessor();

  private:
    static const int32_t NOT_SET = -1;

    wp<Camera2Client> mClient;

    bool mSynthesize3ANotify;
@@ -63,7 +65,7 @@ class FrameProcessor : public FrameProcessorBase {

    // Helper for process3aState
    template<typename Src, typename T>
    bool get3aResult(const CameraMetadata& result, int32_t tag, T* value,
    bool updatePendingState(const CameraMetadata& result, int32_t tag, T* value,
            int32_t frameNumber, int cameraId);


@@ -81,15 +83,20 @@ class FrameProcessor : public FrameProcessorBase {

        // These defaults need to match those in Parameters.cpp
        AlgState() :
                afMode(ANDROID_CONTROL_AF_MODE_AUTO),
                awbMode(ANDROID_CONTROL_AWB_MODE_AUTO),
                aeState(ANDROID_CONTROL_AE_STATE_INACTIVE),
                afState(ANDROID_CONTROL_AF_STATE_INACTIVE),
                awbState(ANDROID_CONTROL_AWB_STATE_INACTIVE),
                afTriggerId(0),
                aeTriggerId(0) {
                afMode((camera_metadata_enum_android_control_af_mode)NOT_SET),
                awbMode((camera_metadata_enum_android_control_awb_mode)NOT_SET),
                aeState((camera_metadata_enum_android_control_ae_state)NOT_SET),
                afState((camera_metadata_enum_android_control_af_state)NOT_SET),
                awbState((camera_metadata_enum_android_control_awb_state)NOT_SET),
                afTriggerId(NOT_SET),
                aeTriggerId(NOT_SET) {
        }
    } m3aState;
    };

    AlgState m3aState;

    // frame number -> pending 3A states that not all data are received yet.
    KeyedVector<int32_t, AlgState> mPending3AStates;

    // Whether the partial result is enabled for this device
    bool mUsePartialResult;
+54 −208
Original line number Diff line number Diff line
@@ -2058,176 +2058,6 @@ status_t Camera3Device::registerInFlight(uint32_t frameNumber,
    return OK;
}

/**
 * Check if all 3A fields are ready, and send off a partial 3A-only result
 * to the output frame queue
 */
bool Camera3Device::processPartial3AResult(
        uint32_t frameNumber,
        const CameraMetadata& partial, const CaptureResultExtras& resultExtras) {

    // Check if all 3A states are present
    // The full list of fields is
    //   android.control.afMode
    //   android.control.awbMode
    //   android.control.aeState
    //   android.control.awbState
    //   android.control.afState
    //   android.control.afTriggerID
    //   android.control.aePrecaptureID
    // TODO: Add android.control.aeMode

    bool gotAllStates = true;

    uint8_t afMode;
    uint8_t awbMode;
    uint8_t aeState;
    uint8_t afState;
    uint8_t awbState;

    gotAllStates &= get3AResult(partial, ANDROID_CONTROL_AF_MODE,
        &afMode, frameNumber);

    gotAllStates &= get3AResult(partial, ANDROID_CONTROL_AWB_MODE,
        &awbMode, frameNumber);

    gotAllStates &= get3AResult(partial, ANDROID_CONTROL_AE_STATE,
        &aeState, frameNumber);

    gotAllStates &= get3AResult(partial, ANDROID_CONTROL_AF_STATE,
        &afState, frameNumber);

    gotAllStates &= get3AResult(partial, ANDROID_CONTROL_AWB_STATE,
        &awbState, frameNumber);

    if (!gotAllStates) return false;

    ALOGVV("%s: Camera %d: Frame %d, Request ID %d: AF mode %d, AWB mode %d, "
        "AF state %d, AE state %d, AWB state %d, "
        "AF trigger %d, AE precapture trigger %d",
        __FUNCTION__, mId, frameNumber, resultExtras.requestId,
        afMode, awbMode,
        afState, aeState, awbState,
        resultExtras.afTriggerId, resultExtras.precaptureTriggerId);

    // Got all states, so construct a minimal result to send
    // In addition to the above fields, this means adding in
    //   android.request.frameCount
    //   android.request.requestId
    //   android.quirks.partialResult (for HAL version below HAL3.2)

    const size_t kMinimal3AResultEntries = 10;

    Mutex::Autolock l(mOutputLock);

    CaptureResult captureResult;
    captureResult.mResultExtras = resultExtras;
    captureResult.mMetadata = CameraMetadata(kMinimal3AResultEntries, /*dataCapacity*/ 0);
    // TODO: change this to sp<CaptureResult>. This will need other changes, including,
    // but not limited to CameraDeviceBase::getNextResult
    CaptureResult& min3AResult =
            *mResultQueue.insert(mResultQueue.end(), captureResult);

    if (!insert3AResult(min3AResult.mMetadata, ANDROID_REQUEST_FRAME_COUNT,
            // TODO: This is problematic casting. Need to fix CameraMetadata.
            reinterpret_cast<int32_t*>(&frameNumber), frameNumber)) {
        return false;
    }

    int32_t requestId = resultExtras.requestId;
    if (!insert3AResult(min3AResult.mMetadata, ANDROID_REQUEST_ID,
            &requestId, frameNumber)) {
        return false;
    }

    if (mDeviceVersion < CAMERA_DEVICE_API_VERSION_3_2) {
        static const uint8_t partialResult = ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL;
        if (!insert3AResult(min3AResult.mMetadata, ANDROID_QUIRKS_PARTIAL_RESULT,
                &partialResult, frameNumber)) {
            return false;
        }
    }

    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AF_MODE,
            &afMode, frameNumber)) {
        return false;
    }

    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AWB_MODE,
            &awbMode, frameNumber)) {
        return false;
    }

    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AE_STATE,
            &aeState, frameNumber)) {
        return false;
    }

    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AF_STATE,
            &afState, frameNumber)) {
        return false;
    }

    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AWB_STATE,
            &awbState, frameNumber)) {
        return false;
    }

    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AF_TRIGGER_ID,
            &resultExtras.afTriggerId, frameNumber)) {
        return false;
    }

    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AE_PRECAPTURE_ID,
            &resultExtras.precaptureTriggerId, frameNumber)) {
        return false;
    }

    // We only send the aggregated partial when all 3A related metadata are available
    // For both API1 and API2.
    // TODO: we probably should pass through all partials to API2 unconditionally.
    mResultSignal.signal();

    return true;
}

template<typename T>
bool Camera3Device::get3AResult(const CameraMetadata& result, int32_t tag,
        T* value, uint32_t frameNumber) {
    (void) frameNumber;

    camera_metadata_ro_entry_t entry;

    entry = result.find(tag);
    if (entry.count == 0) {
        ALOGVV("%s: Camera %d: Frame %d: No %s provided by HAL!", __FUNCTION__,
            mId, frameNumber, get_camera_metadata_tag_name(tag));
        return false;
    }

    if (sizeof(T) == sizeof(uint8_t)) {
        *value = entry.data.u8[0];
    } else if (sizeof(T) == sizeof(int32_t)) {
        *value = entry.data.i32[0];
    } else {
        ALOGE("%s: Unexpected type", __FUNCTION__);
        return false;
    }
    return true;
}

template<typename T>
bool Camera3Device::insert3AResult(CameraMetadata& result, int32_t tag,
        const T* value, uint32_t frameNumber) {
    if (result.update(tag, value, 1) != NO_ERROR) {
        mResultQueue.erase(--mResultQueue.end(), mResultQueue.end());
        SET_ERR("Frame %d: Failed to set %s in partial metadata",
                frameNumber, get_camera_metadata_tag_name(tag));
        return false;
    }
    return true;
}

void Camera3Device::returnOutputBuffers(
        const camera3_stream_buffer_t *outputBuffers, size_t numBuffers,
        nsecs_t timestamp) {
@@ -2295,6 +2125,48 @@ void Camera3Device::removeInFlightRequestIfReadyLocked(int idx) {
    }
}

void Camera3Device::insertResultLocked(CaptureResult *result, uint32_t frameNumber,
            const AeTriggerCancelOverride_t &aeTriggerCancelOverride) {
    if (result == nullptr) return;

    if (result->mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
            (int32_t*)&frameNumber, 1) != OK) {
        SET_ERR("Failed to set frame number %d in metadata", frameNumber);
        return;
    }

    if (result->mMetadata.update(ANDROID_REQUEST_ID, &result->mResultExtras.requestId, 1) != OK) {
        SET_ERR("Failed to set request ID in metadata for frame %d", frameNumber);
        return;
    }

    overrideResultForPrecaptureCancel(&result->mMetadata, aeTriggerCancelOverride);

    // Valid result, insert into queue
    List<CaptureResult>::iterator queuedResult =
            mResultQueue.insert(mResultQueue.end(), CaptureResult(*result));
    ALOGVV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
           ", burstId = %" PRId32, __FUNCTION__,
           queuedResult->mResultExtras.requestId,
           queuedResult->mResultExtras.frameNumber,
           queuedResult->mResultExtras.burstId);

    mResultSignal.signal();
}


void Camera3Device::sendPartialCaptureResult(const camera_metadata_t * partialResult,
        const CaptureResultExtras &resultExtras, uint32_t frameNumber,
        const AeTriggerCancelOverride_t &aeTriggerCancelOverride) {
    Mutex::Autolock l(mOutputLock);

    CaptureResult captureResult;
    captureResult.mResultExtras = resultExtras;
    captureResult.mMetadata = partialResult;

    insertResultLocked(&captureResult, frameNumber, aeTriggerCancelOverride);
}


void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata,
        CaptureResultExtras &resultExtras,
@@ -2330,16 +2202,6 @@ void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata,
    captureResult.mResultExtras = resultExtras;
    captureResult.mMetadata = pendingMetadata;

    if (captureResult.mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
            (int32_t*)&frameNumber, 1) != OK) {
        SET_ERR("Failed to set frame# in metadata (%d)",
                frameNumber);
        return;
    } else {
        ALOGVV("%s: Camera %d: Set frame# in metadata (%d)",
                __FUNCTION__, mId, frameNumber);
    }

    // Append any previous partials to form a complete result
    if (mUsePartialResult && !collectedPartialResult.isEmpty()) {
        captureResult.mMetadata.append(collectedPartialResult);
@@ -2348,26 +2210,14 @@ void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata,
    captureResult.mMetadata.sort();

    // Check that there's a timestamp in the result metadata
    camera_metadata_entry entry =
            captureResult.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
    camera_metadata_entry entry = captureResult.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
    if (entry.count == 0) {
        SET_ERR("No timestamp provided by HAL for frame %d!",
                frameNumber);
        return;
    }

    overrideResultForPrecaptureCancel(&captureResult.mMetadata, aeTriggerCancelOverride);

    // Valid result, insert into queue
    List<CaptureResult>::iterator queuedResult =
            mResultQueue.insert(mResultQueue.end(), CaptureResult(captureResult));
    ALOGVV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
           ", burstId = %" PRId32, __FUNCTION__,
           queuedResult->mResultExtras.requestId,
           queuedResult->mResultExtras.frameNumber,
           queuedResult->mResultExtras.burstId);

    mResultSignal.signal();
    insertResultLocked(&captureResult, frameNumber, aeTriggerCancelOverride);
}

/**
@@ -2444,7 +2294,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
                }
                isPartialResult = (result->partial_result < mNumPartialResults);
                if (isPartialResult) {
                    request.partialResult.collectedResult.append(result->result);
                    request.collectedPartialResult.append(result->result);
                }
            } else {
                camera_metadata_ro_entry_t partialResultEntry;
@@ -2457,21 +2307,17 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
                    // A partial result. Flag this as such, and collect this
                    // set of metadata into the in-flight entry.
                    isPartialResult = true;
                    request.partialResult.collectedResult.append(
                    request.collectedPartialResult.append(
                        result->result);
                    request.partialResult.collectedResult.erase(
                    request.collectedPartialResult.erase(
                        ANDROID_QUIRKS_PARTIAL_RESULT);
                }
            }

            if (isPartialResult) {
                // Fire off a 3A-only result if possible
                if (!request.partialResult.haveSent3A) {
                    request.partialResult.haveSent3A =
                            processPartial3AResult(frameNumber,
                                    request.partialResult.collectedResult,
                                    request.resultExtras);
                }
                // Send partial capture result
                sendPartialCaptureResult(result->result, request.resultExtras, frameNumber,
                        request.aeTriggerCancelOverride);
            }
        }

@@ -2486,9 +2332,9 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
                return;
            }
            if (mUsePartialResult &&
                    !request.partialResult.collectedResult.isEmpty()) {
                    !request.collectedPartialResult.isEmpty()) {
                collectedPartialResult.acquire(
                    request.partialResult.collectedResult);
                    request.collectedPartialResult);
            }
            request.haveResultMetadata = true;
        }
@@ -2531,7 +2377,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
        if (result->result != NULL && !isPartialResult) {
            if (shutterTimestamp == 0) {
                request.pendingMetadata = result->result;
                request.partialResult.collectedResult = collectedPartialResult;
                request.collectedPartialResult = collectedPartialResult;
            } else {
                CameraMetadata metadata;
                metadata = result->result;
@@ -2709,7 +2555,7 @@ void Camera3Device::notifyShutter(const camera3_shutter_msg_t &msg,

            // send pending result and buffers
            sendCaptureResult(r.pendingMetadata, r.resultExtras,
                r.partialResult.collectedResult, msg.frame_number,
                r.collectedPartialResult, msg.frame_number,
                r.hasInputBuffer, r.aeTriggerCancelOverride);
            returnOutputBuffers(r.pendingOutputBuffers.array(),
                r.pendingOutputBuffers.size(), r.shutterTimestamp);
+16 −31
Original line number Diff line number Diff line
@@ -648,6 +648,10 @@ class Camera3Device :
        // receives the shutter event.
        CameraMetadata pendingMetadata;

        // The metadata of the partial results that framework receives from HAL so far
        // and has sent out.
        CameraMetadata collectedPartialResult;

        // Buffers are added by process_capture_result when output buffers
        // return from HAL but framework has not yet received the shutter
        // event. They will be returned to the streams when framework receives
@@ -658,19 +662,6 @@ class Camera3Device :
        // CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
        AeTriggerCancelOverride_t aeTriggerCancelOverride;


        // Fields used by the partial result only
        struct PartialResultInFlight {
            // Set by process_capture_result once 3A has been sent to clients
            bool    haveSent3A;
            // Result metadata collected so far, when partial results are in use
            CameraMetadata collectedResult;

            PartialResultInFlight():
                    haveSent3A(false) {
            }
        } partialResult;

        // Default constructor needed by KeyedVector
        InFlightRequest() :
                shutterTimestamp(0),
@@ -705,23 +696,6 @@ class Camera3Device :
            int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
            const AeTriggerCancelOverride_t &aeTriggerCancelOverride);

    /**
     * For the partial result, check if all 3A state fields are available
     * and if so, queue up 3A-only result to the client. Returns true if 3A
     * is sent.
     */
    bool processPartial3AResult(uint32_t frameNumber,
            const CameraMetadata& partial, const CaptureResultExtras& resultExtras);

    // Helpers for reading and writing 3A metadata into to/from partial results
    template<typename T>
    bool get3AResult(const CameraMetadata& result, int32_t tag,
            T* value, uint32_t frameNumber);

    template<typename T>
    bool insert3AResult(CameraMetadata &result, int32_t tag, const T* value,
            uint32_t frameNumber);

    /**
     * Override result metadata for cancelling AE precapture trigger applied in
     * handleAePrecaptureCancelRequest().
@@ -820,13 +794,24 @@ class Camera3Device :
    void returnOutputBuffers(const camera3_stream_buffer_t *outputBuffers,
            size_t numBuffers, nsecs_t timestamp);

    // Insert the capture result given the pending metadata, result extras,
    // Send a partial capture result.
    void sendPartialCaptureResult(const camera_metadata_t * partialResult,
            const CaptureResultExtras &resultExtras, uint32_t frameNumber,
            const AeTriggerCancelOverride_t &aeTriggerCancelOverride);

    // Send a total capture result given the pending metadata and result extras,
    // partial results, and the frame number to the result queue.
    void sendCaptureResult(CameraMetadata &pendingMetadata,
            CaptureResultExtras &resultExtras,
            CameraMetadata &collectedPartialResult, uint32_t frameNumber,
            bool reprocess, const AeTriggerCancelOverride_t &aeTriggerCancelOverride);

    // Insert the result to the result queue after updating frame number and overriding AE
    // trigger cancel.
    // mOutputLock must be held when calling this function.
    void insertResultLocked(CaptureResult *result, uint32_t frameNumber,
            const AeTriggerCancelOverride_t &aeTriggerCancelOverride);

    /**** Scope for mInFlightLock ****/

    // Remove the in-flight request of the given index from mInFlightMap