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

Commit cb0652e5 authored by Jianing Wei's avatar Jianing Wei
Browse files

CameraService: trigger appropriate callbacks for burst capture.

* Instead of tracking CameraMetadata only, now we track both
CameraMetadata and CaptureResultExtras, which is not part of
the HAL metadata. This will enable the correct callback of
onCaptureStarted and onResultReceived given burst requests.

* Get last frame number in reply when submitting requests,
canceling requests, and flushing device. For repeating requests,
this frame number is the last frame number of the previous
request. For non-repeating requests, this frame number is the
expected last frame number of the current request. The goal
is provide frame number to Java side in order to trigger
onCaptureSequenceCompleted correctly.

* Fix notifyError so that onDeviceError can be called correctly.

Bug: 10749500
Change-Id: I2f3dda6c530090055d4a2ff9f0f087bbbe8d9257
parent d27368f7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ LOCAL_SRC_FILES:= \
	Camera.cpp \
	CameraMetadata.cpp \
	CameraParameters.cpp \
	CaptureResult.cpp \
	ICamera.cpp \
	ICameraClient.cpp \
	ICameraService.cpp \
+127 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "Camera-CaptureResult"
#include <utils/Log.h>

#include <camera/CaptureResult.h>
#include <binder/Parcel.h>

namespace android {

bool CaptureResultExtras::isValid() {
    return requestId >= 0;
}

status_t CaptureResultExtras::readFromParcel(Parcel *parcel) {
    if (parcel == NULL) {
        ALOGE("%s: Null parcel", __FUNCTION__);
        return BAD_VALUE;
    }

    parcel->readInt32(&requestId);
    parcel->readInt32(&burstId);
    parcel->readInt32(&afTriggerId);
    parcel->readInt32(&precaptureTriggerId);
    parcel->readInt64(&frameNumber);

    return OK;
}

status_t CaptureResultExtras::writeToParcel(Parcel *parcel) const {
    if (parcel == NULL) {
        ALOGE("%s: Null parcel", __FUNCTION__);
        return BAD_VALUE;
    }

    parcel->writeInt32(requestId);
    parcel->writeInt32(burstId);
    parcel->writeInt32(afTriggerId);
    parcel->writeInt32(precaptureTriggerId);
    parcel->writeInt64(frameNumber);

    return OK;
}

CaptureResult::CaptureResult() :
        mMetadata(), mResultExtras() {
}

CaptureResult::CaptureResult(const CaptureResult &otherResult) {
    mResultExtras = otherResult.mResultExtras;
    mMetadata = otherResult.mMetadata;
}

status_t CaptureResult::readFromParcel(Parcel *parcel) {

    ALOGV("%s: parcel = %p", __FUNCTION__, parcel);

    if (parcel == NULL) {
        ALOGE("%s: parcel is null", __FUNCTION__);
        return BAD_VALUE;
    }

    mMetadata.clear();

    status_t res = OK;
    res = mMetadata.readFromParcel(parcel);
    if (res != OK) {
        ALOGE("%s: Failed to read metadata from parcel.",
              __FUNCTION__);
        return res;
    }
    ALOGV("%s: Read metadata from parcel", __FUNCTION__);

    res = mResultExtras.readFromParcel(parcel);
    if (res != OK) {
        ALOGE("%s: Failed to read result extras from parcel.",
                __FUNCTION__);
        return res;
    }
    ALOGV("%s: Read result extras from parcel", __FUNCTION__);

    return OK;
}

status_t CaptureResult::writeToParcel(Parcel *parcel) const {

    ALOGV("%s: parcel = %p", __FUNCTION__, parcel);

    if (parcel == NULL) {
        ALOGE("%s: parcel is null", __FUNCTION__);
        return BAD_VALUE;
    }

    status_t res;

    res = mMetadata.writeToParcel(parcel);
    if (res != OK) {
        ALOGE("%s: Failed to write metadata to parcel", __FUNCTION__);
        return res;
    }
    ALOGV("%s: Wrote metadata to parcel", __FUNCTION__);

    res = mResultExtras.writeToParcel(parcel);
    if (res != OK) {
        ALOGE("%s: Failed to write result extras to parcel", __FUNCTION__);
        return res;
    }
    ALOGV("%s: Wrote result extras to parcel", __FUNCTION__);

    return OK;
}

}
+35 −13
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@

