Merge commit 'c9940a2bfe94dbe2ef3bfe5e8692bf4e3cea5ba0' into HEAD
diff --git a/hardware.c b/hardware.c
index 1f831cb..9651f4c 100644
--- a/hardware.c
+++ b/hardware.c
@@ -154,6 +154,10 @@
             if (access(path, R_OK) == 0) break;
         } else {
             snprintf(path, sizeof(path), "%s/%s.default.so",
+                     HAL_LIBRARY_PATH2, name);
+            if (access(path, R_OK) == 0) break;
+
+            snprintf(path, sizeof(path), "%s/%s.default.so",
                      HAL_LIBRARY_PATH1, name);
             if (access(path, R_OK) == 0) break;
         }
diff --git a/include/hardware/audio.h b/include/hardware/audio.h
index 3a0962e..6ba2544 100644
--- a/include/hardware/audio.h
+++ b/include/hardware/audio.h
@@ -67,6 +67,7 @@
 #define AUDIO_HARDWARE_MODULE_ID_A2DP "a2dp"
 #define AUDIO_HARDWARE_MODULE_ID_USB "usb"
 #define AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX "r_submix"
+#define AUDIO_HARDWARE_MODULE_ID_CODEC_OFFLOAD "codec_offload"
 
 /**************************************/
 
@@ -117,16 +118,35 @@
  * "sup_sampling_rates=44100|48000" */
 #define AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES "sup_sampling_rates"
 
+/**
+ * audio codec parameters
+ */
+
+#define AUDIO_OFFLOAD_CODEC_PARAMS "music_offload_codec_param"
+#define AUDIO_OFFLOAD_CODEC_BIT_PER_SAMPLE "music_offload_bit_per_sample"
+#define AUDIO_OFFLOAD_CODEC_BIT_RATE "music_offload_bit_rate"
+#define AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE "music_offload_avg_bit_rate"
+#define AUDIO_OFFLOAD_CODEC_ID "music_offload_codec_id"
+#define AUDIO_OFFLOAD_CODEC_BLOCK_ALIGN "music_offload_block_align"
+#define AUDIO_OFFLOAD_CODEC_SAMPLE_RATE "music_offload_sample_rate"
+#define AUDIO_OFFLOAD_CODEC_ENCODE_OPTION "music_offload_encode_option"
+#define AUDIO_OFFLOAD_CODEC_NUM_CHANNEL  "music_offload_num_channels"
+#define AUDIO_OFFLOAD_CODEC_DOWN_SAMPLING  "music_offload_down_sampling"
+#define AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES  "delay_samples"
+#define AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES  "padding_samples"
 
 /**************************************/
 
-/* common audio stream configuration parameters */
+/* common audio stream configuration parameters
+ * You should memset() the entire structure to zero before use to
+ * ensure forward compatibility
+ */
 struct audio_config {
     uint32_t sample_rate;
     audio_channel_mask_t channel_mask;
     audio_format_t  format;
+    audio_offload_info_t offload_info;
 };
-
 typedef struct audio_config audio_config_t;
 
 /* common audio stream parameters and operations */
@@ -213,6 +233,22 @@
 };
 typedef struct audio_stream audio_stream_t;
 
+/* type of asynchronous write callback events. Mutually exclusive */
+typedef enum {
+    STREAM_CBK_EVENT_WRITE_READY, /* non blocking write completed */
+    STREAM_CBK_EVENT_DRAIN_READY  /* drain completed */
+} stream_callback_event_t;
+
+typedef int (*stream_callback_t)(stream_callback_event_t event, void *param, void *cookie);
+
+/* type of drain requested to audio_stream_out->drain(). Mutually exclusive */
+typedef enum {
+    AUDIO_DRAIN_ALL,            /* drain() returns when all data has been played */
+    AUDIO_DRAIN_EARLY_NOTIFY    /* drain() returns a short time before all data
+                                   from the current track has been played to
+                                   give time for gapless track switch */
+} audio_drain_type_t;
+
 /**
  * audio_stream_out is the abstraction interface for the audio output hardware.
  *
@@ -242,6 +278,13 @@
      * negative status_t. If at least one frame was written successfully prior to the error,
      * it is suggested that the driver return that successful (short) byte count
      * and then return an error in the subsequent call.
+     *
+     * If set_callback() has previously been called to enable non-blocking mode
+     * the write() is not allowed to block. It must write only the number of
+     * bytes that currently fit in the driver/hardware buffer and then return
+     * this byte count. If this is less than the requested write size the
+     * callback function must be called when more space is available in the
+     * driver/hardware buffer.
      */
     ssize_t (*write)(struct audio_stream_out *stream, const void* buffer,
                      size_t bytes);
@@ -259,6 +302,80 @@
     int (*get_next_write_timestamp)(const struct audio_stream_out *stream,
                                     int64_t *timestamp);
 
+    /**
+     * set the callback function for notifying completion of non-blocking
+     * write and drain.
+     * Calling this function implies that all future write() and drain()
+     * must be non-blocking and use the callback to signal completion.
+     */
+    int (*set_callback)(struct audio_stream_out *stream,
+            stream_callback_t callback, void *cookie);
+
+    /**
+     * Notifies to the audio driver to stop playback however the queued buffers are
+     * retained by the hardware. Useful for implementing pause/resume. Empty implementation
+     * if not supported however should be implemented for hardware with non-trivial
+     * latency. In the pause state audio hardware could still be using power. User may
+     * consider calling suspend after a timeout.
+     *
+     * Implementation of this function is mandatory for offloaded playback.
+     */
+    int (*pause)(struct audio_stream_out* stream);
+
+    /**
+     * Notifies to the audio driver to resume playback following a pause.
+     * Returns error if called without matching pause.
+     *
+     * Implementation of this function is mandatory for offloaded playback.
+     */
+    int (*resume)(struct audio_stream_out* stream);
+
+    /**
+     * Requests notification when data buffered by the driver/hardware has
+     * been played. If set_callback() has previously been called to enable
+     * non-blocking mode, the drain() must not block, instead it should return
+     * quickly and completion of the drain is notified through the callback.
+     * If set_callback() has not been called, the drain() must block until
+     * completion.
+     * If type==AUDIO_DRAIN_ALL, the drain completes when all previously written
+     * data has been played.
+     * If type==AUDIO_DRAIN_EARLY_NOTIFY, the drain completes shortly before all
+     * data for the current track has played to allow time for the framework
+     * to perform a gapless track switch.
+     *
+     * Drain must return immediately on stop() and flush() call
+     *
+     * Implementation of this function is mandatory for offloaded playback.
+     */
+    int (*drain)(struct audio_stream_out* stream, audio_drain_type_t type );
+
+    /**
+     * Notifies to the audio driver to flush the queued data. Stream must already
+     * be paused before calling flush().
+     *
+     * Implementation of this function is mandatory for offloaded playback.
+     */
+   int (*flush)(struct audio_stream_out* stream);
+
+    /**
+     * Return a recent count of the number of audio frames presented to an external observer.
+     * This excludes frames which have been written but are still in the pipeline.
+     * The count is not reset to zero when output enters standby.
+     * Also returns the value of CLOCK_MONOTONIC as of this presentation count.
+     * The returned count is expected to be 'recent',
+     * but does not need to be the most recent possible value.
+     * However, the associated time should correspond to whatever count is returned.
+     * Example:  assume that N+M frames have been presented, where M is a 'small' number.
+     * Then it is permissible to return N instead of N+M,
+     * and the timestamp should correspond to N rather than N+M.
+     * The terms 'recent' and 'small' are not defined.
+     * They reflect the quality of the implementation.
+     *
+     * 3.0 and higher only.
+     */
+    int (*get_presentation_position)(const struct audio_stream_out *stream,
+                               uint64_t *frames, struct timespec *timestamp);
+
 };
 typedef struct audio_stream_out audio_stream_out_t;
 
@@ -296,18 +413,14 @@
 static inline size_t audio_stream_frame_size(const struct audio_stream *s)
 {
     size_t chan_samp_sz;
+    audio_format_t format = s->get_format(s);
 
-    switch (s->get_format(s)) {
-    case AUDIO_FORMAT_PCM_16_BIT:
-        chan_samp_sz = sizeof(int16_t);
-        break;
-    case AUDIO_FORMAT_PCM_8_BIT:
-    default:
-        chan_samp_sz = sizeof(int8_t);
-        break;
+    if (audio_is_linear_pcm(format)) {
+        chan_samp_sz = audio_bytes_per_sample(format);
+        return popcount(s->get_channels(s)) * chan_samp_sz;
     }
 
-    return popcount(s->get_channels(s)) * chan_samp_sz;
+    return sizeof(int8_t);
 }
 
 
diff --git a/include/hardware/audio_effect.h b/include/hardware/audio_effect.h
index 2940b1a..b49d02d 100644
--- a/include/hardware/audio_effect.h
+++ b/include/hardware/audio_effect.h
@@ -147,6 +147,9 @@
 //  |                           |           | 1 requires audio source updates
 //  |                           |           | 2..3 reserved
 //  +---------------------------+-----------+-----------------------------------
+//  | Effect offload supported  | 22        | 0 The effect cannot be offloaded to an audio DSP
+//  |                           |           | 1 The effect can be offloaded to an audio DSP
+//  +---------------------------+-----------+-----------------------------------
 
 // Insert mode
 #define EFFECT_FLAG_TYPE_SHIFT          0
@@ -229,6 +232,14 @@
 #define EFFECT_FLAG_AUDIO_SOURCE_IND    (1 << EFFECT_FLAG_AUDIO_SOURCE_SHIFT)
 #define EFFECT_FLAG_AUDIO_SOURCE_NONE   (0 << EFFECT_FLAG_AUDIO_SOURCE_SHIFT)
 
+// Effect offload indication
+#define EFFECT_FLAG_OFFLOAD_SHIFT       (EFFECT_FLAG_AUDIO_SOURCE_SHIFT + \
+                                                    EFFECT_FLAG_AUDIO_SOURCE_SIZE)
+#define EFFECT_FLAG_OFFLOAD_SIZE        1
+#define EFFECT_FLAG_OFFLOAD_MASK        (((1 << EFFECT_FLAG_OFFLOAD_SIZE) -1) \
+                                          << EFFECT_FLAG_OFFLOAD_SHIFT)
+#define EFFECT_FLAG_OFFLOAD_SUPPORTED   (1 << EFFECT_FLAG_OFFLOAD_SHIFT)
+
 #define EFFECT_MAKE_API_VERSION(M, m)  (((M)<<16) | ((m) & 0xFFFF))
 #define EFFECT_API_VERSION_MAJOR(v)    ((v)>>16)
 #define EFFECT_API_VERSION_MINOR(v)    ((m) & 0xFFFF)
@@ -426,6 +437,8 @@
    EFFECT_CMD_GET_FEATURE_CONFIG,   // get current feature configuration
    EFFECT_CMD_SET_FEATURE_CONFIG,   // set current feature configuration
    EFFECT_CMD_SET_AUDIO_SOURCE,     // set the audio source (see audio.h, audio_source_t)
+   EFFECT_CMD_OFFLOAD,              // set if effect thread is an offload one,
+                                    // send the ioHandle of the effect thread
    EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code
 };
 
@@ -732,6 +745,20 @@
 //  size: 0
 //  data: N/A
 //==================================================================================================
+// command: EFFECT_CMD_OFFLOAD
+//--------------------------------------------------------------------------------------------------
+// description:
+//  1.indicate if the playback thread the effect is attached to is offloaded or not
+//  2.update the io handle of the playback thread the effect is attached to
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(effect_offload_param_t)
+//  data: effect_offload_param_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(uint32_t)
+//  data: uint32_t
+//--------------------------------------------------------------------------------------------------
 // command: EFFECT_CMD_FIRST_PROPRIETARY
 //--------------------------------------------------------------------------------------------------
 // description:
@@ -868,6 +895,11 @@
     char        data[];     // Start of Parameter + Value data
 } effect_param_t;
 
+// structure used by EFFECT_CMD_OFFLOAD command
+typedef struct effect_offload_param_s {
+    bool isOffload;         // true if the playback thread the effect is attached to is offloaded
+    int ioHandle;           // io handle of the playback thread the effect is attached to
+} effect_offload_param_t;
 
 
 /////////////////////////////////////////////////
diff --git a/include/hardware/audio_policy.h b/include/hardware/audio_policy.h
index c635ebf..4e75e02 100644
--- a/include/hardware/audio_policy.h
+++ b/include/hardware/audio_policy.h
@@ -133,7 +133,8 @@
                                     uint32_t samplingRate,
                                     audio_format_t format,
                                     audio_channel_mask_t channelMask,
-                                    audio_output_flags_t flags);
+                                    audio_output_flags_t flags,
+                                    const audio_offload_info_t *offloadInfo);
 
     /* indicates to the audio policy manager that the output starts being used
      * by corresponding stream. */
@@ -241,6 +242,10 @@
 
     /* dump state */
     int (*dump)(const struct audio_policy *pol, int fd);
+
+    /* check if offload is possible for given sample rate, bitrate, duration, ... */
+    bool (*is_offload_supported)(const struct audio_policy *pol,
+                                const audio_offload_info_t *info);
 };
 
 /* audio hw module handle used by load_hw_module(), open_output_on_module()
@@ -390,7 +395,8 @@
                                      audio_format_t *pFormat,
                                      audio_channel_mask_t *pChannelMask,
                                      uint32_t *pLatencyMs,
-                                     audio_output_flags_t flags);
+                                     audio_output_flags_t flags,
+                                     const audio_offload_info_t *offloadInfo);
 
     /* Opens an audio input on a particular HW module.
      *
diff --git a/include/hardware/bluetooth.h b/include/hardware/bluetooth.h
old mode 100755
new mode 100644
index 2741332..c00a8f7
--- a/include/hardware/bluetooth.h
+++ b/include/hardware/bluetooth.h
@@ -451,6 +451,8 @@
     /* opcode MUST be one of: LE_Receiver_Test, LE_Transmitter_Test, LE_Test_End */
     int (*le_test_mode)(uint16_t opcode, uint8_t *buf, uint8_t len);
 
+    /* enable or disable bluetooth HCI snoop log */
+    int (*config_hci_snoop_log)(uint8_t enable);
 } bt_interface_t;
 
 /** TODO: Need to add APIs for Service Discovery, Service authorization and
diff --git a/include/hardware/bt_gatt_client.h b/include/hardware/bt_gatt_client.h
index 8b49f59..d6b0cb4 100644
--- a/include/hardware/bt_gatt_client.h
+++ b/include/hardware/bt_gatt_client.h
@@ -40,8 +40,8 @@
 typedef struct
 {
     btgatt_srvc_id_t    srvc_id;
-    btgatt_char_id_t    char_id;
-    bt_uuid_t           descr_id;
+    btgatt_gatt_id_t    char_id;
+    btgatt_gatt_id_t    descr_id;
     btgatt_unformatted_value_t value;
     uint16_t            value_type;
     uint8_t             status;
@@ -51,8 +51,8 @@
 typedef struct
 {
     btgatt_srvc_id_t    srvc_id;
-    btgatt_char_id_t    char_id;
-    bt_uuid_t           descr_id;
+    btgatt_gatt_id_t    char_id;
+    btgatt_gatt_id_t    descr_id;
     uint8_t             status;
 } btgatt_write_params_t;
 
@@ -62,7 +62,7 @@
     uint8_t             value[BTGATT_MAX_ATTR_LEN];
     bt_bdaddr_t         bda;
     btgatt_srvc_id_t    srvc_id;
-    btgatt_char_id_t    char_id;
+    btgatt_gatt_id_t    char_id;
     uint16_t            len;
     uint8_t             is_notify;
 } btgatt_notify_params_t;
@@ -105,13 +105,13 @@
 
 /** GATT characteristic enumeration result callback */
 typedef void (*get_characteristic_callback)(int conn_id, int status,
-                btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id,
+                btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
                 int char_prop);
 
 /** GATT descriptor enumeration result callback */
 typedef void (*get_descriptor_callback)(int conn_id, int status,
-                btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id,
-                bt_uuid_t *descr_id);
+                btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+                btgatt_gatt_id_t *descr_id);
 
 /** GATT included service enumeration result callback */
 typedef void (*get_included_service_callback)(int conn_id, int status,
@@ -120,7 +120,7 @@
 /** Callback invoked in response to [de]register_for_notification */
 typedef void (*register_for_notification_callback)(int conn_id,
                 int registered, int status, btgatt_srvc_id_t *srvc_id,
-                btgatt_char_id_t *char_id);
+                btgatt_gatt_id_t *char_id);
 
 /**
  * Remote device notification callback, invoked when a remote device sends
@@ -151,6 +151,11 @@
 typedef void (*read_remote_rssi_callback)(int client_if, bt_bdaddr_t* bda,
                                           int rssi, int status);
 
+/**
+ * Callback indicationg the status of a listen() operation
+ */
+typedef void (*listen_callback)(int status, int server_if);
+
 typedef struct {
     register_client_callback            register_client_cb;
     scan_result_callback                scan_result_cb;
@@ -169,6 +174,7 @@
     write_descriptor_callback           write_descriptor_cb;
     execute_write_callback              execute_write_cb;
     read_remote_rssi_callback           read_remote_rssi_cb;
+    listen_callback                     listen_cb;
 } btgatt_client_callbacks_t;
 
 /** Represents the standard BT-GATT client interface. */
@@ -191,6 +197,9 @@
     bt_status_t (*disconnect)( int client_if, const bt_bdaddr_t *bd_addr,
                     int conn_id);
 
+    /** Start or stop advertisements to listen for incoming connections */
+    bt_status_t (*listen)(int client_if, bool start);
+
     /** Clear the attribute cache for a given device */
     bt_status_t (*refresh)( int client_if, const bt_bdaddr_t *bd_addr );
 
@@ -212,36 +221,36 @@
      * Set start_char_id to NULL to get the first characteristic.
      */
     bt_status_t (*get_characteristic)( int conn_id,
-                    btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *start_char_id);
+                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id);
 
     /**
      * Enumerate descriptors for a given characteristic.
      * Set start_descr_id to NULL to get the first descriptor.
      */
     bt_status_t (*get_descriptor)( int conn_id,
-                    btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id,
-                    bt_uuid_t *start_descr_id);
+                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+                    btgatt_gatt_id_t *start_descr_id);
 
     /** Read a characteristic on a remote device */
     bt_status_t (*read_characteristic)( int conn_id,
-                    btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id,
+                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
                     int auth_req );
 
     /** Write a remote characteristic */
     bt_status_t (*write_characteristic)(int conn_id,
-                    btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id,
+                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
                     int write_type, int len, int auth_req,
                     char* p_value);
 
     /** Read the descriptor for a given characteristic */
     bt_status_t (*read_descriptor)(int conn_id,
-                    btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id,
-                    bt_uuid_t *descr_id, int auth_req);
+                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+                    btgatt_gatt_id_t *descr_id, int auth_req);
 
     /** Write a remote descriptor for a given characteristic */
     bt_status_t (*write_descriptor)( int conn_id,
-                    btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id,
-                    bt_uuid_t *descr_id, int write_type, int len,
+                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+                    btgatt_gatt_id_t *descr_id, int write_type, int len,
                     int auth_req, char* p_value);
 
     /** Execute a prepared write operation */
@@ -253,12 +262,12 @@
      */
     bt_status_t (*register_for_notification)( int client_if,
                     const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
-                    btgatt_char_id_t *char_id);
+                    btgatt_gatt_id_t *char_id);
 
     /** Deregister a previous request for notifications/indications */
     bt_status_t (*deregister_for_notification)( int client_if,
                     const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
-                    btgatt_char_id_t *char_id);
+                    btgatt_gatt_id_t *char_id);
 
     /** Request RSSI for a given remote device */
     bt_status_t (*read_remote_rssi)( int client_if, const bt_bdaddr_t *bd_addr);
@@ -266,6 +275,11 @@
     /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
     int (*get_device_type)( const bt_bdaddr_t *bd_addr );
 
+    /** Set the advertising data or scan response data */
+    bt_status_t (*set_adv_data)(int server_if, bool set_scan_rsp, bool include_name,
+                    bool include_txpower, int min_interval, int max_interval, int appearance,
+                    uint16_t manufacturer_len, char* manufacturer_data);
+
     /** Test mode interface */
     bt_status_t (*test_command)( int command, btgatt_test_params_t* params);
 } btgatt_client_interface_t;
diff --git a/include/hardware/bt_gatt_types.h b/include/hardware/bt_gatt_types.h
index fee9bb5..0ac217e 100644
--- a/include/hardware/bt_gatt_types.h
+++ b/include/hardware/bt_gatt_types.h
@@ -29,17 +29,17 @@
 #define BTGATT_SERVICE_TYPE_PRIMARY 0
 #define BTGATT_SERVICE_TYPE_SECONDARY 1
 
-/** GATT Characteristic ID adding instance id tracking to the UUID */
+/** GATT ID adding instance id tracking to the UUID */
 typedef struct
 {
     bt_uuid_t           uuid;
     uint8_t             inst_id;
-} btgatt_char_id_t;
+} btgatt_gatt_id_t;
 
 /** GATT Service ID also identifies the service type (primary/secondary) */
 typedef struct
 {
-    btgatt_char_id_t    id;
+    btgatt_gatt_id_t    id;
     uint8_t             is_primary;
 } btgatt_srvc_id_t;
 
diff --git a/include/hardware/bt_rc.h b/include/hardware/bt_rc.h
old mode 100755
new mode 100644
index 952652e..d455543
--- a/include/hardware/bt_rc.h
+++ b/include/hardware/bt_rc.h
@@ -30,6 +30,13 @@
 typedef uint8_t btrc_uid_t[BTRC_UID_SIZE];
 
 typedef enum {
+    BTRC_FEAT_NONE = 0x00,    /* AVRCP 1.0 */
+    BTRC_FEAT_METADATA = 0x01,    /* AVRCP 1.3 */
+    BTRC_FEAT_ABSOLUTE_VOLUME = 0x02,    /* Supports TG role and volume sync */
+    BTRC_FEAT_BROWSE = 0x04,    /* AVRCP 1.4 and up, with Browsing support */
+} btrc_remote_features_t;
+
+typedef enum {
     BTRC_PLAYSTATE_STOPPED = 0x00,    /* Stopped */
     BTRC_PLAYSTATE_PLAYING = 0x01,    /* Playing */
     BTRC_PLAYSTATE_PAUSED = 0x02,    /* Paused  */
@@ -114,6 +121,10 @@
     uint8_t text[BTRC_MAX_ATTR_STR_LEN];
 } btrc_element_attr_val_t;
 
+/** Callback for the controller's supported feautres */
+typedef void (* btrc_remote_features_callback)(bt_bdaddr_t *bd_addr,
+                                                      btrc_remote_features_t features);
+
 /** Callback for play status request */
 typedef void (* btrc_get_play_status_callback)();
 
@@ -151,10 +162,20 @@
 */
 typedef void (* btrc_register_notification_callback) (btrc_event_id_t event_id, uint32_t param);
 
+/* AVRCP 1.4 Enhancements */
+/** Callback for volume change on CT
+**  volume: Current volume setting on the CT (0-127)
+*/
+typedef void (* btrc_volume_change_callback) (uint8_t volume, uint8_t ctype);
+
+/** Callback for passthrough commands */
+typedef void (* btrc_passthrough_cmd_callback) (int id, int key_state);
+
 /** BT-RC callback structure. */
 typedef struct {
     /** set to sizeof(BtRcCallbacks) */
     size_t      size;
+    btrc_remote_features_callback               remote_features_cb;
     btrc_get_play_status_callback               get_play_status_cb;
     btrc_list_player_app_attr_callback          list_player_app_attr_cb;
     btrc_list_player_app_values_callback        list_player_app_values_cb;
@@ -164,6 +185,8 @@
     btrc_set_player_app_value_callback          set_player_app_value_cb;
     btrc_get_element_attr_callback              get_element_attr_cb;
     btrc_register_notification_callback         register_notification_cb;
+    btrc_volume_change_callback                 volume_change_cb;
+    btrc_passthrough_cmd_callback               passthrough_cmd_cb;
 } btrc_callbacks_t;
 
 /** Represents the standard BT-RC interface. */
@@ -225,6 +248,15 @@
                                              btrc_notification_type_t type,
                                              btrc_register_notification_t *p_param);
 
+    /* AVRCP 1.4 enhancements */
+
+    /**Send current volume setting to remote side. Support limited to SetAbsoluteVolume
+    ** This can be enhanced to support Relative Volume (AVRCP 1.0).
+    ** With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN opposed to absolute volume level
+    ** volume: Should be in the range 0-127. bit7 is reseved and cannot be set
+    */
+    bt_status_t (*set_volume)(uint8_t volume);
+
     /** Closes the interface. */
     void  (*cleanup)( void );
 } btrc_interface_t;
