Merge "Ran update-makefiles.sh"
diff --git a/audio/2.0/IDevice.hal b/audio/2.0/IDevice.hal
index 84e0d28..38bfe21 100644
--- a/audio/2.0/IDevice.hal
+++ b/audio/2.0/IDevice.hal
@@ -180,19 +180,20 @@
 
     /*
      * Gets the HW synchronization source of the device. Calling this method is
-     * equivalent to getting AUDIO_PARAMETER_STREAM_HW_AV_SYNC on the legacy
-     * HAL.
+     * equivalent to getting AUDIO_PARAMETER_HW_AV_SYNC on the legacy HAL.
      *
-     * @return retval operation completion status.
      * @return hwAvSync HW synchronization source
      */
-    getHwAvSync() generates (Result retval, AudioHwSync hwAvSync);
+    getHwAvSync() generates (AudioHwSync hwAvSync);
 
     /*
      * Sets whether the screen is on. Calling this method is equivalent to
      * setting AUDIO_PARAMETER_KEY_SCREEN_STATE on the legacy HAL.
+     *
+     * @param turnedOn whether the screen is turned on.
+     * @return retval operation completion status.
      */
-    setScreenState(bool turnedOn);
+    setScreenState(bool turnedOn) generates (Result retval);
 
     /*
      * Generic method for retrieving vendor-specific parameter values.
diff --git a/audio/2.0/IStream.hal b/audio/2.0/IStream.hal
index 09ba42a..dc43346 100644
--- a/audio/2.0/IStream.hal
+++ b/audio/2.0/IStream.hal
@@ -134,18 +134,20 @@
     /*
      * Applies audio effect to the stream.
      *
-     * @param effect the effect to apply.
+     * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+     *                 the effect to apply.
      * @return retval operation completion status.
      */
-    addEffect(IEffect effect) generates (Result retval);
+    addEffect(uint64_t effectId) generates (Result retval);
 
     /*
      * Stops application of the effect to the stream.
      *
-     * @param effect the effect to apply.
+     * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+     *                 the effect to remove.
      * @return retval operation completion status.
      */
-    removeEffect(IEffect effect) generates (Result retval);
+    removeEffect(uint64_t effectId) generates (Result retval);
 
     /*
      * Put the audio hardware input/output into standby mode.
@@ -158,10 +160,9 @@
     /*
      * Return the set of device(s) which this stream is connected to.
      *
-     * @return retval operation completion status.
      * @return device set of device(s) which this stream is connected to.
      */
-    getDevice() generates (Result retval, AudioDevice device);
+    getDevice() generates (AudioDevice device);
 
     /*
      * Connects the stream to the device.
diff --git a/audio/2.0/IStreamIn.hal b/audio/2.0/IStreamIn.hal
index 049df75..6cf7425 100644
--- a/audio/2.0/IStreamIn.hal
+++ b/audio/2.0/IStreamIn.hal
@@ -61,10 +61,9 @@
      * typically occurs when the user space process is blocked longer than the
      * capacity of audio driver buffers.
      *
-     * @return retval operation completion status.
      * @return framesLost the number of input audio frames lost.
      */