#include <camera/camera2/ICameraDeviceCallbacks.h>
#include "camera/CameraMetadata.h"
#include "camera/CaptureResult.h"

namespace android {

@@ -46,12 +47,14 @@ public:
    {
    }

    void onDeviceError(CameraErrorCode errorCode)
    void onDeviceError(CameraErrorCode errorCode, const CaptureResultExtras& resultExtras)
    {
        ALOGV("onDeviceError");
        Parcel data, reply;
        data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
        data.writeInt32(static_cast<int32_t>(errorCode));
        data.writeInt32(1); // to mark presence of CaptureResultExtras object
        resultExtras.writeToParcel(&data);
        remote()->transact(CAMERA_ERROR, data, &reply, IBinder::FLAG_ONEWAY);
        data.writeNoException();
    }
@@ -65,25 +68,28 @@ public:
        data.writeNoException();
    }

    void onCaptureStarted(int32_t requestId, int64_t timestamp)
    void onCaptureStarted(const CaptureResultExtras& result, int64_t timestamp)
    {
        ALOGV("onCaptureStarted");
        Parcel data, reply;
        data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
        data.writeInt32(requestId);
        data.writeInt32(1); // to mark presence of CaptureResultExtras object
        result.writeToParcel(&data);
        data.writeInt64(timestamp);
        remote()->transact(CAPTURE_STARTED, data, &reply, IBinder::FLAG_ONEWAY);
        data.writeNoException();
    }


    void onResultReceived(int32_t requestId, const CameraMetadata& result) {
    void onResultReceived(const CameraMetadata& metadata,
            const CaptureResultExtras& resultExtras) {
        ALOGV("onResultReceived");
        Parcel data, reply;
        data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
        data.writeInt32(requestId);
        data.writeInt32(1); // to mark presence of metadata object
        result.writeToParcel(&data);
        metadata.writeToParcel(&data);
        data.writeInt32(1); // to mark presence of CaptureResult object
        resultExtras.writeToParcel(&data);
        remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY);
        data.writeNoException();
    }
@@ -104,7 +110,13 @@ status_t BnCameraDeviceCallbacks::onTransact(
            CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
            CameraErrorCode errorCode =
                    static_cast<CameraErrorCode>(data.readInt32());
            onDeviceError(errorCode);
            CaptureResultExtras resultExtras;
            if (data.readInt32() != 0) {
                resultExtras.readFromParcel(const_cast<Parcel*>(&data));
            } else {
                ALOGE("No CaptureResultExtras object is present!");
            }
            onDeviceError(errorCode, resultExtras);
            data.readExceptionCode();
            return NO_ERROR;
        } break;