diff --git a/include/hardware/camera3.h b/include/hardware/camera3.h
index 3a900fc..afc9d9f 100644
--- a/include/hardware/camera3.h
+++ b/include/hardware/camera3.h
@@ -21,17 +21,17 @@
 #include "camera_common.h"
 
 /**
- * Camera device HAL 3.0 [ CAMERA_DEVICE_API_VERSION_3_0 ]
+ * Camera device HAL 3.1 [ CAMERA_DEVICE_API_VERSION_3_1 ]
  *
  * EXPERIMENTAL.
  *
  * Supports the android.hardware.Camera API.
  *
  * Camera devices that support this version of the HAL must return
- * CAMERA_DEVICE_API_VERSION_3_0 in camera_device_t.common.version and in
+ * CAMERA_DEVICE_API_VERSION_3_1 in camera_device_t.common.version and in
  * camera_info_t.device_version (from camera_module_t.get_camera_info).
  *
- * Camera modules that may contain version 3.0 devices must implement at least
+ * Camera modules that may contain version 3.1 devices must implement at least
  * version 2.0 of the camera module interface (as defined by
  * camera_module_t.common.module_api_version).
  *
@@ -82,6 +82,12 @@
  *     management. Bidirectional streams replace STREAM_FROM_STREAM construct.
  *
  *   - Limited mode semantics for older/limited hardware devices.
+ *
+ * 3.1: Minor revision of expanded-capability HAL:
+ *
+ *   - configure_streams passes consumer usage flags to the HAL.
+ *
+ *   - flush call to drop all in-flight requests/buffers as fast as possible.
  */
 
 /**
@@ -392,6 +398,10 @@
  *        well focused. The lens is not moving. The HAL may spontaneously leave
  *        this state.
  *
+ *     AF_STATE_PASSIVE_UNFOCUSED: A continuous focus algorithm believes it is
+ *        not well focused. The lens is not moving. The HAL may spontaneously
+ *        leave this state.
+ *
  *     AF_STATE_ACTIVE_SCAN: A scan triggered by the user is underway.
  *
  *     AF_STATE_FOCUSED_LOCKED: The AF algorithm believes it is focused. The
@@ -565,10 +575,16 @@
  *
  * S4.5. AF state machines
  *
+ *                       when enabling AF or changing AF mode
+ *| state              | trans. cause  | new state          | notes            |
+ *+--------------------+---------------+--------------------+------------------+
+ *| Any                | AF mode change| INACTIVE           |                  |
+ *+--------------------+---------------+--------------------+------------------+
+ *
  *                            mode = AF_MODE_OFF or AF_MODE_EDOF
  *| state              | trans. cause  | new state          | notes            |
  *+--------------------+---------------+--------------------+------------------+
- *| INACTIVE           |               |                    | AF is disabled   |
+ *| INACTIVE           |               | INACTIVE           | Never changes    |
  *+--------------------+---------------+--------------------+------------------+
  *
  *                            mode = AF_MODE_AUTO or AF_MODE_MACRO
@@ -611,6 +627,9 @@
  *| PASSIVE_SCAN       | HAL completes | PASSIVE_FOCUSED    | End AF scan      |
  *|                    | current scan  |                    | Lens now locked  |
  *+--------------------+---------------+--------------------+------------------+
+ *| PASSIVE_SCAN       | HAL fails     | PASSIVE_UNFOCUSED  | End AF scan      |
+ *|                    | current scan  |                    | Lens now locked  |
+ *+--------------------+---------------+--------------------+------------------+
  *| PASSIVE_SCAN       | AF_TRIGGER    | FOCUSED_LOCKED     | Immediate trans. |
  *|                    |               |                    | if focus is good |
  *|                    |               |                    | Lens now locked  |
@@ -626,12 +645,13 @@
  *| PASSIVE_FOCUSED    | HAL initiates | PASSIVE_SCAN       | Start AF scan    |
  *|                    | new scan      |                    | Lens now moving  |
  *+--------------------+---------------+--------------------+------------------+
+ *| PASSIVE_UNFOCUSED  | HAL initiates | PASSIVE_SCAN       | Start AF scan    |
+ *|                    | new scan      |                    | Lens now moving  |
+ *+--------------------+---------------+--------------------+------------------+
  *| PASSIVE_FOCUSED    | AF_TRIGGER    | FOCUSED_LOCKED     | Immediate trans. |
- *|                    |               |                    | if focus is good |
  *|                    |               |                    | Lens now locked  |
  *+--------------------+---------------+--------------------+------------------+
- *| PASSIVE_FOCUSED    | AF_TRIGGER    | NOT_FOCUSED_LOCKED | Immediate trans. |
- *|                    |               |                    | if focus is bad  |
+ *| PASSIVE_UNFOCUSED  | AF_TRIGGER    | NOT_FOCUSED_LOCKED | Immediate trans. |
  *|                    |               |                    | Lens now locked  |
  *+--------------------+---------------+--------------------+------------------+
  *| FOCUSED_LOCKED     | AF_TRIGGER    | FOCUSED_LOCKED     | No effect        |
@@ -655,6 +675,9 @@
  *| PASSIVE_SCAN       | HAL completes | PASSIVE_FOCUSED    | End AF scan      |
  *|                    | current scan  |                    | Lens now locked  |
  *+--------------------+---------------+--------------------+------------------+
+ *| PASSIVE_SCAN       | HAL fails     | PASSIVE_UNFOCUSED  | End AF scan      |
+ *|                    | current scan  |                    | Lens now locked  |
+ *+--------------------+---------------+--------------------+------------------+
  *| PASSIVE_SCAN       | AF_TRIGGER    | FOCUSED_LOCKED     | Eventual trans.  |
  *|                    |               |                    | once focus good  |
  *|                    |               |                    | Lens now locked  |
@@ -670,12 +693,13 @@
  *| PASSIVE_FOCUSED    | HAL initiates | PASSIVE_SCAN       | Start AF scan    |
  *|                    | new scan      |                    | Lens now moving  |
  *+--------------------+---------------+--------------------+------------------+
+ *| PASSIVE_UNFOCUSED  | HAL initiates | PASSIVE_SCAN       | Start AF scan    |
+ *|                    | new scan      |                    | Lens now moving  |
+ *+--------------------+---------------+--------------------+------------------+
  *| PASSIVE_FOCUSED    | AF_TRIGGER    | FOCUSED_LOCKED     | Immediate trans. |
- *|                    |               |                    | if focus is good |
  *|                    |               |                    | Lens now locked  |
  *+--------------------+---------------+--------------------+------------------+
- *| PASSIVE_FOCUSED    | AF_TRIGGER    | NOT_FOCUSED_LOCKED | Immediate trans. |
- *|                    |               |                    | if focus is bad  |
+ *| PASSIVE_UNFOCUSED  | AF_TRIGGER    | NOT_FOCUSED_LOCKED | Immediate trans. |
  *|                    |               |                    | Lens now locked  |
  *+--------------------+---------------+--------------------+------------------+
  *| FOCUSED_LOCKED     | AF_TRIGGER    | FOCUSED_LOCKED     | No effect        |
@@ -693,10 +717,16 @@
  *   FLASH_REQUIRED and PRECAPTURE states. So rows below that refer to those two
  *   states should be ignored for the AWB state machine.
  *
+ *                  when enabling AE/AWB or changing AE/AWB mode
+ *| state              | trans. cause  | new state          | notes            |
+ *+--------------------+---------------+--------------------+------------------+
+ *| Any                |  mode change  | INACTIVE           |                  |
+ *+--------------------+---------------+--------------------+------------------+
+ *
  *                            mode = AE_MODE_OFF / AWB mode not AUTO
  *| state              | trans. cause  | new state          | notes            |
  *+--------------------+---------------+--------------------+------------------+
- *| INACTIVE           |               |                    | AE/AWB disabled  |
+ *| INACTIVE           |               | INACTIVE           | AE/AWB disabled  |
  *+--------------------+---------------+--------------------+------------------+
  *
  *                            mode = AE_MODE_ON_* / AWB_MODE_AUTO
@@ -1041,6 +1071,9 @@
  * remain valid as if configure_streams() had not been called.
  *
  * The endpoint of the stream is not visible to the camera HAL device.
+ * In DEVICE_API_VERSION_3_1, this was changed to share consumer usage flags
+ * on streams where the camera is a producer (OUTPUT and BIDIRECTIONAL stream
+ * types) see the usage field below.
  */
 typedef struct camera3_stream {
 
@@ -1092,6 +1125,25 @@
      * the producer and the consumer will be combined together and then passed
      * to the platform gralloc HAL module for allocating the gralloc buffers for
      * each stream.
+     *
+     * Version information:
+     *
+     * == CAMERA_DEVICE_API_VERSION_3_0:
+     *
+     *   No initial value guaranteed when passed via configure_streams().
+     *   HAL may not use this field as input, and must write over this field
+     *   with its usage flags.
+     *
+     * >= CAMERA_DEVICE_API_VERSION_3_1:
+     *
+     *   For stream_type OUTPUT and BIDIRECTIONAL, when passed via
+     *   configure_streams(), the initial value of this is the consumer's
+     *   usage flags.  The HAL may use these consumer flags to decide stream
+     *   configuration.
+     *   For stream_type INPUT, when passed via configure_streams(), the initial
+     *   value of this is 0.
+     *   For all streams passed via configure_streams(), the HAL must write
+     *   over this field with its usage flags.
      */
     uint32_t usage;
 
@@ -2035,6 +2087,49 @@
      */
     void (*dump)(const struct camera3_device *, int fd);
 
+    /**
+     * flush:
+     *
+     * Flush all currently in-process captures and all buffers in the pipeline
+     * on the given device. The framework will use this to dump all state as
+     * quickly as possible in order to prepare for a configure_streams() call.
+     *
+     * No buffers are required to be successfully returned, so every buffer
+     * held at the time of flush() (whether sucessfully filled or not) may be
+     * returned with CAMERA3_BUFFER_STATUS_ERROR. Note the HAL is still allowed
+     * to return valid (STATUS_OK) buffers during this call, provided they are
+     * succesfully filled.
+     *
+     * All requests currently in the HAL are expected to be returned as soon as
+     * possible.  Not-in-process requests should return errors immediately. Any
+     * interruptible hardware blocks should be stopped, and any uninterruptible
+     * blocks should be waited on.
+     *
+     * flush() should only return when there are no more outstanding buffers or
+     * requests left in the HAL.  The framework may call configure_streams (as
+     * the HAL state is now quiesced) or may issue new requests.
+     *
+     * A flush() call should only take 100ms or less. The maximum time it can
+     * take is 1 second.
+     *
+     * Version information:
+     *
+     *   only available if device version >= CAMERA_DEVICE_API_VERSION_3_1.
+     *
+     * Return values:
+     *
+     *  0:      On a successful flush of the camera HAL.
+     *
+     * -EINVAL: If the input is malformed (the device is not valid).
+     *
+     * -ENODEV: If the camera device has encountered a serious error. After this
+     *          error is returned, only the close() method can be successfully
+     *          called by the framework.
+     */
+    int (*flush)(const struct camera3_device *);
+
+    /* reserved for future use */
+    void *reserved[8];
 } camera3_device_ops_t;
 
 /**********************************************************************
diff --git a/include/hardware/camera_common.h b/include/hardware/camera_common.h
index 62c5740..3a1233f 100644
--- a/include/hardware/camera_common.h
+++ b/include/hardware/camera_common.h
@@ -67,6 +67,13 @@
  *   framework from the camera HAL module, which is used to notify the framework
  *   about changes to the camera module state. Modules that provide a valid
  *   set_callbacks() method must report at least this version number.
+ *
+ *******************************************************************************
+ * Version: 2.2 [CAMERA_MODULE_API_VERSION_2_2]
+ *
+ *   This camera module version adds vendor tag support from the module, and
+ *   deprecates the old vendor_tag_query_ops that were previously only
+ *   accessible with a device open.
  */
 
 /**
@@ -80,8 +87,9 @@
 #define CAMERA_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0)
 #define CAMERA_MODULE_API_VERSION_2_0 HARDWARE_MODULE_API_VERSION(2, 0)
 #define CAMERA_MODULE_API_VERSION_2_1 HARDWARE_MODULE_API_VERSION(2, 1)
+#define CAMERA_MODULE_API_VERSION_2_2 HARDWARE_MODULE_API_VERSION(2, 2)
 
-#define CAMERA_MODULE_API_VERSION_CURRENT CAMERA_MODULE_API_VERSION_2_1
+#define CAMERA_MODULE_API_VERSION_CURRENT CAMERA_MODULE_API_VERSION_2_2
 
 /**
  * All device versions <= HARDWARE_DEVICE_API_VERSION(1, 0xFF) must be treated
@@ -91,6 +99,7 @@
 #define CAMERA_DEVICE_API_VERSION_2_0 HARDWARE_DEVICE_API_VERSION(2, 0)
 #define CAMERA_DEVICE_API_VERSION_2_1 HARDWARE_DEVICE_API_VERSION(2, 1)
 #define CAMERA_DEVICE_API_VERSION_3_0 HARDWARE_DEVICE_API_VERSION(3, 0)
+#define CAMERA_DEVICE_API_VERSION_3_1 HARDWARE_DEVICE_API_VERSION(3, 1)
 
 // Device version 2.x is outdated; device version 3.0 is experimental
 #define CAMERA_DEVICE_API_VERSION_CURRENT CAMERA_DEVICE_API_VERSION_1_0
@@ -242,6 +251,65 @@
 
 } camera_module_callbacks_t;
 
+/**
+ * Set up vendor-specific tag query methods. These are needed to properly query
+ * entries with vendor-specified tags, potentially returned by get_camera_info.
+ *
+ * This should be used in place of vendor_tag_query_ops, which are deprecated.
+ */
+typedef struct vendor_tag_ops vendor_tag_ops_t;
+struct vendor_tag_ops {
+    /**
+     * Get the number of vendor tags supported on this platform. Used to
+     * calculate the size of buffer needed for holding the array of all tags
+     * returned by get_all_tags().
+     */
+    int (*get_tag_count)(const vendor_tag_ops_t *v);
+
+    /**
+     * Fill an array with all the supported vendor tags on this platform.
+     * get_tag_count() returns the number of tags supported, and
+     * tag_array will be allocated with enough space to hold all of the tags.
+     */
+    void (*get_all_tags)(const vendor_tag_ops_t *v, uint32_t *tag_array);
+
+    /**
+     * Get vendor section name for a vendor-specified entry tag. Only called for
+     * vendor-defined tags. The section name must start with the name of the
+     * vendor in the Java package style. For example, CameraZoom Inc. must
+     * prefix their sections with "com.camerazoom." Must return NULL if the tag
+     * is outside the bounds of vendor-defined sections.
+     *
+     * There may be different vendor-defined tag sections, for example the
+     * phone maker, the chipset maker, and the camera module maker may each
+     * have their own "com.vendor."-prefixed section.
+     *
+     * The memory pointed to by the return value must remain valid for the
+     * lifetime that the module is loaded, and is owned by the module.
+     */
+    const char *(*get_section_name)(const vendor_tag_ops_t *v, uint32_t tag);
+
+    /**
+     * Get tag name for a vendor-specified entry tag. Only called for
+     * vendor-defined tags. Must return NULL if the it is not a vendor-defined
+     * tag.
+     *
+     * The memory pointed to by the return value must remain valid for the
+     * lifetime that the module is loaded, and is owned by the module.
+     */
+    const char *(*get_tag_name)(const vendor_tag_ops_t *v, uint32_t tag);
+
+    /**
+     * Get tag type for a vendor-specified entry tag. Only called for tags >=
+     * 0x80000000. Must return -1 if the tag is outside the bounds of
+     * vendor-defined sections.
+     */
+    int (*get_tag_type)(const vendor_tag_ops_t *v, uint32_t tag);
+
+    /* reserved for future use */
+    void* reserved[8];
+};
+
 typedef struct camera_module {
     hw_module_t common;
 
@@ -290,6 +358,25 @@
      */
     int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
 
+    /**
+     * get_vendor_tag_ops:
+     *
+     * Get methods to query for vendor extension metadata tag information. The
+     * HAL should fill in all the vendor tag operation methods, or leave ops
+     * unchanged if no vendor tags are defined.
+     *
+     * Version information (based on camera_module_t.common.module_api_version):
+     *
+     *  CAMERA_MODULE_API_VERSION_1_x/2_0/2_1:
+     *    Not provided by HAL module. Framework may not call this function.
+     *
+     *  CAMERA_MODULE_API_VERSION_2_2:
+     *    Valid to be called by the framework.
+     */
+    void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);
+
+    /* reserved for future use */
+    void* reserved[8];
 } camera_module_t;
 
 __END_DECLS
diff --git a/include/hardware/consumerir.h b/include/hardware/consumerir.h
new file mode 100644
index 0000000..5adf6be
--- /dev/null
+++ b/include/hardware/consumerir.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_CONSUMERIR_H
+#define ANDROID_INCLUDE_HARDWARE_CONSUMERIR_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer_defs.h>
+
+#define CONSUMERIR_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0)
+#define CONSUMERIR_HARDWARE_MODULE_ID "consumerir"
+#define CONSUMERIR_TRANSMITTER "transmitter"
+
+typedef struct consumerir_freq_range {
+    int min;
+    int max;
+} consumerir_freq_range_t;
+
+typedef struct consumerir_module {
+    struct hw_module_t common;
+} consumerir_module_t;
+
+typedef struct consumerir_device {
+    struct hw_device_t common;
+
+    /*
+     * (*transmit)() is called to by the ConsumerIrService to send an IR pattern
+     * at a given carrier_freq.
+     *
+     * The pattern is alternating series of carrier on and off periods measured in
+     * microseconds.  The carrier should be turned off at the end of a transmit
+     * even if there are and odd number of entries in the pattern array.
+     *
+     * This call should return when the transmit is complete or encounters an error.
+     *
+     * returns: 0 on success. A negative error code on error.
+     */
+    int (*transmit)(struct consumerir_device *dev, int carrier_freq,
+            const int pattern[], int pattern_len);
+
+    /*
+     * (*get_num_carrier_freqs)() is called by the ConsumerIrService to get the
+     * number of carrier freqs to allocate space for, which is then filled by
+     * a subsequent call to (*get_carrier_freqs)().
+     *
+     * returns: the number of ranges on success. A negative error code on error.
+     */
+    int (*get_num_carrier_freqs)(struct consumerir_device *dev);
+
+    /*
+     * (*get_carrier_freqs)() is called by the ConsumerIrService to enumerate
+     * which frequencies the IR transmitter supports.  The HAL implementation
+     * should fill an array of consumerir_freq_range structs with the
+     * appropriate values for the transmitter, up to len elements.
+     *
+     * returns: the number of ranges on success. A negative error code on error.
+     */
+    int (*get_carrier_freqs)(struct consumerir_device *dev,
+            size_t len, consumerir_freq_range_t *ranges);
+
+    /* Reserved for future use. Must be NULL. */
+    void* reserved[8 - 3];
+} consumerir_device_t;
+
+#endif /* ANDROID_INCLUDE_HARDWARE_CONSUMERIR_H */
diff --git a/include/hardware/fused_location.h b/include/hardware/fused_location.h
new file mode 100644
index 0000000..5c7821c
--- /dev/null
+++ b/include/hardware/fused_location.h
@@ -0,0 +1,734 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_FUSED_LOCATION_H
+#define ANDROID_INCLUDE_HARDWARE_FUSED_LOCATION_H
+
+#include <hardware/hardware.h>
+
+
+/**
+ * This header file defines the interface of the Fused Location Provider.
+ * Fused Location Provider is designed to fuse data from various sources
+ * like GPS, Wifi, Cell, Sensors, Bluetooth etc to provide a fused location to the
+ * upper layers. The advantage of doing fusion in hardware is power savings.
+ * The goal is to do this without waking up the AP to get additional data.
+ * The software implementation of FLP will decide when to use
+ * the hardware fused location. Other location features like geofencing will
+ * also be implemented using fusion in hardware.
+ */
+__BEGIN_DECLS
+
+#define FLP_HEADER_VERSION          1
+#define FLP_MODULE_API_VERSION_0_1  HARDWARE_MODULE_API_VERSION(0, 1)
+#define FLP_DEVICE_API_VERSION_0_1  HARDWARE_DEVICE_API_VERSION_2(0, 1, FLP_HEADER_VERSION)
+
+/**
+ * The id of this module
+ */
+#define FUSED_LOCATION_HARDWARE_MODULE_ID "flp"
+
+/**
+ * Name for the FLP location interface
+ */
+#define FLP_LOCATION_INTERFACE     "flp_location"
+
+/**
+ * Name for the FLP location interface
+ */
+#define FLP_DIAGNOSTIC_INTERFACE     "flp_diagnostic"
+
+/**
+ * Name for the FLP_Geofencing interface.
+ */
+#define FLP_GEOFENCING_INTERFACE   "flp_geofencing"
+
+/**
+ * Name for the FLP_device context interface.
+ */
+#define FLP_DEVICE_CONTEXT_INTERFACE   "flp_device_context"
+
+/**
+ * Constants to indicate the various subsystems
+ * that will be used.
+ */
+#define FLP_TECH_MASK_GNSS      (1U<<0)
+#define FLP_TECH_MASK_WIFI      (1U<<1)
+#define FLP_TECH_MASK_SENSORS   (1U<<2)
+#define FLP_TECH_MASK_CELL      (1U<<3)
+#define FLP_TECH_MASK_BLUETOOTH (1U<<4)
+
+/**
+ * This constant is used with the batched locations
+ * APIs. Batching is mandatory when FLP implementation
+ * is supported. If the flag is set, the hardware implementation
+ * will wake up the application processor when the FIFO is full,
+ * If the flag is not set, the hardware implementation will drop
+ * the oldest data when the FIFO is full.
+ */
+#define FLP_BATCH_WAKEUP_ON_FIFO_FULL        0x0000001
+
+/**
+ * While batching, the implementation should not call the
+ * flp_location_callback on every location fix. However,
+ * sometimes in high power mode, the system might need
+ * a location callback every single time the location
+ * fix has been obtained. This flag controls that option.
+ * Its the responsibility of the upper layers (caller) to switch
+ * it off, if it knows that the AP might go to sleep.
+ * When this bit is on amidst a batching session, batching should
+ * continue while location fixes are reported in real time.
+ */
+#define FLP_BATCH_CALLBACK_ON_LOCATION_FIX   0x0000002
+
+/** Flags to indicate which values are valid in a FlpLocation. */
+typedef uint16_t FlpLocationFlags;
+
+// IMPORTANT: Note that the following values must match
+// constants in the corresponding java file.
+
+/** FlpLocation has valid latitude and longitude. */
+#define FLP_LOCATION_HAS_LAT_LONG   (1U<<0)
+/** FlpLocation has valid altitude. */
+#define FLP_LOCATION_HAS_ALTITUDE   (1U<<1)
+/** FlpLocation has valid speed. */
+#define FLP_LOCATION_HAS_SPEED      (1U<<2)
+/** FlpLocation has valid bearing. */
+#define FLP_LOCATION_HAS_BEARING    (1U<<4)
+/** FlpLocation has valid accuracy. */
+#define FLP_LOCATION_HAS_ACCURACY   (1U<<8)
+
+
+typedef int64_t FlpUtcTime;
+
+/** Represents a location. */
+typedef struct {
+    /** set to sizeof(FlpLocation) */
+    size_t          size;
+
+    /** Flags associated with the location object. */
+    FlpLocationFlags flags;
+
+    /** Represents latitude in degrees. */
+    double          latitude;
+
+    /** Represents longitude in degrees. */
+    double          longitude;
+
+    /**
+     * Represents altitude in meters above the WGS 84 reference
+     * ellipsoid. */
+    double          altitude;
+
+    /** Represents speed in meters per second. */
+    float           speed;
+
+    /** Represents heading in degrees. */
+    float           bearing;
+
+    /** Represents expected accuracy in meters. */
+    float           accuracy;
+
+    /** Timestamp for the location fix. */
+    FlpUtcTime      timestamp;
+
+    /** Sources used, will be Bitwise OR of the FLP_TECH_MASK bits. */
+    uint32_t         sources_used;
+} FlpLocation;
+
+typedef enum {
+    ASSOCIATE_JVM,
+    DISASSOCIATE_JVM,
+} ThreadEvent;
+
+/**
+ *  Callback with location information.
+ *  Can only be called from a thread associated to JVM using set_thread_event_cb.
+ *  Parameters:
+ *     num_locations is the number of batched locations available.
+ *     location is the pointer to an array of pointers to location objects.
+ */
+typedef void (*flp_location_callback)(int32_t num_locations, FlpLocation** location);
+
+/**
+ * Callback utility for acquiring a wakelock.
+ * This can be used to prevent the CPU from suspending while handling FLP events.
+ */
+typedef void (*flp_acquire_wakelock)();
+
+/**
+ * Callback utility for releasing the FLP wakelock.
+ */
+typedef void (*flp_release_wakelock)();
+
+/**
+ * Callback for associating a thread that can call into the Java framework code.
+ * This must be used to initialize any threads that report events up to the framework.
+ * Return value:
+ *      FLP_RESULT_SUCCESS on success.
+ *      FLP_RESULT_ERROR if the association failed in the current thread.
+ */
+typedef int (*flp_set_thread_event)(ThreadEvent event);
+
+/** FLP callback structure. */
+typedef struct {
+    /** set to sizeof(FlpCallbacks) */
+    size_t      size;
+    flp_location_callback location_cb;
+    flp_acquire_wakelock acquire_wakelock_cb;
+    flp_release_wakelock release_wakelock_cb;
+    flp_set_thread_event set_thread_event_cb;
+} FlpCallbacks;
+
+
+/** Options with the batching FLP APIs */
+typedef struct {
+    /**
+     * Maximum power in mW that the underlying implementation
+     * can use for this batching call.
+     * If max_power_allocation_mW is 0, only fixes that are generated
+     * at no additional cost of power shall be reported.
+     */
+    double max_power_allocation_mW;
+
+    /** Bitwise OR of the FLP_TECH_MASKS to use */
+    uint32_t sources_to_use;
+
+    /**
+     * FLP_BATCH_WAKEUP_ON_FIFO_FULL - If set the hardware
+     * will wake up the AP when the buffer is full. If not set, the
+     * hardware will drop the oldest location object.
+     *
+     * FLP_BATCH_CALLBACK_ON_LOCATION_FIX - If set the location
+     * callback will be called every time there is a location fix.
+     * Its the responsibility of the upper layers (caller) to switch
+     * it off, if it knows that the AP might go to sleep. When this
+     * bit is on amidst a batching session, batching should continue
+     * while location fixes are reported in real time.
+     *
+     * Other flags to be bitwised ORed in the future.
+     */
+    uint32_t flags;
+
+    /**
+     * Frequency with which location needs to be batched in nano
+     * seconds.
+     */
+    int64_t period_ns;
+} FlpBatchOptions;
+
+#define FLP_RESULT_SUCCESS                       0
+#define FLP_RESULT_ERROR                        -1
+#define FLP_RESULT_INSUFFICIENT_MEMORY          -2
+#define FLP_RESULT_TOO_MANY_GEOFENCES           -3
+#define FLP_RESULT_ID_EXISTS                    -4
+#define FLP_RESULT_ID_UNKNOWN                   -5
+#define FLP_RESULT_INVALID_GEOFENCE_TRANSITION  -6
+
+/**
+ * Represents the standard FLP interface.
+ */
+typedef struct {
+    /**
+     * set to sizeof(FlpLocationInterface)
+     */
+    size_t size;
+
+    /**
+     * Opens the interface and provides the callback routines
+     * to the implemenation of this interface.
+     */
+    int (*init)(FlpCallbacks* callbacks );
+
+    /**
+     * Return the batch size (in number of FlpLocation objects)
+     * available in the hardware.  Note, different HW implementations
+     * may have different sample sizes.  This shall return number
+     * of samples defined in the format of FlpLocation.
+     * This will be used by the upper layer, to decide on the batching
+     * interval and whether the AP should be woken up or not.
+     */
+    int (*get_batch_size)();
+
+    /**
+     * Start batching locations. This API is primarily used when the AP is
+     * asleep and the device can batch locations in the hardware.
+     *   flp_location_callback is used to return the locations. When the buffer
+     * is full and FLP_BATCH_WAKEUP_ON_FIFO_FULL is used, the AP is woken up.
+     * When the buffer is full and FLP_BATCH_WAKEUP_ON_FIFO_FULL is not set,
+     * the oldest location object is dropped. In this case the  AP will not be
+     * woken up. The upper layer will use get_batched_location
+     * API to explicitly ask for the location.
+     *   If FLP_BATCH_CALLBACK_ON_LOCATION_FIX is set, the implementation
+     * will call the flp_location_callback every single time there is a location
+     * fix. This overrides FLP_BATCH_WAKEUP_ON_FIFO_FULL flag setting.
+     * It's the responsibility of the upper layers (caller) to switch
+     * it off, if it knows that the AP might go to sleep. This is useful
+     * for nagivational applications when the system is in high power mode.
+     * Parameters:
+     *    id - Id for the request.
+     *    options - See FlpBatchOptions struct definition.
+     * Return value:
+     *    FLP_RESULT_SUCCESS on success, FLP_RESULT_INSUFFICIENT_MEMORY,
+     *    FLP_RESULT_ID_EXISTS, FLP_RESULT_ERROR on failure.
+     */
+    int (*start_batching)(int id, FlpBatchOptions* options);
+
+    /**
+     * Update FlpBatchOptions associated with a batching request.
+     * When a batching operation is in progress and a batching option
+     * such as FLP_BATCH_WAKEUP_ON_FIFO_FULL needs to be updated, this API
+     * will be used. For instance, this can happen when the AP is awake and
+     * the maps application is being used.
+     * Parameters:
+     *    id - Id of an existing batch request.
+     *    new_options - Updated FlpBatchOptions
+     * Return value:
+     *    FLP_RESULT_SUCCESS on success, FLP_RESULT_ID_UNKNOWN,
+     *    FLP_RESULT_ERROR on error.
+     */
+    int (*update_batching_options)(int id, FlpBatchOptions* new_options);
+
+    /**
+     * Stop batching.
+     * Parameters:
+     *    id - Id for the request.
+     * Return Value:
+     *    FLP_RESULT_SUCCESS on success, FLP_RESULT_ID_UNKNOWN or
+     *    FLP_RESULT_ERROR on failure.
+     */
+    int (*stop_batching)(int id);
+
+    /**
+     * Closes the interface. If any batch operations are in progress,
+     * they should be stopped.
+     */
+    void (*cleanup)();
+
+    /**
+     * Get the fused location that was batched.
+     *   flp_location_callback is used to return the location. The location object
+     * is dropped from the buffer only when the buffer is full. Do not remove it
+     * from the buffer just because it has been returned using the callback.
+     * In other words, when there is no new location object, two calls to
+     * get_batched_location(1) should return the same location object.
+     * Parameters:
+     *      last_n_locations - Number of locations to get. This can be one or many.
+     *      If the last_n_locations is 1, you get the latest location known to the
+     *      hardware.
+     */
+    void (*get_batched_location)(int last_n_locations);
+
+    /**
+     * Injects current location from another location provider
+     * latitude and longitude are measured in degrees
+     * expected accuracy is measured in meters
+     * Parameters:
+     *      location - The location object being injected.
+     * Return value: FLP_RESULT_SUCCESS or FLP_RESULT_ERROR.
+     */
+    int  (*inject_location)(FlpLocation* location);
+
+    /**
+     * Get a pointer to extension information.
+     */
+    const void* (*get_extension)(const char* name);
+} FlpLocationInterface;
+
+struct flp_device_t {
+    struct hw_device_t common;
+
+    /**
+     * Get a handle to the FLP Interface.
+     */
+    const FlpLocationInterface* (*get_flp_interface)(struct flp_device_t* dev);
+};
+
+/**
+ * Callback for reports diagnostic data into the Java framework code.
+*/
+typedef void (*report_data)(char* data, int length);
+
+/**
+ * FLP diagnostic callback structure.
+ * Currently, not used - but this for future extension.
+ */
+typedef struct {
+    /** set to sizeof(FlpDiagnosticCallbacks) */
+    size_t      size;
+
+    flp_set_thread_event set_thread_event_cb;
+
+    /** reports diagnostic data into the Java framework code */
+    report_data data_cb;
+} FlpDiagnosticCallbacks;
+
+/** Extended interface for diagnostic support. */
+typedef struct {
+    /** set to sizeof(FlpDiagnosticInterface) */
+    size_t          size;
+
+    /**
+     * Opens the diagnostic interface and provides the callback routines
+     * to the implemenation of this interface.
+     */
+    void  (*init)(FlpDiagnosticCallbacks* callbacks);
+
+    /**
+     * Injects diagnostic data into the FLP subsystem.
+     * Return 0 on success, -1 on error.
+     **/
+    int  (*inject_data)(char* data, int length );
+} FlpDiagnosticInterface;
+
+/**
+ * Context setting information.
+ * All these settings shall be injected to FLP HAL at FLP init time.
+ * Following that, only the changed setting need to be re-injected
+ * upon changes.
+ */
+
+#define FLP_DEVICE_CONTEXT_GPS_ENABLED                     (1U<<0)
+#define FLP_DEVICE_CONTEXT_AGPS_ENABLED                    (1U<<1)
+#define FLP_DEVICE_CONTEXT_NETWORK_POSITIONING_ENABLED     (1U<<2)
+#define FLP_DEVICE_CONTEXT_WIFI_CONNECTIVITY_ENABLED       (1U<<3)
+#define FLP_DEVICE_CONTEXT_WIFI_POSITIONING_ENABLED        (1U<<4)
+#define FLP_DEVICE_CONTEXT_HW_NETWORK_POSITIONING_ENABLED  (1U<<5)
+#define FLP_DEVICE_CONTEXT_AIRPLANE_MODE_ON                (1U<<6)
+#define FLP_DEVICE_CONTEXT_DATA_ENABLED                    (1U<<7)
+#define FLP_DEVICE_CONTEXT_ROAMING_ENABLED                 (1U<<8)
+#define FLP_DEVICE_CONTEXT_CURRENTLY_ROAMING               (1U<<9)
+#define FLP_DEVICE_CONTEXT_SENSOR_ENABLED                  (1U<<10)
+#define FLP_DEVICE_CONTEXT_BLUETOOTH_ENABLED               (1U<<11)
+#define FLP_DEVICE_CONTEXT_CHARGER_ON                      (1U<<12)
+
+/** Extended interface for device context support. */
+typedef struct {
+    /** set to sizeof(FlpDeviceContextInterface) */
+    size_t          size;
+
+    /**
+     * Injects debug data into the FLP subsystem.
+     * Return 0 on success, -1 on error.
+     **/
+    int  (*inject_device_context)(uint32_t enabledMask);
+} FlpDeviceContextInterface;
+
+
+/**
+ * There are 3 states associated with a Geofence: Inside, Outside, Unknown.
+ * There are 3 transitions: ENTERED, EXITED, UNCERTAIN.
+ *
+ * An example state diagram with confidence level: 95% and Unknown time limit
+ * set as 30 secs is shown below. (confidence level and Unknown time limit are
+ * explained latter)
+ *                         ____________________________
+ *                        |       Unknown (30 secs)   |
+ *                         """"""""""""""""""""""""""""
+ *                            ^ |                  |  ^
+ *                   UNCERTAIN| |ENTERED     EXITED|  |UNCERTAIN
+ *                            | v                  v  |
+ *                        ________    EXITED     _________
+ *                       | Inside | -----------> | Outside |
+ *                       |        | <----------- |         |
+ *                        """"""""    ENTERED    """""""""
+ *
+ * Inside state: We are 95% confident that the user is inside the geofence.
+ * Outside state: We are 95% confident that the user is outside the geofence
+ * Unknown state: Rest of the time.
+ *
+ * The Unknown state is better explained with an example:
+ *
+ *                            __________
+ *                           |         c|
+ *                           |  ___     |    _______
+ *                           |  |a|     |   |   b   |
+ *                           |  """     |    """""""
+ *                           |          |
+ *                            """"""""""
+ * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy
+ * circle reported by the FLP subsystem. Now with regard to "b", the system is
+ * confident that the user is outside. But with regard to "a" is not confident
+ * whether it is inside or outside the geofence. If the accuracy remains the
+ * same for a sufficient period of time, the UNCERTAIN transition would be
+ * triggered with the state set to Unknown. If the accuracy improves later, an
+ * appropriate transition should be triggered.  This "sufficient period of time"
+ * is defined by the parameter in the add_geofence_area API.
+ *     In other words, Unknown state can be interpreted as a state in which the
+ * FLP subsystem isn't confident enough that the user is either inside or
+ * outside the Geofence. It moves to Unknown state only after the expiry of the
+ * timeout.
+ *
+ * The geofence callback needs to be triggered for the ENTERED and EXITED
+ * transitions, when the FLP system is confident that the user has entered
+ * (Inside state) or exited (Outside state) the Geofence. An implementation
+ * which uses a value of 95% as the confidence is recommended. The callback
+ * should be triggered only for the transitions requested by the
+ * add_geofence_area call.
+ *
+ * Even though the diagram and explanation talks about states and transitions,
+ * the callee is only interested in the transistions. The states are mentioned
+ * here for illustrative purposes.
+ *
+ * Startup Scenario: When the device boots up, if an application adds geofences,
+ * and then we get an accurate FLP location fix, it needs to trigger the
+ * appropriate (ENTERED or EXITED) transition for every Geofence it knows about.
+ * By default, all the Geofences will be in the Unknown state.
+ *
+ * When the FLP system is unavailable, flp_geofence_status_callback should be
+ * called to inform the upper layers of the same. Similarly, when it becomes
+ * available the callback should be called. This is a global state while the
+ * UNKNOWN transition described above is per geofence.
+ *
+ */
+#define FLP_GEOFENCE_TRANSITION_ENTERED     (1L<<0)
+#define FLP_GEOFENCE_TRANSITION_EXITED      (1L<<1)
+#define FLP_GEOFENCE_TRANSITION_UNCERTAIN   (1L<<2)
+
+#define FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE (1L<<0)
+#define FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE   (1L<<1)
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ *      geofence_id - The id associated with the add_geofence_area.
+ *      location    - The current location as determined by the FLP subsystem.
+ *      transition  - Can be one of FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED,
+ *                    FLP_GEOFENCE_TRANSITION_UNCERTAIN.
+ *      timestamp   - Timestamp when the transition was detected; -1 if not available.
+ *      sources_used - Bitwise OR of FLP_TECH_MASK flags indicating which
+ *                     subsystems were used.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*flp_geofence_transition_callback) (int32_t geofence_id,  FlpLocation* location,
+        int32_t transition, FlpUtcTime timestamp, uint32_t sources_used);
+
+/**
+ * The callback associated with the availablity of one the sources used for geofence
+ * monitoring by the FLP sub-system For example, if the GPS system determines that it cannot
+ * monitor geofences because of lack of reliability or unavailability of the GPS signals,
+ * it will call this callback with FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE parameter and the
+ * source set to FLP_TECH_MASK_GNSS.
+ *
+ * Parameters:
+ *  status - FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE or FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE.
+ *  source - One of the FLP_TECH_MASKS
+ *  last_location - Last known location.
+ */
+typedef void (*flp_geofence_monitor_status_callback) (int32_t status, uint32_t source,
+                                                      FlpLocation* last_location);
+
+/**
+ * The callback associated with the add_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT_ERROR_TOO_MANY_GEOFENCES  - geofence limit has been reached.
+ *          FLP_RESULT_ID_EXISTS  - geofence with id already exists
+ *          FLP_RESULT_INVALID_GEOFENCE_TRANSITION - the monitorTransition contains an
+ *              invalid transition
+ *          FLP_RESULT_ERROR - for other errors.
+ */
+typedef void (*flp_geofence_add_callback) (int32_t geofence_id, int32_t result);
+
+/**
+ * The callback associated with the remove_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT_ID_UNKNOWN - for invalid id
+ *          FLP_RESULT_ERROR for others.
+ */
+typedef void (*flp_geofence_remove_callback) (int32_t geofence_id, int32_t result);
+
+
+/**
+ * The callback associated with the pause_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT__ID_UNKNOWN - for invalid id
+ *          FLP_RESULT_INVALID_TRANSITION -
+ *                    when monitor_transitions is invalid
+ *          FLP_RESULT_ERROR for others.
+ */
+typedef void (*flp_geofence_pause_callback) (int32_t geofence_id, int32_t result);
+
+/**
+ * The callback associated with the resume_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT_ID_UNKNOWN - for invalid id
+ *          FLP_RESULT_ERROR for others.
+ */
+typedef void (*flp_geofence_resume_callback) (int32_t geofence_id, int32_t result);
+
+typedef struct {
+    /** set to sizeof(FlpGeofenceCallbacks) */
+    size_t size;
+    flp_geofence_transition_callback geofence_transition_callback;
+    flp_geofence_monitor_status_callback geofence_status_callback;
+    flp_geofence_add_callback geofence_add_callback;
+    flp_geofence_remove_callback geofence_remove_callback;
+    flp_geofence_pause_callback geofence_pause_callback;
+    flp_geofence_resume_callback geofence_resume_callback;
+    flp_set_thread_event set_thread_event_cb;
+} FlpGeofenceCallbacks;
+
+
+/** Type of geofence */
+typedef enum {
+    TYPE_CIRCLE = 0,
+} GeofenceType;
+
+/** Circular geofence is represented by lat / long / radius */
+typedef struct {
+    double latitude;
+    double longitude;
+    double radius_m;
+} GeofenceCircle;
+
+/** Represents the type of geofence and data */
+typedef struct {
+    GeofenceType type;
+    union {
+        GeofenceCircle circle;
+    } geofence;
+} GeofenceData;
+
+/** Geofence Options */
+typedef struct {
+   /**
+    * The current state of the geofence. For example, if
+    * the system already knows that the user is inside the geofence,
+    * this will be set to FLP_GEOFENCE_TRANSITION_ENTERED. In most cases, it
+    * will be FLP_GEOFENCE_TRANSITION_UNCERTAIN. */
+    int last_transition;
+
+   /**
+    * Transitions to monitor. Bitwise OR of
+    * FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED and
+    * FLP_GEOFENCE_TRANSITION_UNCERTAIN.
+    */
+    int monitor_transitions;
+
+   /**
+    * Defines the best-effort description
+    * of how soon should the callback be called when the transition
+    * associated with the Geofence is triggered. For instance, if set
+    * to 1000 millseconds with FLP_GEOFENCE_TRANSITION_ENTERED, the callback
+    * should be called 1000 milliseconds within entering the geofence.
+    * This parameter is defined in milliseconds.
+    * NOTE: This is not to be confused with the rate that the GPS is
+    * polled at. It is acceptable to dynamically vary the rate of
+    * sampling the GPS for power-saving reasons; thus the rate of
+    * sampling may be faster or slower than this.
+    */
+    int notification_responsivenes_ms;
+
+   /**
+    * The time limit after which the UNCERTAIN transition
+    * should be triggered. This paramter is defined in milliseconds.
+    */
+    int unknown_timer_ms;
+
+    /**
+     * The sources to use for monitoring geofences. Its a BITWISE-OR
+     * of FLP_TECH_MASK flags.
+     */
+    uint32_t sources_to_use;
+} GeofenceOptions;
+
+/** Geofence struct */
+typedef struct {
+    int32_t geofence_id;
+    GeofenceData* data;
+    GeofenceOptions* options;
+} Geofence;
+
+/** Extended interface for FLP_Geofencing support */
+typedef struct {
+   /** set to sizeof(FlpGeofencingInterface) */
+   size_t          size;
+
+   /**
+    * Opens the geofence interface and provides the callback routines
+    * to the implemenation of this interface.
+    */
+   void  (*init)( FlpGeofenceCallbacks* callbacks );
+
+   /**
+    * Add a list of geofences.
+    * Parameters:
+    *     number_of_geofences - The number of geofences that needed to be added.
+    *     geofences - Pointer to array of pointers to Geofence structure.
+    */
+   void (*add_geofences) (int32_t number_of_geofences, Geofence** geofences);
+
+   /**
+    * Pause monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*pause_geofence) (int32_t geofence_id);
+
+   /**
+    * Resume monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    *   monitor_transitions - Which transitions to monitor. Bitwise OR of
+    *       FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED and
+    *       FLP_GEOFENCE_TRANSITION_UNCERTAIN.
+    *       This supersedes the value associated provided in the
+    *       add_geofence_area call.
+    */
+   void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+   /**
+    * Modify a particular geofence option.
+    * Parameters:
+    *    geofence_id - The id for the geofence.
+    *    options - Various options associated with the geofence. See
+    *        GeofenceOptions structure for details.
+    */
+   void (*modify_geofence_option) (int32_t geofence_id, GeofenceOptions* options);
+
+   /**
+    * Remove a list of geofences. After the function returns, no notifications
+    * should be sent.
+    * Parameter:
+    *     number_of_geofences - The number of geofences that needed to be added.
+    *     geofence_id - Pointer to array of geofence_ids to be removed.
+    */
+   void (*remove_geofences) (int32_t number_of_geofences, int32_t* geofence_id);
+} FlpGeofencingInterface;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_FLP_H */
+
diff --git a/include/hardware/gralloc.h b/include/hardware/gralloc.h
index 9c62242..0dbebcf 100644
--- a/include/hardware/gralloc.h
+++ b/include/hardware/gralloc.h
@@ -104,6 +104,9 @@
     /* mask for the software usage bit-mask */
     GRALLOC_USAGE_HW_MASK               = 0x00071F00,
 
