am 588f7259: am f4530d6e: Merge "Add missing includes."

* commit '588f725985ef0757dcf3e1257471b9c91dd4f106':
  Add missing includes.
diff --git a/include/hardware/audio_effect.h b/include/hardware/audio_effect.h
index ee48e4c..41cd2e6 100644
--- a/include/hardware/audio_effect.h
+++ b/include/hardware/audio_effect.h
@@ -344,9 +344,10 @@
     //    Output:
     //          returned value: 0       successful operation
     //                          -EINVAL invalid interface handle or
-    //                                  invalid command/reply size or format according to command code
-    //              The return code should be restricted to indicate problems related to the this
-    //              API specification. Status related to the execution of a particular command should be
+    //                                  invalid command/reply size or format according to
+    //                                  command code
+    //              The return code should be restricted to indicate problems related to this API
+    //              specification. Status related to the execution of a particular command should be
     //              indicated as part of the reply field.
     //
     //          *pReplyData updated with command response
@@ -937,11 +938,12 @@
     //
     //    Input:
     //          uuid:    pointer to the effect uuid.
-    //          sessionId:  audio session to which this effect instance will be attached. All effects
-    //              created with the same session ID are connected in series and process the same signal
-    //              stream. Knowing that two effects are part of the same effect chain can help the
-    //              library implement some kind of optimizations.
-    //          ioId:   identifies the output or input stream this effect is directed to at audio HAL.
+    //          sessionId:  audio session to which this effect instance will be attached.
+    //              All effects created with the same session ID are connected in series and process
+    //              the same signal stream. Knowing that two effects are part of the same effect
+    //              chain can help the library implement some kind of optimizations.
+    //          ioId:   identifies the output or input stream this effect is directed to in
+    //              audio HAL.
     //              For future use especially with tunneled HW accelerated effects
     //
     //    Input/Output:
diff --git a/include/hardware/camera_common.h b/include/hardware/camera_common.h
index dadbc8f..88c4379 100644
--- a/include/hardware/camera_common.h
+++ b/include/hardware/camera_common.h
@@ -20,6 +20,7 @@
 #define ANDROID_INCLUDE_CAMERA_COMMON_H
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <sys/cdefs.h>
 #include <sys/types.h>
 #include <cutils/native_handle.h>
@@ -85,6 +86,27 @@
  *   The standard hardware module open call (common.methods->open) continues
  *   to open the camera device with the latest supported version, which is
  *   also the version listed in camera_info_t.device_version.
+ *
+ *******************************************************************************
+ * Version: 2.4 [CAMERA_MODULE_API_VERSION_2_4]
+ *
+ * This camera module version adds below API changes:
+ *
+ * 1. Torch mode support. The framework can use it to turn on torch mode for
+ *    any camera device that has a flash unit, without opening a camera device. The
+ *    camera device has a higher priority accessing the flash unit than the camera
+ *    module; opening a camera device will turn off the torch if it had been enabled
+ *    through the module interface. When there are any resource conflicts, such as
+ *    open() is called to open a camera device, the camera HAL module must notify the
+ *    framework through the torch mode status callback that the torch mode has been
+ *    turned off.
+ *
+ * 2. External camera (e.g. USB hot-plug camera) support. The API updates specify that
+ *    the camera static info is only available when camera is connected and ready to
+ *    use for external hot-plug cameras. Calls to get static info will be invalid
+ *    calls when camera status is not CAMERA_DEVICE_STATUS_PRESENT. The frameworks
+ *    will only count on device status change callbacks to manage the available external
+ *    camera list.
  */
 
 /**
@@ -100,8 +122,9 @@
 #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_2_3 HARDWARE_MODULE_API_VERSION(2, 3)
+#define CAMERA_MODULE_API_VERSION_2_4 HARDWARE_MODULE_API_VERSION(2, 4)
 
-#define CAMERA_MODULE_API_VERSION_CURRENT CAMERA_MODULE_API_VERSION_2_3
+#define CAMERA_MODULE_API_VERSION_CURRENT CAMERA_MODULE_API_VERSION_2_4
 
 /**
  * All device versions <= HARDWARE_DEVICE_API_VERSION(1, 0xFF) must be treated
@@ -125,11 +148,19 @@
 
 typedef struct camera_info {
     /**
-     * The direction that the camera faces to. It should be CAMERA_FACING_BACK
-     * or CAMERA_FACING_FRONT.
+     * The direction that the camera faces to. See system/core/include/system/camera.h
+     * for camera facing definitions.
      *
-     * Version information:
-     *   Valid in all camera_module versions
+     * Version information (based on camera_module_t.common.module_api_version):
+     *
+     * CAMERA_MODULE_API_VERSION_2_3 or lower:
+     *
+     *   It should be CAMERA_FACING_BACK or CAMERA_FACING_FRONT.
+     *
+     * CAMERA_MODULE_API_VERSION_2_4 or higher:
+     *
+     *   It should be CAMERA_FACING_BACK, CAMERA_FACING_FRONT or
+     *   CAMERA_FACING_EXTERNAL.
      */
     int facing;
 
@@ -145,8 +176,16 @@
      * top side of a front-facing camera sensor is aligned with the right of the
      * screen, the value should be 270.
      *
-     * Version information:
-     *   Valid in all camera_module versions
+     * Version information (based on camera_module_t.common.module_api_version):
+     *
+     * CAMERA_MODULE_API_VERSION_2_3 or lower:
+     *
+     *   Valid in all camera_module versions.
+     *
+     * CAMERA_MODULE_API_VERSION_2_4 or higher:
+     *
+     *   Valid if camera facing is CAMERA_FACING_BACK or CAMERA_FACING_FRONT,
+     *   not valid if camera facing is CAMERA_FACING_EXTERNAL.
      */
     int orientation;
 
@@ -168,9 +207,9 @@
     uint32_t device_version;
 
     /**
-     * The camera's fixed characteristics, which include all camera metadata in
-     * the android.*.info.* sections. This should be a sorted metadata buffer,
-     * and may not be modified or freed by the caller. The pointer should remain
+     * The camera's fixed characteristics, which include all static camera metadata
+     * specified in system/media/camera/docs/docs.html. This should be a sorted metadata
+     * buffer, and may not be modified or freed by the caller. The pointer should remain
      * valid for the lifetime of the camera module, and values in it may not
      * change after it is returned by get_camera_info().
      *
@@ -211,33 +250,138 @@
 typedef enum camera_device_status {
     /**
      * The camera device is not currently connected, and opening it will return
-     * failure. Calls to get_camera_info must still succeed, and provide the
-     * same information it would if the camera were connected
+     * failure.
+     *
+     * Version information (based on camera_module_t.common.module_api_version):
+     *
+     * CAMERA_MODULE_API_VERSION_2_3 or lower:
+     *
+     *   Calls to get_camera_info must still succeed, and provide the same information
+     *   it would if the camera were connected.
+     *
+     * CAMERA_MODULE_API_VERSION_2_4:
+     *
+     *   The camera device at this status must return -EINVAL for get_camera_info call,
+     *   as the device is not connected.
      */
     CAMERA_DEVICE_STATUS_NOT_PRESENT = 0,
 
     /**
-     * The camera device is connected, and opening it will succeed. The
-     * information returned by get_camera_info cannot change due to this status
-     * change. By default, the framework will assume all devices are in this
-     * state.
+     * The camera device is connected, and opening it will succeed.
+     *
+     * CAMERA_MODULE_API_VERSION_2_3 or lower:
+     *
+     *   The information returned by get_camera_info cannot change due to this status
+     *   change. By default, the framework will assume all devices are in this state.
+     *
+     * CAMERA_MODULE_API_VERSION_2_4:
+     *
+     *   The information returned by get_camera_info will become valid after a device's
+     *   status changes to this. By default, the framework will assume all devices are in
+     *   this state.
      */
     CAMERA_DEVICE_STATUS_PRESENT = 1,
 
     /**
      * The camera device is connected, but it is undergoing an enumeration and
-     * so opening the device will return -EBUSY. Calls to get_camera_info
-     * must still succeed, as if the camera was in the PRESENT status.
+     * so opening the device will return -EBUSY.
+     *
+     * CAMERA_MODULE_API_VERSION_2_3 or lower:
+     *
+     *   Calls to get_camera_info must still succeed, as if the camera was in the
+     *   PRESENT status.
+     *
+     * CAMERA_MODULE_API_VERSION_2_4:
+     *
+     *   The camera device at this status must return -EINVAL for get_camera_info for call,
+     *   as the device is not ready.
      */
     CAMERA_DEVICE_STATUS_ENUMERATING = 2,
 
 } camera_device_status_t;
 
 /**
+ * torch_mode_status_t:
+ *
+ * The current status of the torch mode, as provided by the HAL through the
+ * camera_module_callbacks.torch_mode_status_change() call.
+ *
+ * The torch mode status of a camera device is applicable only when the camera
+ * device is present. The framework will not call set_torch_mode() to turn on
+ * torch mode of a camera device if the camera device is not present. At module
+ * load time, the framework will assume torch modes are in the
+ * TORCH_MODE_STATUS_AVAILABLE state if the camera device is present and
+ * android.flash.info.available is reported as true via get_camera_info() call.
+ *
+ * The behaviors of the camera HAL module that the framework expects in the
+ * following situations when a camera device's status changes:
+ *  1. A previously-disconnected camera device becomes connected.
+ *      After camera_module_callbacks::camera_device_status_change() is invoked
+ *      to inform the framework that the camera device is present, the framework
+ *      will assume the camera device's torch mode is in
+ *      TORCH_MODE_STATUS_AVAILABLE state. The camera HAL module does not need
+ *      to invoke camera_module_callbacks::torch_mode_status_change() unless the
+ *      flash unit is unavailable to use by set_torch_mode().
+ *
+ *  2. A previously-connected camera becomes disconnected.
+ *      After camera_module_callbacks::camera_device_status_change() is invoked
+ *      to inform the framework that the camera device is not present, the
+ *      framework will not call set_torch_mode() for the disconnected camera
+ *      device until its flash unit becomes available again. The camera HAL
+ *      module does not need to invoke
+ *      camera_module_callbacks::torch_mode_status_change() separately to inform
+ *      that the flash unit has become unavailable.
+ *
+ *  3. open() is called to open a camera device.
+ *      The camera HAL module must invoke
+ *      camera_module_callbacks::torch_mode_status_change() for all flash units
+ *      that have entered TORCH_MODE_STATUS_RESOURCE_BUSY state and can not be
+ *      turned on by calling set_torch_mode() anymore due to this open() call.
+ *
+ *  4. close() is called to close a camera device.
+ *      The camera HAL module must invoke
+ *      camera_module_callbacks::torch_mode_status_change() for all flash units
+ *      that have entered TORCH_MODE_STATUS_AVAILABLE state and can be turned
+ *      on by calling set_torch_mode() again because of enough resources freed
+ *      up by this close() call.
+ *
+ *  Note that the framework calling set_torch_mode() should not trigger any
+ *  callbacks.
+ */
+typedef enum torch_mode_status {
+    /**
+     * The flash unit is available and the torch mode can be turned on by
+     * calling set_torch_mode(). By default, the framework will assume all
+     * flash units of all present camera devices are in this state if
+     * android.flash.info.available is reported as true via get_camera_info()
+     * call.
+     */
+    TORCH_MODE_STATUS_AVAILABLE = 0,
+
+    /**
+     * The flash unit is no longer available and the torch mode can not be
+     * turned on by calling set_torch_mode(). If the torch mode is on, it
+     * will be turned off by HAL before HAL calls torch_mode_status_change().
+     */
+    TORCH_MODE_STATUS_RESOURCE_BUSY = 1,
+
+} torch_mode_status_t;
+
+/**
  * Callback functions for the camera HAL module to use to inform the framework
- * of changes to the camera subsystem. These are called only by HAL modules
- * implementing version CAMERA_MODULE_API_VERSION_2_1 or higher of the HAL
- * module API interface.
+ * of changes to the camera subsystem.
+ *
+ * Version information (based on camera_module_t.common.module_api_version):
+ *
+ * Each callback is called only by HAL modules implementing the indicated
+ * version or higher of the HAL module API interface.
+ *
+ *  CAMERA_MODULE_API_VERSION_2_1:
+ *    camera_device_status_change()
+ *
+ *  CAMERA_MODULE_API_VERSION_2_4:
+ *    torch_mode_status_change()
+
  */
 typedef struct camera_module_callbacks {
 
@@ -250,6 +394,8 @@
      * must call this method to inform the framework of any initially
      * NOT_PRESENT devices.
      *
+     * This callback is added for CAMERA_MODULE_API_VERSION_2_1.
+     *
      * camera_module_callbacks: The instance of camera_module_callbacks_t passed
      *   to the module with set_callbacks.
      *
@@ -263,6 +409,30 @@
             int camera_id,
             int new_status);
 
