Merge "LE: Add limited advertising duration capability (1/3)" into lmp-dev
diff --git a/include/hardware/audio.h b/include/hardware/audio.h
index 95111dd..59fb9a3 100644
--- a/include/hardware/audio.h
+++ b/include/hardware/audio.h
@@ -94,6 +94,12 @@
 #define AUDIO_PARAMETER_VALUE_TTY_HCO "tty_hco"
 #define AUDIO_PARAMETER_VALUE_TTY_FULL "tty_full"
 
+/* Hearing Aid Compatibility - Telecoil (HAC-T) mode on/off
+   Strings must be in sync with CallFeaturesSetting.java */
+#define AUDIO_PARAMETER_KEY_HAC "HACSetting"
+#define AUDIO_PARAMETER_VALUE_HAC_ON "ON"
+#define AUDIO_PARAMETER_VALUE_HAC_OFF "OFF"
+
 /* A2DP sink address set by framework */
 #define AUDIO_PARAMETER_A2DP_SINK_ADDRESS "a2dp_sink_address"
 
@@ -106,16 +112,17 @@
 /* Bluetooth SCO wideband */
 #define AUDIO_PARAMETER_KEY_BT_SCO_WB "bt_wbs"
 
+
 /**
  *  audio stream parameters
  */
 
-#define AUDIO_PARAMETER_STREAM_ROUTING "routing"            // audio_devices_t
-#define AUDIO_PARAMETER_STREAM_FORMAT "format"              // audio_format_t
-#define AUDIO_PARAMETER_STREAM_CHANNELS "channels"          // audio_channel_mask_t
-#define AUDIO_PARAMETER_STREAM_FRAME_COUNT "frame_count"    // size_t
-#define AUDIO_PARAMETER_STREAM_INPUT_SOURCE "input_source"  // audio_source_t
-#define AUDIO_PARAMETER_STREAM_SAMPLING_RATE "sampling_rate" // uint32_t
+#define AUDIO_PARAMETER_STREAM_ROUTING "routing"             /* audio_devices_t */
+#define AUDIO_PARAMETER_STREAM_FORMAT "format"               /* audio_format_t */
+#define AUDIO_PARAMETER_STREAM_CHANNELS "channels"           /* audio_channel_mask_t */
+#define AUDIO_PARAMETER_STREAM_FRAME_COUNT "frame_count"     /* size_t */
+#define AUDIO_PARAMETER_STREAM_INPUT_SOURCE "input_source"   /* audio_source_t */
+#define AUDIO_PARAMETER_STREAM_SAMPLING_RATE "sampling_rate" /* uint32_t */
 
 /* Query supported formats. The response is a '|' separated list of strings from
  * audio_format_t enum e.g: "sup_formats=AUDIO_FORMAT_PCM_16_BIT" */
@@ -127,6 +134,11 @@
  * "sup_sampling_rates=44100|48000" */
 #define AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES "sup_sampling_rates"
 
+/* Get the HW synchronization source used for an output stream.
+ * Return a valid source (positive integer) or AUDIO_HW_SYNC_INVALID if an error occurs
+ * or no HW sync source is used. */
+#define AUDIO_PARAMETER_STREAM_HW_AV_SYNC "hw_av_sync"
+
 /**
  * audio codec parameters
  */
@@ -146,18 +158,6 @@
 
 /**************************************/
 
-/* common audio stream configuration parameters
- * You should memset() the entire structure to zero before use to
- * ensure forward compatibility
- */
-struct audio_config {
-    uint32_t sample_rate;
-    audio_channel_mask_t channel_mask;
-    audio_format_t  format;
-    audio_offload_info_t offload_info;
-};
-typedef struct audio_config audio_config_t;
-
 /* common audio stream parameters and operations */
 struct audio_stream {
 
@@ -563,13 +563,21 @@
     size_t (*get_input_buffer_size)(const struct audio_hw_device *dev,
                                     const struct audio_config *config);
 
-    /** This method creates and opens the audio hardware output stream */
+    /** This method creates and opens the audio hardware output stream.
+     * The "address" parameter qualifies the "devices" audio device type if needed.
+     * The format format depends on the device type:
+     * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC"
+     * - USB devices use the ALSA card and device numbers in the form  "card=X;device=Y"
+     * - Other devices may use a number or any other string.
+     */
+
     int (*open_output_stream)(struct audio_hw_device *dev,
                               audio_io_handle_t handle,
                               audio_devices_t devices,
                               audio_output_flags_t flags,
                               struct audio_config *config,
-                              struct audio_stream_out **stream_out);
+                              struct audio_stream_out **stream_out,
+                              const char *address);
 
     void (*close_output_stream)(struct audio_hw_device *dev,
                                 struct audio_stream_out* stream_out);
@@ -580,7 +588,9 @@
                              audio_devices_t devices,
                              struct audio_config *config,
                              struct audio_stream_in **stream_in,
-                             audio_input_flags_t flags);
+                             audio_input_flags_t flags,
+                             const char *address,
+                             audio_source_t source);
 
     void (*close_input_stream)(struct audio_hw_device *dev,
                                struct audio_stream_in *stream_in);
diff --git a/include/hardware/bluetooth.h b/include/hardware/bluetooth.h
index 4d38ff7..74cd1fc 100644
--- a/include/hardware/bluetooth.h
+++ b/include/hardware/bluetooth.h
@@ -98,6 +98,15 @@
     uint8_t pin[16];
 } __attribute__((packed))bt_pin_code_t;
 
+typedef struct {
+    uint8_t status;
+    uint8_t ctrl_state;     /* stack reported state */
+    uint64_t tx_time;       /* in ms */
+    uint64_t rx_time;       /* in ms */
+    uint64_t idle_time;     /* in ms */
+    uint64_t energy_used;   /* a product of mA, V and ms */
+} __attribute__((packed))bt_activity_energy_info;
+
 /** Bluetooth Adapter Discovery state */
 typedef enum {
     BT_DISCOVERY_STOPPED,
@@ -139,7 +148,9 @@
     uint8_t rpa_offload_supported;
     uint8_t max_irk_list_size;
     uint8_t max_adv_filter_supported;
-    uint8_t scan_result_storage_size;
+    uint8_t scan_result_storage_size_lobyte;
+    uint8_t scan_result_storage_size_hibyte;
+    uint8_t activity_energy_info_supported;
 }bt_local_le_features_t;
 
 /* Bluetooth Adapter and Remote Device property types */
@@ -345,6 +356,15 @@
 * This callback shall be invoked whenever the le_tx_test, le_rx_test or le_test_end is invoked
 * The num_packets is valid only for le_test_end command */
 typedef void (*le_test_mode_callback)(bt_status_t status, uint16_t num_packets);
+
+/** Callback invoked when energy details are obtained */
+/* Ctrl_state-Current controller state-Active-1,scan-2,or idle-3 state as defined by HCI spec.
+ * If the ctrl_state value is 0, it means the API call failed
+ * Time values-In milliseconds as returned by the controller
+ * Energy used-Value as returned by the controller
+ * Status-Provides the status of the read_energy_info API call */
+typedef void (*energy_info_callback)(bt_activity_energy_info *energy_info);
+
 /** TODO: Add callbacks for Link Up/Down and other generic
   *  notifications/callbacks */
 
@@ -364,6 +384,7 @@
     callback_thread_event thread_evt_cb;
     dut_mode_recv_callback dut_mode_recv_cb;
     le_test_mode_callback le_test_mode_cb;
+    energy_info_callback energy_info_cb;
 } bt_callbacks_t;
 
 typedef void (*alarm_cb)(void *data);
@@ -459,7 +480,7 @@
     int (*cancel_discovery)(void);
 
     /** Create Bluetooth Bonding */
-    int (*create_bond)(const bt_bdaddr_t *bd_addr);
+    int (*create_bond)(const bt_bdaddr_t *bd_addr, int transport);
 
     /** Remove Bond */
     int (*remove_bond)(const bt_bdaddr_t *bd_addr);
@@ -507,6 +528,11 @@
       * This should be called immediately after a successful |init|.
       */
     int (*set_os_callouts)(bt_os_callouts_t *callouts);
+
+    /** Read Energy info details - return value indicates BT_STATUS_SUCCESS or BT_STATUS_NOT_READY
+      * Success indicates that the VSC command was sent to controller
+      */
+    int (*read_energy_info)();
 } bt_interface_t;
 
 /** TODO: Need to add APIs for Service Discovery, Service authorization and
diff --git a/include/hardware/bt_gatt_client.h b/include/hardware/bt_gatt_client.h
index 295f5c8..8073dd1 100644
--- a/include/hardware/bt_gatt_client.h
+++ b/include/hardware/bt_gatt_client.h
@@ -170,10 +170,6 @@
 /** Callback invoked when a scan filter configuration command has completed */
 typedef void (*scan_filter_status_callback)(int enable, int client_if, int status);
 
-/** Track ADV VSE callback invoked when tracked device is found or lost */
-typedef void (*track_adv_event_callback)(int client_if, int filt_index, int addr_type,
-                                             bt_bdaddr_t* bda, int adv_state);
-
 /** Callback invoked when multi-adv enable operation has completed */
 typedef void (*multi_adv_enable_callback)(int client_if, int status);
 
@@ -205,6 +201,9 @@
 /** Callback invoked when batchscan storage threshold limit is crossed */
 typedef void (*batchscan_threshold_callback)(int client_if);
 
+/** Track ADV VSE callback invoked when tracked device is found or lost */
+typedef void (*track_adv_event_callback)(int client_if, int filt_index, int addr_type,
+                                             bt_bdaddr_t* bda, int adv_state);
 
 typedef struct {
     register_client_callback            register_client_cb;
diff --git a/include/hardware/camera_common.h b/include/hardware/camera_common.h
index 0ee929e..322ed93 100644
--- a/include/hardware/camera_common.h
+++ b/include/hardware/camera_common.h
@@ -268,8 +268,29 @@
     /**
      * Common methods of the camera module.  This *must* be the first member of
      * camera_module as users of this structure will cast a hw_module_t to
-     * camera_module pointer in contexts where it's known the hw_module_t references a
-     * camera_module.
+     * camera_module pointer in contexts where it's known the hw_module_t
+     * references a camera_module.
+     *
+     * The return values for common.methods->open for camera_module are:
+     *
+     * 0:           On a successful open of the camera device.
+     *
+     * -ENODEV:     The camera device cannot be opened due to an internal
+     *              error.
+     *
+     * -EINVAL:     The input arguments are invalid, i.e. the id is invalid,
+     *              and/or the module is invalid.
+     *
+     * -EBUSY:      The camera device was already opened for this camera id
+     *              (by using this method or open_legacy),
+     *              regardless of the device HAL version it was opened as.
+     *
+     * -EUSERS:     The maximal number of camera devices that can be
+     *              opened concurrently were opened already, either by
+     *              this method or the open_legacy method.
+     *
+     * All other return values from common.methods->open will be treated as
+     * -ENODEV.
      */
     hw_module_t common;
 
@@ -293,6 +314,15 @@
      * Return the static camera information for a given camera device. This
      * information may not change for a camera device.
      *
+     * Return values:
+     *
+     * 0:           On a successful operation
+     *
+     * -ENODEV:     The information cannot be provided due to an internal
+     *              error.
+     *
+     * -EINVAL:     The input arguments are invalid, i.e. the id is invalid,
+     *              and/or the module is invalid.
      */
     int (*get_camera_info)(int camera_id, struct camera_info *info);
 
@@ -315,6 +345,15 @@
      *
      *    Valid to be called by the framework.
      *
+     * Return values:
+     *
+     * 0:           On a successful operation
+     *
+     * -ENODEV:     The operation cannot be completed due to an internal
+     *              error.
+     *
+     * -EINVAL:     The input arguments are invalid, i.e. the callbacks are
+     *              null
      */
     int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
 
diff --git a/include/hardware/gps.h b/include/hardware/gps.h
index 5747faa..eb44d5c 100644
--- a/include/hardware/gps.h
+++ b/include/hardware/gps.h
@@ -110,6 +110,10 @@
 #define GPS_CAPABILITY_ON_DEMAND_TIME   0x0000010
 /** GPS supports Geofencing  */
 #define GPS_CAPABILITY_GEOFENCING       0x0000020
+/** GPS supports Measurements */
+#define GPS_CAPABILITY_MEASUREMENTS     0x0000040
+/** GPS supports Navigation Messages */
+#define GPS_CAPABILITY_NAV_MESSAGES     0x0000080
 
 /** Flags used to specify which aiding data to delete
     when calling delete_aiding_data(). */
@@ -1690,7 +1694,7 @@
     /**
      * The length of the data (in bytes) contained in the current message.
      * If this value is different from zero, 'data' must point to an array of the same size.
-     * i.e. for L1 C/A the size of the sub-frame will be 40 bytes (10 words).
+     * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
      *
      * This is a Mandatory value.
      */
@@ -1699,6 +1703,9 @@
     /**
      * The data of the reported GPS message.
      * The bytes (or words) specified using big endian format (MSB first).
+     *
+     * For L1 C/A, each subframe contains 10 30-bit GPS words. Each GPS word (30 bits) should be
+     * fitted into the last 30 bits in a 4-byte word (skip B31 and B32), with MSB first.
      */
     uint8_t* data;
 
diff --git a/include/hardware/gralloc.h b/include/hardware/gralloc.h
index e7d0103..91e2f69 100644
--- a/include/hardware/gralloc.h
+++ b/include/hardware/gralloc.h
@@ -124,6 +124,9 @@
      */
     GRALLOC_USAGE_PROTECTED             = 0x00004000,
 
+    /* buffer may be used as a cursor */
+    GRALLOC_USAGE_CURSOR                = 0x00008000,
+
     /* implementation-specific private usage flags */
     GRALLOC_USAGE_PRIVATE_0             = 0x10000000,
     GRALLOC_USAGE_PRIVATE_1             = 0x20000000,
diff --git a/include/hardware/hdmi_cec.h b/include/hardware/hdmi_cec.h
index 646dc45..95c0c4e 100644
--- a/include/hardware/hdmi_cec.h
+++ b/include/hardware/hdmi_cec.h
@@ -339,7 +339,7 @@
      * some reason. HAL implementation should take the situation into account
      * so as not to wait forever for the message to get sent out.
      *
-     * It should not try retransmission because it's handled by upper layer.
+     * It should try retransmission at least once as specified in the standard.
      *
      * Returns error code. See HDMI_RESULT_SUCCESS, HDMI_RESULT_NACK, and
      * HDMI_RESULT_BUSY.
diff --git a/include/hardware/hwcomposer.h b/include/hardware/hwcomposer.h
index af04181..3dfb4fd 100644
--- a/include/hardware/hwcomposer.h
+++ b/include/hardware/hwcomposer.h
@@ -141,6 +141,13 @@
      *   as a solid color since the platform is not currently able to composite
      *   sideband layers with the GPU. This may be improved in future
      *   versions of the platform.
+     *
+     *
+     * HWC_CURSOR_OVERLAY
+     *   Set by the HWC implementation during (*prepare)(), this value
+     *   indicates the layer's composition will now be handled by the HWC.
+     *   Additionally, the client can now asynchronously update the on-screen
+     *   position of this layer using the setCursorPositionAsync() api.
      */
     int32_t compositionType;
 
@@ -505,11 +512,12 @@
      * (*prepare)() can be called more than once, the last call prevails.
      *
      * The HWC responds by setting the compositionType field in each layer to
-     * either HWC_FRAMEBUFFER or HWC_OVERLAY. In the former case, the
-     * composition for the layer is handled by SurfaceFlinger with OpenGL ES,
-     * in the later case, the HWC will have to handle the layer's composition.
-     * compositionType and hints are preserved between (*prepare)() calles
-     * unless the HWC_GEOMETRY_CHANGED flag is set.
+     * either HWC_FRAMEBUFFER, HWC_OVERLAY, or HWC_CURSOR_OVERLAY. For the
+     * HWC_FRAMEBUFFER type, composition for the layer is handled by
+     * SurfaceFlinger with OpenGL ES. For the latter two overlay types,
+     * the HWC will have to handle the layer's composition. compositionType
+     * and hints are preserved between (*prepare)() calles unless the
+     * HWC_GEOMETRY_CHANGED flag is set.
      *
      * (*prepare)() is called with HWC_GEOMETRY_CHANGED to indicate that the
      * list's geometry has changed, that is, when more than just the buffer's
@@ -751,11 +759,37 @@
      */
     int (*setActiveConfig)(struct hwc_composer_device_1* dev, int disp,
             int index);
+    /*
+     * Asynchronously update the location of the cursor layer.
+     *
+     * Within the standard prepare()/set() composition loop, the client
+     * (surfaceflinger) can request that a given layer uses dedicated cursor
+     * composition hardware by specifiying the HWC_IS_CURSOR_LAYER flag. Only
+     * one layer per display can have this flag set. If the layer is suitable
+     * for the platform's cursor hardware, hwcomposer will return from prepare()
+     * a composition type of HWC_CURSOR_OVERLAY for that layer. This indicates
+     * not only that the client is not responsible for compositing that layer,
+     * but also that the client can continue to update the position of that layer
+     * after a call to set(). This can reduce the visible latency of mouse
+     * movement to visible, on-screen cursor updates. Calls to
+     * setCursorPositionAsync() may be made from a different thread doing the
+     * prepare()/set() composition loop, but care must be taken to not interleave
+     * calls of setCursorPositionAsync() between calls of set()/prepare().
+     *
+     * Notes:
+     * - Only one layer per display can be specified as a cursor layer with
+     *   HWC_IS_CURSOR_LAYER.
+     * - hwcomposer will only return one layer per display as HWC_CURSOR_OVERLAY
+     * - This returns 0 on success or -errno on error.
+     * - This field is optional for HWC_DEVICE_API_VERSION_1_4 and later. It
+     *   should be null for previous versions.
+     */
+    int (*setCursorPositionAsync)(struct hwc_composer_device_1 *dev, int disp, int x_pos, int y_pos);
 
     /*
      * Reserved for future use. Must be NULL.
      */
-    void* reserved_proc[2];
+    void* reserved_proc[1];
 
 } hwc_composer_device_1_t;
 