+    /* buffer will be used as a RenderScript Allocation */
+    GRALLOC_USAGE_RENDERSCRIPT          = 0x00100000,
+
     /* buffer should be displayed full-screen on an external display when
      * possible
      */
diff --git a/include/hardware/hwcomposer.h b/include/hardware/hwcomposer.h
index d75a047..846bab4 100644
--- a/include/hardware/hwcomposer.h
+++ b/include/hardware/hwcomposer.h
@@ -54,6 +54,13 @@
     int bottom;
 } hwc_rect_t;
 
+typedef struct hwc_frect {
+    float left;
+    float top;
+    float right;
+    float bottom;
+} hwc_frect_t;
+
 typedef struct hwc_region {
     size_t numRects;
     hwc_rect_t const* rects;
@@ -149,8 +156,17 @@
             int32_t blending;
 
             /* area of the source to consider, the origin is the top-left corner of
-             * the buffer */
-            hwc_rect_t sourceCrop;
+             * the buffer. As of HWC_DEVICE_API_VERSION_1_3, sourceRect uses floats.
+             * If the h/w can't support a non-integer source crop rectangle, it should
+             * punt to OpenGL ES composition.
+             */
+            union {
+                // crop rectangle in integer (pre HWC_DEVICE_API_VERSION_1_3)
+                hwc_rect_t sourceCropi;
+                hwc_rect_t sourceCrop; // just for source compatibility
+                // crop rectangle in floats (as of HWC_DEVICE_API_VERSION_1_3)
+                hwc_frect_t sourceCropf;
+            };
 
             /* where to composite the sourceCrop onto the display. The sourceCrop
              * is scaled using linear filtering to the displayFrame. The origin is the
@@ -433,12 +449,12 @@
      * For HWC 1.0, numDisplays will always be one, and displays[0] will be
      * non-NULL.
      *
-     * For HWC 1.1, numDisplays will always be HWC_NUM_DISPLAY_TYPES. Entries
-     * for unsupported or disabled/disconnected display types will be NULL.
+     * For HWC 1.1, numDisplays will always be HWC_NUM_PHYSICAL_DISPLAY_TYPES.
+     * Entries for unsupported or disabled/disconnected display types will be
+     * NULL.
      *
-     * In a future version, numDisplays may be larger than
-     * HWC_NUM_DISPLAY_TYPES. The extra entries correspond to enabled virtual
-     * displays, and will be non-NULL.
+     * In HWC 1.3, numDisplays may be up to HWC_NUM_DISPLAY_TYPES. The extra
+     * entries correspond to enabled virtual displays, and will be non-NULL.
      *
      * returns: 0 on success. An negative error code on error. If an error is
      * returned, SurfaceFlinger will assume that none of the layer will be
@@ -466,12 +482,12 @@
      * For HWC 1.0, numDisplays will always be one, and displays[0] will be
      * non-NULL.
      *
-     * For HWC 1.1, numDisplays will always be HWC_NUM_DISPLAY_TYPES. Entries
-     * for unsupported or disabled/disconnected display types will be NULL.
+     * For HWC 1.1, numDisplays will always be HWC_NUM_PHYSICAL_DISPLAY_TYPES.
+     * Entries for unsupported or disabled/disconnected display types will be
+     * NULL.
      *
-     * In a future version, numDisplays may be larger than
-     * HWC_NUM_DISPLAY_TYPES. The extra entries correspond to enabled virtual
-     * displays, and will be non-NULL.
+     * In HWC 1.3, numDisplays may be up to HWC_NUM_DISPLAY_TYPES. The extra
+     * entries correspond to enabled virtual displays, and will be non-NULL.
      *
      * IMPORTANT NOTE: There is an implicit layer containing opaque black
      * pixels behind all the layers in the list. It is the responsibility of
diff --git a/include/hardware/hwcomposer_defs.h b/include/hardware/hwcomposer_defs.h
index 1edfd3d..c69a4bc 100644
--- a/include/hardware/hwcomposer_defs.h
+++ b/include/hardware/hwcomposer_defs.h
@@ -35,6 +35,7 @@
 #define HWC_DEVICE_API_VERSION_1_0  HARDWARE_DEVICE_API_VERSION_2(1, 0, HWC_HEADER_VERSION)
 #define HWC_DEVICE_API_VERSION_1_1  HARDWARE_DEVICE_API_VERSION_2(1, 1, HWC_HEADER_VERSION)
 #define HWC_DEVICE_API_VERSION_1_2  HARDWARE_DEVICE_API_VERSION_2(1, 2, HWC_HEADER_VERSION)
+#define HWC_DEVICE_API_VERSION_1_3  HARDWARE_DEVICE_API_VERSION_2(1, 3, HWC_HEADER_VERSION)
 
 enum {
     /* hwc_composer_device_t::set failed in EGL */
@@ -181,12 +182,16 @@
 enum {
     HWC_DISPLAY_PRIMARY     = 0,
     HWC_DISPLAY_EXTERNAL    = 1,    // HDMI, DP, etc.
-    HWC_NUM_DISPLAY_TYPES
+    HWC_DISPLAY_VIRTUAL     = 2,
+
+    HWC_NUM_PHYSICAL_DISPLAY_TYPES = 2,
+    HWC_NUM_DISPLAY_TYPES          = 3,
 };
 
 enum {
     HWC_DISPLAY_PRIMARY_BIT     = 1 << HWC_DISPLAY_PRIMARY,
     HWC_DISPLAY_EXTERNAL_BIT    = 1 << HWC_DISPLAY_EXTERNAL,
+    HWC_DISPLAY_VIRTUAL_BIT     = 1 << HWC_DISPLAY_VIRTUAL,
 };
 
 /*****************************************************************************/
diff --git a/include/hardware/memtrack.h b/include/hardware/memtrack.h
new file mode 100644
index 0000000..57ba4ad
--- /dev/null
+++ b/include/hardware/memtrack.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_MEMTRACK_H
+#define ANDROID_INCLUDE_HARDWARE_MEMTRACK_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <hardware/hardware.h>
+
+__BEGIN_DECLS
+
+#define MEMTRACK_MODULE_API_VERSION_0_1  HARDWARE_MODULE_API_VERSION(0, 1)
+
+/**
+ * The id of this module
+ */
+#define MEMTRACK_HARDWARE_MODULE_ID "memtrack"
+
+/*
+ * The Memory Tracker HAL is designed to return information about device-specific
+ * memory usage.  The primary goal is to be able to track memory that is not
+ * trackable in any other way, for example texture memory that is allocated by
+ * a process, but not mapped in to that process' address space.
+ * A secondary goal is to be able to categorize memory used by a process into
+ * GL, graphics, etc.  All memory sizes should be in real memory usage,
+ * accounting for stride, bit depth, rounding up to page size, etc.
+ *
+ * A process collecting memory statistics will call getMemory for each
+ * combination of pid and memory type.  For each memory type that it recognizes
+ * the HAL should fill out an array of memtrack_record structures breaking
+ * down the statistics of that memory type as much as possible.  For example,
+ * getMemory(<pid>, MEMTRACK_TYPE_GL) might return:
+ * { { 4096,  ACCOUNTED | PRIVATE | SYSTEM },
+ *   { 40960, UNACCOUNTED | PRIVATE | SYSTEM },
+ *   { 8192,  ACCOUNTED | PRIVATE | DEDICATED },
+ *   { 8192,  UNACCOUNTED | PRIVATE | DEDICATED } }
+ * If the HAL could not differentiate between SYSTEM and DEDICATED memory, it
+ * could return:
+ * { { 12288,  ACCOUNTED | PRIVATE },
+ *   { 49152,  UNACCOUNTED | PRIVATE } }
+ *
+ * Memory should not overlap between types.  For example, a graphics buffer
+ * that has been mapped into the GPU as a surface should show up when
+ * MEMTRACK_TYPE_GRAPHICS is requested, and not when MEMTRACK_TYPE_GL
+ * is requested.
+ */
+
+enum memtrack_type {
+    MEMTRACK_TYPE_OTHER = 0,
+    MEMTRACK_TYPE_GL = 1,
+    MEMTRACK_TYPE_GRAPHICS = 2,
+    MEMTRACK_TYPE_MULTIMEDIA = 3,
+    MEMTRACK_TYPE_CAMERA = 4,
+    MEMTRACK_NUM_TYPES,
+};
+
+struct memtrack_record {
+    size_t size_in_bytes;
+    unsigned int flags;
+};
+
+/**
+ * Flags to differentiate memory that can already be accounted for in
+ * /proc/<pid>/smaps,
+ * (Shared_Clean + Shared_Dirty + Private_Clean + Private_Dirty = Size).
+ * In general, memory mapped in to a userspace process is accounted unless
+ * it was mapped with remap_pfn_range.
+ * Exactly one of these should be set.
+ */
+#define MEMTRACK_FLAG_SMAPS_ACCOUNTED   (1 << 1)
+#define MEMTRACK_FLAG_SMAPS_UNACCOUNTED (1 << 2)
+
+/**
+ * Flags to differentiate memory shared across multiple processes vs. memory
+ * used by a single process.  Only zero or one of these may be set in a record.
+ * If none are set, record is assumed to count shared + private memory.
+ */
+#define MEMTRACK_FLAG_SHARED      (1 << 3)
+#define MEMTRACK_FLAG_SHARED_PSS  (1 << 4) /* shared / num_procesess */
+#define MEMTRACK_FLAG_PRIVATE     (1 << 5)
+
+/**
+ * Flags to differentiate memory taken from the kernel's allocation pool vs.
+ * memory that is dedicated to non-kernel allocations, for example a carveout
+ * or separate video memory.  Only zero or one of these may be set in a record.
+ * If none are set, record is assumed to count system + dedicated memory.
+ */
+#define MEMTRACK_FLAG_SYSTEM     (1 << 6)
+#define MEMTRACK_FLAG_DEDICATED  (1 << 7)
+
+/**
+ * Flags to differentiate memory accessible by the CPU in non-secure mode vs.
+ * memory that is protected.  Only zero or one of these may be set in a record.
+ * If none are set, record is assumed to count secure + nonsecure memory.
+ */
+#define MEMTRACK_FLAG_NONSECURE  (1 << 8)
+#define MEMTRACK_FLAG_SECURE     (1 << 9)
+
+/**
+ * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
+ * and the fields of this data structure must begin with hw_module_t
+ * followed by module specific information.
+ */
+typedef struct memtrack_module {
+    struct hw_module_t common;
+
+    /**
+     * (*init)() performs memtrack management setup actions and is called
+     * once before any calls to getMemory().
+     * Returns 0 on success, -errno on error.
+     */
+    int (*init)(const struct memtrack_module *module);
+
+    /**
+     * (*getMemory)() expects an array of record objects and populates up to
+     * *num_record structures with the sizes of memory plus associated flags for
+     * that memory.  It also updates *num_records with the total number of
+     * records it could return if *num_records was large enough when passed in.
+     * Returning records with size 0 is expected, the number of records should
+     * not vary between calls to getMemory for the same memory type, even
+     * for different pids.
+     *
+     * The caller will often call getMemory for a type and pid with
+     * *num_records == 0 to determine how many records to allocate room for,
+     * this case should be a fast-path in the HAL, returning a constant and
+     * not querying any kernel files.  If *num_records passed in is 0,
+     * then records may be NULL.
+     *
+     * This function must be thread-safe, it may get called from multiple
+     * threads at the same time.
+     *
+     * Returns 0 on success, -ENODEV if the type is not supported, -errno
+     * on other errors.
+     */
+    int (*getMemory)(const struct memtrack_module *module,
+                     pid_t pid,
+                     int type,
+                     struct memtrack_record *records,
+                     size_t *num_records);
+} memtrack_module_t;
+
+__END_DECLS
+
+#endif  // ANDROID_INCLUDE_HARDWARE_MEMTRACK_H
diff --git a/include/hardware/sensors.h b/include/hardware/sensors.h
index 7778e8f..4c13848 100644
--- a/include/hardware/sensors.h
+++ b/include/hardware/sensors.h
@@ -32,6 +32,7 @@
 #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)
 #define SENSORS_DEVICE_API_VERSION_1_0  HARDWARE_DEVICE_API_VERSION_2(1, 0, SENSORS_HEADER_VERSION)
+#define SENSORS_DEVICE_API_VERSION_1_1  HARDWARE_DEVICE_API_VERSION_2(1, 1, SENSORS_HEADER_VERSION)
 
 /**
  * The id of this module
@@ -64,6 +65,15 @@
     SENSORS_BATCH_WAKE_UPON_FIFO_FULL   = 0x00000002
 };
 
+/*
+ * what field for meta_data_event_t
+ */
+enum {
+    /* a previous flush operation has completed */
+    META_DATA_FLUSH_COMPLETE = 1,
+    META_DATA_VERSION   /* always last, leave auto-assigned */
+};
+
 /**
  * Definition of the axis used by the sensor HAL API
  *
@@ -132,9 +142,20 @@
  *
  * Each sensor has a type which defines what this sensor measures and how
  * measures are reported. All types are defined below.
+ *
+ * Device manufacturers (OEMs) can define their own sensor types, for
+ * their private use by applications or services provided by them. Such
+ * sensor types are specific to an OEM and can't be exposed in the SDK.
+ * These types must start at SENSOR_TYPE_DEVICE_PRIVATE_BASE.
  */
 
 /*
+ * Base for device manufacturers private sensor types.
+ * These sensor types can't be exposed in the SDK.
+ */
+#define SENSOR_TYPE_DEVICE_PRIVATE_BASE     0x10000
+
+/*
  * Sensor fusion and virtual sensors
  *
  * Many sensor types are or can be implemented as virtual sensors from
@@ -174,6 +195,40 @@
  *
  */
 
+
+/*
+ * SENSOR_TYPE_META_DATA
+ * trigger-mode: n/a
+ * wake-up sensor: n/a
+ *
+ * NO SENSOR OF THAT TYPE MUST BE RETURNED (*get_sensors_list)()
+ *
+ * SENSOR_TYPE_META_DATA is a special token used to populate the
+ * sensors_meta_data_event structure. It doesn't correspond to a physical
+ * sensor. sensors_meta_data_event are special, they exist only inside
+ * the HAL and are generated spontaneously, as opposed to be related to
+ * a physical sensor.
+ *
+ *   sensors_meta_data_event_t.version must be META_DATA_VERSION
+ *   sensors_meta_data_event_t.sensor must be 0
+ *   sensors_meta_data_event_t.type must be SENSOR_TYPE_META_DATA
+ *   sensors_meta_data_event_t.reserved must be 0
+ *   sensors_meta_data_event_t.timestamp must be 0
+ *
+ * The payload is a meta_data_event_t, where:
+ * meta_data_event_t.what can take the following values:
+ *
+ * META_DATA_FLUSH_COMPLETE
+ *   This event indicates that a previous (*flush)() call has completed for the sensor
+ *   handle specified in meta_data_event_t.sensor.
+ *   see (*flush)() for more details
+ *
+ * All other values for meta_data_event_t.what are reserved and
+ * must not be used.
+ *
+ */
+#define SENSOR_TYPE_META_DATA                           (0)
+
 /*
  * SENSOR_TYPE_ACCELEROMETER
  * trigger-mode: continuous
@@ -451,6 +506,9 @@
  *  SENSOR_TYPE_MAGNETIC_FIELD must be present and both must return the
  *  same sensor_t::name and sensor_t::vendor.
  *
+ *  Minimum filtering should be applied to this sensor. In particular, low pass
+ *  filters should be avoided.
+ *
  * See SENSOR_TYPE_MAGNETIC_FIELD for more information
  */
 #define SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED     (14)
@@ -608,7 +666,7 @@
  *
  * A sensor of this type returns the number of steps taken by the user since
  * the last reboot while activated. The value is returned as a uint64_t and is
- * reset to zero only on a system reboot.
+ * reset to zero only on a system / android reboot.
  *
  * The timestamp of the event is set to the time when the first step
  * for that event was taken.
@@ -662,7 +720,9 @@
  *  of using a gyroscope.
  *
  *  This sensor must be based on a magnetometer. It cannot be implemented using
- *  a gyroscope, and gyroscope input cannot be used by this sensor.
+ *  a gyroscope, and gyroscope input cannot be used by this sensor, as the
+ *  goal of this sensor is to be low power.
+ *  The accelerometer can be (and usually is) used.
  *
  *  Just like SENSOR_TYPE_ROTATION_VECTOR, this sensor reports an estimated
  *  heading accuracy:
@@ -740,6 +800,11 @@
   };
 } uncalibrated_event_t;
 
+typedef struct meta_data_event {
+    int32_t what;
+    int32_t sensor;
+} meta_data_event_t;
+
 /**
  * Union of the various types of sensor data
  * that can be returned.
@@ -761,48 +826,63 @@
     int64_t timestamp;
 
     union {
-        float           data[16];
+        union {
+            float           data[16];
 
-        /* acceleration values are in meter per second per second (m/s^2) */
-        sensors_vec_t   acceleration;
+            /* acceleration values are in meter per second per second (m/s^2) */
+            sensors_vec_t   acceleration;
 
-        /* magnetic vector values are in micro-Tesla (uT) */
-        sensors_vec_t   magnetic;
+            /* magnetic vector values are in micro-Tesla (uT) */
+            sensors_vec_t   magnetic;
 
-        /* orientation values are in degrees */
-        sensors_vec_t   orientation;
+            /* orientation values are in degrees */
+            sensors_vec_t   orientation;
 
-        /* gyroscope values are in rad/s */
-        sensors_vec_t   gyro;
+            /* gyroscope values are in rad/s */
+            sensors_vec_t   gyro;
 
-        /* temperature is in degrees centigrade (Celsius) */
-        float           temperature;
+            /* temperature is in degrees centigrade (Celsius) */
+            float           temperature;
 
-        /* distance in centimeters */
-        float           distance;
+            /* distance in centimeters */
+            float           distance;
 
-        /* light in SI lux units */
-        float           light;
+            /* light in SI lux units */
+            float           light;
 
-        /* pressure in hectopascal (hPa) */
-        float           pressure;
+            /* pressure in hectopascal (hPa) */
+            float           pressure;
 
-        /* relative humidity in percent */
-        float           relative_humidity;
+            /* relative humidity in percent */
+            float           relative_humidity;
 
-        /* step-counter */
-        uint64_t        step_counter;
+            /* uncalibrated gyroscope values are in rad/s */
+            uncalibrated_event_t uncalibrated_gyro;
 
-        /* uncalibrated gyroscope values are in rad/s */
-        uncalibrated_event_t uncalibrated_gyro;
+            /* uncalibrated magnetometer values are in micro-Teslas */
+            uncalibrated_event_t uncalibrated_magnetic;
 
-        /* uncalibrated magnetometer values are in micro-Teslas */
-        uncalibrated_event_t uncalibrated_magnetic;
+            /* this is a special event. see SENSOR_TYPE_META_DATA above.
+             * sensors_meta_data_event_t events are all reported with a type of
+             * SENSOR_TYPE_META_DATA. The handle is ignored and must be zero.
+             */
+            meta_data_event_t meta_data;
+        };
+
+        union {
+            uint64_t        data[8];
+
+            /* step-counter */
+            uint64_t        step_counter;
+        } u64;
     };
-    uint32_t        reserved1[4];
+    uint32_t reserved1[4];
 } sensors_event_t;
 
 
+/* see SENSOR_TYPE_META_DATA */
+typedef sensors_event_t sensors_meta_data_event_t;
+
 
 struct sensor_t;
 
@@ -865,8 +945,21 @@
      */
     int32_t         minDelay;
 
+    /* number of events reserved for this sensor in the batch mode FIFO.
+     * If there is a dedicated FIFO for this sensor, then this is the
+     * size of this FIFO. If the FIFO is shared with other sensors,
+     * this is the size reserved for that sensor and it can be zero.
+     */
+    uint32_t        fifoReservedEventCount;
+
+    /* maximum number of events of this sensor that could be batched.
+     * This is especially relevant when the FIFO is shared between
+     * several sensors; this value is then set to the size of that FIFO.
+     */
+    uint32_t        fifoMaxEventCount;
+
     /* reserved fields, must be zero */
-    void*           reserved[8];
+    void*           reserved[6];
 };
 
 
@@ -903,6 +996,10 @@
              * handle is the handle of the sensor to change.
              * enabled set to 1 to enable, or 0 to disable the sensor.
              *
+             * if enabled is set to 1, the sensor is activated even if
+             * setDelay() wasn't called before. In this case, a default rate
+             * should be used.
+             *
              * unless otherwise noted in the sensor types definitions, an
              * activated sensor never prevents the SoC to go into suspend
              * mode; that is, the HAL shall not hold a partial wake-lock on
@@ -912,10 +1009,10 @@
              * receiving an event and they must still accept to be deactivated
              * through a call to activate(..., ..., 0).
              *
-             * if "enabled" is true and the sensor is already activated, this
+             * if "enabled" is 1 and the sensor is already activated, this
              * function is a no-op and succeeds.
              *
-             * if "enabled" is false and the sensor is already de-activated,
+             * if "enabled" is 0 and the sensor is already de-activated,
              * this function is a no-op and succeeds.
              *
              * return 0 on success, negative errno code otherwise
@@ -939,6 +1036,9 @@
              * sensor_t::minDelay unless sensor_t::minDelay is 0, in which
              * case it is clamped to >= 1ms.
              *
+             * setDelay will not be called when the sensor is in batching mode.
+             * In this case, batch() will be called with the new period.
+             *
              * @return 0 if successful, < 0 on error
              */
             int (*setDelay)(struct sensors_poll_device_t *dev,
@@ -1068,19 +1168,30 @@
      * if a batch call with SENSORS_BATCH_DRY_RUN is successful,
      * the same call without SENSORS_BATCH_DRY_RUN must succeed as well).
      *