@@ -118,23 +130,33 @@ status_t BnCameraDeviceCallbacks::onTransact(
        case CAPTURE_STARTED: {
            ALOGV("onCaptureStarted");
            CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
            int32_t requestId = data.readInt32();
            CaptureResultExtras result;
            if (data.readInt32() != 0) {
                result.readFromParcel(const_cast<Parcel*>(&data));
            } else {
                ALOGE("No CaptureResultExtras object is present in result!");
            }
            int64_t timestamp = data.readInt64();
            onCaptureStarted(requestId, timestamp);
            onCaptureStarted(result, timestamp);
            data.readExceptionCode();
            return NO_ERROR;
        } break;
        case RESULT_RECEIVED: {
            ALOGV("onResultReceived");
            CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
            int32_t requestId = data.readInt32();
            CameraMetadata result;
            CameraMetadata metadata;
            if (data.readInt32() != 0) {
                result.readFromParcel(const_cast<Parcel*>(&data));
                metadata.readFromParcel(const_cast<Parcel*>(&data));
            } else {
                ALOGW("No metadata object is present in result");
            }
            onResultReceived(requestId, result);
            CaptureResultExtras resultExtras;
            if (data.readInt32() != 0) {
                resultExtras.readFromParcel(const_cast<Parcel*>(&data));
            } else {
                ALOGW("No capture result extras object is present in result");
            }
            onResultReceived(metadata, resultExtras);
            data.readExceptionCode();
            return NO_ERROR;
        } break;
+125 −11
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ typedef Parcel::ReadableBlob ReadableBlob;
enum {
    DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
    SUBMIT_REQUEST,
    SUBMIT_REQUEST_LIST,
    CANCEL_REQUEST,
    DELETE_STREAM,
    CREATE_STREAM,
@@ -75,7 +76,8 @@ public:
        reply.readExceptionCode();
    }

    virtual int submitRequest(sp<CaptureRequest> request, bool streaming)
    virtual status_t submitRequest(sp<CaptureRequest> request, bool repeating,
                              int64_t *lastFrameNumber)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
@@ -89,15 +91,67 @@ public:
        }

        // arg1 = streaming (bool)
        data.writeInt32(streaming);
        data.writeInt32(repeating);

        remote()->transact(SUBMIT_REQUEST, data, &reply);

        reply.readExceptionCode();
        return reply.readInt32();
        status_t res = reply.readInt32();

        status_t resFrameNumber = BAD_VALUE;
        if (reply.readInt32() != 0) {
            if (lastFrameNumber != NULL) {
                resFrameNumber = reply.readInt64(lastFrameNumber);
            }
        }

	if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
            res = FAILED_TRANSACTION;
        }
        return res;
    }

    virtual status_t cancelRequest(int requestId)
    virtual status_t submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating,
                                  int64_t *lastFrameNumber)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());

        data.writeInt32(requestList.size());

        for (List<sp<CaptureRequest> >::iterator it = requestList.begin();
                it != requestList.end(); ++it) {
            sp<CaptureRequest> request = *it;
            if (request != 0) {
                data.writeInt32(1);
                if (request->writeToParcel(&data) != OK) {
                    return BAD_VALUE;
                }
            } else {
                data.writeInt32(0);
            }
        }

        data.writeInt32(repeating);

        remote()->transact(SUBMIT_REQUEST_LIST, data, &reply);

        reply.readExceptionCode();
        status_t res = reply.readInt32();

        status_t resFrameNumber = BAD_VALUE;
        if (reply.readInt32() != 0) {
            if (lastFrameNumber != NULL) {
                resFrameNumber = reply.readInt64(lastFrameNumber);
            }
        }
        if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
            res = FAILED_TRANSACTION;
        }
        return res;
    }

    virtual status_t cancelRequest(int requestId, int64_t *lastFrameNumber)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
@@ -106,7 +160,18 @@ public:
        remote()->transact(CANCEL_REQUEST, data, &reply);

        reply.readExceptionCode();
        return reply.readInt32();
        status_t res = reply.readInt32();

        status_t resFrameNumber = BAD_VALUE;
        if (reply.readInt32() != 0) {
            if (lastFrameNumber != NULL) {
                res = reply.readInt64(lastFrameNumber);
            }
        }
        if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
            res = FAILED_TRANSACTION;
        }
        return res;
    }

    virtual status_t deleteStream(int streamId)
@@ -197,14 +262,25 @@ public:
        return reply.readInt32();
    }

    virtual status_t flush()
    virtual status_t flush(int64_t *lastFrameNumber)
    {
        ALOGV("flush");
        Parcel data, reply;
        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
        remote()->transact(FLUSH, data, &reply);
        reply.readExceptionCode();
        return reply.readInt32();
        status_t res = reply.readInt32();

        status_t resFrameNumber = BAD_VALUE;
        if (reply.readInt32() != 0) {
            if (lastFrameNumber != NULL) {
                res = reply.readInt64(lastFrameNumber);
            }
        }
        if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
            res = FAILED_TRANSACTION;
        }
        return res;
    }