diff --git a/include/hardware/hwcomposer_defs.h b/include/hardware/hwcomposer_defs.h
index d24bc9d..9a52436 100644
--- a/include/hardware/hwcomposer_defs.h
+++ b/include/hardware/hwcomposer_defs.h
@@ -77,6 +77,16 @@
      * by SurfaceFlinger (just as if compositionType was set to HWC_OVERLAY).
      */
     HWC_SKIP_LAYER = 0x00000001,
+
+    /*
+     * HWC_IS_CURSOR_LAYER is set by surfaceflinger to indicate that this
+     * layer is being used as a cursor on this particular display, and that
+     * surfaceflinger can potentially perform asynchronous position updates for
+     * this layer. If a call to prepare() returns HWC_CURSOR_OVERLAY for the
+     * composition type of this layer, then the hwcomposer will allow async
+     * position updates to this layer via setCursorPositionAsync().
+     */
+    HWC_IS_CURSOR_LAYER = 0x00000002
 };
 
 /*
@@ -100,8 +110,13 @@
     /* this layer's contents are taken from a sideband buffer stream.
      * Added in HWC_DEVICE_API_VERSION_1_4. */
     HWC_SIDEBAND = 4,
-};
 
+    /* this layer's composition will be handled by hwcomposer by dedicated
+       cursor overlay hardware. hwcomposer will also all async position updates
+       of this layer outside of the normal prepare()/set() loop. Added in
+       HWC_DEVICE_API_VERSION_1_4. */
+    HWC_CURSOR_OVERLAY =  5
+ };
 /*
  * hwc_layer_t::blending values
  */
diff --git a/include/hardware/mcu.h b/include/hardware/mcu.h
deleted file mode 100644
index 6fe2cfe..0000000
--- a/include/hardware/mcu.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_INCLUDE_HARDWARE_MCU_H
-#define ANDROID_INCLUDE_HARDWARE_MCU_H
-
-#include <stdint.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#include <hardware/hardware.h>
-
-__BEGIN_DECLS
-
-#define MCU_MODULE_API_VERSION_0_1  HARDWARE_MODULE_API_VERSION(0, 1)
-
-/*
- * The id of this module
- */
-#define MCU_HARDWARE_MODULE_ID "mcu"
-
-/*
- * MCU message keys passed to (*sendMessage)
- */
-#define MCU_PARAMETER_MSG_ENABLE_MCU "enable_mcu"
-
-/*
- * MCU message values passed to (*sendMessage)
- */
-#define MCU_PARAMETER_ARG_ON "on"
-#define MCU_PARAMETER_ARG_OFF "off"
-
-/*
- * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
- * and the fields of this data structure must begin with hw_module_t
- * followed by module specific information.
- */
-typedef struct mcu_module {
-    struct hw_module_t common;
-
-    /*
-     * (*init)() performs MCU module setup actions at runtime startup, such
-     * as to initialize an external MCU. This is called only by the MCU HAL
-     * instance loaded by PowerManagerService.
-     *
-     * Returns 0 on success or -errno on error.
-     */
-    int (*init)(struct mcu_module *module);
-
-    /*
-     * (*sendMessage)() passes a message/argument pair to the MCU to execute
-     * a function. msg is NULL-terminated. If arg is text, then arg_len must
-     * reflect the string length. result is a heap-allocated buffer that the
-     * caller must free. If there is no result, then *result will be NULL and
-     * *result_len will be 0.
-     *
-     * Returns 0 on success or -errno in case of error (for example, if the
-     * MCU does not support the specified message.)
-     *
-     */
-    int (*sendMessage)(struct mcu_module *module, const char *msg,
-                        const void *arg, size_t arg_len, void **result,
-                        size_t *result_len);
-
-} mcu_module_t;
-
-__END_DECLS
-
-#endif  // ANDROID_INCLUDE_HARDWARE_MCU_H
diff --git a/include/hardware/nfc.h b/include/hardware/nfc.h
index 0a8ed72..58d33d9 100644
--- a/include/hardware/nfc.h
+++ b/include/hardware/nfc.h
@@ -53,6 +53,7 @@
  * 9) Core NCI stack calls close()
  */
 #define NFC_NCI_HARDWARE_MODULE_ID "nfc_nci"
+#define NFC_NCI_BCM2079X_HARDWARE_MODULE_ID "nfc_nci.bcm2079x"
 #define NFC_NCI_CONTROLLER "nci"
 
 /*
diff --git a/include/hardware/sensors.h b/include/hardware/sensors.h
index ec68b2b..339508a 100644
--- a/include/hardware/sensors.h
+++ b/include/hardware/sensors.h
@@ -205,13 +205,39 @@
 #define SENSOR_TYPE_META_DATA                        (0)
 
 /*
+  * Wake up sensors.
+  * Each sensor may have either or both a wake-up and a non-wake variant.
+  * When registered in batch mode, wake-up sensors will wake up the AP when
+  * their FIFOs are full or when the batch timeout expires. A separate FIFO has
+  * to be maintained for wake up sensors and non wake up sensors. The non wake-up
+  * sensors need to overwrite their FIFOs when they are full till the AP wakes up
+  * and the wake-up sensors will wake-up the AP when their FIFOs are full or when
+  * the batch timeout expires without losing events. Wake-up and non wake-up variants
+  * of each sensor can be activated at different rates independently of each other.
+  *
+  * Note: Proximity sensor and significant motion sensor which were defined in previous
+  * releases are also wake-up sensors and should be treated as such. Wake-up one-shot
+  * sensors like SIGNIFICANT_MOTION cannot be batched, hence the text about batch above
+  * doesn't apply to them. See the definitions of SENSOR_TYPE_PROXIMITY and
+  * SENSOR_TYPE_SIGNIFICANT_MOTION for more info.
+  *
+  * Set SENSOR_FLAG_WAKE_UP flag for all wake-up sensors.
+  *
+  * For example, A device can have two sensors both of SENSOR_TYPE_ACCELEROMETER and
+  * one of them can be a wake_up sensor (with SENSOR_FLAG_WAKE_UP flag set) and the other
+  * can be a regular non wake_up sensor. Both of these sensors must be activated/deactivated
+  * independently of the other.
+  */
+
+/*
  * SENSOR_TYPE_ACCELEROMETER
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  *  All values are in SI units (m/s^2) and measure the acceleration of the
  *  device minus the force of gravity.
  *
+ *  Implement the non-wake-up version of this sensor and implement the wake-up
+ *  version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_ACCELEROMETER                    (1)
 #define SENSOR_STRING_TYPE_ACCELEROMETER             "android.sensor.accelerometer"
@@ -219,11 +245,12 @@
 /*
  * SENSOR_TYPE_GEOMAGNETIC_FIELD
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  *  All values are in micro-Tesla (uT) and measure the geomagnetic
  *  field in the X, Y and Z axis.
  *
+ *  Implement the non-wake-up version of this sensor and implement the wake-up
+ *  version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_GEOMAGNETIC_FIELD                (2)
 #define SENSOR_TYPE_MAGNETIC_FIELD  SENSOR_TYPE_GEOMAGNETIC_FIELD
@@ -232,12 +259,14 @@
 /*
  * SENSOR_TYPE_ORIENTATION
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  * All values are angles in degrees.
  *
  * Orientation sensors return sensor events for all 3 axes at a constant
  * rate defined by setDelay().
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_ORIENTATION                      (3)
 #define SENSOR_STRING_TYPE_ORIENTATION               "android.sensor.orientation"
@@ -245,10 +274,12 @@
 /*
  * SENSOR_TYPE_GYROSCOPE
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  *  All values are in radians/second and measure the rate of rotation
  *  around the X, Y and Z axis.
+ *
+ *  Implement the non-wake-up version of this sensor and implement the wake-up
+ *  version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_GYROSCOPE                        (4)
 #define SENSOR_STRING_TYPE_GYROSCOPE                 "android.sensor.gyroscope"
@@ -256,9 +287,10 @@
 /*
  * SENSOR_TYPE_LIGHT
  * reporting-mode: on-change
- * wake-up sensor: no
  *
  * The light sensor value is returned in SI lux units.
+ *
+ * Both wake-up and non wake-up versions are useful.
  */
 #define SENSOR_TYPE_LIGHT                            (5)
 #define SENSOR_STRING_TYPE_LIGHT                     "android.sensor.light"
@@ -266,9 +298,11 @@
 /*
  * SENSOR_TYPE_PRESSURE
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  * The pressure sensor return the athmospheric pressure in hectopascal (hPa)
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_PRESSURE                         (6)
 #define SENSOR_STRING_TYPE_PRESSURE                  "android.sensor.pressure"
@@ -280,8 +314,11 @@
 /*
  * SENSOR_TYPE_PROXIMITY
  * reporting-mode: on-change
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
  *
+ * The proximity sensor which turns the screen off and back on during calls is the
+ * wake-up proximity sensor. Implement wake-up proximity sensor before implementing
+ * a non wake-up proximity sensor. For the wake-up proximity sensor set the flag
+ * SENSOR_FLAG_WAKE_UP.
  * The value corresponds to the distance to the nearest object in centimeters.
  */
 #define SENSOR_TYPE_PROXIMITY                        (8)
@@ -290,10 +327,12 @@
 /*
  * SENSOR_TYPE_GRAVITY
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  * A gravity output indicates the direction of and magnitude of gravity in
  * the devices's coordinates.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_GRAVITY                          (9)
 #define SENSOR_STRING_TYPE_GRAVITY                   "android.sensor.gravity"
@@ -301,10 +340,12 @@
 /*
  * SENSOR_TYPE_LINEAR_ACCELERATION
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  * Indicates the linear acceleration of the device in device coordinates,
  * not including gravity.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_LINEAR_ACCELERATION             (10)
 #define SENSOR_STRING_TYPE_LINEAR_ACCELERATION      "android.sensor.linear_acceleration"
@@ -313,10 +354,12 @@
 /*
  * SENSOR_TYPE_ROTATION_VECTOR
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  * The rotation vector symbolizes the orientation of the device relative to the
  * East-North-Up coordinates frame.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_ROTATION_VECTOR                 (11)
 #define SENSOR_STRING_TYPE_ROTATION_VECTOR          "android.sensor.rotation_vector"
@@ -324,10 +367,11 @@
 /*
  * SENSOR_TYPE_RELATIVE_HUMIDITY
  * reporting-mode: on-change
- * wake-up sensor: no
  *
  * A relative humidity sensor measures relative ambient air humidity and
  * returns a value in percent.
+ *
+ * Both wake-up and non wake-up versions are useful.
  */
 #define SENSOR_TYPE_RELATIVE_HUMIDITY               (12)
 #define SENSOR_STRING_TYPE_RELATIVE_HUMIDITY        "android.sensor.relative_humidity"