-     * If successful, 0 is returned.
-     * If the specified sensor doesn't support batch mode, -EINVAL is returned.
-     * If the specified sensor's trigger-mode is one-shot, -EINVAL is returned.
-     * If WAKE_UPON_FIFO_FULL is specified and the specified sensor's internal
-     * FIFO is too small to store at least 10 seconds worth of data at the
-     * given rate, -EINVAL is returned. Note that as stated above, this has to
-     * be determined at compile time, and not based on the state of the system.
-     * If some other constraints above cannot be satisfied, -EINVAL is returned.
+     * When timeout is not 0:
+     *   If successful, 0 is returned.
+     *   If the specified sensor doesn't support batch mode, return -EINVAL.
+     *   If the specified sensor's trigger-mode is one-shot, return -EINVAL.
+     *   If WAKE_UPON_FIFO_FULL is specified and the specified sensor's internal
+     *   FIFO is too small to store at least 10 seconds worth of data at the
+     *   given rate, -EINVAL is returned. Note that as stated above, this has to
+     *   be determined at compile time, and not based on the state of the
+     *   system.
+     *   If some other constraints above cannot be satisfied, return -EINVAL.
      *
      * Note: the timeout parameter, when > 0, has no impact on whether this
      *       function succeeds or fails.
      *
-     * If timeout is set to 0, this function must succeed.
+     * When timeout is 0:
+     *   The caller will never set the wake_upon_fifo_full flag.
+     *   The function must succeed, and batch mode must be deactivated.
+     *
+     * Independently of whether DRY_RUN is specified, When the call to batch()
+     * fails, no state should be changed. In particular, a failed call to
+     * batch() should not change the rate of the sensor. Example:
+     *   setDelay(..., 10ms)
+     *   batch(..., 20ms, ...) fails
+     *   rate should stay 10ms.
      *
      *
      * IMPLEMENTATION NOTES:
@@ -1150,6 +1261,35 @@
     int (*batch)(struct sensors_poll_device_1* dev,
             int handle, int flags, int64_t period_ns, int64_t timeout);
 
+    /*
+     * Flush adds a META_DATA_FLUSH_COMPLETE event (sensors_event_meta_data_t)
+     * to the end of the "batch mode" FIFO for the specified sensor and flushes
+     * the FIFO; those events are delivered as usual (i.e.: as if the batch
+     * timeout had expired) and removed from the FIFO.
+     *
+     * See the META_DATA_FLUSH_COMPLETE section for details about the
+     * META_DATA_FLUSH_COMPLETE event.
+     *
+     * The flush happens asynchronously (i.e.: this function must return
+     * immediately).
+     *
+     * If the implementation uses a single FIFO for several sensors, that
+     * FIFO is flushed and the META_DATA_FLUSH_COMPLETE event is added only
+     * for the specified sensor.
+     *
+     * If the specified sensor wasn't in batch mode, flush succeeds and
+     * promptly sends a META_DATA_FLUSH_COMPLETE event for that sensor.
+     *
+     * If the FIFO was empty at the time of the call, flush returns
+     * 0 (success) and promptly sends a META_DATA_FLUSH_COMPLETE event
+     * for that sensor.
+     *
+     * If the specified sensor wasn't enabled, flush returns -EINVAL.
+     *
+     * return 0 on success, negative errno code otherwise.
+     */
+    int (*flush)(struct sensors_poll_device_1* dev, int handle);
+
     void (*reserved_procs[8])(void);
 
 } sensors_poll_device_1_t;
diff --git a/modules/Android.mk b/modules/Android.mk
index 486b42d..b2d5a2a 100644
--- a/modules/Android.mk
+++ b/modules/Android.mk
@@ -1,2 +1,3 @@
-hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time power usbaudio audio_remote_submix camera
+hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time \
+	power usbaudio audio_remote_submix camera consumerir
 include $(call all-named-subdir-makefiles,$(hardware_modules))
diff --git a/modules/audio/audio_policy.c b/modules/audio/audio_policy.c
index 2dd3dbe..9335654 100644
--- a/modules/audio/audio_policy.c
+++ b/modules/audio/audio_policy.c
@@ -99,7 +99,8 @@
                                        uint32_t sampling_rate,
                                        audio_format_t format,
                                        audio_channel_mask_t channelMask,
-                                       audio_output_flags_t flags)
+                                       audio_output_flags_t flags,
+                                       const audio_offload_info_t *info)
 {
     return 0;
 }
@@ -229,6 +230,12 @@
     return -ENOSYS;
 }
 
+static bool ap_is_offload_supported(const struct audio_policy *pol,
+                                   const audio_offload_info_t *info)
+{
+    return false;
+}
+
 static int create_default_ap(const struct audio_policy_device *device,
                              struct audio_policy_service_ops *aps_ops,
                              void *service,
@@ -278,6 +285,8 @@
     dap->policy.is_stream_active = ap_is_stream_active;
     dap->policy.dump = ap_dump;
 
+    dap->policy.is_offload_supported = ap_is_offload_supported;
+
     dap->service = service;
     dap->aps_ops = aps_ops;
 
diff --git a/modules/audio_remote_submix/audio_hw.cpp b/modules/audio_remote_submix/audio_hw.cpp
old mode 100755
new mode 100644
index 5e88ef7..9df17b6
--- a/modules/audio_remote_submix/audio_hw.cpp
+++ b/modules/audio_remote_submix/audio_hw.cpp
@@ -271,7 +271,7 @@
             return 0;
         } else {
             // write() returned UNDERRUN or WOULD_BLOCK, retry
-            ALOGE("out_write() write to pipe returned unexpected %16lx", written_frames);
+            ALOGE("out_write() write to pipe returned unexpected %d", written_frames);
             written_frames = sink->write(buffer, frames);
         }
     }
