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

Commit bfb5d5ef authored by Igor Murashkin's avatar Igor Murashkin
Browse files

Camera: Add ProCamera private binder interface for an API2-light functionality

Change-Id: I2af7a807c99df75ea659e6e6acc9c4fca6a56274
parent e4e5b2f2
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -12,7 +12,10 @@ LOCAL_SRC_FILES:= \
	ICameraClient.cpp \
	ICameraService.cpp \
	ICameraRecordingProxy.cpp \
	ICameraRecordingProxyListener.cpp
	ICameraRecordingProxyListener.cpp \
	IProCameraUser.cpp \
	IProCameraCallbacks.cpp \
	ProCamera.cpp \

LOCAL_SHARED_LIBRARIES := \
	libcutils \
+2 −1
Original line number Diff line number Diff line
@@ -120,9 +120,10 @@ sp<Camera> Camera::connect(int cameraId)
{
    ALOGV("connect");
    sp<Camera> c = new Camera();
    sp<ICameraClient> cl = c;
    const sp<ICameraService>& cs = getCameraService();
    if (cs != 0) {
        c->mCamera = cs->connect(c, cameraId);
        c->mCamera = cs->connect(cl, cameraId);
    }
    if (c->mCamera != 0) {
        c->mCamera->asBinder()->linkToDeath(c);
+18 −0
Original line number Diff line number Diff line
@@ -65,6 +65,17 @@ public:
        remote()->transact(BnCameraService::CONNECT, data, &reply);
        return interface_cast<ICamera>(reply.readStrongBinder());
    }

    // connect to camera service (pro client)
    virtual sp<IProCameraUser> connect(const sp<IProCameraCallbacks>& cameraCb, int cameraId)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
        data.writeStrongBinder(cameraCb->asBinder());
        data.writeInt32(cameraId);
        remote()->transact(BnCameraService::CONNECT_PRO, data, &reply);
        return interface_cast<IProCameraUser>(reply.readStrongBinder());
    }
};

IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService");
@@ -97,6 +108,13 @@ status_t BnCameraService::onTransact(
            reply->writeStrongBinder(camera->asBinder());
            return NO_ERROR;
        } break;
        case CONNECT_PRO: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<IProCameraCallbacks> cameraClient = interface_cast<IProCameraCallbacks>(data.readStrongBinder());
            sp<IProCameraUser> camera = connect(cameraClient, data.readInt32());
            reply->writeStrongBinder(camera->asBinder());
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
+144 −0
Original line number Diff line number Diff line
/*
**
** Copyright 2013, 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_NDEBUG 0
#define LOG_TAG "IProCameraCallbacks"
#include <utils/Log.h>
#include <stdint.h>
#include <sys/types.h>

#include <binder/Parcel.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <utils/Mutex.h>

#include <camera/IProCameraCallbacks.h>

namespace android {

enum {
    NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
    DATA_CALLBACK,
    DATA_CALLBACK_TIMESTAMP,
};

class BpProCameraCallbacks: public BpInterface<IProCameraCallbacks>
{
public:
    BpProCameraCallbacks(const sp<IBinder>& impl)
        : BpInterface<IProCameraCallbacks>(impl)
    {
    }

    // generic callback from camera service to app
    void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
    {
        ALOGV("notifyCallback");
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
        data.writeInt32(msgType);
        data.writeInt32(ext1);
        data.writeInt32(ext2);
        remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
    }

    // generic data callback from camera service to app with image data
    void dataCallback(int32_t msgType, const sp<IMemory>& imageData,
                      camera_frame_metadata_t *metadata)
    {
        ALOGV("dataCallback");
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
        data.writeInt32(msgType);
        data.writeStrongBinder(imageData->asBinder());
        if (metadata) {
            data.writeInt32(metadata->number_of_faces);
            data.write(metadata->faces,
                            sizeof(camera_face_t) * metadata->number_of_faces);
        }
        remote()->transact(DATA_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
    }

    // generic data callback from camera service to app with image data
    void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
                                                  const sp<IMemory>& imageData)
    {
        ALOGV("dataCallback");
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
        data.writeInt64(timestamp);
        data.writeInt32(msgType);
        data.writeStrongBinder(imageData->asBinder());
        remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply,
                                                          IBinder::FLAG_ONEWAY);
    }
};

IMPLEMENT_META_INTERFACE(ProCameraCallbacks,
                                        "android.hardware.IProCameraCallbacks");

// ----------------------------------------------------------------------

status_t BnProCameraCallbacks::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case NOTIFY_CALLBACK: {
            ALOGV("NOTIFY_CALLBACK");
            CHECK_INTERFACE(IProCameraCallbacks, data, reply);
            int32_t msgType = data.readInt32();
            int32_t ext1 = data.readInt32();
            int32_t ext2 = data.readInt32();
            notifyCallback(msgType, ext1, ext2);
            return NO_ERROR;
        } break;
        case DATA_CALLBACK: {
            ALOGV("DATA_CALLBACK");
            CHECK_INTERFACE(IProCameraCallbacks, data, reply);
            int32_t msgType = data.readInt32();
            sp<IMemory> imageData = interface_cast<IMemory>(
                                                       data.readStrongBinder());
            camera_frame_metadata_t *metadata = NULL;
            if (data.dataAvail() > 0) {
                metadata = new camera_frame_metadata_t;
                metadata->number_of_faces = data.readInt32();
                metadata->faces = (camera_face_t *) data.readInplace(
                        sizeof(camera_face_t) * metadata->number_of_faces);
            }
            dataCallback(msgType, imageData, metadata);
            if (metadata) delete metadata;
            return NO_ERROR;
        } break;
        case DATA_CALLBACK_TIMESTAMP: {
            ALOGV("DATA_CALLBACK_TIMESTAMP");
            CHECK_INTERFACE(IProCameraCallbacks, data, reply);
            nsecs_t timestamp = data.readInt64();
            int32_t msgType = data.readInt32();
            sp<IMemory> imageData = interface_cast<IMemory>(
                                                       data.readStrongBinder());
            dataCallbackTimestamp(timestamp, msgType, imageData);
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

// ----------------------------------------------------------------------------

}; // namespace android
+264 −0
Original line number Diff line number Diff line
/*
**
** Copyright 2013, 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_NDEBUG 0
#define LOG_TAG "IProCameraUser"
#include <utils/Log.h>
#include <stdint.h>
#include <sys/types.h>
#include <binder/Parcel.h>
#include <camera/IProCameraUser.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <system/camera_metadata.h>

namespace android {

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

enum {
    DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
    CONNECT,
    EXCLUSIVE_TRY_LOCK,
    EXCLUSIVE_LOCK,
    EXCLUSIVE_UNLOCK,
    HAS_EXCLUSIVE_LOCK,
    SUBMIT_REQUEST,
    CANCEL_REQUEST,
    REQUEST_STREAM,
    CANCEL_STREAM,
};

class BpProCameraUser: public BpInterface<IProCameraUser>
{
public:
    BpProCameraUser(const sp<IBinder>& impl)
        : BpInterface<IProCameraUser>(impl)
    {
    }

    // disconnect from camera service
    void disconnect()
    {
        ALOGV("disconnect");
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
        remote()->transact(DISCONNECT, data, &reply);
    }

    virtual status_t connect(const sp<IProCameraCallbacks>& cameraClient)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
        data.writeStrongBinder(cameraClient->asBinder());
        remote()->transact(CONNECT, data, &reply);
        return reply.readInt32();
    }

    /* Shared ProCameraUser */

    virtual status_t exclusiveTryLock()
    {
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
        remote()->transact(EXCLUSIVE_TRY_LOCK, data, &reply);
        return reply.readInt32();
    }
    virtual status_t exclusiveLock()
    {
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
        remote()->transact(EXCLUSIVE_LOCK, data, &reply);
        return reply.readInt32();
    }

    virtual status_t exclusiveUnlock()
    {
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
        remote()->transact(EXCLUSIVE_UNLOCK, data, &reply);
        return reply.readInt32();
    }

    virtual bool hasExclusiveLock()
    {
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
        remote()->transact(HAS_EXCLUSIVE_LOCK, data, &reply);
        return !!reply.readInt32();
    }

    virtual int submitRequest(camera_metadata_t* metadata, bool streaming)
    {

        Parcel data, reply;
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());

        // arg0 = metadataSize (int32)
        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);
        }
        blob.release();

        // arg2 = streaming (bool)
        data.writeInt32(streaming);

        remote()->transact(SUBMIT_REQUEST, data, &reply);
        return reply.readInt32();
    }

    virtual status_t cancelRequest(int requestId)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
        data.writeInt32(requestId);

        remote()->transact(CANCEL_REQUEST, data, &reply);
        return reply.readInt32();
    }

    virtual status_t requestStream(int streamId)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
        data.writeInt32(streamId);

        remote()->transact(REQUEST_STREAM, data, &reply);
        return reply.readInt32();
    }
    virtual status_t cancelStream(int streamId)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
        data.writeInt32(streamId);

        remote()->transact(CANCEL_STREAM, data, &reply);
        return reply.readInt32();
    }

};

IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser");

// ----------------------------------------------------------------------

status_t BnProCameraUser::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case DISCONNECT: {
            ALOGV("DISCONNECT");
            CHECK_INTERFACE(IProCameraUser, data, reply);
            disconnect();
            return NO_ERROR;
        } break;
        case CONNECT: {
            CHECK_INTERFACE(IProCameraUser, data, reply);
            sp<IProCameraCallbacks> cameraClient =
                   interface_cast<IProCameraCallbacks>(data.readStrongBinder());
            reply->writeInt32(connect(cameraClient));
            return NO_ERROR;
        } break;

        /* Shared ProCameraUser */
        case EXCLUSIVE_TRY_LOCK: {
            CHECK_INTERFACE(IProCameraUser, data, reply);
            reply->writeInt32(exclusiveTryLock());
            return NO_ERROR;
        } break;
        case EXCLUSIVE_LOCK: {
            CHECK_INTERFACE(IProCameraUser, data, reply);
            reply->writeInt32(exclusiveLock());
            return NO_ERROR;
        } break;
        case EXCLUSIVE_UNLOCK: {
            CHECK_INTERFACE(IProCameraUser, data, reply);
            reply->writeInt32(exclusiveUnlock());
            return NO_ERROR;
        } break;
        case HAS_EXCLUSIVE_LOCK: {
            CHECK_INTERFACE(IProCameraUser, data, reply);
            reply->writeInt32(hasExclusiveLock());
            return NO_ERROR;
        } break;
        case SUBMIT_REQUEST: {
            CHECK_INTERFACE(IProCameraUser, data, reply);
            camera_metadata_t* metadata;

            // arg0 = metadataSize (int32)
            size_t metadataSize = static_cast<size_t>(data.readInt32());

            // 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)
            {
                data.readBlob(metadataSize, &blob);
                const camera_metadata_t* tmp =
                        reinterpret_cast<const camera_metadata_t*>(blob.data());
                size_t entry_capacity = get_camera_metadata_entry_capacity(tmp);
                size_t data_capacity = get_camera_metadata_data_capacity(tmp);

                metadata = allocate_camera_metadata(entry_capacity,
                                                                 data_capacity);
                copy_camera_metadata(metadata, metadataSize, tmp);
            }
            blob.release();

            // arg2 = streaming (bool)
            bool streaming = data.readInt32();

            // return code: requestId (int32)
            reply->writeInt32(submitRequest(metadata, streaming));

            return NO_ERROR;
        } break;
        case CANCEL_REQUEST: {
            CHECK_INTERFACE(IProCameraUser, data, reply);
            int requestId = data.readInt32();
            reply->writeInt32(cancelRequest(requestId));
            return NO_ERROR;
        } break;
        case REQUEST_STREAM: {
            CHECK_INTERFACE(IProCameraUser, data, reply);
            int streamId = data.readInt32();
            reply->writeInt32(requestStream(streamId));
            return NO_ERROR;
        } break;
        case CANCEL_STREAM: {
            CHECK_INTERFACE(IProCameraUser, data, reply);
            int streamId = data.readInt32();
            reply->writeInt32(cancelStream(streamId));
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

// ----------------------------------------------------------------------------

}; // namespace android
Loading