summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2013-11-22 10:35:26 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2013-11-22 10:35:26 -0800
commitbae5cf92cfa9e2867af91057265df7f029f7865e (patch)
tree36c850418ad1433bef13b30be214f4f844a14efa /modules
parentaf822c43cf144a991db49d8c25068d054265ae37 (diff)
parentc9940a2bfe94dbe2ef3bfe5e8692bf4e3cea5ba0 (diff)
downloadhardware_libhardware-bae5cf92cfa9e2867af91057265df7f029f7865e.zip
hardware_libhardware-bae5cf92cfa9e2867af91057265df7f029f7865e.tar.gz
hardware_libhardware-bae5cf92cfa9e2867af91057265df7f029f7865e.tar.bz2
Merge commit 'c9940a2bfe94dbe2ef3bfe5e8692bf4e3cea5ba0' into HEAD
Diffstat (limited to 'modules')
-rw-r--r--modules/Android.mk3
-rw-r--r--modules/audio/audio_policy.c11
-rw-r--r--[-rwxr-xr-x]modules/audio_remote_submix/audio_hw.cpp8
-rw-r--r--modules/camera/Android.mk3
-rw-r--r--modules/camera/Camera.cpp528
-rw-r--r--modules/camera/Camera.h40
-rw-r--r--modules/camera/CameraHAL.cpp9
-rw-r--r--modules/camera/Metadata.cpp246
-rw-r--r--modules/camera/Metadata.h79
-rw-r--r--modules/camera/ScopedTrace.h51
-rw-r--r--modules/camera/Stream.cpp177
-rw-r--r--modules/camera/Stream.h79
-rw-r--r--modules/consumerir/Android.mk25
-rw-r--r--modules/consumerir/consumerir.c116
-rw-r--r--modules/gralloc/gralloc.cpp2
15 files changed, 1345 insertions, 32 deletions
diff --git a/modules/Android.mk b/modules/Android.mk
index 486b42d..b2d5a2a 100644
--- a/modules/Android.mk
+++ b/modules/Android.mk
@@ -1,2 +1,3 @@
-hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time power usbaudio audio_remote_submix camera
+hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time \
+ power usbaudio audio_remote_submix camera consumerir
include $(call all-named-subdir-makefiles,$(hardware_modules))
diff --git a/modules/audio/audio_policy.c b/modules/audio/audio_policy.c
index 2dd3dbe..9335654 100644
--- a/modules/audio/audio_policy.c
+++ b/modules/audio/audio_policy.c
@@ -99,7 +99,8 @@ static audio_io_handle_t ap_get_output(struct audio_policy *pol,
uint32_t sampling_rate,
audio_format_t format,
audio_channel_mask_t channelMask,
- audio_output_flags_t flags)
+ audio_output_flags_t flags,
+ const audio_offload_info_t *info)
{
return 0;
}
@@ -229,6 +230,12 @@ static int ap_dump(const struct audio_policy *pol, int fd)
return -ENOSYS;
}
+static bool ap_is_offload_supported(const struct audio_policy *pol,
+ const audio_offload_info_t *info)
+{
+ return false;
+}
+
static int create_default_ap(const struct audio_policy_device *device,
struct audio_policy_service_ops *aps_ops,
void *service,
@@ -278,6 +285,8 @@ static int create_default_ap(const struct audio_policy_device *device,
dap->policy.is_stream_active = ap_is_stream_active;
dap->policy.dump = ap_dump;
+ dap->policy.is_offload_supported = ap_is_offload_supported;
+
dap->service = service;
dap->aps_ops = aps_ops;
diff --git a/modules/audio_remote_submix/audio_hw.cpp b/modules/audio_remote_submix/audio_hw.cpp
index 5e88ef7..9df17b6 100755..100644
--- a/modules/audio_remote_submix/audio_hw.cpp
+++ b/modules/audio_remote_submix/audio_hw.cpp
@@ -271,7 +271,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
return 0;
} else {
// write() returned UNDERRUN or WOULD_BLOCK, retry
- ALOGE("out_write() write to pipe returned unexpected %16lx", written_frames);
+ ALOGE("out_write() write to pipe returned unexpected %d", written_frames);
written_frames = sink->write(buffer, frames);
}
}
@@ -281,7 +281,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
pthread_mutex_unlock(&out->dev->lock);
if (written_frames < 0) {
- ALOGE("out_write() failed writing to pipe with %16lx", written_frames);
+ ALOGE("out_write() failed writing to pipe with %d", written_frames);
return 0;
} else {
ALOGV("out_write() wrote %lu bytes)", written_frames * frame_size);
@@ -549,7 +549,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
rsxadev->config.channel_mask = config->channel_mask;
- if ((config->sample_rate != 48000) || (config->sample_rate != 44100)) {
+ if ((config->sample_rate != 48000) && (config->sample_rate != 44100)) {
config->sample_rate = DEFAULT_RATE_HZ;
}
rsxadev->config.rate = config->sample_rate;
@@ -708,7 +708,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
rsxadev->config.channel_mask = config->channel_mask;
- if ((config->sample_rate != 48000) || (config->sample_rate != 44100)) {
+ if ((config->sample_rate != 48000) && (config->sample_rate != 44100)) {
config->sample_rate = DEFAULT_RATE_HZ;
}
rsxadev->config.rate = config->sample_rate;
diff --git a/modules/camera/Android.mk b/modules/camera/Android.mk
index eebffc1..e02a143 100644
--- a/modules/camera/Android.mk
+++ b/modules/camera/Android.mk
@@ -26,11 +26,14 @@ LOCAL_C_INCLUDES += \
LOCAL_SRC_FILES := \
CameraHAL.cpp \
Camera.cpp \
+ Metadata.cpp \
+ Stream.cpp \
LOCAL_SHARED_LIBRARIES := \
libcamera_metadata \
libcutils \
liblog \
+ libsync \
LOCAL_CFLAGS += -Wall -Wextra -fvisibility=hidden
diff --git a/modules/camera/Camera.cpp b/modules/camera/Camera.cpp
index 203b772..973380e 100644
--- a/modules/camera/Camera.cpp
+++ b/modules/camera/Camera.cpp
@@ -17,7 +17,12 @@
#include <cstdlib>
#include <pthread.h>
#include <hardware/camera3.h>
+#include <sync/sync.h>
+#include <system/camera_metadata.h>
+#include <system/graphics.h>
#include "CameraHAL.h"
+#include "Metadata.h"
+#include "Stream.h"
//#define LOG_NDEBUG 0
#define LOG_TAG "Camera"
@@ -25,9 +30,14 @@
#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
#include <cutils/trace.h>
+#include "ScopedTrace.h"
#include "Camera.h"
+#define CAMERA_SYNC_TIMEOUT 5000 // in msecs
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
namespace default_camera_hal {
extern "C" {
@@ -42,14 +52,19 @@ static int close_device(hw_device_t* dev)
Camera::Camera(int id)
: mId(id),
+ mStaticInfo(NULL),
mBusy(false),
- mCallbackOps(NULL)
+ mCallbackOps(NULL),
+ mStreams(NULL),
+ mNumStreams(0),
+ mSettings(NULL)
{
- pthread_mutex_init(&mMutex,
- NULL); // No pthread mutex attributes.
+ pthread_mutex_init(&mMutex, NULL);
+ pthread_mutex_init(&mStaticInfoMutex, NULL);
memset(&mDevice, 0, sizeof(mDevice));
mDevice.common.tag = HARDWARE_DEVICE_TAG;
+ mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_0;
mDevice.common.close = close_device;
mDevice.ops = const_cast<camera3_device_ops_t*>(&sOps);
mDevice.priv = this;
@@ -57,16 +72,17 @@ Camera::Camera(int id)
Camera::~Camera()
{
+ pthread_mutex_destroy(&mMutex);
+ pthread_mutex_destroy(&mStaticInfoMutex);
}
int Camera::open(const hw_module_t *module, hw_device_t **device)
{
ALOGI("%s:%d: Opening camera device", __func__, mId);
- ATRACE_BEGIN(__func__);
+ CAMTRACE_CALL();
pthread_mutex_lock(&mMutex);
if (mBusy) {
pthread_mutex_unlock(&mMutex);
- ATRACE_END();
ALOGE("%s:%d: Error! Camera device already opened", __func__, mId);
return -EBUSY;
}
@@ -77,18 +93,33 @@ int Camera::open(const hw_module_t *module, hw_device_t **device)
*device = &mDevice.common;
pthread_mutex_unlock(&mMutex);
- ATRACE_END();
+ return 0;
+}
+
+int Camera::getInfo(struct camera_info *info)
+{
+ info->facing = CAMERA_FACING_FRONT;
+ info->orientation = 0;
+ info->device_version = mDevice.common.version;
+
+ pthread_mutex_lock(&mStaticInfoMutex);
+ if (mStaticInfo == NULL) {
+ mStaticInfo = initStaticInfo();
+ }
+ pthread_mutex_unlock(&mStaticInfoMutex);
+
+ info->static_camera_characteristics = mStaticInfo;
+
return 0;
}
int Camera::close()
{
ALOGI("%s:%d: Closing camera device", __func__, mId);
- ATRACE_BEGIN(__func__);
+ CAMTRACE_CALL();
pthread_mutex_lock(&mMutex);
if (!mBusy) {
pthread_mutex_unlock(&mMutex);
- ATRACE_END();
ALOGE("%s:%d: Error! Camera device not open", __func__, mId);
return -EINVAL;
}
@@ -97,7 +128,6 @@ int Camera::close()
mBusy = false;
pthread_mutex_unlock(&mMutex);
- ATRACE_END();
return 0;
}
@@ -105,44 +135,500 @@ int Camera::initialize(const camera3_callback_ops_t *callback_ops)
{
ALOGV("%s:%d: callback_ops=%p", __func__, mId, callback_ops);
mCallbackOps = callback_ops;
+ // Create standard settings templates
+ // 0 is invalid as template
+ mTemplates[0] = NULL;
+ // CAMERA3_TEMPLATE_PREVIEW = 1
+ mTemplates[1] = new Metadata(ANDROID_CONTROL_MODE_OFF,
+ ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW);
+ // CAMERA3_TEMPLATE_STILL_CAPTURE = 2
+ mTemplates[2] = new Metadata(ANDROID_CONTROL_MODE_OFF,
+ ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
+ // CAMERA3_TEMPLATE_VIDEO_RECORD = 3
+ mTemplates[3] = new Metadata(ANDROID_CONTROL_MODE_OFF,
+ ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
+ // CAMERA3_TEMPLATE_VIDEO_SNAPSHOT = 4
+ mTemplates[4] = new Metadata(ANDROID_CONTROL_MODE_OFF,
+ ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT);
+ // CAMERA3_TEMPLATE_STILL_ZERO_SHUTTER_LAG = 5
+ mTemplates[5] = new Metadata(ANDROID_CONTROL_MODE_OFF,
+ ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG);
+ // Pre-generate metadata structures
+ for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
+ mTemplates[i]->generate();
+ }
+ // TODO: create vendor templates
return 0;
}
-int Camera::configureStreams(camera3_stream_configuration_t *stream_list)
+camera_metadata_t *Camera::initStaticInfo()
+{
+ /*
+ * Setup static camera info. This will have to customized per camera
+ * device.
+ */
+ Metadata m;
+
+ /* android.control */
+ int32_t android_control_ae_available_target_fps_ranges[] = {30, 30};
+ m.addInt32(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+ ARRAY_SIZE(android_control_ae_available_target_fps_ranges),
+ android_control_ae_available_target_fps_ranges);
+
+ int32_t android_control_ae_compensation_range[] = {-4, 4};
+ m.addInt32(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+ ARRAY_SIZE(android_control_ae_compensation_range),
+ android_control_ae_compensation_range);
+
+ camera_metadata_rational_t android_control_ae_compensation_step[] = {{2,1}};
+ m.addRational(ANDROID_CONTROL_AE_COMPENSATION_STEP,
+ ARRAY_SIZE(android_control_ae_compensation_step),
+ android_control_ae_compensation_step);
+
+ int32_t android_control_max_regions[] = {1};
+ m.addInt32(ANDROID_CONTROL_MAX_REGIONS,
+ ARRAY_SIZE(android_control_max_regions),
+ android_control_max_regions);
+
+ /* android.jpeg */
+ int32_t android_jpeg_available_thumbnail_sizes[] = {0, 0, 128, 96};
+ m.addInt32(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+ ARRAY_SIZE(android_jpeg_available_thumbnail_sizes),
+ android_jpeg_available_thumbnail_sizes);
+
+ /* android.lens */
+ float android_lens_info_available_focal_lengths[] = {1.0};
+ m.addFloat(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+ ARRAY_SIZE(android_lens_info_available_focal_lengths),
+ android_lens_info_available_focal_lengths);
+
+ /* android.request */
+ int32_t android_request_max_num_output_streams[] = {0, 3, 1};
+ m.addInt32(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+ ARRAY_SIZE(android_request_max_num_output_streams),
+ android_request_max_num_output_streams);
+
+ /* android.scaler */
+ int32_t android_scaler_available_formats[] = {
+ HAL_PIXEL_FORMAT_RAW_SENSOR,
+ HAL_PIXEL_FORMAT_BLOB,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ // These are handled by YCbCr_420_888
+ // HAL_PIXEL_FORMAT_YV12,
+ // HAL_PIXEL_FORMAT_YCrCb_420_SP,
+ HAL_PIXEL_FORMAT_YCbCr_420_888};
+ m.addInt32(ANDROID_SCALER_AVAILABLE_FORMATS,
+ ARRAY_SIZE(android_scaler_available_formats),
+ android_scaler_available_formats);
+
+ int64_t android_scaler_available_jpeg_min_durations[] = {1};
+ m.addInt64(ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS,
+ ARRAY_SIZE(android_scaler_available_jpeg_min_durations),
+ android_scaler_available_jpeg_min_durations);
+
+ int32_t android_scaler_available_jpeg_sizes[] = {640, 480};
+ m.addInt32(ANDROID_SCALER_AVAILABLE_JPEG_SIZES,
+ ARRAY_SIZE(android_scaler_available_jpeg_sizes),
+ android_scaler_available_jpeg_sizes);
+
+ float android_scaler_available_max_digital_zoom[] = {1};
+ m.addFloat(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+ ARRAY_SIZE(android_scaler_available_max_digital_zoom),
+ android_scaler_available_max_digital_zoom);
+
+ int64_t android_scaler_available_processed_min_durations[] = {1};
+ m.addInt64(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS,
+ ARRAY_SIZE(android_scaler_available_processed_min_durations),
+ android_scaler_available_processed_min_durations);
+
+ int32_t android_scaler_available_processed_sizes[] = {640, 480};
+ m.addInt32(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES,
+ ARRAY_SIZE(android_scaler_available_processed_sizes),
+ android_scaler_available_processed_sizes);
+
+ int64_t android_scaler_available_raw_min_durations[] = {1};
+ m.addInt64(ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS,
+ ARRAY_SIZE(android_scaler_available_raw_min_durations),
+ android_scaler_available_raw_min_durations);
+
+ int32_t android_scaler_available_raw_sizes[] = {640, 480};
+ m.addInt32(ANDROID_SCALER_AVAILABLE_RAW_SIZES,
+ ARRAY_SIZE(android_scaler_available_raw_sizes),
+ android_scaler_available_raw_sizes);
+
+ /* android.sensor */
+
+ int32_t android_sensor_info_active_array_size[] = {0, 0, 640, 480};
+ m.addInt32(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+ ARRAY_SIZE(android_sensor_info_active_array_size),
+ android_sensor_info_active_array_size);
+
+ int32_t android_sensor_info_sensitivity_range[] =
+ {100, 1600};
+ m.addInt32(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
+ ARRAY_SIZE(android_sensor_info_sensitivity_range),
+ android_sensor_info_sensitivity_range);
+
+ int64_t android_sensor_info_max_frame_duration[] = {30000000000};
+ m.addInt64(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+ ARRAY_SIZE(android_sensor_info_max_frame_duration),
+ android_sensor_info_max_frame_duration);
+
+ float android_sensor_info_physical_size[] = {3.2, 2.4};
+ m.addFloat(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
+ ARRAY_SIZE(android_sensor_info_physical_size),
+ android_sensor_info_physical_size);
+
+ int32_t android_sensor_info_pixel_array_size[] = {640, 480};
+ m.addInt32(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+ ARRAY_SIZE(android_sensor_info_pixel_array_size),
+ android_sensor_info_pixel_array_size);
+
+ int32_t android_sensor_orientation[] = {0};
+ m.addInt32(ANDROID_SENSOR_ORIENTATION,
+ ARRAY_SIZE(android_sensor_orientation),
+ android_sensor_orientation);
+
+ /* End of static camera characteristics */
+
+ return clone_camera_metadata(m.generate());
+}
+
+int Camera::configureStreams(camera3_stream_configuration_t *stream_config)
{
- ALOGV("%s:%d: stream_list=%p", __func__, mId, stream_list);
- // TODO: validate input, create internal stream representations
+ camera3_stream_t *astream;
+ Stream **newStreams = NULL;
+
+ CAMTRACE_CALL();
+ ALOGV("%s:%d: stream_config=%p", __func__, mId, stream_config);
+
+ if (stream_config == NULL) {
+ ALOGE("%s:%d: NULL stream configuration array", __func__, mId);
+ return -EINVAL;
+ }
+ if (stream_config->num_streams == 0) {
+ ALOGE("%s:%d: Empty stream configuration array", __func__, mId);
+ return -EINVAL;
+ }
+
+ // Create new stream array
+ newStreams = new Stream*[stream_config->num_streams];
+ ALOGV("%s:%d: Number of Streams: %d", __func__, mId,
+ stream_config->num_streams);
+
+ pthread_mutex_lock(&mMutex);
+
+ // Mark all current streams unused for now
+ for (int i = 0; i < mNumStreams; i++)
+ mStreams[i]->mReuse = false;
+ // Fill new stream array with reused streams and new streams
+ for (unsigned int i = 0; i < stream_config->num_streams; i++) {
+ astream = stream_config->streams[i];
+ if (astream->max_buffers > 0) {
+ ALOGV("%s:%d: Reusing stream %d", __func__, mId, i);
+ newStreams[i] = reuseStream(astream);
+ } else {
+ ALOGV("%s:%d: Creating new stream %d", __func__, mId, i);
+ newStreams[i] = new Stream(mId, astream);
+ }
+
+ if (newStreams[i] == NULL) {
+ ALOGE("%s:%d: Error processing stream %d", __func__, mId, i);
+ goto err_out;
+ }
+ astream->priv = newStreams[i];
+ }
+
+ // Verify the set of streams in aggregate
+ if (!isValidStreamSet(newStreams, stream_config->num_streams)) {
+ ALOGE("%s:%d: Invalid stream set", __func__, mId);
+ goto err_out;
+ }
+
+ // Set up all streams (calculate usage/max_buffers for each)
+ setupStreams(newStreams, stream_config->num_streams);
+
+ // Destroy all old streams and replace stream array with new one
+ destroyStreams(mStreams, mNumStreams);
+ mStreams = newStreams;
+ mNumStreams = stream_config->num_streams;
+
+ // Clear out last seen settings metadata
+ setSettings(NULL);
+
+ pthread_mutex_unlock(&mMutex);
return 0;
+
+err_out:
+ // Clean up temporary streams, preserve existing mStreams/mNumStreams
+ destroyStreams(newStreams, stream_config->num_streams);
+ pthread_mutex_unlock(&mMutex);
+ return -EINVAL;
+}
+
+void Camera::destroyStreams(Stream **streams, int count)
+{
+ if (streams == NULL)
+ return;
+ for (int i = 0; i < count; i++) {
+ // Only destroy streams that weren't reused
+ if (streams[i] != NULL && !streams[i]->mReuse)
+ delete streams[i];
+ }
+ delete [] streams;
+}
+
+Stream *Camera::reuseStream(camera3_stream_t *astream)
+{
+ Stream *priv = reinterpret_cast<Stream*>(astream->priv);
+ // Verify the re-used stream's parameters match
+ if (!priv->isValidReuseStream(mId, astream)) {
+ ALOGE("%s:%d: Mismatched parameter in reused stream", __func__, mId);
+ return NULL;
+ }
+ // Mark stream to be reused
+ priv->mReuse = true;
+ return priv;
+}
+
+bool Camera::isValidStreamSet(Stream **streams, int count)
+{
+ int inputs = 0;
+ int outputs = 0;
+
+ if (streams == NULL) {
+ ALOGE("%s:%d: NULL stream configuration streams", __func__, mId);
+ return false;
+ }
+ if (count == 0) {
+ ALOGE("%s:%d: Zero count stream configuration streams", __func__, mId);
+ return false;
+ }
+ // Validate there is at most one input stream and at least one output stream
+ for (int i = 0; i < count; i++) {
+ // A stream may be both input and output (bidirectional)
+ if (streams[i]->isInputType())
+ inputs++;
+ if (streams[i]->isOutputType())
+ outputs++;
+ }
+ ALOGV("%s:%d: Configuring %d output streams and %d input streams",
+ __func__, mId, outputs, inputs);
+ if (outputs < 1) {
+ ALOGE("%s:%d: Stream config must have >= 1 output", __func__, mId);
+ return false;
+ }
+ if (inputs > 1) {
+ ALOGE("%s:%d: Stream config must have <= 1 input", __func__, mId);
+ return false;
+ }
+ // TODO: check for correct number of Bayer/YUV/JPEG/Encoder streams
+ return true;
+}
+
+void Camera::setupStreams(Stream **streams, int count)
+{
+ /*
+ * This is where the HAL has to decide internally how to handle all of the
+ * streams, and then produce usage and max_buffer values for each stream.
+ * Note, the stream array has been checked before this point for ALL invalid
+ * conditions, so it must find a successful configuration for this stream
+ * array. The HAL may not return an error from this point.
+ *
+ * In this demo HAL, we just set all streams to be the same dummy values;
+ * real implementations will want to avoid USAGE_SW_{READ|WRITE}_OFTEN.
+ */
+ for (int i = 0; i < count; i++) {
+ uint32_t usage = 0;
+
+ if (streams[i]->isOutputType())
+ usage |= GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_CAMERA_WRITE;
+ if (streams[i]->isInputType())
+ usage |= GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_HW_CAMERA_READ;
+
+ streams[i]->setUsage(usage);
+ streams[i]->setMaxBuffers(1);
+ }
}
int Camera::registerStreamBuffers(const camera3_stream_buffer_set_t *buf_set)
{
ALOGV("%s:%d: buffer_set=%p", __func__, mId, buf_set);
- // TODO: register buffers with hardware
- return 0;
+ if (buf_set == NULL) {
+ ALOGE("%s:%d: NULL buffer set", __func__, mId);
+ return -EINVAL;
+ }
+ if (buf_set->stream == NULL) {
+ ALOGE("%s:%d: NULL stream handle", __func__, mId);
+ return -EINVAL;
+ }
+ Stream *stream = reinterpret_cast<Stream*>(buf_set->stream->priv);
+ return stream->registerBuffers(buf_set);
}
const camera_metadata_t* Camera::constructDefaultRequestSettings(int type)
{
ALOGV("%s:%d: type=%d", __func__, mId, type);
- // TODO: return statically built default request
- return NULL;
+
+ if (type < 1 || type >= CAMERA3_TEMPLATE_COUNT) {
+ ALOGE("%s:%d: Invalid template request type: %d", __func__, mId, type);
+ return NULL;
+ }
+ return mTemplates[type]->generate();
}
int Camera::processCaptureRequest(camera3_capture_request_t *request)
{
+ camera3_capture_result result;
+
ALOGV("%s:%d: request=%p", __func__, mId, request);
- ATRACE_BEGIN(__func__);
+ CAMTRACE_CALL();
if (request == NULL) {
ALOGE("%s:%d: NULL request recieved", __func__, mId);
- ATRACE_END();
return -EINVAL;
}
- // TODO: verify request; submit request to hardware
- ATRACE_END();
+ ALOGV("%s:%d: Request Frame:%d Settings:%p", __func__, mId,
+ request->frame_number, request->settings);
+
+ // NULL indicates use last settings
+ if (request->settings == NULL) {
+ if (mSettings == NULL) {
+ ALOGE("%s:%d: NULL settings without previous set Frame:%d Req:%p",
+ __func__, mId, request->frame_number, request);
+ return -EINVAL;
+ }
+ } else {
+ setSettings(request->settings);
+ }
+
+ if (request->input_buffer != NULL) {
+ ALOGV("%s:%d: Reprocessing input buffer %p", __func__, mId,
+ request->input_buffer);
+
+ if (!isValidReprocessSettings(request->settings)) {
+ ALOGE("%s:%d: Invalid settings for reprocess request: %p",
+ __func__, mId, request->settings);
+ return -EINVAL;
+ }
+ } else {
+ ALOGV("%s:%d: Capturing new frame.", __func__, mId);
+
+ if (!isValidCaptureSettings(request->settings)) {
+ ALOGE("%s:%d: Invalid settings for capture request: %p",
+ __func__, mId, request->settings);
+ return -EINVAL;
+ }
+ }
+
+ if (request->num_output_buffers <= 0) {
+ ALOGE("%s:%d: Invalid number of output buffers: %d", __func__, mId,
+ request->num_output_buffers);
+ return -EINVAL;
+ }
+ result.num_output_buffers = request->num_output_buffers;
+ result.output_buffers = new camera3_stream_buffer_t[result.num_output_buffers];
+ for (unsigned int i = 0; i < request->num_output_buffers; i++) {
+ int res = processCaptureBuffer(&request->output_buffers[i],
+ const_cast<camera3_stream_buffer_t*>(&result.output_buffers[i]));
+ if (res)
+ goto err_out;
+ }
+
+ result.frame_number = request->frame_number;
+ // TODO: return actual captured/reprocessed settings
+ result.result = request->settings;
+ // TODO: asynchronously return results
+ notifyShutter(request->frame_number, 0);
+ mCallbackOps->process_capture_result(mCallbackOps, &result);
+
return 0;
+
+err_out:
+ delete [] result.output_buffers;
+ // TODO: this should probably be a total device failure; transient for now
+ return -EINVAL;
+}
+
+void Camera::setSettings(const camera_metadata_t *new_settings)
+{
+ if (mSettings != NULL) {
+ free_camera_metadata(mSettings);
+ mSettings = NULL;
+ }
+
+ if (new_settings != NULL)
+ mSettings = clone_camera_metadata(new_settings);
+}
+
+bool Camera::isValidCaptureSettings(const camera_metadata_t* /*settings*/)
+{
+ // TODO: reject settings that cannot be captured
+ return true;
+}
+
+bool Camera::isValidReprocessSettings(const camera_metadata_t* /*settings*/)
+{
+ // TODO: reject settings that cannot be reprocessed
+ // input buffers unimplemented, use this to reject reprocessing requests
+ ALOGE("%s:%d: Input buffer reprocessing not implemented", __func__, mId);
+ return false;
+}
+
+int Camera::processCaptureBuffer(const camera3_stream_buffer_t *in,
+ camera3_stream_buffer_t *out)
+{
+ if (in->acquire_fence != -1) {
+ int res = sync_wait(in->acquire_fence, CAMERA_SYNC_TIMEOUT);
+ if (res == -ETIME) {
+ ALOGE("%s:%d: Timeout waiting on buffer acquire fence",
+ __func__, mId);
+ return res;
+ } else if (res) {
+ ALOGE("%s:%d: Error waiting on buffer acquire fence: %s(%d)",
+ __func__, mId, strerror(-res), res);
+ return res;
+ }
+ }
+
+ out->stream = in->stream;
+ out->buffer = in->buffer;
+ out->status = CAMERA3_BUFFER_STATUS_OK;
+ // TODO: use driver-backed release fences
+ out->acquire_fence = -1;
+ out->release_fence = -1;
+
+ // TODO: lock and software-paint buffer
+ return 0;
+}
+
+void Camera::notifyShutter(uint32_t frame_number, uint64_t timestamp)
+{
+ int res;
+ struct timespec ts;
+
+ // If timestamp is 0, get timestamp from right now instead
+ if (timestamp == 0) {
+ ALOGW("%s:%d: No timestamp provided, using CLOCK_BOOTTIME",
+ __func__, mId);
+ res = clock_gettime(CLOCK_BOOTTIME, &ts);
+ if (res == 0) {
+ timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec;
+ } else {
+ ALOGE("%s:%d: No timestamp and failed to get CLOCK_BOOTTIME %s(%d)",
+ __func__, mId, strerror(errno), errno);
+ }
+ }
+ camera3_notify_msg_t m;
+ memset(&m, 0, sizeof(m));
+ m.type = CAMERA3_MSG_SHUTTER;
+ m.message.shutter.frame_number = frame_number;
+ m.message.shutter.timestamp = timestamp;
+ mCallbackOps->notify(mCallbackOps, &m);
}
void Camera::getMetadataVendorTagOps(vendor_tag_query_ops_t *ops)
@@ -153,7 +639,7 @@ void Camera::getMetadataVendorTagOps(vendor_tag_query_ops_t *ops)
void Camera::dump(int fd)
{
- ALOGV("%s:%d: Dumping to fd %d", fd);
+ ALOGV("%s:%d: Dumping to fd %d", __func__, mId, fd);
// TODO: dprintf all relevant state to fd
}
diff --git a/modules/camera/Camera.h b/modules/camera/Camera.h
index f2ad093..be672f9 100644
--- a/modules/camera/Camera.h
+++ b/modules/camera/Camera.h
@@ -20,6 +20,8 @@
#include <pthread.h>
#include <hardware/hardware.h>
#include <hardware/camera3.h>
+#include "Metadata.h"
+#include "Stream.h"
namespace default_camera_hal {
// Camera represents a physical camera on a device.
@@ -35,6 +37,7 @@ class Camera {
// Common Camera Device Operations (see <hardware/camera_common.h>)
int open(const hw_module_t *module, hw_device_t **device);
+ int getInfo(struct camera_info *info);
int close();
// Camera v3 Device Operations (see <hardware/camera3.h>)
@@ -50,8 +53,34 @@ class Camera {
camera3_device_t mDevice;
private:
+ // Separate initialization method for static metadata
+ camera_metadata_t *initStaticInfo();
+ // Reuse a stream already created by this device
+ Stream *reuseStream(camera3_stream_t *astream);
+ // Destroy all streams in a stream array, and the array itself
+ void destroyStreams(Stream **array, int count);
+ // Verify a set of streams is valid in aggregate
+ bool isValidStreamSet(Stream **array, int count);
+ // Calculate usage and max_bufs of each stream
+ void setupStreams(Stream **array, int count);
+ // Copy new settings for re-use and clean up old settings.
+ void setSettings(const camera_metadata_t *new_settings);
+ // Verify settings are valid for a capture
+ bool isValidCaptureSettings(const camera_metadata_t *settings);
+ // Verify settings are valid for reprocessing an input buffer
+ bool isValidReprocessSettings(const camera_metadata_t *settings);
+ // Process an output buffer
+ int processCaptureBuffer(const camera3_stream_buffer_t *in,
+ camera3_stream_buffer_t *out);
+ // Send a shutter notify message with start of exposure time
+ void notifyShutter(uint32_t frame_number, uint64_t timestamp);
+
// Identifier used by framework to distinguish cameras
const int mId;
+ // Metadata containing persistent camera characteristics
+ Metadata mMetadata;
+ // camera_metadata structure containing static characteristics
+ camera_metadata_t *mStaticInfo;
// Busy flag indicates camera is in use
bool mBusy;
// Camera device operations handle shared by all devices
@@ -60,6 +89,17 @@ class Camera {
const camera3_callback_ops_t *mCallbackOps;
// Lock protecting the Camera object for modifications
pthread_mutex_t mMutex;
+ // Lock protecting only static camera characteristics, which may
+ // be accessed without the camera device open
+ pthread_mutex_t mStaticInfoMutex;
+ // Array of handles to streams currently in use by the device
+ Stream **mStreams;
+ // Number of streams in mStreams
+ int mNumStreams;
+ // Static array of standard camera settings templates
+ Metadata *mTemplates[CAMERA3_TEMPLATE_COUNT];
+ // Most recent request settings seen, memoized to be reused
+ camera_metadata_t *mSettings;
};
} // namespace default_camera_hal
diff --git a/modules/camera/CameraHAL.cpp b/modules/camera/CameraHAL.cpp
index 6cae7d2..dfbbe4c 100644
--- a/modules/camera/CameraHAL.cpp
+++ b/modules/camera/CameraHAL.cpp
@@ -76,7 +76,7 @@ int CameraHAL::getCameraInfo(int id, struct camera_info* info)
return -ENODEV;
}
// TODO: return device-specific static metadata
- return 0;
+ return mCameras[id]->getInfo(info);
}
int CameraHAL::setCallbacks(const camera_module_callbacks_t *callbacks)
@@ -90,11 +90,14 @@ int CameraHAL::open(const hw_module_t* mod, const char* name, hw_device_t** dev)
{
int id;
char *nameEnd;
- Camera *cam;
ALOGV("%s: module=%p, name=%s, device=%p", __func__, mod, name, dev);
+ if (*name == '\0') {
+ ALOGE("%s: Invalid camera id name is NULL", __func__);
+ return -EINVAL;
+ }
id = strtol(name, &nameEnd, 10);
- if (nameEnd != NULL) {
+ if (*nameEnd != '\0') {
ALOGE("%s: Invalid camera id name %s", __func__, name);
return -EINVAL;
} else if (id < 0 || id >= mNumberOfCameras) {
diff --git a/modules/camera/Metadata.cpp b/modules/camera/Metadata.cpp
new file mode 100644
index 0000000..d5854f9
--- /dev/null
+++ b/modules/camera/Metadata.cpp
@@ -0,0 +1,246 @@
+/*
+ * 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.
+ */
+
+#include <pthread.h>
+#include <system/camera_metadata.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Metadata"
+#include <cutils/log.h>
+
+#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+#include <cutils/trace.h>
+#include "ScopedTrace.h"
+
+#include "Metadata.h"
+
+namespace default_camera_hal {
+
+Metadata::Metadata()
+ : mHead(NULL),
+ mTail(NULL),
+ mEntryCount(0),
+ mDataCount(0),
+ mGenerated(NULL),
+ mDirty(true)
+{
+ // NULL (default) pthread mutex attributes
+ pthread_mutex_init(&mMutex, NULL);
+}
+
+Metadata::~Metadata()
+{
+ Entry *current = mHead;
+
+ while (current != NULL) {
+ Entry *tmp = current;
+ current = current->mNext;
+ delete tmp;
+ }
+
+ if (mGenerated != NULL)
+ free_camera_metadata(mGenerated);
+
+ pthread_mutex_destroy(&mMutex);
+}
+
+Metadata::Metadata(uint8_t mode, uint8_t intent)
+ : mHead(NULL),
+ mTail(NULL),
+ mEntryCount(0),
+ mDataCount(0),
+ mGenerated(NULL),
+ mDirty(true)
+{
+ pthread_mutex_init(&mMutex, NULL);
+
+ if (validate(ANDROID_CONTROL_MODE, TYPE_BYTE, 1)) {
+ int res = add(ANDROID_CONTROL_MODE, 1, &mode);
+ if (res != 0) {
+ ALOGE("%s: Unable to add mode to template!", __func__);
+ }
+ } else {
+ ALOGE("%s: Invalid mode constructing template!", __func__);
+ }
+
+ if (validate(ANDROID_CONTROL_CAPTURE_INTENT, TYPE_BYTE, 1)) {
+ int res = add(ANDROID_CONTROL_CAPTURE_INTENT, 1, &intent);
+ if (res != 0) {
+ ALOGE("%s: Unable to add capture intent to template!", __func__);
+ }
+ } else {
+ ALOGE("%s: Invalid capture intent constructing template!", __func__);
+ }
+}
+
+int Metadata::addUInt8(uint32_t tag, int count, uint8_t *data)
+{
+ if (!validate(tag, TYPE_BYTE, count)) return -EINVAL;
+ return add(tag, count, data);
+}
+
+int Metadata::addInt32(uint32_t tag, int count, int32_t *data)
+{
+ if (!validate(tag, TYPE_INT32, count)) return -EINVAL;
+ return add(tag, count, data);
+}
+
+int Metadata::addFloat(uint32_t tag, int count, float *data)
+{
+ if (!validate(tag, TYPE_FLOAT, count)) return -EINVAL;
+ return add(tag, count, data);
+}
+
+int Metadata::addInt64(uint32_t tag, int count, int64_t *data)
+{
+ if (!validate(tag, TYPE_INT64, count)) return -EINVAL;
+ return add(tag, count, data);
+}
+
+int Metadata::addDouble(uint32_t tag, int count, double *data)
+{
+ if (!validate(tag, TYPE_DOUBLE, count)) return -EINVAL;
+ return add(tag, count, data);
+}
+
+int Metadata::addRational(uint32_t tag, int count,
+ camera_metadata_rational_t *data)
+{
+ if (!validate(tag, TYPE_RATIONAL, count)) return -EINVAL;
+ return add(tag, count, data);
+}
+
+bool Metadata::validate(uint32_t tag, int tag_type, int count)
+{
+ if (get_camera_metadata_tag_type(tag) < 0) {
+ ALOGE("%s: Invalid metadata entry tag: %d", __func__, tag);
+ return false;
+ }
+ if (tag_type < 0 || tag_type >= NUM_TYPES) {
+ ALOGE("%s: Invalid metadata entry tag type: %d", __func__, tag_type);
+ return false;
+ }
+ if (tag_type != get_camera_metadata_tag_type(tag)) {
+ ALOGE("%s: Tag %d called with incorrect type: %s(%d)", __func__, tag,
+ camera_metadata_type_names[tag_type], tag_type);
+ return false;
+ }
+ if (count < 1) {
+ ALOGE("%s: Invalid metadata entry count: %d", __func__, count);
+ return false;
+ }
+ return true;
+}
+
+int Metadata::add(uint32_t tag, int count, void *tag_data)
+{
+ int tag_type = get_camera_metadata_tag_type(tag);
+ size_t type_sz = camera_metadata_type_size[tag_type];
+
+ // Allocate array to hold new metadata
+ void *data = malloc(count * type_sz);
+ if (data == NULL)
+ return -ENOMEM;
+ memcpy(data, tag_data, count * type_sz);
+
+ pthread_mutex_lock(&mMutex);
+ mEntryCount++;
+ mDataCount += calculate_camera_metadata_entry_data_size(tag_type, count);
+ push(new Entry(tag, data, count));
+ mDirty = true;
+ pthread_mutex_unlock(&mMutex);
+ return 0;
+}
+
+camera_metadata_t* Metadata::generate()
+{
+ pthread_mutex_lock(&mMutex);
+ // Reuse if old generated metadata still valid
+ if (!mDirty && mGenerated != NULL) {
+ ALOGV("%s: Reusing generated metadata at %p", __func__, mGenerated);
+ goto out;
+ }
+ // Destroy old metadata
+ if (mGenerated != NULL) {
+ ALOGV("%s: Freeing generated metadata at %p", __func__, mGenerated);
+ free_camera_metadata(mGenerated);
+ mGenerated = NULL;
+ }
+ // Generate new metadata structure
+ ALOGV("%s: Generating new camera metadata structure, Entries:%d Data:%d",
+ __func__, mEntryCount, mDataCount);
+ mGenerated = allocate_camera_metadata(mEntryCount, mDataCount);
+ if (mGenerated == NULL) {
+ ALOGE("%s: Failed to allocate metadata (%d entries %d data)",
+ __func__, mEntryCount, mDataCount);
+ goto out;
+ }
+ // Walk list of entries adding each one to newly allocated metadata
+ for (Entry *current = mHead; current != NULL; current = current->mNext) {
+ int res = add_camera_metadata_entry(mGenerated, current->mTag,
+ current->mData, current->mCount);
+ if (res != 0) {
+ ALOGE("%s: Failed to add camera metadata: %d", __func__, res);
+ free_camera_metadata(mGenerated);
+ mGenerated = NULL;
+ goto out;
+ }
+ }
+
+out:
+ pthread_mutex_unlock(&mMutex);
+ return mGenerated;
+}
+
+Metadata::Entry::Entry(uint32_t tag, void *data, int count)
+ : mNext(NULL),
+ mPrev(NULL),
+ mTag(tag),
+ mData(data),
+ mCount(count)
+{
+}
+
+void Metadata::push(Entry *e)
+{
+ if (mHead == NULL) {
+ mHead = mTail = e;
+ } else {
+ mTail->insertAfter(e);
+ mTail = e;
+ }
+}
+
+Metadata::Entry::~Entry()
+{
+ if (mNext != NULL)
+ mNext->mPrev = mPrev;
+ if (mPrev != NULL)
+ mPrev->mNext = mNext;
+}
+
+void Metadata::Entry::insertAfter(Entry *e)
+{
+ if (e == NULL)
+ return;
+ if (mNext != NULL)
+ mNext->mPrev = e;
+ e->mNext = mNext;
+ e->mPrev = this;
+ mNext = e;
+}
+
+} // namespace default_camera_hal
diff --git a/modules/camera/Metadata.h b/modules/camera/Metadata.h
new file mode 100644
index 0000000..22d2f22
--- /dev/null
+++ b/modules/camera/Metadata.h
@@ -0,0 +1,79 @@
+/*
+ * 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 METADATA_H_
+#define METADATA_H_
+
+#include <hardware/camera3.h>
+#include <hardware/gralloc.h>
+#include <system/camera_metadata.h>
+#include <system/graphics.h>
+
+namespace default_camera_hal {
+// Metadata is a convenience class for dealing with libcamera_metadata
+class Metadata {
+ public:
+ Metadata();
+ ~Metadata();
+ // Constructor used for request metadata templates
+ Metadata(uint8_t mode, uint8_t intent);
+
+ // Parse and add an entry
+ int addUInt8(uint32_t tag, int count, uint8_t *data);
+ int addInt32(uint32_t tag, int count, int32_t *data);
+ int addFloat(uint32_t tag, int count, float *data);
+ int addInt64(uint32_t tag, int count, int64_t *data);
+ int addDouble(uint32_t tag, int count, double *data);
+ int addRational(uint32_t tag, int count,
+ camera_metadata_rational_t *data);
+ // Generate a camera_metadata structure and fill it with internal data
+ camera_metadata_t *generate();
+
+ private:
+ // Validate the tag, type and count for a metadata entry
+ bool validate(uint32_t tag, int tag_type, int count);
+ // Add a verified tag with data to this Metadata structure
+ int add(uint32_t tag, int count, void *tag_data);
+
+ class Entry {
+ public:
+ Entry(uint32_t tag, void *data, int count);
+ ~Entry();
+ Entry *mNext;
+ Entry *mPrev;
+ const uint32_t mTag;
+ const void *mData;
+ const int mCount;
+ void insertAfter(Entry *e);
+ };
+ // List ends
+ Entry *mHead;
+ Entry *mTail;
+ // Append entry to list
+ void push(Entry *e);
+ // Total of entries and entry data size
+ int mEntryCount;
+ int mDataCount;
+ // Save generated metadata, invalidated on update
+ camera_metadata_t *mGenerated;
+ // Flag to force metadata regeneration
+ bool mDirty;
+ // Lock protecting the Metadata object for modifications
+ pthread_mutex_t mMutex;
+};
+} // namespace default_camera_hal
+
+#endif // METADATA_H_
diff --git a/modules/camera/ScopedTrace.h b/modules/camera/ScopedTrace.h
new file mode 100644
index 0000000..ed00570
--- /dev/null
+++ b/modules/camera/ScopedTrace.h
@@ -0,0 +1,51 @@
+/*
+ * 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 CAMERA_SCOPED_TRACE_H
+#define CAMERA_SCOPED_TRACE_H
+
+#include <stdint.h>
+#include <cutils/trace.h>
+
+// See <cutils/trace.h> for more tracing macros.
+
+// CAMTRACE_NAME traces the beginning and end of the current scope. To trace
+// the correct start and end times this macro should be declared first in the
+// scope body.
+#define CAMTRACE_NAME(name) ScopedTrace ___tracer(ATRACE_TAG, name)
+// CAMTRACE_CALL is an ATRACE_NAME that uses the current function name.
+#define CAMTRACE_CALL() CAMTRACE_NAME(__FUNCTION__)
+
+namespace default_camera_hal {
+
+class ScopedTrace {
+public:
+inline ScopedTrace(uint64_t tag, const char* name)
+ : mTag(tag) {
+ atrace_begin(mTag,name);
+}
+
+inline ~ScopedTrace() {
+ atrace_end(mTag);
+}
+
+private:
+ uint64_t mTag;
+};
+
+}; // namespace default_camera_hal
+
+#endif // CAMERA_SCOPED_TRACE_H
diff --git a/modules/camera/Stream.cpp b/modules/camera/Stream.cpp
new file mode 100644
index 0000000..aae7adb
--- /dev/null
+++ b/modules/camera/Stream.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+#include <pthread.h>
+#include <hardware/camera3.h>
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Stream"
+#include <cutils/log.h>
+
+#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+#include <cutils/trace.h>
+#include "ScopedTrace.h"
+
+#include "Stream.h"
+
+namespace default_camera_hal {
+
+Stream::Stream(int id, camera3_stream_t *s)
+ : mReuse(false),
+ mId(id),
+ mStream(s),
+ mType(s->stream_type),
+ mWidth(s->width),
+ mHeight(s->height),
+ mFormat(s->format),
+ mUsage(0),
+ mMaxBuffers(0),
+ mRegistered(false),
+ mBuffers(0),
+ mNumBuffers(0)
+{
+ // NULL (default) pthread mutex attributes
+ pthread_mutex_init(&mMutex, NULL);
+}
+
+Stream::~Stream()
+{
+ pthread_mutex_lock(&mMutex);
+ unregisterBuffers_L();
+ pthread_mutex_unlock(&mMutex);
+}
+
+void Stream::setUsage(uint32_t usage)
+{
+ pthread_mutex_lock(&mMutex);
+ if (usage != mUsage) {
+ mUsage = usage;
+ mStream->usage = usage;
+ unregisterBuffers_L();
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+void Stream::setMaxBuffers(uint32_t max_buffers)
+{
+ pthread_mutex_lock(&mMutex);
+ if (max_buffers != mMaxBuffers) {
+ mMaxBuffers = max_buffers;
+ mStream->max_buffers = max_buffers;
+ unregisterBuffers_L();
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+int Stream::getType()
+{
+ return mType;
+}
+
+bool Stream::isInputType()
+{
+ return mType == CAMERA3_STREAM_INPUT ||
+ mType == CAMERA3_STREAM_BIDIRECTIONAL;
+}
+
+bool Stream::isOutputType()
+{
+ return mType == CAMERA3_STREAM_OUTPUT ||
+ mType == CAMERA3_STREAM_BIDIRECTIONAL;
+}
+
+bool Stream::isRegistered()
+{
+ return mRegistered;
+}
+
+bool Stream::isValidReuseStream(int id, camera3_stream_t *s)
+{
+ if (id != mId) {
+ ALOGE("%s:%d: Invalid camera id for reuse. Got %d expect %d",
+ __func__, mId, id, mId);
+ return false;
+ }
+ if (s != mStream) {
+ ALOGE("%s:%d: Invalid stream handle for reuse. Got %p expect %p",
+ __func__, mId, s, mStream);
+ return false;
+ }
+ if (s->stream_type != mType) {
+ // TODO: prettyprint type string
+ ALOGE("%s:%d: Mismatched type in reused stream. Got %d expect %d",
+ __func__, mId, s->stream_type, mType);
+ return false;
+ }
+ if (s->format != mFormat) {
+ // TODO: prettyprint format string
+ ALOGE("%s:%d: Mismatched format in reused stream. Got %d expect %d",
+ __func__, mId, s->format, mFormat);
+ return false;
+ }
+ if (s->width != mWidth) {
+ ALOGE("%s:%d: Mismatched width in reused stream. Got %d expect %d",
+ __func__, mId, s->width, mWidth);
+ return false;
+ }
+ if (s->height != mHeight) {
+ ALOGE("%s:%d: Mismatched height in reused stream. Got %d expect %d",
+ __func__, mId, s->height, mHeight);
+ return false;
+ }
+ return true;
+}
+
+int Stream::registerBuffers(const camera3_stream_buffer_set_t *buf_set)
+{
+ CAMTRACE_CALL();
+
+ if (buf_set->stream != mStream) {
+ ALOGE("%s:%d: Buffer set for invalid stream. Got %p expect %p",
+ __func__, mId, buf_set->stream, mStream);
+ return -EINVAL;
+ }
+
+ pthread_mutex_lock(&mMutex);
+
+ mNumBuffers = buf_set->num_buffers;
+ mBuffers = new buffer_handle_t*[mNumBuffers];
+
+ for (unsigned int i = 0; i < mNumBuffers; i++) {
+ ALOGV("%s:%d: Registering buffer %p", __func__, mId,
+ buf_set->buffers[i]);
+ mBuffers[i] = buf_set->buffers[i];
+ // TODO: register buffers with hw, handle error cases
+ }
+ mRegistered = true;
+
+ pthread_mutex_unlock(&mMutex);
+
+ return 0;
+}
+
+// This must only be called with mMutex held
+void Stream::unregisterBuffers_L()
+{
+ mRegistered = false;
+ mNumBuffers = 0;
+ delete [] mBuffers;
+ // TODO: unregister buffers from hw
+}
+
+} // namespace default_camera_hal
diff --git a/modules/camera/Stream.h b/modules/camera/Stream.h
new file mode 100644
index 0000000..34abd95
--- /dev/null
+++ b/modules/camera/Stream.h
@@ -0,0 +1,79 @@
+/*
+ * 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 STREAM_H_
+#define STREAM_H_
+
+#include <hardware/camera3.h>
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+
+namespace default_camera_hal {
+// Stream represents a single input or output stream for a camera device.
+class Stream {
+ public:
+ Stream(int id, camera3_stream_t *s);
+ ~Stream();
+
+ // validate that astream's parameters match this stream's parameters
+ bool isValidReuseStream(int id, camera3_stream_t *s);
+
+ // Register buffers with hardware
+ int registerBuffers(const camera3_stream_buffer_set_t *buf_set);
+
+ void setUsage(uint32_t usage);
+ void setMaxBuffers(uint32_t max_buffers);
+
+ int getType();
+ bool isInputType();
+ bool isOutputType();
+ bool isRegistered();
+
+ // This stream is being reused. Used in stream configuration passes
+ bool mReuse;
+
+ private:
+ // Clean up buffer state. must be called with mMutex held.
+ void unregisterBuffers_L();
+
+ // The camera device id this stream belongs to
+ const int mId;
+ // Handle to framework's stream, used as a cookie for buffers
+ camera3_stream_t *mStream;
+ // Stream type: CAMERA3_STREAM_* (see <hardware/camera3.h>)
+ const int mType;
+ // Width in pixels of the buffers in this stream
+ const uint32_t mWidth;
+ // Height in pixels of the buffers in this stream
+ const uint32_t mHeight;
+ // Gralloc format: HAL_PIXEL_FORMAT_* (see <system/graphics.h>)
+ const int mFormat;
+ // Gralloc usage mask : GRALLOC_USAGE_* (see <hardware/gralloc.h>)
+ uint32_t mUsage;
+ // Max simultaneous in-flight buffers for this stream
+ uint32_t mMaxBuffers;
+ // Buffers have been registered for this stream and are ready
+ bool mRegistered;
+ // Array of handles to buffers currently in use by the stream
+ buffer_handle_t **mBuffers;
+ // Number of buffers in mBuffers
+ unsigned int mNumBuffers;
+ // Lock protecting the Stream object for modifications
+ pthread_mutex_t mMutex;
+};
+} // namespace default_camera_hal
+
+#endif // STREAM_H_
diff --git a/modules/consumerir/Android.mk b/modules/consumerir/Android.mk
new file mode 100644
index 0000000..ed6aa0f
--- /dev/null
+++ b/modules/consumerir/Android.mk
@@ -0,0 +1,25 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := consumerir.default
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SRC_FILES := consumerir.c
+LOCAL_SHARED_LIBRARIES := liblog libcutils
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/modules/consumerir/consumerir.c b/modules/consumerir/consumerir.c
new file mode 100644
index 0000000..83eba75
--- /dev/null
+++ b/modules/consumerir/consumerir.c
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+#define LOG_TAG "ConsumerIrHal"
+
+#include <errno.h>
+#include <string.h>
+#include <cutils/log.h>
+#include <hardware/hardware.h>
+#include <hardware/consumerir.h>
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+static const consumerir_freq_range_t consumerir_freqs[] = {
+ {.min = 30000, .max = 30000},
+ {.min = 33000, .max = 33000},
+ {.min = 36000, .max = 36000},
+ {.min = 38000, .max = 38000},
+ {.min = 40000, .max = 40000},
+ {.min = 56000, .max = 56000},
+};
+
+static int consumerir_transmit(struct consumerir_device *dev,
+ int carrier_freq, int pattern[], int pattern_len)
+{
+ int total_time = 0;
+ long i;
+
+ for (i = 0; i < pattern_len; i++)
+ total_time += pattern[i];
+
+ /* simulate the time spent transmitting by sleeping */
+ ALOGD("transmit for %d uS at %d Hz", total_time, carrier_freq);
+ usleep(total_time);
+
+ return 0;
+}
+
+static int consumerir_get_num_carrier_freqs(struct consumerir_device *dev)
+{
+ return ARRAY_SIZE(consumerir_freqs);
+}
+
+static int consumerir_get_carrier_freqs(struct consumerir_device *dev,
+ size_t len, consumerir_freq_range_t *ranges)
+{
+ size_t to_copy = ARRAY_SIZE(consumerir_freqs);
+
+ to_copy = len < to_copy ? len : to_copy;
+ memcpy(ranges, consumerir_freqs, to_copy * sizeof(consumerir_freq_range_t));
+ return to_copy;
+}
+
+static int consumerir_close(hw_device_t *dev)
+{
+ free(dev);
+ return 0;
+}
+
+/*
+ * Generic device handling
+ */
+static int consumerir_open(const hw_module_t* module, const char* name,
+ hw_device_t** device)
+{
+ if (strcmp(name, CONSUMERIR_TRANSMITTER) != 0) {
+ return -EINVAL;
+ }
+ if (device == NULL) {
+ ALOGE("NULL device on open");
+ return -EINVAL;
+ }
+
+ consumerir_device_t *dev = malloc(sizeof(consumerir_device_t));
+ memset(dev, 0, sizeof(consumerir_device_t));
+
+ dev->common.tag = HARDWARE_DEVICE_TAG;
+ dev->common.version = 0;
+ dev->common.module = (struct hw_module_t*) module;
+ dev->common.close = consumerir_close;
+
+ dev->transmit = consumerir_transmit;
+ dev->get_num_carrier_freqs = consumerir_get_num_carrier_freqs;
+ dev->get_carrier_freqs = consumerir_get_carrier_freqs;
+
+ *device = (hw_device_t*) dev;
+ return 0;
+}
+
+static struct hw_module_methods_t consumerir_module_methods = {
+ .open = consumerir_open,
+};
+
+consumerir_module_t HAL_MODULE_INFO_SYM = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = CONSUMERIR_MODULE_API_VERSION_1_0,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
+ .id = CONSUMERIR_HARDWARE_MODULE_ID,
+ .name = "Demo IR HAL",
+ .author = "The Android Open Source Project",
+ .methods = &consumerir_module_methods,
+ },
+};
diff --git a/modules/gralloc/gralloc.cpp b/modules/gralloc/gralloc.cpp
index 03d46d5..f832f35 100644
--- a/modules/gralloc/gralloc.cpp
+++ b/modules/gralloc/gralloc.cpp
@@ -217,8 +217,6 @@ static int gralloc_alloc(alloc_device_t* dev,
bpp = 3;
break;
case HAL_PIXEL_FORMAT_RGB_565:
- case HAL_PIXEL_FORMAT_RGBA_5551:
- case HAL_PIXEL_FORMAT_RGBA_4444:
case HAL_PIXEL_FORMAT_RAW_SENSOR:
bpp = 2;
break;