-    getInputFramesLost() generates (Result retval, uint32_t framesLost);
+    getInputFramesLost() generates (uint32_t framesLost);
 
     /**
      * Return a recent count of the number of audio frames received and the
diff --git a/audio/2.0/IStreamOut.hal b/audio/2.0/IStreamOut.hal
index adce538..55a852d 100644
--- a/audio/2.0/IStreamOut.hal
+++ b/audio/2.0/IStreamOut.hal
@@ -142,12 +142,12 @@
      * 'setCallback' has not been called, then 'drain' must block until
      * completion.
      *
-     * If 'type' is 'AUDIO_DRAIN_ALL', the drain completes when all previously
-     * written data has been played.
+     * If 'type' is 'ALL', the drain completes when all previously written data
+     * has been played.
      *
-     * If 'type' is 'AUDIO_DRAIN_EARLY_NOTIFY', the drain completes shortly
-     * before all data for the current track has played to allow time for the
-     * framework to perform a gapless track switch.
+     * If 'type' is 'EARLY_NOTIFY', the drain completes shortly before all data
+     * for the current track has played to allow time for the framework to
+     * perform a gapless track switch.
      *
      * Drain must return immediately on 'stop' and 'flush' calls.
      *
diff --git a/audio/2.0/default/Android.mk b/audio/2.0/default/Android.mk
index a987b41..a5c0383 100644
--- a/audio/2.0/default/Android.mk
+++ b/audio/2.0/default/Android.mk
@@ -17,20 +17,53 @@
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.audio@2.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    Conversions.cpp \
+    Device.cpp \
+    DevicesFactory.cpp \
+    ParametersUtil.cpp \
+    PrimaryDevice.cpp \
+    Stream.cpp \
+    StreamIn.cpp \
+    StreamOut.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libhidl \
+    libhwbinder \
+    libutils \
+    libhardware \
+    liblog \
+    android.hardware.audio@2.0 \
+    android.hardware.audio.common@2.0 \
+    android.hardware.audio.common@2.0-util \
+
+LOCAL_WHOLE_STATIC_LIBRARIES := libmedia_helper
+
+include $(BUILD_SHARED_LIBRARY)
+
+#
+# Service
+#
+
+include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.audio@2.0-service
 LOCAL_INIT_RC := android.hardware.audio@2.0-service.rc
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_SRC_FILES := \
-  service.cpp
+    service.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-  libhidl \
-  liblog \
-  libhwbinder \
-  libutils \
-  libhardware \
-  android.hardware.soundtrigger@2.0 \
-  android.hardware.audio.common@2.0
+    libhidl \
+    liblog \
+    libhwbinder \
+    libutils \
+    libhardware \
+    android.hardware.audio@2.0 \
+    android.hardware.audio.common@2.0 \
+    android.hardware.audio.effect@2.0 \
+    android.hardware.soundtrigger@2.0 \
 
 ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
 LOCAL_MULTILIB := 32
diff --git a/audio/2.0/default/Conversions.cpp b/audio/2.0/default/Conversions.cpp
new file mode 100644
index 0000000..1ba16e1
--- /dev/null
+++ b/audio/2.0/default/Conversions.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#include "Conversions.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+std::string deviceAddressToHal(const DeviceAddress& address) {
+    // HAL assumes that the address is NUL-terminated.
+    char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
+    memset(halAddress, 0, sizeof(halAddress));
+    uint32_t halDevice = static_cast<uint32_t>(address.device);
+    if ((halDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0
+            || (halDevice & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0) {
+        snprintf(halAddress, sizeof(halAddress),
+                "%02X:%02X:%02X:%02X:%02X:%02X",
+                address.address.mac[0], address.address.mac[1], address.address.mac[2],
+                address.address.mac[3], address.address.mac[4], address.address.mac[5]);
+    } else if ((halDevice & AUDIO_DEVICE_OUT_IP) != 0 || (halDevice & AUDIO_DEVICE_IN_IP) != 0) {
+        snprintf(halAddress, sizeof(halAddress),
+                "%d.%d.%d.%d",
+                address.address.ipv4[0], address.address.ipv4[1],
+                address.address.ipv4[2], address.address.ipv4[3]);
+    } else if ((halDevice & AUDIO_DEVICE_OUT_ALL_USB) != 0
+            || (halDevice & AUDIO_DEVICE_IN_ALL_USB) != 0) {
+        snprintf(halAddress, sizeof(halAddress),
+                "card=%d;device=%d",
+                address.address.alsa.card, address.address.alsa.device);
+    } else if ((halDevice & AUDIO_DEVICE_OUT_BUS) != 0 || (halDevice & AUDIO_DEVICE_IN_BUS) != 0) {
+        snprintf(halAddress, sizeof(halAddress),
+                "%s", address.busAddress.c_str());
+    } else if ((halDevice & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) != 0
+            || (halDevice & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0) {
+        snprintf(halAddress, sizeof(halAddress),
+                "%s", address.rSubmixAddress.c_str());
+    }
+    return halAddress;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/Conversions.h b/audio/2.0/default/Conversions.h
new file mode 100644
index 0000000..ebda5c5
--- /dev/null
+++ b/audio/2.0/default/Conversions.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 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_audio_V2_0_Conversions_H_
+#define android_hardware_audio_V2_0_Conversions_H_
+
+#include <string>
+
+#include <android/hardware/audio/2.0/types.h>
+#include <system/audio.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::V2_0::DeviceAddress;
+
+std::string deviceAddressToHal(const DeviceAddress& address);
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_audio_V2_0_Conversions_H_
diff --git a/audio/2.0/default/Device.cpp b/audio/2.0/default/Device.cpp
new file mode 100644
index 0000000..05824c7
--- /dev/null
+++ b/audio/2.0/default/Device.cpp
@@ -0,0 +1,534 @@
+ /*
+ * Copyright (C) 2016 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 "DeviceHAL"
+
+#include <algorithm>
+#include <memory.h>
+#include <string.h>
+
+#include <utils/Log.h>
+
+#include "Conversions.h"
+#include "Device.h"
+#include "StreamIn.h"
+#include "StreamOut.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+Device::Device(audio_hw_device_t* device)
+        : mDevice(device) {
+}
+
+Device::~Device() {
+    int status = audio_hw_device_close(mDevice);
+    ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice, strerror(-status));
+    mDevice = nullptr;
+}
+
+// static
+void Device::audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig) {
+    memset(halConfig, 0, sizeof(audio_config_t));
+    halConfig->sample_rate = config.sampleRateHz;
+    halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
+    halConfig->format = static_cast<audio_format_t>(config.format);
+    audioOffloadInfoToHal(config.offloadInfo, &halConfig->offload_info);
+    halConfig->frame_count = config.frameCount;
+}
+
+// static
+void Device::audioGainConfigFromHal(
+        const struct audio_gain_config& halConfig, AudioGainConfig* config) {
+    config->index = halConfig.index;
+    config->mode = AudioGainMode(halConfig.mode);
+    config->channelMask = AudioChannelMask(halConfig.channel_mask);
+    for (size_t i = 0; i < sizeof(audio_channel_mask_t) * 8; ++i) {
+        config->values[i] = halConfig.values[i];
+    }
+    config->rampDurationMs = halConfig.ramp_duration_ms;
+}
+
+// static
+void Device::audioGainConfigToHal(
+        const AudioGainConfig& config, struct audio_gain_config* halConfig) {
+    halConfig->index = config.index;
+    halConfig->mode = static_cast<audio_gain_mode_t>(config.mode);
+    halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
+    memset(halConfig->values, 0, sizeof(halConfig->values));
+    for (size_t i = 0; i < sizeof(audio_channel_mask_t) * 8; ++i) {
+        halConfig->values[i] = config.values[i];
+    }
+    halConfig->ramp_duration_ms = config.rampDurationMs;
+}
+
+// static
+void Device::audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain) {
+    gain->mode = AudioGainMode(halGain.mode);
+    gain->channelMask = AudioChannelMask(halGain.channel_mask);
+    gain->minValue = halGain.min_value;
+    gain->maxValue = halGain.max_value;
+    gain->defaultValue = halGain.default_value;
+    gain->stepValue = halGain.step_value;
+    gain->minRampMs = halGain.min_ramp_ms;
+    gain->maxRampMs = halGain.max_ramp_ms;
+}
+
+// static
+void Device::audioGainToHal(const AudioGain& gain, struct audio_gain* halGain) {
+    halGain->mode = static_cast<audio_gain_mode_t>(gain.mode);
+    halGain->channel_mask = static_cast<audio_channel_mask_t>(gain.channelMask);
+    halGain->min_value = gain.minValue;
+    halGain->max_value = gain.maxValue;
+    halGain->default_value = gain.defaultValue;
+    halGain->step_value = gain.stepValue;
+    halGain->min_ramp_ms = gain.minRampMs;
+    halGain->max_ramp_ms = gain.maxRampMs;
+}
+
+// static
+void Device::audioOffloadInfoToHal(
+        const AudioOffloadInfo& offload, audio_offload_info_t* halOffload) {
+    *halOffload = AUDIO_INFO_INITIALIZER;
+    halOffload->sample_rate = offload.sampleRateHz;
+    halOffload->channel_mask = static_cast<audio_channel_mask_t>(offload.channelMask);
+    halOffload->stream_type = static_cast<audio_stream_type_t>(offload.streamType);
+    halOffload->bit_rate = offload.bitRatePerSecond;
+    halOffload->duration_us = offload.durationMicroseconds;
+    halOffload->has_video = offload.hasVideo;
+    halOffload->is_streaming = offload.isStreaming;
+}
+
+// static
+void Device::audioPortConfigFromHal(
+        const struct audio_port_config& halConfig, AudioPortConfig* config) {
+    config->id = halConfig.id;
+    config->role = AudioPortRole(halConfig.role);
+    config->type = AudioPortType(halConfig.type);
+    config->configMask = AudioPortConfigMask(halConfig.config_mask);
+    config->sampleRateHz = halConfig.sample_rate;
+    config->channelMask = AudioChannelMask(halConfig.channel_mask);
+    config->format = AudioFormat(halConfig.format);
+    audioGainConfigFromHal(halConfig.gain, &config->gain);
+    switch (halConfig.type) {
+        case AUDIO_PORT_TYPE_NONE: break;
+        case AUDIO_PORT_TYPE_DEVICE: {
+            config->ext.device.hwModule = halConfig.ext.device.hw_module;
+            config->ext.device.type = AudioDevice(halConfig.ext.device.type);
+            memcpy(config->ext.device.address.data(),
+                    halConfig.ext.device.address,
+                    AUDIO_DEVICE_MAX_ADDRESS_LEN);
+            break;
+        }
+        case AUDIO_PORT_TYPE_MIX: {
+            config->ext.mix.hwModule = halConfig.ext.mix.hw_module;
+            config->ext.mix.ioHandle = halConfig.ext.mix.handle;
+            if (halConfig.role == AUDIO_PORT_ROLE_SOURCE) {
+                config->ext.mix.useCase.source = AudioSource(halConfig.ext.mix.usecase.source);
+            } else if (halConfig.role == AUDIO_PORT_ROLE_SINK) {
+                config->ext.mix.useCase.stream = AudioStreamType(halConfig.ext.mix.usecase.stream);
+            }
+            break;
+        }
+        case AUDIO_PORT_TYPE_SESSION: {
+            config->ext.session.session = halConfig.ext.session.session;
+            break;
+        }
+    }
+}
+
+// static
+void Device::audioPortConfigToHal(
+        const AudioPortConfig& config, struct audio_port_config* halConfig) {
+    memset(halConfig, 0, sizeof(audio_port_config));
+    halConfig->id = config.id;
+    halConfig->role = static_cast<audio_port_role_t>(config.role);
+    halConfig->type = static_cast<audio_port_type_t>(config.type);
+    halConfig->config_mask = static_cast<unsigned int>(config.configMask);
+    halConfig->sample_rate = config.sampleRateHz;
+    halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
+    halConfig->format = static_cast<audio_format_t>(config.format);
+    audioGainConfigToHal(config.gain, &halConfig->gain);
+    switch (config.type) {
+        case AudioPortType::NONE: break;
+        case AudioPortType::DEVICE: {
+            halConfig->ext.device.hw_module = config.ext.device.hwModule;
+            halConfig->ext.device.type = static_cast<audio_devices_t>(config.ext.device.type);
+            memcpy(halConfig->ext.device.address,
+                    config.ext.device.address.data(),
+                    AUDIO_DEVICE_MAX_ADDRESS_LEN);
+            break;
+        }
+        case AudioPortType::MIX: {
+            halConfig->ext.mix.hw_module = config.ext.mix.hwModule;
+            halConfig->ext.mix.handle = config.ext.mix.ioHandle;
+            if (config.role == AudioPortRole::SOURCE) {
+                halConfig->ext.mix.usecase.source =
+                        static_cast<audio_source_t>(config.ext.mix.useCase.source);
+            } else if (config.role == AudioPortRole::SINK) {
+                halConfig->ext.mix.usecase.stream =
+                        static_cast<audio_stream_type_t>(config.ext.mix.useCase.stream);
+            }
+            break;
+        }
+        case AudioPortType::SESSION: {
+            halConfig->ext.session.session =
+                    static_cast<audio_session_t>(config.ext.session.session);
+            break;
+        }
+    }
+}
+
+// static
+std::unique_ptr<audio_port_config[]> Device::audioPortConfigsToHal(
+        const hidl_vec<AudioPortConfig>& configs) {
+    std::unique_ptr<audio_port_config[]> halConfigs(new audio_port_config[configs.size()]);
+    for (size_t i = 0; i < configs.size(); ++i) {
+        audioPortConfigToHal(configs[i], &halConfigs[i]);
+    }
+    return halConfigs;
+}
+
+// static
+void Device::audioPortFromHal(const struct audio_port& halPort, AudioPort* port) {
+    port->id = halPort.id;
+    port->role = AudioPortRole(halPort.role);
+    port->type = AudioPortType(halPort.type);
+    port->name.setToExternal(halPort.name, strlen(halPort.name));
+    port->sampleRates.resize(halPort.num_sample_rates);
+    for (size_t i = 0; i < halPort.num_sample_rates; ++i) {
+        port->sampleRates[i] = halPort.sample_rates[i];
+    }
+    port->channelMasks.resize(halPort.num_channel_masks);
+    for (size_t i = 0; i < halPort.num_channel_masks; ++i) {
+        port->channelMasks[i] = AudioChannelMask(halPort.channel_masks[i]);
+    }
+    port->formats.resize(halPort.num_formats);
+    for (size_t i = 0; i < halPort.num_formats; ++i) {
+        port->formats[i] = AudioFormat(halPort.formats[i]);
+    }
+    port->gains.resize(halPort.num_gains);
+    for (size_t i = 0; i < halPort.num_gains; ++i) {
+        audioGainFromHal(halPort.gains[i], &port->gains[i]);
+    }
+    audioPortConfigFromHal(halPort.active_config, &port->activeConfig);
+    switch (halPort.type) {
+        case AUDIO_PORT_TYPE_NONE: break;
+        case AUDIO_PORT_TYPE_DEVICE: {
+            port->ext.device.hwModule = halPort.ext.device.hw_module;
+            port->ext.device.type = AudioDevice(halPort.ext.device.type);
+            memcpy(port->ext.device.address.data(),
+                    halPort.ext.device.address,
+                    AUDIO_DEVICE_MAX_ADDRESS_LEN);
+            break;
+        }
+        case AUDIO_PORT_TYPE_MIX: {
+            port->ext.mix.hwModule = halPort.ext.mix.hw_module;
+            port->ext.mix.ioHandle = halPort.ext.mix.handle;
+            port->ext.mix.latencyClass = AudioMixLatencyClass(halPort.ext.mix.latency_class);
+            break;
+        }
+        case AUDIO_PORT_TYPE_SESSION: {
+            port->ext.session.session = halPort.ext.session.session;
+            break;
+        }
+    }
+}
+
+// static
+void Device::audioPortToHal(const AudioPort& port, struct audio_port* halPort) {
+    memset(halPort, 0, sizeof(audio_port));
+    halPort->id = port.id;
+    halPort->role = static_cast<audio_port_role_t>(port.role);
+    halPort->type = static_cast<audio_port_type_t>(port.type);
+    memcpy(halPort->name,
+            port.name.c_str(),
+            std::min(port.name.size(), static_cast<size_t>(AUDIO_PORT_MAX_NAME_LEN)));
+    halPort->num_sample_rates =
+            std::min(port.sampleRates.size(), static_cast<size_t>(AUDIO_PORT_MAX_SAMPLING_RATES));
+    for (size_t i = 0; i < halPort->num_sample_rates; ++i) {
+        halPort->sample_rates[i] = port.sampleRates[i];
+    }
+    halPort->num_channel_masks =
+            std::min(port.channelMasks.size(), static_cast<size_t>(AUDIO_PORT_MAX_CHANNEL_MASKS));
+    for (size_t i = 0; i < halPort->num_channel_masks; ++i) {
+        halPort->channel_masks[i] = static_cast<audio_channel_mask_t>(port.channelMasks[i]);
+    }
+    halPort->num_formats =
+            std::min(port.formats.size(), static_cast<size_t>(AUDIO_PORT_MAX_FORMATS));
+    for (size_t i = 0; i < halPort->num_formats; ++i) {
+        halPort->formats[i] = static_cast<audio_format_t>(port.formats[i]);
+    }
+    halPort->num_gains = std::min(port.gains.size(), static_cast<size_t>(AUDIO_PORT_MAX_GAINS));
+    for (size_t i = 0; i < halPort->num_gains; ++i) {
+        audioGainToHal(port.gains[i], &halPort->gains[i]);
+    }
+    audioPortConfigToHal(port.activeConfig, &halPort->active_config);
+    switch (port.type) {
+        case AudioPortType::NONE: break;
+        case AudioPortType::DEVICE: {
+            halPort->ext.device.hw_module = port.ext.device.hwModule;
+            halPort->ext.device.type = static_cast<audio_devices_t>(port.ext.device.type);
+            memcpy(halPort->ext.device.address,
+                    port.ext.device.address.data(),
+                    AUDIO_DEVICE_MAX_ADDRESS_LEN);
+            break;
+        }
+        case AudioPortType::MIX: {
+            halPort->ext.mix.hw_module = port.ext.mix.hwModule;
+            halPort->ext.mix.handle = port.ext.mix.ioHandle;
+            halPort->ext.mix.latency_class =
+                    static_cast<audio_mix_latency_class_t>(port.ext.mix.latencyClass);
+            break;
+        }
+        case AudioPortType::SESSION: {
+            halPort->ext.session.session = static_cast<audio_session_t>(port.ext.session.session);
+            break;
+        }
+    }
+}
+
+Result Device::analyzeStatus(const char* funcName, int status) {
+    if (status != 0) {
+        ALOGW("Device %p %s: %s", mDevice, funcName, strerror(-status));
+    }
+    switch (status) {
+        case 0: return Result::OK;
+        case -EINVAL: return Result::INVALID_ARGUMENTS;
+        case -ENODATA: return Result::INVALID_STATE;
+        case -ENODEV: return Result::NOT_INITIALIZED;
+        case -ENOSYS: return Result::NOT_SUPPORTED;
+        default: return Result::INVALID_STATE;
+    }
+}
+
+char* Device::halGetParameters(const char* keys) {
+    return mDevice->get_parameters(mDevice, keys);
+}
+
+int Device::halSetParameters(const char* keysAndValues) {
+    return mDevice->set_parameters(mDevice, keysAndValues);
+}
+
+// Methods from ::android::hardware::audio::V2_0::IDevice follow.
+Return<Result> Device::initCheck()  {
+    return analyzeStatus("init_check", mDevice->init_check(mDevice));
+}
+
+Return<Result> Device::setMasterVolume(float volume)  {
+    Result retval(Result::NOT_SUPPORTED);
+    if (mDevice->set_master_volume != NULL) {
+        retval = analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume));
+    }
+    return retval;
+}
+
+Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb)  {
+    Result retval(Result::NOT_SUPPORTED);
+    float volume = 0;
+    if (mDevice->get_master_volume != NULL) {
+        retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume));
+    }
+    _hidl_cb(retval, volume);
+    return Void();
+}
+
+Return<Result> Device::setMicMute(bool mute)  {
+    return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
+}
+
+Return<void> Device::getMicMute(getMicMute_cb _hidl_cb)  {
+    bool mute = false;
+    Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
+    _hidl_cb(retval, mute);
+    return Void();
+}
+
+Return<Result> Device::setMasterMute(bool mute)  {
+    Result retval(Result::NOT_SUPPORTED);
+    if (mDevice->set_master_mute != NULL) {
+        retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute));
+    }
+    return retval;
+}
+
+Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb)  {
+    Result retval(Result::NOT_SUPPORTED);
+    bool mute = false;
+    if (mDevice->get_master_mute != NULL) {
+        retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute));
+    }
+    _hidl_cb(retval, mute);
+    return Void();
+}
+
+Return<void> Device::getInputBufferSize(
+        const AudioConfig& config, getInputBufferSize_cb _hidl_cb)  {
+    audio_config_t halConfig;
+    audioConfigToHal(config, &halConfig);
+    size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
+    Result retval(Result::INVALID_ARGUMENTS);
+    uint64_t bufferSize = 0;
+    if (halBufferSize != 0) {
+        retval = Result::OK;
+        bufferSize = halBufferSize;
+    }
+    _hidl_cb(retval, bufferSize);
+    return Void();
+}
+
+Return<void> Device::openOutputStream(
+        int32_t ioHandle,
+        const DeviceAddress& device,
+        const AudioConfig& config,
+        AudioOutputFlag flags,
+        openOutputStream_cb _hidl_cb)  {
+    audio_config_t halConfig;
+    audioConfigToHal(config, &halConfig);
+    audio_stream_out_t *halStream;
+    int status = mDevice->open_output_stream(
+            mDevice,
+            ioHandle,
+            static_cast<audio_devices_t>(device.device),
+            static_cast<audio_output_flags_t>(flags),
+            &halConfig,
+            &halStream,
+            deviceAddressToHal(device).c_str());
+    sp<IStreamOut> streamOut;
+    if (status == OK) {
+        streamOut = new StreamOut(mDevice, halStream);
+    }
+    _hidl_cb(analyzeStatus("open_output_stream", status), streamOut);
+    return Void();
+}
+
+Return<void> Device::openInputStream(
+        int32_t ioHandle,
+        const DeviceAddress& device,
+        const AudioConfig& config,
+        AudioInputFlag flags,
+        AudioSource source,
+        openInputStream_cb _hidl_cb)  {
+    audio_config_t halConfig;
+    audioConfigToHal(config, &halConfig);
+    audio_stream_in_t *halStream;
+    int status = mDevice->open_input_stream(
+            mDevice,
+            ioHandle,
+            static_cast<audio_devices_t>(device.device),
+            &halConfig,
+            &halStream,
+            static_cast<audio_input_flags_t>(flags),
+            deviceAddressToHal(device).c_str(),
+            static_cast<audio_source_t>(source));
+    sp<IStreamIn> streamIn;
+    if (status == OK) {
+        streamIn = new StreamIn(mDevice, halStream);
+    }
+    _hidl_cb(analyzeStatus("open_input_stream", status), streamIn);
+    return Void();
+}
+
+Return<void> Device::createAudioPatch(
+        const hidl_vec<AudioPortConfig>& sources,
+        const hidl_vec<AudioPortConfig>& sinks,
+        createAudioPatch_cb _hidl_cb)  {
+    Result retval(Result::NOT_SUPPORTED);
+    AudioPatchHandle patch = 0;
+    if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
+        std::unique_ptr<audio_port_config[]> halSources(audioPortConfigsToHal(sources));
+        std::unique_ptr<audio_port_config[]> halSinks(audioPortConfigsToHal(sinks));
+        audio_patch_handle_t halPatch;
+        retval = analyzeStatus(
+                "create_audio_patch",
+                mDevice->create_audio_patch(
+                        mDevice,
+                        sources.size(), &halSources[0],
+                        sinks.size(), &halSinks[0],
+                        &halPatch));
+        if (retval == Result::OK) {
+            patch = static_cast<AudioPatchHandle>(halPatch);
+        }
+    }
+    _hidl_cb(retval, patch);
+    return Void();
+}
+
+Return<Result> Device::releaseAudioPatch(int32_t patch)  {
+    if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
+        return analyzeStatus(
+                "release_audio_patch",
+                mDevice->release_audio_patch(mDevice, static_cast<audio_patch_handle_t>(patch)));
+    }
+    return Result::NOT_SUPPORTED;
+}
+
+Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb)  {
+    audio_port halPort;
+    audioPortToHal(port, &halPort);
+    Result retval = analyzeStatus("get_audio_port", mDevice->get_audio_port(mDevice, &halPort));
+    AudioPort resultPort = port;
+    if (retval == Result::OK) {
+        audioPortFromHal(halPort, &resultPort);
+    }
+    _hidl_cb(retval, resultPort);
+    return Void();
+}
+
+Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config)  {
+    if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
+        struct audio_port_config halPortConfig;
+        audioPortConfigToHal(config, &halPortConfig);
+        return analyzeStatus(
+                "set_audio_port_config", mDevice->set_audio_port_config(mDevice, &halPortConfig));
+    }
+    return Result::NOT_SUPPORTED;
+}
+
+Return<AudioHwSync> Device::getHwAvSync()  {
+    int halHwAvSync;
+    Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
+    return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID;
+}
+
+Return<Result> Device::setScreenState(bool turnedOn)  {
+    return setParam(AudioParameter::keyScreenState, turnedOn);
+}
+
+Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  {
+    getParametersImpl(keys, _hidl_cb);
+    return Void();
+}
+
+Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& parameters)  {
+    return setParametersImpl(parameters);
+}
+
+Return<void> Device::debugDump(const native_handle_t* fd)  {
+    if (fd->numFds == 1) {
+        analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/Device.h b/audio/2.0/default/Device.h
new file mode 100644
index 0000000..d7b3128
--- /dev/null
+++ b/audio/2.0/default/Device.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2016 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 HIDL_GENERATED_android_hardware_audio_V2_0_Device_H_
+#define HIDL_GENERATED_android_hardware_audio_V2_0_Device_H_
+
+#include <memory>
+
+#include <media/AudioParameter.h>
+#include <hardware/audio.h>
+
+#include <android/hardware/audio/2.0/IDevice.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "ParametersUtil.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioConfig;
+using ::android::hardware::audio::common::V2_0::AudioGain;
+using ::android::hardware::audio::common::V2_0::AudioGainConfig;
+using ::android::hardware::audio::common::V2_0::AudioGainMode;
+using ::android::hardware::audio::common::V2_0::AudioHwSync;
+using ::android::hardware::audio::common::V2_0::AudioInputFlag;
+using ::android::hardware::audio::common::V2_0::AudioMixLatencyClass;
+using ::android::hardware::audio::common::V2_0::AudioOffloadInfo;
+using ::android::hardware::audio::common::V2_0::AudioOutputFlag;
+using ::android::hardware::audio::common::V2_0::AudioPatchHandle;
+using ::android::hardware::audio::common::V2_0::AudioPort;
+using ::android::hardware::audio::common::V2_0::AudioPortConfig;
+using ::android::hardware::audio::common::V2_0::AudioPortConfigMask;
+using ::android::hardware::audio::common::V2_0::AudioPortRole;
+using ::android::hardware::audio::common::V2_0::AudioPortType;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::common::V2_0::AudioStreamType;
+using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::V2_0::IDevice;
+using ::android::hardware::audio::V2_0::IStreamIn;
+using ::android::hardware::audio::V2_0::IStreamOut;
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Device : public IDevice, public ParametersUtil {
+    explicit Device(audio_hw_device_t* device);
+
+    // Methods from ::android::hardware::audio::V2_0::IDevice follow.
+    Return<Result> initCheck()  override;
+    Return<Result> setMasterVolume(float volume)  override;
+    Return<void> getMasterVolume(getMasterVolume_cb _hidl_cb)  override;
+    Return<Result> setMicMute(bool mute)  override;
+    Return<void> getMicMute(getMicMute_cb _hidl_cb)  override;
+    Return<Result> setMasterMute(bool mute)  override;
+    Return<void> getMasterMute(getMasterMute_cb _hidl_cb)  override;
+    Return<void> getInputBufferSize(
+            const AudioConfig& config, getInputBufferSize_cb _hidl_cb)  override;
+    Return<void> openOutputStream(
+            int32_t ioHandle,
+            const DeviceAddress& device,
+            const AudioConfig& config,
+            AudioOutputFlag flags,
+            openOutputStream_cb _hidl_cb)  override;
+    Return<void> openInputStream(
+            int32_t ioHandle,
+            const DeviceAddress& device,
+            const AudioConfig& config,
+            AudioInputFlag flags,
+            AudioSource source,
+            openInputStream_cb _hidl_cb)  override;
+    Return<void> createAudioPatch(
+            const hidl_vec<AudioPortConfig>& sources,
+            const hidl_vec<AudioPortConfig>& sinks,
+            createAudioPatch_cb _hidl_cb)  override;
+    Return<Result> releaseAudioPatch(int32_t patch)  override;
+    Return<void> getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb)  override;
+    Return<Result> setAudioPortConfig(const AudioPortConfig& config)  override;
+    Return<AudioHwSync> getHwAvSync()  override;
+    Return<Result> setScreenState(bool turnedOn)  override;
+    Return<void> getParameters(
+            const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
+    Return<void> debugDump(const native_handle_t* fd)  override;
+
+    // Utility methods for extending interfaces.
+    Result analyzeStatus(const char* funcName, int status);
+    audio_hw_device_t* device() const { return mDevice; }
+
+  private:
+    audio_hw_device_t *mDevice;
+
+    static void audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig);
+    static void audioGainConfigFromHal(
+            const struct audio_gain_config& halConfig, AudioGainConfig* config);
+    static void audioGainConfigToHal(
+            const AudioGainConfig& config, struct audio_gain_config* halConfig);
+    static void audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain);
+    static void audioGainToHal(const AudioGain& gain, struct audio_gain* halGain);
+    static void audioOffloadInfoToHal(
+            const AudioOffloadInfo& offload, audio_offload_info_t* halOffload);
+    static void audioPortConfigFromHal(
+            const struct audio_port_config& halConfig, AudioPortConfig* config);
+    static void audioPortConfigToHal(
+            const AudioPortConfig& config, struct audio_port_config* halConfig);
+    static std::unique_ptr<audio_port_config[]> audioPortConfigsToHal(
+            const hidl_vec<AudioPortConfig>& configs);
+    static void audioPortFromHal(const struct audio_port& halPort, AudioPort* port);
+    static void audioPortToHal(const AudioPort& port, struct audio_port* halPort);
+
+    virtual ~Device();
+
+    // Methods from ParametersUtil.
+    char* halGetParameters(const char* keys) override;
+    int halSetParameters(const char* keysAndValues) override;
+
+    uint32_t version() const { return mDevice->common.version; }
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_audio_V2_0_Device_H_
diff --git a/audio/2.0/default/DevicesFactory.cpp b/audio/2.0/default/DevicesFactory.cpp
new file mode 100644
index 0000000..1e087f2
--- /dev/null
+++ b/audio/2.0/default/DevicesFactory.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 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 "DevicesFactoryHAL"
+
+#include <string.h>
+
+#include <utils/Log.h>
+
+#include "Device.h"
+#include "DevicesFactory.h"
+#include "PrimaryDevice.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+// static
+const char* DevicesFactory::deviceToString(IDevicesFactory::Device device) {
+    switch (device) {
+        case IDevicesFactory::Device::PRIMARY: return AUDIO_HARDWARE_MODULE_ID_PRIMARY;
+        case IDevicesFactory::Device::A2DP: return AUDIO_HARDWARE_MODULE_ID_A2DP;
+        case IDevicesFactory::Device::USB: return AUDIO_HARDWARE_MODULE_ID_USB;
+        case IDevicesFactory::Device::R_SUBMIX: return AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX;
+    }
+}
+
+// static
+int DevicesFactory::loadAudioInterface(const char *if_name, audio_hw_device_t **dev)
+{
+    const hw_module_t *mod;
+    int rc;
+
+    rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
+    if (rc) {
+        ALOGE("%s couldn't load audio hw module %s.%s (%s)", __func__,
+                AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
+        goto out;
+    }
+    rc = audio_hw_device_open(mod, dev);
+    if (rc) {
+        ALOGE("%s couldn't open audio hw device in %s.%s (%s)", __func__,
+                AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
+        goto out;
+    }
+    if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) {
+        ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
+        rc = -EINVAL;
+        audio_hw_device_close(*dev);
+        goto out;
+    }
+    return OK;
+
+out:
+    *dev = NULL;
+    return rc;
+}
+
+// Methods from ::android::hardware::audio::V2_0::IDevicesFactory follow.
+Return<void> DevicesFactory::openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb)  {
+    audio_hw_device_t *halDevice;
+    int halStatus = loadAudioInterface(deviceToString(device), &halDevice);
+    Result retval(Result::OK);
+    sp<IDevice> result;
+    if (halStatus == OK) {
+        if (device == IDevicesFactory::Device::PRIMARY) {
+            result = new PrimaryDevice(halDevice);
+        } else {
+            result = new ::android::hardware::audio::V2_0::implementation::Device(halDevice);
+        }
+    } else if (halStatus == -EINVAL) {
+        retval = Result::NOT_INITIALIZED;
+    } else {
+        retval = Result::INVALID_ARGUMENTS;
+    }
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* /* name */) {
+    return new DevicesFactory();
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/DevicesFactory.h b/audio/2.0/default/DevicesFactory.h
new file mode 100644
index 0000000..0ea9859
--- /dev/null
+++ b/audio/2.0/default/DevicesFactory.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 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 HIDL_GENERATED_android_hardware_audio_V2_0_DevicesFactory_H_
+#define HIDL_GENERATED_android_hardware_audio_V2_0_DevicesFactory_H_
+
+#include <hardware/audio.h>
+
+#include <android/hardware/audio/2.0/IDevicesFactory.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::V2_0::IDevice;
+using ::android::hardware::audio::V2_0::IDevicesFactory;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct DevicesFactory : public IDevicesFactory {
+    // Methods from ::android::hardware::audio::V2_0::IDevicesFactory follow.
+    Return<void> openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb)  override;
+
+  private:
+    static const char* deviceToString(IDevicesFactory::Device device);
+    static int loadAudioInterface(const char *if_name, audio_hw_device_t **dev);
+
+};
+
+extern "C" IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_audio_V2_0_DevicesFactory_H_
diff --git a/audio/2.0/default/ParametersUtil.cpp b/audio/2.0/default/ParametersUtil.cpp
new file mode 100644
index 0000000..75a60b9
--- /dev/null
+++ b/audio/2.0/default/ParametersUtil.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2016 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 "ParametersUtil.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+Result ParametersUtil::getParam(const char* name, bool* value) {
+    String8 halValue;
+    Result retval = getParam(name, &halValue);
+    *value = false;
+    if (retval == Result::OK) {
+        *value = !(halValue == AudioParameter::valueOff);
+    }
+    return retval;
+}
+
+Result ParametersUtil::getParam(const char* name, int* value) {
+    const String8 halName(name);
+    AudioParameter keys;
+    keys.addKey(halName);
+    std::unique_ptr<AudioParameter> params = getParams(keys);
+    status_t halStatus = params->getInt(halName, *value);
+    return halStatus == OK ? Result::OK : Result::INVALID_ARGUMENTS;
+}
+
+Result ParametersUtil::getParam(const char* name, String8* value) {
+    const String8 halName(name);
+    AudioParameter keys;
+    keys.addKey(halName);
+    std::unique_ptr<AudioParameter> params = getParams(keys);
+    status_t halStatus = params->get(halName, *value);
+    return halStatus == OK ? Result::OK : Result::INVALID_ARGUMENTS;
+}
+
+void ParametersUtil::getParametersImpl(
+        const hidl_vec<hidl_string>& keys,
+        std::function<void(Result retval, const hidl_vec<ParameterValue>& parameters)> cb)  {
+    AudioParameter halKeys;
+    for (size_t i = 0; i < keys.size(); ++i) {
+        halKeys.addKey(String8(keys[i].c_str()));
+    }
+    std::unique_ptr<AudioParameter> halValues = getParams(halKeys);
+    Result retval(Result::INVALID_ARGUMENTS);
+    hidl_vec<ParameterValue> result;
+    if (halValues->size() > 0) {
+        result.resize(halValues->size());
+        String8 halKey, halValue;
+        for (size_t i = 0; i < halValues->size(); ++i) {
+            status_t status = halValues->getAt(i, halKey, halValue);
+            if (status != OK) {
+                result.resize(0);
+                break;
+            }
+            result[i].key = halKey.string();
+            result[i].value = halValue.string();
+        }
+        if (result.size() != 0) {
+            retval = Result::OK;
+        }
+    }
+    cb(retval, result);
+}
+
+std::unique_ptr<AudioParameter> ParametersUtil::getParams(const AudioParameter& keys) {
+    String8 paramsAndValues;
+    char *halValues = halGetParameters(keys.keysToString().string());
+    if (halValues != NULL) {
+        paramsAndValues.setTo(halValues);
+        free(halValues);
+    } else {
+        paramsAndValues.clear();
+    }
+    return std::unique_ptr<AudioParameter>(new AudioParameter(paramsAndValues));
+}
+
+Result ParametersUtil::setParam(const char* name, bool value) {
+    AudioParameter param;
+    param.add(String8(name), String8(value ? AudioParameter::valueOn : AudioParameter::valueOff));
+    return setParams(param);
+}
+
+Result ParametersUtil::setParam(const char* name, int value) {
+    AudioParameter param;
+    param.addInt(String8(name), value);
+    return setParams(param);
+}
+
+Result ParametersUtil::setParam(const char* name, const char* value) {
+    AudioParameter param;
+    param.add(String8(name), String8(value));
+    return setParams(param);
+}
+
+Result ParametersUtil::setParametersImpl(const hidl_vec<ParameterValue>& parameters)  {
+    AudioParameter params;
+    for (size_t i = 0; i < parameters.size(); ++i) {
+        params.add(String8(parameters[i].key.c_str()), String8(parameters[i].value.c_str()));
+    }
+    return setParams(params);
+}
+
+Result ParametersUtil::setParams(const AudioParameter& param) {
+    int halStatus = halSetParameters(param.toString().string());
+    if (halStatus == OK)
+        return Result::OK;
+    else if (halStatus == -ENOSYS)
+        return Result::INVALID_STATE;
+    else
+        return Result::INVALID_ARGUMENTS;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/ParametersUtil.h b/audio/2.0/default/ParametersUtil.h
new file mode 100644
index 0000000..49036dc
--- /dev/null
+++ b/audio/2.0/default/ParametersUtil.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 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_audio_V2_0_ParametersUtil_H_
+#define android_hardware_audio_V2_0_ParametersUtil_H_
+
+#include <functional>
+#include <memory>
+
+#include <android/hardware/audio/2.0/types.h>
+#include <hidl/HidlSupport.h>
+#include <media/AudioParameter.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+
+class ParametersUtil {
+  public:
+    Result getParam(const char* name, bool* value);
+    Result getParam(const char* name, int* value);
+    Result getParam(const char* name, String8* value);
+    void getParametersImpl(
+            const hidl_vec<hidl_string>& keys,
+            std::function<void(Result retval, const hidl_vec<ParameterValue>& parameters)> cb);
+    std::unique_ptr<AudioParameter> getParams(const AudioParameter& keys);
+    Result setParam(const char* name, bool value);
+    Result setParam(const char* name, int value);
+    Result setParam(const char* name, const char* value);
+    Result setParametersImpl(const hidl_vec<ParameterValue>& parameters);
+    Result setParams(const AudioParameter& param);
+
+  protected:
+    virtual ~ParametersUtil() {}
+
+    virtual char* halGetParameters(const char* keys) = 0;
+    virtual int halSetParameters(const char* keysAndValues) = 0;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_audio_V2_0_ParametersUtil_H_
diff --git a/audio/2.0/default/PrimaryDevice.cpp b/audio/2.0/default/PrimaryDevice.cpp
new file mode 100644
index 0000000..9f5180c
--- /dev/null
+++ b/audio/2.0/default/PrimaryDevice.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2016 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 "PrimaryDeviceHAL"
+
+#include "PrimaryDevice.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+PrimaryDevice::PrimaryDevice(audio_hw_device_t* device)
+        : mDevice(new Device(device)) {
+}
+
+PrimaryDevice::~PrimaryDevice() {}
+
+// Methods from ::android::hardware::audio::V2_0::IDevice follow.
+Return<Result> PrimaryDevice::initCheck()  {
+    return mDevice->initCheck();
+}
+
+Return<Result> PrimaryDevice::setMasterVolume(float volume)  {
+    return mDevice->setMasterVolume(volume);
+}
+
+Return<void> PrimaryDevice::getMasterVolume(getMasterVolume_cb _hidl_cb)  {
+    return mDevice->getMasterVolume(_hidl_cb);
+}
+
+Return<Result> PrimaryDevice::setMicMute(bool mute)  {
+    return mDevice->setMicMute(mute);
+}
+
+Return<void> PrimaryDevice::getMicMute(getMicMute_cb _hidl_cb)  {
+    return mDevice->getMicMute(_hidl_cb);
+}
+
+Return<Result> PrimaryDevice::setMasterMute(bool mute)  {
+    return mDevice->setMasterMute(mute);
+}
+
+Return<void> PrimaryDevice::getMasterMute(getMasterMute_cb _hidl_cb)  {
+    return mDevice->getMasterMute(_hidl_cb);
+}
+
+Return<void> PrimaryDevice::getInputBufferSize(
+        const AudioConfig& config, getInputBufferSize_cb _hidl_cb)  {
+    return mDevice->getInputBufferSize(config, _hidl_cb);
+}
+
+Return<void> PrimaryDevice::openOutputStream(
+        int32_t ioHandle,
+        const DeviceAddress& device,
+        const AudioConfig& config,
+        AudioOutputFlag flags,
+        openOutputStream_cb _hidl_cb)  {
+    return mDevice->openOutputStream(ioHandle, device, config, flags, _hidl_cb);
+}
+
+Return<void> PrimaryDevice::openInputStream(
+        int32_t ioHandle,
+        const DeviceAddress& device,
+        const AudioConfig& config,
+        AudioInputFlag flags,
+        AudioSource source,
+        openInputStream_cb _hidl_cb)  {
+    return mDevice->openInputStream(ioHandle, device, config, flags, source, _hidl_cb);
+}
+
+Return<void> PrimaryDevice::createAudioPatch(
+        const hidl_vec<AudioPortConfig>& sources,
+        const hidl_vec<AudioPortConfig>& sinks,
+        createAudioPatch_cb _hidl_cb)  {
+    return mDevice->createAudioPatch(sources, sinks, _hidl_cb);
+}
+
+Return<Result> PrimaryDevice::releaseAudioPatch(int32_t patch)  {
+    return mDevice->releaseAudioPatch(patch);
+}
+
+Return<void> PrimaryDevice::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb)  {
+    return mDevice->getAudioPort(port, _hidl_cb);
+}
+
+Return<Result> PrimaryDevice::setAudioPortConfig(const AudioPortConfig& config)  {
+    return mDevice->setAudioPortConfig(config);
+}
+
+Return<AudioHwSync> PrimaryDevice::getHwAvSync()  {
+    return mDevice->getHwAvSync();
+}
+
+Return<Result> PrimaryDevice::setScreenState(bool turnedOn)  {
+    return mDevice->setScreenState(turnedOn);
+}
+
+Return<void> PrimaryDevice::getParameters(
+        const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  {
+    return mDevice->getParameters(keys, _hidl_cb);
+}
+
+Return<Result> PrimaryDevice::setParameters(const hidl_vec<ParameterValue>& parameters)  {
+    return mDevice->setParameters(parameters);
+}
+
+Return<void> PrimaryDevice::debugDump(const native_handle_t* fd)  {
+    return mDevice->debugDump(fd);
+}
+
+
+// Methods from ::android::hardware::audio::V2_0::IPrimaryDevice follow.
+Return<Result> PrimaryDevice::setVoiceVolume(float volume)  {
+    return mDevice->analyzeStatus(
+            "set_voice_volume",
+            mDevice->device()->set_voice_volume(mDevice->device(), volume));
+}
+
+Return<Result> PrimaryDevice::setMode(AudioMode mode)  {
+    return mDevice->analyzeStatus(
+            "set_mode",
+            mDevice->device()->set_mode(mDevice->device(), static_cast<audio_mode_t>(mode)));
+}
+
+Return<void> PrimaryDevice::getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb)  {
+    bool enabled;
+    Result retval = mDevice->getParam(AudioParameter::keyBtNrec, &enabled);
+    _hidl_cb(retval, enabled);
+    return Void();
+}
+
+Return<Result> PrimaryDevice::setBtScoNrecEnabled(bool enabled)  {
+    return mDevice->setParam(AudioParameter::keyBtNrec, enabled);
+}
+
+Return<void> PrimaryDevice::getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb)  {
+    bool enabled;
+    Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_BT_SCO_WB, &enabled);
+    _hidl_cb(retval, enabled);
+    return Void();
+}
+
+Return<Result> PrimaryDevice::setBtScoWidebandEnabled(bool enabled)  {
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_BT_SCO_WB, enabled);
+}
+
+Return<void> PrimaryDevice::getTtyMode(getTtyMode_cb _hidl_cb)  {
+    int halMode;
+    Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_TTY_MODE, &halMode);
+    TtyMode mode = retval == Result::OK ? TtyMode(halMode) : TtyMode::OFF;
+    _hidl_cb(retval, mode);
+    return Void();
+}
+
+Return<Result> PrimaryDevice::setTtyMode(IPrimaryDevice::TtyMode mode)  {
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_TTY_MODE, static_cast<int>(mode));
+}
+
+Return<void> PrimaryDevice::getHacEnabled(getHacEnabled_cb _hidl_cb)  {
+    bool enabled;
+    Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_HAC, &enabled);
+    _hidl_cb(retval, enabled);
+    return Void();
+}
+
+Return<Result> PrimaryDevice::setHacEnabled(bool enabled)  {
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_HAC, enabled);
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/PrimaryDevice.h b/audio/2.0/default/PrimaryDevice.h
new file mode 100644
index 0000000..4c5b590
--- /dev/null
+++ b/audio/2.0/default/PrimaryDevice.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 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 HIDL_GENERATED_android_hardware_audio_V2_0_PrimaryDevice_H_
+#define HIDL_GENERATED_android_hardware_audio_V2_0_PrimaryDevice_H_
+
+#include <android/hardware/audio/2.0/IPrimaryDevice.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Device.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioConfig;
+using ::android::hardware::audio::common::V2_0::AudioInputFlag;
+using ::android::hardware::audio::common::V2_0::AudioMode;
+using ::android::hardware::audio::common::V2_0::AudioOutputFlag;
+using ::android::hardware::audio::common::V2_0::AudioPort;
+using ::android::hardware::audio::common::V2_0::AudioPortConfig;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::V2_0::IDevice;
+using ::android::hardware::audio::V2_0::IPrimaryDevice;
+using ::android::hardware::audio::V2_0::IStreamIn;
+using ::android::hardware::audio::V2_0::IStreamOut;
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct PrimaryDevice : public IPrimaryDevice {
+    explicit PrimaryDevice(audio_hw_device_t* device);
+
+    // Methods from ::android::hardware::audio::V2_0::IDevice follow.
+    Return<Result> initCheck()  override;
+    Return<Result> setMasterVolume(float volume)  override;
+    Return<void> getMasterVolume(getMasterVolume_cb _hidl_cb)  override;
+    Return<Result> setMicMute(bool mute)  override;
+    Return<void> getMicMute(getMicMute_cb _hidl_cb)  override;
+    Return<Result> setMasterMute(bool mute)  override;
+    Return<void> getMasterMute(getMasterMute_cb _hidl_cb)  override;
+    Return<void> getInputBufferSize(
+            const AudioConfig& config, getInputBufferSize_cb _hidl_cb)  override;
+    Return<void> openOutputStream(
+            int32_t ioHandle,
+            const DeviceAddress& device,
+            const AudioConfig& config,
+            AudioOutputFlag flags,
+            openOutputStream_cb _hidl_cb)  override;
+    Return<void> openInputStream(
+            int32_t ioHandle,
+            const DeviceAddress& device,
+            const AudioConfig& config,
+            AudioInputFlag flags,
+            AudioSource source,
+            openInputStream_cb _hidl_cb)  override;
+    Return<void> createAudioPatch(
+            const hidl_vec<AudioPortConfig>& sources,
+            const hidl_vec<AudioPortConfig>& sinks,
+            createAudioPatch_cb _hidl_cb)  override;
+    Return<Result> releaseAudioPatch(int32_t patch)  override;
+    Return<void> getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb)  override;
+    Return<Result> setAudioPortConfig(const AudioPortConfig& config)  override;
+    Return<AudioHwSync> getHwAvSync()  override;
+    Return<Result> setScreenState(bool turnedOn)  override;
+    Return<void> getParameters(
+            const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
+    Return<void> debugDump(const native_handle_t* fd)  override;
+
+    // Methods from ::android::hardware::audio::V2_0::IPrimaryDevice follow.
+    Return<Result> setVoiceVolume(float volume)  override;
+    Return<Result> setMode(AudioMode mode)  override;
+    Return<void> getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb)  override;
+    Return<Result> setBtScoNrecEnabled(bool enabled)  override;
+    Return<void> getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb)  override;
+    Return<Result> setBtScoWidebandEnabled(bool enabled)  override;
+    Return<void> getTtyMode(getTtyMode_cb _hidl_cb)  override;
+    Return<Result> setTtyMode(IPrimaryDevice::TtyMode mode)  override;
+    Return<void> getHacEnabled(getHacEnabled_cb _hidl_cb)  override;
+    Return<Result> setHacEnabled(bool enabled)  override;
+
+  private:
+    sp<Device> mDevice;
+
+    virtual ~PrimaryDevice();
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_audio_V2_0_PrimaryDevice_H_
diff --git a/audio/2.0/default/Stream.cpp b/audio/2.0/default/Stream.cpp
new file mode 100644
index 0000000..7616bec
--- /dev/null
+++ b/audio/2.0/default/Stream.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2016 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 <inttypes.h>
+
+#define LOG_TAG "StreamHAL"
+
+#include <hardware/audio.h>
+#include <hardware/audio_effect.h>
+#include <media/TypeConverter.h>
+#include <utils/Log.h>
+#include <utils/SortedVector.h>
+#include <utils/Vector.h>
+
+#include "Conversions.h"
+#include "EffectMap.h"
+#include "Stream.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+Stream::Stream(audio_stream_t* stream)
+        : mStream(stream) {
+}
+
+Stream::~Stream() {
+    mStream = nullptr;
+}
+
+Result Stream::analyzeStatus(const char* funcName, int status) {
+    if (status != 0) {
+        ALOGW("Stream %p %s: %s", mStream, funcName, strerror(-status));
+    }
+    switch (status) {
+        case 0: return Result::OK;
+        case -EINVAL: return Result::INVALID_ARGUMENTS;
+        case -ENODATA: return Result::INVALID_STATE;
+        case -ENODEV: return Result::NOT_INITIALIZED;
+        case -ENOSYS: return Result::NOT_SUPPORTED;
+        default: return Result::INVALID_STATE;
+    }
+}
+
+char* Stream::halGetParameters(const char* keys) {
+    return mStream->get_parameters(mStream, keys);
+}
+
+int Stream::halSetParameters(const char* keysAndValues) {
+    return mStream->set_parameters(mStream, keysAndValues);
+}
+
+// Methods from ::android::hardware::audio::V2_0::IStream follow.
+Return<uint64_t> Stream::getFrameSize()  {
+    // Needs to be implemented by interface subclasses. But can't be declared as pure virtual,
+    // since interface subclasses implementation do not inherit from this class.
+    LOG_ALWAYS_FATAL("Stream::getFrameSize is pure abstract");
+    return uint64_t {};
+}
+
+Return<uint64_t> Stream::getFrameCount()  {
+    int halFrameCount;
+    Result retval = getParam(AudioParameter::keyFrameCount, &halFrameCount);
+    return retval == Result::OK ? halFrameCount : 0;
+}
+
+Return<uint64_t> Stream::getBufferSize()  {
+    return mStream->get_buffer_size(mStream);
+}
+
+Return<uint32_t> Stream::getSampleRate()  {
+    return mStream->get_sample_rate(mStream);
+}
+
+Return<void> Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  {
+    String8 halListValue;
+    Result result = getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue);
+    hidl_vec<uint32_t> sampleRates;
+    SortedVector<uint32_t> halSampleRates;
+    if (result == Result::OK) {
+        halSampleRates = samplingRatesFromString(
+                halListValue.string(), AudioParameter::valueListSeparator);
+        sampleRates.setToExternal(halSampleRates.editArray(), halSampleRates.size());
+    }
+    _hidl_cb(sampleRates);
+    return Void();
+}
+
+Return<Result> Stream::setSampleRate(uint32_t sampleRateHz)  {
+    return setParam(AudioParameter::keySamplingRate, static_cast<int>(sampleRateHz));
+}
+
+Return<AudioChannelMask> Stream::getChannelMask()  {
+    return AudioChannelMask(mStream->get_channels(mStream));
+}
+
+Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  {
+    String8 halListValue;
+    Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue);
+    hidl_vec<AudioChannelMask> channelMasks;
+    SortedVector<audio_channel_mask_t> halChannelMasks;
+    if (result == Result::OK) {
+        halChannelMasks = channelMasksFromString(
+                halListValue.string(), AudioParameter::valueListSeparator);
+        channelMasks.resize(halChannelMasks.size());
+        for (size_t i = 0; i < halChannelMasks.size(); ++i) {
+            channelMasks[i] = AudioChannelMask(halChannelMasks[i]);
+        }
+    }
+     _hidl_cb(channelMasks);
+    return Void();
+}
+
+Return<Result> Stream::setChannelMask(AudioChannelMask mask)  {
+    return setParam(AudioParameter::keyChannels, static_cast<int>(mask));
+}
+
+Return<AudioFormat> Stream::getFormat()  {
+    return AudioFormat(mStream->get_format(mStream));
+}
+
+Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb)  {
+    String8 halListValue;
+    Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
+    hidl_vec<AudioFormat> formats;
+    Vector<audio_format_t> halFormats;
+    if (result == Result::OK) {
+        halFormats = formatsFromString(halListValue.string(), AudioParameter::valueListSeparator);
+        formats.resize(halFormats.size());
+        for (size_t i = 0; i < halFormats.size(); ++i) {
+            formats[i] = AudioFormat(halFormats[i]);
+        }
+    }
+     _hidl_cb(formats);
+    return Void();
+}
+
+Return<Result> Stream::setFormat(AudioFormat format)  {
+    return setParam(AudioParameter::keyFormat, static_cast<int>(format));
+}
+
+Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb)  {
+    uint32_t halSampleRate = mStream->get_sample_rate(mStream);
+    audio_channel_mask_t halMask = mStream->get_channels(mStream);
+    audio_format_t halFormat = mStream->get_format(mStream);
+    _hidl_cb(halSampleRate, AudioChannelMask(halMask), AudioFormat(halFormat));
+    return Void();
+}
+
+Return<Result> Stream::addEffect(uint64_t effectId)  {
+    effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
+    if (halEffect != NULL) {
+        return analyzeStatus("add_audio_effect", mStream->add_audio_effect(mStream, halEffect));
+    } else {
+        ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
+        return Result::INVALID_ARGUMENTS;
+    }
+}
+
+Return<Result> Stream::removeEffect(uint64_t effectId)  {
+    effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
+    if (halEffect != NULL) {
+        return analyzeStatus(
+                "remove_audio_effect", mStream->remove_audio_effect(mStream, halEffect));
+    } else {
+        ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
+        return Result::INVALID_ARGUMENTS;
+    }
+}
+
+Return<Result> Stream::standby()  {
+    return analyzeStatus("standby", mStream->standby(mStream));
+}
+
+Return<AudioDevice> Stream::getDevice()  {
+    return AudioDevice(mStream->get_device(mStream));
+}
+
+Return<Result> Stream::setDevice(const DeviceAddress& address)  {
+    char* halDeviceAddress =
+            audio_device_address_to_parameter(
+                    static_cast<audio_devices_t>(address.device),
+                    deviceAddressToHal(address).c_str());
+    AudioParameter params((String8(halDeviceAddress)));
+    free(halDeviceAddress);
+    params.addInt(
+            String8(AudioParameter::keyRouting), static_cast<audio_devices_t>(address.device));
+    return setParams(params);
+}
+
+Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected)  {
+    return setParam(
+            connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect,
+            deviceAddressToHal(address).c_str());
+}
+
+Return<Result> Stream::setHwAvSync(uint32_t hwAvSync)  {
+    return setParam(AudioParameter::keyStreamHwAvSync, static_cast<int>(hwAvSync));
+}
+
+Return<void> Stream::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  {
+    getParametersImpl(keys, _hidl_cb);
+    return Void();
+}
+
+Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters)  {
+    return setParametersImpl(parameters);
+}
+
+Return<void> Stream::debugDump(const native_handle_t* fd)  {
+    if (fd->numFds == 1) {
+        analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
+    }
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/Stream.h b/audio/2.0/default/Stream.h
new file mode 100644
index 0000000..f28fbff
--- /dev/null
+++ b/audio/2.0/default/Stream.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 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 HIDL_GENERATED_android_hardware_audio_V2_0_Stream_H_
+#define HIDL_GENERATED_android_hardware_audio_V2_0_Stream_H_
+
+#include <android/hardware/audio/2.0/IStream.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "ParametersUtil.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioChannelMask;
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioFormat;
+using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::V2_0::IStream;
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Stream : public IStream, public ParametersUtil {
+    explicit Stream(audio_stream_t* stream);
+
+    // Methods from ::android::hardware::audio::V2_0::IStream follow.
+    Return<uint64_t> getFrameSize()  override;
+    Return<uint64_t> getFrameCount()  override;
+    Return<uint64_t> getBufferSize()  override;
+    Return<uint32_t> getSampleRate()  override;
+    Return<void> getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  override;
+    Return<Result> setSampleRate(uint32_t sampleRateHz)  override;
+    Return<AudioChannelMask> getChannelMask()  override;
+    Return<void> getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  override;
+    Return<Result> setChannelMask(AudioChannelMask mask)  override;
+    Return<AudioFormat> getFormat()  override;
+    Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb)  override;
+    Return<Result> setFormat(AudioFormat format)  override;
+    Return<void> getAudioProperties(getAudioProperties_cb _hidl_cb)  override;
+    Return<Result> addEffect(uint64_t effectId)  override;
+    Return<Result> removeEffect(uint64_t effectId)  override;
+    Return<Result> standby()  override;
+    Return<AudioDevice> getDevice()  override;
+    Return<Result> setDevice(const DeviceAddress& address)  override;
+    Return<Result> setConnectedState(const DeviceAddress& address, bool connected)  override;
+    Return<Result> setHwAvSync(uint32_t hwAvSync)  override;
+    Return<void> getParameters(
+            const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
+    Return<void> debugDump(const native_handle_t* fd)  override;
+
+    // Utility methods for extending interfaces.
+    Result analyzeStatus(const char* funcName, int status);
+
+  private:
+    audio_stream_t *mStream;
+
+    virtual ~Stream();
+
+    // Methods from ParametersUtil.
+    char* halGetParameters(const char* keys) override;
+    int halSetParameters(const char* keysAndValues) override;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_audio_V2_0_Stream_H_
diff --git a/audio/2.0/default/StreamIn.cpp b/audio/2.0/default/StreamIn.cpp
new file mode 100644
index 0000000..b590d1a
--- /dev/null
+++ b/audio/2.0/default/StreamIn.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2016 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 "StreamInHAL"
+
+#include <hardware/audio.h>
+#include <utils/Log.h>
+
+#include "StreamIn.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+StreamIn::StreamIn(audio_hw_device_t* device, audio_stream_in_t* stream)
+        : mDevice(device), mStream(stream), mStreamCommon(new Stream(&stream->common)) {
+}
+
+StreamIn::~StreamIn() {
+    mDevice->close_input_stream(mDevice, mStream);
+    mStream = nullptr;
+    mDevice = nullptr;
+}
+
+// Methods from ::android::hardware::audio::V2_0::IStream follow.
+Return<uint64_t> StreamIn::getFrameSize()  {
+    return audio_stream_in_frame_size(mStream);
+}
+
+Return<uint64_t> StreamIn::getFrameCount()  {
+    return mStreamCommon->getFrameCount();
+}
+
+Return<uint64_t> StreamIn::getBufferSize()  {
+    return mStreamCommon->getBufferSize();
+}
+
+Return<uint32_t> StreamIn::getSampleRate()  {
+    return mStreamCommon->getSampleRate();
+}
+
+Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedSampleRates(_hidl_cb);
+}
+
+Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz)  {
+    return mStreamCommon->setSampleRate(sampleRateHz);
+}
+
+Return<AudioChannelMask> StreamIn::getChannelMask()  {
+    return mStreamCommon->getChannelMask();
+}
+
+Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
+}
+
+Return<Result> StreamIn::setChannelMask(AudioChannelMask mask)  {
+    return mStreamCommon->setChannelMask(mask);
+}
+
+Return<AudioFormat> StreamIn::getFormat()  {
+    return mStreamCommon->getFormat();
+}
+
+Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedFormats(_hidl_cb);
+}
+
+Return<Result> StreamIn::setFormat(AudioFormat format)  {
+    return mStreamCommon->setFormat(format);
+}
+
+Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb)  {
+    return mStreamCommon->getAudioProperties(_hidl_cb);
+}
+
+Return<Result> StreamIn::addEffect(uint64_t effectId)  {
+    return mStreamCommon->addEffect(effectId);
+}
+
+Return<Result> StreamIn::removeEffect(uint64_t effectId)  {
+    return mStreamCommon->removeEffect(effectId);
+}
+
+Return<Result> StreamIn::standby()  {
+    return mStreamCommon->standby();
+}
+
+Return<AudioDevice> StreamIn::getDevice()  {
+    return mStreamCommon->getDevice();
+}
+
+Return<Result> StreamIn::setDevice(const DeviceAddress& address)  {
+    return mStreamCommon->setDevice(address);
+}
+
+Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected)  {
+    return mStreamCommon->setConnectedState(address, connected);
+}
+
+Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync)  {
+    return mStreamCommon->setHwAvSync(hwAvSync);
+}
+
+Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
+    return mStreamCommon->getParameters(keys, _hidl_cb);
+}
+
+Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& parameters)  {
+    return mStreamCommon->setParameters(parameters);
+}
+
+Return<void> StreamIn::debugDump(const native_handle_t* fd)  {
+    return mStreamCommon->debugDump(fd);
+}
+
+
+// Methods from ::android::hardware::audio::V2_0::IStreamIn follow.
+Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb)  {
+    int halSource;
+    Result retval = mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource);
+    AudioSource source(AudioSource::DEFAULT);
+    if (retval == Result::OK) {
+        source = AudioSource(halSource);
+    }
+    _hidl_cb(retval, source);
+    return Void();
+}
+
+Return<Result> StreamIn::setGain(float gain)  {
+    return mStreamCommon->analyzeStatus("set_gain", mStream->set_gain(mStream, gain));
+}
+
+Return<void> StreamIn::read(uint64_t size, read_cb _hidl_cb)  {
+    // TODO(mnaganov): Replace with FMQ version.
+    hidl_vec<uint8_t> data;
+    data.resize(size);
+    Result retval(Result::OK);
+    ssize_t readResult = mStream->read(mStream, &data[0], data.size());
+    if (readResult >= 0 && static_cast<size_t>(readResult) != data.size()) {
+        data.resize(readResult);
+    } else if (readResult < 0) {
+        data.resize(0);
+        retval = mStreamCommon->analyzeStatus("read", readResult);
+    }
+    _hidl_cb(retval, data);
+    return Void();
+}
+
+Return<uint32_t> StreamIn::getInputFramesLost()  {
+    return mStream->get_input_frames_lost(mStream);
+}
+
+Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb)  {
+    Result retval(Result::NOT_SUPPORTED);
+    uint64_t frames = 0, time = 0;
+    if (mStream->get_capture_position != NULL) {
+        int64_t halFrames, halTime;
+        retval = mStreamCommon->analyzeStatus(
+                "get_capture_position",
+                mStream->get_capture_position(mStream, &halFrames, &halTime));
+        if (retval == Result::OK) {
+            frames = halFrames;
+            time = halTime;
+        }
+    }
+    _hidl_cb(retval, frames, time);
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/StreamIn.h b/audio/2.0/default/StreamIn.h
new file mode 100644
index 0000000..83f620c
--- /dev/null
+++ b/audio/2.0/default/StreamIn.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 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 HIDL_GENERATED_android_hardware_audio_V2_0_StreamIn_H_
+#define HIDL_GENERATED_android_hardware_audio_V2_0_StreamIn_H_
+
+#include <android/hardware/audio/2.0/IStreamIn.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Stream.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioChannelMask;
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioFormat;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::V2_0::IStream;
+using ::android::hardware::audio::V2_0::IStreamIn;
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct StreamIn : public IStreamIn {
+    StreamIn(audio_hw_device_t* device, audio_stream_in_t* stream);
+
+    // Methods from ::android::hardware::audio::V2_0::IStream follow.
+    Return<uint64_t> getFrameSize()  override;
+    Return<uint64_t> getFrameCount()  override;
+    Return<uint64_t> getBufferSize()  override;
+    Return<uint32_t> getSampleRate()  override;
+    Return<void> getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  override;
+    Return<Result> setSampleRate(uint32_t sampleRateHz)  override;
+    Return<AudioChannelMask> getChannelMask()  override;
+    Return<void> getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  override;
+    Return<Result> setChannelMask(AudioChannelMask mask)  override;
+    Return<AudioFormat> getFormat()  override;
+    Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb)  override;
+    Return<Result> setFormat(AudioFormat format)  override;
+    Return<void> getAudioProperties(getAudioProperties_cb _hidl_cb)  override;
+    Return<Result> addEffect(uint64_t effectId)  override;
+    Return<Result> removeEffect(uint64_t effectId)  override;
+    Return<Result> standby()  override;
+    Return<AudioDevice> getDevice()  override;
+    Return<Result> setDevice(const DeviceAddress& address)  override;
+    Return<Result> setConnectedState(const DeviceAddress& address, bool connected)  override;
+    Return<Result> setHwAvSync(uint32_t hwAvSync)  override;
+    Return<void> getParameters(
+            const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
+    Return<void> debugDump(const native_handle_t* fd)  override;
+
+    // Methods from ::android::hardware::audio::V2_0::IStreamIn follow.
+    Return<void> getAudioSource(getAudioSource_cb _hidl_cb)  override;
+    Return<Result> setGain(float gain)  override;
+    Return<void> read(uint64_t size, read_cb _hidl_cb)  override;
+    Return<uint32_t> getInputFramesLost()  override;
+    Return<void> getCapturePosition(getCapturePosition_cb _hidl_cb)  override;
+
+  private:
+    audio_hw_device_t *mDevice;
+    audio_stream_in_t *mStream;
+    sp<Stream> mStreamCommon;
+
+    virtual ~StreamIn();
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_audio_V2_0_StreamIn_H_
diff --git a/audio/2.0/default/StreamOut.cpp b/audio/2.0/default/StreamOut.cpp
new file mode 100644
index 0000000..34bae29
--- /dev/null
+++ b/audio/2.0/default/StreamOut.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2016 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 "StreamOutHAL"
+
+#include <hardware/audio.h>
+#include <utils/Log.h>
+
+#include "StreamOut.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+StreamOut::StreamOut(audio_hw_device_t* device, audio_stream_out_t* stream)
+        : mDevice(device), mStream(stream), mStreamCommon(new Stream(&stream->common)) {
+}
+
+StreamOut::~StreamOut() {
+    mCallback.clear();
+    mDevice->close_output_stream(mDevice, mStream);
+    mStream = nullptr;
+    mDevice = nullptr;
+}
+
+// Methods from ::android::hardware::audio::V2_0::IStream follow.
+Return<uint64_t> StreamOut::getFrameSize()  {
+    return audio_stream_out_frame_size(mStream);
+}
+
+Return<uint64_t> StreamOut::getFrameCount()  {
+    return mStreamCommon->getFrameCount();
+}
+
+Return<uint64_t> StreamOut::getBufferSize()  {
+    return mStreamCommon->getBufferSize();
+}
+
+Return<uint32_t> StreamOut::getSampleRate()  {
+    return mStreamCommon->getSampleRate();
+}
+
+Return<void> StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedSampleRates(_hidl_cb);
+}
+
+Return<Result> StreamOut::setSampleRate(uint32_t sampleRateHz)  {
+    return mStreamCommon->setSampleRate(sampleRateHz);
+}
+
+Return<AudioChannelMask> StreamOut::getChannelMask()  {
+    return mStreamCommon->getChannelMask();
+}
+
+Return<void> StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
+}
+
+Return<Result> StreamOut::setChannelMask(AudioChannelMask mask)  {
+    return mStreamCommon->setChannelMask(mask);
+}
+
+Return<AudioFormat> StreamOut::getFormat()  {
+    return mStreamCommon->getFormat();
+}
+
+Return<void> StreamOut::getSupportedFormats(getSupportedFormats_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedFormats(_hidl_cb);
+}
+
+Return<Result> StreamOut::setFormat(AudioFormat format)  {
+    return mStreamCommon->setFormat(format);
+}
+
+Return<void> StreamOut::getAudioProperties(getAudioProperties_cb _hidl_cb)  {
+    return mStreamCommon->getAudioProperties(_hidl_cb);
+}
+
+Return<Result> StreamOut::addEffect(uint64_t effectId)  {
+    return mStreamCommon->addEffect(effectId);
+}
+
+Return<Result> StreamOut::removeEffect(uint64_t effectId)  {
+    return mStreamCommon->removeEffect(effectId);
+}
+
+Return<Result> StreamOut::standby()  {
+    return mStreamCommon->standby();
+}
+
+Return<AudioDevice> StreamOut::getDevice()  {
+    return mStreamCommon->getDevice();
+}
+
+Return<Result> StreamOut::setDevice(const DeviceAddress& address)  {
+    return mStreamCommon->setDevice(address);
+}
+
+Return<Result> StreamOut::setConnectedState(const DeviceAddress& address, bool connected)  {
+    return mStreamCommon->setConnectedState(address, connected);
+}
+
+Return<Result> StreamOut::setHwAvSync(uint32_t hwAvSync)  {
+    return mStreamCommon->setHwAvSync(hwAvSync);
+}
+
+Return<void> StreamOut::getParameters(
+        const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  {
+    return mStreamCommon->getParameters(keys, _hidl_cb);
+}
+
+Return<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& parameters)  {
+    return mStreamCommon->setParameters(parameters);
+}
+
+Return<void> StreamOut::debugDump(const native_handle_t* fd)  {
+    return mStreamCommon->debugDump(fd);
+}
+
+
+// Methods from ::android::hardware::audio::V2_0::IStreamOut follow.
+Return<uint32_t> StreamOut::getLatency()  {
+    return mStream->get_latency(mStream);
+}
+
+Return<Result> StreamOut::setVolume(float left, float right)  {
+    Result retval(Result::NOT_SUPPORTED);
+    if (mStream->set_volume != NULL) {
+        retval = mStreamCommon->analyzeStatus(
+                "set_volume", mStream->set_volume(mStream, left, right));
+    }
+    return retval;
+}
+
+Return<void> StreamOut::write(const hidl_vec<uint8_t>& data, write_cb _hidl_cb)  {
+    // TODO(mnaganov): Replace with FMQ version.
+    Result retval(Result::OK);
+    uint64_t written = 0;
+    ssize_t writeResult = mStream->write(mStream, &data[0], data.size());
+    if (writeResult >= 0) {
+        written = writeResult;
+    } else {
+        retval = mStreamCommon->analyzeStatus("write", writeResult);
+        written = 0;
+    }
+    _hidl_cb(retval, written);
+    return Void();
+}
+
+Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb)  {
+    uint32_t halDspFrames;
+    Result retval = mStreamCommon->analyzeStatus(
+            "get_render_position", mStream->get_render_position(mStream, &halDspFrames));
+    _hidl_cb(retval, halDspFrames);
+    return Void();
+}
+
+Return<void> StreamOut::getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb)  {
+    Result retval(Result::NOT_SUPPORTED);
+    int64_t timestampUs = 0;
+    if (mStream->get_next_write_timestamp != NULL) {
+        retval = mStreamCommon->analyzeStatus(
+                "get_next_write_timestamp",
+                mStream->get_next_write_timestamp(mStream, &timestampUs));
+    }
+    _hidl_cb(retval, timestampUs);
+    return Void();
+}
+
+Return<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback)  {
+    if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
+    int result = mStream->set_callback(mStream, StreamOut::asyncCallback, this);
+    if (result == 0) {
+        mCallback = callback;
+    }
+    return mStreamCommon->analyzeStatus("set_callback", result);
+}
+
+// static
+int StreamOut::asyncCallback(stream_callback_event_t event, void*, void *cookie) {
+    wp<StreamOut> weakSelf(reinterpret_cast<StreamOut*>(cookie));
+    sp<StreamOut> self = weakSelf.promote();
+    if (self == 0) return 0;
+    sp<IStreamOutCallback> callback = self->mCallback.promote();
+    if (callback == 0) return 0;
+    ALOGV("asyncCallback() event %d", event);
+    switch (event) {
+        case STREAM_CBK_EVENT_WRITE_READY:
+            callback->onWriteReady();
+            break;
+        case STREAM_CBK_EVENT_DRAIN_READY:
+            callback->onDrainReady();
+            break;
+        case STREAM_CBK_EVENT_ERROR:
+            callback->onError();
+            break;
+        default:
+            ALOGW("asyncCallback() unknown event %d", event);
+            break;
+    }
+    return 0;
+}
+
+Return<void> StreamOut::supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb)  {
+    _hidl_cb(mStream->pause != NULL, mStream->resume != NULL);
+    return Void();
+}
+
+Return<Result> StreamOut::pause()  {
+    return mStream->pause != NULL ?
+            mStreamCommon->analyzeStatus("pause", mStream->pause(mStream)) :
+            Result::NOT_SUPPORTED;
+}
+
+Return<Result> StreamOut::resume()  {
+    return mStream->resume != NULL ?
+            mStreamCommon->analyzeStatus("resume", mStream->resume(mStream)) :
+            Result::NOT_SUPPORTED;
+}
+
+Return<bool> StreamOut::supportsDrain()  {
+    return mStream->drain != NULL;
+}
+
+Return<Result> StreamOut::drain(AudioDrain type)  {
+    return mStream->drain != NULL ?
+            mStreamCommon->analyzeStatus(
+                    "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type))) :
+            Result::NOT_SUPPORTED;
+}
+
+Return<Result> StreamOut::flush()  {
+    return mStream->flush != NULL ?
+            mStreamCommon->analyzeStatus("flush", mStream->flush(mStream)) :
+            Result::NOT_SUPPORTED;
+}
+
+Return<void> StreamOut::getPresentationPosition(getPresentationPosition_cb _hidl_cb)  {
+    Result retval(Result::NOT_SUPPORTED);
+    uint64_t frames = 0;
+    TimeSpec timeStamp = { 0, 0 };
+    if (mStream->get_presentation_position != NULL) {
+        struct timespec halTimeStamp;
+        retval = mStreamCommon->analyzeStatus(
+                "get_presentation_position",
+                mStream->get_presentation_position(mStream, &frames, &halTimeStamp));
+        if (retval == Result::OK) {
+            timeStamp.tvSec = halTimeStamp.tv_sec;
+            timeStamp.tvNSec = halTimeStamp.tv_nsec;
+        }
+    }
+    _hidl_cb(retval, frames, timeStamp);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/StreamOut.h b/audio/2.0/default/StreamOut.h
new file mode 100644
index 0000000..51b7df8
--- /dev/null
+++ b/audio/2.0/default/StreamOut.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2016 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 HIDL_GENERATED_android_hardware_audio_V2_0_StreamOut_H_
+#define HIDL_GENERATED_android_hardware_audio_V2_0_StreamOut_H_
+
+#include <android/hardware/audio/2.0/IStreamOut.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Stream.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioChannelMask;
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioFormat;
+using ::android::hardware::audio::V2_0::AudioDrain;
+using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::V2_0::IStream;
+using ::android::hardware::audio::V2_0::IStreamOut;
+using ::android::hardware::audio::V2_0::IStreamOutCallback;
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::audio::V2_0::TimeSpec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct StreamOut : public IStreamOut {
+    StreamOut(audio_hw_device_t* device, audio_stream_out_t* stream);
+
+    // Methods from ::android::hardware::audio::V2_0::IStream follow.
+    Return<uint64_t> getFrameSize()  override;
+    Return<uint64_t> getFrameCount()  override;
+    Return<uint64_t> getBufferSize()  override;
+    Return<uint32_t> getSampleRate()  override;
+    Return<void> getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  override;
+    Return<Result> setSampleRate(uint32_t sampleRateHz)  override;
+    Return<AudioChannelMask> getChannelMask()  override;
+    Return<void> getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  override;
+    Return<Result> setChannelMask(AudioChannelMask mask)  override;
+    Return<AudioFormat> getFormat()  override;
+    Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb)  override;
+    Return<Result> setFormat(AudioFormat format)  override;
+    Return<void> getAudioProperties(getAudioProperties_cb _hidl_cb)  override;
+    Return<Result> addEffect(uint64_t effectId)  override;
+    Return<Result> removeEffect(uint64_t effectId)  override;
+    Return<Result> standby()  override;
+    Return<AudioDevice> getDevice()  override;
+    Return<Result> setDevice(const DeviceAddress& address)  override;
+    Return<Result> setConnectedState(const DeviceAddress& address, bool connected)  override;
+    Return<Result> setHwAvSync(uint32_t hwAvSync)  override;
+    Return<void> getParameters(
+            const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
+    Return<void> debugDump(const native_handle_t* fd)  override;
+
+    // Methods from ::android::hardware::audio::V2_0::IStreamOut follow.
+    Return<uint32_t> getLatency()  override;
+    Return<Result> setVolume(float left, float right)  override;
+    Return<void> write(const hidl_vec<uint8_t>& data, write_cb _hidl_cb)  override;
+    Return<void> getRenderPosition(getRenderPosition_cb _hidl_cb)  override;
+    Return<void> getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb)  override;
+    Return<Result> setCallback(const sp<IStreamOutCallback>& callback)  override;
+    Return<void> supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb)  override;
+    Return<Result> pause()  override;
+    Return<Result> resume()  override;
+    Return<bool> supportsDrain()  override;
+    Return<Result> drain(AudioDrain type)  override;
+    Return<Result> flush()  override;
+    Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb)  override;
+
+  private:
+    audio_hw_device_t *mDevice;
+    audio_stream_out_t *mStream;
+    sp<Stream> mStreamCommon;
+    // Do not store sp<> to avoid creating a reference loop if the entity that holds
+    // onto the output stream owns or implements the callback.
+    wp<IStreamOutCallback> mCallback;
+
+    virtual ~StreamOut();
+
+    static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_audio_V2_0_StreamOut_H_
diff --git a/audio/2.0/default/service.cpp b/audio/2.0/default/service.cpp
index 39708c2..147f7b9 100644
--- a/audio/2.0/default/service.cpp
+++ b/audio/2.0/default/service.cpp
@@ -14,28 +14,23 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "soundtriggerhal"
+#define LOG_TAG "audiohalservice"
 