private:
@@ -239,11 +315,43 @@ status_t BnCameraDeviceUser::onTransact(
            }

            // arg1 = streaming (bool)
            bool streaming = data.readInt32();
            bool repeating = data.readInt32();

            // return code: requestId (int32)
            reply->writeNoException();
            reply->writeInt32(submitRequest(request, streaming));
            int64_t lastFrameNumber = -1;
            reply->writeInt32(submitRequest(request, repeating, &lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);

            return NO_ERROR;
        } break;
        case SUBMIT_REQUEST_LIST: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            List<sp<CaptureRequest> > requestList;
            int requestListSize = data.readInt32();
            for (int i = 0; i < requestListSize; i++) {
                if (data.readInt32() != 0) {
                    sp<CaptureRequest> request = new CaptureRequest();
                    if (request->readFromParcel(const_cast<Parcel*>(&data)) != OK) {
                        return BAD_VALUE;
                    }
                    requestList.push_back(request);
                } else {
                    sp<CaptureRequest> request = 0;
                    requestList.push_back(request);
                    ALOGE("A request is missing. Sending in null request.");
                }
            }

            bool repeating = data.readInt32();

            reply->writeNoException();
            int64_t lastFrameNumber = -1;
            reply->writeInt32(submitRequestList(requestList, repeating, &lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);

            return NO_ERROR;
        } break;
@@ -251,7 +359,10 @@ status_t BnCameraDeviceUser::onTransact(
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            int requestId = data.readInt32();
            reply->writeNoException();
            reply->writeInt32(cancelRequest(requestId));
            int64_t lastFrameNumber = -1;
            reply->writeInt32(cancelRequest(requestId, &lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);
            return NO_ERROR;
        } break;
        case DELETE_STREAM: {
@@ -339,7 +450,10 @@ status_t BnCameraDeviceUser::onTransact(
        case FLUSH: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            reply->writeNoException();
            reply->writeInt32(flush());
            int64_t lastFrameNumber = -1;
            reply->writeInt32(flush(&lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);
            return NO_ERROR;
        }
        default:
+90 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_HARDWARE_CAPTURERESULT_H
#define ANDROID_HARDWARE_CAPTURERESULT_H

#include <utils/RefBase.h>
#include <camera/CameraMetadata.h>

namespace android {

/**
 * CaptureResultExtras is a structure to encapsulate various indices for a capture result.
 * These indices are framework-internal and not sent to the HAL.
 */
struct CaptureResultExtras {
    /**
     * An integer to index the request sequence that this result belongs to.
     */
    int32_t requestId;

    /**
     * An integer to index this result inside a request sequence, starting from 0.
     */
    int32_t burstId;

    /**
     * TODO: Add documentation for this field.
     */
    int32_t afTriggerId;

    /**
     * TODO: Add documentation for this field.
     */
    int32_t precaptureTriggerId;

    /**
     * A 64bit integer to index the frame number associated with this result.
     */
    int64_t frameNumber;

    /**
     * Constructor initializes object as invalid by setting requestId to be -1.
     */
    CaptureResultExtras()
        : requestId(-1),
          burstId(0),
          afTriggerId(0),
          precaptureTriggerId(0),
          frameNumber(0) {
    }

    /**
     * This function returns true if it's a valid CaptureResultExtras object.
     * Otherwise, returns false. It is valid only when requestId is non-negative.
     */
    bool isValid();

    status_t                readFromParcel(Parcel* parcel);
    status_t                writeToParcel(Parcel* parcel) const;
};

struct CaptureResult : public virtual LightRefBase<CaptureResult> {
    CameraMetadata          mMetadata;
    CaptureResultExtras     mResultExtras;

    CaptureResult();

    CaptureResult(const CaptureResult& otherResult);

    status_t                readFromParcel(Parcel* parcel);
    status_t                writeToParcel(Parcel* parcel) const;
};

}

#endif /* ANDROID_HARDWARE_CAPTURERESULT_H */
Loading