@@ -335,9 +379,10 @@
 /*
  * SENSOR_TYPE_AMBIENT_TEMPERATURE
  * reporting-mode: on-change
- * wake-up sensor: no
  *
  * The ambient (room) temperature in degree Celsius.
+ *
+ * Both wake-up and non wake-up versions are useful.
  */
 #define SENSOR_TYPE_AMBIENT_TEMPERATURE             (13)
 #define SENSOR_STRING_TYPE_AMBIENT_TEMPERATURE      "android.sensor.ambient_temperature"
@@ -345,10 +390,12 @@
 /*
  * SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  *  Similar to SENSOR_TYPE_MAGNETIC_FIELD, but the hard iron calibration is
  *  reported separately instead of being included in the measurement.
+ *
+ *  Implement the non-wake-up version of this sensor and implement the wake-up
+ *  version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED     (14)
 #define SENSOR_STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED "android.sensor.magnetic_field_uncalibrated"
@@ -356,10 +403,12 @@
 /*
  * SENSOR_TYPE_GAME_ROTATION_VECTOR
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  *  Similar to SENSOR_TYPE_ROTATION_VECTOR, but not using the geomagnetic
  *  field.
+ *
+ *  Implement the non-wake-up version of this sensor and implement the wake-up
+ *  version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_GAME_ROTATION_VECTOR            (15)
 #define SENSOR_STRING_TYPE_GAME_ROTATION_VECTOR     "android.sensor.game_rotation_vector"
@@ -367,10 +416,12 @@
 /*
  * SENSOR_TYPE_GYROSCOPE_UNCALIBRATED
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  *  All values are in radians/second and measure the rate of rotation
  *  around the X, Y and Z axis.
+ *
+ *  Implement the non-wake-up version of this sensor and implement the wake-up
+ *  version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_GYROSCOPE_UNCALIBRATED          (16)
 #define SENSOR_STRING_TYPE_GYROSCOPE_UNCALIBRATED   "android.sensor.gyroscope_uncalibrated"
@@ -378,10 +429,12 @@
 /*
  * SENSOR_TYPE_SIGNIFICANT_MOTION
  * reporting-mode: one-shot
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
  *
  * A sensor of this type triggers an event each time significant motion
  * is detected and automatically disables itself.
+ * For Significant Motion sensor to be useful, it must be defined as a
+ * wake-up sensor. (set SENSOR_FLAG_WAKE_UP). Implement the wake-up significant motion
+ * sensor. A non wake-up version is not useful.
  * The only allowed value to return is 1.0.
  */
 
@@ -391,11 +444,12 @@
 /*
  * SENSOR_TYPE_STEP_DETECTOR
  * reporting-mode: special
- * wake-up sensor: no
  *
  * A sensor of this type triggers an event each time a step is taken
  * by the user. The only allowed value to return is 1.0 and an event
  * is generated for each step.
+ *
+ * Both wake-up and non wake-up versions are useful.
  */
 
 #define SENSOR_TYPE_STEP_DETECTOR                   (18)
@@ -405,11 +459,13 @@
 /*
  * SENSOR_TYPE_STEP_COUNTER
  * reporting-mode: on-change
- * wake-up sensor: no
  *
  * A sensor of this type returns the number of steps taken by the user since
  * the last reboot while activated. The value is returned as a uint64_t and is
  * reset to zero only on a system / android reboot.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
  */
 
 #define SENSOR_TYPE_STEP_COUNTER                    (19)
@@ -418,10 +474,12 @@
 /*
  * SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR
  * reporting-mode: continuous
- * wake-up sensor: no
  *
  *  Similar to SENSOR_TYPE_ROTATION_VECTOR, but using a magnetometer instead
  *  of using a gyroscope.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
  */
 #define SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR     (20)
 #define SENSOR_STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR "android.sensor.geomagnetic_rotation_vector"
@@ -429,7 +487,6 @@
 /*
  * SENSOR_TYPE_HEART_RATE
  * reporting-mode: on-change
- * wake-up sensor: no
  *
  *  A sensor of this type returns the current heart rate.
  *  The events contain the current heart rate in beats per minute (BPM) and the
@@ -443,96 +500,15 @@
  *  mode for more information.
  *
  *  sensor_t.requiredPermission must be set to SENSOR_PERMISSION_BODY_SENSORS.
+ *
+ *  Both wake-up and non wake-up versions are useful.
  */
 #define SENSOR_TYPE_HEART_RATE                      (21)
 #define SENSOR_STRING_TYPE_HEART_RATE               "android.sensor.heart_rate"
 
 /*
- * SENSOR_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR
- * Same as proximity_sensor but does not wake up the AP from suspend mode.
- * wake-up sensor: no
- */
-#define SENSOR_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR           (22)
-#define SENSOR_STRING_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR    "android.sensor.non_wake_up_proximity_sensor"
-
-/*
- * The sensors below are wake_up variants of the base sensor types defined
- * above. When registered in batch mode, these sensors will wake up the AP when
- * their FIFOs are full or when the batch timeout expires. A separate FIFO has
- * to be maintained for wake up sensors and non wake up sensors. The non wake-up
- * sensors need to overwrite their FIFOs when they are full till the AP wakes up
- * and the wake-up sensors will wake-up the AP when their FIFOs are full or when
- * the batch timeout expires without losing events.
- * Note: Sensors of type SENSOR_TYPE_PROXIMITY are also wake up sensors and
- * should be treated as such. Wake-up one-shot sensors like SIGNIFICANT_MOTION
- * cannot be batched, hence the text about batch above doesn't apply to them.
- *
- * Define these sensors only if:
- * 1) batching is supported.
- * 2) wake-up and non wake-up variants of each sensor can be activated at
- *    different rates.
- *
- * wake-up sensor: yes
- * Set SENSOR_FLAG_WAKE_UP flag for all these sensors.
- */
-#define SENSOR_TYPE_WAKE_UP_ACCELEROMETER                      (23)
-#define SENSOR_STRING_TYPE_WAKE_UP_ACCELEROMETER               "android.sensor.wake_up_accelerometer"
-
-#define SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD                     (24)
-#define SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD              "android.sensor.wake_up_magnetic_field"
-
-#define SENSOR_TYPE_WAKE_UP_ORIENTATION                        (25)
-#define SENSOR_STRING_TYPE_WAKE_UP_ORIENTATION                 "android.sensor.wake_up_orientation"
-
-#define SENSOR_TYPE_WAKE_UP_GYROSCOPE                          (26)
-#define SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE                   "android.sensor.wake_up_gyroscope"
-
-#define SENSOR_TYPE_WAKE_UP_LIGHT                              (27)
-#define SENSOR_STRING_TYPE_WAKE_UP_LIGHT                       "android.sensor.wake_up_light"
-
-#define SENSOR_TYPE_WAKE_UP_PRESSURE                           (28)
-#define SENSOR_STRING_TYPE_WAKE_UP_PRESSURE                    "android.sensor.wake_up_pressure"
-
-#define SENSOR_TYPE_WAKE_UP_GRAVITY                            (29)
-#define SENSOR_STRING_TYPE_WAKE_UP_GRAVITY                     "android.sensor.wake_up_gravity"
-
-#define SENSOR_TYPE_WAKE_UP_LINEAR_ACCELERATION                (30)
-#define SENSOR_STRING_TYPE_WAKE_UP_LINEAR_ACCELERATION         "android.sensor.wake_up_linear_acceleration"
-
-#define SENSOR_TYPE_WAKE_UP_ROTATION_VECTOR                    (31)
-#define SENSOR_STRING_TYPE_WAKE_UP_ROTATION_VECTOR             "android.sensor.wake_up_rotation_vector"
-
-#define SENSOR_TYPE_WAKE_UP_RELATIVE_HUMIDITY                  (32)
-#define SENSOR_STRING_TYPE_WAKE_UP_RELATIVE_HUMIDITY           "android.sensor.wake_up_relative_humidity"
-
-#define SENSOR_TYPE_WAKE_UP_AMBIENT_TEMPERATURE                (33)
-#define SENSOR_STRING_TYPE_WAKE_UP_AMBIENT_TEMPERATURE         "android.sensor.wake_up_ambient_temperature"
-
-#define SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED        (34)
-#define SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED "android.sensor.wake_up_magnetic_field_uncalibrated"
-
-#define SENSOR_TYPE_WAKE_UP_GAME_ROTATION_VECTOR               (35)
-#define SENSOR_STRING_TYPE_WAKE_UP_GAME_ROTATION_VECTOR        "android.sensor.wake_up_game_rotation_vector"
-
-#define SENSOR_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED             (36)
-#define SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED      "android.sensor.wake_up_gyroscope_uncalibrated"
-
-#define SENSOR_TYPE_WAKE_UP_STEP_DETECTOR                      (37)
-#define SENSOR_STRING_TYPE_WAKE_UP_STEP_DETECTOR               "android.sensor.wake_up_step_detector"
-
-#define SENSOR_TYPE_WAKE_UP_STEP_COUNTER                       (38)
-#define SENSOR_STRING_TYPE_WAKE_UP_STEP_COUNTER                "android.sensor.wake_up_step_counter"
-
-#define SENSOR_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR        (39)
-#define SENSOR_STRING_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR "android.sensor.wake_up_geomagnetic_rotation_vector"
-
-#define SENSOR_TYPE_WAKE_UP_HEART_RATE                         (40)
-#define SENSOR_STRING_TYPE_WAKE_UP_HEART_RATE                  "android.sensor.wake_up_heart_rate"
-
-/*
  * SENSOR_TYPE_WAKE_UP_TILT_DETECTOR
  * reporting-mode: special (setDelay has no impact)
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
  *
  * A sensor of this type generates an event each time a tilt event is detected. A tilt event
  * should be generated if the direction of the 2-seconds window average gravity changed by at least
@@ -552,14 +528,15 @@
  * sensor that should allow the AP to go into suspend mode. Do not emulate this sensor in the HAL.
  * Like other wake up sensors, the driver is expected to a hold a wake_lock with a timeout of 200 ms
  * while reporting this event. The only allowed return value is 1.0.
+ *
+ * Implement only the wake-up version of this sensor.
  */
-#define SENSOR_TYPE_WAKE_UP_TILT_DETECTOR                      (41)
-#define SENSOR_STRING_TYPE_WAKE_UP_TILT_DETECTOR               "android.sensor.wake_up_tilt_detector"
+#define SENSOR_TYPE_TILT_DETECTOR                      (22)
+#define SENSOR_STRING_TYPE_TILT_DETECTOR               "android.sensor.tilt_detector"
 
 /*
  * SENSOR_TYPE_WAKE_GESTURE
  * reporting-mode: one-shot
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
  *
  * A sensor enabling waking up the device based on a device specific motion.
  *
@@ -573,14 +550,15 @@
  * the manufacturer of the device.
  * This sensor must be low power, as it is likely to be activated 24/7.
  * The only allowed value to return is 1.0.
+ *
+ * Implement only the wake-up version of this sensor.
  */
-#define SENSOR_TYPE_WAKE_GESTURE                               (42)
+#define SENSOR_TYPE_WAKE_GESTURE                               (23)
 #define SENSOR_STRING_TYPE_WAKE_GESTURE                        "android.sensor.wake_gesture"
 
 /*
  * SENSOR_TYPE_GLANCE_GESTURE
  * reporting-mode: one-shot
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
  *
  * A sensor enabling briefly turning the screen on to enable the user to
  * glance content on screen based on a specific motion.  The device should
@@ -598,20 +576,23 @@
  * the manufacturer of the device.
  * This sensor must be low power, as it is likely to be activated 24/7.
  * The only allowed value to return is 1.0.
+ *
+ * Implement only the wake-up version of this sensor.
  */
-#define SENSOR_TYPE_GLANCE_GESTURE                             (43)
+#define SENSOR_TYPE_GLANCE_GESTURE                             (24)
 #define SENSOR_STRING_TYPE_GLANCE_GESTURE                      "android.sensor.glance_gesture"
 
 /**
  * SENSOR_TYPE_PICK_UP_GESTURE
  * reporting-mode: one-shot
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
  *
  * A sensor of this type triggers when the device is picked up regardless of wherever is was
  * before (desk, pocket, bag). The only allowed return value is 1.0.
  * This sensor de-activates itself immediately after it triggers.
+ *
+ * Implement only the wake-up version of this sensor.
  */