-#include <hwbinder/IInterface.h>
-#include <hwbinder/IPCThreadState.h>
-#include <hwbinder/ProcessState.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/Looper.h>
-#include <utils/StrongPointer.h>
+#include <hidl/LegacySupport.h>
+#include <android/hardware/audio/2.0/IDevicesFactory.h>
+#include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
 
 using android::hardware::IPCThreadState;
 using android::hardware::ProcessState;
+using android::hardware::audio::effect::V2_0::IEffectsFactory;
+using android::hardware::audio::V2_0::IDevicesFactory;
 using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
+using android::hardware::registerPassthroughServiceImplementation;
 
 int main(int /* argc */, char* /* argv */ []) {
-    android::sp<ISoundTriggerHw> service =
-            ISoundTriggerHw::getService("sound_trigger.primary", true /* getStub */);
-
-    service->registerAsService("sound_trigger.primary");
-
-    ProcessState::self()->setThreadPoolMaxThreadCount(0);
-    ProcessState::self()->startThreadPool();
-    IPCThreadState::self()->joinThreadPool();
+    registerPassthroughServiceImplementation<IDevicesFactory>("audio_devices_factory");
+    registerPassthroughServiceImplementation<IEffectsFactory>("audio_effects_factory");
+    registerPassthroughServiceImplementation<ISoundTriggerHw>("sound_trigger.primary");
+    return android::hardware::launchRpcServer(16);
 }