+    /**
+     * torch_mode_status_change:
+     *
+     * Callback to the framework to indicate that the state of the torch mode
+     * of the flash unit associated with a specific camera device has changed.
+     * At module load time, the framework will assume the torch modes are in
+     * the TORCH_MODE_STATUS_AVAILABLE state if android.flash.info.available
+     * is reported as true via get_camera_info() call.
+     *
+     * This callback is added for CAMERA_MODULE_API_VERSION_2_4.
+     *
+     * camera_module_callbacks: The instance of camera_module_callbacks_t
+     *   passed to the module with set_callbacks.
+     *
+     * camera_id: The ID of camera device whose flash unit has a new torch mode
+     *   status.
+     *
+     * new_status: The new status code, one of the torch_mode_status_t enums.
+     */
+    void (*torch_mode_status_change)(const struct camera_module_callbacks*,
+            const char* camera_id,
+            int new_status);
+
+
 } camera_module_callbacks_t;
 
 typedef struct camera_module {
@@ -304,8 +474,21 @@
      * simply the number converted to a string. That is, "0" for camera ID 0,
      * "1" for camera ID 1.
      *
-     * The value here must be static, and cannot change after the first call to
-     * this method
+     * Version information (based on camera_module_t.common.module_api_version):
+     *
+     * CAMERA_MODULE_API_VERSION_2_3 or lower:
+     *
+     *   The value here must be static, and cannot change after the first call
+     *   to this method.
+     *
+     * CAMERA_MODULE_API_VERSION_2_4 or higher:
+     *
+     *   The value here must be static, and must count only built-in cameras,
+     *   which have CAMERA_FACING_BACK or CAMERA_FACING_FRONT camera facing values
+     *   (camera_info.facing). The HAL must not include the external cameras
+     *   (camera_info.facing == CAMERA_FACING_EXTERNAL) into the return value
+     *   of this call. Frameworks will use camera_device_status_change callback
+     *   to manage number of external cameras.
      */
     int (*get_number_of_cameras)(void);
 
@@ -324,6 +507,14 @@
      *
      * -EINVAL:     The input arguments are invalid, i.e. the id is invalid,
      *              and/or the module is invalid.
+     *
+     * Version information (based on camera_module_t.common.module_api_version):
+     *
+     * CAMERA_MODULE_API_VERSION_2_4 or higher:
+     *
+     *   When a camera is disconnected, its camera id becomes invalid. Calling this
+     *   this method with this invalid camera id will get -EINVAL and NULL camera
+     *   static metadata (camera_info.static_camera_characteristics).
      */
     int (*get_camera_info)(int camera_id, struct camera_info *info);
 
@@ -425,8 +616,51 @@
     int (*open_legacy)(const struct hw_module_t* module, const char* id,
             uint32_t halVersion, struct hw_device_t** device);
 
+    /**
+     * set_torch_mode:
+     *
+     * Turn on or off the torch mode of the flash unit associated with a given
+     * camera ID. This function is blocking until the operation completes or
+     * fails.
+     *
+     * The camera device has a higher priority accessing the flash unit. When
+     * there are any resource conflicts, such as open() is called to open a
+     * camera device, HAL module must notify the framework through
+     * camera_module_callbacks.torch_mode_status_change() that the
+     * torch mode has been turned off and the torch mode state has become
+     * TORCH_MODE_STATUS_RESOURCE_BUSY. When resources to turn on torch mode
+     * become available again, HAL module must notify the framework through
+     * camera_module_callbacks.torch_mode_status_change() that the torch mode
+     * state has become available for set_torch_mode() to be called.
+     *
+     * Version information (based on camera_module_t.common.module_api_version):
+     *
+     * CAMERA_MODULE_API_VERSION_1_x/2_0/2_1/2_2/2_3:
+     *   Not provided by HAL module. Framework will not call this function.
+     *
+     * CAMERA_MODULE_API_VERSION_2_4:
+     *   Valid to be called by the framework.
+     *
+     * Return values:
+     *
+     * 0:           On a successful operation.
+     *
+     * -ENOSYS:     The camera device does not support this operation. It is
+     *              returned if and only if android.flash.info.available is
+     *              false.
+     *
+     * -EBUSY:      The flash unit or the resource needed to turn on the torch
+     *              mode is busy, typically because the camera device is already
+     *              in use, or some other camera device is using enough
+     *              resources to make using the flash unit not possible.
+     *
+     * -EINVAL:     camera_id is invalid.
+     *
+     */
+    int (*set_torch_mode)(const char* camera_id, bool on);
+
     /* reserved for future use */
-    void* reserved[7];
+    void* reserved[6];
 } camera_module_t;
 
 __END_DECLS
diff --git a/modules/Android.mk b/modules/Android.mk
index 0725d3e..13a0b5b 100644
--- a/modules/Android.mk
+++ b/modules/Android.mk
@@ -1,4 +1,4 @@
 hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time \
-	power usbaudio audio_remote_submix camera consumerir sensors vibrator \
+	power usbaudio audio_remote_submix camera usbcamera consumerir sensors vibrator \
 	tv_input fingerprint
 include $(call all-named-subdir-makefiles,$(hardware_modules))
diff --git a/modules/camera/CameraHAL.cpp b/modules/camera/CameraHAL.cpp
index 6f64a0d..06f308f 100644
--- a/modules/camera/CameraHAL.cpp
+++ b/modules/camera/CameraHAL.cpp
@@ -185,6 +185,7 @@
     set_callbacks         : set_callbacks,
     get_vendor_tag_ops    : get_vendor_tag_ops,
     open_legacy           : NULL,
+    set_torch_mode        : NULL,
     reserved              : {0},
 };
 } // extern "C"
diff --git a/modules/usbaudio/Android.mk b/modules/usbaudio/Android.mk
index ec8a8c0..9df1e79 100644
--- a/modules/usbaudio/Android.mk
+++ b/modules/usbaudio/Android.mk
@@ -19,15 +19,12 @@
 LOCAL_MODULE := audio.usb.default
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_SRC_FILES := \
-	audio_hw.c \
-	alsa_device_profile.c \
-	alsa_device_proxy.c \
-	logging.c \
-	format.c
+	audio_hal.c
 LOCAL_C_INCLUDES += \
 	external/tinyalsa/include \
-	$(call include-path-for, audio-utils)
-LOCAL_SHARED_LIBRARIES := liblog libcutils libtinyalsa libaudioutils
+	$(call include-path-for, audio-utils) \
+	$(call include-path-for, alsa-utils)
+LOCAL_SHARED_LIBRARIES := liblog libcutils libtinyalsa libaudioutils libalsautils
 LOCAL_MODULE_TAGS := optional
 LOCAL_CFLAGS := -Wno-unused-parameter
 