-#define SENSOR_TYPE_PICK_UP_GESTURE                            (43)
+#define SENSOR_TYPE_PICK_UP_GESTURE                            (25)
 #define SENSOR_STRING_TYPE_PICK_UP_GESTURE                     "android.sensor.pick_up_gesture"
 
 /**
diff --git a/modules/Android.mk b/modules/Android.mk
index c903eee..0725d3e 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 \
-	mcu tv_input fingerprint
+	tv_input fingerprint
 include $(call all-named-subdir-makefiles,$(hardware_modules))
diff --git a/modules/audio/audio_hw.c b/modules/audio/audio_hw.c
index ef070c1..18c0e59 100644
--- a/modules/audio/audio_hw.c
+++ b/modules/audio/audio_hw.c
@@ -218,7 +218,8 @@
                                    audio_devices_t devices,
                                    audio_output_flags_t flags,
                                    struct audio_config *config,
-                                   struct audio_stream_out **stream_out)
+                                   struct audio_stream_out **stream_out,
+                                   const char *address __unused)
 {
     struct stub_audio_device *ladev = (struct stub_audio_device *)dev;
     struct stub_stream_out *out;
@@ -328,7 +329,9 @@
                                   audio_devices_t devices,
                                   struct audio_config *config,
                                   struct audio_stream_in **stream_in,
-                                  audio_input_flags_t flags __unused)
+                                  audio_input_flags_t flags __unused,
+                                  const char *address __unused,
+                                  audio_source_t source __unused)
 {
     struct stub_audio_device *ladev = (struct stub_audio_device *)dev;
     struct stub_stream_in *in;
diff --git a/modules/audio_remote_submix/audio_hw.cpp b/modules/audio_remote_submix/audio_hw.cpp
index 9e824b1..014da8e 100644
--- a/modules/audio_remote_submix/audio_hw.cpp
+++ b/modules/audio_remote_submix/audio_hw.cpp
@@ -1188,7 +1188,8 @@
                                    audio_devices_t devices,
                                    audio_output_flags_t flags,
                                    struct audio_config *config,
-                                   struct audio_stream_out **stream_out)
+                                   struct audio_stream_out **stream_out,
+                                   const char *address __unused)
 {
     struct submix_audio_device * const rsxadev = audio_hw_device_get_submix_audio_device(dev);
     ALOGV("adev_open_output_stream()");
@@ -1374,7 +1375,9 @@
                                   audio_devices_t devices,
                                   struct audio_config *config,
                                   struct audio_stream_in **stream_in,
-                                  audio_input_flags_t flags __unused)
+                                  audio_input_flags_t flags __unused,
+                                  const char *address __unused,
+                                  audio_source_t source __unused)
 {
     struct submix_audio_device *rsxadev = audio_hw_device_get_submix_audio_device(dev);
     struct submix_stream_in *in;
diff --git a/modules/mcu/Android.mk b/modules/mcu/Android.mk
deleted file mode 100644
index ec40e3a..0000000
--- a/modules/mcu/Android.mk
+++ /dev/null
@@ -1,25 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := mcu.default
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := mcu.c
-LOCAL_SHARED_LIBRARIES := liblog
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/modules/mcu/mcu.c b/modules/mcu/mcu.c
deleted file mode 100644
index 47300f9..0000000
--- a/modules/mcu/mcu.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#define LOG_TAG "Legacy MCU HAL"
-#include <utils/Log.h>
-
-#include <hardware/hardware.h>
-#include <hardware/mcu.h>
-
-static int mcu_init(struct mcu_module *module)
-{
-    return 0;
-}
-
-static int mcu_send_message(struct mcu_module *module, const char *msg,
-                            const void *arg, size_t arg_len, void **result,
-                            size_t *result_len)
-{
-    return 0;
-}
-
-static struct hw_module_methods_t mcu_module_methods = {
-    .open = NULL,
-};
-
-struct mcu_module HAL_MODULE_INFO_SYM = {
-    .common = {
-        .tag = HARDWARE_MODULE_TAG,
-        .module_api_version = MCU_MODULE_API_VERSION_0_1,
-        .hal_api_version = HARDWARE_HAL_API_VERSION,
-        .id = MCU_HARDWARE_MODULE_ID,
-        .name = "Default MCU HAL",
-        .author = "The Android Open Source Project",
-        .methods = &mcu_module_methods,
-    },
-
-    .init = mcu_init,
-    .sendMessage = mcu_send_message,
-};
diff --git a/modules/soundtrigger/sound_trigger_hw.c b/modules/soundtrigger/sound_trigger_hw.c
index b78a0d1..e7f9baf 100644
--- a/modules/soundtrigger/sound_trigger_hw.c
+++ b/modules/soundtrigger/sound_trigger_hw.c
@@ -38,6 +38,7 @@
         false, // capture_transition
         0, // max_buffer_ms
         false, // concurrent_capture
+        false, // trigger_in_event
         0 // power_consumption_mw
 };
 
@@ -51,7 +52,6 @@
     pthread_t callback_thread;
     pthread_mutex_t lock;
     pthread_cond_t  cond;
-
 };
 
 
@@ -78,9 +78,9 @@
         event->common.status = RECOGNITION_STATUS_SUCCESS;
         event->common.type = SOUND_MODEL_TYPE_KEYPHRASE;
         event->common.model = stdev->model_handle;
-        event->key_phrase_in_capture = false;
         event->num_phrases = 1;
         event->phrase_extras[0].recognition_modes = RECOGNITION_MODE_VOICE_TRIGGER;
+        event->phrase_extras[0].confidence_level = 100;
         event->phrase_extras[0].num_levels = 1;
         event->phrase_extras[0].levels[0].level = 100;
         event->phrase_extras[0].levels[0].user_id = 0;
diff --git a/modules/usbaudio/Android.mk b/modules/usbaudio/Android.mk
index 89c498b..ec8a8c0 100644
--- a/modules/usbaudio/Android.mk
+++ b/modules/usbaudio/Android.mk
@@ -19,7 +19,11 @@
 LOCAL_MODULE := audio.usb.default
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_SRC_FILES := \
-	audio_hw.c
+	audio_hw.c \
+	alsa_device_profile.c \
+	alsa_device_proxy.c \
+	logging.c \
+	format.c
 LOCAL_C_INCLUDES += \
 	external/tinyalsa/include \
 	$(call include-path-for, audio-utils)
diff --git a/modules/usbaudio/alsa_device_profile.c b/modules/usbaudio/alsa_device_profile.c
new file mode 100644
index 0000000..f214eab
--- /dev/null
+++ b/modules/usbaudio/alsa_device_profile.c
@@ -0,0 +1,476 @@
+/*
+ * 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};
+
+void profile_init(alsa_device_profile* profile, int direction)
+{
+    profile->card = profile->device = -1;
+    profile->direction = direction;
+
+    /* 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;
+}
+
+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;
+}
+
+/*
+ * 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, std_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;
+    bool stereo_allowed = false;
+    unsigned index;
+    unsigned channel_count;
+
+    for (index = 0; (channel_count = profile->channel_counts[index]) != 0; index++) {
+        stereo_allowed = stereo_allowed || 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_allowed && isOutProfile) {
+        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
new file mode 100644
index 0000000..b75e1dc
--- /dev/null
+++ b/modules/usbaudio/alsa_device_profile.h
@@ -0,0 +1,88 @@
+/*
+ * 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_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
new file mode 100644
index 0000000..b887d1d
--- /dev/null
+++ b/modules/usbaudio/alsa_device_proxy.c
@@ -0,0 +1,157 @@
+/*
+ * 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 "alsa_device_proxy.h"
+
+#include "logging.h"
+
+#define DEFAULT_PERIOD_SIZE     1024
+#define DEFAULT_PERIOD_COUNT    2
+
+//void proxy_init(alsa_device_proxy * proxy)
+//{
+//    proxy->profile = NULL;
+//
+//    proxy->alsa_config.format = DEFAULT_SAMPLE_FORMAT;
+//    proxy->alsa_config.rate = DEFAULT_SAMPLE_RATE;
+//    proxy->alsa_config.channels = DEFAULT_CHANNEL_COUNT;
+//
+//    proxy->alsa_config.period_size = DEFAULT_PERIOD_SIZE;
+//    proxy->alsa_config.period_count = DEFAULT_PERIOD_COUNT;
+//
+//    proxy->pcm = NULL;
+//}
+
+void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
+                   struct pcm_config * config)
+{
+    ALOGV("proxy_prepare()");
+
+    proxy->profile = profile;
+
+#if 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);
+
+    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)
+{
+    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
new file mode 100644
index 0000000..f090c56
--- /dev/null
+++ b/modules/usbaudio/alsa_device_proxy.h
@@ -0,0 +1,49 @@
+/*
+ * 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_hw.c
index 05f0d2b..22d5e0f 100644
--- a/modules/usbaudio/audio_hw.c
+++ b/modules/usbaudio/audio_hw.c
@@ -16,7 +16,6 @@
 
 #define LOG_TAG "usb_audio_hw"
 /*#define LOG_NDEBUG 0*/
-/*#define LOG_PCM_PARAMS 0*/
 
 #include <errno.h>
 #include <inttypes.h>
@@ -39,46 +38,22 @@
 
 #include <audio_utils/channels.h>
 
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-/* This is the default configuration to hand to The Framework on the initial
- * adev_open_output_stream(). Actual device attributes will be used on the subsequent
- * adev_open_output_stream() after the card and device number have been set in out_set_parameters()
+/* FOR TESTING:
+ * Set k_force_channels to force the number of channels to present to AudioFlinger.
+ *   0 disables (this is default: present the device channels to AudioFlinger).
+ *   2 forces to legacy stereo mode.
+ *
+ * Others values can be tried (up to 8).
+ * TODO: AudioFlinger cannot support more than 8 active output channels
+ * at this time, so limiting logic needs to be put here or communicated from above.
  */
-#define OUT_PERIOD_SIZE 1024
-#define OUT_PERIOD_COUNT 4
-#define OUT_SAMPLING_RATE 44100
+static const unsigned k_force_channels = 0;
 
-struct pcm_config default_alsa_out_config = {
-    .channels = 2,
-    .rate = OUT_SAMPLING_RATE,
-    .period_size = OUT_PERIOD_SIZE,
-    .period_count = OUT_PERIOD_COUNT,
-    .format = PCM_FORMAT_S16_LE,
-};
+#include "alsa_device_profile.h"
+#include "alsa_device_proxy.h"
+#include "logging.h"
 
-/*
- * Input defaults.  See comment above.
- */
-#define IN_PERIOD_SIZE 1024
-#define IN_PERIOD_COUNT 4
-#define IN_SAMPLING_RATE 44100
-
-struct pcm_config default_alsa_in_config = {
-    .channels = 2,
-    .rate = IN_SAMPLING_RATE,
-    .period_size = IN_PERIOD_SIZE,
-    .period_count = IN_PERIOD_COUNT,
-    .format = PCM_FORMAT_S16_LE,
-    .start_threshold = 1,
-    .stop_threshold = (IN_PERIOD_SIZE * IN_PERIOD_COUNT),
-};
-
-struct audio_device_profile {
-    int card;
-    int device;
-    int direction; /* PCM_OUT or PCM_IN */
-};
+#define DEFAULT_INPUT_BUFFER_SIZE_MS 20
 
 struct audio_device {
     struct audio_hw_device hw_device;
@@ -86,10 +61,10 @@
     pthread_mutex_t lock; /* see note below on mutex acquisition order */
 
     /* output */
-    struct audio_device_profile out_profile;
+    alsa_device_profile out_profile;
 
     /* input */
-    struct audio_device_profile in_profile;
+    alsa_device_profile in_profile;
 
     bool standby;
 };
@@ -98,49 +73,39 @@
     struct audio_stream_out stream;
 
     pthread_mutex_t lock;               /* see note below on mutex acquisition order */
-    struct pcm *pcm;                    /* state of the stream */
     bool standby;
 
-    struct audio_device *dev;           /* hardware information */
-    struct audio_device_profile * profile;
+    struct audio_device *dev;           /* hardware information - only using this for the lock */
 
+    alsa_device_profile * profile;
+    alsa_device_proxy proxy;            /* state of the stream */
+
+    unsigned hal_channel_count;         /* channel count exposed to AudioFlinger.
+                                         * This may differ from the device channel count when
+                                         * the device is not compatible with AudioFlinger
+                                         * capabilities, e.g. exposes too many channels or
+                                         * too few channels. */
     void * conversion_buffer;           /* any conversions are put into here
                                          * they could come from here too if
                                          * there was a previous conversion */
     size_t conversion_buffer_size;      /* in bytes */
 };
 