diff --git a/audio/2.0/types.hal b/audio/2.0/types.hal
index 6369885..9a5e4f1 100644
--- a/audio/2.0/types.hal
+++ b/audio/2.0/types.hal
@@ -66,7 +66,7 @@
             int32_t card;
             int32_t device;
         } alsa;             // used for USB_*
-        int32_t busId;      // used for BUS
     } address;
+    string busAddress;      // used for BUS
     string rSubmixAddress;  // used for REMOTE_SUBMIX
 };
diff --git a/audio/Android.bp b/audio/Android.bp
index 4117288..3121a36 100644
--- a/audio/Android.bp
+++ b/audio/Android.bp
@@ -3,4 +3,5 @@
     "2.0",
     "common/2.0",
     "effect/2.0",
+    "effect/2.0/vts/functional",
 ]
diff --git a/audio/common/2.0/default/Android.mk b/audio/common/2.0/default/Android.mk
new file mode 100644
index 0000000..aa60eb2
--- /dev/null
+++ b/audio/common/2.0/default/Android.mk
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2016 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 := android.hardware.audio.common@2.0-util
+LOCAL_SRC_FILES := \
+    EffectMap.cpp \
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+
+LOCAL_SHARED_LIBRARIES := \
+    libutils \
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/audio/common/2.0/default/EffectMap.cpp b/audio/common/2.0/default/EffectMap.cpp
new file mode 100644
index 0000000..703b91c
--- /dev/null
+++ b/audio/common/2.0/default/EffectMap.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 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 <atomic>
+
+#include "EffectMap.h"
+
+namespace android {
+
+ANDROID_SINGLETON_STATIC_INSTANCE(EffectMap);
+
+// static
+const uint64_t EffectMap::INVALID_ID = 0;
+
+// static
+uint64_t EffectMap::makeUniqueId() {
+    static std::atomic<uint64_t> counter{INVALID_ID + 1};
+    return counter++;
+}
+
+uint64_t EffectMap::add(effect_handle_t handle) {
+    uint64_t newId = makeUniqueId();
+    std::lock_guard<std::mutex> lock(mLock);
+    mEffects.add(newId, handle);
+    return newId;
+}
+
+effect_handle_t EffectMap::get(const uint64_t& id) {
+    std::lock_guard<std::mutex> lock(mLock);
+    ssize_t idx = mEffects.indexOfKey(id);
+    return idx >= 0 ? mEffects[idx] : NULL;
+}
+
+void EffectMap::remove(effect_handle_t handle) {
+    std::lock_guard<std::mutex> lock(mLock);
+    for (size_t i = 0; i < mEffects.size(); ++i) {
+        if (mEffects[i] == handle) {
+            mEffects.removeItemsAt(i);
+            break;
+        }
+    }
+}
+
+}  // namespace android
diff --git a/audio/common/2.0/default/EffectMap.h b/audio/common/2.0/default/EffectMap.h
new file mode 100644
index 0000000..82bbb1f
--- /dev/null
+++ b/audio/common/2.0/default/EffectMap.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 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_audio_V2_0_EffectMap_H_
+#define android_hardware_audio_V2_0_EffectMap_H_
+
+#include <mutex>
+
+#include <hardware/audio_effect.h>
+#include <utils/KeyedVector.h>
+#include <utils/Singleton.h>
+
+namespace android {
+
+// This class needs to be in 'android' ns because Singleton macros require that.
+class EffectMap : public Singleton<EffectMap> {
+  public:
+    static const uint64_t INVALID_ID;
+
+    uint64_t add(effect_handle_t handle);
+    effect_handle_t get(const uint64_t& id);
+    void remove(effect_handle_t handle);
+
+  private:
+    static uint64_t makeUniqueId();
+
+    std::mutex mLock;
+    KeyedVector<uint64_t, effect_handle_t> mEffects;
+};
+
+}  // namespace android
+
+#endif  // android_hardware_audio_V2_0_EffectMap_H_
diff --git a/audio/common/2.0/types.hal b/audio/common/2.0/types.hal
index a5ec68d..75fdb52 100644
--- a/audio/common/2.0/types.hal
+++ b/audio/common/2.0/types.hal
@@ -555,8 +555,7 @@
     IN_IP                    = BIT_IN | 0x80000,
     /* audio bus implemented by the audio system (e.g an MOST stereo channel) */
     IN_BUS                   = BIT_IN | 0x100000,