@@ -281,7 +281,7 @@
     pthread_mutex_unlock(&out->dev->lock);
 
     if (written_frames < 0) {
-        ALOGE("out_write() failed writing to pipe with %16lx", written_frames);
+        ALOGE("out_write() failed writing to pipe with %d", written_frames);
         return 0;
     } else {
         ALOGV("out_write() wrote %lu bytes)", written_frames * frame_size);
@@ -549,7 +549,7 @@
     config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
     rsxadev->config.channel_mask = config->channel_mask;
 
-    if ((config->sample_rate != 48000) || (config->sample_rate != 44100)) {
+    if ((config->sample_rate != 48000) && (config->sample_rate != 44100)) {
         config->sample_rate = DEFAULT_RATE_HZ;
     }
     rsxadev->config.rate = config->sample_rate;
@@ -708,7 +708,7 @@
     config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
     rsxadev->config.channel_mask = config->channel_mask;
 
-    if ((config->sample_rate != 48000) || (config->sample_rate != 44100)) {
+    if ((config->sample_rate != 48000) && (config->sample_rate != 44100)) {
         config->sample_rate = DEFAULT_RATE_HZ;
     }
     rsxadev->config.rate = config->sample_rate;
diff --git a/modules/camera/Android.mk b/modules/camera/Android.mk
index eebffc1..e02a143 100644
--- a/modules/camera/Android.mk
+++ b/modules/camera/Android.mk
@@ -26,11 +26,14 @@
 LOCAL_SRC_FILES := \
 	CameraHAL.cpp \
 	Camera.cpp \
+	Metadata.cpp \
+	Stream.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
 	libcamera_metadata \
 	libcutils \
 	liblog \
+	libsync \
 
 LOCAL_CFLAGS += -Wall -Wextra -fvisibility=hidden
 
diff --git a/modules/camera/Camera.cpp b/modules/camera/Camera.cpp
index 203b772..973380e 100644
--- a/modules/camera/Camera.cpp
+++ b/modules/camera/Camera.cpp
@@ -17,7 +17,12 @@
 #include <cstdlib>
 #include <pthread.h>
 #include <hardware/camera3.h>
+#include <sync/sync.h>
+#include <system/camera_metadata.h>
+#include <system/graphics.h>
 #include "CameraHAL.h"
+#include "Metadata.h"
+#include "Stream.h"
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "Camera"
@@ -25,9 +30,14 @@
 
 #define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
 #include <cutils/trace.h>
+#include "ScopedTrace.h"
 
 #include "Camera.h"
 
+#define CAMERA_SYNC_TIMEOUT 5000 // in msecs
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
 namespace default_camera_hal {
 
 extern "C" {
@@ -42,14 +52,19 @@
 
 Camera::Camera(int id)
   : mId(id),
+    mStaticInfo(NULL),
     mBusy(false),
-    mCallbackOps(NULL)
+    mCallbackOps(NULL),
+    mStreams(NULL),
+    mNumStreams(0),
+    mSettings(NULL)
 {
-    pthread_mutex_init(&mMutex,
-                       NULL); // No pthread mutex attributes.
+    pthread_mutex_init(&mMutex, NULL);
+    pthread_mutex_init(&mStaticInfoMutex, NULL);
 
     memset(&mDevice, 0, sizeof(mDevice));
     mDevice.common.tag    = HARDWARE_DEVICE_TAG;
+    mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_0;
     mDevice.common.close  = close_device;
     mDevice.ops           = const_cast<camera3_device_ops_t*>(&sOps);
     mDevice.priv          = this;
@@ -57,16 +72,17 @@
 
 Camera::~Camera()
 {
+    pthread_mutex_destroy(&mMutex);
+    pthread_mutex_destroy(&mStaticInfoMutex);
 }
 
 int Camera::open(const hw_module_t *module, hw_device_t **device)
 {
     ALOGI("%s:%d: Opening camera device", __func__, mId);
-    ATRACE_BEGIN(__func__);
+    CAMTRACE_CALL();
     pthread_mutex_lock(&mMutex);
     if (mBusy) {
         pthread_mutex_unlock(&mMutex);
-        ATRACE_END();
         ALOGE("%s:%d: Error! Camera device already opened", __func__, mId);
         return -EBUSY;
     }
@@ -77,18 +93,33 @@
     *device = &mDevice.common;
 
     pthread_mutex_unlock(&mMutex);
-    ATRACE_END();
+    return 0;
+}
+
+int Camera::getInfo(struct camera_info *info)
+{
+    info->facing = CAMERA_FACING_FRONT;
+    info->orientation = 0;
+    info->device_version = mDevice.common.version;
+
+    pthread_mutex_lock(&mStaticInfoMutex);
+    if (mStaticInfo == NULL) {
+        mStaticInfo = initStaticInfo();
+    }
+    pthread_mutex_unlock(&mStaticInfoMutex);
+
+    info->static_camera_characteristics = mStaticInfo;
+
     return 0;
 }
 
 int Camera::close()
 {
     ALOGI("%s:%d: Closing camera device", __func__, mId);
-    ATRACE_BEGIN(__func__);
+    CAMTRACE_CALL();
     pthread_mutex_lock(&mMutex);
     if (!mBusy) {
         pthread_mutex_unlock(&mMutex);
-        ATRACE_END();
         ALOGE("%s:%d: Error! Camera device not open", __func__, mId);
         return -EINVAL;
     }
@@ -97,7 +128,6 @@
     mBusy = false;
 
     pthread_mutex_unlock(&mMutex);
-    ATRACE_END();
     return 0;
 }
 
@@ -105,44 +135,500 @@
 {
     ALOGV("%s:%d: callback_ops=%p", __func__, mId, callback_ops);
     mCallbackOps = callback_ops;
+    // Create standard settings templates
+    // 0 is invalid as template
+    mTemplates[0] = NULL;
+    // CAMERA3_TEMPLATE_PREVIEW = 1
+    mTemplates[1] = new Metadata(ANDROID_CONTROL_MODE_OFF,
+            ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW);
+    // CAMERA3_TEMPLATE_STILL_CAPTURE = 2
+    mTemplates[2] = new Metadata(ANDROID_CONTROL_MODE_OFF,
+            ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
+    // CAMERA3_TEMPLATE_VIDEO_RECORD = 3
+    mTemplates[3] = new Metadata(ANDROID_CONTROL_MODE_OFF,
+            ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
+    // CAMERA3_TEMPLATE_VIDEO_SNAPSHOT = 4
+    mTemplates[4] = new Metadata(ANDROID_CONTROL_MODE_OFF,
+            ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT);
+    // CAMERA3_TEMPLATE_STILL_ZERO_SHUTTER_LAG = 5
+    mTemplates[5] = new Metadata(ANDROID_CONTROL_MODE_OFF,
+            ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG);
+    // Pre-generate metadata structures
+    for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
+        mTemplates[i]->generate();
+    }
+    // TODO: create vendor templates
     return 0;
 }
 
-int Camera::configureStreams(camera3_stream_configuration_t *stream_list)
+camera_metadata_t *Camera::initStaticInfo()
 {
-    ALOGV("%s:%d: stream_list=%p", __func__, mId, stream_list);
-    // TODO: validate input, create internal stream representations
+    /*
+     * Setup static camera info.  This will have to customized per camera
+     * device.
+     */
+    Metadata m;
+
+    /* android.control */
+    int32_t android_control_ae_available_target_fps_ranges[] = {30, 30};
+    m.addInt32(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+            ARRAY_SIZE(android_control_ae_available_target_fps_ranges),
+            android_control_ae_available_target_fps_ranges);
+
+    int32_t android_control_ae_compensation_range[] = {-4, 4};
+    m.addInt32(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+            ARRAY_SIZE(android_control_ae_compensation_range),
+            android_control_ae_compensation_range);
+
+    camera_metadata_rational_t android_control_ae_compensation_step[] = {{2,1}};
+    m.addRational(ANDROID_CONTROL_AE_COMPENSATION_STEP,
+            ARRAY_SIZE(android_control_ae_compensation_step),
+            android_control_ae_compensation_step);
+
+    int32_t android_control_max_regions[] = {1};
+    m.addInt32(ANDROID_CONTROL_MAX_REGIONS,
+            ARRAY_SIZE(android_control_max_regions),
+            android_control_max_regions);
+
+    /* android.jpeg */
+    int32_t android_jpeg_available_thumbnail_sizes[] = {0, 0, 128, 96};
+    m.addInt32(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+            ARRAY_SIZE(android_jpeg_available_thumbnail_sizes),
+            android_jpeg_available_thumbnail_sizes);
+
+    /* android.lens */
+    float android_lens_info_available_focal_lengths[] = {1.0};
+    m.addFloat(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+            ARRAY_SIZE(android_lens_info_available_focal_lengths),
+            android_lens_info_available_focal_lengths);
+
+    /* android.request */
+    int32_t android_request_max_num_output_streams[] = {0, 3, 1};
+    m.addInt32(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+            ARRAY_SIZE(android_request_max_num_output_streams),
+            android_request_max_num_output_streams);
+
+    /* android.scaler */
+    int32_t android_scaler_available_formats[] = {
+            HAL_PIXEL_FORMAT_RAW_SENSOR,
+            HAL_PIXEL_FORMAT_BLOB,
+            HAL_PIXEL_FORMAT_RGBA_8888,
+            HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+            // These are handled by YCbCr_420_888
+            //        HAL_PIXEL_FORMAT_YV12,
+            //        HAL_PIXEL_FORMAT_YCrCb_420_SP,
+            HAL_PIXEL_FORMAT_YCbCr_420_888};
+    m.addInt32(ANDROID_SCALER_AVAILABLE_FORMATS,
+            ARRAY_SIZE(android_scaler_available_formats),
+            android_scaler_available_formats);
+
+    int64_t android_scaler_available_jpeg_min_durations[] = {1};
+    m.addInt64(ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS,
+            ARRAY_SIZE(android_scaler_available_jpeg_min_durations),
+            android_scaler_available_jpeg_min_durations);
+
+    int32_t android_scaler_available_jpeg_sizes[] = {640, 480};
+    m.addInt32(ANDROID_SCALER_AVAILABLE_JPEG_SIZES,
+            ARRAY_SIZE(android_scaler_available_jpeg_sizes),
+            android_scaler_available_jpeg_sizes);
+
+    float android_scaler_available_max_digital_zoom[] = {1};
+    m.addFloat(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+            ARRAY_SIZE(android_scaler_available_max_digital_zoom),
+            android_scaler_available_max_digital_zoom);
+
+    int64_t android_scaler_available_processed_min_durations[] = {1};
+    m.addInt64(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS,
+            ARRAY_SIZE(android_scaler_available_processed_min_durations),
+            android_scaler_available_processed_min_durations);
+
+    int32_t android_scaler_available_processed_sizes[] = {640, 480};
+    m.addInt32(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES,
+            ARRAY_SIZE(android_scaler_available_processed_sizes),
+            android_scaler_available_processed_sizes);
+
+    int64_t android_scaler_available_raw_min_durations[] = {1};
+    m.addInt64(ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS,
+            ARRAY_SIZE(android_scaler_available_raw_min_durations),
+            android_scaler_available_raw_min_durations);
+
+    int32_t android_scaler_available_raw_sizes[] = {640, 480};
+    m.addInt32(ANDROID_SCALER_AVAILABLE_RAW_SIZES,
+            ARRAY_SIZE(android_scaler_available_raw_sizes),
+            android_scaler_available_raw_sizes);
+
+    /* android.sensor */
+
+    int32_t android_sensor_info_active_array_size[] = {0, 0, 640, 480};
+    m.addInt32(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+            ARRAY_SIZE(android_sensor_info_active_array_size),
+            android_sensor_info_active_array_size);
+
+    int32_t android_sensor_info_sensitivity_range[] =
+            {100, 1600};
+    m.addInt32(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
+            ARRAY_SIZE(android_sensor_info_sensitivity_range),
+            android_sensor_info_sensitivity_range);
+
+    int64_t android_sensor_info_max_frame_duration[] = {30000000000};
+    m.addInt64(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+            ARRAY_SIZE(android_sensor_info_max_frame_duration),
+            android_sensor_info_max_frame_duration);
+
+    float android_sensor_info_physical_size[] = {3.2, 2.4};
+    m.addFloat(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
+            ARRAY_SIZE(android_sensor_info_physical_size),
+            android_sensor_info_physical_size);
+
+    int32_t android_sensor_info_pixel_array_size[] = {640, 480};
+    m.addInt32(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+            ARRAY_SIZE(android_sensor_info_pixel_array_size),
+            android_sensor_info_pixel_array_size);
+
+    int32_t android_sensor_orientation[] = {0};
+    m.addInt32(ANDROID_SENSOR_ORIENTATION,
+            ARRAY_SIZE(android_sensor_orientation),
+            android_sensor_orientation);
+
+    /* End of static camera characteristics */
+
+    return clone_camera_metadata(m.generate());
+}
+
+int Camera::configureStreams(camera3_stream_configuration_t *stream_config)
+{
+    camera3_stream_t *astream;
+    Stream **newStreams = NULL;
+
+    CAMTRACE_CALL();
+    ALOGV("%s:%d: stream_config=%p", __func__, mId, stream_config);
+
+    if (stream_config == NULL) {
+        ALOGE("%s:%d: NULL stream configuration array", __func__, mId);
+        return -EINVAL;
+    }
+    if (stream_config->num_streams == 0) {
+        ALOGE("%s:%d: Empty stream configuration array", __func__, mId);
+        return -EINVAL;
+    }
+
+    // Create new stream array
+    newStreams = new Stream*[stream_config->num_streams];
+    ALOGV("%s:%d: Number of Streams: %d", __func__, mId,
+            stream_config->num_streams);
+
+    pthread_mutex_lock(&mMutex);
+
+    // Mark all current streams unused for now
+    for (int i = 0; i < mNumStreams; i++)
+        mStreams[i]->mReuse = false;
+    // Fill new stream array with reused streams and new streams
+    for (unsigned int i = 0; i < stream_config->num_streams; i++) {
+        astream = stream_config->streams[i];
+        if (astream->max_buffers > 0) {
+            ALOGV("%s:%d: Reusing stream %d", __func__, mId, i);
+            newStreams[i] = reuseStream(astream);
+        } else {
+            ALOGV("%s:%d: Creating new stream %d", __func__, mId, i);
+            newStreams[i] = new Stream(mId, astream);
+        }
+
+        if (newStreams[i] == NULL) {
+            ALOGE("%s:%d: Error processing stream %d", __func__, mId, i);
+            goto err_out;
+        }
+        astream->priv = newStreams[i];
+    }
+
+    // Verify the set of streams in aggregate
+    if (!isValidStreamSet(newStreams, stream_config->num_streams)) {
+        ALOGE("%s:%d: Invalid stream set", __func__, mId);
+        goto err_out;
+    }
+
+    // Set up all streams (calculate usage/max_buffers for each)
+    setupStreams(newStreams, stream_config->num_streams);
+
+    // Destroy all old streams and replace stream array with new one
+    destroyStreams(mStreams, mNumStreams);
+    mStreams = newStreams;
+    mNumStreams = stream_config->num_streams;
+
+    // Clear out last seen settings metadata
+    setSettings(NULL);
+
+    pthread_mutex_unlock(&mMutex);
     return 0;
+
+err_out:
+    // Clean up temporary streams, preserve existing mStreams/mNumStreams
+    destroyStreams(newStreams, stream_config->num_streams);
+    pthread_mutex_unlock(&mMutex);
+    return -EINVAL;
+}
+
+void Camera::destroyStreams(Stream **streams, int count)
+{
+    if (streams == NULL)
+        return;
+    for (int i = 0; i < count; i++) {
+        // Only destroy streams that weren't reused
+        if (streams[i] != NULL && !streams[i]->mReuse)
+            delete streams[i];
+    }
+    delete [] streams;
+}
+
+Stream *Camera::reuseStream(camera3_stream_t *astream)
+{
+    Stream *priv = reinterpret_cast<Stream*>(astream->priv);
+    // Verify the re-used stream's parameters match
+    if (!priv->isValidReuseStream(mId, astream)) {
+        ALOGE("%s:%d: Mismatched parameter in reused stream", __func__, mId);
+        return NULL;
+    }
+    // Mark stream to be reused
+    priv->mReuse = true;
+    return priv;
+}
+
+bool Camera::isValidStreamSet(Stream **streams, int count)
+{
+    int inputs = 0;
+    int outputs = 0;
+
+    if (streams == NULL) {
+        ALOGE("%s:%d: NULL stream configuration streams", __func__, mId);
+        return false;
+    }
+    if (count == 0) {
+        ALOGE("%s:%d: Zero count stream configuration streams", __func__, mId);
+        return false;
+    }
+    // Validate there is at most one input stream and at least one output stream
+    for (int i = 0; i < count; i++) {
+        // A stream may be both input and output (bidirectional)
+        if (streams[i]->isInputType())
+            inputs++;
+        if (streams[i]->isOutputType())
+            outputs++;
+    }
+    ALOGV("%s:%d: Configuring %d output streams and %d input streams",
+            __func__, mId, outputs, inputs);
+    if (outputs < 1) {
+        ALOGE("%s:%d: Stream config must have >= 1 output", __func__, mId);
+        return false;
+    }
+    if (inputs > 1) {
+        ALOGE("%s:%d: Stream config must have <= 1 input", __func__, mId);
+        return false;
+    }
+    // TODO: check for correct number of Bayer/YUV/JPEG/Encoder streams
+    return true;
+}
+
+void Camera::setupStreams(Stream **streams, int count)
+{
+    /*
+     * This is where the HAL has to decide internally how to handle all of the
+     * streams, and then produce usage and max_buffer values for each stream.
+     * Note, the stream array has been checked before this point for ALL invalid
+     * conditions, so it must find a successful configuration for this stream
+     * array.  The HAL may not return an error from this point.
+     *
+     * In this demo HAL, we just set all streams to be the same dummy values;
+     * real implementations will want to avoid USAGE_SW_{READ|WRITE}_OFTEN.
+     */
+    for (int i = 0; i < count; i++) {
+        uint32_t usage = 0;
+
+        if (streams[i]->isOutputType())
+            usage |= GRALLOC_USAGE_SW_WRITE_OFTEN |
+                     GRALLOC_USAGE_HW_CAMERA_WRITE;
+        if (streams[i]->isInputType())
+            usage |= GRALLOC_USAGE_SW_READ_OFTEN |
+                     GRALLOC_USAGE_HW_CAMERA_READ;
+
+        streams[i]->setUsage(usage);
+        streams[i]->setMaxBuffers(1);
+    }
 }
 
 int Camera::registerStreamBuffers(const camera3_stream_buffer_set_t *buf_set)
 {
     ALOGV("%s:%d: buffer_set=%p", __func__, mId, buf_set);
-    // TODO: register buffers with hardware
-    return 0;
+    if (buf_set == NULL) {
+        ALOGE("%s:%d: NULL buffer set", __func__, mId);
+        return -EINVAL;
+    }
+    if (buf_set->stream == NULL) {
+        ALOGE("%s:%d: NULL stream handle", __func__, mId);
+        return -EINVAL;
+    }
+    Stream *stream = reinterpret_cast<Stream*>(buf_set->stream->priv);
+    return stream->registerBuffers(buf_set);
 }
 
 const camera_metadata_t* Camera::constructDefaultRequestSettings(int type)
 {
     ALOGV("%s:%d: type=%d", __func__, mId, type);
-    // TODO: return statically built default request
-    return NULL;
+
+    if (type < 1 || type >= CAMERA3_TEMPLATE_COUNT) {
+        ALOGE("%s:%d: Invalid template request type: %d", __func__, mId, type);
+        return NULL;
+    }
+    return mTemplates[type]->generate();
 }
 
 int Camera::processCaptureRequest(camera3_capture_request_t *request)
 {
+    camera3_capture_result result;
+
     ALOGV("%s:%d: request=%p", __func__, mId, request);
-    ATRACE_BEGIN(__func__);
+    CAMTRACE_CALL();
 
     if (request == NULL) {
         ALOGE("%s:%d: NULL request recieved", __func__, mId);
-        ATRACE_END();
         return -EINVAL;
     }
 
-    // TODO: verify request; submit request to hardware
-    ATRACE_END();
+    ALOGV("%s:%d: Request Frame:%d Settings:%p", __func__, mId,
+            request->frame_number, request->settings);
+
+    // NULL indicates use last settings
+    if (request->settings == NULL) {
+        if (mSettings == NULL) {
+            ALOGE("%s:%d: NULL settings without previous set Frame:%d Req:%p",
+                    __func__, mId, request->frame_number, request);
+            return -EINVAL;
+        }
+    } else {
+        setSettings(request->settings);
+    }
+
+    if (request->input_buffer != NULL) {
+        ALOGV("%s:%d: Reprocessing input buffer %p", __func__, mId,
+                request->input_buffer);
+
+        if (!isValidReprocessSettings(request->settings)) {
+            ALOGE("%s:%d: Invalid settings for reprocess request: %p",
+                    __func__, mId, request->settings);
+            return -EINVAL;
+        }
+    } else {
+        ALOGV("%s:%d: Capturing new frame.", __func__, mId);
+
+        if (!isValidCaptureSettings(request->settings)) {
+            ALOGE("%s:%d: Invalid settings for capture request: %p",
+                    __func__, mId, request->settings);
+            return -EINVAL;
+        }
+    }
+
+    if (request->num_output_buffers <= 0) {
+        ALOGE("%s:%d: Invalid number of output buffers: %d", __func__, mId,
+                request->num_output_buffers);
+        return -EINVAL;
+    }
+    result.num_output_buffers = request->num_output_buffers;
+    result.output_buffers = new camera3_stream_buffer_t[result.num_output_buffers];
+    for (unsigned int i = 0; i < request->num_output_buffers; i++) {
+        int res = processCaptureBuffer(&request->output_buffers[i],
+                const_cast<camera3_stream_buffer_t*>(&result.output_buffers[i]));
+        if (res)
+            goto err_out;
+    }
+
+    result.frame_number = request->frame_number;
+    // TODO: return actual captured/reprocessed settings
+    result.result = request->settings;
+    // TODO: asynchronously return results
+    notifyShutter(request->frame_number, 0);
+    mCallbackOps->process_capture_result(mCallbackOps, &result);
+
     return 0;
+
+err_out:
+    delete [] result.output_buffers;
+    // TODO: this should probably be a total device failure; transient for now
+    return -EINVAL;
+}
+
+void Camera::setSettings(const camera_metadata_t *new_settings)
+{
+    if (mSettings != NULL) {
+        free_camera_metadata(mSettings);
+        mSettings = NULL;
+    }
+
+    if (new_settings != NULL)
+        mSettings = clone_camera_metadata(new_settings);
+}
+
+bool Camera::isValidCaptureSettings(const camera_metadata_t* /*settings*/)
+{
+    // TODO: reject settings that cannot be captured
+    return true;
+}
+
+bool Camera::isValidReprocessSettings(const camera_metadata_t* /*settings*/)
+{
+    // TODO: reject settings that cannot be reprocessed
+    // input buffers unimplemented, use this to reject reprocessing requests
+    ALOGE("%s:%d: Input buffer reprocessing not implemented", __func__, mId);
+    return false;
+}
+
+int Camera::processCaptureBuffer(const camera3_stream_buffer_t *in,
+        camera3_stream_buffer_t *out)
+{
+    if (in->acquire_fence != -1) {
+        int res = sync_wait(in->acquire_fence, CAMERA_SYNC_TIMEOUT);
+        if (res == -ETIME) {
+            ALOGE("%s:%d: Timeout waiting on buffer acquire fence",
+                    __func__, mId);
+            return res;
+        } else if (res) {
+            ALOGE("%s:%d: Error waiting on buffer acquire fence: %s(%d)",
+                    __func__, mId, strerror(-res), res);
+            return res;
+        }
+    }
+
+    out->stream = in->stream;
+    out->buffer = in->buffer;
+    out->status = CAMERA3_BUFFER_STATUS_OK;
+    // TODO: use driver-backed release fences
+    out->acquire_fence = -1;
+    out->release_fence = -1;
+
+    // TODO: lock and software-paint buffer
+    return 0;
+}
+
+void Camera::notifyShutter(uint32_t frame_number, uint64_t timestamp)
+{
+    int res;
+    struct timespec ts;
+
+    // If timestamp is 0, get timestamp from right now instead
+    if (timestamp == 0) {
+        ALOGW("%s:%d: No timestamp provided, using CLOCK_BOOTTIME",
+                __func__, mId);
+        res = clock_gettime(CLOCK_BOOTTIME, &ts);
+        if (res == 0) {
+            timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec;
+        } else {
+            ALOGE("%s:%d: No timestamp and failed to get CLOCK_BOOTTIME %s(%d)",
+                    __func__, mId, strerror(errno), errno);
+        }
+    }
+    camera3_notify_msg_t m;
+    memset(&m, 0, sizeof(m));
+    m.type = CAMERA3_MSG_SHUTTER;
+    m.message.shutter.frame_number = frame_number;
+    m.message.shutter.timestamp = timestamp;
+    mCallbackOps->notify(mCallbackOps, &m);
 }
 
 void Camera::getMetadataVendorTagOps(vendor_tag_query_ops_t *ops)
@@ -153,7 +639,7 @@
 
 void Camera::dump(int fd)
 {
-    ALOGV("%s:%d: Dumping to fd %d", fd);
+    ALOGV("%s:%d: Dumping to fd %d", __func__, mId, fd);
     // TODO: dprintf all relevant state to fd
 }
 
diff --git a/modules/camera/Camera.h b/modules/camera/Camera.h
index f2ad093..be672f9 100644
--- a/modules/camera/Camera.h
+++ b/modules/camera/Camera.h
@@ -20,6 +20,8 @@
 #include <pthread.h>
 #include <hardware/hardware.h>
 #include <hardware/camera3.h>
+#include "Metadata.h"
+#include "Stream.h"
 
 namespace default_camera_hal {
 // Camera represents a physical camera on a device.
@@ -35,6 +37,7 @@
 
         // Common Camera Device Operations (see <hardware/camera_common.h>)
         int open(const hw_module_t *module, hw_device_t **device);
+        int getInfo(struct camera_info *info);
         int close();
 
         // Camera v3 Device Operations (see <hardware/camera3.h>)
@@ -50,8 +53,34 @@
         camera3_device_t mDevice;
 
     private:
+        // Separate initialization method for static metadata
+        camera_metadata_t *initStaticInfo();
+        // Reuse a stream already created by this device
+        Stream *reuseStream(camera3_stream_t *astream);
+        // Destroy all streams in a stream array, and the array itself
+        void destroyStreams(Stream **array, int count);
+        // Verify a set of streams is valid in aggregate
+        bool isValidStreamSet(Stream **array, int count);
+        // Calculate usage and max_bufs of each stream
+        void setupStreams(Stream **array, int count);
+        // Copy new settings for re-use and clean up old settings.
+        void setSettings(const camera_metadata_t *new_settings);
+        // Verify settings are valid for a capture
+        bool isValidCaptureSettings(const camera_metadata_t *settings);
+        // Verify settings are valid for reprocessing an input buffer
+        bool isValidReprocessSettings(const camera_metadata_t *settings);
+        // Process an output buffer
+        int processCaptureBuffer(const camera3_stream_buffer_t *in,
+                camera3_stream_buffer_t *out);
+        // Send a shutter notify message with start of exposure time
+        void notifyShutter(uint32_t frame_number, uint64_t timestamp);
+
         // Identifier used by framework to distinguish cameras
         const int mId;
+        // Metadata containing persistent camera characteristics
+        Metadata mMetadata;
+        // camera_metadata structure containing static characteristics
+        camera_metadata_t *mStaticInfo;
         // Busy flag indicates camera is in use
         bool mBusy;
         // Camera device operations handle shared by all devices
@@ -60,6 +89,17 @@
         const camera3_callback_ops_t *mCallbackOps;
         // Lock protecting the Camera object for modifications
         pthread_mutex_t mMutex;
+        // Lock protecting only static camera characteristics, which may
+        // be accessed without the camera device open
+        pthread_mutex_t mStaticInfoMutex;
+        // Array of handles to streams currently in use by the device
+        Stream **mStreams;
+        // Number of streams in mStreams
+        int mNumStreams;
+        // Static array of standard camera settings templates
+        Metadata *mTemplates[CAMERA3_TEMPLATE_COUNT];
+        // Most recent request settings seen, memoized to be reused
+        camera_metadata_t *mSettings;
 };
 } // namespace default_camera_hal
 
diff --git a/modules/camera/CameraHAL.cpp b/modules/camera/CameraHAL.cpp
index 6cae7d2..dfbbe4c 100644
--- a/modules/camera/CameraHAL.cpp
+++ b/modules/camera/CameraHAL.cpp
@@ -76,7 +76,7 @@
         return -ENODEV;
     }
     // TODO: return device-specific static metadata
-    return 0;
+    return mCameras[id]->getInfo(info);
 }
 
 int CameraHAL::setCallbacks(const camera_module_callbacks_t *callbacks)
@@ -90,11 +90,14 @@
 {
     int id;
     char *nameEnd;
-    Camera *cam;
 
     ALOGV("%s: module=%p, name=%s, device=%p", __func__, mod, name, dev);
+    if (*name == '\0') {
+        ALOGE("%s: Invalid camera id name is NULL", __func__);
+        return -EINVAL;
+    }
     id = strtol(name, &nameEnd, 10);
-    if (nameEnd != NULL) {
+    if (*nameEnd != '\0') {
         ALOGE("%s: Invalid camera id name %s", __func__, name);
         return -EINVAL;
     } else if (id < 0 || id >= mNumberOfCameras) {
diff --git a/modules/camera/Metadata.cpp b/modules/camera/Metadata.cpp
new file mode 100644
index 0000000..d5854f9
--- /dev/null
+++ b/modules/camera/Metadata.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pthread.h>
+#include <system/camera_metadata.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Metadata"
+#include <cutils/log.h>
+
+#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+#include <cutils/trace.h>
+#include "ScopedTrace.h"
+
+#include "Metadata.h"
+
+namespace default_camera_hal {
+
+Metadata::Metadata()
+  : mHead(NULL),
+    mTail(NULL),
+    mEntryCount(0),
+    mDataCount(0),
+    mGenerated(NULL),
+    mDirty(true)
+{
+    // NULL (default) pthread mutex attributes
+    pthread_mutex_init(&mMutex, NULL);
+}
+
+Metadata::~Metadata()
+{
+    Entry *current = mHead;
+
+    while (current != NULL) {
+        Entry *tmp = current;
+        current = current->mNext;
+        delete tmp;
+    }
+
+    if (mGenerated != NULL)
+        free_camera_metadata(mGenerated);
+
+    pthread_mutex_destroy(&mMutex);
+}
+
+Metadata::Metadata(uint8_t mode, uint8_t intent)
+  : mHead(NULL),
+    mTail(NULL),
+    mEntryCount(0),
+    mDataCount(0),
+    mGenerated(NULL),
+    mDirty(true)
+{
+    pthread_mutex_init(&mMutex, NULL);
+
+    if (validate(ANDROID_CONTROL_MODE, TYPE_BYTE, 1)) {
+        int res = add(ANDROID_CONTROL_MODE, 1, &mode);
+        if (res != 0) {
+            ALOGE("%s: Unable to add mode to template!", __func__);
+        }
+    } else {
+        ALOGE("%s: Invalid mode constructing template!", __func__);
+    }
+
+    if (validate(ANDROID_CONTROL_CAPTURE_INTENT, TYPE_BYTE, 1)) {
+        int res = add(ANDROID_CONTROL_CAPTURE_INTENT, 1, &intent);
+        if (res != 0) {
+            ALOGE("%s: Unable to add capture intent to template!", __func__);
+        }
+    } else {
+        ALOGE("%s: Invalid capture intent constructing template!", __func__);
+    }
+}
+
+int Metadata::addUInt8(uint32_t tag, int count, uint8_t *data)
+{
+    if (!validate(tag, TYPE_BYTE, count)) return -EINVAL;
+    return add(tag, count, data);
+}
+
+int Metadata::addInt32(uint32_t tag, int count, int32_t *data)
+{
+    if (!validate(tag, TYPE_INT32, count)) return -EINVAL;
+    return add(tag, count, data);
+}
+
+int Metadata::addFloat(uint32_t tag, int count, float *data)
+{
+    if (!validate(tag, TYPE_FLOAT, count)) return -EINVAL;
+    return add(tag, count, data);
+}
+
+int Metadata::addInt64(uint32_t tag, int count, int64_t *data)
+{
+    if (!validate(tag, TYPE_INT64, count)) return -EINVAL;
+    return add(tag, count, data);
+}
+
+int Metadata::addDouble(uint32_t tag, int count, double *data)
+{
+    if (!validate(tag, TYPE_DOUBLE, count)) return -EINVAL;
+    return add(tag, count, data);
+}
+
+int Metadata::addRational(uint32_t tag, int count,
+        camera_metadata_rational_t *data)
+{
+    if (!validate(tag, TYPE_RATIONAL, count)) return -EINVAL;
+    return add(tag, count, data);
+}
+
+bool Metadata::validate(uint32_t tag, int tag_type, int count)
+{
+    if (get_camera_metadata_tag_type(tag) < 0) {
+        ALOGE("%s: Invalid metadata entry tag: %d", __func__, tag);
+        return false;
+    }
+    if (tag_type < 0 || tag_type >= NUM_TYPES) {
+        ALOGE("%s: Invalid metadata entry tag type: %d", __func__, tag_type);
+        return false;
+    }
+    if (tag_type != get_camera_metadata_tag_type(tag)) {
+        ALOGE("%s: Tag %d called with incorrect type: %s(%d)", __func__, tag,
+                camera_metadata_type_names[tag_type], tag_type);
+        return false;
+    }
+    if (count < 1) {
+        ALOGE("%s: Invalid metadata entry count: %d", __func__, count);
+        return false;
+    }
+    return true;
+}
+
+int Metadata::add(uint32_t tag, int count, void *tag_data)
+{
+    int tag_type = get_camera_metadata_tag_type(tag);
+    size_t type_sz = camera_metadata_type_size[tag_type];
+
+    // Allocate array to hold new metadata
+    void *data = malloc(count * type_sz);
+    if (data == NULL)
+        return -ENOMEM;
+    memcpy(data, tag_data, count * type_sz);
+
+    pthread_mutex_lock(&mMutex);
+    mEntryCount++;
+    mDataCount += calculate_camera_metadata_entry_data_size(tag_type, count);
+    push(new Entry(tag, data, count));
+    mDirty = true;
+    pthread_mutex_unlock(&mMutex);
+    return 0;
+}
+
+camera_metadata_t* Metadata::generate()
+{
+    pthread_mutex_lock(&mMutex);
+    // Reuse if old generated metadata still valid
+    if (!mDirty && mGenerated != NULL) {
+        ALOGV("%s: Reusing generated metadata at %p", __func__, mGenerated);
+        goto out;
+    }
+    // Destroy old metadata
+    if (mGenerated != NULL) {
+        ALOGV("%s: Freeing generated metadata at %p", __func__, mGenerated);
+        free_camera_metadata(mGenerated);
+        mGenerated = NULL;
+    }
+    // Generate new metadata structure
+    ALOGV("%s: Generating new camera metadata structure, Entries:%d Data:%d",
+            __func__, mEntryCount, mDataCount);
+    mGenerated = allocate_camera_metadata(mEntryCount, mDataCount);
+    if (mGenerated == NULL) {
+        ALOGE("%s: Failed to allocate metadata (%d entries %d data)",
+                __func__, mEntryCount, mDataCount);
+        goto out;
+    }
+    // Walk list of entries adding each one to newly allocated metadata
+    for (Entry *current = mHead; current != NULL; current = current->mNext) {
+        int res = add_camera_metadata_entry(mGenerated, current->mTag,
+                current->mData, current->mCount);
+        if (res != 0) {
+            ALOGE("%s: Failed to add camera metadata: %d", __func__, res);
+            free_camera_metadata(mGenerated);
+            mGenerated = NULL;
+            goto out;
+        }
+    }
+
+out:
+    pthread_mutex_unlock(&mMutex);
+    return mGenerated;
+}
+
+Metadata::Entry::Entry(uint32_t tag, void *data, int count)
+  : mNext(NULL),
+    mPrev(NULL),
+    mTag(tag),
+    mData(data),
+    mCount(count)
+{
+}
+
+void Metadata::push(Entry *e)
+{
+    if (mHead == NULL) {
+        mHead = mTail = e;
+    } else {
+        mTail->insertAfter(e);
+        mTail = e;
+    }
+}
+
+Metadata::Entry::~Entry()
+{
+    if (mNext != NULL)
+        mNext->mPrev = mPrev;
+    if (mPrev != NULL)
+        mPrev->mNext = mNext;
+}
+
+void Metadata::Entry::insertAfter(Entry *e)
+{
+    if (e == NULL)
+        return;
+    if (mNext != NULL)
+        mNext->mPrev = e;
+    e->mNext = mNext;
+    e->mPrev = this;
+    mNext = e;
+}
+
+} // namespace default_camera_hal
diff --git a/modules/camera/Metadata.h b/modules/camera/Metadata.h
new file mode 100644
index 0000000..22d2f22
--- /dev/null
+++ b/modules/camera/Metadata.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef METADATA_H_
+#define METADATA_H_
+
+#include <hardware/camera3.h>
+#include <hardware/gralloc.h>
+#include <system/camera_metadata.h>
+#include <system/graphics.h>
+
+namespace default_camera_hal {
+// Metadata is a convenience class for dealing with libcamera_metadata
+class Metadata {
+    public:
+        Metadata();
+        ~Metadata();
+        // Constructor used for request metadata templates
+        Metadata(uint8_t mode, uint8_t intent);
+
+        // Parse and add an entry
+        int addUInt8(uint32_t tag, int count, uint8_t *data);
+        int addInt32(uint32_t tag, int count, int32_t *data);
+        int addFloat(uint32_t tag, int count, float *data);
+        int addInt64(uint32_t tag, int count, int64_t *data);
+        int addDouble(uint32_t tag, int count, double *data);
+        int addRational(uint32_t tag, int count,
+                camera_metadata_rational_t *data);
+        // Generate a camera_metadata structure and fill it with internal data
+        camera_metadata_t *generate();
+
+    private:
+        // Validate the tag, type and count for a metadata entry
+        bool validate(uint32_t tag, int tag_type, int count);
+        // Add a verified tag with data to this Metadata structure
+        int add(uint32_t tag, int count, void *tag_data);
+
+        class Entry {
+            public:
+                Entry(uint32_t tag, void *data, int count);
+                ~Entry();
+                Entry *mNext;
+                Entry *mPrev;
+                const uint32_t mTag;
+                const void *mData;
+                const int mCount;
+                void insertAfter(Entry *e);
+        };
+        // List ends
+        Entry *mHead;
+        Entry *mTail;
+        // Append entry to list
+        void push(Entry *e);
+        // Total of entries and entry data size
+        int mEntryCount;
+        int mDataCount;
+        // Save generated metadata, invalidated on update
+        camera_metadata_t *mGenerated;
+        // Flag to force metadata regeneration
+        bool mDirty;
+        // Lock protecting the Metadata object for modifications
+        pthread_mutex_t mMutex;
+};
+} // namespace default_camera_hal
+
+#endif // METADATA_H_
diff --git a/modules/camera/ScopedTrace.h b/modules/camera/ScopedTrace.h
new file mode 100644
index 0000000..ed00570
--- /dev/null
+++ b/modules/camera/ScopedTrace.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CAMERA_SCOPED_TRACE_H
+#define CAMERA_SCOPED_TRACE_H
+
+#include <stdint.h>
+#include <cutils/trace.h>
+
+// See <cutils/trace.h> for more tracing macros.
+
+// CAMTRACE_NAME traces the beginning and end of the current scope.  To trace
+// the correct start and end times this macro should be declared first in the
+// scope body.
+#define CAMTRACE_NAME(name) ScopedTrace ___tracer(ATRACE_TAG, name)
+// CAMTRACE_CALL is an ATRACE_NAME that uses the current function name.
+#define CAMTRACE_CALL() CAMTRACE_NAME(__FUNCTION__)
+
+namespace default_camera_hal {
+
+class ScopedTrace {
+public:
+inline ScopedTrace(uint64_t tag, const char* name)
+    : mTag(tag) {
+    atrace_begin(mTag,name);
+}
+
+inline ~ScopedTrace() {
+    atrace_end(mTag);
+}
+
+private:
+    uint64_t mTag;
+};
+
+}; // namespace default_camera_hal
+
+#endif // CAMERA_SCOPED_TRACE_H
diff --git a/modules/camera/Stream.cpp b/modules/camera/Stream.cpp
new file mode 100644
index 0000000..aae7adb
--- /dev/null
+++ b/modules/camera/Stream.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pthread.h>
+#include <hardware/camera3.h>
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Stream"
+#include <cutils/log.h>
+
+#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+#include <cutils/trace.h>
+#include "ScopedTrace.h"
+
+#include "Stream.h"
+
+namespace default_camera_hal {
+
+Stream::Stream(int id, camera3_stream_t *s)
+  : mReuse(false),
+    mId(id),
+    mStream(s),
+    mType(s->stream_type),
+    mWidth(s->width),
+    mHeight(s->height),
+    mFormat(s->format),
+    mUsage(0),
+    mMaxBuffers(0),
+    mRegistered(false),
+    mBuffers(0),
+    mNumBuffers(0)
+{
+    // NULL (default) pthread mutex attributes
+    pthread_mutex_init(&mMutex, NULL);
+}
+
+Stream::~Stream()
+{
+    pthread_mutex_lock(&mMutex);
+    unregisterBuffers_L();
+    pthread_mutex_unlock(&mMutex);
+}
+
+void Stream::setUsage(uint32_t usage)
+{
+    pthread_mutex_lock(&mMutex);
+    if (usage != mUsage) {
+        mUsage = usage;
+        mStream->usage = usage;
+        unregisterBuffers_L();
+    }
+    pthread_mutex_unlock(&mMutex);
+}
+
+void Stream::setMaxBuffers(uint32_t max_buffers)
+{
+    pthread_mutex_lock(&mMutex);
+    if (max_buffers != mMaxBuffers) {
+        mMaxBuffers = max_buffers;
+        mStream->max_buffers = max_buffers;
+        unregisterBuffers_L();
+    }
+    pthread_mutex_unlock(&mMutex);
+}
+
+int Stream::getType()
+{
+    return mType;
+}
+
+bool Stream::isInputType()
+{
+    return mType == CAMERA3_STREAM_INPUT ||
+        mType == CAMERA3_STREAM_BIDIRECTIONAL;
+}
+
+bool Stream::isOutputType()
+{
+    return mType == CAMERA3_STREAM_OUTPUT ||
+        mType == CAMERA3_STREAM_BIDIRECTIONAL;
+}
+
+bool Stream::isRegistered()
+{
+    return mRegistered;
+}
+
+bool Stream::isValidReuseStream(int id, camera3_stream_t *s)
+{
+    if (id != mId) {
+        ALOGE("%s:%d: Invalid camera id for reuse. Got %d expect %d",
+                __func__, mId, id, mId);
+        return false;
+    }
+    if (s != mStream) {
+        ALOGE("%s:%d: Invalid stream handle for reuse. Got %p expect %p",
+                __func__, mId, s, mStream);
+        return false;
+    }
+    if (s->stream_type != mType) {
+        // TODO: prettyprint type string
+        ALOGE("%s:%d: Mismatched type in reused stream. Got %d expect %d",
+                __func__, mId, s->stream_type, mType);
+        return false;
+    }
+    if (s->format != mFormat) {
+        // TODO: prettyprint format string
+        ALOGE("%s:%d: Mismatched format in reused stream. Got %d expect %d",
+                __func__, mId, s->format, mFormat);
+        return false;
+    }
+    if (s->width != mWidth) {
+        ALOGE("%s:%d: Mismatched width in reused stream. Got %d expect %d",
+                __func__, mId, s->width, mWidth);
+        return false;
+    }
+    if (s->height != mHeight) {
+        ALOGE("%s:%d: Mismatched height in reused stream. Got %d expect %d",
+                __func__, mId, s->height, mHeight);
+        return false;
+    }
+    return true;
+}
+
+int Stream::registerBuffers(const camera3_stream_buffer_set_t *buf_set)
+{
+    CAMTRACE_CALL();
+
+    if (buf_set->stream != mStream) {
+        ALOGE("%s:%d: Buffer set for invalid stream. Got %p expect %p",
+                __func__, mId, buf_set->stream, mStream);
+        return -EINVAL;
+    }
+
+    pthread_mutex_lock(&mMutex);
+
+    mNumBuffers = buf_set->num_buffers;
+    mBuffers = new buffer_handle_t*[mNumBuffers];
+
+    for (unsigned int i = 0; i < mNumBuffers; i++) {
+        ALOGV("%s:%d: Registering buffer %p", __func__, mId,
+                buf_set->buffers[i]);
+        mBuffers[i] = buf_set->buffers[i];
+        // TODO: register buffers with hw, handle error cases
+    }
+    mRegistered = true;
+
+    pthread_mutex_unlock(&mMutex);
+
+    return 0;
+}
+
+// This must only be called with mMutex held
+void Stream::unregisterBuffers_L()
+{
+    mRegistered = false;
+    mNumBuffers = 0;
+    delete [] mBuffers;
+    // TODO: unregister buffers from hw
+}
+
+} // namespace default_camera_hal
diff --git a/modules/camera/Stream.h b/modules/camera/Stream.h
new file mode 100644
index 0000000..34abd95
--- /dev/null
+++ b/modules/camera/Stream.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STREAM_H_
+#define STREAM_H_
+
+#include <hardware/camera3.h>
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+
+namespace default_camera_hal {
+// Stream represents a single input or output stream for a camera device.
+class Stream {
+    public:
+        Stream(int id, camera3_stream_t *s);
+        ~Stream();
+
+        // validate that astream's parameters match this stream's parameters
+        bool isValidReuseStream(int id, camera3_stream_t *s);
+
+        // Register buffers with hardware
+        int registerBuffers(const camera3_stream_buffer_set_t *buf_set);
+
+        void setUsage(uint32_t usage);
+        void setMaxBuffers(uint32_t max_buffers);
+
+        int getType();
+        bool isInputType();
+        bool isOutputType();
+        bool isRegistered();
+
+        // This stream is being reused. Used in stream configuration passes
+        bool mReuse;
+
+    private:
+        // Clean up buffer state. must be called with mMutex held.
+        void unregisterBuffers_L();
+
+        // The camera device id this stream belongs to
+        const int mId;
+        // Handle to framework's stream, used as a cookie for buffers
+        camera3_stream_t *mStream;
+        // Stream type: CAMERA3_STREAM_* (see <hardware/camera3.h>)
+        const int mType;
+        // Width in pixels of the buffers in this stream
+        const uint32_t mWidth;
+        // Height in pixels of the buffers in this stream
+        const uint32_t mHeight;
+        // Gralloc format: HAL_PIXEL_FORMAT_* (see <system/graphics.h>)
+        const int mFormat;
+        // Gralloc usage mask : GRALLOC_USAGE_* (see <hardware/gralloc.h>)
+        uint32_t mUsage;
+        // Max simultaneous in-flight buffers for this stream
+        uint32_t mMaxBuffers;
+        // Buffers have been registered for this stream and are ready
+        bool mRegistered;
+        // Array of handles to buffers currently in use by the stream
+        buffer_handle_t **mBuffers;
+        // Number of buffers in mBuffers
+        unsigned int mNumBuffers;
+        // Lock protecting the Stream object for modifications
+        pthread_mutex_t mMutex;
+};
+} // namespace default_camera_hal
+
+#endif // STREAM_H_
diff --git a/modules/consumerir/Android.mk b/modules/consumerir/Android.mk
new file mode 100644
index 0000000..ed6aa0f
--- /dev/null
+++ b/modules/consumerir/Android.mk
@@ -0,0 +1,25 @@
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := consumerir.default
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SRC_FILES := consumerir.c
+LOCAL_SHARED_LIBRARIES := liblog libcutils
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/modules/consumerir/consumerir.c b/modules/consumerir/consumerir.c
new file mode 100644
index 0000000..83eba75
--- /dev/null
+++ b/modules/consumerir/consumerir.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "ConsumerIrHal"
+
+#include <errno.h>
+#include <string.h>
+#include <cutils/log.h>
+#include <hardware/hardware.h>
+#include <hardware/consumerir.h>
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+static const consumerir_freq_range_t consumerir_freqs[] = {
+    {.min = 30000, .max = 30000},
+    {.min = 33000, .max = 33000},
+    {.min = 36000, .max = 36000},
+    {.min = 38000, .max = 38000},
+    {.min = 40000, .max = 40000},
+    {.min = 56000, .max = 56000},
+};
+
+static int consumerir_transmit(struct consumerir_device *dev,
+   int carrier_freq, int pattern[], int pattern_len)
+{
+    int total_time = 0;
+    long i;
+
+    for (i = 0; i < pattern_len; i++)
+        total_time += pattern[i];
+
+    /* simulate the time spent transmitting by sleeping */
+    ALOGD("transmit for %d uS at %d Hz", total_time, carrier_freq);
+    usleep(total_time);
+
+    return 0;
+}
+
+static int consumerir_get_num_carrier_freqs(struct consumerir_device *dev)
+{
+    return ARRAY_SIZE(consumerir_freqs);
+}
+
+static int consumerir_get_carrier_freqs(struct consumerir_device *dev,
+    size_t len, consumerir_freq_range_t *ranges)
+{
+    size_t to_copy = ARRAY_SIZE(consumerir_freqs);
+
+    to_copy = len < to_copy ? len : to_copy;
+    memcpy(ranges, consumerir_freqs, to_copy * sizeof(consumerir_freq_range_t));
+    return to_copy;
+}
+
+static int consumerir_close(hw_device_t *dev)
+{
+    free(dev);
+    return 0;
+}
+
+/*
+ * Generic device handling
+ */
+static int consumerir_open(const hw_module_t* module, const char* name,
+        hw_device_t** device)
+{
+    if (strcmp(name, CONSUMERIR_TRANSMITTER) != 0) {
+        return -EINVAL;
+    }
+    if (device == NULL) {
+        ALOGE("NULL device on open");
+        return -EINVAL;
+    }
+
+    consumerir_device_t *dev = malloc(sizeof(consumerir_device_t));
+    memset(dev, 0, sizeof(consumerir_device_t));
+
+    dev->common.tag = HARDWARE_DEVICE_TAG;
+    dev->common.version = 0;
+    dev->common.module = (struct hw_module_t*) module;
+    dev->common.close = consumerir_close;
+
+    dev->transmit = consumerir_transmit;
+    dev->get_num_carrier_freqs = consumerir_get_num_carrier_freqs;
+    dev->get_carrier_freqs = consumerir_get_carrier_freqs;
+
+    *device = (hw_device_t*) dev;
+    return 0;
+}
+
+static struct hw_module_methods_t consumerir_module_methods = {
+    .open = consumerir_open,
+};
+
+consumerir_module_t HAL_MODULE_INFO_SYM = {
+    .common = {
+        .tag                = HARDWARE_MODULE_TAG,
+        .module_api_version = CONSUMERIR_MODULE_API_VERSION_1_0,
+        .hal_api_version    = HARDWARE_HAL_API_VERSION,
+        .id                 = CONSUMERIR_HARDWARE_MODULE_ID,
+        .name               = "Demo IR HAL",
+        .author             = "The Android Open Source Project",
+        .methods            = &consumerir_module_methods,
+    },
+};
diff --git a/modules/gralloc/gralloc.cpp b/modules/gralloc/gralloc.cpp
index 03d46d5..f832f35 100644
--- a/modules/gralloc/gralloc.cpp
+++ b/modules/gralloc/gralloc.cpp
@@ -217,8 +217,6 @@
             bpp = 3;
             break;
         case HAL_PIXEL_FORMAT_RGB_565:
-        case HAL_PIXEL_FORMAT_RGBA_5551:
-        case HAL_PIXEL_FORMAT_RGBA_4444:
         case HAL_PIXEL_FORMAT_RAW_SENSOR:
             bpp = 2;
             break;
diff --git a/tests/camera2/Android.mk b/tests/camera2/Android.mk
index 8f2278a..9efac0f 100644
--- a/tests/camera2/Android.mk
+++ b/tests/camera2/Android.mk
@@ -10,6 +10,7 @@
 	CameraStreamTests.cpp \
 	CameraFrameTests.cpp \
 	CameraBurstTests.cpp \
+	CameraMultiStreamTests.cpp\
 	ForkedTests.cpp \
 	TestForkerEventListener.cpp \
 	TestSettings.cpp \
diff --git a/tests/camera2/CameraBurstTests.cpp b/tests/camera2/CameraBurstTests.cpp
index 5c4b6e7..7301fce 100644
--- a/tests/camera2/CameraBurstTests.cpp
+++ b/tests/camera2/CameraBurstTests.cpp
@@ -19,13 +19,14 @@
 #define LOG_TAG "CameraBurstTest"
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
+#include <utils/Timers.h>
 
 #include <cmath>
 
 #include "CameraStreamFixture.h"
 #include "TestExtensions.h"
 
-#define CAMERA_FRAME_TIMEOUT    1000000000 //nsecs (1 secs)
+#define CAMERA_FRAME_TIMEOUT    1000000000LL //nsecs (1 secs)
 #define CAMERA_HEAP_COUNT       2 //HALBUG: 1 means registerBuffers fails
 #define CAMERA_BURST_DEBUGGING  0
 #define CAMERA_FRAME_BURST_COUNT 10
@@ -37,12 +38,21 @@
 #define CAMERA_EXPOSURE_FORMAT CAMERA_STREAM_AUTO_CPU_FORMAT
 #define CAMERA_EXPOSURE_STARTING 100000 // 1/10ms, up to 51.2ms with 10 steps
 
+#define USEC 1000LL        // in ns
+#define MSEC 1000000LL     // in ns
+#define SEC  1000000000LL  // in ns
+
 #if CAMERA_BURST_DEBUGGING
 #define dout std::cout
 #else
 #define dout if (0) std::cout
 #endif
 
+#define WARN_UNLESS(condition) (!(condition) ? (std::cerr) : (std::ostream(NULL)) << "Warning: ")
+#define WARN_LE(exp, act) WARN_UNLESS((exp) <= (act))
+#define WARN_LT(exp, act) WARN_UNLESS((exp) < (act))
+#define WARN_GT(exp, act) WARN_UNLESS((exp) > (act))
+
 using namespace android;
 using namespace android::camera2;
 
@@ -122,6 +132,23 @@
 
         return acc;
     }
+
+    // Parses a comma-separated string list into a Vector
+    template<typename T>
+    void ParseList(const char *src, Vector<T> &list) {
+        std::istringstream s(src);
+        while (!s.eof()) {
+            char c = s.peek();
+            if (c == ',' || c == ' ') {
+                s.ignore(1, EOF);
+                continue;
+            }
+            T val;
+            s >> val;
+            list.push_back(val);
+        }
+    }
+
 };
 
 TEST_F(CameraBurstTest, ManualExposureControl) {
@@ -161,7 +188,7 @@
     ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
                                                 &previewRequest));
     {
-        Vector<uint8_t> outputStreamIds;
+        Vector<int32_t> outputStreamIds;
         outputStreamIds.push(mStreamId);
         ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
                                             outputStreamIds));
@@ -251,10 +278,447 @@
 
     dout << "max doubling count: " << max_doubling_count << std::endl;
 
-    EXPECT_LE(CAMERA_EXPOSURE_DOUBLING_COUNT, max_doubling_count)
-      << "average brightness should double at least "
-      << CAMERA_EXPOSURE_DOUBLING_COUNT
-      << " times over each consecutive frame as the exposure is doubled";
+    /**
+     * Make this check warning only, since the brightness calculation is not reliable
+     * and we have separate test to cover this case. Plus it is pretty subtle to make
+     * it right without complicating the test too much.
+     */
+    WARN_LE(CAMERA_EXPOSURE_DOUBLING_COUNT, max_doubling_count)
+            << "average brightness should double at least "
+            << CAMERA_EXPOSURE_DOUBLING_COUNT
+            << " times over each consecutive frame as the exposure is doubled"
+            << std::endl;
+}
+
+/**
+ * This test varies exposure time, frame duration, and sensitivity for a
+ * burst of captures. It picks values by default, but the selection can be
+ * overridden with the environment variables
+ *   CAMERA2_TEST_VARIABLE_BURST_EXPOSURE_TIMES
+ *   CAMERA2_TEST_VARIABLE_BURST_FRAME_DURATIONS
+ *   CAMERA2_TEST_VARIABLE_BURST_SENSITIVITIES
+ * which must all be a list of comma-separated values, and each list must be
+ * the same length.  In addition, if the environment variable
+ *   CAMERA2_TEST_VARIABLE_BURST_DUMP_FRAMES
+ * is set to 1, then the YUV buffers are dumped into files named
+ *   "camera2_test_variable_burst_frame_NNN.yuv"
+ *
+ * For example:
+ *   $ setenv CAMERA2_TEST_VARIABLE_BURST_EXPOSURE_TIMES 10000000,20000000
+ *   $ setenv CAMERA2_TEST_VARIABLE_BURST_FRAME_DURATIONS 40000000,40000000
+ *   $ setenv CAMERA2_TEST_VARIABLE_BURST_SENSITIVITIES 200,100
+ *   $ setenv CAMERA2_TEST_VARIABLE_BURST_DUMP_FRAMES 1
+ *   $ /data/nativetest/camera2_test/camera2_test --gtest_filter="*VariableBurst"
+ */
+TEST_F(CameraBurstTest, VariableBurst) {
+
+    TEST_EXTENSION_FORKING_INIT;
+
+    // Bounds for checking frame duration is within range
+    const nsecs_t DURATION_UPPER_BOUND = 10 * MSEC;
+    const nsecs_t DURATION_LOWER_BOUND = 20 * MSEC;
+
+    // Threshold for considering two captures to have equivalent exposure value,
+    // as a ratio of the smaller EV to the larger EV.
+    const float   EV_MATCH_BOUND = 0.95;
+    // Bound for two captures with equivalent exp values to have the same
+    // measured brightness, in 0-255 luminance.
+    const float   BRIGHTNESS_MATCH_BOUND = 5;
+
+    // Environment variables to look for to override test settings
+    const char *expEnv         = "CAMERA2_TEST_VARIABLE_BURST_EXPOSURE_TIMES";
+    const char *durationEnv    = "CAMERA2_TEST_VARIABLE_BURST_FRAME_DURATIONS";
+    const char *sensitivityEnv = "CAMERA2_TEST_VARIABLE_BURST_SENSITIVITIES";
+    const char *dumpFrameEnv   = "CAMERA2_TEST_VARIABLE_BURST_DUMP_FRAMES";
+
+    // Range of valid exposure times, in nanoseconds
+    int64_t minExp = 0, maxExp = 0;
+    // List of valid sensor sensitivities
+    Vector<int32_t> sensitivities;
+    // Range of valid frame durations, in nanoseconds
+    int64_t minDuration = 0, maxDuration = 0;
+
+    {
+        camera_metadata_ro_entry exposureTimeRange =
+            GetStaticEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE);
+
+        EXPECT_EQ(2u, exposureTimeRange.count) << "Bad exposure time range tag."
+                "Using default values";
+        if (exposureTimeRange.count == 2) {
+            minExp = exposureTimeRange.data.i64[0];
+            maxExp = exposureTimeRange.data.i64[1];
+        }
+
+        EXPECT_LT(0, minExp) << "Minimum exposure time is 0";
+        EXPECT_LT(0, maxExp) << "Maximum exposure time is 0";
+        EXPECT_LE(minExp, maxExp) << "Minimum exposure is greater than maximum";
+
+        if (minExp == 0) {
+            minExp = 1 * MSEC; // Fallback minimum exposure time
+        }
+
+        if (maxExp == 0) {
+            maxExp = 10 * SEC; // Fallback maximum exposure time
+        }
+    }
+
+    camera_metadata_ro_entry hardwareLevel =
+        GetStaticEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
+    ASSERT_EQ(1u, hardwareLevel.count);
+    uint8_t level = hardwareLevel.data.u8[0];
+    ASSERT_GE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED);
+    ASSERT_LE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
+    if (level == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) {
+        const ::testing::TestInfo* const test_info =
+            ::testing::UnitTest::GetInstance()->current_test_info();
+        std::cerr << "Skipping test "
+                  << test_info->test_case_name() << "."
+                  << test_info->name()
+                  << " because HAL hardware supported level is limited "
+                  << std::endl;
+        return;
+    }
+
+    dout << "Stream size is " << mWidth << " x " << mHeight << std::endl;
+    dout << "Valid exposure range is: " <<
+            minExp << " - " << maxExp << " ns " << std::endl;
+
+    {
+        camera_metadata_ro_entry sensivityRange =
+            GetStaticEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE);
+        EXPECT_EQ(2u, sensivityRange.count) << "No sensitivity range listed."
+                "Falling back to default set.";
+        int32_t minSensitivity = 100;
+        int32_t maxSensitivity = 800;
+        if (sensivityRange.count == 2) {
+            ASSERT_GT(sensivityRange.data.i32[0], 0);
+            ASSERT_GT(sensivityRange.data.i32[1], 0);
+            minSensitivity = sensivityRange.data.i32[0];
+            maxSensitivity = sensivityRange.data.i32[1];
+        }
+        int32_t count = (maxSensitivity - minSensitivity + 99) / 100;
+        sensitivities.push_back(minSensitivity);
+        for (int i = 1; i < count; i++) {
+            sensitivities.push_back(minSensitivity + i * 100);
+        }
+        sensitivities.push_back(maxSensitivity);
+    }
+
+    dout << "Available sensitivities: ";
+    for (size_t i = 0; i < sensitivities.size(); i++) {
+        dout << sensitivities[i] << " ";
+    }
+    dout << std::endl;
+
+    {
+        camera_metadata_ro_entry availableProcessedSizes =
+                GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
+
+        camera_metadata_ro_entry availableProcessedMinFrameDurations =
+                GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS);
+
+        EXPECT_EQ(availableProcessedSizes.count,
+                availableProcessedMinFrameDurations.count * 2) <<
+                "The number of minimum frame durations doesn't match the number of "
+                "available sizes. Using fallback values";
+
+        if (availableProcessedSizes.count ==
+                availableProcessedMinFrameDurations.count * 2) {
+            bool gotSize = false;
+            for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
+                if (availableProcessedSizes.data.i32[i] == mWidth &&
+                        availableProcessedSizes.data.i32[i+1] == mHeight) {
+                    gotSize = true;
+                    minDuration = availableProcessedMinFrameDurations.data.i64[i/2];
+                }
+            }
+            EXPECT_TRUE(gotSize) << "Can't find stream size in list of "
+                    "available sizes: " << mWidth << ", " << mHeight;
+        }
+        if (minDuration == 0) {
+            minDuration = 1 * SEC / 30; // Fall back to 30 fps as minimum duration
+        }
+
+        ASSERT_LT(0, minDuration);
+
+        camera_metadata_ro_entry maxFrameDuration =
+                GetStaticEntry(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION);
+
+        EXPECT_EQ(1u, maxFrameDuration.count) << "No valid maximum frame duration";
+
+        if (maxFrameDuration.count == 1) {
+            maxDuration = maxFrameDuration.data.i64[0];
+        }
+
+        EXPECT_GT(maxDuration, 0) << "Max duration is 0 or not given, using fallback";
+
+        if (maxDuration == 0) {
+            maxDuration = 10 * SEC; // Fall back to 10 seconds as max duration
+        }
+
+    }
+    dout << "Available frame duration range for configured stream size: "
+         << minDuration << " - " << maxDuration << " ns" << std::endl;
+
+    // Get environment variables if set
+    const char *expVal = getenv(expEnv);
+    const char *durationVal = getenv(durationEnv);
+    const char *sensitivityVal = getenv(sensitivityEnv);
+
+    bool gotExp = (expVal != NULL);
+    bool gotDuration = (durationVal != NULL);
+    bool gotSensitivity = (sensitivityVal != NULL);
+
+    // All or none must be provided if using override envs
+    ASSERT_TRUE( (gotDuration && gotExp && gotSensitivity) ||
+            (!gotDuration && !gotExp && !gotSensitivity) ) <<
+            "Incomplete set of environment variable overrides provided";
+
+    Vector<int64_t> expList, durationList;
+    Vector<int32_t> sensitivityList;
+    if (gotExp) {
+        ParseList(expVal, expList);
+        ParseList(durationVal, durationList);
+        ParseList(sensitivityVal, sensitivityList);
+
+        ASSERT_TRUE(
+            (expList.size() == durationList.size()) &&
+            (durationList.size() == sensitivityList.size())) <<
+                "Mismatched sizes in env lists, or parse error";
+
+        dout << "Using burst list from environment with " << expList.size() <<
+                " captures" << std::endl;
+    } else {
+        // Create a default set of controls based on the available ranges
+
+        int64_t e;
+        int64_t d;
+        int32_t s;
+
+        // Exposure ramp
+
+        e = minExp;
+        d = minDuration;
+        s = sensitivities[0];
+        while (e < maxExp) {
+            expList.push_back(e);
+            durationList.push_back(d);
+            sensitivityList.push_back(s);
+            e = e * 2;
+        }
+        e = maxExp;
+        expList.push_back(e);
+        durationList.push_back(d);
+        sensitivityList.push_back(s);
+
+        // Duration ramp
+
+        e = 30 * MSEC;
+        d = minDuration;
+        s = sensitivities[0];
+        while (d < maxDuration) {
+            // make sure exposure <= frame duration
+            expList.push_back(e > d ? d : e);
+            durationList.push_back(d);
+            sensitivityList.push_back(s);
+            d = d * 2;
+        }
+
+        // Sensitivity ramp
+
+        e = 30 * MSEC;
+        d = 30 * MSEC;
+        d = d > minDuration ? d : minDuration;
+        for (size_t i = 0; i < sensitivities.size(); i++) {
+            expList.push_back(e);
+            durationList.push_back(d);
+            sensitivityList.push_back(sensitivities[i]);
+        }
+
+        // Constant-EV ramp, duration == exposure
+
+        e = 30 * MSEC; // at ISO 100
+        for (size_t i = 0; i < sensitivities.size(); i++) {
+            int64_t e_adj = e * 100 / sensitivities[i];
+            expList.push_back(e_adj);
+            durationList.push_back(e_adj > minDuration ? e_adj : minDuration);
+            sensitivityList.push_back(sensitivities[i]);
+        }
+
+        dout << "Default burst sequence created with " << expList.size() <<
+                " entries" << std::endl;
+    }
+
+    // Validate the list, but warn only
+    for (size_t i = 0; i < expList.size(); i++) {
+        EXPECT_GE(maxExp, expList[i])
+                << "Capture " << i << " exposure too long: " << expList[i];
+        EXPECT_LE(minExp, expList[i])
+                << "Capture " << i << " exposure too short: " << expList[i];
+        EXPECT_GE(maxDuration, durationList[i])
+                << "Capture " << i << " duration too long: " << durationList[i];
+        EXPECT_LE(minDuration, durationList[i])
+                 << "Capture " << i << " duration too short: "  << durationList[i];
+        bool validSensitivity = false;
+        for (size_t j = 0; j < sensitivities.size(); j++) {
+            if (sensitivityList[i] == sensitivities[j]) {
+                validSensitivity = true;
+                break;
+            }
+        }
+        EXPECT_TRUE(validSensitivity)
+                << "Capture " << i << " sensitivity not in list: " << sensitivityList[i];
+    }
+
+    // Check if debug yuv dumps are requested
+
+    bool dumpFrames = false;
+    {
+        const char *frameDumpVal = getenv(dumpFrameEnv);
+        if (frameDumpVal != NULL) {
+            if (frameDumpVal[0] == '1') dumpFrames = true;
+        }
+    }
+
+    dout << "Dumping YUV frames " <<
+            (dumpFrames ? "enabled, not checking timing" : "disabled") << std::endl;
+
+    // Create a base preview request, turning off all 3A
+    CameraMetadata previewRequest;
+    ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
+                                                &previewRequest));
+    {
+        Vector<int32_t> outputStreamIds;
+        outputStreamIds.push(mStreamId);
+        ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
+                                            outputStreamIds));
+
+        // Disable all 3A routines
+        uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
+        ASSERT_EQ(OK, previewRequest.update(ANDROID_CONTROL_MODE,
+                                            &cmOff, 1));
+
+        int requestId = 1;
+        ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID,
+                                            &requestId, 1));
+    }
+
+    // Submit capture requests
+
+    for (size_t i = 0; i < expList.size(); ++i) {
+        CameraMetadata tmpRequest = previewRequest;
+        ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_EXPOSURE_TIME,
+                                        &expList[i], 1));
+        ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_FRAME_DURATION,
+                                        &durationList[i], 1));
+        ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_SENSITIVITY,
+                                        &sensitivityList[i], 1));
+        ALOGV("Submitting capture %d with exposure %lld, frame duration %lld, sensitivity %d",
+                i, expList[i], durationList[i], sensitivityList[i]);
+        dout << "Capture request " << i <<
+                ": exposure is " << (expList[i]/1e6f) << " ms" <<
+                ", frame duration is " << (durationList[i]/1e6f) << " ms" <<
+                ", sensitivity is " << sensitivityList[i] <<
+                std::endl;
+        ASSERT_EQ(OK, mDevice->capture(tmpRequest));
+    }
+
+    Vector<float> brightnesses;
+    Vector<nsecs_t> captureTimes;
+    brightnesses.setCapacity(expList.size());
+    captureTimes.setCapacity(expList.size());
+
+    // Get each frame (metadata) and then the buffer. Calculate brightness.
+    for (size_t i = 0; i < expList.size(); ++i) {
+
+        ALOGV("Reading request %d", i);
+        dout << "Waiting for capture " << i << ": " <<
+                " exposure " << (expList[i]/1e6f) << " ms," <<
+                " frame duration " << (durationList[i]/1e6f) << " ms," <<
+                " sensitivity " << sensitivityList[i] <<
+                std::endl;
+
+        // Set wait limit based on expected frame duration, or minimum timeout
+        int64_t waitLimit = CAMERA_FRAME_TIMEOUT;
+        if (expList[i] * 2 > waitLimit) waitLimit = expList[i] * 2;
+        if (durationList[i] * 2 > waitLimit) waitLimit = durationList[i] * 2;
+
+        ASSERT_EQ(OK, mDevice->waitForNextFrame(waitLimit));
+        ALOGV("Reading capture request-1 %d", i);
+        CameraMetadata frameMetadata;
+        ASSERT_EQ(OK, mDevice->getNextFrame(&frameMetadata));
+        ALOGV("Reading capture request-2 %d", i);
+
+        ASSERT_EQ(OK, mFrameListener->waitForFrame(CAMERA_FRAME_TIMEOUT));
+        ALOGV("We got the frame now");
+
+        captureTimes.push_back(systemTime());
+
+        CpuConsumer::LockedBuffer imgBuffer;
+        ASSERT_EQ(OK, mCpuConsumer->lockNextBuffer(&imgBuffer));
+
+        int underexposed, overexposed;
+        float avgBrightness = 0;
+        long long brightness = TotalBrightness(imgBuffer, &underexposed,
+                                               &overexposed);
+        int numValidPixels = mWidth * mHeight - (underexposed + overexposed);
+        if (numValidPixels != 0) {
+            avgBrightness = brightness * 1.0f / numValidPixels;
+        } else if (underexposed < overexposed) {
+            avgBrightness = 255;
+        }
+
+        ALOGV("Total brightness for frame %d was %lld (underexposed %d, "
+              "overexposed %d), avg %f", i, brightness, underexposed,
+              overexposed, avgBrightness);
+        dout << "Average brightness (frame " << i << ") was " << avgBrightness
+             << " (underexposed " << underexposed << ", overexposed "
+             << overexposed << ")" << std::endl;
+        brightnesses.push_back(avgBrightness);
+
+        if (i != 0) {
+            float prevEv = static_cast<float>(expList[i - 1]) * sensitivityList[i - 1];
+            float currentEv = static_cast<float>(expList[i]) * sensitivityList[i];
+            float evRatio = (prevEv > currentEv) ? (currentEv / prevEv) :
+                    (prevEv / currentEv);
+            if ( evRatio > EV_MATCH_BOUND ) {
+                WARN_LT(fabs(brightnesses[i] - brightnesses[i - 1]),
+                        BRIGHTNESS_MATCH_BOUND) <<
+                        "Capture brightness different from previous, even though "
+                        "they have the same EV value. Ev now: " << currentEv <<
+                        ", previous: " << prevEv << ". Brightness now: " <<
+                        brightnesses[i] << ", previous: " << brightnesses[i-1] <<
+                        std::endl;
+            }
+            // Only check timing if not saving to disk, since that slows things
+            // down substantially
+            if (!dumpFrames) {
+                nsecs_t timeDelta = captureTimes[i] - captureTimes[i-1];
+                nsecs_t expectedDelta = expList[i] > durationList[i] ?
+                        expList[i] : durationList[i];
+                WARN_LT(timeDelta, expectedDelta + DURATION_UPPER_BOUND) <<
+                        "Capture took " << timeDelta << " ns to receive, but expected"
+                        " frame duration was " << expectedDelta << " ns." <<
+                        std::endl;
+                WARN_GT(timeDelta, expectedDelta - DURATION_LOWER_BOUND) <<
+                        "Capture took " << timeDelta << " ns to receive, but expected"
+                        " frame duration was " << expectedDelta << " ns." <<
+                        std::endl;
+                dout << "Time delta from previous frame: " << timeDelta / 1e6 <<
+                        " ms.  Expected " << expectedDelta / 1e6 << " ms" << std::endl;
+            }
+        }
+
+        if (dumpFrames) {
+            String8 dumpName =
+                    String8::format("/data/local/tmp/camera2_test_variable_burst_frame_%03d.yuv", i);
+            dout << "  Writing YUV dump to " << dumpName << std::endl;
+            DumpYuvToFile(dumpName, imgBuffer);
+        }
+
+        ASSERT_EQ(OK, mCpuConsumer->unlockBuffer(imgBuffer));
+    }
+
 }
 
 }