diff --git a/modules/usbaudio/alsa_device_profile.c b/modules/usbaudio/alsa_device_profile.c
deleted file mode 100644
index 8e84471..0000000
--- a/modules/usbaudio/alsa_device_profile.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Copyright (C) 2014 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 "alsa_device_profile"
-/*#define LOG_NDEBUG 0*/
-/*#define LOG_PCM_PARAMS 0*/
-
-#include <errno.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <log/log.h>
-
-#include "alsa_device_profile.h"
-#include "format.h"
-#include "logging.h"
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-/*TODO - Evaluate if this value should/can be retrieved from a device-specific property */
-#define BUFF_DURATION_MS   5
-
-#define DEFAULT_PERIOD_SIZE 1024
-
-static const char * const format_string_map[] = {
-    "AUDIO_FORMAT_PCM_16_BIT",      /* "PCM_FORMAT_S16_LE", */
-    "AUDIO_FORMAT_PCM_32_BIT",      /* "PCM_FORMAT_S32_LE", */
-    "AUDIO_FORMAT_PCM_8_BIT",       /* "PCM_FORMAT_S8", */
-    "AUDIO_FORMAT_PCM_8_24_BIT",    /* "PCM_FORMAT_S24_LE", */
-    "AUDIO_FORMAT_PCM_24_BIT_PACKED"/* "PCM_FORMAT_S24_3LE" */
-};
-
-static const unsigned const format_byte_size_map[] = {
-    2, /* PCM_FORMAT_S16_LE */
-    4, /* PCM_FORMAT_S32_LE */
-    1, /* PCM_FORMAT_S8 */
-    4, /* PCM_FORMAT_S24_LE */
-    3, /* PCM_FORMAT_S24_3LE */
-};
-
-extern int8_t const pcm_format_value_map[50];
-
-/* sort these highest -> lowest (to default to best quality) */
-static const unsigned std_sample_rates[] =
-    {48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
-
-static void profile_reset(alsa_device_profile* profile)
-{
-    profile->card = profile->device = -1;
-
-    /* Fill the attribute arrays with invalid values */
-    size_t index;
-    for (index = 0; index < ARRAY_SIZE(profile->formats); index++) {
-        profile->formats[index] = PCM_FORMAT_INVALID;
-    }
-
-    for (index = 0; index < ARRAY_SIZE(profile->sample_rates); index++) {
-        profile->sample_rates[index] = 0;
-    }
-
-    for (index = 0; index < ARRAY_SIZE(profile->channel_counts); index++) {
-        profile->channel_counts[index] = 0;
-    }
-
-    profile->min_period_size = profile->max_period_size = 0;
-    profile->min_channel_count = profile->max_channel_count = DEFAULT_CHANNEL_COUNT;
-
-    profile->is_valid = false;
-}
-
-void profile_init(alsa_device_profile* profile, int direction)
-{
-    profile->direction = direction;
-    profile_reset(profile);
-}
-
-bool profile_is_initialized(alsa_device_profile* profile)
-{
-    return profile->card >= 0 && profile->device >= 0;
-}
-
-bool profile_is_valid(alsa_device_profile* profile) {
-    return profile->is_valid;
-}
-
-bool profile_is_cached_for(alsa_device_profile* profile, int card, int device) {
-    return card == profile->card && device == profile->device;
-}
-
-void profile_decache(alsa_device_profile* profile) {
-    profile_reset(profile);
-}
-
-/*
- * Returns the supplied value rounded up to the next even multiple of 16
- */
-static unsigned int round_to_16_mult(unsigned int size)
-{
-    return (size + 15) & ~15;   // 0xFFFFFFF0;
-}
-
-/*
- * Returns the system defined minimum period size based on the supplied sample rate.
- */
-unsigned profile_calc_min_period_size(alsa_device_profile* profile, unsigned sample_rate)
-{
-    ALOGV("profile_calc_min_period_size(%p, rate:%d)", profile, sample_rate);
-    if (profile == NULL) {
-        return DEFAULT_PERIOD_SIZE;
-    } else {
-        unsigned num_sample_frames = (sample_rate * BUFF_DURATION_MS) / 1000;
-        if (num_sample_frames < profile->min_period_size) {
-            num_sample_frames = profile->min_period_size;
-        }
-        return round_to_16_mult(num_sample_frames) * 2;
-    }
-}
-
-unsigned int profile_get_period_size(alsa_device_profile* profile, unsigned sample_rate)
-{
-    // return profile->default_config.period_size;
-    unsigned int period_size = profile_calc_min_period_size(profile, sample_rate);
-    ALOGV("profile_get_period_size(rate:%d) = %d", sample_rate, period_size);
-    return period_size;
-}
-
-/*
- * Sample Rate
- */
-unsigned profile_get_default_sample_rate(alsa_device_profile* profile)
-{
-    /*
-     * TODO this won't be right in general. we should store a preferred rate as we are scanning.
-     * But right now it will return the highest rate, which may be correct.
-     */
-    return profile_is_valid(profile) ? profile->sample_rates[0] : DEFAULT_SAMPLE_RATE;
-}
-
-bool profile_is_sample_rate_valid(alsa_device_profile* profile, unsigned rate)
-{
-    if (profile_is_valid(profile)) {
-        size_t index;
-        for (index = 0; profile->sample_rates[index] != 0; index++) {
-            if (profile->sample_rates[index] == rate) {
-                return true;
-            }
-        }
-
-        return false;
-    } else {
-        return rate == DEFAULT_SAMPLE_RATE;
-    }
-}
-
-/*
- * Format
- */
-enum pcm_format profile_get_default_format(alsa_device_profile* profile)
-{
-    /*
-     * TODO this won't be right in general. we should store a preferred format as we are scanning.
-     */
-    return profile_is_valid(profile) ? profile->formats[0] : DEFAULT_SAMPLE_FORMAT;
-}
-
-bool profile_is_format_valid(alsa_device_profile* profile, enum pcm_format fmt) {
-    if (profile_is_valid(profile)) {
-        size_t index;
-        for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) {
-            if (profile->formats[index] == fmt) {
-                return true;
-            }
-        }
-
-        return false;
-    } else {
-        return fmt == DEFAULT_SAMPLE_FORMAT;
-    }
-}
-
-/*
- * Channels
- */
-unsigned profile_get_default_channel_count(alsa_device_profile* profile)
-{
-    return profile_is_valid(profile) ? profile->channel_counts[0] : DEFAULT_CHANNEL_COUNT;
-}
-
-bool profile_is_channel_count_valid(alsa_device_profile* profile, unsigned count)
-{
-    if (profile_is_initialized(profile)) {
-        return count >= profile->min_channel_count && count <= profile->max_channel_count;
-    } else {
-        return count == DEFAULT_CHANNEL_COUNT;
-    }
-}
-
-static bool profile_test_sample_rate(alsa_device_profile* profile, unsigned rate)
-{
-    struct pcm_config config = profile->default_config;
-    config.rate = rate;
-
-    bool works = false; /* let's be pessimistic */
-    struct pcm * pcm = pcm_open(profile->card, profile->device,
-                                profile->direction, &config);
-
-    if (pcm != NULL) {
-        works = pcm_is_ready(pcm);
-        pcm_close(pcm);
-    }
-
-    return works;
-}
-
-static unsigned profile_enum_sample_rates(alsa_device_profile* profile, unsigned min, unsigned max)
-{
-    unsigned num_entries = 0;
-    unsigned index;
-
-    for (index = 0; index < ARRAY_SIZE(std_sample_rates) &&
-                    num_entries < ARRAY_SIZE(profile->sample_rates) - 1;
-         index++) {
-        if (std_sample_rates[index] >= min && std_sample_rates[index] <= max
-                && profile_test_sample_rate(profile, std_sample_rates[index])) {
-            profile->sample_rates[num_entries++] = std_sample_rates[index];
-        }
-    }
-
-    return num_entries; /* return # of supported rates */
-}
-
-static unsigned profile_enum_sample_formats(alsa_device_profile* profile, struct pcm_mask * mask)
-{
-    const int num_slots = ARRAY_SIZE(mask->bits);
-    const int bits_per_slot = sizeof(mask->bits[0]) * 8;
-
-    const int table_size = ARRAY_SIZE(pcm_format_value_map);
-
-    int slot_index, bit_index, table_index;
-    table_index = 0;
-    int num_written = 0;
-    for (slot_index = 0; slot_index < num_slots && table_index < table_size;
-            slot_index++) {
-        unsigned bit_mask = 1;
-        for (bit_index = 0;
-                bit_index < bits_per_slot && table_index < table_size;
-                bit_index++) {
-            if ((mask->bits[slot_index] & bit_mask) != 0) {
-                enum pcm_format format = pcm_format_value_map[table_index];
-                /* Never return invalid (unrecognized) or 8-bit */
-                if (format != PCM_FORMAT_INVALID && format != PCM_FORMAT_S8) {
-                    profile->formats[num_written++] = format;
-                    if (num_written == ARRAY_SIZE(profile->formats) - 1) {
-                        /* leave at least one PCM_FORMAT_INVALID at the end */
-                        return num_written;
-                    }
-                }
-            }
-            bit_mask <<= 1;
-            table_index++;
-        }
-    }
-
-    return num_written;
-}
-
-static unsigned profile_enum_channel_counts(alsa_device_profile* profile, unsigned min, unsigned max)
-{
-    static const unsigned std_channel_counts[] = {8, 4, 2, 1};
-
-    unsigned num_counts = 0;
-    unsigned index;
-    /* TODO write a profile_test_channel_count() */
-    /* Ensure there is at least one invalid channel count to terminate the channel counts array */
-    for (index = 0; index < ARRAY_SIZE(std_channel_counts) &&
-                    num_counts < ARRAY_SIZE(profile->channel_counts) - 1;
-         index++) {
-        /* TODO Do we want a channel counts test? */
-        if (std_channel_counts[index] >= min && std_channel_counts[index] <= max /* &&
-            profile_test_channel_count(profile, channel_counts[index])*/) {
-            profile->channel_counts[num_counts++] = std_channel_counts[index];
-        }
-    }
-
-    return num_counts; /* return # of supported counts */
-}
-
-/*
- * Reads and decodes configuration info from the specified ALSA card/device.
- */
-static int read_alsa_device_config(alsa_device_profile * profile, struct pcm_config * config)
-{
-    ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)",
-          profile->card, profile->device, profile->direction);
-
-    if (profile->card < 0 || profile->device < 0) {
-        return -EINVAL;
-    }
-
-    struct pcm_params * alsa_hw_params =
-        pcm_params_get(profile->card, profile->device, profile->direction);
-    if (alsa_hw_params == NULL) {
-        return -EINVAL;
-    }
-
-    profile->min_period_size = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
-    profile->max_period_size = pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
-
-    profile->min_channel_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
-    profile->max_channel_count = pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS);
-
-    int ret = 0;
-
-    /*
-     * This Logging will be useful when testing new USB devices.
-     */
-#ifdef LOG_PCM_PARAMS
-    log_pcm_params(alsa_hw_params);
-#endif
-
-    config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
-    config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
-    config->period_size = profile_calc_min_period_size(profile, config->rate);
-    config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
-    config->format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
-#ifdef LOG_PCM_PARAMS
-    log_pcm_config(config, "read_alsa_device_config");
-#endif
-    if (config->format == PCM_FORMAT_INVALID) {
-        ret = -EINVAL;
-    }
-
-    pcm_params_free(alsa_hw_params);
-
-    return ret;
-}
-
-bool profile_read_device_info(alsa_device_profile* profile)
-{
-    if (!profile_is_initialized(profile)) {
-        return false;
-    }
-
-    /* let's get some defaults */
-    read_alsa_device_config(profile, &profile->default_config);
-    ALOGV("default_config chans:%d rate:%d format:%d count:%d size:%d",
-          profile->default_config.channels, profile->default_config.rate,
-          profile->default_config.format, profile->default_config.period_count,
-          profile->default_config.period_size);
-
-    struct pcm_params * alsa_hw_params = pcm_params_get(profile->card,
-                                                        profile->device,
-                                                        profile->direction);
-    if (alsa_hw_params == NULL) {
-        return false;
-    }
-
-    /* Formats */
-    struct pcm_mask * format_mask = pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT);
-    profile_enum_sample_formats(profile, format_mask);
-
-    /* Channels */
-    profile_enum_channel_counts(
-            profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS),
-            pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS));
-
-    /* Sample Rates */
-    profile_enum_sample_rates(
-            profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE),
-            pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE));
-
-    profile->is_valid = true;
-
-    return true;
-}
-
-char * profile_get_sample_rate_strs(alsa_device_profile* profile)
-{
-    char buffer[128];
-    buffer[0] = '\0';
-    int buffSize = ARRAY_SIZE(buffer);
-
-    char numBuffer[32];
-
-    int numEntries = 0;
-    unsigned index;
-    for (index = 0; profile->sample_rates[index] != 0; index++) {
-        if (numEntries++ != 0) {
-            strncat(buffer, "|", buffSize);
-        }
-        snprintf(numBuffer, sizeof(numBuffer), "%u", profile->sample_rates[index]);
-        strncat(buffer, numBuffer, buffSize);
-    }
-
-    return strdup(buffer);
-}
-
-char * profile_get_format_strs(alsa_device_profile* profile)
-{
-    /* TODO remove this hack when we have support for input in non PCM16 formats */
-    if (profile->direction == PCM_IN) {
-        return strdup("AUDIO_FORMAT_PCM_16_BIT");
-    }
-
-    char buffer[128];
-    buffer[0] = '\0';
-    int buffSize = ARRAY_SIZE(buffer);
-
-    int numEntries = 0;
-    unsigned index = 0;
-    for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) {
-        if (numEntries++ != 0) {
-            strncat(buffer, "|", buffSize);
-        }
-        strncat(buffer, format_string_map[profile->formats[index]], buffSize);
-    }
-
-    return strdup(buffer);
-}
-
-char * profile_get_channel_count_strs(alsa_device_profile* profile)
-{
-    static const char * const out_chans_strs[] = {
-        /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
-        /* 1 */"AUDIO_CHANNEL_OUT_MONO",
-        /* 2 */"AUDIO_CHANNEL_OUT_STEREO",
-        /* 3 */ /* "AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_FRONT_CENTER" */ NULL,
-        /* 4 */"AUDIO_CHANNEL_OUT_QUAD",
-        /* 5 */ /* "AUDIO_CHANNEL_OUT_QUAD|AUDIO_CHANNEL_OUT_FRONT_CENTER" */ NULL,
-        /* 6 */"AUDIO_CHANNEL_OUT_5POINT1",
-        /* 7 */ /* "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_BACK_CENTER" */ NULL,
-        /* 8 */"AUDIO_CHANNEL_OUT_7POINT1",
-        /* channel counts greater than this not considered */
-    };
-
-    static const char * const in_chans_strs[] = {
-        /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
-        /* 1 */"AUDIO_CHANNEL_IN_MONO",
-        /* 2 */"AUDIO_CHANNEL_IN_STEREO",
-        /* channel counts greater than this not considered */
-    };
-
-    const bool isOutProfile = profile->direction == PCM_OUT;
-
-    const char * const * const names_array = isOutProfile ? out_chans_strs : in_chans_strs;
-    const size_t names_size = isOutProfile ? ARRAY_SIZE(out_chans_strs)
-            : ARRAY_SIZE(in_chans_strs);
-
-    char buffer[256]; /* caution, may need to be expanded */
-    buffer[0] = '\0';
-    const int buffer_size = ARRAY_SIZE(buffer);
-    int num_entries = 0;
-    /* We currently support MONO and STEREO, and always report STEREO but some (many)
-     * USB Audio Devices may only announce support for MONO (a headset mic for example), or
-     * The total number of output channels. SO, if the device itself doesn't explicitly
-     * support STEREO, append to the channel config strings we are generating.
-     */
-    bool stereo_present = false;
-    unsigned index;
-    unsigned channel_count;
-
-    for (index = 0; (channel_count = profile->channel_counts[index]) != 0; index++) {
-        stereo_present = stereo_present || channel_count == 2;
-        if (channel_count < names_size && names_array[channel_count] != NULL) {
-            if (num_entries++ != 0) {
-                strncat(buffer, "|", buffer_size);
-            }
-            strncat(buffer, names_array[channel_count], buffer_size);
-        }
-    }
-
-    /* emulated modes:
-     * always expose stereo as we can emulate it for PCM_OUT
-     */
-    if (!stereo_present) {
-        if (num_entries++ != 0) {
-            strncat(buffer, "|", buffer_size);
-        }
-        strncat(buffer, names_array[2], buffer_size); /* stereo */
-    }
-
-    return strdup(buffer);
-}
diff --git a/modules/usbaudio/alsa_device_profile.h b/modules/usbaudio/alsa_device_profile.h
deleted file mode 100644
index 2c0da39..0000000
--- a/modules/usbaudio/alsa_device_profile.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2014 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_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROFILE_H
-#define ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROFILE_H
-
-#include <stdbool.h>
-
-#include <tinyalsa/asoundlib.h>
-
-#define MAX_PROFILE_FORMATS         6  /* We long support the 5 standard formats defined
-                                        * in asound.h, so we just need this to be 1 more
-                                        * than that */
-#define MAX_PROFILE_SAMPLE_RATES    10 /* this number needs to be 1 more than the number of
-                                        * standard formats in std_sample_rates[]
-                                        * (in alsa_device_profile.c) */
-#define MAX_PROFILE_CHANNEL_COUNTS  5  /* this number need to be 1 more than the number of
-                                        * standard channel formats in std_channel_counts[]
-                                        * (in alsa_device_profile.c) */
-
-#define DEFAULT_SAMPLE_RATE         44100
-#define DEFAULT_SAMPLE_FORMAT       PCM_FORMAT_S16_LE
-#define DEFAULT_CHANNEL_COUNT       2
-
-typedef struct  {
-    int card;
-    int device;
-    int direction; /* PCM_OUT or PCM_IN */
-
-    enum pcm_format formats[MAX_PROFILE_FORMATS];
-
-    unsigned sample_rates[MAX_PROFILE_SAMPLE_RATES];
-
-    unsigned channel_counts[MAX_PROFILE_CHANNEL_COUNTS];
-
-    bool is_valid;
-
-    /* read from the hardware device */
-    struct pcm_config default_config;
-
-    unsigned min_period_size;
-    unsigned max_period_size;
-
-    unsigned min_channel_count;
-    unsigned max_channel_count;
-} alsa_device_profile;
-
-void profile_init(alsa_device_profile* profile, int direction);
-bool profile_is_initialized(alsa_device_profile* profile);
-bool profile_is_valid(alsa_device_profile* profile);
-bool profile_is_cached_for(alsa_device_profile* profile, int card, int device);
-void profile_decache(alsa_device_profile* profile);
-
-bool profile_read_device_info(alsa_device_profile* profile);
-
-/* Audio Config Strings Methods */
-char * profile_get_sample_rate_strs(alsa_device_profile* profile);
-char * profile_get_format_strs(alsa_device_profile* profile);
-char * profile_get_channel_count_strs(alsa_device_profile* profile);
-
-/* Sample Rate Methods */
-unsigned profile_get_default_sample_rate(alsa_device_profile* profile);
-bool profile_is_sample_rate_valid(alsa_device_profile* profile, unsigned rate);
-
-/* Format Methods */
-enum pcm_format profile_get_default_format(alsa_device_profile* profile);
-bool profile_is_format_valid(alsa_device_profile* profile, enum pcm_format fmt);
-
-/* Channel Methods */
-unsigned profile_get_default_channel_count(alsa_device_profile* profile);
-bool profile_is_channel_count_valid(alsa_device_profile* profile, unsigned count);
-
-/* Utility */
-unsigned profile_calc_min_period_size(alsa_device_profile* profile, unsigned sample_rate);
-unsigned int profile_get_period_size(alsa_device_profile* profile, unsigned sample_rate);
-
-#endif /* ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROFILE_H */
diff --git a/modules/usbaudio/alsa_device_proxy.c b/modules/usbaudio/alsa_device_proxy.c
deleted file mode 100644
index 676f288..0000000
--- a/modules/usbaudio/alsa_device_proxy.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2014 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 "alsa_device_proxy"
-/*#define LOG_NDEBUG 0*/
-/*#define LOG_PCM_PARAMS 0*/
-
-#include <log/log.h>
-
-#include <errno.h>
-
-#include "alsa_device_proxy.h"
-
-#include "logging.h"
-
-#define DEFAULT_PERIOD_SIZE     1024
-#define DEFAULT_PERIOD_COUNT    2
-
-void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
-                   struct pcm_config * config)
-{
-    ALOGV("proxy_prepare()");
-
-    proxy->profile = profile;
-
-#ifdef LOG_PCM_PARAMS
-    log_pcm_config(config, "proxy_setup()");
-#endif
-
-    proxy->alsa_config.format =
-        config->format != PCM_FORMAT_INVALID && profile_is_format_valid(profile, config->format)
-            ? config->format : profile->default_config.format;
-    proxy->alsa_config.rate =
-        config->rate != 0 && profile_is_sample_rate_valid(profile, config->rate)
-            ? config->rate : profile->default_config.rate;
-    proxy->alsa_config.channels =
-        config->channels != 0 && profile_is_channel_count_valid(profile, config->channels)
-            ? config->channels : profile->default_config.channels;
-
-    proxy->alsa_config.period_count = profile->default_config.period_count;
-    proxy->alsa_config.period_size =
-            profile_get_period_size(proxy->profile, proxy->alsa_config.rate);
-
-    // Hack for USB accessory audio.
-    // Here we set the correct value for period_count if tinyalsa fails to get it from the
-    // f_audio_source driver.
-    if (proxy->alsa_config.period_count == 0) {
-        proxy->alsa_config.period_count = 4;
-    }
-
-    proxy->pcm = NULL;
-}
-
-int proxy_open(alsa_device_proxy * proxy)
-{
-    alsa_device_profile* profile = proxy->profile;
-    ALOGV("proxy_open(card:%d device:%d %s)", profile->card, profile->device,
-          profile->direction == PCM_OUT ? "PCM_OUT" : "PCM_IN");
-
-    proxy->pcm = pcm_open(profile->card, profile->device, profile->direction, &proxy->alsa_config);
-    if (proxy->pcm == NULL) {
-        return -ENOMEM;
-    }
-
-    if (!pcm_is_ready(proxy->pcm)) {
-        ALOGE("[%s] proxy_open() pcm_open() failed: %s", LOG_TAG, pcm_get_error(proxy->pcm));
-#ifdef LOG_PCM_PARAMS
-        log_pcm_config(&proxy->alsa_config, "config");
-#endif
-        pcm_close(proxy->pcm);
-        proxy->pcm = NULL;
-        return -ENOMEM;
-    }
-
-    return 0;
-}
-
-void proxy_close(alsa_device_proxy * proxy)
-{
-    ALOGV("proxy_close() [pcm:%p]", proxy->pcm);
-
-    if (proxy->pcm != NULL) {
-        pcm_close(proxy->pcm);
-        proxy->pcm = NULL;
-    }
-}
-
-/*
- * Sample Rate
- */
-unsigned proxy_get_sample_rate(const alsa_device_proxy * proxy)
-{
-    return proxy->alsa_config.rate;
-}
-
-/*
- * Format
- */
-enum pcm_format proxy_get_format(const alsa_device_proxy * proxy)
-{
-    return proxy->alsa_config.format;
-}
-
-/*
- * Channel Count
- */
-unsigned proxy_get_channel_count(const alsa_device_proxy * proxy)
-{
-    return proxy->alsa_config.channels;
-}
-
-/*
- * Other
- */
-unsigned int proxy_get_period_size(const alsa_device_proxy * proxy)
-{
-    return proxy->alsa_config.period_size;
-}
-
-unsigned int proxy_get_period_count(const alsa_device_proxy * proxy)
-{
-    return proxy->alsa_config.period_count;
-}
-
-unsigned proxy_get_latency(const alsa_device_proxy * proxy)
-{
-    return (proxy_get_period_size(proxy) * proxy_get_period_count(proxy) * 1000)
-               / proxy_get_sample_rate(proxy);
-}
-
-/*
- * I/O
- */
-int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count)
-{
-    return pcm_write(proxy->pcm, data, count);
-}
-
-int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count)
-{
-    return pcm_read(proxy->pcm, data, count);
-}
diff --git a/modules/usbaudio/alsa_device_proxy.h b/modules/usbaudio/alsa_device_proxy.h
deleted file mode 100644
index f090c56..0000000
--- a/modules/usbaudio/alsa_device_proxy.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2014 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_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROXY_H
-#define ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROXY_H
-
-#include <tinyalsa/asoundlib.h>
-
-#include "alsa_device_profile.h"
-
-typedef struct {
-    alsa_device_profile* profile;
-
-    struct pcm_config alsa_config;
-
-    struct pcm * pcm;
-} alsa_device_proxy;
-
-void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile * profile,
-                   struct pcm_config * config);
-
-unsigned proxy_get_sample_rate(const alsa_device_proxy * proxy);
-enum pcm_format proxy_get_format(const alsa_device_proxy * proxy);
-unsigned proxy_get_channel_count(const alsa_device_proxy * proxy);
-
-unsigned int proxy_get_period_size(const alsa_device_proxy * proxy);
-
-unsigned proxy_get_latency(const alsa_device_proxy * proxy);
-
-int proxy_open(alsa_device_proxy * proxy);
-void proxy_close(alsa_device_proxy * proxy);
-
-int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count);
-int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count);
-
-#endif /* ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROXY_H */
diff --git a/modules/usbaudio/audio_hw.c b/modules/usbaudio/audio_hal.c
similarity index 94%
rename from modules/usbaudio/audio_hw.c
rename to modules/usbaudio/audio_hal.c
index ad01833..2814e37 100644
--- a/modules/usbaudio/audio_hw.c
+++ b/modules/usbaudio/audio_hal.c
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "usb_audio_hw"
+#define LOG_TAG "modules.usbaudio.audio_hal"
 /*#define LOG_NDEBUG 0*/
 
 #include <errno.h>