-/*
- * Output Configuration Cache
- * FIXME(pmclean) This is not reentrant. Should probably be moved into the stream structure.
- */
-static struct pcm_config cached_output_hardware_config;
-static bool output_hardware_config_is_cached = false;
-
 struct stream_in {
     struct audio_stream_in stream;
 
     pthread_mutex_t lock; /* see note below on mutex acquisition order */
-    struct pcm *pcm;
     bool standby;
 
-    struct audio_device *dev;
+    struct audio_device *dev;           /* hardware information - only using this for the lock */
 
-    struct audio_device_profile * profile;
+    alsa_device_profile * profile;
+    alsa_device_proxy proxy;            /* state of the stream */
 
-    struct audio_config hal_pcm_config;
+    // not used?
+    // struct audio_config hal_pcm_config;
 
-    /* this is the format the framework thinks it's using. We may need to convert from the actual
-     * (24-bit, 32-bit?) format to this theoretical (framework, probably 16-bit)
-     * format in in_read() */
-    enum pcm_format input_framework_format;
-
-//    struct resampler_itfe *resampler;
-//    struct resampler_buffer_provider buf_provider;
-
-    int read_status;
-
-    // We may need to read more data from the device in order to data reduce to 16bit, 4chan */
+    /* We may need to read more data from the device in order to data reduce to 16bit, 4chan */
     void * conversion_buffer;           /* any conversions are put into here
                                          * they could come from here too if
                                          * there was a previous conversion */
@@ -148,17 +113,6 @@
 };
 
 /*
- * Input Configuration Cache
- * FIXME(pmclean) This is not reentrant. Should probably be moved into the stream structure
- * but that will involve changes in The Framework.
- */
-static struct pcm_config cached_input_hardware_config;
-static bool input_hardware_config_is_cached = false;
-
-/*
- * Utility
- */
-/*
  * Data Conversions
  */
 /*
@@ -226,465 +180,49 @@
     return num_in_samples * 2;
 }
 
-/*
- * ALSA Utilities
- */
-/*TODO This table and the function that uses it should be moved to a utilities module (probably) */
-/*
- * Maps bit-positions in a pcm_mask to the corresponding AUDIO_ format string.
- */
-static const char * const format_string_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 */
-    NULL,                               /* 03 - SNDRV_PCM_FORMAT_S16_BE */
-    NULL,                               /* 04 - SNDRV_PCM_FORMAT_U16_LE */
-    NULL,                               /* 05 - SNDRV_PCM_FORMAT_U16_BE */
-    "AUDIO_FORMAT_PCM_24_BIT_PACKED",   /* 06 - SNDRV_PCM_FORMAT_S24_LE */
-    NULL,                               /* 07 - SNDRV_PCM_FORMAT_S24_BE */
-    NULL,                               /* 08 - SNDRV_PCM_FORMAT_U24_LE */
-    NULL,                               /* 09 - SNDRV_PCM_FORMAT_U24_BE */
-    "AUDIO_FORMAT_PCM_32_BIT",          /* 10 - SNDRV_PCM_FORMAT_S32_LE */
-    NULL,                               /* 11 - SNDRV_PCM_FORMAT_S32_BE */
-    NULL,                               /* 12 - SNDRV_PCM_FORMAT_U32_LE */
-    NULL,                               /* 13 - SNDRV_PCM_FORMAT_U32_BE */
-    "AUDIO_FORMAT_PCM_FLOAT",           /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
-    NULL,                               /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
-    NULL,                               /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
-    NULL,                               /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
-    NULL,                               /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
-    NULL,                               /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
-    NULL,                               /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
-    NULL,                               /* 21 - SNDRV_PCM_FORMAT_A_LAW */
-    NULL,                               /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
-    NULL,                               /* 23 - SNDRV_PCM_FORMAT_MPEG */
-    NULL,                               /* 24 - SNDRV_PCM_FORMAT_GSM */
-    NULL, NULL, NULL, NULL, NULL, NULL, /* 25 -> 30 (not assigned) */
-    NULL,                               /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
-    "AUDIO_FORMAT_PCM_24_BIT_PACKED",   /* 32 - SNDRV_PCM_FORMAT_S24_3LE */ /* ??? */
-    NULL,                               /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
-    NULL,                               /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
-    NULL,                               /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
-    NULL,                               /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
-    NULL,                               /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
-    NULL,                               /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
-    NULL,                               /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
-    NULL,                               /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
-    NULL,                               /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
-    NULL,                               /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
-    NULL,                               /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
-    NULL,                               /* 44 - SNDRV_PCM_FORMAT_G723_24 */
-    NULL,                               /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
-    NULL,                               /* 46 - SNDRV_PCM_FORMAT_G723_40 */
-    NULL,                               /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
-    NULL,                               /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
-    NULL                                /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
-};
-
-/*
- * Generate string containing a bar ("|") delimited list of AUDIO_ formats specified in
- * the mask parameter.
- *
- */
-static char* get_format_str_for_mask(struct pcm_mask* mask)
+static char * device_get_parameters(alsa_device_profile * profile, const char * keys)
 {
-    char buffer[256];
-    int buffer_size = sizeof(buffer) / sizeof(buffer[0]);
-    buffer[0] = '\0';
+    ALOGV("usb:audio_hw::device_get_parameters() keys:%s", keys);
 
-    int num_slots = sizeof(mask->bits) / sizeof(mask->bits[0]);
-    int bits_per_slot = sizeof(mask->bits[0]) * 8;
-
-    const char* format_str = NULL;
-    int table_size = sizeof(format_string_map)/sizeof(format_string_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++) {
-            if ((mask->bits[slot_index] & bit_mask) != 0) {
-                format_str = table_index < table_size
-                                ? format_string_map[table_index]
-                                : NULL;
-                if (format_str != NULL) {
-                    if (num_written != 0) {
-                        num_written += snprintf(buffer + num_written,
-                                                buffer_size - num_written, "|");
-                    }
-                    num_written += snprintf(buffer + num_written, buffer_size - num_written,
-                                            "%s", format_str);
-                }
-            }
-            bit_mask <<= 1;
-            table_index++;
-        }
+    if (profile->card < 0 || profile->device < 0) {
+        return strdup("");
     }
 
-    return strdup(buffer);
-}
+    struct str_parms *query = str_parms_create_str(keys);
+    struct str_parms *result = str_parms_create();
 
-/*
- * 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 */
-};
-
-/*
- * Returns true if mask indicates support for PCM_16.
- */
-static bool mask_has_pcm_16(struct pcm_mask* mask) {
-    return (mask->bits[0] & 0x0004) != 0;
-}
-
-static 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++) {
-            if ((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++;
-        }
+    /* These keys are from hardware/libhardware/include/audio.h */
+    /* supported sample rates */
+    if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
+        char* rates_list = profile_get_sample_rate_strs(profile);
+        str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
+                          rates_list);
+        free(rates_list);
     }
 
-    return AUDIO_FORMAT_INVALID;
-}
-
-/*
- * Maps from bit position in pcm_mask to PCM_ format constants.
- */
-static int8_t const pcm_format_value_map[] = {
-    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.
- */
-static int get_pcm_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 = 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) {
-                /* TODO - we don't want a low-level function to be making this decision */
-                if (table_index != 0) { /* Don't pick 8-bit */
-                    /* just return the first one */
-                    return (int)pcm_format_value_map[table_index];
-                }
-            }
-            bit_mask <<= 1;
-            table_index++;
-        }
+    /* supported channel counts */
+    if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
+        char* channels_list = profile_get_channel_count_strs(profile);
+        str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_CHANNELS,
+                          channels_list);
+        free(channels_list);
     }
 
-    return PCM_FORMAT_INVALID;
-}
-
-static bool test_out_sample_rate(struct audio_device_profile* dev_profile, unsigned rate) {
-    struct pcm_config local_config = cached_output_hardware_config;
-    local_config.rate = rate;
-
-    bool works = false; /* let's be pessimistic */
-    struct pcm * pcm =
-        pcm_open(dev_profile->card, dev_profile->device, dev_profile->direction, &local_config);
-
-    if (pcm != NULL) {
-        works = pcm_is_ready(pcm);
-        pcm_close(pcm);
+    /* supported sample formats */
+    if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
+        char * format_params = profile_get_format_strs(profile);
+        str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS,
+                          format_params);
+        free(format_params);
     }
+    str_parms_destroy(query);
 
-    return works;
-}
+    char* result_str = str_parms_to_str(result);
+    str_parms_destroy(result);
 
-/* sort these highest -> lowest */
-static const unsigned std_sample_rates[] =
-    {48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
+    ALOGV("usb:audio_hw::device_get_parameters = %s", result_str);
 
-static char* enum_std_sample_rates(struct audio_device_profile* dev_profile,
-                                   unsigned min, unsigned max)
-{
-    char buffer[128];
-    buffer[0] = '\0';
-    int buffSize = ARRAY_SIZE(buffer);
-
-    char numBuffer[32];
-
-    int numEntries = 0;
-    unsigned index;
-    for(index = 0; index < ARRAY_SIZE(std_sample_rates); index++) {
-        if (std_sample_rates[index] >= min && std_sample_rates[index] <= max &&
-            test_out_sample_rate(dev_profile, std_sample_rates[index])) {
-            if (numEntries++ != 0) {
-                strncat(buffer, "|", buffSize);
-            }
-            snprintf(numBuffer, sizeof(numBuffer), "%u", std_sample_rates[index]);
-            strncat(buffer, numBuffer, buffSize);
-        }
-    }
-
-    return strdup(buffer);
-}
-
-/*
- * Logging
- */
-static void log_pcm_mask(const char* mask_name, struct pcm_mask* mask) {
-    char buff[512];
-    char bit_buff[32];
-    int buffSize = sizeof(buff)/sizeof(buff[0]);
-
-    buff[0] = '\0';
-
-    int num_slots = sizeof(mask->bits) / sizeof(mask->bits[0]);
-    int bits_per_slot = sizeof(mask->bits[0]) * 8;
-
-    int 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("usb:audio_hw - %s mask:%s", mask_name, buff);
-}
-
-static 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));
-}
-
-/*
- * 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) & 0xFFFFFFF0;
-}
-
-/*TODO - Evaluate if this value should/can be retrieved from a device-specific property */
-#define MIN_BUFF_TIME   5   /* milliseconds */
-
-/*
- * Returns the system defined minimum period size based on the supplied sample rate
- */
-static unsigned int calc_min_period_size(unsigned int sample_rate) {
-    unsigned int period_size = (sample_rate * MIN_BUFF_TIME) / 1000;
-    return round_to_16_mult(period_size);
-}
-
-/*
- * Reads and decodes configuration info from the specified ALSA card/device
- */
-static int read_alsa_device_config(struct audio_device_profile * dev_profile,
-                                   struct pcm_config * config)
-{
-    ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)",
-          dev_profile->card, dev_profile->device, dev_profile->direction);
-
-    if (dev_profile->card < 0 || dev_profile->device < 0) {
-        return -EINVAL;
-    }
-
-    struct pcm_params * alsa_hw_params =
-        pcm_params_get(dev_profile->card, dev_profile->device, dev_profile->direction);
-    if (alsa_hw_params == NULL) {
-        return -EINVAL;
-    }
-
-    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 = pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_SIZE);
-    /* round this up to a multiple of 16 */
-    config->period_size = round_to_16_mult(config->period_size);
-    /* make sure it is above a minimum value to minimize jitter */
-    unsigned int min_period_size = calc_min_period_size(config->rate);
-    if (config->period_size < min_period_size) {
-        config->period_size = min_period_size;
-    }
-    config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
-
-    int format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
-    if (format == PCM_FORMAT_INVALID) {
-        ret = -EINVAL;
-    } else {
-        config->format = format;
-    }
-
-    pcm_params_free(alsa_hw_params);
-    return ret;
+    return result_str;
 }
 
 /*
@@ -695,10 +233,14 @@
  * following order: hw device > out stream
  */
 
-/* Helper functions */
+/*
+ * OUT functions
+ */
 static uint32_t out_get_sample_rate(const struct audio_stream *stream)
 {
-    return cached_output_hardware_config.rate;
+    uint32_t rate = proxy_get_sample_rate(&((struct stream_out*)stream)->proxy);
+    ALOGV("out_get_sample_rate() = %d", rate);
+    return rate;
 }
 
 static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
@@ -708,26 +250,33 @@
 
 static size_t out_get_buffer_size(const struct audio_stream *stream)
 {
-    return cached_output_hardware_config.period_size *
-                audio_stream_out_frame_size((const struct audio_stream_out *)stream);
+    const struct stream_out* out = (const struct stream_out*)stream;
+    size_t buffer_size =
+        proxy_get_period_size(&out->proxy) * audio_stream_out_frame_size(&(out->stream));
+    ALOGV("out_get_buffer_size()  = %zu", buffer_size);
+    return buffer_size;
 }
 
 static uint32_t out_get_channels(const struct audio_stream *stream)
 {
-    // Always Stero for now. We will do *some* conversions in this HAL.
-    /* TODO When AudioPolicyManager & AudioFlinger supports arbitrary channels
-       rewrite this to return the ACTUAL channel format */
-    return AUDIO_CHANNEL_OUT_STEREO;
+    const struct stream_out *out = (const struct stream_out*)stream;
+    return audio_channel_out_mask_from_count(out->hal_channel_count);
 }
 
 static audio_format_t out_get_format(const struct audio_stream *stream)
 {
-    return audio_format_from_pcm_format(cached_output_hardware_config.format);
+    /* Note: The HAL doesn't do any FORMAT conversion at this time. It
+     * Relies on the framework to provide data in the specified format.
+     * This could change in the future.
+     */
+    alsa_device_proxy * proxy = &((struct stream_out*)stream)->proxy;
+    audio_format_t format = audio_format_from_pcm_format(proxy_get_format(proxy));
+    ALOGV("out_get_format() = %d", format);
+    return format;
 }
 
 static int out_set_format(struct audio_stream *stream, audio_format_t format)
 {
-    cached_output_hardware_config.format = pcm_format_from_audio_format(format);
     return 0;
 }
 
@@ -739,8 +288,7 @@
     pthread_mutex_lock(&out->lock);
 
     if (!out->standby) {
-        pcm_close(out->pcm);
-        out->pcm = NULL;
+        proxy_close(&out->proxy);
         out->standby = true;
     }
 
@@ -760,34 +308,43 @@
     ALOGV("usb:audio_hw::out out_set_parameters() keys:%s", kvpairs);
 
     struct stream_out *out = (struct stream_out *)stream;
-    struct str_parms *parms;
+
     char value[32];
     int param_val;
     int routing = 0;
     int ret_value = 0;
+    int card = -1;
+    int device = -1;
 
-    parms = str_parms_create_str(kvpairs);
+    struct str_parms * parms = str_parms_create_str(kvpairs);
     pthread_mutex_lock(&out->dev->lock);
     pthread_mutex_lock(&out->lock);
 
-    bool recache_device_params = false;
     param_val = str_parms_get_str(parms, "card", value, sizeof(value));
-    if (param_val >= 0) {
-        out->profile->card = atoi(value);
-        recache_device_params = true;
-    }
+    if (param_val >= 0)
+        card = atoi(value);
 
     param_val = str_parms_get_str(parms, "device", value, sizeof(value));
-    if (param_val >= 0) {
-        out->profile->device = atoi(value);
-        recache_device_params = true;
-    }
+    if (param_val >= 0)
+        device = atoi(value);
 
-    if (recache_device_params && out->profile->card >= 0 && out->profile->device >= 0) {
-        ret_value = read_alsa_device_config(out->profile, &cached_output_hardware_config);
-        output_hardware_config_is_cached = (ret_value == 0);
+    if ((card >= 0) && (card != out->profile->card) &&
+            (device >= 0) && (device != out->profile->device)) {
+        /* cannot read pcm device info if playback is active */
+        if (!out->standby)
+            ret_value = -ENOSYS;
+        else {
+            int saved_card = out->profile->card;
+            int saved_device = out->profile->device;
+            out->profile->card = card;
+            out->profile->device = device;
+            ret_value = profile_read_device_info(out->profile) ? 0 : -EINVAL;
+            if (ret_value != 0) {
+                out->profile->card = saved_card;
+                out->profile->device = saved_device;
+            }
+        }
     }
-
     pthread_mutex_unlock(&out->lock);
     pthread_mutex_unlock(&out->dev->lock);
     str_parms_destroy(parms);
@@ -795,78 +352,9 @@
     return ret_value;
 }
 