diff --git a/tests/camera2/CameraFrameTests.cpp b/tests/camera2/CameraFrameTests.cpp
index 8445098..e78a862 100644
--- a/tests/camera2/CameraFrameTests.cpp
+++ b/tests/camera2/CameraFrameTests.cpp
@@ -23,9 +23,8 @@
 #include "hardware/hardware.h"
 #include "hardware/camera2.h"
 
-#include "CameraDeviceBase.h"
-#include "utils/StrongPointer.h"
-
+#include <common/CameraDeviceBase.h>
+#include <utils/StrongPointer.h>
 #include <gui/CpuConsumer.h>
 #include <gui/Surface.h>
 
@@ -91,7 +90,7 @@
     ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
                                                 &previewRequest));
     {
-        Vector<uint8_t> outputStreamIds;
+        Vector<int32_t> outputStreamIds;
         outputStreamIds.push(mStreamId);
         ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
                                             outputStreamIds));
diff --git a/tests/camera2/CameraMetadataTests.cpp b/tests/camera2/CameraMetadataTests.cpp
index 66c4847..eddc593 100644
--- a/tests/camera2/CameraMetadataTests.cpp
+++ b/tests/camera2/CameraMetadataTests.cpp
@@ -25,7 +25,7 @@
 #include "hardware/hardware.h"
 #include "hardware/camera2.h"
 
-#include "CameraDeviceBase.h"
+#include "common/CameraDeviceBase.h"
 #include "utils/StrongPointer.h"
 
 #include <gui/CpuConsumer.h>
