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

Commit d44ffc82 authored by Igor Murashkin's avatar Igor Murashkin Committed by Android (Google) Code Review
Browse files

Merge changes I5b2eeab2,I71568560

* changes:
  Make android.hardware.photography.Camera work on HAL3+ devices
  Initial implementation of android.hardware.photography.CameraDevice (service)
parents b68fc263 98e24724
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@ LOCAL_SRC_FILES:= \
	ICameraRecordingProxyListener.cpp \
	IProCameraUser.cpp \
	IProCameraCallbacks.cpp \
	photography/ICameraDeviceUser.cpp \
	photography/ICameraDeviceCallbacks.cpp \
	photography/CaptureRequest.cpp \
	ProCamera.cpp \
	CameraBase.cpp \

+175 −0
Original line number Diff line number Diff line
@@ -21,9 +21,13 @@
#include <utils/Errors.h>

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

namespace android {

typedef Parcel::WritableBlob WritableBlob;
typedef Parcel::ReadableBlob ReadableBlob;

CameraMetadata::CameraMetadata() :
        mBuffer(NULL), mLocked(false) {
}
@@ -408,4 +412,175 @@ status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
    return OK;
}

status_t CameraMetadata::readFromParcel(const Parcel& data,
                                        camera_metadata_t** out) {

    status_t err = OK;

    camera_metadata_t* metadata = NULL;

    if (out) {
        *out = NULL;
    }

    // arg0 = metadataSize (int32)
    int32_t metadataSizeTmp = -1;
    if ((err = data.readInt32(&metadataSizeTmp)) != OK) {
        ALOGE("%s: Failed to read metadata size (error %d %s)",
              __FUNCTION__, err, strerror(-err));
        return err;
    }
    const size_t metadataSize = static_cast<size_t>(metadataSizeTmp);

    if (metadataSize == 0) {
        ALOGV("%s: Read 0-sized metadata", __FUNCTION__);
        return OK;
    }

    // NOTE: this doesn't make sense to me. shouldnt the blob
    // know how big it is? why do we have to specify the size
    // to Parcel::readBlob ?

    ReadableBlob blob;
    // arg1 = metadata (blob)
    do {
        if ((err = data.readBlob(metadataSize, &blob)) != OK) {
            ALOGE("%s: Failed to read metadata blob (sized %d). Possible "
                  " serialization bug. Error %d %s",
                  __FUNCTION__, metadataSize, err, strerror(-err));
            break;
        }
        const camera_metadata_t* tmp =
                       reinterpret_cast<const camera_metadata_t*>(blob.data());

        metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
        if (metadata == NULL) {
            // We consider that allocation only fails if the validation
            // also failed, therefore the readFromParcel was a failure.
            err = BAD_VALUE;
        }
    } while(0);
    blob.release();

    if (out) {
        ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata);
        *out = metadata;
    } else if (metadata != NULL) {
        ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata);
        free_camera_metadata(metadata);
    }

    return err;
}

status_t CameraMetadata::writeToParcel(Parcel& data,
                                       const camera_metadata_t* metadata) {
    status_t res = OK;

    // arg0 = metadataSize (int32)

    if (metadata == NULL) {
        return data.writeInt32(0);
    }

    const size_t metadataSize = get_camera_metadata_compact_size(metadata);
    res = data.writeInt32(static_cast<int32_t>(metadataSize));
    if (res != OK) {
        return res;
    }

    // arg1 = metadata (blob)
    WritableBlob blob;
    do {
        res = data.writeBlob(metadataSize, &blob);
        if (res != OK) {
            break;
        }
        copy_camera_metadata(blob.data(), metadataSize, metadata);

        IF_ALOGV() {
            if (validate_camera_metadata_structure(
                        (const camera_metadata_t*)blob.data(),
                        &metadataSize) != OK) {
                ALOGV("%s: Failed to validate metadata %p after writing blob",
                       __FUNCTION__, blob.data());
            } else {
                ALOGV("%s: Metadata written to blob. Validation success",
                        __FUNCTION__);
            }
        }

        // Not too big of a problem since receiving side does hard validation
        // Don't check the size since the compact size could be larger
        if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
            ALOGW("%s: Failed to validate metadata %p before writing blob",
                   __FUNCTION__, metadata);
        }

    } while(false);
    blob.release();

    return res;
}

status_t CameraMetadata::readFromParcel(Parcel *parcel) {

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

    status_t res = OK;

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

    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }

    camera_metadata *buffer = NULL;
    // TODO: reading should return a status code, in case validation fails
    res = CameraMetadata::readFromParcel(*parcel, &buffer);

    if (res != NO_ERROR) {
        ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
              __FUNCTION__);
        return res;
    }

    clear();
    mBuffer = buffer;

    return OK;
}

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

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

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

    return CameraMetadata::writeToParcel(*parcel, mBuffer);
}