-    IN_DEFAULT               = BIT_IN |
-                                            BIT_DEFAULT,
+    IN_DEFAULT               = BIT_IN | BIT_DEFAULT,
 
     IN_ALL     = (IN_COMMUNICATION |
             IN_AMBIENT |
@@ -798,10 +797,10 @@
             union UseCase {
                 AudioStreamType stream;
                 AudioSource source;
-            };
+            } useCase;
         } mix;
         AudioPortConfigSessionExt session;
-    };
+    } ext;
 };
 
 /*
@@ -849,16 +848,5 @@
         AudioPortDeviceExt device;
         AudioPortMixExt mix;
         AudioPortSessionExt session;
-    };
-};
-
-/*
- * An audio patch represents a connection between one or more source ports and
- * one or more sink ports. Patches are connected and disconnected by audio
- * policy manager or by applications via framework APIs.
- */
-struct AudioPatch {
-    AudioPatchHandle id;
-    vec<AudioPortConfig> sources;
-    vec<AudioPortConfig> sinks;
+    } ext;
 };
diff --git a/audio/effect/2.0/IEffectsFactory.hal b/audio/effect/2.0/IEffectsFactory.hal
index 6763825..c82b4a2 100644
--- a/audio/effect/2.0/IEffectsFactory.hal
+++ b/audio/effect/2.0/IEffectsFactory.hal
@@ -50,9 +50,11 @@
      *                 directed to in audio HAL.
      * @return retval operation completion status.
      * @return result the interface for the created effect.