@@ -51,7 +51,7 @@
 
 #include "alsa_device_profile.h"
 #include "alsa_device_proxy.h"
-#include "logging.h"
+#include "alsa_logging.h"
 
 #define DEFAULT_INPUT_BUFFER_SIZE_MS 20
 
@@ -184,10 +184,40 @@
     return num_in_samples * 2;
 }
 
+/*
+ * Extract the card and device numbers from the supplied key/value pairs.
+ *   kvpairs    A null-terminated string containing the key/value pairs or card and device.
+ *              i.e. "card=1;device=42"
+ *   card   A pointer to a variable to receive the parsed-out card number.
+ *   device A pointer to a variable to receive the parsed-out device number.
+ * NOTE: The variables pointed to by card and device return -1 (undefined) if the
+ *  associated key/value pair is not found in the provided string.
+ */
+static void parse_card_device_params(const char *kvpairs, int *card, int *device)
+{
+    struct str_parms * parms = str_parms_create_str(kvpairs);
+    char value[32];
+    int param_val;
+
+    // initialize to "undefined" state.
+    *card = -1;
+    *device = -1;
+
+    param_val = str_parms_get_str(parms, "card", value, sizeof(value));
+    if (param_val >= 0) {
+        *card = atoi(value);
+    }
+
+    param_val = str_parms_get_str(parms, "device", value, sizeof(value));
+    if (param_val >= 0) {
+        *device = atoi(value);
+    }
+
+    str_parms_destroy(parms);
+}
+
 static char * device_get_parameters(alsa_device_profile * profile, const char * keys)
 {
-    ALOGV("usb:audio_hw::device_get_parameters() keys:%s", keys);
-
     if (profile->card < 0 || profile->device < 0) {
         return strdup("");
     }
@@ -311,24 +341,15 @@
 
     struct stream_out *out = (struct stream_out *)stream;
 
-    char value[32];
-    int param_val;
     int routing = 0;
     int ret_value = 0;
     int card = -1;
     int device = -1;
 
-    struct str_parms * parms = str_parms_create_str(kvpairs);
     pthread_mutex_lock(&out->dev->lock);
     pthread_mutex_lock(&out->lock);
 
-    param_val = str_parms_get_str(parms, "card", value, sizeof(value));
-    if (param_val >= 0)
-        card = atoi(value);
-
-    param_val = str_parms_get_str(parms, "device", value, sizeof(value));
-    if (param_val >= 0)
-        device = atoi(value);
+    parse_card_device_params(kvpairs, &card, &device);
 
     if (card >= 0 && device >= 0 && !profile_is_cached_for(out->profile, card, device)) {
         /* cannot read pcm device info if playback is active */
@@ -349,7 +370,6 @@
 
     pthread_mutex_unlock(&out->lock);
     pthread_mutex_unlock(&out->dev->lock);
-    str_parms_destroy(parms);
 
     return ret_value;
 }
@@ -480,10 +500,11 @@
                                    audio_output_flags_t flags,
                                    struct audio_config *config,
                                    struct audio_stream_out **stream_out,
-                                   const char *address __unused)
+                                   const char *address /*__unused*/)
 {
-    ALOGV("usb:audio_hw::out adev_open_output_stream() handle:0x%X, device:0x%X, flags:0x%X",
-          handle, devices, flags);
+    ALOGV("usb:audio_hw::out adev_open_output_stream()"
+          "handle:0x%X, device:0x%X, flags:0x%X, addr:%s",
+          handle, devices, flags, address);
 
     struct audio_device *adev = (struct audio_device *)dev;
 
@@ -514,13 +535,20 @@
     out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
 
     out->dev = adev;
-
+    pthread_mutex_lock(&adev->lock);
     out->profile = &adev->out_profile;
 
     // build this to hand to the alsa_device_proxy
     struct pcm_config proxy_config;
     memset(&proxy_config, 0, sizeof(proxy_config));
 
+    /* Pull out the card/device pair */
+    parse_card_device_params(address, &(out->profile->card), &(out->profile->device));
+
+    profile_read_device_info(out->profile);
+
+    pthread_mutex_unlock(&adev->lock);
+
     int ret = 0;
 
     /* Rate */
@@ -585,8 +613,9 @@
 static void adev_close_output_stream(struct audio_hw_device *dev,
                                      struct audio_stream_out *stream)
 {
-    ALOGV("usb:audio_hw::out adev_close_output_stream()");
     struct stream_out *out = (struct stream_out *)stream;
+    ALOGV("usb:audio_hw::out adev_close_output_stream(c:%d d:%d)",
+          out->profile->card, out->profile->device);
 
     /* Close the pcm device */
     out_standby(&stream->common);
@@ -691,19 +720,10 @@
     int card = -1;
     int device = -1;
 
-    struct str_parms * parms = str_parms_create_str(kvpairs);
-
     pthread_mutex_lock(&in->dev->lock);
     pthread_mutex_lock(&in->lock);
 
-    /* Device Connection Message ("card=1,device=0") */
-    param_val = str_parms_get_str(parms, "card", value, sizeof(value));
-    if (param_val >= 0)
-        card = atoi(value);
-
-    param_val = str_parms_get_str(parms, "device", value, sizeof(value));
-    if (param_val >= 0)
-        device = atoi(value);
+    parse_card_device_params(kvpairs, &card, &device);
 
     if (card >= 0 && device >= 0 && !profile_is_cached_for(in->profile, card, device)) {
         /* cannot read pcm device info if playback is active */
@@ -725,8 +745,6 @@
     pthread_mutex_unlock(&in->lock);
     pthread_mutex_unlock(&in->dev->lock);
 
-    str_parms_destroy(parms);
-
     return ret_value;
 }
 
@@ -890,7 +908,7 @@
                                   struct audio_config *config,
                                   struct audio_stream_in **stream_in,
                                   audio_input_flags_t flags __unused,
-                                  const char *address __unused,
+                                  const char *address /*__unused*/,
                                   audio_source_t source __unused)
 {
     ALOGV("usb: in adev_open_input_stream() rate:%" PRIu32 ", chanMask:0x%" PRIX32 ", fmt:%" PRIu8,
@@ -921,12 +939,19 @@
     in->stream.get_input_frames_lost = in_get_input_frames_lost;
 
     in->dev = (struct audio_device *)dev;
+    pthread_mutex_lock(&in->dev->lock);
 
     in->profile = &in->dev->in_profile;
 
     struct pcm_config proxy_config;
     memset(&proxy_config, 0, sizeof(proxy_config));
 
+    /* Pull out the card/device pair */
+    parse_card_device_params(address, &(in->profile->card), &(in->profile->device));
+
+    profile_read_device_info(in->profile);
+    pthread_mutex_unlock(&in->dev->lock);
+
     /* Rate */
     if (config->sample_rate == 0) {
         proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(in->profile);
diff --git a/modules/usbaudio/format.c b/modules/usbaudio/format.c
deleted file mode 100644
index 6aac1d3..0000000
--- a/modules/usbaudio/format.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2014 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 "usb_profile"
-/*#define LOG_NDEBUG 0*/
-
-#include "format.h"
-
-#include <tinyalsa/asoundlib.h>
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-/*
- * Maps from bit position in pcm_mask to AUDIO_ format constants.
- */
-static audio_format_t const format_value_map[] = {
-    AUDIO_FORMAT_PCM_8_BIT,           /* 00 - SNDRV_PCM_FORMAT_S8 */
-    AUDIO_FORMAT_PCM_8_BIT,           /* 01 - SNDRV_PCM_FORMAT_U8 */
-    AUDIO_FORMAT_PCM_16_BIT,          /* 02 - SNDRV_PCM_FORMAT_S16_LE */
-    AUDIO_FORMAT_INVALID,             /* 03 - SNDRV_PCM_FORMAT_S16_BE */
-    AUDIO_FORMAT_INVALID,             /* 04 - SNDRV_PCM_FORMAT_U16_LE */
-    AUDIO_FORMAT_INVALID,             /* 05 - SNDRV_PCM_FORMAT_U16_BE */
-    AUDIO_FORMAT_INVALID,             /* 06 - SNDRV_PCM_FORMAT_S24_LE */
-    AUDIO_FORMAT_INVALID,             /* 07 - SNDRV_PCM_FORMAT_S24_BE */
-    AUDIO_FORMAT_INVALID,             /* 08 - SNDRV_PCM_FORMAT_U24_LE */
-    AUDIO_FORMAT_INVALID,             /* 09 - SNDRV_PCM_FORMAT_U24_BE */
-    AUDIO_FORMAT_PCM_32_BIT,          /* 10 - SNDRV_PCM_FORMAT_S32_LE */
-    AUDIO_FORMAT_INVALID,             /* 11 - SNDRV_PCM_FORMAT_S32_BE */
-    AUDIO_FORMAT_INVALID,             /* 12 - SNDRV_PCM_FORMAT_U32_LE */
-    AUDIO_FORMAT_INVALID,             /* 13 - SNDRV_PCM_FORMAT_U32_BE */
-    AUDIO_FORMAT_PCM_FLOAT,           /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
-    AUDIO_FORMAT_INVALID,             /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
-    AUDIO_FORMAT_INVALID,             /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
-    AUDIO_FORMAT_INVALID,             /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
-    AUDIO_FORMAT_INVALID,             /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
-    AUDIO_FORMAT_INVALID,             /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
-    AUDIO_FORMAT_INVALID,             /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
-    AUDIO_FORMAT_INVALID,             /* 21 - SNDRV_PCM_FORMAT_A_LAW */
-    AUDIO_FORMAT_INVALID,             /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
-    AUDIO_FORMAT_INVALID,             /* 23 - SNDRV_PCM_FORMAT_MPEG */
-    AUDIO_FORMAT_INVALID,             /* 24 - SNDRV_PCM_FORMAT_GSM */
-    AUDIO_FORMAT_INVALID,             /* 25 -> 30 (not assigned) */
-    AUDIO_FORMAT_INVALID,
-    AUDIO_FORMAT_INVALID,
-    AUDIO_FORMAT_INVALID,
-    AUDIO_FORMAT_INVALID,
-    AUDIO_FORMAT_INVALID,
-    AUDIO_FORMAT_INVALID,             /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
-    AUDIO_FORMAT_PCM_24_BIT_PACKED,   /* 32 - SNDRV_PCM_FORMAT_S24_3LE */
-    AUDIO_FORMAT_INVALID,             /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
-    AUDIO_FORMAT_INVALID,             /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
-    AUDIO_FORMAT_INVALID,             /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
-    AUDIO_FORMAT_INVALID,             /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
-    AUDIO_FORMAT_INVALID,             /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
-    AUDIO_FORMAT_INVALID,             /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
-    AUDIO_FORMAT_INVALID,             /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
-    AUDIO_FORMAT_INVALID,             /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
-    AUDIO_FORMAT_INVALID,             /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
-    AUDIO_FORMAT_INVALID,             /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
-    AUDIO_FORMAT_INVALID,             /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
-    AUDIO_FORMAT_INVALID,             /* 44 - SNDRV_PCM_FORMAT_G723_24 */
-    AUDIO_FORMAT_INVALID,             /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
-    AUDIO_FORMAT_INVALID,             /* 46 - SNDRV_PCM_FORMAT_G723_40 */
-    AUDIO_FORMAT_INVALID,             /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
-    AUDIO_FORMAT_INVALID,             /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
-    AUDIO_FORMAT_INVALID              /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
-};
-
-audio_format_t get_format_for_mask(struct pcm_mask* mask)
-{
-    int num_slots = sizeof(mask->bits) / sizeof(mask->bits[0]);
-    int bits_per_slot = sizeof(mask->bits[0]) * 8;
-
-    int table_size = sizeof(format_value_map) / sizeof(format_value_map[0]);
-
-    int slot_index, bit_index, table_index;
-    table_index = 0;
-    int num_written = 0;
-    for (slot_index = 0; slot_index < num_slots; slot_index++) {
-        unsigned bit_mask = 1;
-        for (bit_index = 0; bit_index < bits_per_slot; bit_index++) {
-            /* don't return b-bit formats even if they are supported */
-            if (table_index >= 2 && (mask->bits[slot_index] & bit_mask) != 0) {
-                /* just return the first one */
-                return table_index < table_size
-                           ? format_value_map[table_index]
-                           : AUDIO_FORMAT_INVALID;
-            }
-            bit_mask <<= 1;
-            table_index++;
-        }
-    }
-
-    return AUDIO_FORMAT_INVALID;
-}
-
-/*
- * Maps from bit position in pcm_mask to PCM_ format constants.
- */
-int8_t const pcm_format_value_map[50] = {
-    PCM_FORMAT_S8,          /* 00 - SNDRV_PCM_FORMAT_S8 */
-    PCM_FORMAT_INVALID,     /* 01 - SNDRV_PCM_FORMAT_U8 */
-    PCM_FORMAT_S16_LE,      /* 02 - SNDRV_PCM_FORMAT_S16_LE */
-    PCM_FORMAT_INVALID,     /* 03 - SNDRV_PCM_FORMAT_S16_BE */
-    PCM_FORMAT_INVALID,     /* 04 - SNDRV_PCM_FORMAT_U16_LE */
-    PCM_FORMAT_INVALID,     /* 05 - SNDRV_PCM_FORMAT_U16_BE */
-    PCM_FORMAT_S24_3LE,     /* 06 - SNDRV_PCM_FORMAT_S24_LE */
-    PCM_FORMAT_INVALID,     /* 07 - SNDRV_PCM_FORMAT_S24_BE */
-    PCM_FORMAT_INVALID,     /* 08 - SNDRV_PCM_FORMAT_U24_LE */
-    PCM_FORMAT_INVALID,     /* 09 - SNDRV_PCM_FORMAT_U24_BE */
-    PCM_FORMAT_S32_LE,      /* 10 - SNDRV_PCM_FORMAT_S32_LE */
-    PCM_FORMAT_INVALID,     /* 11 - SNDRV_PCM_FORMAT_S32_BE */
-    PCM_FORMAT_INVALID,     /* 12 - SNDRV_PCM_FORMAT_U32_LE */
-    PCM_FORMAT_INVALID,     /* 13 - SNDRV_PCM_FORMAT_U32_BE */
-    PCM_FORMAT_INVALID,     /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
-    PCM_FORMAT_INVALID,     /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
-    PCM_FORMAT_INVALID,     /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
-    PCM_FORMAT_INVALID,     /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
-    PCM_FORMAT_INVALID,     /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
-    PCM_FORMAT_INVALID,     /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
-    PCM_FORMAT_INVALID,     /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
-    PCM_FORMAT_INVALID,     /* 21 - SNDRV_PCM_FORMAT_A_LAW */
-    PCM_FORMAT_INVALID,     /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
-    PCM_FORMAT_INVALID,     /* 23 - SNDRV_PCM_FORMAT_MPEG */
-    PCM_FORMAT_INVALID,     /* 24 - SNDRV_PCM_FORMAT_GSM */
-    PCM_FORMAT_INVALID,     /* 25 -> 30 (not assigned) */
-    PCM_FORMAT_INVALID,
-    PCM_FORMAT_INVALID,
-    PCM_FORMAT_INVALID,
-    PCM_FORMAT_INVALID,
-    PCM_FORMAT_INVALID,
-    PCM_FORMAT_INVALID,     /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
-    PCM_FORMAT_S24_3LE,     /* 32 - SNDRV_PCM_FORMAT_S24_3LE */ /* ??? */
-    PCM_FORMAT_INVALID,     /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
-    PCM_FORMAT_INVALID,     /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
-    PCM_FORMAT_INVALID,     /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
-    PCM_FORMAT_INVALID,     /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
-    PCM_FORMAT_INVALID,     /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
-    PCM_FORMAT_INVALID,     /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
-    PCM_FORMAT_INVALID,     /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
-    PCM_FORMAT_INVALID,     /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
-    PCM_FORMAT_INVALID,     /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
-    PCM_FORMAT_INVALID,     /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
-    PCM_FORMAT_INVALID,     /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
-    PCM_FORMAT_INVALID,     /* 44 - SNDRV_PCM_FORMAT_G723_24 */
-    PCM_FORMAT_INVALID,     /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
-    PCM_FORMAT_INVALID,     /* 46 - SNDRV_PCM_FORMAT_G723_40 */
-    PCM_FORMAT_INVALID,     /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
-    PCM_FORMAT_INVALID,     /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
-    PCM_FORMAT_INVALID      /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
-};
-
-/*
- * Scans the provided format mask and returns the first non-8 bit sample
- * format supported by the devices.
- */
-enum pcm_format get_pcm_format_for_mask(struct pcm_mask* mask)
-{
-    int num_slots = ARRAY_SIZE(mask->bits);
-    int bits_per_slot = sizeof(mask->bits[0]) * 8;
-
-    int table_size = ARRAY_SIZE(pcm_format_value_map);
-
-    int slot_index, bit_index, table_index;
-    table_index = 0;
-    int num_written = 0;
-    for (slot_index = 0; slot_index < num_slots && table_index < table_size; slot_index++) {
-        unsigned bit_mask = 1;
-        for (bit_index = 0; bit_index < bits_per_slot && table_index < table_size; bit_index++) {
-            /* skip any 8-bit formats */
-            if (table_index >= 2 && (mask->bits[slot_index] & bit_mask) != 0) {
-                /* just return the first one which will be at least 16-bit */
-                return (int)pcm_format_value_map[table_index];
-            }
-            bit_mask <<= 1;
-            table_index++;
-        }
-    }
-
-    return PCM_FORMAT_INVALID;
-}
diff --git a/modules/usbaudio/format.h b/modules/usbaudio/format.h
deleted file mode 100644
index e23935e..0000000
--- a/modules/usbaudio/format.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2014 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_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_FORMAT_H
-#define ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_FORMAT_H
-
-#include <system/audio.h>
-
-#include <tinyalsa/asoundlib.h>
-
-audio_format_t get_format_for_mask(struct pcm_mask* mask);
-enum pcm_format get_pcm_format_for_mask(struct pcm_mask* mask);
-
-#endif /* ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_FORMAT_H */
diff --git a/modules/usbaudio/logging.c b/modules/usbaudio/logging.c
deleted file mode 100644
index 0a05511..0000000
--- a/modules/usbaudio/logging.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2014 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 "usb_logging"
-/*#define LOG_NDEBUG 0*/
-
-#include <string.h>
-
-#include <log/log.h>
-
-#include "logging.h"
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-/*
- * Logging
- */
-void log_pcm_mask(const char* mask_name, struct pcm_mask* mask)
-{
-    const size_t num_slots = ARRAY_SIZE(mask->bits);
-    const size_t bits_per_slot = (sizeof(mask->bits[0]) * 8);
-    const size_t chars_per_slot = (bits_per_slot + 1); /* comma */
-
-    const size_t BUFF_SIZE =
-            (num_slots * chars_per_slot + 2 + 1);  /* brackets and null-terminator */
-    char buff[BUFF_SIZE];
-    buff[0] = '\0';
-
-    size_t slot_index, bit_index;
-    strcat(buff, "[");
-    for (slot_index = 0; slot_index < num_slots; slot_index++) {
-        unsigned bit_mask = 1;
-        for (bit_index = 0; bit_index < bits_per_slot; bit_index++) {
-            strcat(buff, (mask->bits[slot_index] & bit_mask) != 0 ? "1" : "0");
-            bit_mask <<= 1;
-        }
-        if (slot_index < num_slots - 1) {
-            strcat(buff, ",");
-        }
-    }
-    strcat(buff, "]");
-
-    ALOGV("%s: mask:%s", mask_name, buff);
-}
-
-void log_pcm_params(struct pcm_params * alsa_hw_params)
-{
-    ALOGV("usb:audio_hw - PCM_PARAM_SAMPLE_BITS min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_SAMPLE_BITS),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_SAMPLE_BITS));
-    ALOGV("usb:audio_hw - PCM_PARAM_FRAME_BITS min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_FRAME_BITS),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_FRAME_BITS));
-    log_pcm_mask("PCM_PARAM_FORMAT",
-                 pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
-    log_pcm_mask("PCM_PARAM_SUBFORMAT",
-                 pcm_params_get_mask(alsa_hw_params, PCM_PARAM_SUBFORMAT));
-    ALOGV("usb:audio_hw - PCM_PARAM_CHANNELS min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS));
-    ALOGV("usb:audio_hw - PCM_PARAM_RATE min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE));
-    ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_TIME min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_TIME),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_TIME));
-    ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_SIZE min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE));
-    ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_BYTES min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_BYTES),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_BYTES));
-    ALOGV("usb:audio_hw - PCM_PARAM_PERIODS min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIODS));
-    ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_TIME min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_TIME),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_TIME));
-    ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_SIZE min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_SIZE),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_SIZE));
-    ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_BYTES min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_BYTES),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_BYTES));
-    ALOGV("usb:audio_hw - PCM_PARAM_TICK_TIME min:%u, max:%u",
-          pcm_params_get_min(alsa_hw_params, PCM_PARAM_TICK_TIME),
-          pcm_params_get_max(alsa_hw_params, PCM_PARAM_TICK_TIME));
-}
-
-void log_pcm_config(struct pcm_config * config, const char* label) {
-    ALOGV("log_pcm_config() - %s", label);
-    ALOGV("  channels:%d", config->channels);
-    ALOGV("  rate:%d", config->rate);
-    ALOGV("  period_size:%d", config->period_size);
-    ALOGV("  period_count:%d", config->period_count);
-    ALOGV("  format:%d", config->format);
-#if 0
-    /* Values to use for the ALSA start, stop and silence thresholds.  Setting
-     * any one of these values to 0 will cause the default tinyalsa values to be
-     * used instead.  Tinyalsa defaults are as follows.
-     *
-     * start_threshold   : period_count * period_size
-     * stop_threshold    : period_count * period_size
-     * silence_threshold : 0
-     */
-    unsigned int start_threshold;
-    unsigned int stop_threshold;
-    unsigned int silence_threshold;
-
-    /* Minimum number of frames available before pcm_mmap_write() will actually
-     * write into the kernel buffer. Only used if the stream is opened in mmap mode
-     * (pcm_open() called with PCM_MMAP flag set).   Use 0 for default.
-     */
-    int avail_min;
-#endif
-}
diff --git a/modules/usbaudio/logging.h b/modules/usbaudio/logging.h
deleted file mode 100644
index b5640ed..0000000
--- a/modules/usbaudio/logging.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2014 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_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_LOGGING_H
-#define ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_LOGGING_H
-
-#include <tinyalsa/asoundlib.h>
-
-void log_pcm_mask(const char* mask_name, struct pcm_mask* mask);
-void log_pcm_params(struct pcm_params * alsa_hw_params);
-void log_pcm_config(struct pcm_config * config, const char* label);
-
-#endif /* ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_LOGGING_H */
diff --git a/modules/usbcamera/Android.mk b/modules/usbcamera/Android.mk
new file mode 100644
index 0000000..162b158
--- /dev/null
+++ b/modules/usbcamera/Android.mk
@@ -0,0 +1,45 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := camera.usb.default
+LOCAL_MODULE_RELATIVE_PATH := hw
+
+LOCAL_C_INCLUDES += \
+	system/core/include \
+	system/media/camera/include \
+
+LOCAL_SRC_FILES := \
+	CameraHAL.cpp \
+	Camera.cpp \
+	UsbCamera.cpp \
+	Metadata.cpp \
+	Stream.cpp \
+	HotplugThread.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+	libcamera_metadata \
+	libcutils \
+	liblog \
+	libsync \
+	libutils \
+
+LOCAL_CFLAGS += -Wall -Wextra -fvisibility=hidden
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/modules/usbcamera/Camera.cpp b/modules/usbcamera/Camera.cpp
new file mode 100644
index 0000000..cf62f7f
--- /dev/null
+++ b/modules/usbcamera/Camera.cpp
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Camera"
+#include <cutils/log.h>
+
+#include <cstdlib>
+#include <stdio.h>
+#include <hardware/camera3.h>
+#include <system/camera_metadata.h>
+#include <system/graphics.h>
+#include <utils/Mutex.h>
+#include "CameraHAL.h"
+#include "Metadata.h"
+#include "Stream.h"
+
+#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+#include <utils/Trace.h>
+
+#include "Camera.h"
+
+namespace usb_camera_hal {
+
+extern "C" {
+// Shim passed to the framework to close an opened device.
+static int close_device(hw_device_t* dev) {
+    camera3_device_t* cam_dev = reinterpret_cast<camera3_device_t*>(dev);
+    Camera* cam = static_cast<Camera*>(cam_dev->priv);
+    return cam->close();
+}
+
+// Get handle to camera from device priv data
+static Camera *camdev_to_camera(const camera3_device_t *dev) {
+    return reinterpret_cast<Camera*>(dev->priv);
+}
+
+static int initialize(const camera3_device_t *dev,
+        const camera3_callback_ops_t *callback_ops) {
+    return camdev_to_camera(dev)->initialize(callback_ops);
+}
+
+static int configure_streams(const camera3_device_t *dev,
+        camera3_stream_configuration_t *stream_list) {
+    return camdev_to_camera(dev)->configureStreams(stream_list);
+}
+
+static const camera_metadata_t *construct_default_request_settings(
+        const camera3_device_t *dev, int type) {
+    return camdev_to_camera(dev)->constructDefaultRequestSettings(type);
+}
+
+static int process_capture_request(const camera3_device_t *dev,
+        camera3_capture_request_t *request) {
+    return camdev_to_camera(dev)->processCaptureRequest(request);
+}
+
+static void dump(const camera3_device_t *dev, int fd) {
+    camdev_to_camera(dev)->dump(fd);
+}
+
+static int flush(const camera3_device_t *dev) {
+    return camdev_to_camera(dev)->flush();
+}
+
+} // extern "C"
+
+const camera3_device_ops_t Camera::sOps = {
+    .initialize = usb_camera_hal::initialize,
+    .configure_streams = usb_camera_hal::configure_streams,
+    .register_stream_buffers = NULL,
+    .construct_default_request_settings
+        = usb_camera_hal::construct_default_request_settings,
+    .process_capture_request = usb_camera_hal::process_capture_request,
+    .get_metadata_vendor_tag_ops = NULL,
+    .dump = usb_camera_hal::dump,
+    .flush = usb_camera_hal::flush,
+    .reserved = {0},
+};
+
+Camera::Camera(int id)
+          : mId(id),
+            mStaticInfo(NULL),
+            mBusy(false),
+            mCallbackOps(NULL),
+            mSettings(NULL),
+            mIsInitialized(false) {
+    memset(&mTemplates, 0, sizeof(mTemplates));
+    memset(&mDevice, 0, sizeof(mDevice));
+    mDevice.common.tag    = HARDWARE_DEVICE_TAG;
+    // TODO: Upgrade to HAL3.3
+    mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_2;
+    mDevice.common.close  = close_device;
+    mDevice.ops           = const_cast<camera3_device_ops_t*>(&sOps);
+    mDevice.priv          = this;
+}
+
+Camera::~Camera() {
+    if (mStaticInfo != NULL) {
+        free_camera_metadata(mStaticInfo);
+    }
+
+    for (int i = 0; i < CAMERA3_TEMPLATE_COUNT; i++) {
+        free_camera_metadata(mTemplates[i]);
+    }
+
+    if (mSettings != NULL) {
+        free_camera_metadata(mSettings);
+    }
+}
+
+int Camera::open(const hw_module_t *module, hw_device_t **device) {
+    ALOGI("%s:%d: Opening camera device", __func__, mId);
+    ATRACE_CALL();
+    android::Mutex::Autolock al(mDeviceLock);
+
+    if (mBusy) {
+        ALOGE("%s:%d: Error! Camera device already opened", __func__, mId);
+        return -EBUSY;
+    }
+
+    mBusy = true;
+    mDevice.common.module = const_cast<hw_module_t*>(module);
+    *device = &mDevice.common;
+    return openDevice();
+}
+
+int Camera::getInfo(struct camera_info *info) {
+    android::Mutex::Autolock al(mStaticInfoLock);
+
+    // TODO: update to CAMERA_FACING_EXTERNAL once the HAL API changes are merged.
+    info->facing = CAMERA_FACING_FRONT;
+    info->orientation = 0;
+    info->device_version = mDevice.common.version;
+    if (mStaticInfo == NULL) {
+        initStaticInfo();
+    }
+    info->static_camera_characteristics = mStaticInfo;
+    return 0;
+}
+
+void Camera::updateInfo() {
+    android::Mutex::Autolock al(mStaticInfoLock);
+    initStaticInfo();
+}
+
+int Camera::close() {
+    ALOGI("%s:%d: Closing camera device", __func__, mId);
+    ATRACE_CALL();
+    android::Mutex::Autolock al(mDeviceLock);
+
+    if (!mBusy) {
+        ALOGE("%s:%d: Error! Camera device not open", __func__, mId);
+        return -EINVAL;
+    }
+
+    mBusy = false;
+    mIsInitialized = false;
+    return closeDevice();
+}
+
+int Camera::initialize(const camera3_callback_ops_t *callback_ops) {
+    int res;
+
+    ALOGV("%s:%d: callback_ops=%p", __func__, mId, callback_ops);
+    ATRACE_CALL();
+    android::Mutex::Autolock al(mDeviceLock);
+
+    mCallbackOps = callback_ops;
+    // per-device specific initialization
+    res = initDevice();
+    if (res != 0) {
+        ALOGE("%s:%d: Failed to initialize device!", __func__, mId);
+        return res;
+    }
+
+    mIsInitialized = true;
+    return 0;
+}
+
+int Camera::configureStreams(camera3_stream_configuration_t *stream_config) {
+    camera3_stream_t *astream;
+    android::Vector<Stream *> newStreams;
+
+    ALOGV("%s:%d: stream_config=%p", __func__, mId, stream_config);
+    ATRACE_CALL();
+    android::Mutex::Autolock al(mDeviceLock);
+    if (!mIsInitialized) {
+        ALOGE("Device is not initialized yet");
+        return -EINVAL;
+    }
+
+    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;
+    }
+
+    ALOGV("%s:%d: Number of Streams: %d", __func__, mId,
+            stream_config->num_streams);
+    // Mark all current streams unused for now
+    for (size_t i = 0; i < mStreams.size(); 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.add(reuseStreamLocked(astream));
+        } else {
+            ALOGV("%s:%d: Creating new stream %d", __func__, mId, i);
+            newStreams.add(new Stream(mId, astream));
+        }
+
+        if (newStreams[i] == NULL) {
+            ALOGE("%s:%d: Error processing stream %d", __func__, mId, i);
+            goto err_out;
+        }
+        astream->priv = reinterpret_cast<void *>(newStreams[i]);
+    }
+
+    // Verify the set of streams in aggregate
+    if (!isValidStreamSetLocked(newStreams)) {
+        ALOGE("%s:%d: Invalid stream set", __func__, mId);
+        goto err_out;
+    }
+
+    // Set up all streams (calculate usage/max_buffers for each)
+    setupStreamsLocked(newStreams);
+
+    // Destroy all old streams and replace stream array with new one
+    destroyStreamsLocked(mStreams);
+    mStreams = newStreams;
+
+    // Clear out last seen settings metadata
+    updateSettingsLocked(NULL);
+    return 0;
+
+err_out:
+    // Clean up temporary streams, preserve existing mStreams
+    destroyStreamsLocked(newStreams);
+    return -EINVAL;
+}
+
+void Camera::destroyStreamsLocked(android::Vector<Stream *> &streams) {
+    for (size_t i = 0; i < streams.size(); i++) {
+        delete streams[i];
+    }
+    streams.clear();
+}
+
+Stream *Camera::reuseStreamLocked(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::isValidStreamSetLocked(const android::Vector<Stream *> &streams) {
+    int inputs = 0;
+    int outputs = 0;
+
+    if (streams.isEmpty()) {
+        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 (size_t i = 0; i < streams.size(); 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::setupStreamsLocked(android::Vector<Stream *> &streams) {
+    /*
+     * 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 vector 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.
+     *
+     * TODO: we just set all streams to be the same dummy values;
+     * real implementations will want to avoid USAGE_SW_{READ|WRITE}_OFTEN.
+     */
+    for (size_t i = 0; i < streams.size(); 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);
+    }
+}
+
+bool Camera::isValidTemplateType(int type) {
+    return type >= 1 && type < CAMERA3_TEMPLATE_COUNT;
+}
+
+const camera_metadata_t* Camera::constructDefaultRequestSettings(int type) {
+    ALOGV("%s:%d: type=%d", __func__, mId, type);
+    android::Mutex::Autolock al(mDeviceLock);
+
+    if (!isValidTemplateType(type)) {
+        ALOGE("%s:%d: Invalid template request type: %d", __func__, mId, type);
+        return NULL;
+    }
+
+    // DO NOT try to initialize the device here, it will be guaranteed deadlock.
+    if (!mIsInitialized) {
+        ALOGE("Device is not initialized yet");
+        return NULL;
+    }
+
+    return mTemplates[type];
+}
+
+// This implementation is a copy-paste, probably we should override (or move) this to
+// device specific class.
+int Camera::processCaptureRequest(camera3_capture_request_t *request) {
+    camera3_capture_result result;
+    ALOGV("%s:%d: request=%p", __func__, mId, request);
+    ATRACE_CALL();
+    android::Mutex::Autolock al(mDeviceLock);
+
+    if (request == NULL) {
+        ALOGE("%s:%d: NULL request recieved", __func__, mId);
+        return -EINVAL;
+    }
+
+    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 {
+        updateSettingsLocked(request->settings);
+    }
+
+    if (request->input_buffer != NULL) {
+        ALOGV("%s:%d: Reprocessing input buffer is not supported yet", __func__, mId);
+        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) {
+            delete [] result.output_buffers;
+            // TODO: this should probably be a total device failure; transient for now
+            return -EINVAL;
+        }
+    }
+
+    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);
+
+    // Free up capture result related resources, HAL owns the capture result, and it
+    // is only valid during the process_capture_result call.
+    delete[] result.output_buffers;
+
+    return 0;
+}
+
+int Camera::flush() {
+    int res;
+
+    ALOGV("%s:%d: flush device", __func__, mId);
+    // per-device specific flush
+    res = flushDevice();
+    if (res != 0) {
+        ALOGE("%s:%d: Failed to flush device!", __func__, mId);
+        return res;
+    }
+    return 0;
+}
+
+void Camera::updateSettingsLocked(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);
+}
+
+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::dump(int fd) {
+    ALOGV("%s:%d: Dumping to fd %d", __func__, mId, fd);
+    ATRACE_CALL();
+    android::Mutex::Autolock al(mDeviceLock);
+
+    dprintf(fd, "Camera ID: %d (Busy: %d)\n", mId, mBusy);
+
+    // TODO: dump all settings
+    dprintf(fd, "Most Recent Settings: (%p)\n", mSettings);
+
+    dprintf(fd, "Number of streams: %d\n", mStreams.size());
+    for (size_t i = 0; i < mStreams.size(); i++) {
+        dprintf(fd, "Stream %d/%d:\n", i, mStreams.size());
+        mStreams[i]->dump(fd);
+    }
+}
+
+const char* Camera::templateToString(int type) {
+    switch (type) {
+    case CAMERA3_TEMPLATE_PREVIEW:
+        return "CAMERA3_TEMPLATE_PREVIEW";
+    case CAMERA3_TEMPLATE_STILL_CAPTURE:
+        return "CAMERA3_TEMPLATE_STILL_CAPTURE";
+    case CAMERA3_TEMPLATE_VIDEO_RECORD:
+        return "CAMERA3_TEMPLATE_VIDEO_RECORD";
+    case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
+        return "CAMERA3_TEMPLATE_VIDEO_SNAPSHOT";
+    case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
+        return "CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG";
+    case CAMERA3_TEMPLATE_MANUAL:
+        return "CAMERA3_TEMPLATE_MANUAL";
+    }
+
+    return "Invalid template type!";
+}
+
+int Camera::setTemplate(int type, camera_metadata_t *settings) {
+    android::Mutex::Autolock al(mDeviceLock);
+
+    if (!isValidTemplateType(type)) {
+        ALOGE("%s:%d: Invalid template request type: %d", __func__, mId, type);
+        return -EINVAL;
+    }
+
+    if (mTemplates[type] != NULL) {
+        ALOGE("%s:%d: Setting already constructed template type %s(%d)",
+                __func__, mId, templateToString(type), type);
+        return -EINVAL;
+    }
+
+    // Make a durable copy of the underlying metadata
+    mTemplates[type] = clone_camera_metadata(settings);
+    if (mTemplates[type] == NULL) {
+        ALOGE("%s:%d: Failed to clone metadata %p for template type %s(%d)",
+                __func__, mId, settings, templateToString(type), type);
+        return -EINVAL;
+    }
+    return 0;
+}
+
+} // namespace usb_camera_hal
diff --git a/modules/usbcamera/Camera.h b/modules/usbcamera/Camera.h
new file mode 100644
index 0000000..6419c7d
--- /dev/null
+++ b/modules/usbcamera/Camera.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CAMERA_H_
+#define CAMERA_H_
+
+#include <hardware/hardware.h>
+#include <hardware/camera3.h>
+#include <utils/Mutex.h>
+#include <utils/Vector.h>
+#include "Metadata.h"
+#include <sync/sync.h>
+#include "Stream.h"
+
+#define CAMERA_SYNC_TIMEOUT_MS 5000
+
+namespace usb_camera_hal {
+// Camera represents a physical camera on a device.
+// This is constructed when the HAL module is loaded, one per physical camera.
+// It is opened by the framework, and must be closed before it can be opened
+// again.
+// This is an abstract class, containing all logic and data shared between all
+// camera devices.
+class Camera {
+    public:
+        // id is used to distinguish cameras. 0 <= id < NUM_CAMERAS.
+        // module is a handle to the HAL module, used when the device is opened.
+        Camera(int id);
+        virtual ~Camera();
+
+        // Common Camera Device Operations (see <hardware/camera_common.h>)
+        int open(const hw_module_t *module, hw_device_t **device);
+        int getInfo(struct camera_info *info);
+        int close();
+
+        // Camera v3 Device Operations (see <hardware/camera3.h>)
+        int initialize(const camera3_callback_ops_t *callback_ops);
+        int configureStreams(camera3_stream_configuration_t *stream_list);
+        const camera_metadata_t *constructDefaultRequestSettings(int type);
+        int processCaptureRequest(camera3_capture_request_t *request);
+        int flush();
+        void dump(int fd);
+
+        // Update static camera characteristics. This method could be called by
+        // HAL hotplug thread when camera is plugged.
+        void updateInfo();
+
+    protected:
+        // Initialize static camera characteristics.
+        virtual int initStaticInfo() = 0;
+        // Verify settings are valid for a capture
+        virtual bool isValidCaptureSettings(const camera_metadata_t *) = 0;
+        // Separate open method for individual devices
+        virtual int openDevice() = 0;
+        // Separate initialization method for individual devices when opened
+        virtual int initDevice() = 0;
+        // Flush camera pipeline for each individual device
+        virtual int flushDevice() = 0;
+        // Separate close method for individual devices
+        virtual int closeDevice() = 0;
+        // Capture and file an output buffer for an input buffer.
+        virtual int processCaptureBuffer(const camera3_stream_buffer_t *in,
+                camera3_stream_buffer_t *out) = 0;
+        // Accessor method used by initDevice() to set the templates' metadata
+        int setTemplate(int type, camera_metadata_t *settings);
+        // Prettyprint template names
+        const char* templateToString(int type);
+        // Process an output buffer
+
+        // 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;
+
+    private:
+        // Camera device handle returned to framework for use
+        camera3_device_t mDevice;
+        // Reuse a stream already created by this device. Must be called with mDeviceLock held.
+        Stream *reuseStreamLocked(camera3_stream_t *astream);
+        // Destroy all streams in a stream array, and the array itself. Must be called with
+        // mDeviceLock held.
+        void destroyStreamsLocked(android::Vector<Stream *> &streams);
+        // Verify a set of streams is valid in aggregate. Must be called with mDeviceLock held.
+        bool isValidStreamSetLocked(const android::Vector<Stream *> &streams);
+        // Calculate usage and max_bufs of each stream. Must be called with mDeviceLock held.
+        void setupStreamsLocked(android::Vector<Stream *> &streams);
+        // Update new settings for re-use and clean up old settings. Must be called with
+        // mDeviceLock held.
+        void updateSettingsLocked(const camera_metadata_t *new_settings);
+        // Send a shutter notify message with start of exposure time
+        void notifyShutter(uint32_t frame_number, uint64_t timestamp);
+        // Is type a valid template type (and valid index into mTemplates)
+        bool isValidTemplateType(int type);
+
+        // Busy flag indicates camera is in use
+        bool mBusy;
+        // Camera device operations handle shared by all devices
+        const static camera3_device_ops_t sOps;
+        // Methods used to call back into the framework
+        const camera3_callback_ops_t *mCallbackOps;
+        // Lock protecting the Camera object for modifications
+        android::Mutex mDeviceLock;
+        // Lock protecting only static camera characteristics, which may
+        // be accessed without the camera device open
+        android::Mutex mStaticInfoLock;
+        // Array of handles to streams currently in use by the device
+        android::Vector<Stream *> mStreams;
+        // Static array of standard camera settings templates
+        camera_metadata_t *mTemplates[CAMERA3_TEMPLATE_COUNT];
+        // Most recent request settings seen, memoized to be reused
+        camera_metadata_t *mSettings;
+        bool mIsInitialized;
+};
+} // namespace usb_camera_hal
+
+#endif // CAMERA_H_
diff --git a/modules/usbcamera/CameraHAL.cpp b/modules/usbcamera/CameraHAL.cpp
new file mode 100644
index 0000000..98111ef
--- /dev/null
+++ b/modules/usbcamera/CameraHAL.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "UsbCameraHAL"
+#include <cutils/log.h>
+
+#include <cstdlib>
+#include <hardware/camera_common.h>
+#include <hardware/hardware.h>
+#include "UsbCamera.h"
+#include "CameraHAL.h"
+
+/*
+ * This file serves as the entry point to the HAL.  It contains the module
+ * structure and functions used by the framework to load and interface to this
+ * HAL, as well as the handles to the individual camera devices.
+ */
+
+namespace usb_camera_hal {
+
+static CameraHAL gCameraHAL;
+
+CameraHAL::CameraHAL()
+  : mCallbacks(NULL) {
+    // Should not allocate the camera devices for now, as it is unclear if the device is plugged.
+
+    // Start hotplug thread
+    mHotplugThread = new HotplugThread(this);
+    mHotplugThread->run("usb-camera-hotplug");
+}
+
+CameraHAL::~CameraHAL() {
+    // Stop hotplug thread
+    {
+        android::Mutex::Autolock al(mModuleLock);
+        if (mHotplugThread != NULL) {
+            mHotplugThread->requestExit();
+        }
+
+        // Delete camera device from mCameras
+    }
+
+    // Joining done without holding mLock, otherwise deadlocks may ensue
+    // as the threads try to access parent states.
+    if (mHotplugThread != NULL) {
+        mHotplugThread->join();
+    }
+
+    delete mHotplugThread;
+}
+
+int CameraHAL::getNumberOfCameras() {
+    android::Mutex::Autolock al(mModuleLock);
+    ALOGV("%s: %d", __func__, mCameras.size());
+    return static_cast<int>(mCameras.size());
+}
+
+int CameraHAL::getCameraInfo(int id, struct camera_info* info) {
+    android::Mutex::Autolock al(mModuleLock);
+    ALOGV("%s: camera id %d: info=%p", __func__, id, info);
+    if (id < 0 || id >= static_cast<int>(mCameras.size())) {
+        ALOGE("%s: Invalid camera id %d", __func__, id);
+        return -ENODEV;
+    }
+
+    return mCameras[id]->getInfo(info);
+}
+
+int CameraHAL::setCallbacks(const camera_module_callbacks_t *callbacks) {
+    ALOGV("%s : callbacks=%p", __func__, callbacks);
+    mCallbacks = callbacks;
+    return 0;
+}
+
+int CameraHAL::open(const hw_module_t* mod, const char* name, hw_device_t** dev) {
+    int id;
+    char *nameEnd;
+
+    android::Mutex::Autolock al(mModuleLock);
+    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 != '\0') {
+        ALOGE("%s: Invalid camera id name %s", __func__, name);
+        return -EINVAL;
+    } else if (id < 0 || id >= static_cast<int>(mCameras.size())) {
+        ALOGE("%s: Invalid camera id %d", __func__, id);
+        return -ENODEV;
+    }
+    return mCameras[id]->open(mod, dev);
+}
+
+extern "C" {
+
+static int get_number_of_cameras() {
+    return gCameraHAL.getNumberOfCameras();
+}
+
+static int get_camera_info(int id, struct camera_info* info) {
+    return gCameraHAL.getCameraInfo(id, info);
+}
+
+static int set_callbacks(const camera_module_callbacks_t *callbacks) {
+    return gCameraHAL.setCallbacks(callbacks);
+}
+
+static int open_dev(const hw_module_t* mod, const char* name, hw_device_t** dev) {
+    return gCameraHAL.open(mod, name, dev);
+}
+
+static hw_module_methods_t gCameraModuleMethods = {
+    open : open_dev
+};
+
+camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) = {
+    common : {
+        tag                : HARDWARE_MODULE_TAG,
+        module_api_version : CAMERA_MODULE_API_VERSION_2_4,
+        hal_api_version    : HARDWARE_HAL_API_VERSION,
+        id                 : CAMERA_HARDWARE_MODULE_ID,
+        name               : "Default USB Camera HAL",
+        author             : "The Android Open Source Project",
+        methods            : &gCameraModuleMethods,
+        dso                : NULL,
+        reserved           : {0},
+    },
+    get_number_of_cameras : get_number_of_cameras,
+    get_camera_info       : get_camera_info,
+    set_callbacks         : set_callbacks,
+    get_vendor_tag_ops    : NULL,
+    open_legacy           : NULL,
+    set_torch_mode        : NULL,
+    reserved              : {0},
+};
+} // extern "C"
+
+} // namespace usb_camera_hal
diff --git a/modules/usbcamera/CameraHAL.h b/modules/usbcamera/CameraHAL.h
new file mode 100644
index 0000000..1770d95
--- /dev/null
+++ b/modules/usbcamera/CameraHAL.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 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_HAL_H_
+#define CAMERA_HAL_H_
+
+#include <hardware/hardware.h>
+#include <hardware/camera_common.h>
+#include <utils/Vector.h>
+#include <utils/Mutex.h>
+#include "HotplugThread.h"
+#include "Camera.h"
+
+namespace usb_camera_hal {
+
+class HotplugThread;
+
+/**
+ * CameraHAL contains all module state that isn't specific to an individual camera device
+ */
+class CameraHAL {
+    public:
+        CameraHAL();
+        ~CameraHAL();
+
+        // Camera Module Interface (see <hardware/camera_common.h>)
+        int getNumberOfCameras();
+        int getCameraInfo(int camera_id, struct camera_info *info);
+        int setCallbacks(const camera_module_callbacks_t *callbacks);
+        void getVendorTagOps(vendor_tag_ops_t* ops);
+
+        // Hardware Module Interface (see <hardware/hardware.h>)
+        int open(const hw_module_t* mod, const char* name, hw_device_t** dev);
+
+    private:
+        // Callback handle
+        const camera_module_callbacks_t *mCallbacks;
+        android::Vector<Camera*> mCameras;
+        // Lock to protect the module method calls.
+        android::Mutex mModuleLock;
+        // Hot plug thread managing camera hot plug.
+        HotplugThread *mHotplugThread;
+
+};
+} // namespace usb_camera_hal
+
+#endif // CAMERA_HAL_H_
diff --git a/modules/usbcamera/HotplugThread.cpp b/modules/usbcamera/HotplugThread.cpp
new file mode 100644
index 0000000..6c65086
--- /dev/null
+++ b/modules/usbcamera/HotplugThread.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "HotplugThread"
+#include <cutils/log.h>
+
+#include "HotplugThread.h"
+
+namespace usb_camera_hal {
+
+HotplugThread::HotplugThread(CameraHAL *hal)
+    : mModule(hal) {
+
+}
+
+HotplugThread::~HotplugThread() {
+
+}
+
+void HotplugThread::requestExit() {
+    // Call parent to set up shutdown
+    Thread::requestExit();
+
+    // Cleanup other states?
+}
+
+bool HotplugThread::threadLoop() {
+
+    /**
+     * Check camera connection status change, if connected, do below:
+     * 1. Create camera device, add to mCameras.
+     * 2. Init static info (mCameras[id]->initStaticInfo())
+     * 3. Notify on_status_change callback
+     *
+     * If unconnected, similarly, do below:
+     * 1. Destroy camera device and remove it from mCameras.
+     * 2. Notify on_status_change callback
+     *
+     * DO NOT have a tight polling loop here, to avoid excessive CPU utilization.
+     */
+
+    return true;
+}
+
+} // namespace usb_camera_hal
diff --git a/modules/usbcamera/HotplugThread.h b/modules/usbcamera/HotplugThread.h
new file mode 100644
index 0000000..a13adb7
--- /dev/null
+++ b/modules/usbcamera/HotplugThread.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 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 HOTPLUG_THREAD_H_
+#define HOTPLUG_THREAD_H_
+
+#include <utils/Thread.h>
+#include "CameraHAL.h"
+
+namespace usb_camera_hal {
+/**
+ * Thread for managing usb camera hotplug. It does below:
+ * 1. Monitor camera hotplug status, and notify the status changes by calling
+ *    module callback methods.
+ * 2. When camera is plugged, create camera device instance, initialize the camera
+ *    static info. When camera is unplugged, destroy the camera device instance and
+ *    static metadata. As an optimization option, the camera device instance (including
+ *    the static info) could be cached when the same camera plugged/unplugged multiple
+ *    times.
+ */
+
+class CameraHAL;
+
+class HotplugThread : public android::Thread {
+
+    public:
+        HotplugThread(CameraHAL *hal);
+        ~HotplugThread();
+
+        // Override below two methods for proper cleanup.
+        virtual bool threadLoop();
+        virtual void requestExit();
+
+    private:
+        CameraHAL *mModule;
+};
+
+} // namespace usb_camera_hal
+
+#endif // HOTPLUG_THREAD_H_
diff --git a/modules/usbcamera/Metadata.cpp b/modules/usbcamera/Metadata.cpp
new file mode 100644
index 0000000..f243834
--- /dev/null
+++ b/modules/usbcamera/Metadata.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Metadata"
+#include <cutils/log.h>
+
+#include <system/camera_metadata.h>
+
+#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+#include <utils/Trace.h>
+
+#include "Metadata.h"
+
+namespace usb_camera_hal {
+
+Metadata::Metadata():
+    mData(NULL) {
+}
+
+Metadata::~Metadata() {
+    replace(NULL);
+}
+
+void Metadata::replace(camera_metadata_t *m) {
+    if (m == mData) {
+        return;
+    }
+    if (mData)
+        free_camera_metadata(mData);
+    mData = m;
+}
+
+int Metadata::init(const camera_metadata_t *metadata) {
+    camera_metadata_t* tmp;
+
+    if (!validate_camera_metadata_structure(metadata, NULL))
+        return -EINVAL;
+
+    tmp = clone_camera_metadata(metadata);
+    if (tmp == NULL)
+        return -EINVAL;
+
+    replace(tmp);
+    return 0;
+}
+
+int Metadata::addUInt8(uint32_t tag, int count, const uint8_t *data) {
+    if (!validate(tag, TYPE_BYTE, count)) return -EINVAL;
+    return add(tag, count, data);
+}
+
+int Metadata::add1UInt8(uint32_t tag, const uint8_t data) {
+    return addUInt8(tag, 1, &data);
+}
+
+int Metadata::addInt32(uint32_t tag, int count, const int32_t *data) {
+    if (!validate(tag, TYPE_INT32, count)) return -EINVAL;
+    return add(tag, count, data);
+}
+
+int Metadata::addFloat(uint32_t tag, int count, const float *data) {
+    if (!validate(tag, TYPE_FLOAT, count)) return -EINVAL;
+    return add(tag, count, data);
+}
+
+int Metadata::addInt64(uint32_t tag, int count, const int64_t *data) {
+    if (!validate(tag, TYPE_INT64, count)) return -EINVAL;
+    return add(tag, count, data);
+}
+
+int Metadata::addDouble(uint32_t tag, int count, const double *data) {
+    if (!validate(tag, TYPE_DOUBLE, count)) return -EINVAL;
+    return add(tag, count, data);
+}
+
+int Metadata::addRational(uint32_t tag, int count,
+        const 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, const void *tag_data) {
+    // Opportunistically attempt to add if metadata has room for it
+    if (!add_camera_metadata_entry(mData, tag, tag_data, count)) {
+        return 0;
+    }
+
+    int res;
+    camera_metadata_t* tmp;
+    int tag_type = get_camera_metadata_tag_type(tag);
+    size_t size = calculate_camera_metadata_entry_data_size(tag_type, count);
+    size_t entry_capacity = get_camera_metadata_entry_count(mData) + 1;
+    size_t data_capacity = get_camera_metadata_data_count(mData) + size;
+
+    // Double new dimensions to minimize future reallocations
+    tmp = allocate_camera_metadata(entry_capacity * 2, data_capacity * 2);
+    if (tmp == NULL) {
+        ALOGE("%s: Failed to allocate new metadata with %zu entries, %zu data",
+                __func__, entry_capacity, data_capacity);
+        return -ENOMEM;
+    }
+    // Append the current metadata to the new (empty) metadata
+    res = append_camera_metadata(tmp, mData);
+    if (res) {
+        ALOGE("%s: Failed to append old metadata %p to new %p",
+                __func__, mData, tmp);
+        return res;
+    }
+    // Add the remaining new item
+    res = add_camera_metadata_entry(tmp, tag, tag_data, count);
+    if (res) {
+        ALOGE("%s: Failed to add new entry (%d, %p, %d) to metadata %p",
+                __func__, tag, tag_data, count, tmp);
+        return res;
+    }
+
+    replace(tmp);
+    return 0;
+}
+
+camera_metadata_t* Metadata::get() {
+    return mData;
+}
+
+} // namespace usb_camera_hal
diff --git a/modules/usbcamera/Metadata.h b/modules/usbcamera/Metadata.h
new file mode 100644
index 0000000..288db16
--- /dev/null
+++ b/modules/usbcamera/Metadata.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 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 <stdint.h>
+#include <hardware/camera3.h>
+#include <system/camera_metadata.h>
+
+namespace usb_camera_hal {
+// Metadata is a convenience class for dealing with libcamera_metadata
+class Metadata {
+    public:
+        Metadata();
+        ~Metadata();
+        // Initialize with framework metadata
+        int init(const camera_metadata_t *metadata);
+
+        // Parse and add an entry. Allocates and copies new storage for *data.
+        int addUInt8(uint32_t tag, int count, const uint8_t *data);
+        int add1UInt8(uint32_t tag, const uint8_t data);
+        int addInt32(uint32_t tag, int count, const int32_t *data);
+        int addFloat(uint32_t tag, int count, const float *data);
+        int addInt64(uint32_t tag, int count, const int64_t *data);
+        int addDouble(uint32_t tag, int count, const double *data);
+        int addRational(uint32_t tag, int count,
+                const camera_metadata_rational_t *data);
+
+        // Get a handle to the current metadata
+        // This is not a durable handle, and may be destroyed by add*/init
+        camera_metadata_t* get();
+
+    private:
+        // Actual internal storage
+        camera_metadata_t* mData;
+        // Destroy old metadata and replace with new
+        void replace(camera_metadata_t *m);
+        // 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
+        int add(uint32_t tag, int count, const void *tag_data);
+};
+} // namespace usb_camera_hal
+
+#endif // METADATA_H_
diff --git a/modules/usbcamera/Stream.cpp b/modules/usbcamera/Stream.cpp
new file mode 100644
index 0000000..a3fefa3
--- /dev/null
+++ b/modules/usbcamera/Stream.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Stream"
+#include <cutils/log.h>
+
+#include <stdio.h>
+#include <hardware/camera3.h>
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+#include <utils/Mutex.h>
+
+#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+#include <utils/Trace.h>
+
+#include "Stream.h"
+
+namespace usb_camera_hal {
+
+Stream::Stream(int id, camera3_stream_t *s)
+  : mReuse(false),
+    mId(id),
+    mStream(s){
+}
+
+Stream::~Stream() {
+    for (size_t i = 0; i < mBuffers.size(); i++) {
+        delete mBuffers[i];
+    }
+
+    mBuffers.clear();
+}
+
+void Stream::setUsage(uint32_t usage) {
+    android::Mutex::Autolock al(mLock);
+    if (usage != mStream->usage) {
+        mStream->usage = usage;
+    }
+}
+
+void Stream::setMaxBuffers(uint32_t max_buffers) {
+    android::Mutex::Autolock al(mLock);
+    if (max_buffers != mStream->max_buffers) {
+        mStream->max_buffers = max_buffers;
+    }
+}
+
+int Stream::getType() {
+    return mStream->stream_type;
+}
+
+bool Stream::isInputType() {
+    return mStream->stream_type == CAMERA3_STREAM_INPUT ||
+            mStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL;
+}
+
+bool Stream::isOutputType() {
+    return mStream->stream_type == CAMERA3_STREAM_OUTPUT ||
+            mStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL;
+}
+
+const char* Stream::typeToString(int type) {
+    switch (type) {
+    case CAMERA3_STREAM_INPUT:
+        return "CAMERA3_STREAM_INPUT";
+    case CAMERA3_STREAM_OUTPUT:
+        return "CAMERA3_STREAM_OUTPUT";
+    case CAMERA3_STREAM_BIDIRECTIONAL:
+        return "CAMERA3_STREAM_BIDIRECTIONAL";
+    }
+    return "Invalid stream type!";
+}
+
+const char* Stream::formatToString(int format) {
+    // See <system/graphics.h> for full list
+    switch (format) {
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+        return "BGRA 8888";
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+        return "RGBA 8888";
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+        return "RGBX 8888";
+    case HAL_PIXEL_FORMAT_RGB_888:
+        return "RGB 888";
+    case HAL_PIXEL_FORMAT_RGB_565:
+        return "RGB 565";
+    case HAL_PIXEL_FORMAT_sRGB_A_8888:
+        return "sRGB A 8888";
+    case HAL_PIXEL_FORMAT_sRGB_X_8888:
+        return "sRGB B 8888";
+    case HAL_PIXEL_FORMAT_Y8:
+        return "Y8";
+    case HAL_PIXEL_FORMAT_Y16:
+        return "Y16";
+    case HAL_PIXEL_FORMAT_YV12:
+        return "YV12";
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+        return "NV16";
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        return "NV21";
+    case HAL_PIXEL_FORMAT_YCbCr_422_I:
+        return "YUY2";
+    case HAL_PIXEL_FORMAT_RAW_SENSOR:
+        return "RAW SENSOR";
+    case HAL_PIXEL_FORMAT_BLOB:
+        return "BLOB";
+    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+        return "IMPLEMENTATION DEFINED";
+    case HAL_PIXEL_FORMAT_YCbCr_420_888:
+        return "FLEXIBLE YCbCr 420 888";
+    }
+    return "Invalid stream format!";
+}
+
+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 != mStream->stream_type) {
+        ALOGE("%s:%d: Mismatched type in reused stream. Got %s(%d) "
+                "expect %s(%d)", __func__, mId, typeToString(s->stream_type),
+                s->stream_type, typeToString(mStream->stream_type), mStream->stream_type);
+        return false;
+    }
+    if (s->format != mStream->format) {
+        ALOGE("%s:%d: Mismatched format in reused stream. Got %s(%d) "
+                "expect %s(%d)", __func__, mId, formatToString(s->format),
+                s->format, formatToString(mStream->format), mStream->format);
+        return false;
+    }
+    if (s->width != mStream->width) {
+        ALOGE("%s:%d: Mismatched width in reused stream. Got %d expect %d",
+                __func__, mId, s->width, mStream->width);
+        return false;
+    }
+    if (s->height != mStream->height) {
+        ALOGE("%s:%d: Mismatched height in reused stream. Got %d expect %d",
+                __func__, mId, s->height, mStream->height);
+        return false;
+    }
+    return true;
+}
+
+void Stream::dump(int fd) {
+    android::Mutex::Autolock al(mLock);
+
+    dprintf(fd, "Stream ID: %d (%p)\n", mId, mStream);
+    dprintf(fd, "Stream Type: %s (%d)\n", typeToString(mStream->stream_type), mStream->stream_type);
+    dprintf(fd, "Width: %" PRIu32 " Height: %" PRIu32 "\n", mStream->width, mStream->height);
+    dprintf(fd, "Stream Format: %s (%d)", formatToString(mStream->format), mStream->format);
+    // ToDo: prettyprint usage mask flags
+    dprintf(fd, "Gralloc Usage Mask: %#" PRIx32 "\n", mStream->usage);
+    dprintf(fd, "Max Buffer Count: %" PRIu32 "\n", mStream->max_buffers);
+    dprintf(fd, "Number of Buffers in use by HAL: %" PRIu32 "\n", mBuffers.size());
+    for (size_t i = 0; i < mBuffers.size(); i++) {
+        dprintf(fd, "Buffer %" PRIu32 "/%" PRIu32 ": %p\n", i, mBuffers.size(),
+                mBuffers[i]);
+    }
+}
+
+} // namespace usb_camera_hal
diff --git a/modules/usbcamera/Stream.h b/modules/usbcamera/Stream.h
new file mode 100644
index 0000000..022ca9f
--- /dev/null
+++ b/modules/usbcamera/Stream.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 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>
+#include <utils/Mutex.h>
+#include <utils/Vector.h>
+
+namespace usb_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 a stream's parameters match this stream's parameters
+        bool isValidReuseStream(int id, camera3_stream_t *s);
+
+        void setUsage(uint32_t usage);
+        void setMaxBuffers(uint32_t max_buffers);
+
+        int getType();
+        bool isInputType();
+        bool isOutputType();
+        const char* typeToString(int type);
+        const char* formatToString(int format);
+        void dump(int fd);
+
+        // This stream is being reused. Used in stream configuration passes
+        bool mReuse;
+
+    private:
+        // 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;
+        // Array of handles to buffers currently in use by the stream
+        android::Vector<buffer_handle_t *> mBuffers;
+        // Lock protecting the Stream object for modifications
+        android::Mutex mLock;
+};
+} // namespace usb_camera_hal
+
+#endif // STREAM_H_
diff --git a/modules/usbcamera/UsbCamera.cpp b/modules/usbcamera/UsbCamera.cpp
new file mode 100644
index 0000000..ded3e92
--- /dev/null
+++ b/modules/usbcamera/UsbCamera.cpp
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "UsbCameraDevice"
+#include <cutils/log.h>
+
+#include <system/camera_metadata.h>
+
+#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+#include <utils/Trace.h>
+
+#include "Camera.h"
+#include "UsbCamera.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+namespace usb_camera_hal {
+
+UsbCamera::UsbCamera(int id) : Camera(id) {
+}
+
+UsbCamera::~UsbCamera() {
+}
+
+int UsbCamera::initStaticInfo() {
+    /*
+     * Setup static camera info.  This will have to customized per camera
+     * device.
+     * TODO: this is just some sample code, need tailor for USB cameras.
+     */
+    if (mStaticInfo != NULL) {
+        free_camera_metadata(mStaticInfo);
+    }
+
+    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[] = {/*AE*/ 1,/*AWB*/ 1,/*AF*/ 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);
+
+    int32_t android_jpeg_max_size[] = {13 * 1024 * 1024}; // 13MB
+    m.addInt32(ANDROID_JPEG_MAX_SIZE,
+            ARRAY_SIZE(android_jpeg_max_size),
+            android_jpeg_max_size);
+
+    /* 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 */
+
+    mStaticInfo = clone_camera_metadata(m.get());
+
+    return 0;
+}
+
+int UsbCamera::openDevice() {
+    // TODO: implement usb camera device open sequence: open device nodes etc.
+
+    return 0;
+}
+
+int UsbCamera::closeDevice() {
+    // TODO: implement usb camera device close sequence: close device nodes etc.
+
+    return 0;
+}
+
+int UsbCamera::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_MS);
+        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;
+}
+
+int UsbCamera::initDevice() {
+    int res;
+    Metadata base;
+
+    // Create standard settings templates from copies of base metadata
+    res = base.add1UInt8(ANDROID_CONTROL_MODE, ANDROID_CONTROL_MODE_OFF);
+    if (res)
+        return res;
+
+    // Use base settings to create all other templates and set them. This is just some samples,
+    // More initialization may be needed.
+    res = initPreviewTemplate(base);
+    if (res)
+        return res;
+    res = initStillTemplate(base);
+    if (res)
+        return res;
+    res = initRecordTemplate(base);
+    if (res)
+        return res;
+    res = initSnapshotTemplate(base);
+    if (res)
+        return res;
+    res = initZslTemplate(base);
+    if (res)
+        return res;
+    res = initManualTemplate(base);
+    if (res)
+        return res;
+
+    return 0;
+}
+
+int UsbCamera::initPreviewTemplate(Metadata m) {
+    // Setup default preview controls
+    int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT,
+                            ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW);
+
+    if (res)
+        return res;
+    // TODO: set fast auto-focus, auto-whitebalance, auto-exposure, auto flash
+    return setTemplate(CAMERA3_TEMPLATE_PREVIEW, m.get());
+}
+
+int UsbCamera::initStillTemplate(Metadata m) {
+    int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT,
+                            ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
+    // Setup default still capture controls
+    if (res)
+        return res;
+    // TODO: set fast auto-focus, auto-whitebalance, auto-exposure, auto flash
+    return setTemplate(CAMERA3_TEMPLATE_STILL_CAPTURE, m.get());
+}
+
+int UsbCamera::initRecordTemplate(Metadata m) {
+    int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT,
+                            ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
+    // Setup default video record controls
+    if (res)
+        return res;
+    // TODO: set slow auto-focus, auto-whitebalance, auto-exposure, flash off
+    return setTemplate(CAMERA3_TEMPLATE_VIDEO_RECORD, m.get());
+}
+
+int UsbCamera::initSnapshotTemplate(Metadata m) {
+    int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT,
+                            ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT);
+    // Setup default video snapshot controls
+    if (res)
+        return res;
+    // TODO: set slow auto-focus, auto-whitebalance, auto-exposure, flash off
+    return setTemplate(CAMERA3_TEMPLATE_VIDEO_SNAPSHOT, m.get());
+}
+
+int UsbCamera::initZslTemplate(Metadata m) {
+    int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT,
+                            ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG);
+    // Setup default zero shutter lag controls
+    if (res)
+        return res;
+    // TODO: set reprocessing parameters for zsl input queue
+    return setTemplate(CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG, m.get());
+}
+
+int UsbCamera::initManualTemplate(Metadata m) {
+    int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT,
+                            ANDROID_CONTROL_CAPTURE_INTENT_MANUAL);
+    // Setup manual controls
+    if (res)
+        return res;
+    // TODO: set reprocessing parameters for zsl input queue
+    return setTemplate(CAMERA3_TEMPLATE_MANUAL, m.get());
+}
+
+bool UsbCamera::isValidCaptureSettings(const camera_metadata_t* settings) {
+    // TODO: reject settings that cannot be captured
+    return true;
+}
+
+} // namespace usb_camera_hal
diff --git a/modules/usbcamera/UsbCamera.h b/modules/usbcamera/UsbCamera.h
new file mode 100644
index 0000000..fe52ade
--- /dev/null
+++ b/modules/usbcamera/UsbCamera.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 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 EXAMPLE_CAMERA_H_
+#define EXAMPLE_CAMERA_H_
+
+#include <system/camera_metadata.h>
+#include "Camera.h"
+
+namespace usb_camera_hal {
+/**
+ * UsbCamera is an example for a specific camera device. The Camera instance contains
+ * a specific camera device (e.g. UsbCamera) holds all specific metadata and logic about
+ * that device.
+ */
+class UsbCamera : public Camera {
+    public:
+        UsbCamera(int id);
+        ~UsbCamera();
+
+    private:
+        // Initialize static camera characteristics for individual device
+        int initStaticInfo();
+        int openDevice();
+        // Initialize whole device (templates/etc) when opened
+        int initDevice();
+        int flushDevice();
+        int closeDevice();
+        int processCaptureBuffer(const camera3_stream_buffer_t *in, camera3_stream_buffer_t *out);
+        // Initialize each template metadata controls
+        int initPreviewTemplate(Metadata m);
+        int initStillTemplate(Metadata m);
+        int initRecordTemplate(Metadata m);
+        int initSnapshotTemplate(Metadata m);
+        int initZslTemplate(Metadata m);
+        int initManualTemplate(Metadata m);
+        // Verify settings are valid for a capture with this device
+        bool isValidCaptureSettings(const camera_metadata_t* settings);
+};
+} // namespace usb_camera_hal
+
+#endif // CAMERA_H_
diff --git a/tests/hardware/struct-offset.cpp b/tests/hardware/struct-offset.cpp
index a7ff797..0f4ef41 100644
--- a/tests/hardware/struct-offset.cpp
+++ b/tests/hardware/struct-offset.cpp
@@ -212,7 +212,8 @@
     CHECK_MEMBER_AT(camera_module_t, set_callbacks, 136, 264);
     CHECK_MEMBER_AT(camera_module_t, get_vendor_tag_ops, 140, 272);
     CHECK_MEMBER_AT(camera_module_t, open_legacy, 144, 280);
-    CHECK_MEMBER_AT(camera_module_t, reserved, 148, 288);
+    CHECK_MEMBER_AT(camera_module_t, set_torch_mode, 148, 288);
+    CHECK_MEMBER_AT(camera_module_t, reserved, 152, 296);
 
     //Types defined in camera3.h
     CHECK_MEMBER_AT(camera3_device_ops_t, initialize, 0, 0);