void CameraMetadata::swap(CameraMetadata& other) {
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return;
    } else if (other.mLocked) {
        ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
        return;
    }

    camera_metadata* thisBuf = mBuffer;
    camera_metadata* otherBuf = other.mBuffer;

    other.mBuffer = thisBuf;
    mBuffer = otherBuf;
}

}; // namespace android
+35 −1
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@
#include <camera/IProCameraCallbacks.h>
#include <camera/ICamera.h>
#include <camera/ICameraClient.h>
#include <camera/photography/ICameraDeviceUser.h>
#include <camera/photography/ICameraDeviceCallbacks.h>

namespace android {

@@ -117,7 +119,7 @@ public:
        return result;
    }

    // connect to camera service
    // connect to camera service (android.hardware.Camera)
    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId,
                                const String16 &clientPackageName, int clientUid)
    {
@@ -149,6 +151,25 @@ public:
        return interface_cast<IProCameraUser>(reply.readStrongBinder());
    }

    // connect to camera service (android.hardware.photography.CameraDevice)
    virtual sp<ICameraDeviceUser> connect(
            const sp<ICameraDeviceCallbacks>& cameraCb,
            int cameraId,
            const String16& clientPackageName,
            int clientUid)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
        data.writeStrongBinder(cameraCb->asBinder());
        data.writeInt32(cameraId);
        data.writeString16(clientPackageName);
        data.writeInt32(clientUid);
        remote()->transact(BnCameraService::CONNECT_DEVICE, data, &reply);

        if (readExceptionCode(reply)) return NULL;
        return interface_cast<ICameraDeviceUser>(reply.readStrongBinder());
    }

    virtual status_t addListener(const sp<ICameraServiceListener>& listener)
    {
        Parcel data, reply;
@@ -226,6 +247,19 @@ status_t BnCameraService::onTransact(
            reply->writeStrongBinder(camera->asBinder());
            return NO_ERROR;
        } break;
        case CONNECT_DEVICE: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraDeviceCallbacks> cameraClient =
                interface_cast<ICameraDeviceCallbacks>(data.readStrongBinder());
            int32_t cameraId = data.readInt32();
            const String16 clientName = data.readString16();
            int32_t clientUid = data.readInt32();
            sp<ICameraDeviceUser> camera = connect(cameraClient, cameraId,
                                                clientName, clientUid);
            reply->writeNoException();
            reply->writeStrongBinder(camera->asBinder());
            return NO_ERROR;
        } break;
        case ADD_LISTENER: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraServiceListener> listener =
+3 −6
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@

#include <camera/IProCameraCallbacks.h>

#include <system/camera_metadata.h>
#include "camera/CameraMetadata.h"

