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

Commit 7fa43f37 authored by Eino-Ville Talvala's avatar Eino-Ville Talvala
Browse files

Camera: Start of support for version 3.0 of camera device HAL

- Refactor common CameraDevice interface out of Camera2Device
- Initial skeleton only for Camera3Device

Change-Id: I097cc76e2ad102a51712ac114235163245f5482c
parent f5daac42
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -11,7 +11,9 @@ LOCAL_SRC_FILES:= \
    CameraClient.cpp \
    Camera2Client.cpp \
    ProCamera2Client.cpp \
    CameraDeviceBase.cpp \
    Camera2Device.cpp \
    Camera3Device.cpp \
    camera2/Parameters.cpp \
    camera2/FrameProcessor.cpp \
    camera2/StreamingProcessor.cpp \
+25 −3
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include <gui/Surface.h>
#include "camera2/Parameters.h"
#include "Camera2Client.h"
#include "Camera2Device.h"
#include "Camera3Device.h"

#define ALOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
#define ALOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
@@ -45,7 +47,8 @@ Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
        int cameraFacing,
        int clientPid,
        uid_t clientUid,
        int servicePid):
        int servicePid,
        int deviceVersion):
        Client(cameraService, cameraClient, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid),
        mSharedCameraClient(cameraClient),
@@ -54,7 +57,20 @@ Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
    ATRACE_CALL();
    ALOGI("Camera %d: Opened", cameraId);

    switch (deviceVersion) {
        case CAMERA_DEVICE_API_VERSION_2_0:
            mDevice = new Camera2Device(cameraId);
            break;
        case CAMERA_DEVICE_API_VERSION_3_0:
            mDevice = new Camera3Device(cameraId);
            break;
        default:
            ALOGE("Camera %d: Unknown HAL device version %d",
                    cameraId, deviceVersion);
            mDevice = NULL;
            break;
    }


    SharedParameters::Lock l(mParameters);
    l.mParameters.state = Parameters::DISCONNECTED;