-static char * device_get_parameters(struct audio_device_profile * dev_profile, const char *keys)
-{
-    ALOGV("usb:audio_hw::device_get_parameters() keys:%s", keys);
-
-    if (dev_profile->card < 0 || dev_profile->device < 0) {
-        return strdup("");
-    }
-
-    unsigned min, max;
-
-    struct str_parms *query = str_parms_create_str(keys);
-    struct str_parms *result = str_parms_create();
-
-    int num_written = 0;
-    char buffer[256];
-    int buffer_size = sizeof(buffer) / sizeof(buffer[0]);
-    char* result_str = NULL;
-
-    struct pcm_params * alsa_hw_params =
-        pcm_params_get(dev_profile->card, dev_profile->device, dev_profile->direction);
-
-    // These keys are from hardware/libhardware/include/audio.h
-    // supported sample rates
-    if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
-        min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
-        max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE);
-
-        char* rates_list = enum_std_sample_rates(dev_profile, min, max);
-        str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, rates_list);
-        free(rates_list);
-    }  // AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES
-
-    // supported channel counts
-    if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
-        // TODO remove this hack when it is superceeded by proper multi-channel support
-        str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_CHANNELS,
-                          dev_profile->direction == PCM_OUT
-                                          ? "AUDIO_CHANNEL_OUT_STEREO"
-                                          : "AUDIO_CHANNEL_IN_STEREO");
-    }  // AUDIO_PARAMETER_STREAM_SUP_CHANNELS
-
-    // supported sample formats
-    if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
-        // TODO remove this hack when we have support for input in non PCM16 formats
-        if (dev_profile->direction == PCM_IN) {
-            str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, "AUDIO_FORMAT_PCM_16_BIT");
-        } else {
-            struct pcm_mask * format_mask = pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT);
-            char * format_params = get_format_str_for_mask(format_mask);
-            str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, format_params);
-            free(format_params);
-        }
-    }  // AUDIO_PARAMETER_STREAM_SUP_FORMATS
-
-    pcm_params_free(alsa_hw_params);
-
-    result_str = str_parms_to_str(result);
-
-    // done with these...
-    str_parms_destroy(query);
-    str_parms_destroy(result);
-
-    ALOGV("usb:audio_hw::device_get_parameters = %s", result_str);
-
-    return result_str;
-}
-
 static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
 {
-    ALOGV("usb:audio_hw::out out_get_parameters() keys:%s", keys);
-
-    struct stream_out *out = (struct stream_out *) stream;
+    struct stream_out *out = (struct stream_out *)stream;
     pthread_mutex_lock(&out->dev->lock);
     pthread_mutex_lock(&out->lock);
 
@@ -880,13 +368,8 @@
 
 static uint32_t out_get_latency(const struct audio_stream_out *stream)
 {
-    // struct stream_out *out = (struct stream_out *) stream;
-
-    /*TODO Do we need a term here for the USB latency (as reported in the USB descriptors)? */
-    uint32_t latency = (cached_output_hardware_config.period_size
-                    * cached_output_hardware_config.period_count * 1000)
-                    / out_get_sample_rate(&stream->common);
-    return latency;
+    alsa_device_proxy * proxy = &((struct stream_out*)stream)->proxy;
+    return proxy_get_latency(proxy);
 }
 
 static int out_set_volume(struct audio_stream_out *stream, float left, float right)
@@ -897,25 +380,10 @@
 /* must be called with hw device and output stream mutexes locked */
 static int start_output_stream(struct stream_out *out)
 {
-    int return_val = 0;
-
     ALOGV("usb:audio_hw::out start_output_stream(card:%d device:%d)",
           out->profile->card, out->profile->device);
 
-    out->pcm = pcm_open(out->profile->card, out->profile->device, PCM_OUT,
-                        &cached_output_hardware_config);
-
-    if (out->pcm == NULL) {
-        return -ENOMEM;
-    }
-
-    if (out->pcm && !pcm_is_ready(out->pcm)) {
-        ALOGE("audio_hw audio_hw pcm_open() failed: %s", pcm_get_error(out->pcm));
-        pcm_close(out->pcm);
-        return -ENOMEM;
-    }
-
-    return 0;
+    return proxy_open(&out->proxy);
 }
 
 static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes)
@@ -928,53 +396,48 @@
     if (out->standby) {
         ret = start_output_stream(out);
         if (ret != 0) {
+            pthread_mutex_unlock(&out->dev->lock);
             goto err;
         }
         out->standby = false;
     }
+    pthread_mutex_unlock(&out->dev->lock);
 
-    // Setup conversion buffer
-    // compute maximum potential buffer size.
-    // * 2 for stereo -> quad conversion
-    // * 3/2 for 16bit -> 24 bit conversion
-    size_t required_conversion_buffer_size = (bytes * 3 * 2) / 2;
-    if (required_conversion_buffer_size > out->conversion_buffer_size) {
-        /* TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats
-           (and do these conversions themselves) */
-        out->conversion_buffer_size = required_conversion_buffer_size;
-        out->conversion_buffer = realloc(out->conversion_buffer, out->conversion_buffer_size);
-    }
 
+    alsa_device_proxy* proxy = &out->proxy;
     const void * write_buff = buffer;
     int num_write_buff_bytes = bytes;
-
-    /*
-     * Num Channels conversion
-     */
-    int num_device_channels = cached_output_hardware_config.channels;
-    int num_req_channels = 2; /* always, for now */
+    const int num_device_channels = proxy_get_channel_count(proxy); /* what we told alsa */
+    const int num_req_channels = out->hal_channel_count; /* what we told AudioFlinger */
     if (num_device_channels != num_req_channels) {
-        audio_format_t audio_format = out_get_format(&(out->stream.common));
-        unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
+        /* allocate buffer */
+        const size_t required_conversion_buffer_size =
+                 bytes * num_device_channels / num_req_channels;
+        if (required_conversion_buffer_size > out->conversion_buffer_size) {
+            out->conversion_buffer_size = required_conversion_buffer_size;
+            out->conversion_buffer = realloc(out->conversion_buffer,
+                                             out->conversion_buffer_size);
+        }
+        /* convert data */
+        const audio_format_t audio_format = out_get_format(&(out->stream.common));
+        const unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
         num_write_buff_bytes =
-             adjust_channels(write_buff, num_req_channels,
-                             out->conversion_buffer, num_device_channels,
-                             sample_size_in_bytes, num_write_buff_bytes);
+                adjust_channels(write_buff, num_req_channels,
+                                out->conversion_buffer, num_device_channels,
+                                sample_size_in_bytes, num_write_buff_bytes);
         write_buff = out->conversion_buffer;
     }
 
     if (write_buff != NULL && num_write_buff_bytes != 0) {
-        pcm_write(out->pcm, write_buff, num_write_buff_bytes);
+        proxy_write(&out->proxy, write_buff, num_write_buff_bytes);
     }
 
     pthread_mutex_unlock(&out->lock);
-    pthread_mutex_unlock(&out->dev->lock);
 
     return bytes;
 
 err:
     pthread_mutex_unlock(&out->lock);
-    pthread_mutex_unlock(&out->dev->lock);
     if (ret != 0) {
         usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
                out_get_sample_rate(&stream->common));
@@ -988,6 +451,13 @@
     return -EINVAL;
 }
 
+static int out_get_presentation_position(const struct audio_stream_out *stream,
+                                         uint64_t *frames, struct timespec *timestamp)
+{
+    /* FIXME - This needs to be implemented */
+    return -EINVAL;
+}
+
 static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
 {
     return 0;
@@ -1008,7 +478,8 @@
                                    audio_devices_t devices,
                                    audio_output_flags_t flags,
                                    struct audio_config *config,
-                                   struct audio_stream_out **stream_out)
+                                   struct audio_stream_out **stream_out,
+                                   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);
@@ -1021,7 +492,7 @@
     if (!out)
         return -ENOMEM;
 
-    // setup function pointers
+    /* setup function pointers */
     out->stream.common.get_sample_rate = out_get_sample_rate;
     out->stream.common.set_sample_rate = out_set_sample_rate;
     out->stream.common.get_buffer_size = out_get_buffer_size;
@@ -1038,41 +509,70 @@
     out->stream.set_volume = out_set_volume;
     out->stream.write = out_write;
     out->stream.get_render_position = out_get_render_position;
+    out->stream.get_presentation_position = out_get_presentation_position;
     out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
 
     out->dev = adev;
 
-    out->profile = &(adev->out_profile);
-    out->profile->direction = PCM_OUT;
+    out->profile = &adev->out_profile;
 
-    if (output_hardware_config_is_cached) {
-        config->sample_rate = cached_output_hardware_config.rate;
+    // build this to hand to the alsa_device_proxy
+    struct pcm_config proxy_config;
 
-        config->format = audio_format_from_pcm_format(cached_output_hardware_config.format);
+    int ret = 0;
 
-        config->channel_mask =
-                audio_channel_out_mask_from_count(cached_output_hardware_config.channels);
-        if (config->channel_mask != AUDIO_CHANNEL_OUT_STEREO) {
-            // Always report STEREO for now.  AudioPolicyManagerBase/AudioFlinger dont' understand
-            // formats with more channels, so we won't get chosen (say with a 4-channel DAC).
-            /*TODO remove this when the above restriction is removed. */
-            config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
-        }
+    /* Rate */
+    if (config->sample_rate == 0) {
+        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile);
+    } else if (profile_is_sample_rate_valid(out->profile, config->sample_rate)) {
+        proxy_config.rate = config->sample_rate;
     } else {
-        cached_output_hardware_config = default_alsa_out_config;
-
-        config->format = out_get_format(&out->stream.common);
-        config->channel_mask = out_get_channels(&out->stream.common);
-        config->sample_rate = out_get_sample_rate(&out->stream.common);
+        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile);
+        ret = -EINVAL;
     }
 
+    /* Format */
+    if (config->format == AUDIO_FORMAT_DEFAULT) {
+        proxy_config.format = profile_get_default_format(out->profile);
+        config->format = audio_format_from_pcm_format(proxy_config.format);
+    } else {
+        enum pcm_format fmt = pcm_format_from_audio_format(config->format);
+        if (profile_is_format_valid(out->profile, fmt)) {
+            proxy_config.format = fmt;
+        } else {
+            proxy_config.format = profile_get_default_format(out->profile);
+            config->format = audio_format_from_pcm_format(proxy_config.format);
+            ret = -EINVAL;
+        }
+    }
+
+    /* Channels */
+    unsigned proposed_channel_count = profile_get_default_channel_count(out->profile);
+    if (k_force_channels) {
+        proposed_channel_count = k_force_channels;
+    } else if (config->channel_mask != AUDIO_CHANNEL_NONE) {
+        proposed_channel_count = audio_channel_count_from_out_mask(config->channel_mask);
+    }
+    /* we can expose any channel count mask, and emulate internally. */
+    config->channel_mask = audio_channel_out_mask_from_count(proposed_channel_count);
+    out->hal_channel_count = proposed_channel_count;
+    /* no validity checks are needed as proxy_prepare() forces channel_count to be valid.
+     * and we emulate any channel count discrepancies in out_write(). */
+    proxy_config.channels = proposed_channel_count;
+
+    proxy_prepare(&out->proxy, out->profile, &proxy_config);
+
+    /* TODO The retry mechanism isn't implemented in AudioPolicyManager/AudioFlinger. */
+    ret = 0;
+
     out->conversion_buffer = NULL;
     out->conversion_buffer_size = 0;
 
     out->standby = true;
 
     *stream_out = &out->stream;
-    return 0;
+
+    return ret;
 
 err_open:
     free(out);
@@ -1086,16 +586,416 @@
     ALOGV("usb:audio_hw::out adev_close_output_stream()");
     struct stream_out *out = (struct stream_out *)stream;
 
-    // Close the pcm device
+    /* Close the pcm device */
     out_standby(&stream->common);
 
     free(out->conversion_buffer);
+
     out->conversion_buffer = NULL;
     out->conversion_buffer_size = 0;
 
     free(stream);
 }
 