namespace android {

@@ -38,9 +38,6 @@ enum {
    RESULT_RECEIVED,
};

void readMetadata(const Parcel& data, camera_metadata_t** out);
void writeMetadata(Parcel& data, camera_metadata_t* metadata);

class BpProCameraCallbacks: public BpInterface<IProCameraCallbacks>
{
public:
@@ -75,7 +72,7 @@ public:
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
        data.writeInt32(frameId);
        writeMetadata(data, result);
        CameraMetadata::writeToParcel(data, result);
        remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY);
    }
};
@@ -112,7 +109,7 @@ status_t BnProCameraCallbacks::onTransact(
            CHECK_INTERFACE(IProCameraCallbacks, data, reply);
            int32_t frameId = data.readInt32();
            camera_metadata_t *result = NULL;
            readMetadata(data, &result);
            CameraMetadata::readFromParcel(data, &result);
            onResultReceived(frameId, result);
            return NO_ERROR;
            break;
+8 −112
Original line number Diff line number Diff line
@@ -24,13 +24,10 @@
#include <camera/IProCameraUser.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <system/camera_metadata.h>
#include "camera/CameraMetadata.h"

namespace android {

typedef Parcel::WritableBlob WritableBlob;
typedef Parcel::ReadableBlob ReadableBlob;

enum {
    DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
    CONNECT,
@@ -46,107 +43,6 @@ enum {
    GET_CAMERA_INFO,
};

/**
  * Caller becomes the owner of the new metadata
  * 'const Parcel' doesnt prevent us from calling the read functions.
  *  which is interesting since it changes the internal state
  *
  * NULL can be returned when no metadata was sent, OR if there was an issue
  * unpacking the serialized data (i.e. bad parcel or invalid structure).
  */
void readMetadata(const Parcel& data, camera_metadata_t** out) {

    status_t err = OK;

    camera_metadata_t* metadata = NULL;

    if (out) {
        *out = NULL;
    }

    // arg0 = metadataSize (int32)
    int32_t metadataSizeTmp = -1;
    if ((err = data.readInt32(&metadataSizeTmp)) != OK) {
        ALOGE("%s: Failed to read metadata size (error %d %s)",
              __FUNCTION__, err, strerror(-err));
        return;
    }
    const size_t metadataSize = static_cast<size_t>(metadataSizeTmp);

    if (metadataSize == 0) {
        return;
    }

    // NOTE: this doesn't make sense to me. shouldnt the blob
    // know how big it is? why do we have to specify the size
    // to Parcel::readBlob ?

    ReadableBlob blob;
    // arg1 = metadata (blob)
    do {
        if ((err = data.readBlob(metadataSize, &blob)) != OK) {
            ALOGE("%s: Failed to read metadata blob (sized %d). Possible "
                  " serialization bug. Error %d %s",
                  __FUNCTION__, metadataSize, err, strerror(-err));
            break;
        }
        const camera_metadata_t* tmp =
                       reinterpret_cast<const camera_metadata_t*>(blob.data());

        metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
    } while(0);
    blob.release();

    if (out) {
        *out = metadata;
    } else if (metadata != NULL) {
        free_camera_metadata(metadata);
    }
}

/**
  * Caller retains ownership of metadata
  * - Write 2 (int32 + blob) args in the current position
  */
void writeMetadata(Parcel& data, camera_metadata_t* metadata) {
    // arg0 = metadataSize (int32)

    if (metadata == NULL) {
        data.writeInt32(0);
        return;
    }

    const size_t metadataSize = get_camera_metadata_compact_size(metadata);
    data.writeInt32(static_cast<int32_t>(metadataSize));

    // arg1 = metadata (blob)
    WritableBlob blob;
    {
        data.writeBlob(metadataSize, &blob);
        copy_camera_metadata(blob.data(), metadataSize, metadata);

        IF_ALOGV() {
            if (validate_camera_metadata_structure(
                        (const camera_metadata_t*)blob.data(),
                        &metadataSize) != OK) {
                ALOGV("%s: Failed to validate metadata %p after writing blob",
                       __FUNCTION__, blob.data());
            } else {
                ALOGV("%s: Metadata written to blob. Validation success",
                        __FUNCTION__);
            }
        }

        // Not too big of a problem since receiving side does hard validation
        if (validate_camera_metadata_structure(metadata, &metadataSize) != OK) {
            ALOGW("%s: Failed to validate metadata %p before writing blob",
                   __FUNCTION__, metadata);
        }

    }
    blob.release();
}

class BpProCameraUser: public BpInterface<IProCameraUser>
{
public:
@@ -214,7 +110,7 @@ public:
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());

        // arg0+arg1
        writeMetadata(data, metadata);
        CameraMetadata::writeToParcel(data, metadata);

        // arg2 = streaming (bool)
        data.writeInt32(streaming);
@@ -275,7 +171,7 @@ public:
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
        data.writeInt32(templateId);
        remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
        readMetadata(reply, /*out*/request);
        CameraMetadata::readFromParcel(reply, /*out*/request);
        return reply.readInt32();
    }

@@ -286,7 +182,7 @@ public:
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
        data.writeInt32(cameraId);
        remote()->transact(GET_CAMERA_INFO, data, &reply);
        readMetadata(reply, /*out*/info);
        CameraMetadata::readFromParcel(reply, /*out*/info);
        return reply.readInt32();
    }

@@ -343,7 +239,7 @@ status_t BnProCameraUser::onTransact(
        case SUBMIT_REQUEST: {
            CHECK_INTERFACE(IProCameraUser, data, reply);
            camera_metadata_t* metadata;
            readMetadata(data, /*out*/&metadata);
            CameraMetadata::readFromParcel(data, /*out*/&metadata);

            // arg2 = streaming (bool)
            bool streaming = data.readInt32();
@@ -395,7 +291,7 @@ status_t BnProCameraUser::onTransact(
            status_t ret;
            ret = createDefaultRequest(templateId, &request);

            writeMetadata(*reply, request);
            CameraMetadata::writeToParcel(*reply, request);
            reply->writeInt32(ret);

            free_camera_metadata(request);
@@ -411,7 +307,7 @@ status_t BnProCameraUser::onTransact(
            status_t ret;
            ret = getCameraInfo(cameraId, &info);

            writeMetadata(*reply, info);
            CameraMetadata::writeToParcel(*reply, info);
            reply->writeInt32(ret);

            free_camera_metadata(info);
Loading