am 1769442f: am e847651d: Merge "All tests should fail immediate to avoid SEGV"
* commit '1769442facb751a00a80959d492bc7f4797da4f2':
All tests should fail immediate to avoid SEGV
diff --git a/include/hardware/audio_effect.h b/include/hardware/audio_effect.h
index 46e323d..2c8f2e3 100644
--- a/include/hardware/audio_effect.h
+++ b/include/hardware/audio_effect.h
@@ -873,8 +873,10 @@
// Effect library interface
/////////////////////////////////////////////////
-// Effect library interface version 2.0
-#define EFFECT_LIBRARY_API_VERSION EFFECT_MAKE_API_VERSION(2,0)
+// Effect library interface version 3.0
+// Note that EffectsFactory.c only checks the major version component, so changes to the minor
+// number can only be used for fully backwards compatible changes
+#define EFFECT_LIBRARY_API_VERSION EFFECT_MAKE_API_VERSION(3,0)
#define AUDIO_EFFECT_LIBRARY_TAG ((('A') << 24) | (('E') << 16) | (('L') << 8) | ('T'))
@@ -893,57 +895,6 @@
////////////////////////////////////////////////////////////////////////////////
//
- // Function: query_num_effects
- //
- // Description: Returns the number of different effects exposed by the
- // library. Each effect must have a unique effect uuid (see
- // effect_descriptor_t). This function together with EffectQueryEffect()
- // is used to enumerate all effects present in the library.
- //
- // Input/Output:
- // pNumEffects: address where the number of effects should be returned.
- //
- // Output:
- // returned value: 0 successful operation.
- // -ENODEV library failed to initialize
- // -EINVAL invalid pNumEffects
- // *pNumEffects: updated with number of effects in library
- //
- ////////////////////////////////////////////////////////////////////////////////
- int32_t (*query_num_effects)(uint32_t *pNumEffects);
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Function: query_effect
- //
- // Description: Returns the descriptor of the effect engine which index is
- // given as argument.
- // See effect_descriptor_t for details on effect descriptors.
- // This function together with EffectQueryNumberEffects() is used to enumerate all
- // effects present in the library. The enumeration sequence is:
- // EffectQueryNumberEffects(&num_effects);
- // for (i = 0; i < num_effects; i++)
- // EffectQueryEffect(i,...);
- //
- // Input/Output:
- // index: index of the effect
- // pDescriptor: address where to return the effect descriptor.
- //
- // Output:
- // returned value: 0 successful operation.
- // -ENODEV library failed to initialize
- // -EINVAL invalid pDescriptor or index
- // -ENOSYS effect list has changed since last execution of
- // EffectQueryNumberEffects()
- // -ENOENT no more effect available
- // *pDescriptor: updated with the effect descriptor.
- //
- ////////////////////////////////////////////////////////////////////////////////
- int32_t (*query_effect)(uint32_t index,
- effect_descriptor_t *pDescriptor);
-
- ////////////////////////////////////////////////////////////////////////////////
- //
// Function: create_effect
//
// Description: Creates an effect engine of the specified implementation uuid and
diff --git a/include/hardware/sensors.h b/include/hardware/sensors.h
index af6bced..e0ed8a9 100644
--- a/include/hardware/sensors.h
+++ b/include/hardware/sensors.h
@@ -26,6 +26,12 @@
__BEGIN_DECLS
+/*****************************************************************************/
+
+#define SENSORS_HEADER_VERSION 1
+#define SENSORS_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1)
+#define SENSORS_DEVICE_API_VERSION_0_1 HARDWARE_DEVICE_API_VERSION_2(0, 1, SENSORS_HEADER_VERSION)
+
/**
* The id of this module
*/
@@ -48,49 +54,7 @@
/**
- * Sensor types
- */
-#define SENSOR_TYPE_ACCELEROMETER 1
-#define SENSOR_TYPE_MAGNETIC_FIELD 2
-#define SENSOR_TYPE_ORIENTATION 3
-#define SENSOR_TYPE_GYROSCOPE 4
-#define SENSOR_TYPE_LIGHT 5
-#define SENSOR_TYPE_PRESSURE 6
-#define SENSOR_TYPE_TEMPERATURE 7 // deprecated
-#define SENSOR_TYPE_PROXIMITY 8
-#define SENSOR_TYPE_GRAVITY 9
-#define SENSOR_TYPE_LINEAR_ACCELERATION 10
-#define SENSOR_TYPE_ROTATION_VECTOR 11
-#define SENSOR_TYPE_RELATIVE_HUMIDITY 12
-#define SENSOR_TYPE_AMBIENT_TEMPERATURE 13
-
-/**
- * Values returned by the accelerometer in various locations in the universe.
- * all values are in SI units (m/s^2)
- */
-
-#define GRAVITY_SUN (275.0f)
-#define GRAVITY_EARTH (9.80665f)
-
-/** Maximum magnetic field on Earth's surface */
-#define MAGNETIC_FIELD_EARTH_MAX (60.0f)
-
-/** Minimum magnetic field on Earth's surface */
-#define MAGNETIC_FIELD_EARTH_MIN (30.0f)
-
-
-/**
- * status of each sensor
- */
-
-#define SENSOR_STATUS_UNRELIABLE 0
-#define SENSOR_STATUS_ACCURACY_LOW 1
-#define SENSOR_STATUS_ACCURACY_MEDIUM 2
-#define SENSOR_STATUS_ACCURACY_HIGH 3
-
-/**
- * Definition of the axis
- * ----------------------
+ * Definition of the axis used by the sensor HAL API
*
* This API is relative to the screen of the device in its default orientation,
* that is, if the device can be used in portrait or landscape, this API
@@ -117,9 +81,60 @@
*
* O: Origin (x=0,y=0,z=0)
*
+ */
+
+
+/*
+ * SENSOR_TYPE_ACCELEROMETER
*
+ * All values are in SI units (m/s^2) and measure the acceleration of the
+ * device minus the force of gravity.
+ *
+ * Acceleration sensors return sensor events for all 3 axes at a constant
+ * rate defined by setDelay().
+ *
+ * x: Acceleration on the x-axis
+ * y: Acceleration on the y-axis
+ * z: Acceleration on the z-axis
+ *
+ * Note that the readings from the accelerometer include the acceleration
+ * due to gravity (which is opposite to the direction of the gravity vector).
+ *
+ * Examples:
+ * The norm of <x, y, z> should be close to 0 when in free fall.
+ *
+ * When the device lies flat on a table and is pushed on its left side
+ * toward the right, the x acceleration value is positive.
+ *
+ * When the device lies flat on a table, the acceleration value is +9.81,
+ * which correspond to the acceleration of the device (0 m/s^2) minus the
+ * force of gravity (-9.81 m/s^2).
+ *
+ * When the device lies flat on a table and is pushed toward the sky, the
+ * acceleration value is greater than +9.81, which correspond to the
+ * acceleration of the device (+A m/s^2) minus the force of
+ * gravity (-9.81 m/s^2).
+ */
+#define SENSOR_TYPE_ACCELEROMETER (1)
+
+/*
+ * SENSOR_TYPE_GEOMAGNETIC_FIELD
+ *
+ * All values are in micro-Tesla (uT) and measure the geomagnetic
+ * field in the X, Y and Z axis.
+ *
+ * Returned values include calibration mechanisms such that the vector is
+ * aligned with the magnetic declination and heading of the earth's
+ * geomagnetic field.
+ *
+ * Magnetic Field sensors return sensor events for all 3 axes at a constant
+ * rate defined by setDelay().
+ */
+#define SENSOR_TYPE_GEOMAGNETIC_FIELD (2)
+#define SENSOR_TYPE_MAGNETIC_FIELD SENSOR_TYPE_GEOMAGNETIC_FIELD
+
+/*
* SENSOR_TYPE_ORIENTATION
- * -----------------------
*
* All values are angles in degrees.
*
@@ -153,46 +168,11 @@
*
* Note: This definition is different from yaw, pitch and roll used in aviation
* where the X axis is along the long side of the plane (tail to nose).
- *
- *
- * SENSOR_TYPE_ACCELEROMETER
- * -------------------------
- *
- * All values are in SI units (m/s^2) and measure the acceleration of the
- * device minus the force of gravity.
- *
- * Acceleration sensors return sensor events for all 3 axes at a constant
- * rate defined by setDelay().
- *
- * x: Acceleration minus Gx on the x-axis
- * y: Acceleration minus Gy on the y-axis
- * z: Acceleration minus Gz on the z-axis
- *
- * Examples:
- * When the device lies flat on a table and is pushed on its left side
- * toward the right, the x acceleration value is positive.
- *
- * When the device lies flat on a table, the acceleration value is +9.81,
- * which correspond to the acceleration of the device (0 m/s^2) minus the
- * force of gravity (-9.81 m/s^2).
- *
- * When the device lies flat on a table and is pushed toward the sky, the
- * acceleration value is greater than +9.81, which correspond to the
- * acceleration of the device (+A m/s^2) minus the force of
- * gravity (-9.81 m/s^2).
- *
- *
- * SENSOR_TYPE_MAGNETIC_FIELD
- * --------------------------
- *
- * All values are in micro-Tesla (uT) and measure the ambient magnetic
- * field in the X, Y and Z axis.
- *
- * Magnetic Field sensors return sensor events for all 3 axes at a constant
- * rate defined by setDelay().
- *
+ */
+#define SENSOR_TYPE_ORIENTATION (3)
+
+/*
* SENSOR_TYPE_GYROSCOPE
- * ---------------------
*
* All values are in radians/second and measure the rate of rotation
* around the X, Y and Z axis. The coordinate system is the same as is
@@ -205,8 +185,34 @@
* with the definition of roll given earlier.
* The range should at least be 17.45 rad/s (ie: ~1000 deg/s).
*
+ * automatic gyro-drift compensation is allowed but not required.
+ */
+#define SENSOR_TYPE_GYROSCOPE (4)
+
+/*
+ * SENSOR_TYPE_LIGHT
+ *
+ * The light sensor value is returned in SI lux units.
+ *
+ * Light sensors report a value only when it changes and each time the
+ * sensor is enabled.
+ */
+#define SENSOR_TYPE_LIGHT (5)
+
+/*
+ * SENSOR_TYPE_PRESSURE
+ *
+ * The pressure sensor return the athmospheric pressure in hectopascal (hPa)
+ *
+ * Pressure sensors report events at a constant rate defined by setDelay().
+ */
+#define SENSOR_TYPE_PRESSURE (6)
+
+/* SENSOR_TYPE_TEMPERATURE is deprecated in the HAL */
+#define SENSOR_TYPE_TEMPERATURE (7)
+
+/*
* SENSOR_TYPE_PROXIMITY
- * ----------------------
*
* The distance value is measured in centimeters. Note that some proximity
* sensors only support a binary "close" or "far" measurement. In this case,
@@ -215,42 +221,38 @@
*
* Proximity sensors report a value only when it changes and each time the
* sensor is enabled.
- *
- * SENSOR_TYPE_LIGHT
- * -----------------
- *
- * The light sensor value is returned in SI lux units.
- *
- * Light sensors report a value only when it changes and each time the
- * sensor is enabled.
- *
- * SENSOR_TYPE_PRESSURE
- * --------------------
- *
- * The pressure sensor return the athmospheric pressure in hectopascal (hPa)
- *
- * Pressure sensors report events at a constant rate defined by setDelay().
- *
+ */
+#define SENSOR_TYPE_PROXIMITY (8)
+
+/*
* SENSOR_TYPE_GRAVITY
- * -------------------
*
* A gravity output indicates the direction of and magnitude of gravity in
* the devices's coordinates. On Earth, the magnitude is 9.8 m/s^2.
* Units are m/s^2. The coordinate system is the same as is used for the
* acceleration sensor. When the device is at rest, the output of the
* gravity sensor should be identical to that of the accelerometer.
- *
+ */
+#define SENSOR_TYPE_GRAVITY (9)
+
+/*
* SENSOR_TYPE_LINEAR_ACCELERATION
- * --------------------------------
*
* Indicates the linear acceleration of the device in device coordinates,
* not including gravity.
- * This output is essentially Acceleration - Gravity. Units are m/s^2.
+ *
+ * The output is conceptually:
+ * output of TYPE_ACCELERATION - output of TYPE_GRAVITY
+ *
+ * Readings on all axes should be close to 0 when device lies on a table.
+ * Units are m/s^2.
* The coordinate system is the same as is used for the acceleration sensor.
- *
- *
+ */
+#define SENSOR_TYPE_LINEAR_ACCELERATION (10)
+
+
+/*
* SENSOR_TYPE_ROTATION_VECTOR
- * ---------------------------
*
* A rotation vector represents the orientation of the device as a combination
* of an angle and an axis, in which the device has rotated through an angle
@@ -281,28 +283,110 @@
* sensors_event_t.data[1] = y*sin(theta/2)
* sensors_event_t.data[2] = z*sin(theta/2)
* sensors_event_t.data[3] = cos(theta/2)
- *
- *
+ */
+#define SENSOR_TYPE_ROTATION_VECTOR (11)
+
+/*
* SENSOR_TYPE_RELATIVE_HUMIDITY
- * ------------------------------
*
* A relative humidity sensor measures relative ambient air humidity and
* returns a value in percent.
*
* Relative humidity sensors report a value only when it changes and each
* time the sensor is enabled.
- *
- *
+ */
+#define SENSOR_TYPE_RELATIVE_HUMIDITY (12)
+
+/*
* SENSOR_TYPE_AMBIENT_TEMPERATURE
- * -------------------------------
*
* The ambient (room) temperature in degree Celsius.
*
* Temperature sensors report a value only when it changes and each time the
* sensor is enabled.
+ */
+#define SENSOR_TYPE_AMBIENT_TEMPERATURE (13)
+
+/*
+ * SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED
*
+ * All values are in micro-Tesla (uT) and measure the ambient magnetic
+ * field in the X, Y and Z axis.
+ *
+ * No periodic calibration is performed (ie: there are no discontinuities
+ * in the data stream while using this sensor). Assumptions that the the
+ * magnetic field is due to the Earth's poles should be avoided.
+ *
+ * Factory calibration and temperature compensation should still be applied.
+ *
+ * Magnetic Field sensors return sensor events for all 3 axes at a constant
+ * rate defined by setDelay().
+ */
+#define SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED (14)
+
+/*
+ * SENSOR_TYPE_GAME_ROTATION_VECTOR
+ *
+ * SENSOR_TYPE_GAME_ROTATION_VECTOR is identical to SENSOR_TYPE_ROTATION_VECTOR,
+ * except that it doesn't use the geomagnetic field. Therefore the Y axis doesn't
+ * point north, but instead to some other reference, that reference is allowed
+ * to drift by the same order of magnitude than the gyroscope drift around
+ * the Z axis.
+ *
+ * In the ideal case, a phone rotated and returning to the same real-world
+ * orientation should report the same game rotation vector
+ * (without using the earth's geomagnetic field).
+ *
+ * see SENSOR_TYPE_ROTATION_VECTOR for more details
+ */
+#define SENSOR_TYPE_GAME_ROTATION_VECTOR (15)
+
+/*
+ * SENSOR_TYPE_GYROSCOPE_UNCALIBRATED
+ *
+ * All values are in radians/second and measure the rate of rotation
+ * around the X, Y and Z axis. The coordinate system is the same as is
+ * used for the acceleration sensor. Rotation is positive in the
+ * counter-clockwise direction (right-hand rule). That is, an observer
+ * looking from some positive location on the x, y or z axis at a device
+ * positioned on the origin would report positive rotation if the device
+ * appeared to be rotating counter clockwise. Note that this is the
+ * standard mathematical definition of positive rotation and does not agree
+ * with the definition of roll given earlier.
+ * The range should at least be 17.45 rad/s (ie: ~1000 deg/s).
+ *
+ * No gyro-drift compensation shall be performed.
+ * Factory calibration and temperature compensation should still be applied.
+ */
+#define SENSOR_TYPE_GYROSCOPE_UNCALIBRATED (16)
+
+/**
+ * Values returned by the accelerometer in various locations in the universe.
+ * all values are in SI units (m/s^2)
+ */
+#define GRAVITY_SUN (275.0f)
+#define GRAVITY_EARTH (9.80665f)
+
+/** Maximum magnetic field on Earth's surface */
+#define MAGNETIC_FIELD_EARTH_MAX (60.0f)
+
+/** Minimum magnetic field on Earth's surface */
+#define MAGNETIC_FIELD_EARTH_MIN (30.0f)
+
+
+/**
+ * status of orientation sensor
*/
+#define SENSOR_STATUS_UNRELIABLE 0
+#define SENSOR_STATUS_ACCURACY_LOW 1
+#define SENSOR_STATUS_ACCURACY_MEDIUM 2
+#define SENSOR_STATUS_ACCURACY_HIGH 3
+
+
+/**
+ * sensor event data
+ */
typedef struct {
union {
float v[3];
diff --git a/modules/Android.mk b/modules/Android.mk
index faa8bb3..486b42d 100644
--- a/modules/Android.mk
+++ b/modules/Android.mk
@@ -1,2 +1,2 @@
-hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time power usbaudio audio_remote_submix
+hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time power usbaudio audio_remote_submix camera
include $(call all-named-subdir-makefiles,$(hardware_modules))
diff --git a/modules/audio_remote_submix/audio_hw.cpp b/modules/audio_remote_submix/audio_hw.cpp
index 3756274..e9759e5 100755
--- a/modules/audio_remote_submix/audio_hw.cpp
+++ b/modules/audio_remote_submix/audio_hw.cpp
@@ -571,8 +571,7 @@
// initialize pipe
{
ALOGV(" initializing pipe");
- const NBAIO_Format format =
- config->sample_rate == 48000 ? Format_SR48_C2_I16 : Format_SR44_1_C2_I16;
+ const NBAIO_Format format = Format_from_SR_C(config->sample_rate, 2);
const NBAIO_Format offers[1] = {format};
size_t numCounterOffers = 0;
// creating a MonoPipe with optional blocking set to true.
diff --git a/modules/camera/Android.mk b/modules/camera/Android.mk
new file mode 100644
index 0000000..aa457f4
--- /dev/null
+++ b/modules/camera/Android.mk
@@ -0,0 +1,37 @@
+# Copyright (C) 2012 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 := camera.default
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+
+LOCAL_C_INCLUDES += \
+ system/media/camera/include \
+
+LOCAL_SRC_FILES := \
+ CameraHAL.cpp \
+ Camera.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libcamera_metadata \
+ liblog \
+
+LOCAL_CFLAGS += -Wall -Wextra
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/modules/camera/Camera.cpp b/modules/camera/Camera.cpp
new file mode 100644
index 0000000..24cfe4f
--- /dev/null
+++ b/modules/camera/Camera.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2012 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 <cstdlib>
+#include <pthread.h>
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "Camera"
+#include <cutils/log.h>
+
+#include "Camera.h"
+
+namespace default_camera_hal {
+
+extern "C" {
+// Shim passed to the framework to close an opened device.
+static int close_device(hw_device_t* dev)
+{
+ camera2_device_t* cam_dev = reinterpret_cast<camera2_device_t*>(dev);
+ Camera* cam = static_cast<Camera*>(cam_dev->priv);
+ return cam->close();
+}
+} // extern "C"
+
+Camera::Camera(int id, const hw_module_t* module)
+ : mId(id),
+ mBusy(false),
+ mMetadata(NULL)
+{
+ pthread_mutex_init(&mMutex,
+ NULL); // No pthread mutex attributes.
+
+ // TODO: fill in device operations function pointers
+ mDevice.common.tag = HARDWARE_DEVICE_TAG;
+ mDevice.common.module = const_cast<hw_module_t*>(module);
+ mDevice.common.close = close_device;
+ mDevice.priv = this;
+}
+
+Camera::~Camera()
+{
+}
+
+int Camera::open()
+{
+ ALOGV("%s: camera id %d", __func__, mId);
+ pthread_mutex_lock(&mMutex);
+ if (mBusy) {
+ pthread_mutex_unlock(&mMutex);
+ ALOGE("%s:id%d: Error, device already in use.", __func__, mId);
+ return -EBUSY;
+ }
+
+ // TODO: open camera dev nodes, etc
+ mBusy = true;
+
+ pthread_mutex_unlock(&mMutex);
+ return 0;
+}
+
+int Camera::close()
+{
+ ALOGV("%s: camera id %d", __func__, mId);
+ pthread_mutex_lock(&mMutex);
+ if (!mBusy) {
+ pthread_mutex_unlock(&mMutex);
+ ALOGE("%s:id%d: Error, close() on not open device.", __func__, mId);
+ return -EINVAL;
+ }
+
+ // TODO: close camera dev nodes, etc
+ mBusy = false;
+
+ pthread_mutex_unlock(&mMutex);
+ return 0;
+}
+
+int Camera::getCameraInfo(struct camera_info* info)
+{
+ ALOGV("%s: camera id %d: info=%p", __func__, mId, info);
+ init();
+ if (mMetadata == NULL) {
+ ALOGE("%s:id%d: unable to initialize metadata.", __func__, mId);
+ return -ENOENT;
+ }
+
+ // TODO: fill remainder of info struct
+ info->static_camera_characteristics = mMetadata;
+
+ return 0;
+}
+
+void Camera::init()
+{
+ pthread_mutex_lock(&mMutex);
+ if (mMetadata != NULL) {
+ pthread_mutex_unlock(&mMutex);
+ return;
+ }
+
+ // TODO: init metadata, dummy value for now
+ mMetadata = allocate_camera_metadata(1,1);
+
+ pthread_mutex_unlock(&mMutex);
+}
+
+} // namespace default_camera_hal
diff --git a/modules/camera/Camera.h b/modules/camera/Camera.h
new file mode 100644
index 0000000..72cbde2
--- /dev/null
+++ b/modules/camera/Camera.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 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_H_
+#define CAMERA_H_
+
+#include <pthread.h>
+#include <hardware/camera2.h>
+
+namespace default_camera_hal {
+// Camera represents a physical camera on a device.
+// This is constructed when the HAL module is loaded, one per physical camera.
+// It is opened by the framework, and must be closed before it can be opened
+// again.
+// Also, the framework can query for camera metadata with getCameraInfo.
+// For the first query, the metadata must first be allocated and initialized,
+// but once done it is used for all future calls.
+// It is protected by @mMutex, and functions that modify the Camera object hold
+// this lock when performing modifications. Currently these functions are:
+// @open, @close, and @init.
+class Camera {
+ public:
+ // id is used to distinguish cameras. 0 <= id < NUM_CAMERAS.
+ // module is a handle to the HAL module, used when the device is opened.
+ Camera(int id, const hw_module_t* module);
+ ~Camera();
+ // Open this camera, preparing it for use. Returns nonzero on failure.
+ int open();
+ // Close this camera. Returns nonzero on failure.
+ int close();
+ // Query for camera metadata, filling info struct. Returns nonzero if
+ // allocation or initialization failed.
+ int getCameraInfo(struct camera_info* info);
+ // Handle to this device passed to framework in response to open().
+ camera2_device_t mDevice;
+ private:
+ // One-time initialization of camera metadata.
+ void init();
+ // Identifier used by framework to distinguish cameras
+ int mId;
+ // True indicates camera is already open.
+ bool mBusy;
+ // Camera characteristics. NULL means it has not been allocated yet.
+ camera_metadata_t* mMetadata;
+ // Lock protecting the Camera object for modifications
+ pthread_mutex_t mMutex;
+};
+} // namespace default_camera_hal
+
+#endif // CAMERA_H_
diff --git a/modules/camera/CameraHAL.cpp b/modules/camera/CameraHAL.cpp
new file mode 100644
index 0000000..22c7aef
--- /dev/null
+++ b/modules/camera/CameraHAL.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2012 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 <cstdlib>
+#include <hardware/camera2.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CameraHAL"
+#include <cutils/log.h>
+
+#include "Camera.h"
+
+/*
+ * This file serves as the entry point to the HAL. It contains the module
+ * structure and functions used by the framework to load and interface to this
+ * HAL, as well as the handles to the individual camera devices.
+ */
+
+namespace default_camera_hal {
+
+enum camera_id_t {
+ CAMERA_A,
+ CAMERA_B,
+ NUM_CAMERAS
+};
+
+// Symbol used by the framework when loading the HAL, defined below.
+extern "C" camera_module_t HAL_MODULE_INFO_SYM;
+
+// Camera devices created when the module is loaded. See Camera.h
+static Camera gCameras[NUM_CAMERAS] = {
+ Camera(CAMERA_A, &HAL_MODULE_INFO_SYM.common),
+ Camera(CAMERA_B, &HAL_MODULE_INFO_SYM.common)
+};
+
+extern "C" {
+
+static int get_number_of_cameras()
+{
+ ALOGV("%s", __func__);
+ return NUM_CAMERAS;
+}
+
+static int get_camera_info(int id, struct camera_info* info)
+{
+ ALOGV("%s: camera id %d: info=%p", __func__, id, info);
+ if (id < 0 || id >= NUM_CAMERAS) {
+ ALOGE("%s: Invalid camera id %d", __func__, id);
+ return -ENODEV;
+ }
+ return gCameras[id].getCameraInfo(info);
+}
+
+static int open_device(const hw_module_t* module,
+ const char* name,
+ hw_device_t** device)
+{
+ ALOGV("%s: module=%p, name=%s, device=%p", __func__, module, name, device);
+ char *nameEnd;
+ int id;
+
+ id = strtol(name, &nameEnd, 10);
+ if (nameEnd != NULL) {
+ ALOGE("%s: Invalid camera id name %s", __func__, name);
+ return -EINVAL;
+ } else if (id < 0 || id >= NUM_CAMERAS) {
+ ALOGE("%s: Invalid camera id %d", __func__, id);
+ return -ENODEV;
+ }
+ *device = &gCameras[id].mDevice.common;
+ return gCameras[id].open();
+}
+
+static hw_module_methods_t gCameraModuleMethods = {
+ open : open_device
+};
+
+camera_module_t HAL_MODULE_INFO_SYM = {
+ common : {
+ tag : HARDWARE_MODULE_TAG,
+ module_api_version : CAMERA_MODULE_API_VERSION_2_0,
+ hal_api_version : HARDWARE_HAL_API_VERSION,
+ id : CAMERA_HARDWARE_MODULE_ID,
+ name : "Reference Camera v2 HAL",
+ author : "The Android Open Source Project",
+ methods : &gCameraModuleMethods,
+ dso : NULL,
+ reserved : {0},
+ },
+ get_number_of_cameras : get_number_of_cameras,
+ get_camera_info : get_camera_info
+};
+
+} // extern "C"
+} // namespace default_camera_hal
diff --git a/tests/camera2/Android.mk b/tests/camera2/Android.mk
index c378e12..6b6a6c4 100644
--- a/tests/camera2/Android.mk
+++ b/tests/camera2/Android.mk
@@ -3,20 +3,29 @@
LOCAL_SRC_FILES:= \
camera2.cpp \
- camera2_utils.cpp
+ camera2_utils.cpp \
+ main.cpp \
+ CameraMetadataTests.cpp \
+ CameraModuleTests.cpp \
+ CameraStreamTests.cpp \
+ CameraFrameTests.cpp \
+ ForkedTests.cpp \
+ TestForkerEventListener.cpp \
LOCAL_SHARED_LIBRARIES := \
libutils \
+ libcutils \
libstlport \
libhardware \
libcamera_metadata \
+ libcameraservice \
libgui \
libsync \
- libui
+ libui \
+ libdl
LOCAL_STATIC_LIBRARIES := \
- libgtest \
- libgtest_main
+ libgtest
LOCAL_C_INCLUDES += \
bionic \
@@ -24,6 +33,10 @@
external/gtest/include \
external/stlport/stlport \
system/media/camera/include \
+ frameworks/av/services/camera/libcameraservice \
+ frameworks/native/include \
+
+LOCAL_CFLAGS += -Wall -Wextra
LOCAL_MODULE:= camera2_test
LOCAL_MODULE_TAGS := tests
diff --git a/tests/camera2/CameraFrameTests.cpp b/tests/camera2/CameraFrameTests.cpp
new file mode 100644
index 0000000..6f88312
--- /dev/null
+++ b/tests/camera2/CameraFrameTests.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012 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 <gtest/gtest.h>
+
+#define LOG_TAG "CameraFrameTest"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "hardware/hardware.h"
+#include "hardware/camera2.h"
+
+#include "Camera2Device.h"
+#include "utils/StrongPointer.h"
+
+#include <gui/CpuConsumer.h>
+#include <gui/SurfaceTextureClient.h>
+
+#include <unistd.h>
+
+#include "CameraStreamFixture.h"
+#include "TestExtensions.h"
+
+#define CAMERA_FRAME_TIMEOUT 1000000000 //nsecs (1 secs)
+#define CAMERA_HEAP_COUNT 2 //HALBUG: 1 means registerBuffers fails
+#define CAMERA_FRAME_DEBUGGING 0
+
+using namespace android;
+using namespace android::camera2;
+
+namespace android {
+namespace camera2 {
+namespace tests {
+
+static CameraStreamParams STREAM_PARAMETERS = {
+ /*mCameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_YCrCb_420_SP,
+ /*mHeapCount*/ CAMERA_HEAP_COUNT
+};
+
+class CameraFrameTest
+ : public ::testing::TestWithParam<int>,
+ public CameraStreamFixture {
+
+public:
+ CameraFrameTest() : CameraStreamFixture(STREAM_PARAMETERS) {
+ TEST_EXTENSION_FORKING_CONSTRUCTOR;
+
+ if (!HasFatalFailure()) {
+ CreateStream();
+ }
+ }
+
+ ~CameraFrameTest() {
+ TEST_EXTENSION_FORKING_DESTRUCTOR;
+
+ if (mDevice.get()) {
+ mDevice->waitUntilDrained();
+ }
+ DeleteStream();
+ }
+
+ virtual void SetUp() {
+ TEST_EXTENSION_FORKING_SET_UP;
+ }
+ virtual void TearDown() {
+ TEST_EXTENSION_FORKING_TEAR_DOWN;
+ }
+
+protected:
+
+};
+
+TEST_P(CameraFrameTest, GetFrame) {
+
+ TEST_EXTENSION_FORKING_INIT;
+
+ /* Submit a PREVIEW type request, then wait until we get the frame back */
+ CameraMetadata previewRequest;
+ ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
+ &previewRequest));
+ {
+ Vector<uint8_t> outputStreamIds;
+ outputStreamIds.push(mStreamId);
+ ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
+ outputStreamIds));
+ if (CAMERA_FRAME_DEBUGGING) {
+ int frameCount = 0;
+ ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_FRAME_COUNT,
+ &frameCount, 1));
+ }
+ }
+
+ if (CAMERA_FRAME_DEBUGGING) {
+ previewRequest.dump(STDOUT_FILENO);
+ }
+
+ for (int i = 0; i < GetParam(); ++i) {
+ ALOGV("Submitting capture request");
+ CameraMetadata tmpRequest = previewRequest;
+ ASSERT_EQ(OK, mDevice->capture(tmpRequest));
+ }
+
+ for (int i = 0; i < GetParam(); ++i) {
+ ASSERT_EQ(OK, mDevice->waitForNextFrame(CAMERA_FRAME_TIMEOUT));
+ CameraMetadata frameMetadata;
+ ASSERT_EQ(OK, mDevice->getNextFrame(&frameMetadata));
+ }
+
+}
+
+//FIXME: dont hardcode stream params, and also test multistream
+INSTANTIATE_TEST_CASE_P(FrameParameterCombinations, CameraFrameTest,
+ testing::Range(1, 10));
+
+
+}
+}
+}
+
diff --git a/tests/camera2/CameraMetadataTests.cpp b/tests/camera2/CameraMetadataTests.cpp
new file mode 100644
index 0000000..18710bc
--- /dev/null
+++ b/tests/camera2/CameraMetadataTests.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "CameraMetadataTestFunctional"
+#include "cutils/log.h"
+#include "cutils/properties.h"
+#include "utils/Errors.h"
+
+#include "gtest/gtest.h"
+#include "system/camera_metadata.h"
+#include "hardware/hardware.h"
+#include "hardware/camera2.h"
+
+#include "Camera2Device.h"
+#include "utils/StrongPointer.h"
+
+#include <gui/CpuConsumer.h>
+#include <gui/SurfaceTextureClient.h>
+
+#include <string>
+
+#include "CameraStreamFixture.h"
+#include "TestExtensions.h"
+
+namespace android {
+namespace camera2 {
+namespace tests {
+
+//FIXME: dont hardcode
+static CameraStreamParams METADATA_STREAM_PARAMETERS = {
+ /*mCameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_YCrCb_420_SP,
+ /*mHeapCount*/ 2
+};
+
+class CameraMetadataTest
+ : public ::testing::Test,
+ public CameraStreamFixture {
+
+public:
+ CameraMetadataTest()
+ : CameraStreamFixture(METADATA_STREAM_PARAMETERS) {
+ TEST_EXTENSION_FORKING_CONSTRUCTOR;
+ }
+
+ ~CameraMetadataTest() {
+ TEST_EXTENSION_FORKING_DESTRUCTOR;
+ }
+
+ int GetTypeFromTag(uint32_t tag) const {
+ return get_camera_metadata_tag_type(tag);
+ }
+
+ int GetTypeFromStaticTag(uint32_t tag) const {
+ const CameraMetadata& staticInfo = mDevice->info();
+ camera_metadata_ro_entry entry = staticInfo.find(tag);
+ return entry.type;
+ }
+
+protected:
+
+};
+
+TEST_F(CameraMetadataTest, types) {
+
+ TEST_EXTENSION_FORKING_INIT;
+
+ //FIXME: set this up in an external file of some sort (xml?)
+ {
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.build.id", value, "");
+ std::string str_value(value);
+
+ if (str_value == "manta")
+ {
+ EXPECT_EQ(TYPE_BYTE,
+ GetTypeFromStaticTag(ANDROID_QUIRKS_TRIGGER_AF_WITH_AUTO));
+ EXPECT_EQ(TYPE_BYTE,
+ GetTypeFromStaticTag(ANDROID_QUIRKS_USE_ZSL_FORMAT));
+ EXPECT_EQ(TYPE_BYTE,
+ GetTypeFromStaticTag(ANDROID_QUIRKS_METERING_CROP_REGION));
+ }
+ }
+
+ /*
+ TODO:
+ go through all static metadata and make sure all fields we expect
+ that are there, ARE there.
+
+ dont worry about the type as its enforced by the metadata api
+ we can probably check the range validity though
+ */
+
+ if (0) {
+ camera_metadata_ro_entry entry;
+ EXPECT_EQ(TYPE_BYTE, entry.type);
+ EXPECT_EQ(TYPE_INT32, entry.type);
+ EXPECT_EQ(TYPE_FLOAT, entry.type);
+ EXPECT_EQ(TYPE_INT64, entry.type);
+ EXPECT_EQ(TYPE_DOUBLE, entry.type);
+ EXPECT_EQ(TYPE_RATIONAL, entry.type);
+ }
+}
+
+}
+}
+}
diff --git a/tests/camera2/CameraModuleFixture.h b/tests/camera2/CameraModuleFixture.h
new file mode 100644
index 0000000..d604ff7
--- /dev/null
+++ b/tests/camera2/CameraModuleFixture.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 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 __ANDROID_HAL_CAMERA2_TESTS_MODULE_FIXTURE__
+#define __ANDROID_HAL_CAMERA2_TESTS_MODULE_FIXTURE__
+
+#include <gtest/gtest.h>
+
+#include "hardware/hardware.h"
+#include "hardware/camera2.h"
+
+#include "Camera2Device.h"
+#include "camera2_utils.h"
+#include "TestExtensions.h"
+
+namespace android {
+namespace camera2 {
+namespace tests {
+
+template <bool InfoQuirk = false>
+struct CameraModuleFixture {
+
+ CameraModuleFixture(int CameraID = -1) {
+ TEST_EXTENSION_FORKING_CONSTRUCTOR;
+
+ mCameraID = CameraID;
+
+ SetUp();
+ }
+
+ ~CameraModuleFixture() {
+ TEST_EXTENSION_FORKING_DESTRUCTOR;
+
+ TearDown();
+ }
+
+private:
+
+ void SetUp() {
+ TEST_EXTENSION_FORKING_SET_UP;
+
+ ASSERT_LE(0, hw_get_module(CAMERA_HARDWARE_MODULE_ID,
+ (const hw_module_t **)&mModule)) << "Could not load camera module";
+ ASSERT_NE((void*)0, mModule);
+
+ mNumberOfCameras = mModule->get_number_of_cameras();
+ ASSERT_LE(0, mNumberOfCameras);
+
+ ASSERT_EQ(
+ CAMERA_MODULE_API_VERSION_2_0, mModule->common.module_api_version)
+ << "Wrong module API version";
+
+ /* For using this fixture in other tests only */
+ SetUpMixin();
+ }
+
+ void TearDown() {
+ TEST_EXTENSION_FORKING_TEAR_DOWN;
+
+ TearDownMixin();
+
+ /* important: device must be destructed before closing module,
+ since it calls back into HAL */
+ mDevice.clear();
+
+ if (!TEST_EXTENSION_FORKING_ENABLED) {
+ ASSERT_EQ(0, HWModuleHelpers::closeModule(&mModule->common))
+ << "Failed to close camera HAL module";
+ }
+ }
+
+ void SetUpMixin() {
+ /* For using this fixture in other tests only */
+ if (mCameraID != -1) {
+ EXPECT_LE(0, mCameraID);
+ EXPECT_LT(mCameraID, mNumberOfCameras);
+
+ /* HALBUG (Exynos5); crashes if trying to initialize
+ before calling get_camera_info */
+ if (InfoQuirk) {
+ struct camera_info info;
+ ASSERT_EQ(OK, mModule->get_camera_info(mCameraID, &info));
+ }
+
+ mDevice = new Camera2Device(mCameraID);
+ ASSERT_EQ(OK, mDevice->initialize(mModule))
+ << "Failed to initialize device " << mCameraID;
+ }
+ }
+
+ void TearDownMixin() {
+
+ }
+
+protected:
+ int mNumberOfCameras;
+ camera_module_t *mModule;
+ sp<Camera2Device> mDevice;
+
+private:
+ int mCameraID;
+};
+
+
+}
+}
+}
+
+#endif
diff --git a/tests/camera2/CameraModuleTests.cpp b/tests/camera2/CameraModuleTests.cpp
new file mode 100644
index 0000000..5e85698
--- /dev/null
+++ b/tests/camera2/CameraModuleTests.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 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 <gtest/gtest.h>
+
+#define LOG_TAG "CameraModuleTest"
+#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "hardware/hardware.h"
+#include "hardware/camera2.h"
+
+#include "Camera2Device.h"
+#include "utils/StrongPointer.h"
+#include "CameraModuleFixture.h"
+
+namespace android {
+namespace camera2 {
+namespace tests {
+
+class CameraModuleTest : public ::testing::Test,
+ public CameraModuleFixture<> {
+};
+
+TEST_F(CameraModuleTest, LoadModule) {
+
+ TEST_EXTENSION_FORKING_INIT;
+
+ for (int i = 0; i < mNumberOfCameras; ++i) {
+ mDevice = new Camera2Device(i);
+ ASSERT_EQ(OK, mDevice->initialize(mModule))
+ << "Failed to initialize device " << i;
+ mDevice.clear();
+ }
+
+}
+
+TEST_F(CameraModuleTest, LoadModuleBadIndices) {
+
+ TEST_EXTENSION_FORKING_INIT;
+
+ int idx[] = { -1, mNumberOfCameras, mNumberOfCameras + 1 };
+
+ for (unsigned i = 0; i < sizeof(idx)/sizeof(idx[0]); ++i) {
+ mDevice = new Camera2Device(idx[i]);
+ status_t deviceInitializeCode = mDevice->initialize(mModule);
+ EXPECT_NE(OK, deviceInitializeCode);
+ EXPECT_EQ(-ENODEV, deviceInitializeCode)
+ << "Incorrect error code when trying to initialize invalid index "
+ << idx[i];
+ mDevice.clear();
+ }
+}
+
+TEST_F(CameraModuleTest, GetCameraInfo) {
+
+ TEST_EXTENSION_FORKING_INIT;
+
+ for (int i = 0; i < mNumberOfCameras; ++i) {
+ struct camera_info info;
+ ASSERT_EQ(OK, mModule->get_camera_info(i, &info));
+ }
+
+}
+
+TEST_F(CameraModuleTest, GetCameraInfoBadIndices) {
+
+ TEST_EXTENSION_FORKING_INIT;
+
+ int idx[] = { -1, mNumberOfCameras, mNumberOfCameras + 1 };
+ for (unsigned i = 0; i < sizeof(idx)/sizeof(idx[0]); ++i) {
+ struct camera_info info;
+ EXPECT_NE(OK, mModule->get_camera_info(idx[i], &info));
+ EXPECT_EQ(-ENODEV, mModule->get_camera_info(idx[i], &info))
+ << "Incorrect error code for get_camera_info idx= "
+ << idx[i];
+ }
+}
+
+/**
+ * TODO: Additional test to add: open two cameras at once.
+ * (is allowed to fail, at least for now, but should not blow up)
+ * - open same device multiple times
+ * - close same device multiple times
+ */
+
+
+
+
+}
+}
+}
+
diff --git a/tests/camera2/CameraStreamFixture.h b/tests/camera2/CameraStreamFixture.h
new file mode 100644
index 0000000..d4ba764
--- /dev/null
+++ b/tests/camera2/CameraStreamFixture.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012 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 __ANDROID_HAL_CAMERA2_TESTS_STREAM_FIXTURE__
+#define __ANDROID_HAL_CAMERA2_TESTS_STREAM_FIXTURE__
+
+#include <gtest/gtest.h>
+#include <iostream>
+
+#include <gui/CpuConsumer.h>
+#include <gui/SurfaceTextureClient.h>
+
+#include "CameraModuleFixture.h"
+#include "TestExtensions.h"
+
+namespace android {
+namespace camera2 {
+namespace tests {
+
+struct CameraStreamParams {
+ int mCameraId;
+ int mFormat;
+ int mHeapCount;
+};
+
+inline void PrintTo(const CameraStreamParams& p, ::std::ostream* os) {
+ *os << "{ ";
+ *os << "CameraID: " << p.mCameraId << ", ";
+ *os << "Format: " << p.mCameraId << ", ";
+ *os << "HeapCount: " << p.mCameraId;
+ *os << " }";
+}
+
+class CameraStreamFixture
+ : public CameraModuleFixture</*InfoQuirk*/true> {
+
+public:
+ CameraStreamFixture(CameraStreamParams p)
+ : CameraModuleFixture(p.mCameraId) {
+ TEST_EXTENSION_FORKING_CONSTRUCTOR;
+
+ mParam = p;
+
+ SetUp();
+ }
+
+ ~CameraStreamFixture() {
+ TEST_EXTENSION_FORKING_DESTRUCTOR;
+
+ TearDown();
+ }
+
+private:
+
+ void SetUp() {
+ TEST_EXTENSION_FORKING_SET_UP;
+
+ CameraStreamParams p = mParam;
+ sp<Camera2Device> device = mDevice;
+
+ /* use an arbitrary w,h */
+ {
+ const int tag = ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES;
+
+ const android::camera2::CameraMetadata& staticInfo = device->info();
+ camera_metadata_ro_entry entry = staticInfo.find(tag);
+ ASSERT_NE(0u, entry.count)
+ << "Missing tag android.scaler.availableProcessedSizes";
+
+ ASSERT_LE(2u, entry.count);
+ /* this seems like it would always be the smallest w,h
+ but we actually make no contract that it's sorted asc */;
+ mWidth = entry.data.i32[0];
+ mHeight = entry.data.i32[1];
+ }
+ }
+ void TearDown() {
+ TEST_EXTENSION_FORKING_TEAR_DOWN;
+ }
+
+protected:
+
+ void CreateStream() {
+ sp<Camera2Device> device = mDevice;
+ CameraStreamParams p = mParam;
+
+ mCpuConsumer = new CpuConsumer(p.mHeapCount);
+ mCpuConsumer->setName(String8("CameraStreamTest::mCpuConsumer"));
+
+ mNativeWindow = new SurfaceTextureClient(
+ mCpuConsumer->getProducerInterface());
+
+ ASSERT_EQ(OK,
+ device->createStream(mNativeWindow,
+ mWidth, mHeight, p.mFormat, /*size (for jpegs)*/0,
+ &mStreamId));
+
+ ASSERT_NE(-1, mStreamId);
+ }
+
+ void DeleteStream() {
+ ASSERT_EQ(OK, mDevice->deleteStream(mStreamId));
+ }
+
+ int mWidth;
+ int mHeight;
+
+ int mStreamId;
+ android::sp<CpuConsumer> mCpuConsumer;
+ android::sp<ANativeWindow> mNativeWindow;
+
+private:
+ CameraStreamParams mParam;
+};
+
+}
+}
+}
+
+#endif
diff --git a/tests/camera2/CameraStreamTests.cpp b/tests/camera2/CameraStreamTests.cpp
new file mode 100644
index 0000000..26b2551
--- /dev/null
+++ b/tests/camera2/CameraStreamTests.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2012 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 <gtest/gtest.h>
+
+#define LOG_TAG "CameraStreamTest"
+#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "hardware/hardware.h"
+#include "hardware/camera2.h"
+
+#include "Camera2Device.h"
+#include "utils/StrongPointer.h"
+
+#include <gui/CpuConsumer.h>
+#include <gui/SurfaceTextureClient.h>
+
+#include "CameraStreamFixture.h"
+#include "TestExtensions.h"
+
+using namespace android;
+using namespace android::camera2;
+
+namespace android {
+namespace camera2 {
+namespace tests {
+
+class CameraStreamTest
+ : public ::testing::TestWithParam<CameraStreamParams>,
+ public CameraStreamFixture {
+
+public:
+ CameraStreamTest() : CameraStreamFixture(GetParam()) {
+ TEST_EXTENSION_FORKING_CONSTRUCTOR;
+ }
+
+ ~CameraStreamTest() {
+ TEST_EXTENSION_FORKING_DESTRUCTOR;
+ }
+
+ virtual void SetUp() {
+ TEST_EXTENSION_FORKING_SET_UP;
+ }
+ virtual void TearDown() {
+ TEST_EXTENSION_FORKING_TEAR_DOWN;
+ }
+
+protected:
+
+};
+
+TEST_P(CameraStreamTest, CreateStream) {
+
+ TEST_EXTENSION_FORKING_INIT;
+
+ ASSERT_NO_FATAL_FAILURE(CreateStream());
+ ASSERT_NO_FATAL_FAILURE(DeleteStream());
+}
+
+//TODO: use a combinatoric generator
+static CameraStreamParams TestParameters[] = {
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ /*mHeapCount*/ 1
+ },
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ /*mHeapCount*/ 2
+ },
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ /*mHeapCount*/ 3
+ },
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_YCrCb_420_SP, // NV21
+ /*mHeapCount*/ 1
+ },
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_YCrCb_420_SP,
+ /*mHeapCount*/ 2
+ },
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_YCrCb_420_SP,
+ /*mHeapCount*/ 3
+ },
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_YV12,
+ /*mHeapCount*/ 1
+ },
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_YV12,
+ /*mHeapCount*/ 2
+ },
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_YV12,
+ /*mHeapCount*/ 3
+ },
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_RAW_SENSOR,
+ /*mHeapCount*/ 1
+ },
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_RAW_SENSOR,
+ /*mHeapCount*/ 2
+ },
+ {
+ /*cameraId*/ 0,
+ /*mFormat*/ HAL_PIXEL_FORMAT_RAW_SENSOR,
+ /*mHeapCount*/ 3
+ },
+};
+
+INSTANTIATE_TEST_CASE_P(StreamParameterCombinations, CameraStreamTest,
+ testing::ValuesIn(TestParameters));
+
+
+}
+}
+}
+
diff --git a/tests/camera2/ForkedTests.cpp b/tests/camera2/ForkedTests.cpp
new file mode 100644
index 0000000..315233e
--- /dev/null
+++ b/tests/camera2/ForkedTests.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 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 <gtest/gtest.h>
+
+#include "TestExtensions.h"
+
+namespace android {
+namespace camera2 {
+namespace tests {
+
+// Intentionally disabled since 2 of these tests are supposed to fail
+class DISABLED_ForkedTest : public ::testing::Test {
+
+ virtual void SetUp() {
+ TEST_EXTENSION_FORKING_SET_UP;
+ }
+
+ virtual void TearDown() {
+ TEST_EXTENSION_FORKING_TEAR_DOWN;
+ }
+};
+
+// intentionally fail
+TEST_F(DISABLED_ForkedTest, FailCrash) {
+ TEST_EXTENSION_FORKING_INIT;
+
+ //intentionally crash
+ *(int*)0 = 0xDEADBEEF;
+}
+
+TEST_F(DISABLED_ForkedTest, SucceedNormal) {
+ TEST_EXTENSION_FORKING_INIT;
+
+ EXPECT_TRUE(true);
+}
+
+// intentionally fail
+TEST_F(DISABLED_ForkedTest, FailNormal) {
+ TEST_EXTENSION_FORKING_INIT;
+
+ EXPECT_TRUE(false);
+}
+
+}
+}
+}
+
diff --git a/tests/camera2/TestExtensions.h b/tests/camera2/TestExtensions.h
new file mode 100644
index 0000000..68a5e97
--- /dev/null
+++ b/tests/camera2/TestExtensions.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 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 __ANDROID_HAL_CAMERA2_TESTS_EXTENSIONS__
+#define __ANDROID_HAL_CAMERA2_TESTS_EXTENSIONS__
+
+#include "TestForkerEventListener.h"
+
+// Use at the beginning of each Test::SetUp() impl
+#define TEST_EXTENSION_FORKING_SET_UP \
+ do { \
+ if (TEST_EXTENSION_FORKING_ENABLED) { \
+ if (!TestForkerEventListener::mIsForked) { \
+ return; \
+ } \
+ } \
+ } while (false) \
+
+// Use at the beginning of each Test::TearDown() impl
+#define TEST_EXTENSION_FORKING_TEAR_DOWN TEST_EXTENSION_FORKING_SET_UP
+
+// Use at the beginning of each Test::Test constructor
+#define TEST_EXTENSION_FORKING_CONSTRUCTOR TEST_EXTENSION_FORKING_SET_UP
+
+// Use at the beginning of each Test::~Test destructor
+#define TEST_EXTENSION_FORKING_DESTRUCTOR TEST_EXTENSION_FORKING_TEAR_DOWN
+
+// Use at the beginning of each test body, e.g. TEST(x,y), TEST_F(x,y), etc
+#define TEST_EXTENSION_FORKING_INIT \
+ do { \
+ TEST_EXTENSION_FORKING_SET_UP; \
+ if (HasFatalFailure()) return; \
+ } while(false) \
+
+// Are we running each test by forking it?
+#define TEST_EXTENSION_FORKING_ENABLED (TestForkerEventListener::mUsingForking)
+
+
+
+#endif
+
diff --git a/tests/camera2/TestForkerEventListener.cpp b/tests/camera2/TestForkerEventListener.cpp
new file mode 100644
index 0000000..c9f1942
--- /dev/null
+++ b/tests/camera2/TestForkerEventListener.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+
+#include <gtest/gtest.h>
+
+#include "TestForkerEventListener.h"
+#include "TestExtensions.h"
+
+#define DEBUG_TEST_FORKER_EVENT_LISTENER 0
+
+#define RETURN_CODE_PASSED 0
+#define RETURN_CODE_FAILED 1
+
+namespace android {
+namespace camera2 {
+namespace tests {
+
+bool TestForkerEventListener::mUsingForking = true;
+bool TestForkerEventListener::mIsForked = false;
+
+TestForkerEventListener::TestForkerEventListener() {
+ mIsForked = false;
+ mHasSucceeded = true;
+ mTermSignal = 0;
+}
+
+void TestForkerEventListener::SetForking(bool enabled) {
+ mUsingForking = enabled;
+}
+
+// Called before a test starts.
+void TestForkerEventListener::OnTestStart(const ::testing::TestInfo&) {
+
+ if (!TEST_EXTENSION_FORKING_ENABLED) {
+ return;
+ }
+
+ pid_t childPid = fork();
+ if (childPid != 0) {
+ int status;
+ waitpid(childPid, &status, /*options*/0);
+
+ // terminated normally?
+ mHasSucceeded = WIFEXITED(status);
+ // terminate with return code 0 = test passed, 1 = test failed
+ if (mHasSucceeded) {
+ mHasSucceeded = WEXITSTATUS(status) == RETURN_CODE_PASSED;
+ } else if (WIFSIGNALED(status)) {
+ mTermSignal = WTERMSIG(status);
+ }
+
+ /* the test is then skipped by inserting the various
+ TEST_EXTENSION_ macros in TestExtensions.h */
+
+ } else {
+ mIsForked = true;
+ }
+}
+
+// Called after a failed assertion or a SUCCEED() invocation.
+void TestForkerEventListener::OnTestPartResult(
+ const ::testing::TestPartResult& test_part_result) {
+
+ if (DEBUG_TEST_FORKER_EVENT_LISTENER) {
+ printf("%s in %s:%d\n%s\n",
+ test_part_result.failed() ? "*** Failure" : "Success",
+ test_part_result.file_name(),
+ test_part_result.line_number(),
+ test_part_result.summary());
+ }
+}
+
+// Called after a test ends.
+void TestForkerEventListener::OnTestEnd(const ::testing::TestInfo& test_info) {
+
+ if (!TEST_EXTENSION_FORKING_ENABLED) {
+ return;
+ }
+
+ if (mIsForked) {
+ exit(test_info.result()->Passed()
+ ? RETURN_CODE_PASSED : RETURN_CODE_FAILED);
+ } else if (!mHasSucceeded && mTermSignal != 0) {
+
+ printf("*** Test %s.%s crashed with signal = %s\n",
+ test_info.test_case_name(), test_info.name(),
+ strsignal(mTermSignal));
+ }
+
+ //TODO: overload the default event listener to suppress this message
+ // dynamically (e.g. by skipping OnTestPartResult after OnTestEnd )
+
+ // trigger a test failure if the child has failed
+ if (!mHasSucceeded) {
+ ADD_FAILURE();
+ }
+ mTermSignal = 0;
+}
+
+
+}
+}
+}
+
diff --git a/tests/camera2/TestForkerEventListener.h b/tests/camera2/TestForkerEventListener.h
new file mode 100644
index 0000000..2383f17
--- /dev/null
+++ b/tests/camera2/TestForkerEventListener.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 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 __ANDROID_HAL_CAMERA2_TESTS_FORKER_EVENT_LISTENER__
+#define __ANDROID_HAL_CAMERA2_TESTS_FORKER_EVENT_LISTENER__
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace camera2 {
+namespace tests {
+
+// Fork before each test runs.
+class TestForkerEventListener : public ::testing::EmptyTestEventListener {
+
+public:
+
+ TestForkerEventListener();
+
+ // Should we fork before running each test?
+ static void SetForking(bool enabled);
+
+private:
+
+ // Called before a test starts.
+ virtual void OnTestStart(const ::testing::TestInfo& test_info);
+
+ // Called after a failed assertion or a SUCCEED() invocation.
+ virtual void OnTestPartResult(
+ const ::testing::TestPartResult& test_part_result);
+
+ // Called after a test ends.
+ virtual void OnTestEnd(const ::testing::TestInfo& test_info);
+
+ bool mHasSucceeded;
+ int mTermSignal;
+
+public:
+ // do not read directly. use TEST_EXTENSION macros instead
+ static bool mUsingForking;
+ static bool mIsForked;
+};
+
+}
+}
+}
+
+#endif
diff --git a/tests/camera2/camera2.cpp b/tests/camera2/camera2.cpp
index f43513e..a15c5e6 100644
--- a/tests/camera2/camera2.cpp
+++ b/tests/camera2/camera2.cpp
@@ -15,7 +15,7 @@
*/
#define LOG_TAG "Camera2_test"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <gtest/gtest.h>
@@ -28,12 +28,15 @@
#include <system/camera_metadata.h>
#include "camera2_utils.h"
+#include "TestExtensions.h"
namespace android {
+namespace camera2 {
+namespace tests {
class Camera2Test: public testing::Test {
public:
- static void SetUpTestCase() {
+ void SetUpModule() {
int res;
hw_module_t *module = NULL;
@@ -103,6 +106,11 @@
}
}
+ void TearDownModule() {
+ hw_module_t *module = reinterpret_cast<hw_module_t*>(sCameraModule);
+ ASSERT_EQ(0, HWModuleHelpers::closeModule(module));
+ }
+
static const camera_module_t *getCameraModule() {
return sCameraModule;
}
@@ -276,20 +284,30 @@
}
virtual void SetUp() {
+ TEST_EXTENSION_FORKING_SET_UP;
+
+ SetUpModule();
+
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
+ (void)testInfo;
- ALOGV("*** Starting test %s in test case %s", testInfo->name(), testInfo->test_case_name());
+ ALOGV("*** Starting test %s in test case %s", testInfo->name(),
+ testInfo->test_case_name());
mDevice = NULL;
}
virtual void TearDown() {
+ TEST_EXTENSION_FORKING_TEAR_DOWN;
+
for (unsigned int i = 0; i < mStreams.size(); i++) {
delete mStreams[i];
}
if (mDevice != NULL) {
closeCameraDevice(mDevice);
}
+
+ TearDownModule();
}
camera2_device *mDevice;
@@ -317,6 +335,9 @@
TEST_F(Camera2Test, OpenClose) {
+
+ TEST_EXTENSION_FORKING_INIT;
+
status_t res;
for (int id = 0; id < getNumCameras(); id++) {
@@ -331,6 +352,9 @@
}
TEST_F(Camera2Test, Capture1Raw) {
+
+ TEST_EXTENSION_FORKING_INIT;
+
status_t res;
for (int id = 0; id < getNumCameras(); id++) {
@@ -363,7 +387,7 @@
camera_metadata_t *request;
request = allocate_camera_metadata(20, 2000);
- uint8_t metadataMode = ANDROID_REQUEST_METADATA_FULL;
+ uint8_t metadataMode = ANDROID_REQUEST_METADATA_MODE_FULL;
add_camera_metadata_entry(request,
ANDROID_REQUEST_METADATA_MODE,
(void**)&metadataMode, 1);
@@ -445,6 +469,9 @@
}
TEST_F(Camera2Test, CaptureBurstRaw) {
+
+ TEST_EXTENSION_FORKING_INIT;
+
status_t res;
for (int id = 0; id < getNumCameras(); id++) {
@@ -477,7 +504,7 @@
camera_metadata_t *request;
request = allocate_camera_metadata(20, 2000);
- uint8_t metadataMode = ANDROID_REQUEST_METADATA_FULL;
+ uint8_t metadataMode = ANDROID_REQUEST_METADATA_MODE_FULL;
add_camera_metadata_entry(request,
ANDROID_REQUEST_METADATA_MODE,
(void**)&metadataMode, 1);
@@ -577,6 +604,9 @@
}
TEST_F(Camera2Test, ConstructDefaultRequests) {
+
+ TEST_EXTENSION_FORKING_INIT;
+
status_t res;
for (int id = 0; id < getNumCameras(); id++) {
@@ -639,7 +669,7 @@
camera_metadata_t *request;
request = allocate_camera_metadata(20, 2000);
- uint8_t metadataMode = ANDROID_REQUEST_METADATA_FULL;
+ uint8_t metadataMode = ANDROID_REQUEST_METADATA_MODE_FULL;
add_camera_metadata_entry(request,
ANDROID_REQUEST_METADATA_MODE,
(void**)&metadataMode, 1);
@@ -720,5 +750,6 @@
}
}
-
+} // namespace tests
+} // namespace camera2
} // namespace android
diff --git a/tests/camera2/camera2_utils.cpp b/tests/camera2/camera2_utils.cpp
index cefe29a..166ac52 100644
--- a/tests/camera2/camera2_utils.cpp
+++ b/tests/camera2/camera2_utils.cpp
@@ -21,8 +21,11 @@
#include "utils/Log.h"
#include "camera2_utils.h"
+#include <dlfcn.h>
namespace android {
+namespace camera2 {
+namespace tests {
/**
* MetadataQueue
@@ -578,4 +581,22 @@
mCondition.signal();
}
+int HWModuleHelpers::closeModule(hw_module_t* module) {
+ int status;
+
+ if (!module) {
+ return -EINVAL;
+ }
+
+ status = dlclose(module->dso);
+ if (status != 0) {
+ char const *err_str = dlerror();
+ ALOGE("%s dlclose failed, error: %s", __func__, err_str ?: "unknown");
+ }
+
+ return status;
+}
+
+} // namespace tests
+} // namespace camera2
} // namespace android
diff --git a/tests/camera2/camera2_utils.h b/tests/camera2/camera2_utils.h
index 7822f5b..757044b 100644
--- a/tests/camera2/camera2_utils.h
+++ b/tests/camera2/camera2_utils.h
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#ifndef __ANDROID_HAL_CAMERA2_TESTS_UTILS__
+#define __ANDROID_HAL_CAMERA2_TESTS_UTILS__
+
// Utility classes for camera2 HAL testing
#include <system/camera_metadata.h>
@@ -27,6 +30,8 @@
#include <utils/Condition.h>
namespace android {
+namespace camera2 {
+namespace tests {
/**
* Queue class for both sending requests to a camera2 device, and for receiving
@@ -233,4 +238,13 @@
Condition mCondition;
};
+struct HWModuleHelpers {
+ /* attempt to unload the library with dlclose */
+ static int closeModule(hw_module_t* module);
+};
+
}
+}
+}
+
+#endif
diff --git a/tests/camera2/main.cpp b/tests/camera2/main.cpp
new file mode 100644
index 0000000..92c117a
--- /dev/null
+++ b/tests/camera2/main.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 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 <stdlib.h>
+
+#include <gtest/gtest.h>
+#include "TestForkerEventListener.h"
+
+using android::camera2::tests::TestForkerEventListener;
+
+int main(int argc, char **argv) {
+
+ ::testing::InitGoogleTest(&argc, argv);
+
+ {
+ //TODO: have a command line flag as well
+ char *env = getenv("CAMERA2_TEST_FORKING_DISABLED");
+ if (env) {
+ int forking = atoi(env);
+
+ TestForkerEventListener::SetForking(!forking);
+ }
+ }
+
+ // Gets hold of the event listener list.
+ ::testing::TestEventListeners& listeners =
+ ::testing::UnitTest::GetInstance()->listeners();
+ // Adds a listener to the end. Google Test takes the ownership.
+ listeners.Append(new TestForkerEventListener());
+
+ int ret = RUN_ALL_TESTS();
+
+ return ret;
+}