@@ -136,10 +136,6 @@
 
     EXPECT_TRUE(
         HasElementInArrayFromStaticTag(ANDROID_SCALER_AVAILABLE_FORMATS,
-                                      HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED));
-
-    EXPECT_TRUE(
-        HasElementInArrayFromStaticTag(ANDROID_SCALER_AVAILABLE_FORMATS,
                                        HAL_PIXEL_FORMAT_BLOB)); // JPEG
 
     if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_0) {
@@ -169,9 +165,11 @@
     // Iff there are listed raw resolutions, the format should be available
     int rawResolutionsCount =
             GetEntryCountFromStaticTag(ANDROID_SCALER_AVAILABLE_RAW_SIZES);
-    EXPECT_EQ(rawResolutionsCount > 0,
-        HasElementInArrayFromStaticTag(ANDROID_SCALER_AVAILABLE_FORMATS,
-                                        HAL_PIXEL_FORMAT_RAW_SENSOR));
+    if (rawResolutionsCount > 0) {
+        EXPECT_TRUE(
+            HasElementInArrayFromStaticTag(ANDROID_SCALER_AVAILABLE_FORMATS,
+                    HAL_PIXEL_FORMAT_RAW_SENSOR));
+    }
 
     // Required processed sizes.
     int processedSizeCount =
diff --git a/tests/camera2/CameraModuleFixture.h b/tests/camera2/CameraModuleFixture.h
index ef4a9a5..acf41e1 100644
--- a/tests/camera2/CameraModuleFixture.h
+++ b/tests/camera2/CameraModuleFixture.h
@@ -22,8 +22,9 @@
 #include "hardware/hardware.h"
 #include "hardware/camera2.h"
 
-#include "Camera2Device.h"
-#include "Camera3Device.h"
+#include <device2/Camera2Device.h>
+#include <device3/Camera3Device.h>
+
 #include "camera2_utils.h"
 #include "TestExtensions.h"
 
diff --git a/tests/camera2/CameraModuleTests.cpp b/tests/camera2/CameraModuleTests.cpp
index 44d3e3b..ae4267b 100644
--- a/tests/camera2/CameraModuleTests.cpp
+++ b/tests/camera2/CameraModuleTests.cpp
@@ -19,12 +19,12 @@
 #define LOG_TAG "CameraModuleTest"
 #define LOG_NDEBUG 0
 #include <utils/Log.h>
+#include <utils/StrongPointer.h>
+#include <common/CameraDeviceBase.h>
 
 #include "hardware/hardware.h"
 #include "hardware/camera2.h"
 
-#include "CameraDeviceBase.h"
-#include "utils/StrongPointer.h"
 #include "CameraModuleFixture.h"
 
 namespace android {
@@ -78,17 +78,19 @@
     TEST_EXTENSION_FORKING_INIT;
 
     int idx[] = { -1, mNumberOfCameras, mNumberOfCameras + 1 };
+    hw_device_t *device = NULL;
 
     for (unsigned i = 0; i < sizeof(idx)/sizeof(idx[0]); ++i) {
-        // Since the initialization should fail at device open(), it doesn't
-        // matter which version of CameraNDevice is used here
-        mDevice = new Camera2Device(idx[i]);
-        status_t deviceInitializeCode = initializeDevice(idx[i]);
-        EXPECT_NE(OK, deviceInitializeCode);
-        EXPECT_EQ(-ENODEV, deviceInitializeCode)
-            << "Incorrect error code when trying to initialize invalid index "
-            << idx[i];
-        mDevice.clear();
+        String8 deviceName = String8::format("%d", idx[i]);
+        status_t res =
+                mModule->common.methods->open(
+                                             &mModule->common,
+                                             deviceName,
+                                             &device);
+        EXPECT_NE(OK, res);
+        EXPECT_EQ(-ENODEV, res)
+            << "Incorrect error code when trying to open camera with invalid id "
+            << deviceName;
     }
 }
 
diff --git a/tests/camera2/CameraMultiStreamTests.cpp b/tests/camera2/CameraMultiStreamTests.cpp
new file mode 100644
index 0000000..de1cfd6
--- /dev/null
+++ b/tests/camera2/CameraMultiStreamTests.cpp
@@ -0,0 +1,683 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CameraMultiStreamTest"
+//#define LOG_NDEBUG 0
+#include "CameraStreamFixture.h"
+#include "TestExtensions.h"
+
+#include <gtest/gtest.h>
+#include <utils/Log.h>
+#include <utils/StrongPointer.h>
+#include <common/CameraDeviceBase.h>
+#include <hardware/hardware.h>
+#include <hardware/camera2.h>
+#include <gui/SurfaceComposerClient.h>
+#include <gui/Surface.h>
+
+#define DEFAULT_FRAME_DURATION 33000000LL // 33ms
+#define CAMERA_HEAP_COUNT       1
+#define CAMERA_EXPOSURE_FORMAT CAMERA_STREAM_AUTO_CPU_FORMAT
+#define CAMERA_DISPLAY_FORMAT HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
+#define CAMERA_MULTI_STREAM_DEBUGGING  0
+#define CAMERA_FRAME_TIMEOUT    1000000000LL // nsecs (1 secs)
+#define PREVIEW_RENDERING_TIME_INTERVAL 200000 // in unit of us, 200ms
+#define TOLERANCE_MARGIN 0.01 // 1% tolerance margin for exposure sanity check.
+/* constants for display */
+#define DISPLAY_BUFFER_HEIGHT 1024
+#define DISPLAY_BUFFER_WIDTH 1024
+#define DISPLAY_BUFFER_FORMAT PIXEL_FORMAT_RGB_888
+
+// This test intends to test large preview size but less than 1080p.
+#define PREVIEW_WIDTH_CAP   1920
+#define PREVIEW_HEIGHT_CAP  1080
+// This test intends to test small metering burst size that is less than 640x480
+#define METERING_WIDTH_CAP  640
+#define METERING_HEIGHT_CAP 480
+
+#define EXP_WAIT_MULTIPLIER 2
+
+namespace android {
+namespace camera2 {
+namespace tests {
+
+static const CameraStreamParams DEFAULT_STREAM_PARAMETERS = {
+    /*mFormat*/     CAMERA_EXPOSURE_FORMAT,
+    /*mHeapCount*/  CAMERA_HEAP_COUNT
+};
+
+static const CameraStreamParams DISPLAY_STREAM_PARAMETERS = {
+    /*mFormat*/     CAMERA_DISPLAY_FORMAT,
+    /*mHeapCount*/  CAMERA_HEAP_COUNT
+};
+
+class CameraMultiStreamTest
+    : public ::testing::Test,
+      public CameraStreamFixture {
+
+public:
+    CameraMultiStreamTest() : CameraStreamFixture(DEFAULT_STREAM_PARAMETERS) {
+        TEST_EXTENSION_FORKING_CONSTRUCTOR;
+
+        if (HasFatalFailure()) {
+            return;
+        }
+        /**
+         * Don't create default stream, each test is in charge of creating
+         * its own streams.
+         */
+    }
+
+    ~CameraMultiStreamTest() {
+        TEST_EXTENSION_FORKING_DESTRUCTOR;
+    }
+
+    sp<SurfaceComposerClient> mComposerClient;
+    sp<SurfaceControl> mSurfaceControl;
+
+    void CreateOnScreenSurface(sp<ANativeWindow>& surface) {
+        mComposerClient = new SurfaceComposerClient;
+        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
+
+        mSurfaceControl = mComposerClient->createSurface(
+                String8("CameraMultiStreamTest StreamingImage Surface"),
+                DISPLAY_BUFFER_HEIGHT, DISPLAY_BUFFER_WIDTH,
+                DISPLAY_BUFFER_FORMAT, 0);
+
+        ASSERT_NE((void*)NULL, mSurfaceControl.get());
+        ASSERT_TRUE(mSurfaceControl->isValid());
+
+        SurfaceComposerClient::openGlobalTransaction();
+        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
+        ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
+        SurfaceComposerClient::closeGlobalTransaction();
+
+        surface = mSurfaceControl->getSurface();
+
+        ASSERT_NE((void*)NULL, surface.get());
+    }
+
+    struct Size {
+        int32_t width;
+        int32_t height;
+    };
+
+    // Select minimal size by number of pixels.
+    void GetMinSize(const int32_t* data, size_t count,
+            Size* min, int32_t* idx) {
+        ASSERT_NE((int32_t*)NULL, data);
+        int32_t minIdx = 0;
+        int32_t minSize = INT_MAX, tempSize;
+        for (size_t i = 0; i < count; i+=2) {
+            tempSize = data[i] * data[i+1];
+            if (minSize > tempSize) {
+                minSize = tempSize;
+                minIdx = i;
+            }
+        }
+        min->width = data[minIdx];
+        min->height = data[minIdx + 1];
+        *idx = minIdx;
+    }
+
+    // Select maximal size by number of pixels.
+    void GetMaxSize(const int32_t* data, size_t count,
+            Size* max, int32_t* idx) {
+        ASSERT_NE((int32_t*)NULL, data);
+        int32_t maxIdx = 0;
+        int32_t maxSize = INT_MIN, tempSize;
+        for (size_t i = 0; i < count; i+=2) {
+            tempSize = data[i] * data[i+1];
+            if (maxSize < tempSize) {
+                maxSize = tempSize;
+                maxIdx = i;
+            }
+        }
+        max->width = data[maxIdx];
+        max->height = data[maxIdx + 1];
+        *idx = maxIdx;
+    }
+
+    // Cap size by number of pixels.
+    Size CapSize(Size cap, Size input) {
+        if (input.width * input.height > cap.width * cap.height) {
+            return cap;
+        }
+        return input;
+    }
+
+    struct CameraStream : public RefBase {
+
+    public:
+        /**
+         * Only initialize the variables here, do the ASSERT check in
+         * SetUp function. To make this stream useful, the SetUp must
+         * be called before using it.
+         */
+        CameraStream(
+                int width,
+                int height,
+                const sp<CameraDeviceBase>& device,
+                CameraStreamParams param, sp<ANativeWindow> surface,
+                bool useCpuConsumer)
+            : mDevice(device),
+              mWidth(width),
+              mHeight(height) {
+            mFormat = param.mFormat;
+            if (useCpuConsumer) {
+                sp<BufferQueue> bq = new BufferQueue();
+                mCpuConsumer = new CpuConsumer(bq, param.mHeapCount);
+                mCpuConsumer->setName(String8(
+                        "CameraMultiStreamTest::mCpuConsumer"));
+                mNativeWindow = new Surface(bq);
+            } else {
+                // Render the stream to screen.
+                mCpuConsumer = NULL;
+                mNativeWindow = surface;
+            }
+
+            mFrameListener = new FrameListener();
+            if (mCpuConsumer != 0) {
+                mCpuConsumer->setFrameAvailableListener(mFrameListener);
+            }
+        }
+
+        /**
+         * Finally create camera stream, and do the ASSERT check, since we
+         * can not do it in ctor.
+         */
+        void SetUp() {
+            ASSERT_EQ(OK,
+                mDevice->createStream(mNativeWindow,
+                    mWidth, mHeight, mFormat, /*size (for jpegs)*/0,
+                    &mStreamId));
+
+            ASSERT_NE(-1, mStreamId);
+        }
+
+        int GetStreamId() { return mStreamId; }
+        sp<CpuConsumer> GetConsumer() { return mCpuConsumer; }
+        sp<FrameListener> GetFrameListener() { return mFrameListener; }
+
+    protected:
+        ~CameraStream() {
+            if (mDevice.get()) {
+                mDevice->waitUntilDrained();
+                mDevice->deleteStream(mStreamId);
+            }
+            // Clear producer before consumer.
+            mNativeWindow.clear();
+            mCpuConsumer.clear();
+        }
+
+    private:
+        sp<FrameListener>       mFrameListener;
+        sp<CpuConsumer>         mCpuConsumer;
+        sp<ANativeWindow>       mNativeWindow;
+        sp<CameraDeviceBase>    mDevice;
+        int                     mStreamId;
+        int                     mWidth;
+        int                     mHeight;
+        int                     mFormat;
+    };
+
+    int64_t GetExposureValue(const CameraMetadata& metaData) {
+        camera_metadata_ro_entry_t entry =
+                metaData.find(ANDROID_SENSOR_EXPOSURE_TIME);
+        EXPECT_EQ(1u, entry.count);
+        if (entry.count == 1) {
+            return entry.data.i64[0];
+        }
+        return -1;
+    }
+
+    int32_t GetSensitivity(const CameraMetadata& metaData) {
+        camera_metadata_ro_entry_t entry =
+                metaData.find(ANDROID_SENSOR_SENSITIVITY);
+        EXPECT_EQ(1u, entry.count);
+        if (entry.count == 1) {
+            return entry.data.i32[0];
+        }
+        return -1;
+    }
+
+    int64_t GetFrameDuration(const CameraMetadata& metaData) {
+        camera_metadata_ro_entry_t entry =
+                metaData.find(ANDROID_SENSOR_FRAME_DURATION);
+        EXPECT_EQ(1u, entry.count);
+        if (entry.count == 1) {
+            return entry.data.i64[0];
+        }
+        return -1;
+    }
+
+    void CreateRequests(CameraMetadata& previewRequest,
+            CameraMetadata& meteringRequest,
+            CameraMetadata& captureRequest,
+            int previewStreamId,
+            int meteringStreamId,
+            int captureStreamId) {
+        int32_t requestId = 0;
+        Vector<int32_t> previewStreamIds;
+        previewStreamIds.push(previewStreamId);
+        ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
+                &previewRequest));
+        ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
+                previewStreamIds));
+        ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID,
+                &requestId, 1));
+
+        // Create metering request, manual settings
+        // Manual control: Disable 3A, noise reduction, edge sharping
+        uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
+        uint8_t nrOff = static_cast<uint8_t>(ANDROID_NOISE_REDUCTION_MODE_OFF);
+        uint8_t sharpOff = static_cast<uint8_t>(ANDROID_EDGE_MODE_OFF);
+        Vector<int32_t> meteringStreamIds;
+        meteringStreamIds.push(meteringStreamId);
+        ASSERT_EQ(OK, mDevice->createDefaultRequest(
+                CAMERA2_TEMPLATE_PREVIEW,
+                &meteringRequest));
+        ASSERT_EQ(OK, meteringRequest.update(
+                ANDROID_REQUEST_OUTPUT_STREAMS,
+                meteringStreamIds));
+        ASSERT_EQ(OK, meteringRequest.update(
+                ANDROID_CONTROL_MODE,
+                &cmOff, 1));
+        ASSERT_EQ(OK, meteringRequest.update(
+                ANDROID_NOISE_REDUCTION_MODE,
+                &nrOff, 1));
+        ASSERT_EQ(OK, meteringRequest.update(
+                ANDROID_EDGE_MODE,
+                &sharpOff, 1));
+
+        // Create capture request, manual settings
+        Vector<int32_t> captureStreamIds;
+        captureStreamIds.push(captureStreamId);
+        ASSERT_EQ(OK, mDevice->createDefaultRequest(
+                CAMERA2_TEMPLATE_PREVIEW,
+                &captureRequest));
+        ASSERT_EQ(OK, captureRequest.update(
+                ANDROID_REQUEST_OUTPUT_STREAMS,
+                captureStreamIds));
+        ASSERT_EQ(OK, captureRequest.update(
+                ANDROID_CONTROL_MODE,
+                &cmOff, 1));
+        ASSERT_EQ(OK, captureRequest.update(
+                ANDROID_NOISE_REDUCTION_MODE,
+                &nrOff, 1));
+        ASSERT_EQ(OK, captureRequest.update(
+                ANDROID_EDGE_MODE,
+                &sharpOff, 1));
+    }
+
+    sp<CameraStream> CreateStream(
+            int width,
+            int height,
+            const sp<CameraDeviceBase>& device,
+            CameraStreamParams param = DEFAULT_STREAM_PARAMETERS,
+            sp<ANativeWindow> surface = NULL,
+            bool useCpuConsumer = true) {
+        param.mFormat = MapAutoFormat(param.mFormat);
+        return new CameraStream(width, height, device,
+                param, surface, useCpuConsumer);
+    }
+
+    void CaptureBurst(CameraMetadata& request, size_t requestCount,
+            const Vector<int64_t>& exposures,
+            const Vector<int32_t>& sensitivities,
+            const sp<CameraStream>& stream,
+            int64_t minFrameDuration,
+            int32_t* requestIdStart) {
+        ASSERT_EQ(OK, request.update(ANDROID_SENSOR_FRAME_DURATION,
+                &minFrameDuration, 1));
+        // Submit a series of requests with the specified exposure/gain values.
+        int32_t targetRequestId = *requestIdStart;
+        for (size_t i = 0; i < requestCount; i++) {
+            ASSERT_EQ(OK, request.update(ANDROID_REQUEST_ID, requestIdStart, 1));
+            ASSERT_EQ(OK, request.update(ANDROID_SENSOR_EXPOSURE_TIME, &exposures[i], 1));
+            ASSERT_EQ(OK, request.update(ANDROID_SENSOR_SENSITIVITY, &sensitivities[i], 1));
+            ASSERT_EQ(OK, mDevice->capture(request));
+            ALOGV("Submitting request with: id %d with exposure %lld, sensitivity %d",
+                    *requestIdStart, exposures[i], sensitivities[i]);
+            if (CAMERA_MULTI_STREAM_DEBUGGING) {
+                request.dump(STDOUT_FILENO);
+            }
+            (*requestIdStart)++;
+        }
+        // Get capture burst results.
+        Vector<nsecs_t> captureBurstTimes;
+        sp<CpuConsumer> consumer = stream->GetConsumer();
+        sp<FrameListener> listener = stream->GetFrameListener();
+
+        // Set wait limit based on expected frame duration.
+        int64_t waitLimit = CAMERA_FRAME_TIMEOUT;
+        for (size_t i = 0; i < requestCount; i++) {
+            ALOGV("Reading request result %d", i);
+
+            /**
+             * Raise the timeout to be at least twice as long as the exposure
+             * time. to avoid a false positive when the timeout is too short.
+             */
+            if ((exposures[i] * EXP_WAIT_MULTIPLIER) > waitLimit) {
+                waitLimit = exposures[i] * EXP_WAIT_MULTIPLIER;
+            }
+
+            CameraMetadata frameMetadata;
+            int32_t resultRequestId;
+            do {
+                ASSERT_EQ(OK, mDevice->waitForNextFrame(waitLimit));
+                ASSERT_EQ(OK, mDevice->getNextFrame(&frameMetadata));
+
+                camera_metadata_entry_t resultEntry = frameMetadata.find(ANDROID_REQUEST_ID);
+                ASSERT_EQ(1u, resultEntry.count);
+                resultRequestId = resultEntry.data.i32[0];
+                if (CAMERA_MULTI_STREAM_DEBUGGING) {
+                    std::cout << "capture result req id: " << resultRequestId << std::endl;
+                }
+            } while (resultRequestId != targetRequestId);
+            targetRequestId++;
+            ALOGV("Got capture burst result for request %d", i);
+
+            // Validate capture result
+            if (CAMERA_MULTI_STREAM_DEBUGGING) {
+                frameMetadata.dump(STDOUT_FILENO);
+            }
+
+            // TODO: Need revisit it to figure out an accurate margin.
+            int64_t resultExposure = GetExposureValue(frameMetadata);
+            int32_t resultSensitivity = GetSensitivity(frameMetadata);
+            EXPECT_LE(sensitivities[i] * (1.0 - TOLERANCE_MARGIN), resultSensitivity);
+            EXPECT_GE(sensitivities[i] * (1.0 + TOLERANCE_MARGIN), resultSensitivity);
+            EXPECT_LE(exposures[i] * (1.0 - TOLERANCE_MARGIN), resultExposure);
+            EXPECT_GE(exposures[i] * (1.0 + TOLERANCE_MARGIN), resultExposure);
+
+            ASSERT_EQ(OK, listener->waitForFrame(waitLimit));
+            captureBurstTimes.push_back(systemTime());
+            CpuConsumer::LockedBuffer imgBuffer;
+            ASSERT_EQ(OK, consumer->lockNextBuffer(&imgBuffer));
+            ALOGV("Got capture buffer for request %d", i);
+
+            /**
+             * TODO: Validate capture buffer. Current brightness calculation
+             * is too slow, it also doesn't account for saturation effects,
+             * which is quite common since we are going over a significant
+             * range of EVs. we need figure out some reliable way to validate
+             * buffer data.
+             */
+
+            ASSERT_EQ(OK, consumer->unlockBuffer(imgBuffer));
+            if (i > 0) {
+                nsecs_t timeDelta =
+                        captureBurstTimes[i] - captureBurstTimes[i-1];
+                EXPECT_GE(timeDelta, exposures[i]);
+            }
+        }
+    }
+
+    /**
+     * Intentionally shadow default CreateStream function from base class,
+     * because we don't want any test in this class to use the default
+     * stream creation function.
+     */
+    void CreateStream() {
+    }
+};
+
+/**
+ * This test adds multiple stream use case test, basically, test 3
+ * streams:
+ *
+ * 1. Preview stream, with large size that is no bigger than 1080p
+ * we render this stream to display and vary the exposure time for
+ * for certain amount of time for visualization purpose.
+ *
+ * 2. Metering stream, with small size that is no bigger than VGA size.
+ * a burst is issued for different exposure times and analog gains
+ * (or analog gain implemented sensitivities) then check if the capture
+ * result metadata matches the request.
+ *
+ * 3. Capture stream, this is basically similar as meterting stream, but
+ * has large size, which is the largest supported JPEG capture size.
+ *
+ * This multiple stream test is to test if HAL supports:
+ *
+ * 1. Multiple streams like above, HAL should support at least 3 streams
+ * concurrently: one preview stream, 2 other YUV stream.
+ *
+ * 2. Manual control(gain/exposure) of mutiple burst capture.
+ */
+TEST_F(CameraMultiStreamTest, MultiBurst) {
+
+    TEST_EXTENSION_FORKING_INIT;
+
+    camera_metadata_ro_entry availableProcessedSizes =
+        GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
+    ASSERT_EQ(0u, availableProcessedSizes.count % 2);
+    ASSERT_GE(availableProcessedSizes.count, 2u);
+    camera_metadata_ro_entry availableProcessedMinFrameDurations =
+        GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS);
+    EXPECT_EQ(availableProcessedSizes.count,
+        availableProcessedMinFrameDurations.count * 2);
+
+    camera_metadata_ro_entry availableJpegSizes =
+        GetStaticEntry(ANDROID_SCALER_AVAILABLE_JPEG_SIZES);
+    ASSERT_EQ(0u, availableJpegSizes.count % 2);
+    ASSERT_GE(availableJpegSizes.count, 2u);
+
+    camera_metadata_ro_entry hardwareLevel =
+        GetStaticEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
+    ASSERT_EQ(1u, hardwareLevel.count);
+    uint8_t level = hardwareLevel.data.u8[0];
+    ASSERT_GE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED);
+    ASSERT_LE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
+    if (level == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) {
+        const ::testing::TestInfo* const test_info =
+            ::testing::UnitTest::GetInstance()->current_test_info();
+        std::cerr << "Skipping test "
+                  << test_info->test_case_name() << "."
+                  << test_info->name()
+                  << " because HAL hardware supported level is limited "
+                  << std::endl;
+        return;
+    }
+
+    // Find the right sizes for preview, metering, and capture streams
+    // assumes at least 2 entries in availableProcessedSizes.
+    int64_t minFrameDuration = DEFAULT_FRAME_DURATION;
+    Size processedMinSize, processedMaxSize, jpegMaxSize;
+    const int32_t* data = availableProcessedSizes.data.i32;
+    size_t count = availableProcessedSizes.count;
+
+    int32_t minIdx, maxIdx;
+    GetMinSize(data, count, &processedMinSize, &minIdx);
+    GetMaxSize(data, count, &processedMaxSize, &maxIdx);
+    ALOGV("Found processed max size: %dx%d, min size = %dx%d",
+            processedMaxSize.width, processedMaxSize.height,
+            processedMinSize.width, processedMinSize.height);
+
+    if (availableProcessedSizes.count ==
+        availableProcessedMinFrameDurations.count * 2) {
+        minFrameDuration =
+            availableProcessedMinFrameDurations.data.i64[maxIdx / 2];
+    }
+
+    EXPECT_GT(minFrameDuration, 0);
+
+    if (minFrameDuration <= 0) {
+        minFrameDuration = DEFAULT_FRAME_DURATION;
+    }
+
+    ALOGV("targeted minimal frame duration is: %lldns", minFrameDuration);
+
+    data = &(availableJpegSizes.data.i32[0]);
+    count = availableJpegSizes.count;
+    GetMaxSize(data, count, &jpegMaxSize, &maxIdx);
+    ALOGV("Found Jpeg size max idx = %d", maxIdx);
+
+    // Max Jpeg size should be available in processed sizes. Use it for
+    // YUV capture anyway.
+    EXPECT_EQ(processedMaxSize.width, jpegMaxSize.width);
+    EXPECT_EQ(processedMaxSize.height, jpegMaxSize.height);
+
+    // Cap preview size.
+    Size previewLimit = { PREVIEW_WIDTH_CAP, PREVIEW_HEIGHT_CAP };
+    // FIXME: need make sure the previewLimit is supported by HAL.
+    Size previewSize = CapSize(previewLimit, processedMaxSize);
+    // Cap Metering size.
+    Size meteringLimit = { METERING_WIDTH_CAP, METERING_HEIGHT_CAP };
+    // Cap metering size to VGA (VGA is mandatory by CDD)
+    Size meteringSize = CapSize(meteringLimit, processedMinSize);
+    // Capture stream should be the max size of jpeg sizes.
+    ALOGV("preview size: %dx%d, metering size: %dx%d, capture size: %dx%d",
+            previewSize.width, previewSize.height,
+            meteringSize.width, meteringSize.height,
+            jpegMaxSize.width, jpegMaxSize.height);
+
+    // Create streams
+    // Preview stream: small resolution, render on the screen.
+    sp<CameraStream> previewStream;
+    {
+        sp<ANativeWindow> surface;
+        ASSERT_NO_FATAL_FAILURE(CreateOnScreenSurface(/*out*/surface));
+        previewStream = CreateStream(
+                previewSize.width,
+                previewSize.height,
+                mDevice,
+                DISPLAY_STREAM_PARAMETERS,
+                surface,
+                false);
+        ASSERT_NE((void*)NULL, previewStream.get());
+        ASSERT_NO_FATAL_FAILURE(previewStream->SetUp());
+    }
+    // Metering burst stream: small resolution yuv stream
+    sp<CameraStream> meteringStream =
+            CreateStream(
+                    meteringSize.width,
+                    meteringSize.height,
+                    mDevice);
+    ASSERT_NE((void*)NULL, meteringStream.get());
+    ASSERT_NO_FATAL_FAILURE(meteringStream->SetUp());
+    // Capture burst stream: full resolution yuv stream
+    sp<CameraStream> captureStream =
+            CreateStream(
+                    jpegMaxSize.width,
+                    jpegMaxSize.height,
+                    mDevice);
+    ASSERT_NE((void*)NULL, captureStream.get());
+    ASSERT_NO_FATAL_FAILURE(captureStream->SetUp());
+
+    // Create Preview request.
+    CameraMetadata previewRequest, meteringRequest, captureRequest;
+    ASSERT_NO_FATAL_FAILURE(CreateRequests(previewRequest, meteringRequest,
+            captureRequest, previewStream->GetStreamId(),
+            meteringStream->GetStreamId(), captureStream->GetStreamId()));
+
+    // Start preview
+    if (CAMERA_MULTI_STREAM_DEBUGGING) {
+        previewRequest.dump(STDOUT_FILENO);
+    }
+
+    // Generate exposure and sensitivity lists
+    camera_metadata_ro_entry exposureTimeRange =
+        GetStaticEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE);
+    ASSERT_EQ(exposureTimeRange.count, 2u);
+    int64_t minExp = exposureTimeRange.data.i64[0];
+    int64_t maxExp = exposureTimeRange.data.i64[1];
+    ASSERT_GT(maxExp, minExp);
+
+    camera_metadata_ro_entry sensivityRange =
+        GetStaticEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE);
+    ASSERT_EQ(2u, sensivityRange.count);
+    int32_t minSensitivity = sensivityRange.data.i32[0];
+    int32_t maxSensitivity = sensivityRange.data.i32[1];
+    camera_metadata_ro_entry maxAnalogSenEntry =
+            GetStaticEntry(ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY);
+    EXPECT_EQ(1u, maxAnalogSenEntry.count);
+    int32_t maxAnalogSensitivity = maxAnalogSenEntry.data.i32[0];
+    EXPECT_LE(maxAnalogSensitivity, maxSensitivity);
+    // Only test the sensitivity implemented by analog gain.
+    if (maxAnalogSensitivity > maxSensitivity) {
+        // Fallback to maxSensitity
+        maxAnalogSensitivity = maxSensitivity;
+    }
+
+    // sensitivity list, only include the sensitivities that are implemented
+    // purely by analog gain if possible.
+    Vector<int32_t> sensitivities;
+    Vector<int64_t> exposures;
+    count = (maxAnalogSensitivity - minSensitivity + 99) / 100;
+    sensitivities.push_back(minSensitivity);
+    for (size_t i = 1; i < count; i++) {
+        sensitivities.push_back(minSensitivity + i * 100);
+    }
+    sensitivities.push_back(maxAnalogSensitivity);
+    ALOGV("Sensitivity Range: min=%d, max=%d", minSensitivity,
+            maxAnalogSensitivity);
+    int64_t exp = minExp;
+    while (exp < maxExp) {
+        exposures.push_back(exp);
+        exp *= 2;
+    }
+    // Sweep the exposure value for preview, just for visual inspection purpose.
+    uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
+    for (size_t i = 0; i < exposures.size(); i++) {
+        ASSERT_EQ(OK, previewRequest.update(
+                ANDROID_CONTROL_MODE,
+                &cmOff, 1));
+        ASSERT_EQ(OK, previewRequest.update(
+                ANDROID_SENSOR_EXPOSURE_TIME,
+                &exposures[i], 1));
+        ALOGV("Submitting preview request %d with exposure %lld",
+                i, exposures[i]);
+
+        ASSERT_EQ(OK, mDevice->setStreamingRequest(previewRequest));
+
+        // Let preview run 200ms on screen for each exposure time.
+        usleep(PREVIEW_RENDERING_TIME_INTERVAL);
+    }
+
+    size_t requestCount = sensitivities.size();
+    if (requestCount > exposures.size()) {
+        requestCount = exposures.size();
+    }
+
+    // To maintain the request id uniqueness (preview request id is 0), make burst capture start
+    // request id 1 here.
+    int32_t requestIdStart = 1;
+    /**
+     * Submit metering request, set default frame duration to minimal possible
+     * value, we want the capture to run as fast as possible. HAL should adjust
+     * the frame duration to minimal necessary value to support the requested
+     * exposure value if exposure is larger than frame duration.
+     */
+    CaptureBurst(meteringRequest, requestCount, exposures, sensitivities,
+            meteringStream, minFrameDuration, &requestIdStart);
+
+    /**
+     * Submit capture request, set default frame duration to minimal possible
+     * value, we want the capture to run as fast as possible. HAL should adjust
+     * the frame duration to minimal necessary value to support the requested
+     * exposure value if exposure is larger than frame duration.
+     */
+    CaptureBurst(captureRequest, requestCount, exposures, sensitivities,
+            captureStream, minFrameDuration, &requestIdStart);
+
+    ASSERT_EQ(OK, mDevice->clearStreamingRequest());
+}
+
+}
+}
+}
diff --git a/tests/camera2/CameraStreamFixture.h b/tests/camera2/CameraStreamFixture.h
index a4dc4a8..a1f3aae 100644
--- a/tests/camera2/CameraStreamFixture.h
+++ b/tests/camera2/CameraStreamFixture.h
@@ -19,6 +19,7 @@
 
 #include <gtest/gtest.h>
 #include <iostream>
+#include <fstream>
 
 #include <gui/CpuConsumer.h>
 #include <gui/Surface.h>
@@ -29,6 +30,8 @@
 #include "CameraModuleFixture.h"
 #include "TestExtensions.h"
 
+#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
+
 namespace android {
 namespace camera2 {
 namespace tests {
@@ -90,7 +93,6 @@
 
         CameraModuleFixture::SetUp();
 
-        CameraStreamParams p = mParam;
         sp<CameraDeviceBase> device = mDevice;
 
         /* use an arbitrary w,h */
@@ -159,11 +161,11 @@
         sp<CameraDeviceBase> device = mDevice;
         CameraStreamParams p = mParam;
 
-        mCpuConsumer = new CpuConsumer(p.mHeapCount);
+        sp<BufferQueue> bq = new BufferQueue();
+        mCpuConsumer = new CpuConsumer(bq, p.mHeapCount);
         mCpuConsumer->setName(String8("CameraStreamTest::mCpuConsumer"));
 
-        mNativeWindow = new Surface(
-            mCpuConsumer->getProducerInterface());
+        mNativeWindow = new Surface(bq);
 
         int format = MapAutoFormat(p.mFormat);
 
@@ -194,6 +196,80 @@
         return format;
     }
 
+    void DumpYuvToFile(const String8 &fileName, const CpuConsumer::LockedBuffer &img) {
+        uint8_t *dataCb, *dataCr;
+        uint32_t stride;
+        uint32_t chromaStride;
+        uint32_t chromaStep;
+
+        switch (img.format) {
+            case HAL_PIXEL_FORMAT_YCbCr_420_888:
+                stride = img.stride;
+                chromaStride = img.chromaStride;
+                chromaStep = img.chromaStep;
+                dataCb = img.dataCb;
+                dataCr = img.dataCr;
+                break;
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+                stride = img.width;
+                chromaStride = img.width;
+                chromaStep = 2;
+                dataCr = img.data + img.width * img.height;
+                dataCb = dataCr + 1;
+                break;
+            case HAL_PIXEL_FORMAT_YV12:
+                stride = img.stride;
+                chromaStride = ALIGN(img.width / 2, 16);
+                chromaStep = 1;
+                dataCr = img.data + img.stride * img.height;
+                dataCb = dataCr + chromaStride * img.height/2;
+                break;
+            default:
+                ALOGE("Unknown format %d, not dumping", img.format);
+                return;
+        }
+
+        // Write Y
+        FILE *yuvFile = fopen(fileName.string(), "w");
+
+        size_t bytes;
+
+        for (size_t y = 0; y < img.height; ++y) {
+            bytes = fwrite(
+                reinterpret_cast<const char*>(img.data + stride * y),
+                1, img.width, yuvFile);
+            if (bytes != img.width) {
+                ALOGE("Unable to write to file %s", fileName.string());
+                fclose(yuvFile);
+                return;
+            }
+        }
+
+        // Write Cb/Cr
+        uint8_t *src = dataCb;
+        for (int c = 0; c < 2; ++c) {
+            for (size_t y = 0; y < img.height / 2; ++y) {
+                uint8_t *px = src + y * chromaStride;
+                if (chromaStep != 1) {
+                    for (size_t x = 0; x < img.width / 2; ++x) {
+                        fputc(*px, yuvFile);
+                        px += chromaStep;
+                    }
+                } else {
+                    bytes = fwrite(reinterpret_cast<const char*>(px),
+                            1, img.width / 2, yuvFile);
+                    if (bytes != img.width / 2) {
+                        ALOGE("Unable to write to file %s", fileName.string());
+                        fclose(yuvFile);
+                        return;
+                    }
+                }
+            }
+            src = dataCr;
+        }
+        fclose(yuvFile);
+    }
+
     int mWidth;
     int mHeight;
 
diff --git a/tests/camera2/CameraStreamTests.cpp b/tests/camera2/CameraStreamTests.cpp
index 164e0e5..69ee274 100644
--- a/tests/camera2/CameraStreamTests.cpp
+++ b/tests/camera2/CameraStreamTests.cpp
@@ -25,12 +25,12 @@
 #include "hardware/hardware.h"
 #include "hardware/camera2.h"
 
-#include "Camera2Device.h"
-#include "utils/StrongPointer.h"
-
+#include <utils/StrongPointer.h>
 #include <gui/CpuConsumer.h>
 #include <gui/Surface.h>
 
+#include <device2/Camera2Device.h>
+
 #include "CameraStreamFixture.h"
 #include "TestExtensions.h"
 
diff --git a/tests/camera2/camera2.cpp b/tests/camera2/camera2.cpp
index 92ef221..600d440 100644
--- a/tests/camera2/camera2.cpp
+++ b/tests/camera2/camera2.cpp
@@ -201,7 +201,8 @@
         if (mDevice != NULL) {
             closeCameraDevice(&mDevice);
         }
-        mDevice = openCameraDevice(id);
+        mId = id;
+        mDevice = openCameraDevice(mId);
         ASSERT_TRUE(NULL != mDevice) << "Failed to open camera device";
 
         camera_info info;
@@ -334,6 +335,7 @@
         TearDownModule();
     }
 
+    int mId;
     camera2_device    *mDevice;
     const camera_metadata_t *mStaticInfo;
 
@@ -386,7 +388,8 @@
 
         ASSERT_NO_FATAL_FAILURE(setUpCamera(id));
 
-        sp<CpuConsumer> rawConsumer = new CpuConsumer(1);
+        sp<BufferQueue> bq = new BufferQueue();
+        sp<CpuConsumer> rawConsumer = new CpuConsumer(bq, 1);
         sp<FrameWaiter> rawWaiter = new FrameWaiter();
         rawConsumer->setFrameAvailableListener(rawWaiter);
 
@@ -417,8 +420,7 @@
 
         int streamId;
         ASSERT_NO_FATAL_FAILURE(
-            setUpStream(rawConsumer->getProducerInterface(),
-                    width, height, format, &streamId) );
+            setUpStream(bq, width, height, format, &streamId) );
 
         camera_metadata_t *request;
         request = allocate_camera_metadata(20, 2000);
@@ -520,7 +522,8 @@
 
         ASSERT_NO_FATAL_FAILURE(setUpCamera(id));
 
-        sp<CpuConsumer> rawConsumer = new CpuConsumer(1);
+        sp<BufferQueue> bq = new BufferQueue();
+        sp<CpuConsumer> rawConsumer = new CpuConsumer(bq, 1);
         sp<FrameWaiter> rawWaiter = new FrameWaiter();
         rawConsumer->setFrameAvailableListener(rawWaiter);
 
@@ -551,8 +554,7 @@
 
         int streamId;
         ASSERT_NO_FATAL_FAILURE(
-            setUpStream(rawConsumer->getProducerInterface(),
-                    width, height, format, &streamId) );
+            setUpStream(bq, width, height, format, &streamId) );
 
         camera_metadata_t *request;
         request = allocate_camera_metadata(20, 2000);
@@ -701,7 +703,8 @@
 
         ASSERT_NO_FATAL_FAILURE(setUpCamera(id));
 
-        sp<CpuConsumer> jpegConsumer = new CpuConsumer(1);
+        sp<BufferQueue> bq = new BufferQueue();
+        sp<CpuConsumer> jpegConsumer = new CpuConsumer(bq, 1);
         sp<FrameWaiter> jpegWaiter = new FrameWaiter();
         jpegConsumer->setFrameAvailableListener(jpegWaiter);
 
@@ -720,8 +723,7 @@
 
         int streamId;
         ASSERT_NO_FATAL_FAILURE(
-            setUpStream(jpegConsumer->getProducerInterface(),
-                    width, height, format, &streamId) );
+            setUpStream(bq, width, height, format, &streamId) );
 
         camera_metadata_t *request;
         request = allocate_camera_metadata(20, 2000);
diff --git a/tests/camera2/camera2_utils.cpp b/tests/camera2/camera2_utils.cpp
index 76a7233..3c0767a 100644
--- a/tests/camera2/camera2_utils.cpp
+++ b/tests/camera2/camera2_utils.cpp
@@ -210,7 +210,6 @@
 
 int MetadataQueue::consumer_free(const camera2_request_queue_src_ops_t *q,
         camera_metadata_t *old_buffer) {
-    MetadataQueue *queue = getInstance(q);
     free_camera_metadata(old_buffer);
     return OK;
 }