+static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
+                                         const struct audio_config *config)
+{
+    /* TODO This needs to be calculated based on format/channels/rate */
+    return 320;
+}
+
+/*
+ * IN functions
+ */
+static uint32_t in_get_sample_rate(const struct audio_stream *stream)
+{
+    uint32_t rate = proxy_get_sample_rate(&((const struct stream_in *)stream)->proxy);
+    ALOGV("in_get_sample_rate() = %d", rate);
+    return rate;
+}
+
+static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
+{
+    ALOGV("in_set_sample_rate(%d) - NOPE", rate);
+    return -ENOSYS;
+}
+
+static size_t in_get_buffer_size(const struct audio_stream *stream)
+{
+    const struct stream_in * in = ((const struct stream_in*)stream);
+    size_t buffer_size =
+        proxy_get_period_size(&in->proxy) * audio_stream_in_frame_size(&(in->stream));
+    ALOGV("in_get_buffer_size() = %zd", buffer_size);
+
+    return buffer_size;
+}
+
+static uint32_t in_get_channels(const struct audio_stream *stream)
+{
+    /* TODO Here is the code we need when we support arbitrary channel counts
+     * alsa_device_proxy * proxy = ((struct stream_in*)stream)->proxy;
+     * unsigned channel_count = proxy_get_channel_count(proxy);
+     * uint32_t channel_mask = audio_channel_in_mask_from_count(channel_count);
+     * ALOGV("in_get_channels() = 0x%X count:%d", channel_mask, channel_count);
+     * return channel_mask;
+     */
+    /* TODO When AudioPolicyManager & AudioFlinger supports arbitrary channels
+     rewrite this to return the ACTUAL channel format */
+    return AUDIO_CHANNEL_IN_STEREO;
+}
+
+static audio_format_t in_get_format(const struct audio_stream *stream)
+{
+    /* TODO Here is the code we need when we support arbitrary input formats
+     * alsa_device_proxy * proxy = ((struct stream_in*)stream)->proxy;
+     * audio_format_t format = audio_format_from_pcm_format(proxy_get_format(proxy));
+     * ALOGV("in_get_format() = %d", format);
+     * return format;
+     */
+    /* Input only supports PCM16 */
+    /* TODO When AudioPolicyManager & AudioFlinger supports arbitrary input formats
+       rewrite this to return the ACTUAL channel format (above) */
+    return AUDIO_FORMAT_PCM_16_BIT;
+}
+
+static int in_set_format(struct audio_stream *stream, audio_format_t format)
+{
+    ALOGV("in_set_format(%d) - NOPE", format);
+
+    return -ENOSYS;
+}
+
+static int in_standby(struct audio_stream *stream)
+{
+    struct stream_in *in = (struct stream_in *)stream;
+
+    pthread_mutex_lock(&in->dev->lock);
+    pthread_mutex_lock(&in->lock);
+
+    if (!in->standby) {
+        proxy_close(&in->proxy);
+        in->standby = true;
+    }
+
+    pthread_mutex_unlock(&in->lock);
+    pthread_mutex_unlock(&in->dev->lock);
+
+    return 0;
+}
+
+static int in_dump(const struct audio_stream *stream, int fd)
+{
+    return 0;
+}
+
+static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
+{
+    ALOGV("usb: audio_hw::in in_set_parameters() keys:%s", kvpairs);
+
+    struct stream_in *in = (struct stream_in *)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(&in->dev->lock);
+    pthread_mutex_lock(&in->lock);
+
+    /* Card/Device */
+    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);
+
+    if ((card >= 0) && (card != in->profile->card) &&
+            (device >= 0) && (device != in->profile->device)) {
+        /* cannot read pcm device info if playback is active */
+        if (!in->standby)
+            ret_value = -ENOSYS;
+        else {
+            int saved_card = in->profile->card;
+            int saved_device = in->profile->device;
+            in->profile->card = card;
+            in->profile->device = device;
+            ret_value = profile_read_device_info(in->profile) ? 0 : -EINVAL;
+            if (ret_value != 0) {
+                in->profile->card = saved_card;
+                in->profile->device = saved_device;
+            }
+        }
+     }
+
+    pthread_mutex_unlock(&in->lock);
+    pthread_mutex_unlock(&in->dev->lock);
+
+    str_parms_destroy(parms);
+
+    return ret_value;
+}
+
+static char * in_get_parameters(const struct audio_stream *stream, const char *keys)
+{
+    struct stream_in *in = (struct stream_in *)stream;
+
+    pthread_mutex_lock(&in->dev->lock);
+    pthread_mutex_lock(&in->lock);
+
+    char * params_str =  device_get_parameters(in->profile, keys);
+
+    pthread_mutex_unlock(&in->lock);
+    pthread_mutex_unlock(&in->dev->lock);
+
+    return params_str;
+}
+
+static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
+{
+    return 0;
+}
+
+static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
+{
+    return 0;
+}
+
+static int in_set_gain(struct audio_stream_in *stream, float gain)
+{
+    return 0;
+}
+
+/* must be called with hw device and output stream mutexes locked */
+static int start_input_stream(struct stream_in *in)
+{
+    ALOGV("usb:audio_hw::start_input_stream(card:%d device:%d)",
+          in->profile->card, in->profile->device);
+
+    return proxy_open(&in->proxy);
+}
+
+/* TODO mutex stuff here (see out_write) */
+static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t bytes)
+{
+    size_t num_read_buff_bytes = 0;
+    void * read_buff = buffer;
+    void * out_buff = buffer;
+
+    struct stream_in * in = (struct stream_in *)stream;
+
+    pthread_mutex_lock(&in->dev->lock);
+    pthread_mutex_lock(&in->lock);
+    if (in->standby) {
+        if (start_input_stream(in) != 0) {
+            pthread_mutex_unlock(&in->dev->lock);
+            goto err;
+        }
+        in->standby = false;
+    }
+    pthread_mutex_unlock(&in->dev->lock);
+
+
+    alsa_device_profile * profile = in->profile;
+
+    /*
+     * OK, we need to figure out how much data to read to be able to output the requested
+     * number of bytes in the HAL format (16-bit, stereo).
+     */
+    num_read_buff_bytes = bytes;
+    int num_device_channels = proxy_get_channel_count(&in->proxy);
+    int num_req_channels = 2; /* always, for now */
+
+    if (num_device_channels != num_req_channels) {
+        num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels;
+    }
+
+    enum pcm_format format = proxy_get_format(&in->proxy);
+    if (format == PCM_FORMAT_S24_3LE) {
+        /* 24-bit USB device */
+        num_read_buff_bytes = (3 * num_read_buff_bytes) / 2;
+    } else if (format == PCM_FORMAT_S32_LE) {
+        /* 32-bit USB device */
+        num_read_buff_bytes = num_read_buff_bytes * 2;
+    }
+
+    /* Setup/Realloc the conversion buffer (if necessary). */
+    if (num_read_buff_bytes != bytes) {
+        if (num_read_buff_bytes > in->conversion_buffer_size) {
+            /*TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats
+              (and do these conversions themselves) */
+            in->conversion_buffer_size = num_read_buff_bytes;
+            in->conversion_buffer = realloc(in->conversion_buffer, in->conversion_buffer_size);
+        }
+        read_buff = in->conversion_buffer;
+    }
+
+    if (proxy_read(&in->proxy, read_buff, num_read_buff_bytes) == 0) {
+        /*
+         * Do any conversions necessary to send the data in the format specified to/by the HAL
+         * (but different from the ALSA format), such as 24bit ->16bit, or 4chan -> 2chan.
+         */
+        if (format != PCM_FORMAT_S16_LE) {
+            /* we need to convert */
+            if (num_device_channels != num_req_channels) {
+                out_buff = read_buff;
+            }
+
+            if (format == PCM_FORMAT_S24_3LE) {
+                num_read_buff_bytes =
+                    convert_24_3_to_16(read_buff, num_read_buff_bytes / 3, out_buff);
+            } else if (format == PCM_FORMAT_S32_LE) {
+                num_read_buff_bytes =
+                    convert_32_to_16(read_buff, num_read_buff_bytes / 4, out_buff);
+            } else {
+                goto err;
+            }
+        }
+
+        if (num_device_channels != num_req_channels) {
+            // ALOGV("chans dev:%d req:%d", num_device_channels, num_req_channels);
+
+            out_buff = buffer;
+            /* Num Channels conversion */
+            if (num_device_channels != num_req_channels) {
+                audio_format_t audio_format = in_get_format(&(in->stream.common));
+                unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
+
+                num_read_buff_bytes =
+                    adjust_channels(read_buff, num_device_channels,
+                                    out_buff, num_req_channels,
+                                    sample_size_in_bytes, num_read_buff_bytes);
+            }
+        }
+    }
+
+err:
+    pthread_mutex_unlock(&in->lock);
+
+    return num_read_buff_bytes;
+}
+
+static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
+{
+    return 0;
+}
+
+static int adev_open_input_stream(struct audio_hw_device *dev,
+                                  audio_io_handle_t handle,
+                                  audio_devices_t devices,
+                                  struct audio_config *config,
+                                  struct audio_stream_in **stream_in,
+                                  audio_input_flags_t flags __unused,
+                                  const char *address __unused,
+                                  audio_source_t source __unused)
+{
+    ALOGV("usb: in adev_open_input_stream() rate:%" PRIu32 ", chanMask:0x%" PRIX32 ", fmt:%" PRIu8,
+          config->sample_rate, config->channel_mask, config->format);
+
+    struct stream_in *in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
+    int ret = 0;
+
+    if (in == NULL)
+        return -ENOMEM;
+
+    /* setup function pointers */
+    in->stream.common.get_sample_rate = in_get_sample_rate;
+    in->stream.common.set_sample_rate = in_set_sample_rate;
+    in->stream.common.get_buffer_size = in_get_buffer_size;
+    in->stream.common.get_channels = in_get_channels;
+    in->stream.common.get_format = in_get_format;
+    in->stream.common.set_format = in_set_format;
+    in->stream.common.standby = in_standby;
+    in->stream.common.dump = in_dump;
+    in->stream.common.set_parameters = in_set_parameters;
+    in->stream.common.get_parameters = in_get_parameters;
+    in->stream.common.add_audio_effect = in_add_audio_effect;
+    in->stream.common.remove_audio_effect = in_remove_audio_effect;
+
+    in->stream.set_gain = in_set_gain;
+    in->stream.read = in_read;
+    in->stream.get_input_frames_lost = in_get_input_frames_lost;
+
+    in->dev = (struct audio_device *)dev;
+
+    in->profile = &in->dev->in_profile;
+
+    struct pcm_config proxy_config;
+
+    /* Rate */
+    if (config->sample_rate == 0) {
+        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(in->profile);
+    } else if (profile_is_sample_rate_valid(in->profile, config->sample_rate)) {
+        proxy_config.rate = config->sample_rate;
+    } else {
+        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(in->profile);
+        ret = -EINVAL;
+    }
+
+    /* Format */
+    /* until the framework supports format conversion, just take what it asks for
+     * i.e. AUDIO_FORMAT_PCM_16_BIT */
+    if (config->format == AUDIO_FORMAT_DEFAULT) {
+        /* just return AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
+         * formats */
+        config->format = AUDIO_FORMAT_PCM_16_BIT;
+        proxy_config.format = PCM_FORMAT_S16_LE;
+    } else if (config->format == AUDIO_FORMAT_PCM_16_BIT) {
+        /* Always accept AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
+         * formats */
+        proxy_config.format = PCM_FORMAT_S16_LE;
+    } else {
+        /* When the framework support other formats, validate here */
+        config->format = AUDIO_FORMAT_PCM_16_BIT;
+        proxy_config.format = PCM_FORMAT_S16_LE;
+        ret = -EINVAL;
+    }
+
+    if (config->channel_mask == AUDIO_CHANNEL_NONE) {
+        /* just return AUDIO_CHANNEL_IN_STEREO until the framework supports other input
+         * formats */
+        config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
+
+    } else if (config->channel_mask != AUDIO_CHANNEL_IN_STEREO) {
+        /* allow only stereo capture for now */
+        config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
+        ret = -EINVAL;
+    }
+    // proxy_config.channels = 0;  /* don't change */
+    proxy_config.channels = profile_get_default_channel_count(in->profile);
+
+    proxy_prepare(&in->proxy, in->profile, &proxy_config);
+
+    in->standby = true;
+
+    in->conversion_buffer = NULL;
+    in->conversion_buffer_size = 0;
+
+    *stream_in = &in->stream;
+
+    return ret;
+}
+
+static void adev_close_input_stream(struct audio_hw_device *dev, struct audio_stream_in *stream)
+{
+    struct stream_in *in = (struct stream_in *)stream;
+
+    /* Close the pcm device */
+    in_standby(&stream->common);
+
+    free(in->conversion_buffer);
+
+    free(stream);
+}
+
+/*
+ * ADEV Functions
+ */
 static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
 {
     return 0;
@@ -1136,375 +1036,6 @@
     return -ENOSYS;
 }
 
