Merge "Camera2: Fix metadata symbols"
diff --git a/include/hardware/hwcomposer.h b/include/hardware/hwcomposer.h
index 0722e32..c30ef33 100644
--- a/include/hardware/hwcomposer.h
+++ b/include/hardware/hwcomposer.h
@@ -80,21 +80,25 @@
 
 typedef struct hwc_layer_1 {
     /*
-     * Initially set to HWC_FRAMEBUFFER, HWC_BACKGROUND, or
-     * HWC_FRAMEBUFFER_TARGET.
+     * compositionType is used to specify this layer's type and is set by either
+     * the hardware composer implementation, or by the caller (see below).
      *
-     * HWC_FRAMEBUFFER
-     *   Indicates the layer will be drawn into the framebuffer
-     *   using OpenGL ES. The HWC can toggle this value to HWC_OVERLAY to
-     *   indicate it will handle the layer.
+     *  This field is always reset to HWC_BACKGROUND or HWC_FRAMEBUFFER
+     *  before (*prepare)() is called when the HWC_GEOMETRY_CHANGED flag is
+     *  also set, otherwise, this field is preserved between (*prepare)()
+     *  calls.
      *
      * HWC_BACKGROUND
-     *   Indicates this is a special "background" layer. The only valid field
-     *   is backgroundColor. The HWC can toggle this value to HWC_FRAMEBUFFER
-     *   to indicate it CANNOT handle the background color.
+     *   Always set by the caller before calling (*prepare)(), this value
+     *   indicates this is a special "background" layer. The only valid field
+     *   is backgroundColor.
+     *   The HWC can toggle this value to HWC_FRAMEBUFFER to indicate it CANNOT
+     *   handle the background color.
+     *
      *
      * HWC_FRAMEBUFFER_TARGET
-     *   Indicates this layer is the framebuffer surface used as the target of
+     *   Always set by the caller before calling (*prepare)(), this value
+     *   indicates this layer is the framebuffer surface used as the target of
      *   OpenGL ES composition. If the HWC sets all other layers to HWC_OVERLAY
      *   or HWC_BACKGROUND, then no OpenGL ES composition will be done, and
      *   this layer should be ignored during set().
@@ -103,13 +107,38 @@
      *   HWC version is HWC_DEVICE_API_VERSION_1_1 or higher. In older versions,
      *   the OpenGL ES target surface is communicated by the (dpy, sur) fields
      *   in hwc_compositor_device_1_t.
+     *
+     *   This value cannot be set by the HWC implementation.
+     *
+     *
+     * HWC_FRAMEBUFFER
+     *   Set by the caller before calling (*prepare)() ONLY when the
+     *   HWC_GEOMETRY_CHANGED flag is also set.
+     *
+     *   Set by the HWC implementation during (*prepare)(), this indicates
+     *   that the layer will be drawn into the framebuffer using OpenGL ES.
+     *   The HWC can toggle this value to HWC_OVERLAY to indicate it will
+     *   handle the layer.
+     *
+     *
+     * HWC_OVERLAY
+     *   Set by the HWC implementation during (*prepare)(), this indicates
+     *   that the layer will be handled by the HWC (ie: it must not be
+     *   composited with OpenGL ES).
+     *
      */
     int32_t compositionType;
 
-    /* see hwc_layer_t::hints above */
+    /*
+     * hints is bit mask set by the HWC implementation during (*prepare)().
+     * It is preserved between (*prepare)() calls, unless the
+     * HWC_GEOMETRY_CHANGED flag is set, in which case it is reset to 0.
+     *
+     * see hwc_layer_t::hints
+     */
     uint32_t hints;
 
-    /* see hwc_layer_t::flags above */
+    /* see hwc_layer_t::flags */
     uint32_t flags;
 
     union {
@@ -356,11 +385,14 @@
      * either HWC_FRAMEBUFFER or HWC_OVERLAY. In the former case, the
      * composition for the layer is handled by SurfaceFlinger with OpenGL ES,
      * in the later case, the HWC will have to handle the layer's composition.
+     * compositionType and hints are preserved between (*prepare)() calles
+     * unless the HWC_GEOMETRY_CHANGED flag is set.
      *
      * (*prepare)() is called with HWC_GEOMETRY_CHANGED to indicate that the
      * list's geometry has changed, that is, when more than just the buffer's
      * handles have been updated. Typically this happens (but is not limited to)
-     * when a window is added, removed, resized or moved.
+     * when a window is added, removed, resized or moved. In this case
+     * compositionType and hints are reset to their default value.
      *
      * For HWC 1.0, numDisplays will always be one, and displays[0] will be
      * non-NULL.
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/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 e9a8ebc..6b6a6c4 100644
--- a/tests/camera2/Android.mk
+++ b/tests/camera2/Android.mk
@@ -9,6 +9,8 @@
 	CameraModuleTests.cpp \
 	CameraStreamTests.cpp \
 	CameraFrameTests.cpp \
+	ForkedTests.cpp \
+	TestForkerEventListener.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
 	libutils \
@@ -34,6 +36,8 @@
 	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
index 9e3482c..6f88312 100644
--- a/tests/camera2/CameraFrameTests.cpp
+++ b/tests/camera2/CameraFrameTests.cpp
@@ -32,6 +32,7 @@
 #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
@@ -56,12 +57,16 @@
 
 public:
     CameraFrameTest() : CameraStreamFixture(STREAM_PARAMETERS) {
+        TEST_EXTENSION_FORKING_CONSTRUCTOR;
+
         if (!HasFatalFailure()) {
             CreateStream();
         }
     }
 
     ~CameraFrameTest() {
+        TEST_EXTENSION_FORKING_DESTRUCTOR;
+
         if (mDevice.get()) {
             mDevice->waitUntilDrained();
         }
@@ -69,8 +74,10 @@
     }
 
     virtual void SetUp() {
+        TEST_EXTENSION_FORKING_SET_UP;
     }
     virtual void TearDown() {
+        TEST_EXTENSION_FORKING_TEAR_DOWN;
     }
 
 protected:
@@ -79,9 +86,7 @@
 
 TEST_P(CameraFrameTest, GetFrame) {
 
-    if (HasFatalFailure()) {
-        return;
-    }
+    TEST_EXTENSION_FORKING_INIT;
 
     /* Submit a PREVIEW type request, then wait until we get the frame back */
     CameraMetadata previewRequest;
diff --git a/tests/camera2/CameraMetadataTests.cpp b/tests/camera2/CameraMetadataTests.cpp
index 739eba6..18710bc 100644
--- a/tests/camera2/CameraMetadataTests.cpp
+++ b/tests/camera2/CameraMetadataTests.cpp
@@ -32,7 +32,9 @@
 #include <gui/SurfaceTextureClient.h>
 
 #include <string>
+
 #include "CameraStreamFixture.h"
+#include "TestExtensions.h"
 
 namespace android {
 namespace camera2 {
@@ -45,16 +47,18 @@
     /*mHeapCount*/  2
 };
 
-class DISABLED_CameraMetadataTest
+class CameraMetadataTest
     : public ::testing::Test,
       public CameraStreamFixture {
 
 public:
-    DISABLED_CameraMetadataTest()
+    CameraMetadataTest()
     : CameraStreamFixture(METADATA_STREAM_PARAMETERS) {
+        TEST_EXTENSION_FORKING_CONSTRUCTOR;
     }
 
-    ~DISABLED_CameraMetadataTest() {
+    ~CameraMetadataTest() {
+        TEST_EXTENSION_FORKING_DESTRUCTOR;
     }
 
     int GetTypeFromTag(uint32_t tag) const {
@@ -67,22 +71,13 @@
         return entry.type;
     }
 
-    static void SetUpTestCase() {
-    }
-
-    static void TearDownTestCase()
-    {
-    }
-
 protected:
 
 };
 
-TEST_F(DISABLED_CameraMetadataTest, types) {
+TEST_F(CameraMetadataTest, types) {
 
-    if (HasFatalFailure()) {
-        return;
-    }
+    TEST_EXTENSION_FORKING_INIT;
 
     //FIXME: set this up in an external file of some sort (xml?)
     {
diff --git a/tests/camera2/CameraModuleFixture.h b/tests/camera2/CameraModuleFixture.h
index f000fdf..d604ff7 100644
--- a/tests/camera2/CameraModuleFixture.h
+++ b/tests/camera2/CameraModuleFixture.h
@@ -14,6 +14,9 @@
  * 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"
@@ -21,6 +24,7 @@
 
 #include "Camera2Device.h"
 #include "camera2_utils.h"
+#include "TestExtensions.h"
 
 namespace android {
 namespace camera2 {
@@ -30,18 +34,24 @@
 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);
@@ -58,14 +68,18 @@
     }
 
     void TearDown() {
+        TEST_EXTENSION_FORKING_TEAR_DOWN;
+
         TearDownMixin();
 
         /* important: device must be destructed before closing module,
            since it calls back into HAL */
         mDevice.clear();
 
-        ASSERT_EQ(0, HWModuleHelpers::closeModule(&mModule->common))
-            << "Failed to close camera HAL module";
+        if (!TEST_EXTENSION_FORKING_ENABLED) {
+            ASSERT_EQ(0, HWModuleHelpers::closeModule(&mModule->common))
+                << "Failed to close camera HAL module";
+        }
     }
 
     void SetUpMixin() {
@@ -105,3 +119,4 @@
 }
 }
 
+#endif
diff --git a/tests/camera2/CameraModuleTests.cpp b/tests/camera2/CameraModuleTests.cpp
index 2bfdb88..5e85698 100644
--- a/tests/camera2/CameraModuleTests.cpp
+++ b/tests/camera2/CameraModuleTests.cpp
@@ -16,7 +16,7 @@
 
 #include <gtest/gtest.h>
 
-#define LOG_TAG "DISABLED_CameraModuleTest"
+#define LOG_TAG "CameraModuleTest"
 #define LOG_NDEBUG 0
 #include <utils/Log.h>
 
@@ -31,23 +31,13 @@
 namespace camera2 {
 namespace tests {
 
-class DISABLED_CameraModuleTest : public ::testing::Test,
+class CameraModuleTest : public ::testing::Test,
                                   public CameraModuleFixture<> {
-
-    virtual void SetUp() {
-        //CameraModuleFixture::SetUp();
-    }
-
-    virtual void TearDown() {
-        //CameraModuleFixture::TearDown();
-    }
 };
 
-TEST_F(DISABLED_CameraModuleTest, LoadModule) {
+TEST_F(CameraModuleTest, LoadModule) {
 
-    if (HasFatalFailure()) {
-        return;
-    }
+    TEST_EXTENSION_FORKING_INIT;
 
     for (int i = 0; i < mNumberOfCameras; ++i) {
         mDevice = new Camera2Device(i);
@@ -58,11 +48,9 @@
 
 }
 
-TEST_F(DISABLED_CameraModuleTest, LoadModuleBadIndices) {
+TEST_F(CameraModuleTest, LoadModuleBadIndices) {
 
-    if (HasFatalFailure()) {
-        return;
-    }
+    TEST_EXTENSION_FORKING_INIT;
 
     int idx[] = { -1, mNumberOfCameras, mNumberOfCameras + 1 };
 
@@ -77,11 +65,9 @@
     }
 }
 
-TEST_F(DISABLED_CameraModuleTest, GetCameraInfo) {
+TEST_F(CameraModuleTest, GetCameraInfo) {
 
-    if (HasFatalFailure()) {
-        return;
-    }
+    TEST_EXTENSION_FORKING_INIT;
 
     for (int i = 0; i < mNumberOfCameras; ++i) {
         struct camera_info info;
@@ -90,11 +76,9 @@
 
 }
 
-TEST_F(DISABLED_CameraModuleTest, GetCameraInfoBadIndices) {
+TEST_F(CameraModuleTest, GetCameraInfoBadIndices) {
 
-    if (HasFatalFailure()) {
-        return;
-    }
+    TEST_EXTENSION_FORKING_INIT;
 
     int idx[] = { -1, mNumberOfCameras, mNumberOfCameras + 1 };
     for (unsigned i = 0; i < sizeof(idx)/sizeof(idx[0]); ++i) {
@@ -109,6 +93,8 @@
 /**
  * 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
index 4bd8ac1..d4ba764 100644
--- a/tests/camera2/CameraStreamFixture.h
+++ b/tests/camera2/CameraStreamFixture.h
@@ -14,12 +14,17 @@
  * 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 {
@@ -31,24 +36,38 @@
     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;
 
@@ -69,6 +88,7 @@
         }
     }
     void TearDown() {
+        TEST_EXTENSION_FORKING_TEAR_DOWN;
     }
 
 protected:
@@ -95,13 +115,6 @@
         ASSERT_EQ(OK, mDevice->deleteStream(mStreamId));
     }
 
-    /* consider factoring out this common code into
-      a CameraStreamFixture<T>, e.g.
-      class CameraStreamTest : TestWithParam<CameraStreamParameters>,
-                               CameraStreamFixture<CameraStreamParameters>
-       to make it easier for other classes to not duplicate the params
-      */
-
     int mWidth;
     int mHeight;
 
@@ -117,3 +130,4 @@
 }
 }
 
+#endif
diff --git a/tests/camera2/CameraStreamTests.cpp b/tests/camera2/CameraStreamTests.cpp
index e06e4e9..26b2551 100644
--- a/tests/camera2/CameraStreamTests.cpp
+++ b/tests/camera2/CameraStreamTests.cpp
@@ -16,7 +16,7 @@
 
 #include <gtest/gtest.h>
 
-#define LOG_TAG "DISABLED_CameraStreamTest"
+#define LOG_TAG "CameraStreamTest"
 #define LOG_NDEBUG 0
 #include <utils/Log.h>
 
@@ -30,7 +30,7 @@
 #include <gui/SurfaceTextureClient.h>
 
 #include "CameraStreamFixture.h"
-
+#include "TestExtensions.h"
 
 using namespace android;
 using namespace android::camera2;
@@ -39,39 +39,36 @@
 namespace camera2 {
 namespace tests {
 
-class DISABLED_CameraStreamTest
+class CameraStreamTest
     : public ::testing::TestWithParam<CameraStreamParams>,
       public CameraStreamFixture {
 
 public:
-    DISABLED_CameraStreamTest() : CameraStreamFixture(GetParam()) {
+    CameraStreamTest() : CameraStreamFixture(GetParam()) {
+        TEST_EXTENSION_FORKING_CONSTRUCTOR;
     }
 
-    ~DISABLED_CameraStreamTest() {
+    ~CameraStreamTest() {
+        TEST_EXTENSION_FORKING_DESTRUCTOR;
     }
 
     virtual void SetUp() {
+        TEST_EXTENSION_FORKING_SET_UP;
     }
     virtual void TearDown() {
+        TEST_EXTENSION_FORKING_TEAR_DOWN;
     }
 
 protected:
 
 };
 
-TEST_P(DISABLED_CameraStreamTest, CreateStream) {
+TEST_P(CameraStreamTest, CreateStream) {
 
-    if (HasFatalFailure()) {
-        return;
-    }
+    TEST_EXTENSION_FORKING_INIT;
 
-    CreateStream();
-
-    if (HasFatalFailure()) {
-        return;
-    }
-
-    DeleteStream();
+    ASSERT_NO_FATAL_FAILURE(CreateStream());
+    ASSERT_NO_FATAL_FAILURE(DeleteStream());
 }
 
 //TODO: use a combinatoric generator
@@ -138,7 +135,7 @@
     },
 };
 
-INSTANTIATE_TEST_CASE_P(StreamParameterCombinations, DISABLED_CameraStreamTest,
+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 373d015..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,6 +28,7 @@
 #include <system/camera_metadata.h>
 
 #include "camera2_utils.h"
+#include "TestExtensions.h"
 
 namespace android {
 namespace camera2 {
@@ -35,7 +36,7 @@
 
 class Camera2Test: public testing::Test {
   public:
-    static void SetUpTestCase() {
+    void SetUpModule() {
         int res;
 
         hw_module_t *module = NULL;
@@ -105,7 +106,7 @@
         }
     }
 
-    static void TearDownTestCase() {
+    void TearDownModule() {
         hw_module_t *module = reinterpret_cast<hw_module_t*>(sCameraModule);
         ASSERT_EQ(0, HWModuleHelpers::closeModule(module));
     }
@@ -283,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;
@@ -324,6 +335,9 @@
 
 
 TEST_F(Camera2Test, OpenClose) {
+
+    TEST_EXTENSION_FORKING_INIT;
+
     status_t res;
 
     for (int id = 0; id < getNumCameras(); id++) {
@@ -338,6 +352,9 @@
 }
 
 TEST_F(Camera2Test, Capture1Raw) {
+
+    TEST_EXTENSION_FORKING_INIT;
+
     status_t res;
 
     for (int id = 0; id < getNumCameras(); id++) {
@@ -452,6 +469,9 @@
 }
 
 TEST_F(Camera2Test, CaptureBurstRaw) {
+
+    TEST_EXTENSION_FORKING_INIT;
+
     status_t res;
 
     for (int id = 0; id < getNumCameras(); id++) {
@@ -584,6 +604,9 @@
 }
 
 TEST_F(Camera2Test, ConstructDefaultRequests) {
+
+    TEST_EXTENSION_FORKING_INIT;
+
     status_t res;
 
     for (int id = 0; id < getNumCameras(); id++) {
@@ -613,7 +636,7 @@
     }
 }
 
-TEST_F(Camera2Test, DISABLED_Capture1Jpeg) {
+TEST_F(Camera2Test, Capture1Jpeg) {
     status_t res;
 
     for (int id = 0; id < getNumCameras(); id++) {
diff --git a/tests/camera2/camera2_utils.h b/tests/camera2/camera2_utils.h
index c938ee7..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>
@@ -243,3 +246,5 @@
 }
 }
 }
+
+#endif
diff --git a/tests/camera2/main.cpp b/tests/camera2/main.cpp
index 40b9872..92c117a 100644
--- a/tests/camera2/main.cpp
+++ b/tests/camera2/main.cpp
@@ -14,12 +14,33 @@
  * 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;