diff --git a/tests/hwc/Android.mk b/tests/hwc/Android.mk
new file mode 100644
index 0000000..4cae9eb
--- /dev/null
+++ b/tests/hwc/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcnativewindow 
+LOCAL_SRC_FILES := cnativewindow.c util.c
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := hwc-test-arrows
+LOCAL_SRC_FILES := test-arrows.c
+LOCAL_STATIC_LIBRARIES := libcnativewindow
+LOCAL_SHARED_LIBRARIES := libEGL libGLESv2 libdl libhardware
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
+include $(BUILD_EXECUTABLE)
diff --git a/tests/hwc/cnativewindow.c b/tests/hwc/cnativewindow.c
new file mode 100644
index 0000000..76f4564
--- /dev/null
+++ b/tests/hwc/cnativewindow.c
@@ -0,0 +1,578 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+
+#include <pthread.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+#include <hardware/hwcomposer.h>
+
+#include <system/window.h>
+#include <cutils/native_handle.h>
+
+// normalize and shorten type names
+typedef struct android_native_base_t aBase;
+typedef struct ANativeWindowBuffer aBuffer;
+typedef struct ANativeWindow aWindow;
+
+static int trace_level = 1;
+
+#define _TRACE(n,fmt...) \
+	do { if (trace_level >= n) fprintf(stderr, "CNW: " fmt); } while (0)
+
+#define ERROR(fmt...) _TRACE(0, fmt)
+#define INFO(fmt...) _TRACE(1, fmt)
+#define LOG(fmt...) _TRACE(2, fmt)
+#define TRACE(fmt...) _TRACE(3, fmt)
+
+#define QCT_WORKAROUND 1
+
+typedef struct CNativeBuffer {
+	aBuffer base;
+	struct CNativeBuffer *next;
+	struct CNativeBuffer *prev;
+	int ffd;
+} CNativeBuffer;
+
+typedef struct CNativeWindow {
+	aWindow base;
+
+	hwc_composer_device_1_t *hwc;
+	framebuffer_device_t *fb;
+	alloc_device_t *gr;
+
+	pthread_mutex_t lock;
+	pthread_cond_t cvar;
+
+	aBuffer *front;
+	aBuffer *spare;
+
+	CNativeBuffer free_buffer_queue;
+
+	unsigned width;
+	unsigned height;
+	unsigned xdpi;
+	unsigned ydpi;
+	unsigned format;
+
+	hwc_display_contents_1_t *dclist[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
+
+	hwc_display_contents_1_t dc;
+	hwc_layer_1_t layer[4];
+} CNativeWindow;
+
+static inline CNativeBuffer *from_abuffer(aBuffer *buf) {
+	return (CNativeBuffer*) buf;
+}
+
+static CNativeBuffer *get_front(struct CNativeBuffer *queue) {
+	CNativeBuffer *buf = queue->next;
+	if (buf == queue)
+		return 0;
+	buf->next->prev = queue;
+	queue->next = buf->next;
+	buf->next = buf->prev = 0;
+	return buf;
+}
+
+static void put_front(struct CNativeBuffer *queue, aBuffer *_buf) {
+	struct CNativeBuffer *buf = (struct CNativeBuffer *) _buf;
+	buf->prev = queue;
+	buf->next = queue->next;
+	queue->next->prev = buf;
+	queue->next = buf;
+}
+
+static void put_back(struct CNativeBuffer *queue, aBuffer *_buf) {
+	struct CNativeBuffer *buf = (struct CNativeBuffer *) _buf;
+	buf->next = queue;
+	buf->prev = queue->prev;
+	queue->prev->next = buf;
+	queue->prev = buf;
+}
+
+static void cnw_inc_ref(aBase *base) { TRACE("buf %p ref++\n",base); }
+static void cnw_dec_ref(aBase *base) { TRACE("buf %p ref--\n",base); }
+
+static inline CNativeWindow *from_base(aWindow *base) {
+	return (CNativeWindow *) base;
+}
+
+static inline CNativeWindow *from_base_const(const aWindow *base) {
+	return (CNativeWindow *) base;
+}
+
+static int cnw_set_swap_interval(aWindow *base, int interval) {
+	CNativeWindow *win = from_base(base);
+	if (win->fb && win->fb->setSwapInterval)
+		return win->fb->setSwapInterval(win->fb, interval);
+	return 0;
+}
+
+static int cnw_dequeue_buffer1(aWindow *base, aBuffer **buf, int *ffd) {
+	CNativeWindow *win = from_base(base);
+	CNativeBuffer *cnb;
+
+	pthread_mutex_lock(&win->lock);
+
+	while ((cnb = get_front(&win->free_buffer_queue)) == 0) {
+		pthread_cond_wait(&win->cvar, &win->lock);
+	}
+
+	*ffd = cnb->ffd;
+	*buf = &cnb->base;
+	cnb->ffd = -1;
+	LOG("<< dequeue buffer %p %d\n", *buf, *ffd);
+
+	pthread_mutex_unlock(&win->lock);
+	return 0;
+}
+
+static int cnw_lock_buffer0(aWindow *base, aBuffer *buffer) {
+	return 0;
+}
+
+static void set_layer(hwc_layer_1_t *dl, aBuffer *buf, int ffd) {
+	int right = buf->width;
+	int bottom = buf->height;
+
+	dl->compositionType = HWC_FRAMEBUFFER;
+	dl->hints = 0;
+	dl->flags = 0;
+
+	dl->handle = buf->handle;
+	dl->transform = 0;
+	dl->blending = HWC_BLENDING_NONE;
+	dl->sourceCrop.left = 0;
+	dl->sourceCrop.top = 0;
+	dl->sourceCrop.right = right;
+	dl->sourceCrop.bottom = bottom;
+	dl->displayFrame.left = 0;
+	dl->displayFrame.top = 0;
+	dl->displayFrame.right = right;
+	dl->displayFrame.bottom = bottom;
+	dl->visibleRegionScreen.numRects = 1;
+	dl->visibleRegionScreen.rects = &dl->displayFrame;
+
+	dl->acquireFenceFd = ffd;
+	dl->releaseFenceFd = -1;
+}
+
+static void hwc_post(CNativeWindow *win, aBuffer *buf, int ffd) {
+	hwc_composer_device_1_t *hwc = win->hwc;
+	hwc_display_contents_1_t *dc = &(win->dc);
+	hwc_layer_1_t *dl = win->dc.hwLayers;
+	int r, i;
+
+	dc->retireFenceFd = -1;
+	dc->outbufAcquireFenceFd = -1;
+	dc->flags = HWC_GEOMETRY_CHANGED;
+	dc->numHwLayers = 1;
+
+	// some hwcomposers fail if these are NULL
+	dc->dpy = (void*) 0xdeadbeef;
+	dc->sur = (void*) 0xdeadbeef;
+
+	set_layer(&dl[0], buf, ffd);
+
+	if (QCT_WORKAROUND) {
+		set_layer(&dl[1], win->spare, -1);
+		dl[1].compositionType = HWC_FRAMEBUFFER_TARGET;
+		dc->numHwLayers++;
+	}
+
+	r = hwc->prepare(hwc, HWC_NUM_PHYSICAL_DISPLAY_TYPES, win->dclist);
+	if (r) {
+		ERROR("hwc->prepare failed r=%d\n",r);
+		return;
+	}
+
+//	for (i = 0; i < dc->numHwLayers; i++)
+//		LOG("dl[%d] ctype=0x%08x hints=0x%08x flags=0x%08x\n", i,
+//			dl[i].compositionType, dl[0].hints, dl[0].flags);
+
+	r = hwc->set(hwc, HWC_NUM_PHYSICAL_DISPLAY_TYPES, win->dclist);
+	if (r) {
+		ERROR("hwc->set failed, r=%d\n", r);
+		return;
+	}
+
+	if (dc->retireFenceFd != -1)
+		close(dc->retireFenceFd);
+	if (dl->releaseFenceFd != -1) {
+		CNativeBuffer *cnb = from_abuffer(buf);
+		cnb->ffd = dl->releaseFenceFd;
+	}
+	if (QCT_WORKAROUND)
+		if (dl[1].releaseFenceFd != -1)
+			close(dl[1].releaseFenceFd);
+}
+
+static int cnw_queue_buffer1(aWindow *base, aBuffer *buffer, int ffd) {
+	CNativeWindow *win = from_base(base);
+	int res;
+	LOG(">> queue buffer %p %d\n", buffer, ffd);
+	if (win->fb) {
+		res = win->fb->post(win->fb, buffer->handle);
+		if (ffd != -1)
+			close(ffd);
+	} else {
+		hwc_post(win, buffer, ffd);
+		res = 0;
+	}
+	pthread_mutex_lock(&win->lock);
+	if (win->front)
+		put_back(&win->free_buffer_queue, win->front);
+	win->front = buffer;
+	pthread_cond_signal(&win->cvar);
+	pthread_mutex_unlock(&win->lock);
+
+	return res;
+}
+
+static int cnw_cancel_buffer1(aWindow *base, aBuffer *buf, int ffd) {
+	CNativeWindow *win = from_base(base);
+	CNativeBuffer *cnb = from_abuffer(buf);
+	LOG("<< cancel buffer %p %d\n", buf, ffd);
+	cnb->ffd = ffd;
+	pthread_mutex_lock(&win->lock);
+	put_front(&win->free_buffer_queue, buf);
+	pthread_mutex_unlock(&win->lock);
+	return 0;
+}
+
+static int cnw_dequeue_buffer0(aWindow *base, aBuffer **buf) {
+	int ffd = -1;
+	int r;
+	r = cnw_dequeue_buffer1(base, buf, &ffd);
+	if (ffd != -1)
+		close(ffd);
+	return r;
+}
+
+static int cnw_queue_buffer0(aWindow *base, aBuffer *buf) {
+	return cnw_queue_buffer1(base, buf, -1);
+}
+
+static int cnw_cancel_buffer0(aWindow *base, aBuffer *buf) {
+	return cnw_cancel_buffer1(base, buf, -1);
+}
+
+static int cnw_query(const aWindow *base, int what, int *value) {
+	CNativeWindow *win = from_base_const(base);
+
+	switch (what) {
+	case NATIVE_WINDOW_WIDTH:
+	case NATIVE_WINDOW_DEFAULT_WIDTH:
+		*value = win->width;
+		TRACE("query window width: %d\n", *value);
+		return 0;
+	case NATIVE_WINDOW_HEIGHT:
+	case NATIVE_WINDOW_DEFAULT_HEIGHT:
+		*value = win->height;
+		TRACE("query window height: %d\n", *value);
+		return 0;
+	case NATIVE_WINDOW_FORMAT:
+		*value = win->format;
+		TRACE("query window format: %d\n", *value);
+		return 0;
+	case NATIVE_WINDOW_TRANSFORM_HINT:
+		TRACE("query transform hint: 0\n");
+		*value = 0;
+		return 0;
+	case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+		TRACE("query min undequeued buffers: 1\n");
+		*value = 1;
+		return 0;
+	default:
+		*value = 0;
+		ERROR("query %d unknown!\n", what);
+		return -EINVAL;
+	}
+}
+
+static int cnw_perform(aWindow *base, int op, ...) {
+	CNativeWindow *win = from_base(base);
+	va_list ap;
+	va_start(ap, op);
+
+	switch (op) {
+	case NATIVE_WINDOW_SET_USAGE:
+		TRACE("set usage %d\n", va_arg(ap,int));
+		return 0;
+	case NATIVE_WINDOW_CONNECT:
+	case NATIVE_WINDOW_DISCONNECT:
+	case NATIVE_WINDOW_API_CONNECT:
+	case NATIVE_WINDOW_API_DISCONNECT:
+		return 0;
+	case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
+		TRACE("set buffers format %d\n", va_arg(ap,int));
+		return 0;
+	case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
+		TRACE("set buffers transform %d\n", va_arg(ap,int));
+		return 0;
+	case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
+		TRACE("set buffers timestamp %lld\n", va_arg(ap,long long));
+		return 0;
+	case NATIVE_WINDOW_SET_SCALING_MODE:
+		TRACE("set scaling mode %d\n", va_arg(ap,int));
+		return 0;
+	case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: {
+		int w = va_arg(ap,int);
+		int h = va_arg(ap,int);
+		if ((w == win->width) && (h == win->height)) {
+			TRACE("set buffers dimensions %d x %d\n", w, h);
+			return 0;
+		}
+		ERROR("cannot resize buffers to %d x %d\n", w, h);
+		return -1;
+	}
+	default:
+		ERROR("perform %d unknown!\n", op);
+		return -ENODEV;
+	}
+}
+
+static void hwc_invalidate(const struct hwc_procs *procs) {}
+static void hwc_vsync(const struct hwc_procs *procs, int disp, int64_t ts) {}
+static void hwc_hotplug(const struct hwc_procs *procs, int disp, int conn) {}
+
+struct hwc_procs hprocs = {
+	.invalidate = hwc_invalidate,
+	.vsync = hwc_vsync,
+	.hotplug = hwc_hotplug,
+};
+
+uint32_t attrs[] = {
+	HWC_DISPLAY_WIDTH,
+	HWC_DISPLAY_HEIGHT,
+	HWC_DISPLAY_VSYNC_PERIOD,
+	HWC_DISPLAY_DPI_X,
+	HWC_DISPLAY_DPI_Y,
+	HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static int hwc_init(CNativeWindow *win) {
+	hw_module_t const* module;
+	hwc_composer_device_1_t *hwc;
+	unsigned i;
+	int r;
+	uint32_t configs[32];
+	uint32_t numconfigs = 32;
+	int32_t values[8];
+
+	if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
+		ERROR("cannot open hw composer module\n");
+		return -ENODEV;
+	}
+
+	if (hwc_open_1(module, &hwc)) {
+		ERROR("cannot open hwc device\n");
+		return -ENODEV;
+	}
+	win->hwc = hwc;
+
+	LOG("hwc version 0x%08x\n", hwc->common.version);
+
+	if ((hwc->common.version & 0xFFFF0000) < 0x01010000) {
+		ERROR("hwc version less than 1.1\n");
+		hwc_close_1(hwc);
+		return -ENODEV;
+	}
+
+	hwc->registerProcs(hwc, &hprocs);
+
+	if (hwc->getDisplayConfigs(hwc, 0, configs, &numconfigs)) {
+		ERROR("cannot get configs\n");
+		return -ENODEV;
+	}
+	for (i = 0; i < numconfigs; i++)
+		LOG("cfg[%d] = 0x%08x\n", i, configs[i]);
+
+	if ((r = hwc->getDisplayAttributes(hwc, 0, configs[0], attrs, values))) {
+		ERROR("cannot get attributes %d\n", r);
+		return -ENODEV;
+	}
+
+	win->width = values[0];
+	win->height = values[1];
+	win->xdpi = values[3];
+	win->ydpi = values[4];
+	win->format = HAL_PIXEL_FORMAT_RGBA_8888;
+
+	hwc->blank(hwc, 0, 0);
+
+	win->dclist[0] = &(win->dc);
+	return 0;
+}
+
+static aBuffer *cnw_alloc(CNativeWindow *win, unsigned format, unsigned usage) {
+	CNativeBuffer *cnb;
+	aBuffer *buf;
+	int err;
+
+	if (!(cnb = malloc(sizeof(CNativeBuffer))))
+		return 0;
+
+	buf = &cnb->base;
+	cnb->ffd = -1;
+
+	buf->common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
+	buf->common.version = sizeof(aBuffer);
+	buf->common.incRef = cnw_inc_ref;
+	buf->common.decRef = cnw_dec_ref;
+
+	buf->width = win->width;
+	buf->height = win->height;
+	buf->format = format;
+	buf->usage = usage;
+
+	err = win->gr->alloc(win->gr, win->width, win->height,
+		format, usage, &buf->handle, &buf->stride);
+	if (err) {
+		ERROR("gralloc of %d x %d failed: err=%d\n",
+			win->width, win->height, err);
+		free(buf);
+		return 0;
+	}
+	INFO("alloc buffer %p %d x %d\n", buf, win->width, win->height);
+	return buf;
+}
+
+static int cnw_init(CNativeWindow *win) {
+	hw_module_t const* module;
+	framebuffer_device_t *fb = NULL;
+	alloc_device_t *gr;
+	int err, i, n;
+	unsigned usage, format;
+
+	memset(win, 0, sizeof(CNativeWindow));
+
+	win->free_buffer_queue.next = &(win->free_buffer_queue);
+	win->free_buffer_queue.prev = &(win->free_buffer_queue);
+
+	if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) {
+		ERROR("cannot open gralloc module\n");
+		return -ENODEV;
+	}
+
+	if (hwc_init(win)) {
+		ERROR("cannot open hwcomposer, trying legacy fb HAL\n");
+		err = framebuffer_open(module, &fb);
+		if (err) {
+			ERROR("cannot open fb HAL (%s)", strerror(-err));
+			return -ENODEV;
+		}
+		win->width = fb->width;
+		win->height = fb->height;
+		win->format = fb->format;
+		win->xdpi = fb->xdpi;
+		win->ydpi = fb->ydpi;
+		win->fb = fb;
+	}
+
+	INFO("display %d x %d fmt=%d\n",
+		win->width, win->height, win->format);
+
+	err = gralloc_open(module, &gr);
+	if (err) {
+		ERROR("couldn't open gralloc HAL (%s)", strerror(-err));
+		return -ENODEV;
+	}
+	win->gr = gr;
+
+	usage = GRALLOC_USAGE_HW_FB |
+		GRALLOC_USAGE_HW_COMPOSER |
+		GRALLOC_USAGE_HW_RENDER;
+
+	for (i = 0; i < 2; i++) {
+		aBuffer *buf = cnw_alloc(win, win->format, usage);
+		if (!buf)
+			return -ENOMEM;
+		put_back(&win->free_buffer_queue, buf);
+	}
+
+	if (!win->fb && QCT_WORKAROUND) {
+		win->spare = cnw_alloc(win, win->format, usage);
+		if (!win->spare)
+			return -ENOMEM;
+	}
+
+	// Disgusting, but we need to init these "const" fields
+	// and unlike C++ we can't use const_cast<>
+	*((float*) &win->base.xdpi) = win->xdpi;
+	*((float*) &win->base.ydpi) = win->ydpi;
+	*((int*) &win->base.minSwapInterval) = 1;
+	*((int*) &win->base.maxSwapInterval) = 1;
+
+	win->base.common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
+	win->base.common.version = sizeof(aWindow);
+	win->base.common.incRef = cnw_inc_ref;
+	win->base.common.decRef = cnw_dec_ref;
+
+	win->base.setSwapInterval = cnw_set_swap_interval;
+	win->base.dequeueBuffer_DEPRECATED = cnw_dequeue_buffer0;
+	win->base.lockBuffer_DEPRECATED = cnw_lock_buffer0;
+	win->base.queueBuffer_DEPRECATED = cnw_queue_buffer0;
+	win->base.query = cnw_query;
+	win->base.perform = cnw_perform;
+	win->base.cancelBuffer_DEPRECATED = cnw_cancel_buffer0;
+	win->base.dequeueBuffer = cnw_dequeue_buffer1;
+	win->base.queueBuffer = cnw_queue_buffer1;
+	win->base.cancelBuffer = cnw_cancel_buffer1;
+
+	pthread_mutex_init(&win->lock, NULL);
+	pthread_cond_init(&win->cvar, NULL);
+
+	return 0;
+}
+
+void cnw_destroy(CNativeWindow *win) {
+	if (win->fb)
+		framebuffer_close(win->fb);
+	if (win->hwc)
+		hwc_close_1(win->hwc);
+	if (win->gr)
+		gralloc_close(win->gr);
+	free(win);
+}
+
+CNativeWindow *cnw_create(void) {
+	CNativeWindow *win;
+	char *x;
+	if ((x = getenv("CNWDEBUG")))
+		trace_level = atoi(x);
+	if (!(win = malloc(sizeof(CNativeWindow))))
+		return NULL;
+	if (cnw_init(win)) {
+		cnw_destroy(win);
+		return NULL;
+	}
+	return win;
+}
+
+void cnw_info(CNativeWindow *win, unsigned *w, unsigned *h, unsigned *fmt) {
+	*w = win->width;
+	*h = win->height;
+	*fmt = win->format;
+}
+
diff --git a/tests/hwc/test-arrows.c b/tests/hwc/test-arrows.c
new file mode 100644
index 0000000..a35faa7
--- /dev/null
+++ b/tests/hwc/test-arrows.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+
+#include "util.h"
+
+static const char gVertexShader[] =
+	"attribute vec4 aPosition;\n"
+	"uniform mat4 uTransform;\n"
+	"varying vec4 vTexCoord;\n"
+	"void main() {\n"
+	"  gl_Position = aPosition * uTransform;\n"
+	"  vTexCoord = aPosition * vec4(1.0/16.0,-1.0/16.0,0.0,0.0);\n"
+	"}\n";
+
+static const char gFragmentShader[] =
+	"precision mediump float;\n"
+	"uniform sampler2D uTexture;\n"
+	"uniform float uAnim;\n"
+	"varying vec4 vTexCoord;\n"
+	"void main() {\n"
+	"  vec2 tc = vec2(vTexCoord.x, uAnim + vTexCoord.y);\n"
+	"  gl_FragColor = texture2D(uTexture, tc);\n"
+	"}\n";
+
+static GLuint pgm;
+static GLint aPosition, uTransform, uTexture, uAnim;
+
+static GLfloat vtx[2 * 3 * 2];
+static GLfloat mtx[16];
+
+//#define R (0xFF0000FF)
+#define R (0xFF000000)
+#define G (0xFF00FF00)
+uint32_t t32[] = {
+	R, R, R, R, R, R, R, G, G, R, R, R, R, R, R, R,
+	R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R,
+	R, R, R, R, R, G, G, G, G, G, G, R, R, R, R, R,
+	R, R, R, R, G, G, G, G, G, G, G, G, R, R, R, R,
+	R, R, R, G, G, G, G, G, G, G, G, G, G, R, R, R,
+	R, R, G, G, G, G, G, G, G, G, G, G, G, G, R, R,
+	R, R, G, G, G, G, G, G, G, G, G, G, G, G, R, R,
+	R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R,
+	R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R,
+	R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R,
+	R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R,
+	R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R,
+	R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R,
+	R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,
+	R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,
+	R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,
+};
+#undef R
+#undef G
+
+int prepare(int w, int h) {
+	GLuint texid;
+
+	int left = w / 4;
+	int top = h / 4;
+	int right = (w / 4) * 3;
+	int bottom = (h / 4) * 3;
+
+	vtx[0] = left;
+	vtx[1] = top;
+	vtx[2] = left;
+	vtx[3] = bottom;
+	vtx[4] = right;
+	vtx[5] = bottom;
+
+	vtx[6] = right;
+	vtx[7] = bottom;
+	vtx[8] = right;
+	vtx[9] = top;
+	vtx[10] = left;
+	vtx[11] = top;
+
+	matrix_init_ortho(mtx, w, h);
+
+	pgm = load_program(gVertexShader, gFragmentShader);
+	if (!pgm)
+		return -1;
+
+	aPosition = glGetAttribLocation(pgm, "aPosition");
+	uTexture = glGetUniformLocation(pgm, "uTexture");
+	uTransform = glGetUniformLocation(pgm, "uTransform");
+	uAnim = glGetUniformLocation(pgm, "uAnim");
+
+	glViewport(0, 0, w, h);
+
+	glGenTextures(1, &texid);
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(GL_TEXTURE_2D, texid);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+	glEnable(GL_TEXTURE_2D);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+		GL_RGBA, GL_UNSIGNED_BYTE, t32);
+
+	return 0;
+}
+
+static float anim = 0.0;
+
+void render() {
+	anim += 0.1;
+	if (anim >= 16.0) anim = 0.0;
+
+	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+	glUseProgram(pgm);
+	glUniform1i(uTexture, 0);
+	glUniform1f(uAnim, anim);
+	glUniformMatrix4fv(uTransform, 1, 0, mtx);
+	glVertexAttribPointer(aPosition, 2, GL_FLOAT, GL_FALSE, 0, vtx);
+	glEnableVertexAttribArray(aPosition);
+	glDrawArrays(GL_TRIANGLES, 0, 6);
+}
+
+int main(int argc, char **argv) {
+	EGLDisplay display;
+	EGLSurface surface;
+	int w, h, count;
+
+	if (argc > 1)
+		count = atoi(argv[1]);
+
+	if (egl_create(&display, &surface, &w, &h))
+		return -1;
+
+	if (prepare(w, h))
+		return -1;
+
+	for (;;) {
+		render();
+		eglSwapBuffers(display, surface);
+		if (count > 0)
+			if (--count == 0)
+				break;
+	}
+
+	egl_destroy(display, surface);
+	return 0;
+}
diff --git a/tests/hwc/util.c b/tests/hwc/util.c
new file mode 100644
index 0000000..8931305
--- /dev/null
+++ b/tests/hwc/util.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+
+#include <system/graphics.h>
+
+#include "util.h"
+
+void matrix_init_ortho(GLfloat *m, float w, float h) {
+	m[0] = 2.0 / w;
+	m[1] = 0.0;
+	m[2] = 0.0;
+	m[3] = -1.0;
+	m[4] = 0.0;
+	m[5] = 2.0 / h;
+	m[6] = 0.0;
+	m[7] = -1.0;
+	m[8] = 0.0;
+	m[9] = 0.0;
+	m[10] -1.0;
+	m[11] = 0.0;
+	m[12] = 0.0;
+	m[13] = 0.0;
+	m[14] = 0.0;
+	m[15] = 1.0;
+}
+
+static GLuint load_shader(GLenum shaderType, const char *src) {
+	GLint status = 0, len = 0;
+	GLuint shader;
+
+	if (!(shader = glCreateShader(shaderType)))
+		return 0;
+
+	glShaderSource(shader, 1, &src, NULL);
+	glCompileShader(shader);
+	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+
+	if (status)
+		return shader;
+
+	glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
+	if (len) {
+		char *msg = malloc(len);
+		if (msg) {
+			glGetShaderInfoLog(shader, len, NULL, msg);
+			msg[len-1] = 0;
+			fprintf(stderr, "error compiling shader:\n%s\n", msg);
+			free(msg);
+		}
+	}
+	glDeleteShader(shader);
+	return 0;
+}
+
+GLuint load_program(const char *vert_src, const char *frag_src) {
+	GLuint vert, frag, prog;
+	GLint status = 0, len = 0;
+
+	if (!(vert = load_shader(GL_VERTEX_SHADER, vert_src)))
+		return 0;
+	if (!(frag = load_shader(GL_FRAGMENT_SHADER, frag_src)))
+		goto fail_frag;
+	if (!(prog = glCreateProgram()))
+		goto fail_prog;
+
+	glAttachShader(prog, vert);
+	glAttachShader(prog, frag);
+	glLinkProgram(prog);
+
+	glGetProgramiv(prog, GL_LINK_STATUS, &status);
+	if (status)
+		return prog;
+
+	glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
+	if (len) {
+		char *buf = (char*) malloc(len);
+		if (buf) {
+			glGetProgramInfoLog(prog, len, NULL, buf);
+			buf[len-1] = 0;
+			fprintf(stderr, "error linking program:\n%s\n", buf);
+			free(buf);
+		}
+	}
+	glDeleteProgram(prog);
+fail_prog:
+	glDeleteShader(frag);
+fail_frag:
+	glDeleteShader(vert);
+	return 0;
+}
+
+int select_config_for_window(EGLDisplay dpy, EGLint *attr,
+	unsigned format, EGLConfig *config) {
+	EGLint R,G,B,A,r,g,b,a;
+	EGLint i, n, max;
+	EGLConfig *cfg;
+
+	switch (format) {
+	case HAL_PIXEL_FORMAT_RGBA_8888:
+	case HAL_PIXEL_FORMAT_BGRA_8888:
+		R = G = B = A = 8;
+		break;
+	case HAL_PIXEL_FORMAT_RGB_565:
+		R = 5; G = 6; B = 5; A = 0;
+		break;
+	default:
+		fprintf(stderr, "unknown fb pixel format %d\n", format);
+		return -1;
+	}
+
+	if (eglGetConfigs(dpy, NULL, 0, &max) == EGL_FALSE) {
+		fprintf(stderr, "no EGL configurations available?!\n");
+		return -1;
+	}
+
+	cfg = (EGLConfig*) malloc(sizeof(EGLConfig) * max);
+	if (!cfg)
+		return -1;
+
+	if (eglChooseConfig(dpy, attr, cfg, max, &n) == EGL_FALSE) {
+		fprintf(stderr, "eglChooseConfig failed\n");
+		return -1;
+	}
+
+	for (i = 0; i < n; i++) {
+		EGLint r,g,b,a;
+		eglGetConfigAttrib(dpy, cfg[i], EGL_RED_SIZE,   &r);
+		eglGetConfigAttrib(dpy, cfg[i], EGL_GREEN_SIZE, &g);
+		eglGetConfigAttrib(dpy, cfg[i], EGL_BLUE_SIZE,  &b);
+		eglGetConfigAttrib(dpy, cfg[i], EGL_ALPHA_SIZE, &a);
+		if (r == R && g == G && b == B && a == A) {
+			*config = cfg[i];
+			free(cfg);
+			return 0;
+		}
+	}
+
+	fprintf(stderr, "cannot find matching config\n");
+	free(cfg);
+	return -1;
+}
+
+static struct CNativeWindow *_cnw = 0;
+
+int egl_create(EGLDisplay *_display, EGLSurface *_surface, int *_w, int *_h) {
+	EGLBoolean res;
+	EGLConfig config = { 0 };
+	EGLint context_attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+	EGLint config_attrs[] = {
+		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+		EGL_NONE };
+	EGLint major, minor;
+	EGLContext context;
+	EGLSurface surface;
+	EGLint w, h;
+	EGLDisplay display;
+	EGLNativeWindowType window;
+	unsigned width, height, format;
+	struct CNativeWindow *cnw;
+
+	display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+	if (display == EGL_NO_DISPLAY)
+		return -1;
+
+	if (!(res = eglInitialize(display, &major, &minor)))
+		return -1;
+
+	fprintf(stderr, "egl version: %d.%d\n", major, minor);
+
+	if ((cnw = cnw_create()) == 0)
+		return -1;
+
+	cnw_info(cnw, &width, &height, &format);
+	window = (EGLNativeWindowType) cnw;
+
+	if ((res = select_config_for_window(display, config_attrs, format, &config)))
+		goto fail;
+
+	surface = eglCreateWindowSurface(display, config, window, NULL);
+	if (surface == EGL_NO_SURFACE)
+		goto fail;
+
+	context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attrs);
+	if (context == EGL_NO_CONTEXT)
+		goto fail;
+
+	if (!(res = eglMakeCurrent(display, surface, surface, context)))
+		goto fail;
+
+	eglQuerySurface(display, surface, EGL_WIDTH, &w);
+	eglQuerySurface(display, surface, EGL_HEIGHT, &h);
+
+	fprintf(stderr, "window: %d x %d\n", w, h);
+
+	*_display = display;
+	*_surface = surface;
+	*_w = w;
+	*_h = h;
+
+	_cnw = cnw;
+	return 0;
+
+fail:
+	cnw_destroy(cnw);
+	return -1;
+}
+
+void egl_destroy(EGLDisplay display, EGLSurface surface) {
+	if (_cnw) {
+		eglDestroySurface(display, surface);
+		eglTerminate(display);
+		cnw_destroy(_cnw);
+		_cnw = 0;
+	}
+}
diff --git a/tests/hwc/util.h b/tests/hwc/util.h
new file mode 100644
index 0000000..a0d38ce
--- /dev/null
+++ b/tests/hwc/util.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _GL_UTIL_H_
+#define _GL_UTIL_H_
+
+/* convenience */
+
+GLuint load_program(const char *vert_src, const char *frag_src);
+void matrix_init_ortho(GLfloat *m, float w, float h);
+
+/* context setup / teardown */
+
+int egl_create(EGLDisplay *_display, EGLSurface *_surface, int *_w, int *_h);
+void egl_destroy(EGLDisplay display, EGLSurface surface);
+
+/* internals needed by util.c */
+
+struct CNativeWindow;
+struct CNativeWindow *cnw_create(void);
+void cnw_destroy(struct CNativeWindow *win);
+void cnw_info(struct CNativeWindow *win,
+	unsigned *w, unsigned *h, unsigned *fmt);
+
+#endif