-static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
-                                         const struct audio_config *config)
-{
-    return 0;
-}
-
-/* Helper functions */
-static uint32_t in_get_sample_rate(const struct audio_stream *stream)
-{
-    return cached_input_hardware_config.rate;
-}
-
-static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
-{
-    return -ENOSYS;
-}
-
-static size_t in_get_buffer_size(const struct audio_stream *stream)
-{
-    size_t buffer_size = cached_input_hardware_config.period_size *
-                            audio_stream_in_frame_size((const struct audio_stream_in *)stream);
-    ALOGV("usb: in_get_buffer_size() = %zu", buffer_size);
-    return buffer_size;
-}
-
-static uint32_t in_get_channels(const struct audio_stream *stream)
-{
-    // just report stereo for now
-    return AUDIO_CHANNEL_IN_STEREO;
-}
-
-static audio_format_t in_get_format(const struct audio_stream *stream)
-{
-    const struct stream_in * in_stream = (const struct stream_in *)stream;
-
-    ALOGV("in_get_format() = %d -> %d", in_stream->input_framework_format,
-          audio_format_from_pcm_format(in_stream->input_framework_format));
-    /* return audio_format_from_pcm_format(cached_input_hardware_config.format); */
-    return audio_format_from_pcm_format(in_stream->input_framework_format);
-}
-
-static int in_set_format(struct audio_stream *stream, audio_format_t format)
-{
-    return -ENOSYS;
-}
-
-static int in_standby(struct audio_stream *stream)
-{
-    struct stream_in *in = (struct stream_in *) stream;
-
-    pthread_mutex_lock(&in->dev->lock);
-    pthread_mutex_lock(&in->lock);
-
-    if (!in->standby) {
-        pcm_close(in->pcm);
-        in->pcm = NULL;
-        in->standby = true;
-    }
-
-    pthread_mutex_unlock(&in->lock);
-    pthread_mutex_unlock(&in->dev->lock);
-
-    return 0;
-}
-
-static int in_dump(const struct audio_stream *stream, int fd)
-{
-    return 0;
-}
-
-static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
-{
-    ALOGV("usb: audio_hw::in in_set_parameters() keys:%s", kvpairs);
-
-    struct stream_in *in = (struct stream_in *)stream;
-    struct str_parms *parms;
-    char value[32];
-    int param_val;
-    int routing = 0;
-    int ret_value = 0;
-
-    parms = str_parms_create_str(kvpairs);
-    pthread_mutex_lock(&in->dev->lock);
-    pthread_mutex_lock(&in->lock);
-
-    bool recache_device_params = false;
-
-    // Card/Device
-    param_val = str_parms_get_str(parms, "card", value, sizeof(value));
-    if (param_val >= 0) {
-        in->profile->card = atoi(value);
-        recache_device_params = true;
-    }
-
-    param_val = str_parms_get_str(parms, "device", value, sizeof(value));
-    if (param_val >= 0) {
-        in->profile->device = atoi(value);
-        recache_device_params = true;
-    }
-
-    if (recache_device_params && in->profile->card >= 0 && in->profile->device >= 0) {
-        ret_value = read_alsa_device_config(in->profile, &cached_input_hardware_config);
-        input_hardware_config_is_cached = (ret_value == 0);
-    }
-
-    pthread_mutex_unlock(&in->lock);
-    pthread_mutex_unlock(&in->dev->lock);
-    str_parms_destroy(parms);
-
-    return ret_value;
-}
-
-static char * in_get_parameters(const struct audio_stream *stream, const char *keys) {
-    ALOGV("usb:audio_hw::in in_get_parameters() keys:%s", keys);
-
-    struct stream_in *in = (struct stream_in *)stream;
-    pthread_mutex_lock(&in->dev->lock);
-    pthread_mutex_lock(&in->lock);
-
-    char * params_str  = device_get_parameters(in->profile, keys);
-
-    pthread_mutex_unlock(&in->lock);
-    pthread_mutex_unlock(&in->dev->lock);
-
-    return params_str;
-}
-
-static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
-{
-    return 0;
-}
-
-static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
-{
-    return 0;
-}
-
-static int in_set_gain(struct audio_stream_in *stream, float gain)
-{
-    return 0;
-}
-
-/* must be called with hw device and output stream mutexes locked */
-static int start_input_stream(struct stream_in *in) {
-    int return_val = 0;
-
-    ALOGV("usb:audio_hw::start_input_stream(card:%d device:%d)",
-          in->profile->card, in->profile->device);
-
-    in->pcm = pcm_open(in->profile->card, in->profile->device, PCM_IN,
-                       &cached_input_hardware_config);
-    if (in->pcm == NULL) {
-        ALOGE("usb:audio_hw pcm_open() in->pcm == NULL");
-        return -ENOMEM;
-    }
-
-    if (in->pcm && !pcm_is_ready(in->pcm)) {
-        ALOGE("usb:audio_hw audio_hw pcm_open() failed: %s", pcm_get_error(in->pcm));
-        pcm_close(in->pcm);
-        return -ENOMEM;
-    }
-
-    return 0;
-}
-
-/* TODO mutex stuff here (see out_write) */
-static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t bytes)
-{
-    size_t num_read_buff_bytes = 0;
-    void * read_buff = buffer;
-    void * out_buff = buffer;
-
-    struct stream_in * in = (struct stream_in *) stream;
-
-    pthread_mutex_lock(&in->dev->lock);
-    pthread_mutex_lock(&in->lock);
-
-    if (in->standby) {
-        if (start_input_stream(in) != 0) {
-            goto err;
-        }
-        in->standby = false;
-    }
-
-    // OK, we need to figure out how much data to read to be able to output the requested
-    // number of bytes in the HAL format (16-bit, stereo).
-    num_read_buff_bytes = bytes;
-    int num_device_channels = cached_input_hardware_config.channels;
-    int num_req_channels = 2; /* always, for now */
-
-    if (num_device_channels != num_req_channels) {
-        num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels;
-    }
-
-    /* Assume (for now) that in->input_framework_format == PCM_FORMAT_S16_LE */
-    if (cached_input_hardware_config.format == PCM_FORMAT_S24_3LE) {
-        /* 24-bit USB device */
-        num_read_buff_bytes = (3 * num_read_buff_bytes) / 2;
-    } else if (cached_input_hardware_config.format == PCM_FORMAT_S32_LE) {
-        /* 32-bit USB device */
-        num_read_buff_bytes = num_read_buff_bytes * 2;
-    }
-
-    // Setup/Realloc the conversion buffer (if necessary).
-    if (num_read_buff_bytes != bytes) {
-        if (num_read_buff_bytes > in->conversion_buffer_size) {
-            /*TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats
-              (and do these conversions themselves) */
-            in->conversion_buffer_size = num_read_buff_bytes;
-            in->conversion_buffer = realloc(in->conversion_buffer, in->conversion_buffer_size);
-        }
-        read_buff = in->conversion_buffer;
-    }
-
-    if (pcm_read(in->pcm, read_buff, num_read_buff_bytes) == 0) {
-        /*
-         * Do any conversions necessary to send the data in the format specified to/by the HAL
-         * (but different from the ALSA format), such as 24bit ->16bit, or 4chan -> 2chan.
-         */
-        if (cached_input_hardware_config.format != PCM_FORMAT_S16_LE) {
-            // we need to convert
-            if (num_device_channels != num_req_channels) {
-                out_buff = read_buff;
-            }
-
-            if (cached_input_hardware_config.format == PCM_FORMAT_S24_3LE) {
-                num_read_buff_bytes =
-                    convert_24_3_to_16(read_buff, num_read_buff_bytes / 3, out_buff);
-            } else if (cached_input_hardware_config.format == PCM_FORMAT_S32_LE) {
-                num_read_buff_bytes =
-                    convert_32_to_16(read_buff, num_read_buff_bytes / 4, out_buff);
-            }
-            else {
-                goto err;
-            }
-        }
-
-        if (num_device_channels != num_req_channels) {
-            out_buff = buffer;
-            /* Num Channels conversion */
-            if (num_device_channels != num_req_channels) {
-                audio_format_t audio_format = in_get_format(&(in->stream.common));
-                unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
-
-                num_read_buff_bytes =
-                    adjust_channels(read_buff, num_device_channels,
-                                    out_buff, num_req_channels,
-                                    sample_size_in_bytes, num_read_buff_bytes);
-            }
-        }
-    }
-
-err:
-    pthread_mutex_unlock(&in->lock);
-    pthread_mutex_unlock(&in->dev->lock);
-
-    return num_read_buff_bytes;
-}
-
-static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
-{
-    return 0;
-}
-
-static int adev_open_input_stream(struct audio_hw_device *dev,
-                                  audio_io_handle_t handle,
-                                  audio_devices_t devices,
-                                  struct audio_config *config,
-                                  struct audio_stream_in **stream_in,
-                                  audio_input_flags_t flags __unused)
-{
-    ALOGV("usb: in adev_open_input_stream() rate:%" PRIu32 ", chanMask:0x%" PRIX32 ", fmt:%" PRIu8,
-          config->sample_rate, config->channel_mask, config->format);
-
-    struct stream_in *in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
-    int ret = 0;
-
-    if (in == NULL)
-        return -ENOMEM;
-
-    // setup function pointers
-    in->stream.common.get_sample_rate = in_get_sample_rate;
-    in->stream.common.set_sample_rate = in_set_sample_rate;
-    in->stream.common.get_buffer_size = in_get_buffer_size;
-    in->stream.common.get_channels = in_get_channels;
-    in->stream.common.get_format = in_get_format;
-    in->stream.common.set_format = in_set_format;
-    in->stream.common.standby = in_standby;
-    in->stream.common.dump = in_dump;
-    in->stream.common.set_parameters = in_set_parameters;
-    in->stream.common.get_parameters = in_get_parameters;
-    in->stream.common.add_audio_effect = in_add_audio_effect;
-    in->stream.common.remove_audio_effect = in_remove_audio_effect;
-
-    in->stream.set_gain = in_set_gain;
-    in->stream.read = in_read;
-    in->stream.get_input_frames_lost = in_get_input_frames_lost;
-
-    in->input_framework_format = PCM_FORMAT_S16_LE;
-
-    in->dev = (struct audio_device *)dev;
-
-    in->profile = &(in->dev->in_profile);
-    in->profile->direction = PCM_IN;
-
-    if (!input_hardware_config_is_cached) {
-        // just return defaults until we can actually query the device.
-        cached_input_hardware_config = default_alsa_in_config;
-    }
-
-    /* Rate */
-    /* TODO Check that the requested rate is valid for the connected device */
-    if (config->sample_rate == 0) {
-        config->sample_rate = cached_input_hardware_config.rate;
-    } else {
-        cached_input_hardware_config.rate = config->sample_rate;
-    }
-
-    /* Format */
-    /* until the framework supports format conversion, just take what it asks for
-     * i.e. AUDIO_FORMAT_PCM_16_BIT */
-    /* config->format = audio_format_from_pcm_format(cached_input_hardware_config.format); */
-    if (config->format == AUDIO_FORMAT_DEFAULT) {
-        /* just return AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
-         * formats */
-        config->format = AUDIO_FORMAT_PCM_16_BIT;
-    } else if (config->format == AUDIO_FORMAT_PCM_16_BIT) {
-        /* Always accept AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
-         * formats */
-    } else {
-        /* When the framework support other formats, validate here */
-        config->format = AUDIO_FORMAT_PCM_16_BIT;
-        ret = -EINVAL;
-    }
-
-    /* don't change the cached_input_hardware_config, we will open it as what it is and
-     * convert as necessary */
-    if (config->channel_mask == AUDIO_CHANNEL_NONE) {
-        /* just return AUDIO_CHANNEL_IN_STEREO until the framework supports other input
-         * formats */
-        config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
-    } else if (config->channel_mask != AUDIO_CHANNEL_IN_STEREO) {
-        /* allow only stereo capture for now */
-        config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
-        ret = -EINVAL;
-    }
-
-    in->standby = true;
-
-    in->conversion_buffer = NULL;
-    in->conversion_buffer_size = 0;
-
-    *stream_in = &in->stream;
-
-    return ret;
-}
-
-static void adev_close_input_stream(struct audio_hw_device *dev, struct audio_stream_in *stream)
-{
-    struct stream_in *in = (struct stream_in *)stream;
-
-    // Close the pcm device
-    in_standby(&stream->common);
-
-    free(in->conversion_buffer);
-
-    free(stream);
-}
-
 static int adev_dump(const audio_hw_device_t *device, int fd)
 {
     return 0;
@@ -1515,9 +1046,6 @@
     struct audio_device *adev = (struct audio_device *)device;
     free(device);
 
-    output_hardware_config_is_cached = false;
-    input_hardware_config_is_cached = false;
-
     return 0;
 }
 
@@ -1530,9 +1058,12 @@
     if (!adev)
         return -ENOMEM;
 
+    profile_init(&adev->out_profile, PCM_OUT);
+    profile_init(&adev->in_profile, PCM_IN);
+
     adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
     adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
-    adev->hw_device.common.module = (struct hw_module_t *) module;
+    adev->hw_device.common.module = (struct hw_module_t *)module;
     adev->hw_device.common.close = adev_close;
 
     adev->hw_device.init_check = adev_init_check;
diff --git a/modules/usbaudio/format.c b/modules/usbaudio/format.c
new file mode 100644
index 0000000..6aac1d3
--- /dev/null
+++ b/modules/usbaudio/format.c
@@ -0,0 +1,194 @@
+/*
+ * 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
new file mode 100644
index 0000000..e23935e
--- /dev/null
+++ b/modules/usbaudio/format.h
@@ -0,0 +1,27 @@
+/*
+ * 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
new file mode 100644
index 0000000..0a05511
--- /dev/null
+++ b/modules/usbaudio/logging.c
@@ -0,0 +1,129 @@
+/*
+ * 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
new file mode 100644
index 0000000..b5640ed
--- /dev/null
+++ b/modules/usbaudio/logging.h
@@ -0,0 +1,26 @@
+/*
+ * 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/tests/camera2/CameraBurstTests.cpp b/tests/camera2/CameraBurstTests.cpp
index 65ff460..58763de 100644
--- a/tests/camera2/CameraBurstTests.cpp
+++ b/tests/camera2/CameraBurstTests.cpp
@@ -311,7 +311,8 @@
  *   $ setenv CAMERA2_TEST_VARIABLE_BURST_DUMP_FRAMES 1
  *   $ /data/nativetest/camera2_test/camera2_test --gtest_filter="*VariableBurst"
  */
-TEST_F(CameraBurstTest, VariableBurst) {
+// Disable this test for now, as we need cleanup the usage of the deprecated tag quite a bit.
+TEST_F(CameraBurstTest, DISABLED_VariableBurst) {
 
     TEST_EXTENSION_FORKING_INIT;
 
diff --git a/tests/camera2/CameraModuleFixture.h b/tests/camera2/CameraModuleFixture.h
index acf41e1..0bb0e7d 100644
--- a/tests/camera2/CameraModuleFixture.h
+++ b/tests/camera2/CameraModuleFixture.h
@@ -97,6 +97,8 @@
                 *device = new Camera2Device(cameraID);
                 break;
             case CAMERA_DEVICE_API_VERSION_3_0:
+            case CAMERA_DEVICE_API_VERSION_3_1:
+            case CAMERA_DEVICE_API_VERSION_3_2:
                 *device = new Camera3Device(cameraID);
                 break;
             default:
diff --git a/tests/camera2/CameraMultiStreamTests.cpp b/tests/camera2/CameraMultiStreamTests.cpp
index 536b656..066f4ee 100644
--- a/tests/camera2/CameraMultiStreamTests.cpp
+++ b/tests/camera2/CameraMultiStreamTests.cpp
@@ -467,7 +467,8 @@
  *
  * 2. Manual control(gain/exposure) of mutiple burst capture.
  */
-TEST_F(CameraMultiStreamTest, MultiBurst) {
+// Disable this test for now, as we need cleanup the usage of the deprecated tag quite a bit.
+TEST_F(CameraMultiStreamTest, DISABLED_MultiBurst) {
 
     TEST_EXTENSION_FORKING_INIT;
 
diff --git a/tests/hardware/struct-offset.cpp b/tests/hardware/struct-offset.cpp
index 2354408..a7ff797 100644
--- a/tests/hardware/struct-offset.cpp
+++ b/tests/hardware/struct-offset.cpp
@@ -169,7 +169,8 @@
     CHECK_MEMBER_AT(hwc_composer_device_1_t, getDisplayAttributes, 96, 184);
     CHECK_MEMBER_AT(hwc_composer_device_1_t, getActiveConfig, 100, 192);
     CHECK_MEMBER_AT(hwc_composer_device_1_t, setActiveConfig, 104, 200);
-    CHECK_MEMBER_AT(hwc_composer_device_1_t, reserved_proc, 108, 208);
+    CHECK_MEMBER_AT(hwc_composer_device_1_t, setCursorPositionAsync, 108, 208);
+    CHECK_MEMBER_AT(hwc_composer_device_1_t, reserved_proc, 112, 216);
 
     //Types defined in gralloc.h
     CHECK_MEMBER_AT(gralloc_module_t, common, 0, 0);