+     * @return effectId the unique ID of the effect to be used with
+     *                  IStream::addEffect and IStream::removeEffect methods.
      */
     createEffect(Uuid uid, AudioSession session, AudioIoHandle ioHandle)
-            generates (Result retval, IEffect result);
+        generates (Result retval, IEffect result, uint64_t effectId);
 
     /*
      * Dumps information about effects into the provided file descriptor.
diff --git a/audio/effect/2.0/default/Android.mk b/audio/effect/2.0/default/Android.mk
index 13106f3..50c4bd6 100644
--- a/audio/effect/2.0/default/Android.mk
+++ b/audio/effect/2.0/default/Android.mk
@@ -26,6 +26,7 @@
     libeffects \
     liblog \
     android.hardware.audio.common@2.0 \
+    android.hardware.audio.common@2.0-util \
     android.hardware.audio.effect@2.0 \
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/audio/effect/2.0/default/Effect.cpp b/audio/effect/2.0/default/Effect.cpp
index 8ab0749..82d0292 100644
--- a/audio/effect/2.0/default/Effect.cpp
+++ b/audio/effect/2.0/default/Effect.cpp
@@ -23,6 +23,7 @@
 
 #include "Conversions.h"
 #include "Effect.h"
+#include "EffectMap.h"
 
 namespace android {
 namespace hardware {
@@ -45,6 +46,7 @@
 Effect::~Effect() {
     int status = EffectRelease(mHandle);
     ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
+    EffectMap::getInstance().remove(mHandle);
     mHandle = 0;
 }
 
diff --git a/audio/effect/2.0/default/EffectsFactory.cpp b/audio/effect/2.0/default/EffectsFactory.cpp
index f7c5d62..30fcb26 100644
--- a/audio/effect/2.0/default/EffectsFactory.cpp
+++ b/audio/effect/2.0/default/EffectsFactory.cpp
@@ -36,6 +36,7 @@
 #include "EffectsFactory.h"
 #include "DownmixEffect.h"
 #include "Effect.h"
+#include "EffectMap.h"
 #include "EnvironmentalReverbEffect.h"
 #include "EqualizerEffect.h"
 #include "LoudnessEnhancerEffect.h"
@@ -157,12 +158,16 @@
     Result retval(Result::OK);
     status_t status = EffectCreate(&halUuid, session, ioHandle, &handle);
     sp<IEffect> effect;
+    uint64_t effectId = EffectMap::INVALID_ID;
     if (status == OK) {
         effect_descriptor_t halDescriptor;
         memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
         status = (*handle)->get_descriptor(handle, &halDescriptor);
         if (status == OK) {
             effect = dispatchEffectInstanceCreation(halDescriptor, handle);
+            effectId = EffectMap::getInstance().add(handle);
+        } else {
+            EffectRelease(handle);
         }
     }
     if (status != OK) {
@@ -173,7 +178,7 @@
             retval = Result::NOT_INITIALIZED;
         }
     }
-    _hidl_cb(retval, effect);
+    _hidl_cb(retval, effect, effectId);
     return Void();
 }
 
diff --git a/audio/effect/2.0/vts/functional/Android.bp b/audio/effect/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..fc198e5
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2016 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.
+//
+
+cc_test {
+    name: "audio_effect_hidl_hal_test",
+    gtest: true,
+    srcs: ["audio_effect_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidl",
+        "libhwbinder",
+        "libnativehelper",
+        "libutils",
+        "android.hardware.audio.effect@2.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
diff --git a/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp b/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp
new file mode 100644
index 0000000..c7878d5
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2016 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 "AudioEffectHidlHalTest"
+#include <android-base/logging.h>
+#include <cutils/native_handle.h>
+
+#include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
+#include <android/hardware/audio/effect/2.0/types.h>
+
+#include <gtest/gtest.h>
+
+using ::android::hardware::audio::common::V2_0::Uuid;
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::audio::effect::V2_0::IEffectsFactory;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Status;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::sp;
+
+// The main test class for Audio Effect HIDL HAL.
+class AudioEffectHidlTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    // currently test passthrough mode only
+    effectsFactory = IEffectsFactory::getService("audio_effects_factory", true);
+    ASSERT_NE(effectsFactory, nullptr);
+  }
+
+  virtual void TearDown() override {}
+
+  sp<IEffectsFactory> effectsFactory;
+};
+
+// A class for test environment setup (kept since this file is a template).
+class AudioEffectHidlEnvironment : public ::testing::Environment {
+ public:
+  virtual void SetUp() {}
+  virtual void TearDown() {}
+
+ private:
+};
+
+TEST_F(AudioEffectHidlTest, EnumerateEffects) {
+  Result retval = Result::NOT_INITIALIZED;
+  size_t effectCount = 0;
+  Return<void> ret = effectsFactory->getAllDescriptors(
+      [&](Result r, const hidl_vec<EffectDescriptor>& result) {
+        retval = r;
+        effectCount = result.size();
+      });
+  EXPECT_EQ(ret.getStatus().exceptionCode(), Status::EX_NONE);
+  EXPECT_EQ(retval, Result::OK);
+  EXPECT_GT(effectCount, 0u);
+}
+
+TEST_F(AudioEffectHidlTest, CreateEffect) {
+  bool gotEffect = false;
+  Uuid effectUuid;
+  Return<void> ret = effectsFactory->getAllDescriptors(
+      [&](Result r, const hidl_vec<EffectDescriptor>& result) {
+        if (r == Result::OK && result.size() > 0) {
+          gotEffect = true;
+          effectUuid = result[0].uuid;
+        }
+      });
+  ASSERT_EQ(ret.getStatus().exceptionCode(), Status::EX_NONE);
+  ASSERT_TRUE(gotEffect);
+  Result retval = Result::NOT_INITIALIZED;
+  sp<IEffect> effect;
+  ret = effectsFactory->createEffect(
+      effectUuid, 1 /* session */, 1 /* ioHandle */,
+      [&](Result r, const sp<IEffect>& result, uint64_t /*effectId*/) {
+        retval = r;
+        if (r == Result::OK) {
+          effect = result;
+        }
+      });
+  EXPECT_EQ(ret.getStatus().exceptionCode(), Status::EX_NONE);
+  EXPECT_EQ(retval, Result::OK);
+  EXPECT_NE(effect, nullptr);
+}
+
+// See b/32834072 -- we should have those operator== generated by hidl-gen.
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace common {
+namespace V2_0 {
+
+static bool operator==(const Uuid& lhs, const Uuid& rhs) {
+  return lhs.timeLow == rhs.timeLow && lhs.timeMid == rhs.timeMid &&
+         lhs.versionAndTimeHigh == rhs.versionAndTimeHigh &&
+         lhs.variantAndClockSeqHigh == rhs.variantAndClockSeqHigh &&
+         memcmp(lhs.node.data(), rhs.node.data(), lhs.node.size()) == 0;
+}
+
+}  // namespace V2_0
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+
+static bool operator==(const EffectDescriptor& lhs,
+                       const EffectDescriptor& rhs) {
+  return lhs.type == rhs.type && lhs.uuid == rhs.uuid &&
+         lhs.flags == rhs.flags && lhs.cpuLoad == rhs.cpuLoad &&
+         lhs.memoryUsage == rhs.memoryUsage &&
+         memcmp(lhs.name.data(), rhs.name.data(), lhs.name.size()) == 0 &&
+         memcmp(lhs.implementor.data(), rhs.implementor.data(),
+                lhs.implementor.size()) == 0;
+}
+
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+TEST_F(AudioEffectHidlTest, GetDescriptor) {
+  hidl_vec<EffectDescriptor> allDescriptors;
+  Return<void> ret = effectsFactory->getAllDescriptors(
+      [&](Result r, const hidl_vec<EffectDescriptor>& result) {
+        if (r == Result::OK) {
+          allDescriptors = result;
+        }
+      });
+  ASSERT_EQ(ret.getStatus().exceptionCode(), Status::EX_NONE);
+  ASSERT_GT(allDescriptors.size(), 0u);
+  for (size_t i = 0; i < allDescriptors.size(); ++i) {
+    ret = effectsFactory->getDescriptor(
+        allDescriptors[i].uuid, [&](Result r, const EffectDescriptor& result) {
+          EXPECT_EQ(r, Result::OK);
+          EXPECT_EQ(result, allDescriptors[i]);
+        });
+  }
+  EXPECT_EQ(ret.getStatus().exceptionCode(), Status::EX_NONE);
+}
+
+int main(int argc, char** argv) {
+  ::testing::AddGlobalTestEnvironment(new AudioEffectHidlEnvironment);
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  ALOGI("Test result = %d", status);
+  return status;
+}
diff --git a/contexthub/1.0/Android.bp b/contexthub/1.0/Android.bp
new file mode 100644
index 0000000..23c44de
--- /dev/null
+++ b/contexthub/1.0/Android.bp
@@ -0,0 +1,59 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.contexthub@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces android.hardware.contexthub@1.0",
+    srcs: [
+        "types.hal",
+        "IContexthub.hal",
+        "IContexthubCallback.hal",
+    ],
+    out: [
+        "android/hardware/contexthub/1.0/types.cpp",
+        "android/hardware/contexthub/1.0/ContexthubAll.cpp",
+        "android/hardware/contexthub/1.0/ContexthubCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.contexthub@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces android.hardware.contexthub@1.0",
+    srcs: [
+        "types.hal",
+        "IContexthub.hal",
+        "IContexthubCallback.hal",
+    ],
+    out: [
+        "android/hardware/contexthub/1.0/types.h",
+        "android/hardware/contexthub/1.0/IContexthub.h",
+        "android/hardware/contexthub/1.0/IHwContexthub.h",
+        "android/hardware/contexthub/1.0/BnContexthub.h",
+        "android/hardware/contexthub/1.0/BpContexthub.h",
+        "android/hardware/contexthub/1.0/BsContexthub.h",
+        "android/hardware/contexthub/1.0/IContexthubCallback.h",
+        "android/hardware/contexthub/1.0/IHwContexthubCallback.h",
+        "android/hardware/contexthub/1.0/BnContexthubCallback.h",
+        "android/hardware/contexthub/1.0/BpContexthubCallback.h",
+        "android/hardware/contexthub/1.0/BsContexthubCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.contexthub@1.0",
+    generated_sources: ["android.hardware.contexthub@1.0_genc++"],
+    generated_headers: ["android.hardware.contexthub@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.contexthub@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidl",
+        "libhwbinder",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidl",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/contexthub/1.0/Android.mk b/contexthub/1.0/Android.mk
new file mode 100644
index 0000000..72291e6
--- /dev/null
+++ b/contexthub/1.0/Android.mk
@@ -0,0 +1,552 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.contexthub@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+#
+# Build types.hal (AsyncEventType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/AsyncEventType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.AsyncEventType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ContextHub)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/ContextHub.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.ContextHub
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ContextHubMsg)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/ContextHubMsg.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.ContextHubMsg
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubAppInfo)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/HubAppInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.HubAppInfo
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubMemoryFlag)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/HubMemoryFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.HubMemoryFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubMemoryType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/HubMemoryType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.HubMemoryType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MemRange)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/MemRange.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.MemRange
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NanoAppBinary)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/NanoAppBinary.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.NanoAppBinary
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NanoAppFlags)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/NanoAppFlags.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.NanoAppFlags
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PhysicalSensor)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/PhysicalSensor.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.PhysicalSensor
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Result)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/Result.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.Result
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SensorType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/SensorType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.SensorType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TransactionResult)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/TransactionResult.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.TransactionResult
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IContexthub.hal
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/IContexthub.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IContexthub.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::IContexthub
+
+$(GEN): $(LOCAL_PATH)/IContexthub.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IContexthubCallback.hal
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/IContexthubCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::IContexthubCallback
+
+$(GEN): $(LOCAL_PATH)/IContexthubCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.contexthub@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+#
+# Build types.hal (AsyncEventType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/AsyncEventType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.AsyncEventType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ContextHub)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/ContextHub.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.ContextHub
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ContextHubMsg)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/ContextHubMsg.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.ContextHubMsg
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubAppInfo)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/HubAppInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.HubAppInfo
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubMemoryFlag)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/HubMemoryFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.HubMemoryFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubMemoryType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/HubMemoryType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.HubMemoryType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MemRange)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/MemRange.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.MemRange
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NanoAppBinary)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/NanoAppBinary.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.NanoAppBinary
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NanoAppFlags)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/NanoAppFlags.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.NanoAppFlags
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PhysicalSensor)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/PhysicalSensor.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.PhysicalSensor
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Result)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/Result.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.Result
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SensorType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/SensorType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.SensorType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TransactionResult)
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/TransactionResult.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::types.TransactionResult
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IContexthub.hal
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/IContexthub.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IContexthub.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::IContexthub
+
+$(GEN): $(LOCAL_PATH)/IContexthub.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IContexthubCallback.hal
+#
+GEN := $(intermediates)/android/hardware/contexthub/1.0/IContexthubCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava -randroid.hardware:hardware/interfaces \
+        android.hardware.contexthub@1.0::IContexthubCallback
+
+$(GEN): $(LOCAL_PATH)/IContexthubCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/contexthub/1.0/IContexthub.hal b/contexthub/1.0/IContexthub.hal
new file mode 100644
index 0000000..8d19aeb
--- /dev/null
+++ b/contexthub/1.0/IContexthub.hal
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.hardware.contexthub@1.0;
+
+import IContexthubCallback;
+
+interface IContexthub {
+    /*
+     * Enumerate all available context hubs on the system.
+     *
+     * @return hubs list of hubs on this system.
+     */
+    getHubs() generates (vec<ContextHub> hubs);
+
+    /*
+     * Register a callback for the HAL implementation to send asynchronous
+     * messages to the service from a context hub. There can be a maximum of
+     * one callback registered with the HAL. A call to this function when a
+     * callback has already been registered must override the previous
+     * registration.
+     *
+     * @param hubId    identifier for the hub
+     *        callback an implementation of the IContextHubCallbacks
+     *
+     * @return result OK on success
+     *                BAD_VALUE if parameters are not sane
+     *
+     */
+     registerCallback(uint32_t hubId, IContexthubCallback cb) generates (Result result);
+
+    /**
+     * Send a message to a hub
+     *
+     * @param hubId identifier for hub to send message to
+     *        msg   message to be sent
+     *
+     * @return result OK if successful, error code otherwise
+     *                BAD_VALUE if parameters are not sane
+     *                TRANSACTION_FAILED if message send failed
+     */
+    sendMessageToHub(uint32_t hubId, ContextHubMsg msg)
+            generates (Result result);
+
+    /**
+     * Loads a nanoApp. After loading, the nanoApp's init method must be called.
+     * After the init method for nanoApp returns success, this must be indicated
+     * to the service by an asynchronous call to handleTxnResult.
+     *
+     * @param hubId identifer of the contextHub
+     *        appBinary binary for the nanoApp
+     *        msg   message to be sent
+     *
+     * @return result OK if transation started
+     *                BAD_VALUE if parameters are not sane
+     *                TRANSACTION_PENDING if hub is busy with another
+     *                                    load/unload transaction
+     *                TRANSACTION_FAILED if load failed synchronously
+     *
+     */
+    loadNanoApp(uint32_t hubId, NanoAppBinary appBinary, uint32_t transactionId)
+            generates (Result result);
+
+    /**
+     * Unloads a nanoApp. Before the unload, the apps deinit method is called.
+     * After this, success must be indicated to the service through an
+     * asynchronous call to handleTxnResult.
+     *
+     * @param hubId identifer of the contextHub
+     *        appId appIdentifier returned by the HAL
+     *        msg   message to be sent
+     *
+     * @return result OK if transation started
+     *                BAD_VALUE if parameters are not sane
+     *                TRANSACTION_PENDING if hub is busy with another
+     *                                    load/unload transaction
+     *                TRANSACTION_FAILED if unload failed synchronously
+     *
+     */
+    unloadNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId)
+            generates (Result result);
+
+    /**
+     * Enables a nanoApp. The app's init method is called.
+     * After this, success must be indicated to the service through an
+     * asynchronous message.
+     *
+     * @param hubId identifer of the contextHub
+     *        appId appIdentifier returned by the HAL
+     *        msg   message to be sent
+     *
+     * @return result OK if transation started
+     *                BAD_VALUE if parameters are not sane
+     *                TRANSACTION_PENDING if hub is busy with another
+     *                                    load/unload transaction
+     *                FAILED_TRANSACTION if load fails immediately
+     *
+     */
+    enableNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId)
+            generates (Result result);
+
+    /**
+     * Disables a nanoApp. The app's deinit method is called.
+     * After this, success must be indicated to the service through an
+     * asynchronous message.
+     *
+     * @param hubId identifer of the contextHub
+     *        appId appIdentifier returned by the HAL
+     *        msg   message to be sent
+     *
+     * @return result OK if transation started
+     *                BAD_VALUE if parameters are not sane
+     *                TRANSACTION_PENDING if hub is busy with another
+     *                                    load/unload transaction
+     *                FAILED_TRANSACTION if load fails immediately
+     *
+     */
+    disableNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId)
+            generates (Result result);
+
+    /**
+     * Queries for Loaded apps on the hub
+     *
+     * @param hubId identifer of the contextHub
+     *
+     * @return apps all nanoApps on the hub
+     *
+     */
+    queryApps(uint32_t hubId) generates (Result result);
+
+    /**
+     * Reboots context hub OS, restarts all the nanoApps.
+     * No reboot notification is sent to nanoApps; reboot happens immediately
+     * and unconditionally; all volatile contexthub state and any data is lost
+     * as a result.
+     *
+     * @param hubId identifer of the contextHub
+     *
+     * @return result OK on success
+     *                BAD_VALUE if parameters are not sane
+     *
+     */
+    reboot(uint32_t hubId) generates (Result result);
+};
diff --git a/contexthub/1.0/IContexthubCallback.hal b/contexthub/1.0/IContexthubCallback.hal
new file mode 100644
index 0000000..29c41ce
--- /dev/null
+++ b/contexthub/1.0/IContexthubCallback.hal
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.hardware.contexthub@1.0;
+
+interface IContexthubCallback {
+    /*
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send asynchronous messages back
+     * to the service and registered clients of the ContextHub service.
+     *
+     * @params hubId : identifier of the hub calling callback
+     *         msg   : message
+     *
+     */
+     handleClientMsg(uint32_t hubId, ContextHubMsg msg);
+
+    /*
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send the response for a
+     * transaction.
+     *
+     * @params hubId : identifier of the hub calling callback
+     *         txnId : transaction id whose result is being sent
+     *                 passed in by the service at start of transacation.
+     *         result: result of transaction.
+     *
+     */
+     handleTxnResult(uint32_t hubId, uint32_t txnId,
+             TransactionResult result);
+
+    /*
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send an asynchronous event
+     * to the ContextHub service.
+     *
+     * @params hubId : identifier of the hub calling callback
+     *         msg   : message
+     *
+     */
+     handleHubEvent(uint32_t hubId, AsyncEventType evt);
+
+     /*
+      * This callback is passed by the Contexthub service to the HAL
+      * implementation to allow the HAL to send information about the
+      * currently loaded and active nanoapps on the hub.
+      */
+      handleAppsInfo(uint32_t hubId, vec<HubAppInfo> appInfo);
+};
diff --git a/contexthub/1.0/types.hal b/contexthub/1.0/types.hal
new file mode 100644
index 0000000..7d5a1ac
--- /dev/null
+++ b/contexthub/1.0/types.hal
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.hardware.contexthub@1.0;
+
+enum Result : uint32_t {
+    OK,                  // Success
+    BAD_PARAMS,          // Parameters not sane
+    NOT_INIT,            // not initialized
+    TRANSACTION_FAILED,  // transaction failed
+    TRANSACTION_PENDING, // Pending transaction, cannot accept a new request
+};
+
+
+enum NanoAppFlags : uint32_t {
+    SIGNED = (1<<0),   // Signed nanoapp
+    ENCRYPTED = (1<<1),// Encrypted nanoapp
+};
+
+struct NanoAppBinary {
+    uint32_t headerVersion;    // 0x1 for this version
+    uint32_t magic;            // "NANO"
+    uint64_t appId;            // App Id contains vendor id
+    uint32_t appVersion;       // Version of the app
+    uint32_t flags;            // mask of NanoAppFlags
+    uint64_t hwHubType;        // which hub type is this compiled for
+                               // a unique UUID for each h/w + toolchain
+                               // combination.
+    vec<uint8_t> customBinary; // start of custom binary data
+};
+
+enum SensorType : uint32_t {
+    RESERVED,
+    ACCELEROMETER,
+    GYROSCOPE,
+    MAGNETOMETER,
+    BAROMETER,
+    PROXIMITY_SENSOR,
+    AMBIENT_LIGHT_SENSOR,
+
+    GPS = 0x100,
+    // Reserving this space for variants on GPS
+
+    WIFI = 0x200,
+    // Reserving this space for variants on WIFI
+
+    AUDIO = 0x300,
+    // Reserving this space for variants on Audio
+
+    CAMERA = 0x400,
+    // Reserving this space for variants on Camera
+
+    BLE = 0x500,
+
+    PRIVATE_SENSOR_BASE = 0x10000,
+    // Sensor types beyond PRIVATE_SENSOR_BASE are custom types
+};
+
+struct PhysicalSensor{
+    SensorType sensorType;       // From the definitions above eg: 100
+    string type;                 // Type as a string. eg: "GPS"
+    string name;                 // Identifier eg: "Bosch BMI160"
+    string vendor;               // Vendor : eg "STM"
+    uint32_t version;            // Version : eg 0x1001
+    uint32_t fifoReservedCount;  // Batching possible in hardware. Please
+                                 // note that here hardware does not include
+                                 // the context hub itself. Thus, this
+                                 // definition may be different from say the
+                                 // number advertised in the sensors HAL
+                                 // which allows for batching in a hub.
+    uint32_t fifoMaxCount;       // maximum number of batchable events.
+    uint64_t minDelayMs;         // in milliseconds, corresponding to highest
+                                 // sampling freq.
+    uint64_t maxDelayMs;         // in milliseconds, corresponds to minimum
+                                 // sampling frequency
+    float peakPowerMw;           // At max frequency & no batching, power
+                                 // in milliwatts
+};
+
+struct ContextHub {
+    string name;                // descriptive name eg: "Awesome Hub #1"
+    string vendor;              // hub hardware vendor eg: "Qualcomm"
+    string toolchain;           // toolchain to make binaries eg: "gcc ARM"
+    uint32_t platformVersion;   // Version of the hardware : eg 0x20
+    uint32_t toolchainVersion;  // Version of the toolchain : eg: 0x484
+    uint32_t hubId;             // a device unique id for this hub
+
+    float peakMips;             // Peak MIPS platform can deliver
+    float stoppedPowerDrawMw;   // if stopped, retention power, milliwatts
+    float sleepPowerDrawMw;     // if sleeping, retention power, milliwatts
+    float peakPowerDrawMw;      // for a busy CPUm power in milliwatts
+
+    vec<PhysicalSensor> connectedSensors; // array of connected sensors
+
+    uint32_t maxSupportedMsgLen;// This is the maximum size of the message that can
+                                // be sent to the hub in one chunk (in bytes)
+};
+
+struct ContextHubMsg {
+    uint64_t appName; // intended recipient
+    uint32_t msgType; // identifier for message
+    vec<uint8_t> msg; // message body
+};
+
+enum HubMemoryType : uint32_t {
+    MAIN      = 0, // Main memory
+    SECONDARY = 1, // Secondary memory
+    TCM       = 2, // Tightly coupled memory
+};
+
+enum HubMemoryFlag : uint32_t {
+    READ  = (1<<0), // Readable
+    WRITE = (1<<1), // Writable
+    EXEC  = (1<<2), // Executable
+};
+
+struct MemRange {
+    uint32_t totalBytes; // total capacity in bytes
+    uint32_t freeBytes;  // free capacity in bytes
+    HubMemoryType type;  // type of memory, see HubMemoryType
+    uint32_t flags;      // mask of HubMemoryFlag
+};
+
+enum AsyncEventType : uint32_t {
+    RESTARTED = 1, // Hub restarted unexpectedly
+};
+
+enum TransactionResult {
+    SUCCESS,      // successful completion of transaction
+    FAILURE,      // failed transaction
+};
+
+struct HubAppInfo {
+    uint64_t appId;         // Identifier of the app
+    uint32_t version;       // version of the app
+    vec<MemRange> memUsage; // Memory used by this app
+};
+
diff --git a/contexthub/Android.bp b/contexthub/Android.bp
new file mode 100644
index 0000000..bbb3e4b
--- /dev/null
+++ b/contexthub/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+]
diff --git a/graphics/allocator/2.0/IAllocator.hal b/graphics/allocator/2.0/IAllocator.hal
index 8accb82..ff08a7e 100644
--- a/graphics/allocator/2.0/IAllocator.hal
+++ b/graphics/allocator/2.0/IAllocator.hal
@@ -26,11 +26,16 @@
          * is supported.
          */
         TEST_ALLOCATE = 1,