@@ -81,6 +97,12 @@ status_t Camera2Client::initialize(camera_module_t *module)
        return res;
    }

    if (mDevice == NULL) {
        ALOGE("%s: Camera %d: No device connected",
                __FUNCTION__, mCameraId);
        return NO_INIT;
    }

    res = mDevice->initialize(module);
    if (res != OK) {
        ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
@@ -1465,7 +1487,7 @@ int Camera2Client::getCameraId() const {
    return mCameraId;
}

const sp<Camera2Device>& Camera2Client::getCameraDevice() {
const sp<CameraDeviceBase>& Camera2Client::getCameraDevice() {
    return mDevice;
}

+11 −9
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
#ifndef ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_H
#define ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_H

#include "Camera2Device.h"
#include "CameraDeviceBase.h"
#include "CameraService.h"
#include "camera2/Parameters.h"
#include "camera2/FrameProcessor.h"
@@ -31,12 +31,12 @@ namespace android {

class IMemory;
/**
 * Implements the android.hardware.camera API on top of
 * camera device HAL version 2.
 * Interface between android.hardware.Camera API and Camera HAL device for versions
 * CAMERA_DEVICE_API_VERSION_2_0 and 3_0.
 */
class Camera2Client :
        public CameraService::Client,
        public Camera2Device::NotificationListener
        public CameraDeviceBase::NotificationListener
{
public:
    /**
@@ -77,7 +77,9 @@ public:
            int cameraFacing,
            int clientPid,
            uid_t clientUid,
            int servicePid);
            int servicePid,
            int deviceVersion);

    virtual ~Camera2Client();

    status_t initialize(camera_module_t *module);
@@ -85,7 +87,7 @@ public:
    virtual status_t dump(int fd, const Vector<String16>& args);

    /**
     * Interface used by Camera2Device
     * Interface used by CameraDeviceBase
     */

    virtual void notifyError(int errorCode, int arg1, int arg2);
@@ -99,7 +101,7 @@ public:
     */

    int getCameraId() const;
    const sp<Camera2Device>& getCameraDevice();
    const sp<CameraDeviceBase>& getCameraDevice();
    const sp<CameraService>& getCameraService();
    camera2::SharedParameters& getParameters();

@@ -211,9 +213,9 @@ private:

    bool mAfInMotion;

    /** Camera2Device instance wrapping HAL2 entry */
    /** CameraDevice instance, wraps HAL camera device */

    sp<Camera2Device> mDevice;
    sp<CameraDeviceBase> mDevice;

    /** Utility members */

+29 −36
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ namespace android {

Camera2Device::Camera2Device(int id):
        mId(id),
        mDevice(NULL)
        mHal2Device(NULL)
{
    ATRACE_CALL();
    ALOGV("%s: Created device for camera %d", __FUNCTION__, id);
@@ -51,7 +51,7 @@ status_t Camera2Device::initialize(camera_module_t *module)
{
    ATRACE_CALL();
    ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
    if (mDevice != NULL) {
    if (mHal2Device != NULL) {
        ALOGE("%s: Already initialized!", __FUNCTION__);
        return INVALID_OPERATION;
    }
@@ -131,7 +131,7 @@ status_t Camera2Device::initialize(camera_module_t *module)
    }

    mDeviceInfo = info.static_camera_characteristics;
    mDevice = device;
    mHal2Device = device;

    return OK;
}
@@ -139,23 +139,23 @@ status_t Camera2Device::initialize(camera_module_t *module)
status_t Camera2Device::disconnect() {
    ATRACE_CALL();
    status_t res = OK;
    if (mDevice) {
    if (mHal2Device) {
        ALOGV("%s: Closing device for camera %d", __FUNCTION__, mId);

        int inProgressCount = mDevice->ops->get_in_progress_count(mDevice);
        int inProgressCount = mHal2Device->ops->get_in_progress_count(mHal2Device);
        if (inProgressCount > 0) {
            ALOGW("%s: Closing camera device %d with %d requests in flight!",
                    __FUNCTION__, mId, inProgressCount);
        }
        mReprocessStreams.clear();
        mStreams.clear();
        res = mDevice->common.close(&mDevice->common);
        res = mHal2Device->common.close(&mHal2Device->common);
        if (res != OK) {
            ALOGE("%s: Could not close camera %d: %s (%d)",
                    __FUNCTION__,
                    mId, strerror(-res), res);
        }
        mDevice = NULL;
        mHal2Device = NULL;
        ALOGV("%s: Shutdown complete", __FUNCTION__);
    }
    return res;
@@ -197,7 +197,7 @@ status_t Camera2Device::dump(int fd, const Vector<String16>& args) {
    write(fd, result.string(), result.size());

    status_t res;
    res = mDevice->ops->dump(mDevice, fd);
    res = mHal2Device->ops->dump(mHal2Device, fd);

    return res;
}
@@ -240,7 +240,7 @@ status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
    status_t res;
    ALOGV("%s: E", __FUNCTION__);

    sp<StreamAdapter> stream = new StreamAdapter(mDevice);
    sp<StreamAdapter> stream = new StreamAdapter(mHal2Device);

    res = stream->connectToDevice(consumer, width, height, format, size);
    if (res != OK) {
@@ -276,7 +276,7 @@ status_t Camera2Device::createReprocessStreamFromStream(int outputId, int *id) {
        return BAD_VALUE;
    }

    sp<ReprocessStreamAdapter> stream = new ReprocessStreamAdapter(mDevice);
    sp<ReprocessStreamAdapter> stream = new ReprocessStreamAdapter(mHal2Device);

    res = stream->connectToDevice((*streamI));
    if (res != OK) {
@@ -401,8 +401,8 @@ status_t Camera2Device::createDefaultRequest(int templateId,
    status_t err;
    ALOGV("%s: E", __FUNCTION__);
    camera_metadata_t *rawRequest;
    err = mDevice->ops->construct_default_request(
        mDevice, templateId, &rawRequest);
    err = mHal2Device->ops->construct_default_request(
        mHal2Device, templateId, &rawRequest);
    request->acquire(rawRequest);
    return err;
}
@@ -417,12 +417,12 @@ status_t Camera2Device::waitUntilDrained() {

    // TODO: Set up notifications from HAL, instead of sleeping here
    uint32_t totalTime = 0;
    while (mDevice->ops->get_in_progress_count(mDevice) > 0) {
    while (mHal2Device->ops->get_in_progress_count(mHal2Device) > 0) {
        usleep(kSleepTime);
        totalTime += kSleepTime;
        if (totalTime > kMaxSleepTime) {
            ALOGE("%s: Waited %d us, %d requests still in flight", __FUNCTION__,
                    mDevice->ops->get_in_progress_count(mDevice), totalTime);
                    mHal2Device->ops->get_in_progress_count(mHal2Device), totalTime);
            return TIMED_OUT;
        }
    }
@@ -433,7 +433,7 @@ status_t Camera2Device::waitUntilDrained() {
status_t Camera2Device::setNotifyCallback(NotificationListener *listener) {
    ATRACE_CALL();
    status_t res;
    res = mDevice->ops->set_notify_callback(mDevice, notificationCallback,
    res = mHal2Device->ops->set_notify_callback(mHal2Device, notificationCallback,
            reinterpret_cast<void*>(listener) );
    if (res != OK) {
        ALOGE("%s: Unable to set notification callback!", __FUNCTION__);
@@ -497,7 +497,7 @@ status_t Camera2Device::triggerAutofocus(uint32_t id) {
    ATRACE_CALL();
    status_t res;
    ALOGV("%s: Triggering autofocus, id %d", __FUNCTION__, id);
    res = mDevice->ops->trigger_action(mDevice,
    res = mHal2Device->ops->trigger_action(mHal2Device,
            CAMERA2_TRIGGER_AUTOFOCUS, id, 0);
    if (res != OK) {
        ALOGE("%s: Error triggering autofocus (id %d)",
@@ -510,7 +510,7 @@ status_t Camera2Device::triggerCancelAutofocus(uint32_t id) {
    ATRACE_CALL();
    status_t res;
    ALOGV("%s: Canceling autofocus, id %d", __FUNCTION__, id);
    res = mDevice->ops->trigger_action(mDevice,
    res = mHal2Device->ops->trigger_action(mHal2Device,
            CAMERA2_TRIGGER_CANCEL_AUTOFOCUS, id, 0);
    if (res != OK) {
        ALOGE("%s: Error canceling autofocus (id %d)",
@@ -523,7 +523,7 @@ status_t Camera2Device::triggerPrecaptureMetering(uint32_t id) {
    ATRACE_CALL();
    status_t res;
    ALOGV("%s: Triggering precapture metering, id %d", __FUNCTION__, id);
    res = mDevice->ops->trigger_action(mDevice,
    res = mHal2Device->ops->trigger_action(mHal2Device,
            CAMERA2_TRIGGER_PRECAPTURE_METERING, id, 0);
    if (res != OK) {
        ALOGE("%s: Error triggering precapture metering (id %d)",
@@ -559,19 +559,12 @@ status_t Camera2Device::pushReprocessBuffer(int reprocessStreamId,
    return res;
}

/**
 * Camera2Device::NotificationListener
 */

Camera2Device::NotificationListener::~NotificationListener() {
}

/**
 * Camera2Device::MetadataQueue
 */

Camera2Device::MetadataQueue::MetadataQueue():
            mDevice(NULL),
            mHal2Device(NULL),
            mFrameCount(0),
            mLatestRequestId(0),
            mCount(0),
@@ -602,7 +595,7 @@ status_t Camera2Device::MetadataQueue::setConsumerDevice(camera2_device_t *d) {
    res = d->ops->set_request_queue_src_ops(d,
            this);
    if (res != OK) return res;
    mDevice = d;
    mHal2Device = d;
    return OK;
}

@@ -835,12 +828,12 @@ status_t Camera2Device::MetadataQueue::signalConsumerLocked() {
    ATRACE_CALL();
    status_t res = OK;
    notEmpty.signal();
    if (mSignalConsumer && mDevice != NULL) {
    if (mSignalConsumer && mHal2Device != NULL) {
        mSignalConsumer = false;

        mMutex.unlock();
        ALOGV("%s: Signaling consumer", __FUNCTION__);
        res = mDevice->ops->notify_request_queue_not_empty(mDevice);
        res = mHal2Device->ops->notify_request_queue_not_empty(mHal2Device);
        mMutex.lock();
    }
    return res;
@@ -939,7 +932,7 @@ int Camera2Device::MetadataQueue::producer_enqueue(

Camera2Device::StreamAdapter::StreamAdapter(camera2_device_t *d):
        mState(RELEASED),
        mDevice(d),
        mHal2Device(d),
        mId(-1),
        mWidth(0), mHeight(0), mFormat(0), mSize(0), mUsage(0),
        mMaxProducerBuffers(0), mMaxConsumerBuffers(0),
@@ -990,7 +983,7 @@ status_t Camera2Device::StreamAdapter::connectToDevice(
    uint32_t formatActual;
    uint32_t usage;
    uint32_t maxBuffers = 2;
    res = mDevice->ops->allocate_stream(mDevice,
    res = mHal2Device->ops->allocate_stream(mHal2Device,
            mWidth, mHeight, mFormatRequested, getStreamOps(),
            &id, &formatActual, &usage, &maxBuffers);
    if (res != OK) {
@@ -1106,7 +1099,7 @@ status_t Camera2Device::StreamAdapter::connectToDevice(
    }

    ALOGV("%s: Registering %d buffers with camera HAL", __FUNCTION__, mTotalBuffers);
    res = mDevice->ops->register_stream_buffers(mDevice,
    res = mHal2Device->ops->register_stream_buffers(mHal2Device,
            mId,
            mTotalBuffers,
            buffers);
@@ -1138,7 +1131,7 @@ status_t Camera2Device::StreamAdapter::release() {
    status_t res;
    ALOGV("%s: Releasing stream %d", __FUNCTION__, mId);
    if (mState >= ALLOCATED) {
        res = mDevice->ops->release_stream(mDevice, mId);
        res = mHal2Device->ops->release_stream(mHal2Device, mId);
        if (res != OK) {
            ALOGE("%s: Unable to release stream %d",
                    __FUNCTION__, mId);
@@ -1319,7 +1312,7 @@ int Camera2Device::StreamAdapter::set_crop(const camera2_stream_ops_t* w,

Camera2Device::ReprocessStreamAdapter::ReprocessStreamAdapter(camera2_device_t *d):
        mState(RELEASED),
        mDevice(d),
        mHal2Device(d),
        mId(-1),
        mWidth(0), mHeight(0), mFormat(0),
        mActiveBuffers(0),
@@ -1361,7 +1354,7 @@ status_t Camera2Device::ReprocessStreamAdapter::connectToDevice(
    // Allocate device-side stream interface

    uint32_t id;
    res = mDevice->ops->allocate_reprocess_stream_from_stream(mDevice,
    res = mHal2Device->ops->allocate_reprocess_stream_from_stream(mHal2Device,
            outputStream->getId(), getStreamOps(),
            &id);
    if (res != OK) {
@@ -1385,7 +1378,7 @@ status_t Camera2Device::ReprocessStreamAdapter::release() {
    status_t res;
    ALOGV("%s: Releasing stream %d", __FUNCTION__, mId);
    if (mState >= ACTIVE) {
        res = mDevice->ops->release_reprocess_stream(mDevice, mId);
        res = mHal2Device->ops->release_reprocess_stream(mHal2Device, mId);
        if (res != OK) {
            ALOGE("%s: Unable to release stream %d",
                    __FUNCTION__, mId);
+34 −165
Original line number Diff line number Diff line
@@ -21,184 +21,53 @@
#include <utils/Errors.h>
#include <utils/List.h>
#include <utils/Mutex.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/Vector.h>

#include "hardware/camera2.h"
#include "camera/CameraMetadata.h"
#include "CameraDeviceBase.h"

namespace android {

class Camera2Device : public virtual RefBase {
  public:
    Camera2Device(int id);

    ~Camera2Device();

    status_t initialize(camera_module_t *module);
    status_t disconnect();

    status_t dump(int fd, const Vector<String16>& args);

    /**
     * The device's static characteristics metadata buffer
     */
    const CameraMetadata& info() const;

/**
     * Submit request for capture. The Camera2Device takes ownership of the
     * passed-in buffer.
 * CameraDevice for HAL devices with version CAMERA_DEVICE_API_VERSION_2_0
 */
    status_t capture(CameraMetadata &request);
class Camera2Device: public CameraDeviceBase {
  public:
    Camera2Device(int id);

    /**
     * Submit request for streaming. The Camera2Device makes a copy of the
     * passed-in buffer and the caller retains ownership.
     */
    status_t setStreamingRequest(const CameraMetadata &request);
    virtual ~Camera2Device();

    /**
     * Clear the streaming request slot.
     * CameraDevice interface
     */
    status_t clearStreamingRequest();

    /**
     * Wait until a request with the given ID has been dequeued by the
     * HAL. Returns TIMED_OUT if the timeout duration is reached. Returns
     * immediately if the latest request received by the HAL has this id.
     */
    status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);

    /**
     * Create an output stream of the requested size and format.
     *
     * If format is CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, then the HAL device selects
     * an appropriate format; it can be queried with getStreamInfo.
     *
     * If format is HAL_PIXEL_FORMAT_COMPRESSED, the size parameter must be
     * equal to the size in bytes of the buffers to allocate for the stream. For
     * other formats, the size parameter is ignored.
     */
    status_t createStream(sp<ANativeWindow> consumer,
    virtual status_t initialize(camera_module_t *module);
    virtual status_t disconnect();
    virtual status_t dump(int fd, const Vector<String16>& args);
    virtual const CameraMetadata& info() const;
    virtual status_t capture(CameraMetadata &request);
    virtual status_t setStreamingRequest(const CameraMetadata &request);
    virtual status_t clearStreamingRequest();
    virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);
    virtual status_t createStream(sp<ANativeWindow> consumer,
            uint32_t width, uint32_t height, int format, size_t size,
            int *id);

    /**
     * Create an input reprocess stream that uses buffers from an existing
     * output stream.
     */
    status_t createReprocessStreamFromStream(int outputId, int *id);

    /**
     * Get information about a given stream.
     */
    status_t getStreamInfo(int id,
    virtual status_t createReprocessStreamFromStream(int outputId, int *id);
    virtual status_t getStreamInfo(int id,
            uint32_t *width, uint32_t *height, uint32_t *format);

    /**
     * Set stream gralloc buffer transform
     */
    status_t setStreamTransform(int id, int transform);

    /**
     * Delete stream. Must not be called if there are requests in flight which
     * reference that stream.
     */
    status_t deleteStream(int id);

    /**
     * Delete reprocess stream. Must not be called if there are requests in
     * flight which reference that stream.
     */
    status_t deleteReprocessStream(int id);

    /**
     * Create a metadata buffer with fields that the HAL device believes are
     * best for the given use case
     */
    status_t createDefaultRequest(int templateId, CameraMetadata *request);

    /**
     * Wait until all requests have been processed. Returns INVALID_OPERATION if
     * the streaming slot is not empty, or TIMED_OUT if the requests haven't
     * finished processing in 10 seconds.
     */
    status_t waitUntilDrained();

    /**
     * Abstract class for HAL notification listeners
     */
    class NotificationListener {
      public:
        // Refer to the Camera2 HAL definition for notification definitions
        virtual void notifyError(int errorCode, int arg1, int arg2) = 0;
        virtual void notifyShutter(int frameNumber, nsecs_t timestamp) = 0;
        virtual void notifyAutoFocus(uint8_t newState, int triggerId) = 0;
        virtual void notifyAutoExposure(uint8_t newState, int triggerId) = 0;
        virtual void notifyAutoWhitebalance(uint8_t newState, int triggerId) = 0;
      protected:
        virtual ~NotificationListener();
    };

    /**
     * Connect HAL notifications to a listener. Overwrites previous
     * listener. Set to NULL to stop receiving notifications.
     */
    status_t setNotifyCallback(NotificationListener *listener);

    /**
     * Wait for a new frame to be produced, with timeout in nanoseconds.
     * Returns TIMED_OUT when no frame produced within the specified duration
     */
    status_t waitForNextFrame(nsecs_t timeout);

    /**
     * Get next metadata frame from the frame queue. Returns NULL if the queue
     * is empty; caller takes ownership of the metadata buffer.
     */
    status_t getNextFrame(CameraMetadata *frame);

    /**
     * Trigger auto-focus. The latest ID used in a trigger autofocus or cancel
     * autofocus call will be returned by the HAL in all subsequent AF
     * notifications.
     */
    status_t triggerAutofocus(uint32_t id);

    /**
     * Cancel auto-focus. The latest ID used in a trigger autofocus/cancel
     * autofocus call will be returned by the HAL in all subsequent AF
     * notifications.
     */
    status_t triggerCancelAutofocus(uint32_t id);

    /**
     * Trigger pre-capture metering. The latest ID used in a trigger pre-capture
     * call will be returned by the HAL in all subsequent AE and AWB
     * notifications.
     */
    status_t triggerPrecaptureMetering(uint32_t id);

    /**
     * Abstract interface for clients that want to listen to reprocess buffer
     * release events
     */
    struct BufferReleasedListener: public virtual RefBase {
        virtual void onBufferReleased(buffer_handle_t *handle) = 0;
    };

    /**
     * Push a buffer to be reprocessed into a reprocessing stream, and
     * provide a listener to call once the buffer is returned by the HAL
     */
    status_t pushReprocessBuffer(int reprocessStreamId,
    virtual status_t setStreamTransform(int id, int transform);
    virtual status_t deleteStream(int id);
    virtual status_t deleteReprocessStream(int id);
    virtual status_t createDefaultRequest(int templateId, CameraMetadata *request);
    virtual status_t waitUntilDrained();
    virtual status_t setNotifyCallback(NotificationListener *listener);
    virtual status_t waitForNextFrame(nsecs_t timeout);
    virtual status_t getNextFrame(CameraMetadata *frame);
    virtual status_t triggerAutofocus(uint32_t id);
    virtual status_t triggerCancelAutofocus(uint32_t id);
    virtual status_t triggerPrecaptureMetering(uint32_t id);
    virtual status_t pushReprocessBuffer(int reprocessStreamId,
            buffer_handle_t *buffer, wp<BufferReleasedListener> listener);

  private:
    const int mId;
    camera2_device_t *mDevice;
    camera2_device_t *mHal2Device;

    CameraMetadata mDeviceInfo;
    vendor_tag_query_ops_t *mVendorTagOps;
@@ -249,7 +118,7 @@ class Camera2Device : public virtual RefBase {
        status_t freeBuffers(List<camera_metadata_t*>::iterator start,
                List<camera_metadata_t*>::iterator end);

        camera2_device_t *mDevice;
        camera2_device_t *mHal2Device;

        Mutex mMutex;
        Condition notEmpty;
@@ -341,7 +210,7 @@ class Camera2Device : public virtual RefBase {
        } mState;

        sp<ANativeWindow> mConsumerInterface;
        camera2_device_t *mDevice;
        camera2_device_t *mHal2Device;

        uint32_t mId;
        uint32_t mWidth;
@@ -435,7 +304,7 @@ class Camera2Device : public virtual RefBase {

        List<QueueEntry> mInFlightQueue;

        camera2_device_t *mDevice;
        camera2_device_t *mHal2Device;

        uint32_t mId;
        uint32_t mWidth;
Loading