Bare-bones emulated fake camera for HAL version 3
- Uses same backend as HAL version 2 fake camera.
- No fake 3A yet
- No reprocessing support
- No JPEG support
Change-Id: I9b55b05fbeac9d42340eb988021e65491d13a2f9
diff --git a/camera/Android.mk b/camera/Android.mk
index 0f1685c..8f20cdb 100755
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -39,27 +39,28 @@
LOCAL_SRC_FILES := \
EmulatedCameraHal.cpp \
- EmulatedCameraFactory.cpp \
- EmulatedBaseCamera.cpp \
- EmulatedCamera.cpp \
- EmulatedCameraDevice.cpp \
- EmulatedQemuCamera.cpp \
- EmulatedQemuCameraDevice.cpp \
- EmulatedFakeCamera.cpp \
- EmulatedFakeCameraDevice.cpp \
- Converters.cpp \
- PreviewWindow.cpp \
- CallbackNotifier.cpp \
- QemuClient.cpp \
- JpegCompressor.cpp \
- EmulatedCamera2.cpp \
- EmulatedCameraHotplugThread.cpp \
- EmulatedFakeCamera2.cpp \
- EmulatedQemuCamera2.cpp \
- fake-pipeline2/Scene.cpp \
- fake-pipeline2/Sensor.cpp \
- fake-pipeline2/JpegCompressor.cpp
-
+ EmulatedCameraFactory.cpp \
+ EmulatedCameraHotplugThread.cpp \
+ EmulatedBaseCamera.cpp \
+ EmulatedCamera.cpp \
+ EmulatedCameraDevice.cpp \
+ EmulatedQemuCamera.cpp \
+ EmulatedQemuCameraDevice.cpp \
+ EmulatedFakeCamera.cpp \
+ EmulatedFakeCameraDevice.cpp \
+ Converters.cpp \
+ PreviewWindow.cpp \
+ CallbackNotifier.cpp \
+ QemuClient.cpp \
+ JpegCompressor.cpp \
+ EmulatedCamera2.cpp \
+ EmulatedFakeCamera2.cpp \
+ EmulatedQemuCamera2.cpp \
+ fake-pipeline2/Scene.cpp \
+ fake-pipeline2/Sensor.cpp \
+ fake-pipeline2/JpegCompressor.cpp \
+ EmulatedCamera3.cpp \
+ EmulatedFakeCamera3.cpp
ifeq ($(TARGET_PRODUCT),vbox_x86)
LOCAL_MODULE := camera.vbox_x86
diff --git a/camera/EmulatedCamera3.cpp b/camera/EmulatedCamera3.cpp
new file mode 100644
index 0000000..47de44f
--- /dev/null
+++ b/camera/EmulatedCamera3.cpp
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 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.
+ */
+
+/**
+ * Contains implementation of a class EmulatedCamera that encapsulates
+ * functionality common to all version 3.0 emulated camera devices. Instances
+ * of this class (for each emulated camera) are created during the construction
+ * of the EmulatedCameraFactory instance. This class serves as an entry point
+ * for all camera API calls that defined by camera3_device_ops_t API.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera3_Camera"
+#include <cutils/log.h>
+
+#include "EmulatedCamera3.h"
+#include "system/camera_metadata.h"
+
+namespace android {
+
+/**
+ * Constructs EmulatedCamera3 instance.
+ * Param:
+ * cameraId - Zero based camera identifier, which is an index of the camera
+ * instance in camera factory's array.
+ * module - Emulated camera HAL module descriptor.
+ */
+EmulatedCamera3::EmulatedCamera3(int cameraId,
+ struct hw_module_t* module):
+ EmulatedBaseCamera(cameraId,
+ CAMERA_DEVICE_API_VERSION_3_0,
+ &common,
+ module),
+ mStatus(STATUS_ERROR)
+{
+ common.close = EmulatedCamera3::close;
+ ops = &sDeviceOps;
+
+ mCallbackOps = NULL;
+
+ mVendorTagOps.get_camera_vendor_section_name =
+ EmulatedCamera3::get_camera_vendor_section_name;
+ mVendorTagOps.get_camera_vendor_tag_name =
+ EmulatedCamera3::get_camera_vendor_tag_name;
+ mVendorTagOps.get_camera_vendor_tag_type =
+ EmulatedCamera3::get_camera_vendor_tag_type;
+ mVendorTagOps.parent = this;
+}
+
+/* Destructs EmulatedCamera3 instance. */
+EmulatedCamera3::~EmulatedCamera3() {
+}
+
+/****************************************************************************
+ * Abstract API
+ ***************************************************************************/
+
+/****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+status_t EmulatedCamera3::Initialize() {
+ ALOGV("%s", __FUNCTION__);
+
+ mStatus = STATUS_CLOSED;
+ return NO_ERROR;
+}
+
+/****************************************************************************
+ * Camera API implementation
+ ***************************************************************************/
+
+status_t EmulatedCamera3::connectCamera(hw_device_t** device) {
+ ALOGV("%s", __FUNCTION__);
+ if (device == NULL) return BAD_VALUE;
+
+ if (mStatus != STATUS_CLOSED) {
+ ALOGE("%s: Trying to open a camera in state %d!",
+ __FUNCTION__, mStatus);
+ return INVALID_OPERATION;
+ }
+
+ *device = &common;
+ mStatus = STATUS_OPEN;
+ return NO_ERROR;
+}
+
+status_t EmulatedCamera3::closeCamera() {
+ mStatus = STATUS_CLOSED;
+ return NO_ERROR;
+}
+
+status_t EmulatedCamera3::getCameraInfo(struct camera_info* info) {
+ return EmulatedBaseCamera::getCameraInfo(info);
+}
+
+/****************************************************************************
+ * Camera Device API implementation.
+ * These methods are called from the camera API callback routines.
+ ***************************************************************************/
+
+status_t EmulatedCamera3::initializeDevice(
+ const camera3_callback_ops *callbackOps) {
+ if (callbackOps == NULL) {
+ ALOGE("%s: NULL callback ops provided to HAL!",
+ __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (mStatus != STATUS_OPEN) {
+ ALOGE("%s: Trying to initialize a camera in state %d!",
+ __FUNCTION__, mStatus);
+ return INVALID_OPERATION;
+ }
+
+ mCallbackOps = callbackOps;
+ mStatus = STATUS_READY;
+
+ return NO_ERROR;
+}
+
+status_t EmulatedCamera3::configureStreams(
+ camera3_stream_configuration *streamList) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+status_t EmulatedCamera3::registerStreamBuffers(
+ const camera3_stream_buffer_set *bufferSet) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+const camera_metadata_t* EmulatedCamera3::constructDefaultRequestSettings(
+ int type) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return NULL;
+}
+
+status_t EmulatedCamera3::processCaptureRequest(
+ camera3_capture_request *request) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+/** Custom tag query methods */
+
+const char* EmulatedCamera3::getVendorSectionName(uint32_t tag) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return NULL;
+}
+
+const char* EmulatedCamera3::getVendorTagName(uint32_t tag) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return NULL;
+}
+
+int EmulatedCamera3::getVendorTagType(uint32_t tag) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return -1;
+}
+
+/** Debug methods */
+
+void EmulatedCamera3::dump(int fd) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return;
+}
+
+/****************************************************************************
+ * Protected API. Callbacks to the framework.
+ ***************************************************************************/
+
+void EmulatedCamera3::sendCaptureResult(camera3_capture_result_t *result) {
+ mCallbackOps->process_capture_result(mCallbackOps, result);
+}
+
+void EmulatedCamera3::sendNotify(camera3_notify_msg_t *msg) {
+ mCallbackOps->notify(mCallbackOps, msg);
+}
+
+/****************************************************************************
+ * Private API.
+ ***************************************************************************/
+
+/****************************************************************************
+ * Camera API callbacks as defined by camera3_device_ops structure. See
+ * hardware/libhardware/include/hardware/camera3.h for information on each
+ * of these callbacks. Implemented in this class, these callbacks simply
+ * dispatch the call into an instance of EmulatedCamera3 class defined by the
+ * 'camera_device3' parameter, or set a member value in the same.
+ ***************************************************************************/
+
+EmulatedCamera3* getInstance(const camera3_device_t *d) {
+ const EmulatedCamera3* cec = static_cast<const EmulatedCamera3*>(d);
+ return const_cast<EmulatedCamera3*>(cec);
+}
+
+int EmulatedCamera3::initialize(const struct camera3_device *d,
+ const camera3_callback_ops_t *callback_ops) {
+ EmulatedCamera3* ec = getInstance(d);
+ return ec->initializeDevice(callback_ops);
+}
+
+int EmulatedCamera3::configure_streams(const struct camera3_device *d,
+ camera3_stream_configuration_t *stream_list) {
+ EmulatedCamera3* ec = getInstance(d);
+ return ec->configureStreams(stream_list);
+}
+
+int EmulatedCamera3::register_stream_buffers(
+ const struct camera3_device *d,
+ const camera3_stream_buffer_set_t *buffer_set) {
+ EmulatedCamera3* ec = getInstance(d);
+ return ec->registerStreamBuffers(buffer_set);
+}
+
+int EmulatedCamera3::process_capture_request(
+ const struct camera3_device *d,
+ camera3_capture_request_t *request) {
+ EmulatedCamera3* ec = getInstance(d);
+ return ec->processCaptureRequest(request);
+}
+
+const camera_metadata_t* EmulatedCamera3::construct_default_request_settings(
+ const camera3_device_t *d, int type) {
+ EmulatedCamera3* ec = getInstance(d);
+ return ec->constructDefaultRequestSettings(type);
+}
+
+void EmulatedCamera3::get_metadata_vendor_tag_ops(const camera3_device_t *d,
+ vendor_tag_query_ops_t *ops) {
+ ops->get_camera_vendor_section_name = get_camera_vendor_section_name;
+ ops->get_camera_vendor_tag_name = get_camera_vendor_tag_name;
+ ops->get_camera_vendor_tag_type = get_camera_vendor_tag_type;
+}
+
+const char* EmulatedCamera3::get_camera_vendor_section_name(
+ const vendor_tag_query_ops_t *v,
+ uint32_t tag) {
+ EmulatedCamera3* ec = static_cast<const TagOps*>(v)->parent;
+ return ec->getVendorSectionName(tag);
+}
+
+const char* EmulatedCamera3::get_camera_vendor_tag_name(
+ const vendor_tag_query_ops_t *v,
+ uint32_t tag) {
+ EmulatedCamera3* ec = static_cast<const TagOps*>(v)->parent;
+ return ec->getVendorTagName(tag);
+}
+
+int EmulatedCamera3::get_camera_vendor_tag_type(
+ const vendor_tag_query_ops_t *v,
+ uint32_t tag) {
+ EmulatedCamera3* ec = static_cast<const TagOps*>(v)->parent;
+ return ec->getVendorTagType(tag);
+}
+
+void EmulatedCamera3::dump(const camera3_device_t *d, int fd) {
+ EmulatedCamera3* ec = getInstance(d);
+ ec->dump(fd);
+}
+
+int EmulatedCamera3::close(struct hw_device_t* device) {
+ EmulatedCamera3* ec =
+ static_cast<EmulatedCamera3*>(
+ reinterpret_cast<camera3_device_t*>(device) );
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera3 device", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ return ec->closeCamera();
+}
+
+camera3_device_ops_t EmulatedCamera3::sDeviceOps = {
+ EmulatedCamera3::initialize,
+ EmulatedCamera3::configure_streams,
+ EmulatedCamera3::register_stream_buffers,
+ EmulatedCamera3::construct_default_request_settings,
+ EmulatedCamera3::process_capture_request,
+ EmulatedCamera3::get_metadata_vendor_tag_ops,
+ EmulatedCamera3::dump
+};
+
+}; /* namespace android */
diff --git a/camera/EmulatedCamera3.h b/camera/EmulatedCamera3.h
new file mode 100644
index 0000000..c1bddf6
--- /dev/null
+++ b/camera/EmulatedCamera3.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H
+#define HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H
+
+/**
+ * Contains declaration of a class EmulatedCamera that encapsulates
+ * functionality common to all version 3.0 emulated camera devices. Instances
+ * of this class (for each emulated camera) are created during the construction
+ * of the EmulatedCameraFactory instance. This class serves as an entry point
+ * for all camera API calls that defined by camera3_device_ops_t API.
+ */
+
+#include "hardware/camera3.h"
+#include "system/camera_metadata.h"
+#include "EmulatedBaseCamera.h"
+
+namespace android {
+
+/**
+ * Encapsulates functionality common to all version 3.0 emulated camera devices
+ *
+ * Note that EmulatedCameraFactory instantiates an object of this class just
+ * once, when EmulatedCameraFactory instance gets constructed. Connection to /
+ * disconnection from the actual camera device is handled by calls to
+ * connectDevice(), and closeCamera() methods of this class that are invoked in
+ * response to hw_module_methods_t::open, and camera_device::close callbacks.
+ */
+class EmulatedCamera3 : public camera3_device, public EmulatedBaseCamera {
+public:
+ /* Constructs EmulatedCamera3 instance.
+ * Param:
+ * cameraId - Zero based camera identifier, which is an index of the camera
+ * instance in camera factory's array.
+ * module - Emulated camera HAL module descriptor.
+ */
+ EmulatedCamera3(int cameraId,
+ struct hw_module_t* module);
+
+ /* Destructs EmulatedCamera2 instance. */
+ virtual ~EmulatedCamera3();
+
+ /****************************************************************************
+ * Abstract API
+ ***************************************************************************/
+
+public:
+
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+public:
+ virtual status_t Initialize();
+
+ /****************************************************************************
+ * Camera module API and generic hardware device API implementation
+ ***************************************************************************/
+
+public:
+ virtual status_t connectCamera(hw_device_t** device);
+
+ virtual status_t closeCamera();
+
+ virtual status_t getCameraInfo(struct camera_info* info);
+
+ /****************************************************************************
+ * Camera API implementation.
+ * These methods are called from the camera API callback routines.
+ ***************************************************************************/
+
+protected:
+
+ virtual status_t initializeDevice(
+ const camera3_callback_ops *callbackOps);
+
+ virtual status_t configureStreams(
+ camera3_stream_configuration *streamList);
+
+ virtual status_t registerStreamBuffers(
+ const camera3_stream_buffer_set *bufferSet) ;
+
+ virtual const camera_metadata_t* constructDefaultRequestSettings(
+ int type);
+
+ virtual status_t processCaptureRequest(camera3_capture_request *request);
+
+ /** Debug methods */
+
+ virtual void dump(int fd);
+
+ /** Tag query methods */
+ virtual const char *getVendorSectionName(uint32_t tag);
+
+ virtual const char *getVendorTagName(uint32_t tag);
+
+ virtual int getVendorTagType(uint32_t tag);
+
+ /****************************************************************************
+ * Camera API callbacks as defined by camera3_device_ops structure. See
+ * hardware/libhardware/include/hardware/camera3.h for information on each
+ * of these callbacks. Implemented in this class, these callbacks simply
+ * dispatch the call into an instance of EmulatedCamera3 class defined in
+ * the 'camera_device3' parameter.
+ ***************************************************************************/
+
+private:
+
+ /** Startup */
+ static int initialize(const struct camera3_device *,
+ const camera3_callback_ops_t *callback_ops);
+
+ /** Stream configuration and buffer registration */
+
+ static int configure_streams(const struct camera3_device *,
+ camera3_stream_configuration_t *stream_list);
+
+ static int register_stream_buffers(const struct camera3_device *,
+ const camera3_stream_buffer_set_t *buffer_set);
+
+ /** Template request settings provision */
+
+ static const camera_metadata_t* construct_default_request_settings(
+ const struct camera3_device *, int type);
+
+ /** Submission of capture requests to HAL */
+
+ static int process_capture_request(const struct camera3_device *,
+ camera3_capture_request_t *request);
+
+ /** Vendor metadata registration */
+ static void get_metadata_vendor_tag_ops(const camera3_device_t *,
+ vendor_tag_query_ops_t *ops);
+ // for get_metadata_vendor_tag_ops
+ static const char* get_camera_vendor_section_name(
+ const vendor_tag_query_ops_t *,
+ uint32_t tag);
+ static const char* get_camera_vendor_tag_name(
+ const vendor_tag_query_ops_t *,
+ uint32_t tag);
+ static int get_camera_vendor_tag_type(
+ const vendor_tag_query_ops_t *,
+ uint32_t tag);
+
+ static void dump(const camera3_device_t *, int fd);
+
+ /** For hw_device_t ops */
+ static int close(struct hw_device_t* device);
+
+ /****************************************************************************
+ * Data members shared with implementations
+ ***************************************************************************/
+ protected:
+
+ struct TagOps : public vendor_tag_query_ops {
+ EmulatedCamera3 *parent;
+ };
+ TagOps mVendorTagOps;
+
+ enum {
+ // State at construction time, and after a device operation error
+ STATUS_ERROR = 0,
+ // State after startup-time init and after device instance close
+ STATUS_CLOSED,
+ // State after being opened, before device instance init
+ STATUS_OPEN,
+ // State after device instance initialization
+ STATUS_READY,
+ // State while actively capturing data
+ STATUS_ACTIVE
+ } mStatus;
+
+ /**
+ * Callbacks back to the framework
+ */
+
+ void sendCaptureResult(camera3_capture_result_t *result);
+ void sendNotify(camera3_notify_msg_t *msg);
+
+ /****************************************************************************
+ * Data members
+ ***************************************************************************/
+ private:
+ static camera3_device_ops_t sDeviceOps;
+ const camera3_callback_ops_t *mCallbackOps;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H */
diff --git a/camera/EmulatedCameraFactory.cpp b/camera/EmulatedCameraFactory.cpp
index d36a215..0a8ada7 100755
--- a/camera/EmulatedCameraFactory.cpp
+++ b/camera/EmulatedCameraFactory.cpp
@@ -26,6 +26,7 @@
#include "EmulatedQemuCamera.h"
#include "EmulatedFakeCamera.h"
#include "EmulatedFakeCamera2.h"
+#include "EmulatedFakeCamera3.h"
#include "EmulatedCameraHotplugThread.h"
#include "EmulatedCameraFactory.h"
@@ -86,6 +87,11 @@
new EmulatedFakeCamera2(camera_id, true,
&HAL_MODULE_INFO_SYM.common);
break;
+ case 3:
+ mEmulatedCameras[camera_id] =
+ new EmulatedFakeCamera3(camera_id, true,
+ &HAL_MODULE_INFO_SYM.common);
+ break;
default:
ALOGE("%s: Unknown back camera hal version requested: %d", __FUNCTION__,
getBackCameraHalVersion());
@@ -137,6 +143,11 @@
new EmulatedFakeCamera2(camera_id, false,
&HAL_MODULE_INFO_SYM.common);
break;
+ case 3:
+ mEmulatedCameras[camera_id] =
+ new EmulatedFakeCamera3(camera_id, false,
+ &HAL_MODULE_INFO_SYM.common);
+ break;
default:
ALOGE("%s: Unknown front camera hal version requested: %d",
__FUNCTION__,
diff --git a/camera/EmulatedFakeCamera2.cpp b/camera/EmulatedFakeCamera2.cpp
index ab69063..0fe3a30 100644
--- a/camera/EmulatedFakeCamera2.cpp
+++ b/camera/EmulatedFakeCamera2.cpp
@@ -157,7 +157,7 @@
mConfigureThread = new ConfigureThread(this);
mReadoutThread = new ReadoutThread(this);
mControlThread = new ControlThread(this);
- mSensor = new Sensor(this);
+ mSensor = new Sensor();
mJpegCompressor = new JpegCompressor(this);
mNextStreamId = 1;
diff --git a/camera/EmulatedFakeCamera3.cpp b/camera/EmulatedFakeCamera3.cpp
new file mode 100644
index 0000000..8fd4df0
--- /dev/null
+++ b/camera/EmulatedFakeCamera3.cpp
@@ -0,0 +1,1339 @@
+/*
+ * Copyright (C) 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedFakeCamera3 that encapsulates
+ * functionality of an advanced fake camera.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_FakeCamera3"
+#include <utils/Log.h>
+
+#include "EmulatedFakeCamera3.h"
+#include "EmulatedCameraFactory.h"
+#include <ui/Fence.h>
+#include <ui/Rect.h>
+#include <ui/GraphicBufferMapper.h>
+#include "gralloc_cb.h"
+#include "fake-pipeline2/Sensor.h"
+#include "fake-pipeline2/JpegCompressor.h"
+
+namespace android {
+
+/**
+ * Constants for camera capabilities
+ */
+
+const int64_t USEC = 1000LL;
+const int64_t MSEC = USEC * 1000LL;
+const int64_t SEC = MSEC * 1000LL;
+
+const uint32_t EmulatedFakeCamera3::kAvailableFormats[4] = {
+ HAL_PIXEL_FORMAT_RAW_SENSOR,
+ HAL_PIXEL_FORMAT_BLOB,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ // HAL_PIXEL_FORMAT_YV12,
+ HAL_PIXEL_FORMAT_YCrCb_420_SP
+};
+
+const uint32_t EmulatedFakeCamera3::kAvailableRawSizes[2] = {
+ 640, 480
+ // Sensor::kResolution[0], Sensor::kResolution[1]
+};
+
+const uint64_t EmulatedFakeCamera3::kAvailableRawMinDurations[1] = {
+ (const uint64_t)Sensor::kFrameDurationRange[0]
+};
+
+const uint32_t EmulatedFakeCamera3::kAvailableProcessedSizesBack[4] = {
+ 640, 480, 320, 240
+ // Sensor::kResolution[0], Sensor::kResolution[1]
+};
+
+const uint32_t EmulatedFakeCamera3::kAvailableProcessedSizesFront[4] = {
+ 320, 240, 160, 120
+ // Sensor::kResolution[0], Sensor::kResolution[1]
+};
+
+const uint64_t EmulatedFakeCamera3::kAvailableProcessedMinDurations[1] = {
+ (const uint64_t)Sensor::kFrameDurationRange[0]
+};
+
+const uint32_t EmulatedFakeCamera3::kAvailableJpegSizesBack[2] = {
+ 640, 480
+ // Sensor::kResolution[0], Sensor::kResolution[1]
+};
+
+const uint32_t EmulatedFakeCamera3::kAvailableJpegSizesFront[2] = {
+ 320, 240
+ // Sensor::kResolution[0], Sensor::kResolution[1]
+};
+
+
+const uint64_t EmulatedFakeCamera3::kAvailableJpegMinDurations[1] = {
+ (const uint64_t)Sensor::kFrameDurationRange[0]
+};
+
+/**
+ * Camera device lifecycle methods
+ */
+
+EmulatedFakeCamera3::EmulatedFakeCamera3(int cameraId, bool facingBack,
+ struct hw_module_t* module) :
+ EmulatedCamera3(cameraId, module),
+ mFacingBack(facingBack) {
+ ALOGD("Constructing emulated fake camera 3 facing %s",
+ facingBack ? "back" : "front");
+
+ for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++) {
+ mDefaultTemplates[i] = NULL;
+ }
+}
+
+EmulatedFakeCamera3::~EmulatedFakeCamera3() {
+ for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++) {
+ if (mDefaultTemplates[i] != NULL) {
+ free_camera_metadata(mDefaultTemplates[i]);
+ }
+ }
+}
+
+status_t EmulatedFakeCamera3::Initialize() {
+ ALOGV("%s: E", __FUNCTION__);
+ status_t res;
+
+ if (mStatus != STATUS_ERROR) {
+ ALOGE("%s: Already initialized!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ res = constructStaticInfo();
+ if (res != OK) {
+ ALOGE("%s: Unable to allocate static info: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+
+ return EmulatedCamera3::Initialize();
+}
+
+status_t EmulatedFakeCamera3::connectCamera(hw_device_t** device) {
+ ALOGV("%s: E", __FUNCTION__);
+ Mutex::Autolock l(mLock);
+ status_t res;
+
+ if (mStatus != STATUS_CLOSED) {
+ ALOGE("%s: Can't connect in state %d", __FUNCTION__, mStatus);
+ return INVALID_OPERATION;
+ }
+
+ mSensor = new Sensor();
+
+ res = mSensor->startUp();
+ if (res != NO_ERROR) return res;
+
+ mReadoutThread = new ReadoutThread(this);
+
+ res = mReadoutThread->run("EmuCam3::readoutThread");
+ if (res != NO_ERROR) return res;
+
+ return EmulatedCamera3::connectCamera(device);
+}
+
+status_t EmulatedFakeCamera3::closeCamera() {
+ ALOGV("%s: E", __FUNCTION__);
+ status_t res;
+ {
+ Mutex::Autolock l(mLock);
+ if (mStatus == STATUS_CLOSED) return OK;
+
+ res = mSensor->shutDown();
+ if (res != NO_ERROR) {
+ ALOGE("%s: Unable to shut down sensor: %d", __FUNCTION__, res);
+ return res;
+ }
+ mSensor.clear();
+
+ mReadoutThread->requestExit();
+ }
+
+ mReadoutThread->join();
+
+ {
+ Mutex::Autolock l(mLock);
+ // Clear out private stream information
+ for (StreamIterator s = mStreams.begin(); s != mStreams.end(); s++) {
+ PrivateStreamInfo *privStream =
+ static_cast<PrivateStreamInfo*>((*s)->priv);
+ delete privStream;
+ (*s)->priv = NULL;
+ }
+ mStreams.clear();
+ mReadoutThread.clear();
+ }
+
+ return EmulatedCamera3::closeCamera();
+}
+
+status_t EmulatedFakeCamera3::getCameraInfo(struct camera_info *info) {
+ info->facing = mFacingBack ? CAMERA_FACING_BACK : CAMERA_FACING_FRONT;
+ info->orientation = gEmulatedCameraFactory.getFakeCameraOrientation();
+ return EmulatedCamera3::getCameraInfo(info);
+}
+
+/**
+ * Camera3 interface methods
+ */
+
+status_t EmulatedFakeCamera3::configureStreams(
+ camera3_stream_configuration *streamList) {
+ Mutex::Autolock l(mLock);
+ ALOGV("%s: %d streams", __FUNCTION__, streamList->num_streams);
+
+ if (mStatus != STATUS_OPEN && mStatus != STATUS_READY) {
+ ALOGE("%s: Cannot configure streams in state %d",
+ __FUNCTION__, mStatus);
+ return NO_INIT;
+ }
+
+ /**
+ * Sanity-check input list.
+ */
+ if (streamList == NULL) {
+ ALOGE("%s: NULL stream configuration", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (streamList->streams == NULL) {
+ ALOGE("%s: NULL stream list", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (streamList->num_streams < 1) {
+ ALOGE("%s: Bad number of streams requested: %d", __FUNCTION__,
+ streamList->num_streams);
+ return BAD_VALUE;
+ }
+
+ camera3_stream_t *inputStream = NULL;
+ for (size_t i = 0; i < streamList->num_streams; i++) {
+ camera3_stream_t *newStream = streamList->streams[i];
+ if (newStream->stream_type == CAMERA3_STREAM_INPUT) {
+ if (inputStream != NULL) {
+
+ ALOGE("%s: Multiple input streams requested!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ inputStream = newStream;
+ }
+ }
+ mInputStream = inputStream;
+
+ /**
+ * Initially mark all existing streams as not alive
+ */
+ for (StreamIterator s = mStreams.begin(); s != mStreams.end(); ++s) {
+ PrivateStreamInfo *privStream =
+ static_cast<PrivateStreamInfo*>((*s)->priv);
+ privStream->alive = false;
+ }
+
+ /**
+ * Find new streams and mark still-alive ones
+ */
+ for (size_t i = 0; i < streamList->num_streams; i++) {
+ camera3_stream_t *newStream = streamList->streams[i];
+ if (newStream->priv == NULL) {
+ // New stream, construct info
+ PrivateStreamInfo *privStream = new PrivateStreamInfo();
+ privStream->alive = true;
+ privStream->registered = false;
+
+ switch (newStream->stream_type) {
+ case CAMERA3_STREAM_OUTPUT:
+ newStream->usage = GRALLOC_USAGE_HW_CAMERA_WRITE;
+ break;
+ case CAMERA3_STREAM_INPUT:
+ newStream->usage = GRALLOC_USAGE_HW_CAMERA_READ;
+ break;
+ case CAMERA3_STREAM_BIDIRECTIONAL:
+ newStream->usage = GRALLOC_USAGE_HW_CAMERA_READ |
+ GRALLOC_USAGE_HW_CAMERA_WRITE;
+ break;
+ }
+ newStream->max_buffers = kMaxBufferCount;
+ newStream->priv = privStream;
+ mStreams.push_back(newStream);
+ } else {
+ // Existing stream, mark as still alive.
+ PrivateStreamInfo *privStream =
+ static_cast<PrivateStreamInfo*>(newStream->priv);
+ privStream->alive = true;
+ }
+ }
+
+ /**
+ * Reap the dead streams
+ */
+ for (StreamIterator s = mStreams.begin(); s != mStreams.end();) {
+ PrivateStreamInfo *privStream =
+ static_cast<PrivateStreamInfo*>((*s)->priv);
+ if (!privStream->alive) {
+ (*s)->priv = NULL;
+ delete privStream;
+ s = mStreams.erase(s);
+ } else {
+ ++s;
+ }
+ }
+
+ /**
+ * Can't reuse settings across configure call
+ */
+ mPrevSettings.clear();
+
+ return OK;
+}
+
+status_t EmulatedFakeCamera3::registerStreamBuffers(
+ const camera3_stream_buffer_set *bufferSet) {
+ ALOGV("%s: E", __FUNCTION__);
+ Mutex::Autolock l(mLock);
+
+ /**
+ * Sanity checks
+ */
+
+ if (mStatus != STATUS_READY) {
+ ALOGE("%s: Cannot register buffers in state %d",
+ __FUNCTION__, mStatus);
+ return NO_INIT;
+ }
+
+ if (bufferSet == NULL) {
+ ALOGE("%s: NULL buffer set!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ StreamIterator s = mStreams.begin();
+ for (; s != mStreams.end(); ++s) {
+ if (bufferSet->stream == *s) break;
+ }
+ if (s == mStreams.end()) {
+ ALOGE("%s: Trying to register buffers for a non-configured stream!",
+ __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ /**
+ * Register the buffers. This doesn't mean anything to the emulator besides
+ * marking them off as registered.
+ */
+
+ PrivateStreamInfo *privStream =
+ static_cast<PrivateStreamInfo*>((*s)->priv);
+ privStream->registered = true;
+
+ return OK;
+}
+
+const camera_metadata_t* EmulatedFakeCamera3::constructDefaultRequestSettings(
+ int type) {
+ ALOGV("%s: E", __FUNCTION__);
+ Mutex::Autolock l(mLock);
+
+ if (type < 0 || type >= CAMERA2_TEMPLATE_COUNT) {
+ ALOGE("%s: Unknown request settings template: %d",
+ __FUNCTION__, type);
+ return NULL;
+ }
+
+ /**
+ * Cache is not just an optimization - pointer returned has to live at
+ * least as long as the camera device instance does.
+ */
+ if (mDefaultTemplates[type] != NULL) {
+ return mDefaultTemplates[type];
+ }
+
+ CameraMetadata settings;
+
+ /** android.request */
+
+ static const uint8_t requestType = ANDROID_REQUEST_TYPE_CAPTURE;
+ settings.update(ANDROID_REQUEST_TYPE, &requestType, 1);
+
+ static const uint8_t metadataMode = ANDROID_REQUEST_METADATA_MODE_FULL;
+ settings.update(ANDROID_REQUEST_METADATA_MODE, &metadataMode, 1);
+
+ static const int32_t id = 0;
+ settings.update(ANDROID_REQUEST_ID, &id, 1);
+
+ static const int32_t frameCount = 0;
+ settings.update(ANDROID_REQUEST_FRAME_COUNT, &frameCount, 1);
+
+ /** android.lens */
+
+ static const float focusDistance = 0;
+ settings.update(ANDROID_LENS_FOCUS_DISTANCE, &focusDistance, 1);
+
+ static const float aperture = 2.8f;
+ settings.update(ANDROID_LENS_APERTURE, &aperture, 1);
+
+ static const float focalLength = 5.0f;
+ settings.update(ANDROID_LENS_FOCAL_LENGTH, &focalLength, 1);
+
+ static const float filterDensity = 0;
+ settings.update(ANDROID_LENS_FILTER_DENSITY, &filterDensity, 1);
+
+ static const uint8_t opticalStabilizationMode =
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
+ settings.update(ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+ &opticalStabilizationMode, 1);
+
+ // FOCUS_RANGE set only in frame
+
+ /** android.sensor */
+
+ static const int64_t exposureTime = 10 * MSEC;
+ settings.update(ANDROID_SENSOR_EXPOSURE_TIME, &exposureTime, 1);
+
+ static const int64_t frameDuration = 33333333L; // 1/30 s
+ settings.update(ANDROID_SENSOR_FRAME_DURATION, &frameDuration, 1);
+
+ static const int32_t sensitivity = 100;
+ settings.update(ANDROID_SENSOR_SENSITIVITY, &sensitivity, 1);
+
+ // TIMESTAMP set only in frame
+
+ /** android.flash */
+
+ static const uint8_t flashMode = ANDROID_FLASH_MODE_OFF;
+ settings.update(ANDROID_FLASH_MODE, &flashMode, 1);
+
+ static const uint8_t flashPower = 10;
+ settings.update(ANDROID_FLASH_FIRING_POWER, &flashPower, 1);
+
+ static const int64_t firingTime = 0;
+ settings.update(ANDROID_FLASH_FIRING_TIME, &firingTime, 1);
+
+ /** Processing block modes */
+ uint8_t hotPixelMode = 0;
+ uint8_t demosaicMode = 0;
+ uint8_t noiseMode = 0;
+ uint8_t shadingMode = 0;
+ uint8_t geometricMode = 0;
+ uint8_t colorMode = 0;
+ uint8_t tonemapMode = 0;
+ uint8_t edgeMode = 0;
+ switch (type) {
+ case CAMERA2_TEMPLATE_STILL_CAPTURE:
+ // fall-through
+ case CAMERA2_TEMPLATE_VIDEO_SNAPSHOT:
+ // fall-through
+ case CAMERA2_TEMPLATE_ZERO_SHUTTER_LAG:
+ hotPixelMode = ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY;
+ demosaicMode = ANDROID_DEMOSAIC_MODE_HIGH_QUALITY;
+ noiseMode = ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY;
+ shadingMode = ANDROID_SHADING_MODE_HIGH_QUALITY;
+ geometricMode = ANDROID_GEOMETRIC_MODE_HIGH_QUALITY;
+ colorMode = ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY;
+ tonemapMode = ANDROID_TONEMAP_MODE_HIGH_QUALITY;
+ edgeMode = ANDROID_EDGE_MODE_HIGH_QUALITY;
+ break;
+ case CAMERA2_TEMPLATE_PREVIEW:
+ // fall-through
+ case CAMERA2_TEMPLATE_VIDEO_RECORD:
+ // fall-through
+ default:
+ hotPixelMode = ANDROID_HOT_PIXEL_MODE_FAST;
+ demosaicMode = ANDROID_DEMOSAIC_MODE_FAST;
+ noiseMode = ANDROID_NOISE_REDUCTION_MODE_FAST;
+ shadingMode = ANDROID_SHADING_MODE_FAST;
+ geometricMode = ANDROID_GEOMETRIC_MODE_FAST;
+ colorMode = ANDROID_COLOR_CORRECTION_MODE_FAST;
+ tonemapMode = ANDROID_TONEMAP_MODE_FAST;
+ edgeMode = ANDROID_EDGE_MODE_FAST;
+ break;
+ }
+ settings.update(ANDROID_HOT_PIXEL_MODE, &hotPixelMode, 1);
+ settings.update(ANDROID_DEMOSAIC_MODE, &demosaicMode, 1);
+ settings.update(ANDROID_NOISE_REDUCTION_MODE, &noiseMode, 1);
+ settings.update(ANDROID_SHADING_MODE, &shadingMode, 1);
+ settings.update(ANDROID_GEOMETRIC_MODE, &geometricMode, 1);
+ settings.update(ANDROID_COLOR_CORRECTION_MODE, &colorMode, 1);
+ settings.update(ANDROID_TONEMAP_MODE, &tonemapMode, 1);
+ settings.update(ANDROID_EDGE_MODE, &edgeMode, 1);
+
+ /** android.noise */
+ static const uint8_t noiseStrength = 5;
+ settings.update(ANDROID_NOISE_REDUCTION_STRENGTH, &noiseStrength, 1);
+
+ /** android.color */
+ static const float colorTransform[9] = {
+ 1.0f, 0.f, 0.f,
+ 0.f, 1.f, 0.f,
+ 0.f, 0.f, 1.f
+ };
+ settings.update(ANDROID_COLOR_CORRECTION_TRANSFORM, colorTransform, 9);
+
+ /** android.tonemap */
+ static const float tonemapCurve[4] = {
+ 0.f, 0.f,
+ 1.f, 1.f
+ };
+ settings.update(ANDROID_TONEMAP_CURVE_RED, tonemapCurve, 4);
+ settings.update(ANDROID_TONEMAP_CURVE_GREEN, tonemapCurve, 4);
+ settings.update(ANDROID_TONEMAP_CURVE_BLUE, tonemapCurve, 4);
+
+ /** android.edge */
+ static const uint8_t edgeStrength = 5;
+ settings.update(ANDROID_EDGE_STRENGTH, &edgeStrength, 1);
+
+ /** android.scaler */
+ static const int32_t cropRegion[3] = {
+ 0, 0, (int32_t)Sensor::kResolution[0]
+ };
+ settings.update(ANDROID_SCALER_CROP_REGION, cropRegion, 3);
+
+ /** android.jpeg */
+ static const uint8_t jpegQuality = 80;
+ settings.update(ANDROID_JPEG_QUALITY, &jpegQuality, 1);
+
+ static const int32_t thumbnailSize[2] = {
+ 640, 480
+ };
+ settings.update(ANDROID_JPEG_THUMBNAIL_SIZE, thumbnailSize, 2);
+
+ static const uint8_t thumbnailQuality = 80;
+ settings.update(ANDROID_JPEG_THUMBNAIL_QUALITY, &thumbnailQuality, 1);
+
+ static const double gpsCoordinates[2] = {
+ 0, 0
+ };
+ settings.update(ANDROID_JPEG_GPS_COORDINATES, gpsCoordinates, 2);
+
+ static const uint8_t gpsProcessingMethod[32] = "None";
+ settings.update(ANDROID_JPEG_GPS_PROCESSING_METHOD, gpsProcessingMethod, 32);
+
+ static const int64_t gpsTimestamp = 0;
+ settings.update(ANDROID_JPEG_GPS_TIMESTAMP, &gpsTimestamp, 1);
+
+ static const int32_t jpegOrientation = 0;
+ settings.update(ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1);
+
+ /** android.stats */
+
+ static const uint8_t faceDetectMode =
+ ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
+ settings.update(ANDROID_STATISTICS_FACE_DETECT_MODE, &faceDetectMode, 1);
+
+ static const uint8_t histogramMode = ANDROID_STATISTICS_HISTOGRAM_MODE_OFF;
+ settings.update(ANDROID_STATISTICS_HISTOGRAM_MODE, &histogramMode, 1);
+
+ static const uint8_t sharpnessMapMode =
+ ANDROID_STATISTICS_SHARPNESS_MAP_MODE_OFF;
+ settings.update(ANDROID_STATISTICS_SHARPNESS_MAP_MODE, &sharpnessMapMode, 1);
+
+ // faceRectangles, faceScores, faceLandmarks, faceIds, histogram,
+ // sharpnessMap only in frames
+
+ /** android.control */
+
+ uint8_t controlIntent = 0;
+ switch (type) {
+ case CAMERA2_TEMPLATE_PREVIEW:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
+ break;
+ case CAMERA2_TEMPLATE_STILL_CAPTURE:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
+ break;
+ case CAMERA2_TEMPLATE_VIDEO_RECORD:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
+ break;
+ case CAMERA2_TEMPLATE_VIDEO_SNAPSHOT:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
+ break;
+ case CAMERA2_TEMPLATE_ZERO_SHUTTER_LAG:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG;
+ break;
+ default:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_CUSTOM;
+ break;
+ }
+ settings.update(ANDROID_CONTROL_CAPTURE_INTENT, &controlIntent, 1);
+
+ static const uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO;
+ settings.update(ANDROID_CONTROL_MODE, &controlMode, 1);
+
+ static const uint8_t effectMode = ANDROID_CONTROL_EFFECT_MODE_OFF;
+ settings.update(ANDROID_CONTROL_EFFECT_MODE, &effectMode, 1);
+
+ static const uint8_t sceneMode = ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY;
+ settings.update(ANDROID_CONTROL_SCENE_MODE, &sceneMode, 1);
+
+ static const uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH;
+ settings.update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
+
+ static const uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
+ settings.update(ANDROID_CONTROL_AE_LOCK, &aeLock, 1);
+
+ static const int32_t controlRegions[5] = {
+ 0, 0, (int32_t)Sensor::kResolution[0], (int32_t)Sensor::kResolution[1],
+ 1000
+ };
+ settings.update(ANDROID_CONTROL_AE_REGIONS, controlRegions, 5);
+
+ static const int32_t aeExpCompensation = 0;
+ settings.update(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, &aeExpCompensation, 1);
+
+ static const int32_t aeTargetFpsRange[2] = {
+ 10, 30
+ };
+ settings.update(ANDROID_CONTROL_AE_TARGET_FPS_RANGE, aeTargetFpsRange, 2);
+
+ static const uint8_t aeAntibandingMode =
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
+ settings.update(ANDROID_CONTROL_AE_ANTIBANDING_MODE, &aeAntibandingMode, 1);
+
+ static const uint8_t awbMode =
+ ANDROID_CONTROL_AWB_MODE_AUTO;
+ settings.update(ANDROID_CONTROL_AWB_MODE, &awbMode, 1);
+
+ static const uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
+ settings.update(ANDROID_CONTROL_AWB_LOCK, &awbLock, 1);
+
+ settings.update(ANDROID_CONTROL_AWB_REGIONS, controlRegions, 5);
+
+ uint8_t afMode = 0;
+ switch (type) {
+ case CAMERA2_TEMPLATE_PREVIEW:
+ afMode = ANDROID_CONTROL_AF_MODE_AUTO;
+ break;
+ case CAMERA2_TEMPLATE_STILL_CAPTURE:
+ afMode = ANDROID_CONTROL_AF_MODE_AUTO;
+ break;
+ case CAMERA2_TEMPLATE_VIDEO_RECORD:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
+ break;
+ case CAMERA2_TEMPLATE_VIDEO_SNAPSHOT:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
+ break;
+ case CAMERA2_TEMPLATE_ZERO_SHUTTER_LAG:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+ break;
+ default:
+ afMode = ANDROID_CONTROL_AF_MODE_AUTO;
+ break;
+ }
+ settings.update(ANDROID_CONTROL_AF_MODE, &afMode, 1);
+
+ settings.update(ANDROID_CONTROL_AF_REGIONS, controlRegions, 5);
+
+ static const uint8_t vstabMode =
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
+ settings.update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, &vstabMode, 1);
+
+ // aeState, awbState, afState only in frame
+
+ mDefaultTemplates[type] = settings.release();
+
+ return mDefaultTemplates[type];
+}
+
+status_t EmulatedFakeCamera3::processCaptureRequest(
+ camera3_capture_request *request) {
+
+ Mutex::Autolock l(mLock);
+ status_t res;
+
+ /** Validation */
+
+ if (mStatus < STATUS_READY) {
+ ALOGE("%s: Can't submit capture requests in state %d", __FUNCTION__,
+ mStatus);
+ return INVALID_OPERATION;
+ }
+
+ if (request == NULL) {
+ ALOGE("%s: NULL request!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ uint32_t frameNumber = request->frame_number;
+
+ if (request->settings == NULL && mPrevSettings.isEmpty()) {
+ ALOGE("%s: Request %d: NULL settings for first request after"
+ "configureStreams()", __FUNCTION__, frameNumber);
+ return BAD_VALUE;
+ }
+
+ if (request->input_buffer != NULL &&
+ request->input_buffer->stream != mInputStream) {
+ ALOGE("%s: Request %d: Input buffer not from input stream!",
+ __FUNCTION__, frameNumber);
+ return BAD_VALUE;
+ }
+
+ if (request->num_output_buffers < 1 || request->output_buffers == NULL) {
+ ALOGE("%s: Request %d: No output buffers provided!",
+ __FUNCTION__, frameNumber);
+ return BAD_VALUE;
+ }
+
+ // Validate all buffers, starting with input buffer if it's given
+
+ ssize_t idx;
+ const camera3_stream_buffer_t *b;
+ if (request->input_buffer != NULL) {
+ idx = -1;
+ b = request->input_buffer;
+ } else {
+ idx = 0;
+ b = request->output_buffers;
+ }
+ do {
+ PrivateStreamInfo *priv =
+ static_cast<PrivateStreamInfo*>(b->stream->priv);
+ if (priv == NULL) {
+ ALOGE("%s: Request %d: Buffer %d: Unconfigured stream!",
+ __FUNCTION__, frameNumber, idx);
+ return BAD_VALUE;
+ }
+ if (!priv->alive || !priv->registered) {
+ ALOGE("%s: Request %d: Buffer %d: Unregistered or dead stream!",
+ __FUNCTION__, frameNumber, idx);
+ return BAD_VALUE;
+ }
+ if (b->status != CAMERA3_BUFFER_STATUS_OK) {
+ ALOGE("%s: Request %d: Buffer %d: Status not OK!",
+ __FUNCTION__, frameNumber, idx);
+ return BAD_VALUE;
+ }
+ if (b->release_fence != -1) {
+ ALOGE("%s: Request %d: Buffer %d: Has a release fence!",
+ __FUNCTION__, frameNumber, idx);
+ return BAD_VALUE;
+ }
+ if (b->buffer == NULL) {
+ ALOGE("%s: Request %d: Buffer %d: NULL buffer handle!",
+ __FUNCTION__, frameNumber, idx);
+ return BAD_VALUE;
+ }
+ idx++;
+ b = &(request->output_buffers[idx]);
+ } while (idx < (ssize_t)request->num_output_buffers);
+
+ // TODO: Validate settings parameters
+
+ /**
+ * Start processing this request
+ */
+
+ mStatus = STATUS_ACTIVE;
+
+ CameraMetadata settings;
+
+ if (request->settings == NULL) {
+ settings.acquire(mPrevSettings);
+ } else {
+ settings = request->settings;
+ }
+
+ // TODO: Apply 3A overrides
+
+ // TODO: Handle reprocessing
+
+ /**
+ * Get ready for sensor config
+ */
+
+ nsecs_t exposureTime;
+ nsecs_t frameDuration;
+ uint32_t sensitivity;
+
+ exposureTime = settings.find(ANDROID_SENSOR_EXPOSURE_TIME).data.i64[0];
+ frameDuration = settings.find(ANDROID_SENSOR_FRAME_DURATION).data.i64[0];
+ sensitivity = settings.find(ANDROID_SENSOR_SENSITIVITY).data.i32[0];
+
+ Buffers *sensorBuffers = new Buffers();
+ Vector<camera3_stream_buffer> *buffers = new Vector<camera3_stream_buffer>();
+
+ sensorBuffers->setCapacity(request->num_output_buffers);
+ buffers->setCapacity(request->num_output_buffers);
+
+ // Process all the buffers we got for output, constructing internal buffer
+ // structures for them, and lock them for writing.
+ for (size_t i = 0; i < request->num_output_buffers; i++) {
+ const camera3_stream_buffer &srcBuf = request->output_buffers[i];
+ const cb_handle_t *privBuffer =
+ static_cast<const cb_handle_t*>(*srcBuf.buffer);
+ StreamBuffer destBuf;
+ destBuf.streamId = 0;
+ destBuf.width = srcBuf.stream->width;
+ destBuf.height = srcBuf.stream->height;
+ destBuf.format = privBuffer->format; // Use real private format
+ destBuf.stride = srcBuf.stream->width; // TODO: query from gralloc
+ destBuf.buffer = srcBuf.buffer;
+
+ // Wait on fence
+ sp<Fence> bufferAcquireFence = new Fence(srcBuf.acquire_fence);
+ res = bufferAcquireFence->wait(kFenceTimeoutMs);
+ if (res == TIMED_OUT) {
+ ALOGE("%s: Request %d: Buffer %d: Fence timed out after %d ms",
+ __FUNCTION__, frameNumber, i, kFenceTimeoutMs);
+ }
+ if (res == OK) {
+ // Lock buffer for writing
+ const Rect rect(destBuf.width, destBuf.height);
+ res = GraphicBufferMapper::get().lock(*(destBuf.buffer),
+ GRALLOC_USAGE_HW_CAMERA_WRITE, rect, (void**)&(destBuf.img));
+ if (res != OK) {
+ ALOGE("%s: Request %d: Buffer %d: Unable to lock buffer",
+ __FUNCTION__, frameNumber, i);
+ }
+ }
+
+ if (res != OK) {
+ // Either waiting or locking failed. Unlock locked buffers and bail out.
+ for (size_t j = 0; j < i; j++) {
+ GraphicBufferMapper::get().unlock(
+ *(request->output_buffers[i].buffer));
+ }
+ return NO_INIT;
+ }
+
+ sensorBuffers->push_back(destBuf);
+ buffers->push_back(srcBuf);
+ }
+
+ /**
+ * Wait until the in-flight queue has room
+ */
+ res = mReadoutThread->waitForReadout();
+ if (res != OK) {
+ return NO_INIT;
+ }
+
+ /**
+ * Wait until sensor's ready. This waits for lengthy amounts of time with
+ * mLock held, but the interface spec is that no other calls may by done to
+ * the HAL by the framework while process_capture_request is happening.
+ */
+ int syncTimeoutCount = 0;
+ while(!mSensor->waitForVSync(kSyncWaitTimeout)) {
+ if (mStatus == STATUS_ERROR) {
+ return NO_INIT;
+ }
+ if (syncTimeoutCount == kMaxSyncTimeoutCount) {
+ ALOGE("%s: Request %d: Sensor sync timed out after %lld ms",
+ __FUNCTION__, frameNumber,
+ kSyncWaitTimeout * kMaxSyncTimeoutCount / 1000000);
+ return NO_INIT;
+ }
+ syncTimeoutCount++;
+ }
+
+ /**
+ * Configure sensor and queue up the request to the readout thread
+ */
+ mSensor->setExposureTime(exposureTime);
+ mSensor->setFrameDuration(frameDuration);
+ mSensor->setSensitivity(sensitivity);
+ mSensor->setDestinationBuffers(sensorBuffers);
+
+ ReadoutThread::Request r;
+ r.frameNumber = request->frame_number;
+ r.settings = settings;
+ r.sensorBuffers = sensorBuffers;
+ r.buffers = buffers;
+
+ mReadoutThread->queueCaptureRequest(r);
+
+ // Cache the settings for next time
+ mPrevSettings.acquire(settings);
+
+ return OK;
+}
+
+/** Debug methods */
+
+void EmulatedFakeCamera3::dump(int fd) {
+
+}
+
+/** Tag query methods */
+const char* EmulatedFakeCamera3::getVendorSectionName(uint32_t tag) {
+ return NULL;
+}
+
+const char* EmulatedFakeCamera3::getVendorTagName(uint32_t tag) {
+ return NULL;
+}
+
+int EmulatedFakeCamera3::getVendorTagType(uint32_t tag) {
+ return 0;
+}
+
+/**
+ * Private methods
+ */
+
+status_t EmulatedFakeCamera3::constructStaticInfo() {
+
+ CameraMetadata info;
+ // android.lens
+
+ // 5 cm min focus distance for back camera, infinity (fixed focus) for front
+ const float minFocusDistance = mFacingBack ? 1.0/0.05 : 0.0;
+ info.update(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
+ &minFocusDistance, 1);
+
+ // 5 m hyperfocal distance for back camera, infinity (fixed focus) for front
+ const float hyperFocalDistance = mFacingBack ? 1.0/5.0 : 0.0;
+ info.update(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
+ &minFocusDistance, 1);
+
+ static const float focalLength = 3.30f; // mm
+ info.update(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+ &focalLength, 1);
+ static const float aperture = 2.8f;
+ info.update(ANDROID_LENS_INFO_AVAILABLE_APERTURES,
+ &aperture, 1);
+ static const float filterDensity = 0;
+ info.update(ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
+ &filterDensity, 1);
+ static const uint8_t availableOpticalStabilization =
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
+ info.update(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+ &availableOpticalStabilization, 1);
+
+ static const int32_t lensShadingMapSize[] = {1, 1};
+ info.update(ANDROID_LENS_INFO_SHADING_MAP_SIZE, lensShadingMapSize,
+ sizeof(lensShadingMapSize)/sizeof(int32_t));
+
+ static const float lensShadingMap[3 * 1 * 1 ] =
+ { 1.f, 1.f, 1.f };
+ info.update(ANDROID_LENS_INFO_SHADING_MAP, lensShadingMap,
+ sizeof(lensShadingMap)/sizeof(float));
+
+ // Identity transform
+ static const int32_t geometricCorrectionMapSize[] = {2, 2};
+ info.update(ANDROID_LENS_INFO_GEOMETRIC_CORRECTION_MAP_SIZE,
+ geometricCorrectionMapSize,
+ sizeof(geometricCorrectionMapSize)/sizeof(int32_t));
+
+ static const float geometricCorrectionMap[2 * 3 * 2 * 2] = {
+ 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
+ 1.f, 0.f, 1.f, 0.f, 1.f, 0.f,
+ 0.f, 1.f, 0.f, 1.f, 0.f, 1.f,
+ 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
+ info.update(ANDROID_LENS_INFO_GEOMETRIC_CORRECTION_MAP,
+ geometricCorrectionMap,
+ sizeof(geometricCorrectionMap)/sizeof(float));
+
+ uint8_t lensFacing = mFacingBack ?
+ ANDROID_LENS_FACING_BACK : ANDROID_LENS_FACING_FRONT;
+ info.update(ANDROID_LENS_FACING, &lensFacing, 1);
+
+ float lensPosition[3];
+ if (mFacingBack) {
+ // Back-facing camera is center-top on device
+ lensPosition[0] = 0;
+ lensPosition[1] = 20;
+ lensPosition[2] = -5;
+ } else {
+ // Front-facing camera is center-right on device
+ lensPosition[0] = 20;
+ lensPosition[1] = 20;
+ lensPosition[2] = 0;
+ }
+ info.update(ANDROID_LENS_POSITION, lensPosition, sizeof(lensPosition)/
+ sizeof(float));
+
+ // android.sensor
+
+ info.update(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
+ Sensor::kExposureTimeRange, 2);
+
+ info.update(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+ &Sensor::kFrameDurationRange[1], 1);
+
+ info.update(ANDROID_SENSOR_INFO_AVAILABLE_SENSITIVITIES,
+ (int32_t*)Sensor::kAvailableSensitivities,
+ sizeof(Sensor::kAvailableSensitivities)
+ /sizeof(uint32_t));
+
+ info.update(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
+ &Sensor::kColorFilterArrangement, 1);
+
+ static const float sensorPhysicalSize[2] = {3.20f, 2.40f}; // mm
+ info.update(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
+ sensorPhysicalSize, 2);
+
+ info.update(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+ (int32_t*)Sensor::kResolution, 2);
+
+ info.update(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+ (int32_t*)Sensor::kResolution, 2);
+
+ info.update(ANDROID_SENSOR_INFO_WHITE_LEVEL,
+ (int32_t*)&Sensor::kMaxRawValue, 1);
+
+ static const int32_t blackLevelPattern[4] = {
+ (int32_t)Sensor::kBlackLevel, (int32_t)Sensor::kBlackLevel,
+ (int32_t)Sensor::kBlackLevel, (int32_t)Sensor::kBlackLevel
+ };
+ info.update(ANDROID_SENSOR_BLACK_LEVEL_PATTERN,
+ blackLevelPattern, sizeof(blackLevelPattern)/sizeof(int32_t));
+
+ //TODO: sensor color calibration fields
+
+ // android.flash
+ static const uint8_t flashAvailable = 0;
+ info.update(ANDROID_FLASH_INFO_AVAILABLE, &flashAvailable, 1);
+
+ static const int64_t flashChargeDuration = 0;
+ info.update(ANDROID_FLASH_INFO_CHARGE_DURATION, &flashChargeDuration, 1);
+
+ // android.tonemap
+
+ static const int32_t tonemapCurvePoints = 128;
+ info.update(ANDROID_TONEMAP_MAX_CURVE_POINTS, &tonemapCurvePoints, 1);
+
+ // android.scaler
+
+ info.update(ANDROID_SCALER_AVAILABLE_FORMATS,
+ (int32_t*)kAvailableFormats,
+ sizeof(kAvailableFormats)/sizeof(uint32_t));
+
+ info.update(ANDROID_SCALER_AVAILABLE_RAW_SIZES,
+ (int32_t*)kAvailableRawSizes,
+ sizeof(kAvailableRawSizes)/sizeof(uint32_t));
+
+ info.update(ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS,
+ (int64_t*)kAvailableRawMinDurations,
+ sizeof(kAvailableRawMinDurations)/sizeof(uint64_t));
+
+ if (mFacingBack) {
+ info.update(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES,
+ (int32_t*)kAvailableProcessedSizesBack,
+ sizeof(kAvailableProcessedSizesBack)/sizeof(uint32_t));
+ } else {
+ info.update(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES,
+ (int32_t*)kAvailableProcessedSizesFront,
+ sizeof(kAvailableProcessedSizesFront)/sizeof(uint32_t));
+ }
+
+ info.update(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS,
+ (int64_t*)kAvailableProcessedMinDurations,
+ sizeof(kAvailableProcessedMinDurations)/sizeof(uint64_t));
+
+ if (mFacingBack) {
+ info.update(ANDROID_SCALER_AVAILABLE_JPEG_SIZES,
+ (int32_t*)kAvailableJpegSizesBack,
+ sizeof(kAvailableJpegSizesBack)/sizeof(uint32_t));
+ } else {
+ info.update(ANDROID_SCALER_AVAILABLE_JPEG_SIZES,
+ (int32_t*)kAvailableJpegSizesFront,
+ sizeof(kAvailableJpegSizesFront)/sizeof(uint32_t));
+ }
+
+ info.update(ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS,
+ (int64_t*)kAvailableJpegMinDurations,
+ sizeof(kAvailableJpegMinDurations)/sizeof(uint64_t));
+
+ static const int32_t maxZoom = 10;
+ info.update(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+ &maxZoom, 1);
+
+ // android.jpeg
+
+ static const int32_t jpegThumbnailSizes[] = {
+ 0, 0,
+ 160, 120,
+ 320, 240
+ };
+ info.update(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+ jpegThumbnailSizes, sizeof(jpegThumbnailSizes)/sizeof(int32_t));
+
+ static const int32_t jpegMaxSize = JpegCompressor::kMaxJpegSize;
+ info.update(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
+
+ // android.stats
+
+ static const uint8_t availableFaceDetectModes[] = {
+ ANDROID_STATISTICS_FACE_DETECT_MODE_OFF,
+ ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE,
+ ANDROID_STATISTICS_FACE_DETECT_MODE_FULL
+ };
+
+ info.update(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
+ availableFaceDetectModes,
+ sizeof(availableFaceDetectModes));
+
+ static const int32_t maxFaceCount = 8;
+ info.update(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
+ &maxFaceCount, 1);
+
+ static const int32_t histogramSize = 64;
+ info.update(ANDROID_STATISTICS_INFO_HISTOGRAM_BUCKET_COUNT,
+ &histogramSize, 1);
+
+ static const int32_t maxHistogramCount = 1000;
+ info.update(ANDROID_STATISTICS_INFO_MAX_HISTOGRAM_COUNT,
+ &maxHistogramCount, 1);
+
+ static const int32_t sharpnessMapSize[2] = {64, 64};
+ info.update(ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE,
+ sharpnessMapSize, sizeof(sharpnessMapSize)/sizeof(int32_t));
+
+ static const int32_t maxSharpnessMapValue = 1000;
+ info.update(ANDROID_STATISTICS_INFO_MAX_SHARPNESS_MAP_VALUE,
+ &maxSharpnessMapValue, 1);
+
+ // android.control
+
+ static const uint8_t availableSceneModes[] = {
+ ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED
+ };
+ info.update(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
+ availableSceneModes, sizeof(availableSceneModes));
+
+ static const uint8_t availableEffects[] = {
+ ANDROID_CONTROL_EFFECT_MODE_OFF
+ };
+ info.update(ANDROID_CONTROL_AVAILABLE_EFFECTS,
+ availableEffects, sizeof(availableEffects));
+
+ int32_t max3aRegions = 0;
+ info.update(ANDROID_CONTROL_MAX_REGIONS,
+ &max3aRegions, 1);
+
+ static const uint8_t availableAeModes[] = {
+ ANDROID_CONTROL_AE_MODE_OFF,
+ ANDROID_CONTROL_AE_MODE_ON
+ };
+ info.update(ANDROID_CONTROL_AE_AVAILABLE_MODES,
+ availableAeModes, sizeof(availableAeModes));
+
+ static const camera_metadata_rational exposureCompensationStep = {
+ 1, 3
+ };
+ info.update(ANDROID_CONTROL_AE_COMPENSATION_STEP,
+ &exposureCompensationStep, 1);
+
+ int32_t exposureCompensationRange[] = {-9, 9};
+ info.update(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+ exposureCompensationRange,
+ sizeof(exposureCompensationRange)/sizeof(int32_t));
+
+ static const int32_t availableTargetFpsRanges[] = {
+ 5, 30, 15, 30
+ };
+ info.update(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+ availableTargetFpsRanges,
+ sizeof(availableTargetFpsRanges)/sizeof(int32_t));
+
+ static const uint8_t availableAntibandingModes[] = {
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF,
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO
+ };
+ info.update(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+ availableAntibandingModes, sizeof(availableAntibandingModes));
+
+ static const uint8_t availableAwbModes[] = {
+ ANDROID_CONTROL_AWB_MODE_OFF,
+ ANDROID_CONTROL_AWB_MODE_AUTO,
+ ANDROID_CONTROL_AWB_MODE_INCANDESCENT,
+ ANDROID_CONTROL_AWB_MODE_FLUORESCENT,
+ ANDROID_CONTROL_AWB_MODE_DAYLIGHT,
+ ANDROID_CONTROL_AWB_MODE_SHADE
+ };
+ info.update(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+ availableAwbModes, sizeof(availableAwbModes));
+
+ static const uint8_t availableAfModesBack[] = {
+ ANDROID_CONTROL_AF_MODE_OFF,
+ ANDROID_CONTROL_AF_MODE_AUTO,
+ ANDROID_CONTROL_AF_MODE_MACRO,
+ ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO,
+ ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE
+ };
+
+ static const uint8_t availableAfModesFront[] = {
+ ANDROID_CONTROL_AF_MODE_OFF
+ };
+
+ if (mFacingBack) {
+ info.update(ANDROID_CONTROL_AF_AVAILABLE_MODES,
+ availableAfModesBack, sizeof(availableAfModesBack));
+ } else {
+ info.update(ANDROID_CONTROL_AF_AVAILABLE_MODES,
+ availableAfModesFront, sizeof(availableAfModesFront));
+ }
+
+ static const uint8_t availableVstabModes[] = {
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF
+ };
+ info.update(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+ availableVstabModes, sizeof(availableVstabModes));
+
+ mCameraInfo = info.release();
+
+ return OK;
+}
+
+void EmulatedFakeCamera3::signalReadoutIdle() {
+ Mutex::Autolock l(mLock);
+ // Need to chek isIdle again because waiting on mLock may have allowed
+ // something to be placed in the in-flight queue.
+ if (mStatus == STATUS_ACTIVE && mReadoutThread->isIdle()) {
+ ALOGV("Now idle");
+ mStatus = STATUS_READY;
+ }
+}
+
+EmulatedFakeCamera3::ReadoutThread::ReadoutThread(EmulatedFakeCamera3 *parent) :
+ mParent(parent) {
+}
+
+EmulatedFakeCamera3::ReadoutThread::~ReadoutThread() {
+ for (List<Request>::iterator i = mInFlightQueue.begin();
+ i != mInFlightQueue.end(); i++) {
+ delete i->buffers;
+ delete i->sensorBuffers;
+ }
+}
+
+void EmulatedFakeCamera3::ReadoutThread::queueCaptureRequest(const Request &r) {
+ Mutex::Autolock l(mLock);
+
+ mInFlightQueue.push_back(r);
+ mInFlightSignal.signal();
+}
+
+bool EmulatedFakeCamera3::ReadoutThread::isIdle() {
+ Mutex::Autolock l(mLock);
+ return mInFlightQueue.empty() && !mThreadActive;
+}
+
+status_t EmulatedFakeCamera3::ReadoutThread::waitForReadout() {
+ status_t res;
+ Mutex::Autolock l(mLock);
+ int loopCount = 0;
+ while (mInFlightQueue.size() >= kMaxQueueSize) {
+ res = mInFlightSignal.waitRelative(mLock, kWaitPerLoop);
+ if (res != OK && res != TIMED_OUT) {
+ ALOGE("%s: Error waiting for in-flight queue to shrink",
+ __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ if (loopCount == kMaxWaitLoops) {
+ ALOGE("%s: Timed out waiting for in-flight queue to shrink",
+ __FUNCTION__);
+ return TIMED_OUT;
+ }
+ loopCount++;
+ }
+ return OK;
+}
+
+bool EmulatedFakeCamera3::ReadoutThread::threadLoop() {
+ status_t res;
+
+ // First wait for a request from the in-flight queue
+
+ if (mCurrentRequest.settings.isEmpty()) {
+ Mutex::Autolock l(mLock);
+ if (mInFlightQueue.empty()) {
+ res = mInFlightSignal.waitRelative(mLock, kWaitPerLoop);
+ if (res == TIMED_OUT) {
+ return true;
+ } else if (res != NO_ERROR) {
+ ALOGE("%s: Error waiting for capture requests: %d",
+ __FUNCTION__, res);
+ return false;
+ }
+ }
+ mCurrentRequest.frameNumber = mInFlightQueue.begin()->frameNumber;
+ mCurrentRequest.settings.acquire(mInFlightQueue.begin()->settings);
+ mCurrentRequest.buffers = mInFlightQueue.begin()->buffers;
+ mCurrentRequest.sensorBuffers = mInFlightQueue.begin()->sensorBuffers;
+ mInFlightQueue.erase(mInFlightQueue.begin());
+ mInFlightSignal.signal();
+ mThreadActive = true;
+ }
+
+ // Then wait for it to be delivered from the sensor
+
+ nsecs_t captureTime;
+ bool gotFrame =
+ mParent->mSensor->waitForNewFrame(kWaitPerLoop, &captureTime);
+ if (!gotFrame) return true;
+
+ // Got everything, construct result
+
+ camera3_capture_result result;
+
+ mCurrentRequest.settings.update(ANDROID_SENSOR_TIMESTAMP,
+ &captureTime, 1);
+
+ for (size_t i = 0; i < mCurrentRequest.buffers->size(); i++) {
+ camera3_stream_buffer &buf = mCurrentRequest.buffers->editItemAt(i);
+
+ GraphicBufferMapper::get().unlock(*buf.buffer);
+
+ buf.status = CAMERA3_BUFFER_STATUS_OK;
+ buf.acquire_fence = -1;
+ buf.release_fence = -1;
+ }
+
+ result.frame_number = mCurrentRequest.frameNumber;
+ result.result = mCurrentRequest.settings.getAndLock();
+ result.num_output_buffers = mCurrentRequest.buffers->size();
+ result.output_buffers = mCurrentRequest.buffers->array();
+
+ // Go idle if queue is empty, before sending result
+ bool signalIdle = false;
+ {
+ Mutex::Autolock l(mLock);
+ if (mInFlightQueue.empty()) {
+ mThreadActive = false;
+ signalIdle = true;
+ }
+ }
+ if (signalIdle) mParent->signalReadoutIdle();
+
+ // Send it off to the framework
+
+ mParent->sendCaptureResult(&result);
+
+ // Clean up
+ mCurrentRequest.settings.unlock(result.result);
+
+ delete mCurrentRequest.buffers;
+ mCurrentRequest.buffers = NULL;
+ delete mCurrentRequest.sensorBuffers;
+ mCurrentRequest.sensorBuffers = NULL;
+ mCurrentRequest.settings.clear();
+
+ return true;
+}
+
+
+}; // namespace android
diff --git a/camera/EmulatedFakeCamera3.h b/camera/EmulatedFakeCamera3.h
new file mode 100644
index 0000000..74f8496
--- /dev/null
+++ b/camera/EmulatedFakeCamera3.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA3_H
+#define HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA3_H
+
+/**
+ * Contains declaration of a class EmulatedCamera that encapsulates
+ * functionality of a fake camera that implements version 3 of the camera device
+ * interace.
+ */
+
+#include "EmulatedCamera3.h"
+#include "fake-pipeline2/Base.h"
+#include "fake-pipeline2/Sensor.h"
+#include "fake-pipeline2/JpegCompressor.h"
+#include <camera/CameraMetadata.h>
+#include <utils/List.h>
+#include <utils/Mutex.h>
+
+namespace android {
+
+/* Encapsulates functionality common to all version 3.0 emulated camera devices
+ *
+ * Note that EmulatedCameraFactory instantiates an object of this class just
+ * once, when EmulatedCameraFactory instance gets constructed. Connection to /
+ * disconnection from the actual camera device is handled by calls to
+ * connectDevice(), and closeCamera() methods of this class that are invoked in
+ * response to hw_module_methods_t::open, and camera_device::close callbacks.
+ */
+class EmulatedFakeCamera3 : public EmulatedCamera3 {
+public:
+
+ EmulatedFakeCamera3(int cameraId, bool facingBack,
+ struct hw_module_t* module);
+
+ virtual ~EmulatedFakeCamera3();
+
+ /****************************************************************************
+ * EmulatedCamera3 virtual overrides
+ ***************************************************************************/
+
+public:
+
+ virtual status_t Initialize();
+
+ /****************************************************************************
+ * Camera module API and generic hardware device API implementation
+ ***************************************************************************/
+
+public:
+ virtual status_t connectCamera(hw_device_t** device);
+
+ virtual status_t closeCamera();
+
+ virtual status_t getCameraInfo(struct camera_info *info);
+
+ /****************************************************************************
+ * EmualtedCamera3 abstract API implementation
+ ***************************************************************************/
+
+protected:
+
+ virtual status_t configureStreams(
+ camera3_stream_configuration *streamList);
+
+ virtual status_t registerStreamBuffers(
+ const camera3_stream_buffer_set *bufferSet) ;
+
+ virtual const camera_metadata_t* constructDefaultRequestSettings(
+ int type);
+
+ virtual status_t processCaptureRequest(camera3_capture_request *request);
+
+ /** Debug methods */
+
+ virtual void dump(int fd);
+
+ /** Tag query methods */
+ virtual const char *getVendorSectionName(uint32_t tag);
+
+ virtual const char *getVendorTagName(uint32_t tag);
+
+ virtual int getVendorTagType(uint32_t tag);
+
+private:
+
+ status_t constructStaticInfo();
+
+ /** Signal from readout thread that it doesn't have anything to do */
+ void signalReadoutIdle();
+
+ /****************************************************************************
+ * Static configuration information
+ ***************************************************************************/
+private:
+ static const uint32_t kMaxRawStreamCount = 1;
+ static const uint32_t kMaxProcessedStreamCount = 3;
+ static const uint32_t kMaxJpegStreamCount = 1;
+ static const uint32_t kMaxReprocessStreamCount = 2;
+ static const uint32_t kMaxBufferCount = 4;
+ static const uint32_t kAvailableFormats[];
+ static const uint32_t kAvailableRawSizes[];
+ static const uint64_t kAvailableRawMinDurations[];
+ static const uint32_t kAvailableProcessedSizesBack[];
+ static const uint32_t kAvailableProcessedSizesFront[];
+ static const uint64_t kAvailableProcessedMinDurations[];
+ static const uint32_t kAvailableJpegSizesBack[];
+ static const uint32_t kAvailableJpegSizesFront[];
+ static const uint64_t kAvailableJpegMinDurations[];
+
+ static const int64_t kSyncWaitTimeout = 10000000; // 10 ms
+ static const int32_t kMaxSyncTimeoutCount = 1000; // 1000 kSyncWaitTimeouts
+ static const uint32_t kFenceTimeoutMs = 2000; // 2 s
+
+ /****************************************************************************
+ * Data members.
+ ***************************************************************************/
+
+ /* HAL interface serialization lock. */
+ Mutex mLock;
+
+ /* Facing back (true) or front (false) switch. */
+ bool mFacingBack;
+
+ /**
+ * Cache for default templates. Once one is requested, the pointer must be
+ * valid at least until close() is called on the device
+ */
+ camera_metadata_t *mDefaultTemplates[CAMERA3_TEMPLATE_COUNT];
+
+ /**
+ * Private stream information, stored in camera3_stream_t->priv.
+ */
+ struct PrivateStreamInfo {
+ bool alive;
+ bool registered;
+ };
+
+ // Shortcut to the input stream
+ camera3_stream_t* mInputStream;
+
+ // All streams, including input stream
+ List<camera3_stream_t*> mStreams;
+
+ typedef List<camera3_stream_t*>::iterator StreamIterator;
+
+ // Cached settings from latest submitted request
+ CameraMetadata mPrevSettings;
+
+ /** Fake hardware interfaces */
+ sp<Sensor> mSensor;
+ sp<JpegCompressor> mJpegCompressor;
+
+ /** Processing thread for sending out results */
+
+ class ReadoutThread : public Thread {
+ public:
+ ReadoutThread(EmulatedFakeCamera3 *parent);
+ ~ReadoutThread();
+
+ struct Request {
+ uint32_t frameNumber;
+ CameraMetadata settings;
+ Vector<camera3_stream_buffer> *buffers;
+ Buffers *sensorBuffers;
+ };
+
+ void queueCaptureRequest(const Request &r);
+ bool isIdle();
+ status_t waitForReadout();
+
+ private:
+ static const nsecs_t kWaitPerLoop = 10000000L; // 10 ms
+ static const nsecs_t kMaxWaitLoops = 1000;
+ static const size_t kMaxQueueSize = 2;
+
+ EmulatedFakeCamera3 *mParent;
+ Mutex mLock;
+
+ List<Request> mInFlightQueue;
+ Condition mInFlightSignal;
+ bool mThreadActive;
+
+ virtual bool threadLoop();
+
+ // Only accessed by threadLoop
+
+ Request mCurrentRequest;
+
+ };
+
+ sp<ReadoutThread> mReadoutThread;
+};
+
+} // namespace android
+
+#endif // HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H
diff --git a/camera/fake-pipeline2/Sensor.cpp b/camera/fake-pipeline2/Sensor.cpp
index 316fe02..0c12f6f 100644
--- a/camera/fake-pipeline2/Sensor.cpp
+++ b/camera/fake-pipeline2/Sensor.cpp
@@ -100,9 +100,8 @@
-Sensor::Sensor(EmulatedFakeCamera2 *parent):
+Sensor::Sensor():
Thread(false),
- mParent(parent),
mGotVSync(false),
mExposureTime(kFrameDurationRange[0]-kMinVerticalBlank),
mFrameDuration(kFrameDurationRange[0]),
diff --git a/camera/fake-pipeline2/Sensor.h b/camera/fake-pipeline2/Sensor.h
index ce7b4ad..72128c5 100644
--- a/camera/fake-pipeline2/Sensor.h
+++ b/camera/fake-pipeline2/Sensor.h
@@ -87,7 +87,7 @@
class Sensor: private Thread, public virtual RefBase {
public:
- Sensor(EmulatedFakeCamera2 *parent);
+ Sensor();
~Sensor();
/*
@@ -172,8 +172,6 @@
static const uint32_t kDefaultSensitivity;
private:
- EmulatedFakeCamera2 *mParent;
-
Mutex mControlMutex; // Lock before accessing control parameters
// Start of control parameters
Condition mVSync;