+
+        /*
+         * layerCount must be 1 unless this capability is supported.
+         */
+        LAYERED_BUFFERS = 2,
     };
 
     struct BufferDescriptorInfo {
         /*
-         * The width specifies how many columns of pixels should be in the
+         * The width specifies how many columns of pixels must be in the
          * allocated buffer, but does not necessarily represent the offset in
          * columns between the same column in adjacent rows. The rows may be
          * padded.
@@ -38,11 +43,16 @@
         uint32_t width;
 
        /*
-        * The height specifies how many rows of pixels should be in the
+        * The height specifies how many rows of pixels must be in the
         * allocated buffer.
         */
         uint32_t height;
 
+       /*
+        * The number of image layers that must be in the allocated buffer.
+        */
+        uint32_t layerCount;
+
         /* Buffer pixel format. */
         PixelFormat format;
 
diff --git a/graphics/allocator/2.0/default/Gralloc.cpp b/graphics/allocator/2.0/default/Gralloc.cpp
index a7fc6c1..8a74661 100644
--- a/graphics/allocator/2.0/default/Gralloc.cpp
+++ b/graphics/allocator/2.0/default/Gralloc.cpp
@@ -74,6 +74,7 @@
         GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
         GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
         GRALLOC1_PFN_SET_FORMAT setFormat;
+        GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
         GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
         GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
         GRALLOC1_PFN_ALLOCATE allocate;
@@ -135,6 +136,10 @@
             GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR);
     initDispatch(mDispatch.setDimensions, GRALLOC1_FUNCTION_SET_DIMENSIONS);
     initDispatch(mDispatch.setFormat, GRALLOC1_FUNCTION_SET_FORMAT);
+    if (hasCapability(Capability::LAYERED_BUFFERS)) {
+        initDispatch(
+                mDispatch.setLayerCount, GRALLOC1_FUNCTION_SET_LAYER_COUNT);
+    }
     initDispatch(mDispatch.setConsumerUsage,
             GRALLOC1_FUNCTION_SET_CONSUMER_USAGE);
     initDispatch(mDispatch.setProducerUsage,
@@ -191,6 +196,11 @@
         err = mDispatch.setFormat(mDevice, descriptor,
                 static_cast<int32_t>(descriptorInfo.format));
     }
+    if (err == GRALLOC1_ERROR_NONE &&
+            hasCapability(Capability::LAYERED_BUFFERS)) {
+        err = mDispatch.setLayerCount(mDevice, descriptor,
+                descriptorInfo.layerCount);
+    }
     if (err == GRALLOC1_ERROR_NONE) {
         uint64_t producerUsageMask = descriptorInfo.producerUsageMask;
         if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN) {
diff --git a/graphics/mapper/2.0/default/GrallocMapper.cpp b/graphics/mapper/2.0/default/GrallocMapper.cpp
index eeca5c7..2af1d2c 100644
--- a/graphics/mapper/2.0/default/GrallocMapper.cpp
+++ b/graphics/mapper/2.0/default/GrallocMapper.cpp
@@ -15,10 +15,13 @@
 
 #define LOG_TAG "GrallocMapperPassthrough"
 
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <hardware/gralloc1.h>
 #include <log/log.h>
 
+#include <unordered_set>
+
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -26,6 +29,8 @@
 namespace V2_0 {
 namespace implementation {
 
+using Capability = allocator::V2_0::IAllocator::Capability;
+
 class GrallocDevice : public Device {
 public:
     GrallocDevice();
@@ -38,6 +43,8 @@
             uint32_t* outWidth, uint32_t* outHeight);
     Error getFormat(const native_handle_t* bufferHandle,
             PixelFormat* outFormat);
+    Error getLayerCount(const native_handle_t* bufferHandle,
+            uint32_t* outLayerCount);
     Error getProducerUsageMask(const native_handle_t* bufferHandle,
             uint64_t* outUsageMask);
     Error getConsumerUsageMask(const native_handle_t* bufferHandle,
@@ -58,15 +65,21 @@
             int32_t* outReleaseFence);
 
 private:
+    void initCapabilities();
+
     void initDispatch();
+    bool hasCapability(Capability capability) const;
 
     gralloc1_device_t* mDevice;
 
+    std::unordered_set<Capability> mCapabilities;
+
     struct {
         GRALLOC1_PFN_RETAIN retain;
         GRALLOC1_PFN_RELEASE release;
         GRALLOC1_PFN_GET_DIMENSIONS getDimensions;
         GRALLOC1_PFN_GET_FORMAT getFormat;
+        GRALLOC1_PFN_GET_LAYER_COUNT getLayerCount;
         GRALLOC1_PFN_GET_PRODUCER_USAGE getProducerUsage;
         GRALLOC1_PFN_GET_CONSUMER_USAGE getConsumerUsage;
         GRALLOC1_PFN_GET_BACKING_STORE getBackingStore;
@@ -96,6 +109,7 @@
         LOG_ALWAYS_FATAL("failed to open gralloc1 device");
     }
 
+    initCapabilities();
     initDispatch();
 }
 
@@ -104,6 +118,19 @@
     gralloc1_close(mDevice);
 }
 
+void GrallocDevice::initCapabilities()
+{
+    uint32_t count;
+    mDevice->getCapabilities(mDevice, &count, nullptr);
+
+    std::vector<Capability> caps(count);
+    mDevice->getCapabilities(mDevice, &count, reinterpret_cast<
+              std::underlying_type<Capability>::type*>(caps.data()));
+    caps.resize(count);
+
+    mCapabilities.insert(caps.cbegin(), caps.cend());
+}
+
 void GrallocDevice::initDispatch()
 {
 #define CHECK_FUNC(func, desc) do {                                   \
@@ -118,6 +145,9 @@
     CHECK_FUNC(release, GRALLOC1_FUNCTION_RELEASE);
     CHECK_FUNC(getDimensions, GRALLOC1_FUNCTION_GET_DIMENSIONS);
     CHECK_FUNC(getFormat, GRALLOC1_FUNCTION_GET_FORMAT);
+    if (hasCapability(Capability::LAYERED_BUFFERS)) {
+        CHECK_FUNC(getLayerCount, GRALLOC1_FUNCTION_GET_LAYER_COUNT);
+    }
     CHECK_FUNC(getProducerUsage, GRALLOC1_FUNCTION_GET_PRODUCER_USAGE);
     CHECK_FUNC(getConsumerUsage, GRALLOC1_FUNCTION_GET_CONSUMER_USAGE);
     CHECK_FUNC(getBackingStore, GRALLOC1_FUNCTION_GET_BACKING_STORE);
@@ -130,6 +160,11 @@
 #undef CHECK_FUNC
 }
 
+bool GrallocDevice::hasCapability(Capability capability) const
+{
+    return (mCapabilities.count(capability) > 0);
+}
+
 Error GrallocDevice::retain(const native_handle_t* bufferHandle)
 {
     int32_t error = mDispatch.retain(mDevice, bufferHandle);
@@ -158,6 +193,19 @@
     return static_cast<Error>(error);
 }
 
+Error GrallocDevice::getLayerCount(const native_handle_t* bufferHandle,
+        uint32_t* outLayerCount)
+{
+    if (hasCapability(Capability::LAYERED_BUFFERS)) {
+        int32_t error = mDispatch.getLayerCount(mDevice, bufferHandle,
+                outLayerCount);
+        return static_cast<Error>(error);
+    } else {
+        *outLayerCount = 1;
+        return Error::NONE;
+    }
+}
+
 Error GrallocDevice::getProducerUsageMask(const native_handle_t* bufferHandle,
         uint64_t* outUsageMask)
 {
@@ -238,6 +286,7 @@
         .release = release,
         .getDimensions = getDimensions,
         .getFormat = getFormat,
+        .getLayerCount = getLayerCount,
         .getProducerUsageMask = getProducerUsageMask,
         .getConsumerUsageMask = getConsumerUsageMask,
         .getBackingStore = getBackingStore,
@@ -296,6 +345,12 @@
         return cast(device)->getFormat(bufferHandle, outFormat);
     }
 
+    static Error getLayerCount(Device* device,
+            const native_handle_t* bufferHandle, uint32_t* outLayerCount)
+    {
+        return cast(device)->getLayerCount(bufferHandle, outLayerCount);
+    }
+
     static Error getProducerUsageMask(Device* device,
             const native_handle_t* bufferHandle, uint64_t* outUsageMask)
     {
diff --git a/graphics/mapper/2.0/include/android/hardware/graphics/mapper/2.0/IMapper.h b/graphics/mapper/2.0/include/android/hardware/graphics/mapper/2.0/IMapper.h
index 23faa80..ac8ec45 100644
--- a/graphics/mapper/2.0/include/android/hardware/graphics/mapper/2.0/IMapper.h
+++ b/graphics/mapper/2.0/include/android/hardware/graphics/mapper/2.0/IMapper.h
@@ -128,6 +128,21 @@
                                PixelFormat* outFormat);
 
     /*
+     * Gets the number of layers of the buffer.
+     *
+     * See IAllocator::BufferDescriptorInfo for more information.
+     *
+     * @param device is the mapper device.
+     * @param bufferHandle is the buffer from which to get format.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     * @return layerCount is the number of layers of the buffer.
+     */
+    typedef Error (*getLayerCount)(Device* device,
+                               const native_handle_t* bufferHandle,
+                               uint32_t* outLayerCount);
+
+    /*
      * Gets the producer usage flags which were used to allocate this buffer.
      *
      * See IAllocator::BufferDescriptorInfo for more information.
@@ -364,6 +379,7 @@
     Device::release release;
     Device::getDimensions getDimensions;
     Device::getFormat getFormat;
+    Device::getLayerCount getLayerCount;
     Device::getProducerUsageMask getProducerUsageMask;
     Device::getConsumerUsageMask getConsumerUsageMask;
     Device::getBackingStore getBackingStore;
diff --git a/memtrack/1.0/vts/Android.mk b/memtrack/1.0/vts/Android.mk
new file mode 100644
index 0000000..c0fe968
--- /dev/null
+++ b/memtrack/1.0/vts/Android.mk
@@ -0,0 +1,87 @@
+#
+# Copyright (C) 2016 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)
+
+# build VTS driver for memtrack v1.0.
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libvts_driver_hidl_memtrack@1.0
+
+LOCAL_SRC_FILES := \
+  Memtrack.vts \
+  types.vts \
+
+LOCAL_C_INCLUDES := \
+  android.hardware.memtrack@1.0 \
+  system/core/base/include \
+  system/core/include \
+
+LOCAL_SHARED_LIBRARIES += \
+  android.hardware.memtrack@1.0 \
+  libbase \
+  libutils \
+  libcutils \
+  liblog \
+  libhidl \
+  libhwbinder \
+  libprotobuf-cpp-full \
+  libvts_common \
+  libvts_datatype \
+  libvts_measurement \
+  libvts_multidevice_proto \
+
+LOCAL_CFLAGS += -DENABLE_TREBLE
+
+LOCAL_STATIC_LIBRARIES := \
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := full
+
+LOCAL_MULTILIB := both
+
+include $(BUILD_SHARED_LIBRARY)
+
+# build profiler for memtrack.
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libvts_profiler_hidl_memtrack@1.0
+
+LOCAL_SRC_FILES := \
+  Memtrack.vts \
+  types.vts \
+
+LOCAL_C_INCLUDES += \
+  test/vts/drivers/libprofiling \
+
+LOCAL_VTS_MODE := PROFILER
+
+LOCAL_SHARED_LIBRARIES := \
+   android.hardware.memtrack@1.0 \
+   libbase \
+   libcutils \
+   liblog \
+   libhidl \
+   libhwbinder \
+   libprotobuf-cpp-full \
+   libvts_common \
+   libvts_multidevice_proto \
+   libvts_profiling \
+   libutils \
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := full
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/memtrack/1.0/vts/Memtrack.vts b/memtrack/1.0/vts/Memtrack.vts
new file mode 100644
index 0000000..9fce2a0
--- /dev/null
+++ b/memtrack/1.0/vts/Memtrack.vts
@@ -0,0 +1,33 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IMemtrack"
+
+package: "android.hardware.memtrack"
+
+import: "android.hardware.memtrack@1.0::types"
+
+interface: {
+    api: {
+        name: "getMemory"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::memtrack::V1_0::MemtrackStatus"
+        }
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::memtrack::V1_0::MemtrackRecord"
+            }
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::memtrack::V1_0::MemtrackType"
+        }
+    }
+
+}
diff --git a/memtrack/1.0/vts/types.vts b/memtrack/1.0/vts/types.vts
new file mode 100644
index 0000000..bec090f
--- /dev/null
+++ b/memtrack/1.0/vts/types.vts
@@ -0,0 +1,121 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.memtrack"
+
+
+attribute: {
+    name: "::android::hardware::memtrack::V1_0::MemtrackFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "SMAPS_ACCOUNTED"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "SMAPS_UNACCOUNTED"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "SHARED"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "SHARED_PSS"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "PRIVATE"
+        scalar_value: {
+            uint32_t: 32
+        }
+        enumerator: "SYSTEM"
+        scalar_value: {
+            uint32_t: 64
+        }
+        enumerator: "DEDICATED"
+        scalar_value: {
+            uint32_t: 128
+        }
+        enumerator: "NONSECURE"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "SECURE"
+        scalar_value: {
+            uint32_t: 512
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::memtrack::V1_0::MemtrackType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "OTHER"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "GL"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "GRAPHICS"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "MULTIMEDIA"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "CAMERA"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "NUM_TYPES"
+        scalar_value: {
+            uint32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::memtrack::V1_0::MemtrackStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "SUCCESS"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "MEMORY_TRACKING_NOT_SUPPORTED"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "TYPE_NOT_SUPPORTED"
+        scalar_value: {
+            uint32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::memtrack::V1_0::MemtrackRecord"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sizeInBytes"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "flags"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+