Merge "Refactor VHAL"
diff --git a/audio/2.0/Android.bp b/audio/2.0/Android.bp
index 1643c12..d6e481f 100644
--- a/audio/2.0/Android.bp
+++ b/audio/2.0/Android.bp
@@ -18,6 +18,7 @@
     ],
     interfaces: [
         "android.hardware.audio.common@2.0",
+        "android.hardware.audio.effect@2.0",
         "android.hidl.base@1.0",
     ],
     types: [
diff --git a/audio/2.0/default/Android.mk b/audio/2.0/default/Android.mk
index aa25077..12713d3 100644
--- a/audio/2.0/default/Android.mk
+++ b/audio/2.0/default/Android.mk
@@ -16,45 +16,6 @@
 
 LOCAL_PATH := $(call my-dir)
 
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.audio@2.0-impl
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_SRC_FILES := \
-    Conversions.cpp \
-    Device.cpp \
-    DevicesFactory.cpp \
-    ParametersUtil.cpp \
-    PrimaryDevice.cpp \
-    Stream.cpp \
-    StreamIn.cpp \
-    StreamOut.cpp \
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libcutils \
-    libfmq \
-    libhardware \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    android.hardware.audio@2.0 \
-    android.hardware.audio.common@2.0 \
-    android.hardware.audio.common@2.0-util \
-
-LOCAL_HEADER_LIBRARIES := \
-    libaudioclient_headers \
-    libaudio_system_headers \
-    libhardware_headers \
-    libmedia_headers \
-
-LOCAL_WHOLE_STATIC_LIBRARIES := libmedia_helper
-
-include $(BUILD_SHARED_LIBRARY)
-
 #
 # Service
 #
@@ -79,9 +40,10 @@
     android.hardware.audio.common@2.0 \
     android.hardware.audio.effect@2.0 \
     android.hardware.soundtrigger@2.0 \
-    android.hardware.broadcastradio@1.0 \
-    android.hardware.broadcastradio@1.1
+    android.hardware.soundtrigger@2.1
 
+# Can not switch to Android.bp until AUDIOSERVER_MULTILIB
+# is deprecated as build config variable are not supported
 ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
 LOCAL_MULTILIB := 32
 else
diff --git a/audio/2.0/default/Conversions.cpp b/audio/2.0/default/Conversions.cpp
deleted file mode 100644
index e669185..0000000
--- a/audio/2.0/default/Conversions.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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);
-    const bool isInput = (halDevice & AUDIO_DEVICE_BIT_IN) != 0;
-    if (isInput) halDevice &= ~AUDIO_DEVICE_BIT_IN;
-    if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0)
-            || (isInput && (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 ((!isInput && (halDevice & AUDIO_DEVICE_OUT_IP) != 0)
-            || (isInput && (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 ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_USB) != 0)
-            || (isInput && (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 ((!isInput && (halDevice & AUDIO_DEVICE_OUT_BUS) != 0)
-            || (isInput && (halDevice & AUDIO_DEVICE_IN_BUS) != 0)) {
-        snprintf(halAddress, sizeof(halAddress),
-                "%s", address.busAddress.c_str());
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0
-            || (isInput && (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/Device.h b/audio/2.0/default/Device.h
deleted file mode 100644
index 7738361..0000000
--- a/audio/2.0/default/Device.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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_DEVICE_H
-#define 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::AudioHwSync;
-using ::android::hardware::audio::common::V2_0::AudioInputFlag;
-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::AudioSource;
-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<bool> supportsAudioPatches()  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 hidl_handle& fd)  override;
-
-    // Utility methods for extending interfaces.
-    Result analyzeStatus(const char* funcName, int status);
-    void closeInputStream(audio_stream_in_t* stream);
-    void closeOutputStream(audio_stream_out_t* stream);
-    audio_hw_device_t* device() const { return mDevice; }
-
-  private:
-    audio_hw_device_t *mDevice;
-
-    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  // ANDROID_HARDWARE_AUDIO_V2_0_DEVICE_H
diff --git a/audio/2.0/default/PrimaryDevice.h b/audio/2.0/default/PrimaryDevice.h
deleted file mode 100644
index d95511b..0000000
--- a/audio/2.0/default/PrimaryDevice.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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_PRIMARYDEVICE_H
-#define 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<bool> supportsAudioPatches()  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 hidl_handle& 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  // ANDROID_HARDWARE_AUDIO_V2_0_PRIMARYDEVICE_H
diff --git a/audio/2.0/default/StreamIn.h b/audio/2.0/default/StreamIn.h
deleted file mode 100644
index 950d68f..0000000
--- a/audio/2.0/default/StreamIn.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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_STREAMIN_H
-#define ANDROID_HARDWARE_AUDIO_V2_0_STREAMIN_H
-
-#include <atomic>
-#include <memory>
-
-#include <android/hardware/audio/2.0/IStreamIn.h>
-#include <hidl/MQDescriptor.h>
-#include <fmq/EventFlag.h>
-#include <fmq/MessageQueue.h>
-#include <hidl/Status.h>
-#include <utils/Thread.h>
-
-#include "Device.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 {
-    typedef MessageQueue<ReadParameters, kSynchronizedReadWrite> CommandMQ;
-    typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
-    typedef MessageQueue<ReadStatus, kSynchronizedReadWrite> StatusMQ;
-
-    StreamIn(const sp<Device>& 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 hidl_handle& fd)  override;
-    Return<Result> close()  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> prepareForReading(
-            uint32_t frameSize, uint32_t framesCount, prepareForReading_cb _hidl_cb)  override;
-    Return<uint32_t> getInputFramesLost()  override;
-    Return<void> getCapturePosition(getCapturePosition_cb _hidl_cb)  override;
-    Return<Result> start() override;
-    Return<Result> stop() override;
-    Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
-    Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
-
-    static Result getCapturePositionImpl(
-            audio_stream_in_t *stream, uint64_t *frames, uint64_t *time);
-
-  private:
-    bool mIsClosed;
-    const sp<Device> mDevice;
-    audio_stream_in_t *mStream;
-    const sp<Stream> mStreamCommon;
-    const sp<StreamMmap<audio_stream_in_t>> mStreamMmap;
-    std::unique_ptr<CommandMQ> mCommandMQ;
-    std::unique_ptr<DataMQ> mDataMQ;
-    std::unique_ptr<StatusMQ> mStatusMQ;
-    EventFlag* mEfGroup;
-    std::atomic<bool> mStopReadThread;
-    sp<Thread> mReadThread;
-
-    virtual ~StreamIn();
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_AUDIO_V2_0_STREAMIN_H
diff --git a/audio/2.0/default/StreamOut.h b/audio/2.0/default/StreamOut.h
deleted file mode 100644
index 99352bc..0000000
--- a/audio/2.0/default/StreamOut.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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_STREAMOUT_H
-#define ANDROID_HARDWARE_AUDIO_V2_0_STREAMOUT_H
-
-#include <atomic>
-#include <memory>
-
-#include <android/hardware/audio/2.0/IStreamOut.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-#include <fmq/EventFlag.h>
-#include <fmq/MessageQueue.h>
-#include <utils/Thread.h>
-
-#include "Device.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 {
-    typedef MessageQueue<WriteCommand, kSynchronizedReadWrite> CommandMQ;
-    typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
-    typedef MessageQueue<WriteStatus, kSynchronizedReadWrite> StatusMQ;
-
-    StreamOut(const sp<Device>& 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 hidl_handle& fd)  override;
-    Return<Result> close()  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> prepareForWriting(
-            uint32_t frameSize, uint32_t framesCount, prepareForWriting_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<Result> clearCallback()  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;
-    Return<Result> start() override;
-    Return<Result> stop() override;
-    Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
-    Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
-
-    static Result getPresentationPositionImpl(
-            audio_stream_out_t *stream, uint64_t *frames, TimeSpec *timeStamp);
-
-  private:
-    bool mIsClosed;
-    const sp<Device> mDevice;
-    audio_stream_out_t *mStream;
-    const sp<Stream> mStreamCommon;
-    const sp<StreamMmap<audio_stream_out_t>> mStreamMmap;
-    sp<IStreamOutCallback> mCallback;
-    std::unique_ptr<CommandMQ> mCommandMQ;
-    std::unique_ptr<DataMQ> mDataMQ;
-    std::unique_ptr<StatusMQ> mStatusMQ;
-    EventFlag* mEfGroup;
-    std::atomic<bool> mStopWriteThread;
-    sp<Thread> mWriteThread;
-
-    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  // ANDROID_HARDWARE_AUDIO_V2_0_STREAMOUT_H
diff --git a/audio/2.0/default/service.cpp b/audio/2.0/default/service.cpp
index a215108..3cf7134 100644
--- a/audio/2.0/default/service.cpp
+++ b/audio/2.0/default/service.cpp
@@ -16,11 +16,12 @@
 
 #define LOG_TAG "audiohalservice"
 
-#include <hidl/HidlTransportSupport.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>
+#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
 
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
@@ -28,7 +29,8 @@
 
 using android::hardware::audio::effect::V2_0::IEffectsFactory;
 using android::hardware::audio::V2_0::IDevicesFactory;
-using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
+using V2_0_ISoundTriggerHw = android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
+using V2_1_ISoundTriggerHw = android::hardware::soundtrigger::V2_1::ISoundTriggerHw;
 using android::hardware::registerPassthroughServiceImplementation;
 
 using android::OK;
@@ -41,8 +43,10 @@
     status = registerPassthroughServiceImplementation<IEffectsFactory>();
     LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio effects service: %d", status);
     // Soundtrigger might be not present.
-    status = registerPassthroughServiceImplementation<ISoundTriggerHw>();
-    ALOGE_IF(status != OK, "Error while registering soundtrigger service: %d", status);
+    status = registerPassthroughServiceImplementation<V2_1_ISoundTriggerHw>();
+    ALOGW_IF(status != OK, "Registering soundtrigger V2.1 service was unsuccessful: %d", status);
+    status = registerPassthroughServiceImplementation<V2_0_ISoundTriggerHw>();
+    ALOGW_IF(status != OK, "Registering soundtrigger V2.0 service was unsuccessful: %d", status);
     joinRpcThreadpool();
     return status;
 }
diff --git a/audio/README b/audio/README
new file mode 100644
index 0000000..2b81450
--- /dev/null
+++ b/audio/README
@@ -0,0 +1,47 @@
+Directory structure of the audio HIDL related code.
+
+audio
+|-- 2.0              <== legacy 2.0 core HIDL (.hal) can not be moved to fit
+|                        the directory structure because already published
+|
+|-- common           <== code common to audio core and effect API
+|   |-- 2.0
+|   |   |-- default  <== code that wraps the legacy API
+|   |   `-- vts      <== vts of 2.0 core and effect API common code
+|   |-- 4.0
+|   |   |-- default
+|   |   `-- vts
+|   |-- ...          <== The future versions should continue this structure
+|   |   |-- default
+|   |   `-- vts
+|   `-- all_versions <== code common to all version of both core and effect API
+|       |-- default
+|       `-- vts      <== vts of core and effect API common version independent code
+|
+|-- core           <== code relative to the core API
+|   |-- 2.0          <== 2.0 core API code (except .hal, see audio/2.0)
+|   |   |-- default
+|   |   `-- vts
+|   |-- 4.0
+|   |   |-- default  <== default implementation of the core 4.0 api
+|   |   `-- vts      <== vts code of the 4.0 API
+|   |-- ...
+|   |   |-- default
+|   |   `-- vts
+|   `-- all_versions
+|       |-- default
+|       `-- vts      <== vts of core API common version independent code
+|
+`-- effect           <== idem for the effect API
+    |-- 2.0
+    |   |-- default
+    |   `-- vts
+    |-- 4.0
+    |   |-- default
+    |   `-- vts
+    |-- ...
+    |   |-- default
+    |   `-- vts
+    `-- all_versions
+        |-- default
+        `-- vts
diff --git a/audio/common/2.0/default/Android.bp b/audio/common/2.0/default/Android.bp
index 82b38c0..ac66479 100644
--- a/audio/common/2.0/default/Android.bp
+++ b/audio/common/2.0/default/Android.bp
@@ -21,18 +21,24 @@
         enabled: true,
     },
     srcs: [
-        "EffectMap.cpp",
         "HidlUtils.cpp",
     ],
 
     export_include_dirs: ["."],
 
+    static_libs: [
+    ],
+
     shared_libs: [
         "liblog",
         "libutils",
         "libhidlbase",
+        "android.hardware.audio.common-util",
         "android.hardware.audio.common@2.0",
     ],
+    export_shared_lib_headers: [
+        "android.hardware.audio.common-util"
+    ],
 
     header_libs: [
         "libaudio_system_headers",
diff --git a/audio/common/2.0/default/HidlUtils.cpp b/audio/common/2.0/default/HidlUtils.cpp
index 79cb37c..9771b7b 100644
--- a/audio/common/2.0/default/HidlUtils.cpp
+++ b/audio/common/2.0/default/HidlUtils.cpp
@@ -14,324 +14,8 @@
  * limitations under the License.
  */
 
-#include <string.h>
-
 #include "HidlUtils.h"
 
-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::AudioGainMode;
-using ::android::hardware::audio::common::V2_0::AudioMixLatencyClass;
-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::common::V2_0::AudioUsage;
-
-namespace android {
-
-void HidlUtils::audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config) {
-    config->sampleRateHz = halConfig.sample_rate;
-    config->channelMask = AudioChannelMask(halConfig.channel_mask);
-    config->format = AudioFormat(halConfig.format);
-    audioOffloadInfoFromHal(halConfig.offload_info, &config->offloadInfo);
-    config->frameCount = halConfig.frame_count;
-}
-
-void HidlUtils::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;
-}
-
-void HidlUtils::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;
-}
-
-void HidlUtils::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;
-}
-
-void HidlUtils::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;
-}
-
-void HidlUtils::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;
-}
-
-void HidlUtils::audioOffloadInfoFromHal(
-        const audio_offload_info_t& halOffload, AudioOffloadInfo* offload) {
-    offload->sampleRateHz = halOffload.sample_rate;
-    offload->channelMask = AudioChannelMask(halOffload.channel_mask);
-    offload->format = AudioFormat(halOffload.format);
-    offload->streamType = AudioStreamType(halOffload.stream_type);
-    offload->bitRatePerSecond = halOffload.bit_rate;
-    offload->durationMicroseconds = halOffload.duration_us;
-    offload->hasVideo = halOffload.has_video;
-    offload->isStreaming = halOffload.is_streaming;
-    offload->bitWidth = halOffload.bit_width;
-    offload->bufferSize = halOffload.offload_buffer_size;
-    offload->usage = static_cast<AudioUsage>(halOffload.usage);
-}
-
-void HidlUtils::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->format = static_cast<audio_format_t>(offload.format);
-    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;
-    halOffload->bit_width = offload.bitWidth;
-    halOffload->offload_buffer_size = offload.bufferSize;
-    halOffload->usage = static_cast<audio_usage_t>(offload.usage);
-}
-
-void HidlUtils::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;
-        }
-    }
-}
-
-void HidlUtils::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;
-        }
-    }
-}
-
-void HidlUtils::audioPortConfigsFromHal(
-        unsigned int numHalConfigs, const struct audio_port_config *halConfigs,
-        hidl_vec<AudioPortConfig> *configs) {
-    configs->resize(numHalConfigs);
-    for (unsigned int i = 0; i < numHalConfigs; ++i) {
-        audioPortConfigFromHal(halConfigs[i], &(*configs)[i]);
-    }
-}
-
-std::unique_ptr<audio_port_config[]> HidlUtils::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;
-}
-
-void HidlUtils::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;
-        }
-    }
-}
-
-void HidlUtils::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;
-        }
-    }
-}
-
-void HidlUtils::uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid) {
-    uuid->timeLow = halUuid.timeLow;
-    uuid->timeMid = halUuid.timeMid;
-    uuid->versionAndTimeHigh = halUuid.timeHiAndVersion;
-    uuid->variantAndClockSeqHigh = halUuid.clockSeq;
-    memcpy(uuid->node.data(), halUuid.node, uuid->node.size());
-}
-
-void HidlUtils::uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid) {
-    halUuid->timeLow = uuid.timeLow;
-    halUuid->timeMid = uuid.timeMid;
-    halUuid->timeHiAndVersion = uuid.versionAndTimeHigh;
-    halUuid->clockSeq = uuid.variantAndClockSeqHigh;
-    memcpy(halUuid->node, uuid.node.data(), uuid.node.size());
-}
-
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <common/all-versions/default/HidlUtils.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/common/2.0/default/HidlUtils.h b/audio/common/2.0/default/HidlUtils.h
index 3fde4d7..24543b1 100644
--- a/audio/common/2.0/default/HidlUtils.h
+++ b/audio/common/2.0/default/HidlUtils.h
@@ -17,51 +17,10 @@
 #ifndef android_hardware_audio_V2_0_Hidl_Utils_H_
 #define android_hardware_audio_V2_0_Hidl_Utils_H_
 
-#include <memory>
-
 #include <android/hardware/audio/common/2.0/types.h>
-#include <system/audio.h>
 
-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::AudioOffloadInfo;
-using ::android::hardware::audio::common::V2_0::AudioPort;
-using ::android::hardware::audio::common::V2_0::AudioPortConfig;
-using ::android::hardware::audio::common::V2_0::Uuid;
-using ::android::hardware::hidl_vec;
-
-namespace android {
-
-class HidlUtils {
-  public:
-    static void audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config);
-    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 audioOffloadInfoFromHal(
-            const audio_offload_info_t& halOffload, AudioOffloadInfo* offload);
-    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 void audioPortConfigsFromHal(
-            unsigned int numHalConfigs, const struct audio_port_config *halConfigs,
-            hidl_vec<AudioPortConfig> *configs);
-    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);
-    static void uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid);
-    static void uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid);
-};
-
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <common/all-versions/default/HidlUtils.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // android_hardware_audio_V2_0_Hidl_Utils_H_
diff --git a/audio/common/README b/audio/common/README
new file mode 100644
index 0000000..cd03106
--- /dev/null
+++ b/audio/common/README
@@ -0,0 +1 @@
+This folder contains code common to audio core and effect API
diff --git a/audio/common/2.0/default/OWNERS b/audio/common/all-versions/OWNERS
similarity index 100%
copy from audio/common/2.0/default/OWNERS
copy to audio/common/all-versions/OWNERS
diff --git a/audio/common/all-versions/README b/audio/common/all-versions/README
new file mode 100644
index 0000000..d8df022
--- /dev/null
+++ b/audio/common/all-versions/README
@@ -0,0 +1 @@
+This folder contains code common to all versions of the audio API
diff --git a/audio/common/all-versions/default/Android.bp b/audio/common/all-versions/default/Android.bp
new file mode 100644
index 0000000..8f6b74c
--- /dev/null
+++ b/audio/common/all-versions/default/Android.bp
@@ -0,0 +1,39 @@
+//
+// 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_library_shared {
+    name: "android.hardware.audio.common-util",
+    defaults: ["hidl_defaults"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "EffectMap.cpp",
+    ],
+
+    export_include_dirs: ["include"],
+
+    shared_libs: [
+        "liblog",
+        "libutils",
+        "libhidlbase",
+    ],
+
+    header_libs: [
+        "libaudio_system_headers",
+        "libhardware_headers",
+    ],
+}
diff --git a/audio/common/2.0/default/EffectMap.cpp b/audio/common/all-versions/default/EffectMap.cpp
similarity index 96%
rename from audio/common/2.0/default/EffectMap.cpp
rename to audio/common/all-versions/default/EffectMap.cpp
index 703b91c..7f8da1e 100644
--- a/audio/common/2.0/default/EffectMap.cpp
+++ b/audio/common/all-versions/default/EffectMap.cpp
@@ -16,7 +16,7 @@
 
 #include <atomic>
 
-#include "EffectMap.h"
+#include "common/all-versions/default/EffectMap.h"
 
 namespace android {
 
diff --git a/audio/common/2.0/default/EffectMap.h b/audio/common/all-versions/default/include/common/all-versions/default/EffectMap.h
similarity index 86%
rename from audio/common/2.0/default/EffectMap.h
rename to audio/common/all-versions/default/include/common/all-versions/default/EffectMap.h
index 82bbb1f..547c6d5 100644
--- a/audio/common/2.0/default/EffectMap.h
+++ b/audio/common/all-versions/default/include/common/all-versions/default/EffectMap.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef android_hardware_audio_V2_0_EffectMap_H_
-#define android_hardware_audio_V2_0_EffectMap_H_
+#ifndef android_hardware_audio_common_EffectMap_H_
+#define android_hardware_audio_common_EffectMap_H_
 
 #include <mutex>
 
@@ -27,14 +27,14 @@
 
 // This class needs to be in 'android' ns because Singleton macros require that.
 class EffectMap : public Singleton<EffectMap> {
-  public:
+   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:
+   private:
     static uint64_t makeUniqueId();
 
     std::mutex mLock;
@@ -43,4 +43,4 @@
 
 }  // namespace android
 
-#endif  // android_hardware_audio_V2_0_EffectMap_H_
+#endif  // android_hardware_audio_common_EffectMap_H_
diff --git a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.h
new file mode 100644
index 0000000..1654ac6
--- /dev/null
+++ b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.h
@@ -0,0 +1,73 @@
+/*
+ * 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 AUDIO_HAL_VERSION
+#error "AUDIO_HAL_VERSION must be set before including this file."
+#endif
+
+#include <memory>
+
+#include <system/audio.h>
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioConfig;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioGain;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioGainConfig;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioOffloadInfo;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPort;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPortConfig;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::Uuid;
+using ::android::hardware::hidl_vec;
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace common {
+namespace AUDIO_HAL_VERSION {
+
+class HidlUtils {
+   public:
+    static void audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config);
+    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 audioOffloadInfoFromHal(const audio_offload_info_t& halOffload,
+                                        AudioOffloadInfo* offload);
+    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 void audioPortConfigsFromHal(unsigned int numHalConfigs,
+                                        const struct audio_port_config* halConfigs,
+                                        hidl_vec<AudioPortConfig>* configs);
+    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);
+    static void uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid);
+    static void uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid);
+};
+
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h
new file mode 100644
index 0000000..935f307
--- /dev/null
+++ b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h
@@ -0,0 +1,346 @@
+/*
+ * 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 AUDIO_HAL_VERSION
+#error "AUDIO_HAL_VERSION must be set before including this file."
+#endif
+
+#include <string.h>
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioFormat;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioGainMode;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMixLatencyClass;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPortConfigMask;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPortRole;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPortType;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioStreamType;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioUsage;
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace common {
+namespace AUDIO_HAL_VERSION {
+
+void HidlUtils::audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config) {
+    config->sampleRateHz = halConfig.sample_rate;
+    config->channelMask = AudioChannelMask(halConfig.channel_mask);
+    config->format = AudioFormat(halConfig.format);
+    audioOffloadInfoFromHal(halConfig.offload_info, &config->offloadInfo);
+    config->frameCount = halConfig.frame_count;
+}
+
+void HidlUtils::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;
+}
+
+void HidlUtils::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;
+}
+
+void HidlUtils::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;
+}
+
+void HidlUtils::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;
+}
+
+void HidlUtils::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;
+}
+
+void HidlUtils::audioOffloadInfoFromHal(const audio_offload_info_t& halOffload,
+                                        AudioOffloadInfo* offload) {
+    offload->sampleRateHz = halOffload.sample_rate;
+    offload->channelMask = AudioChannelMask(halOffload.channel_mask);
+    offload->format = AudioFormat(halOffload.format);
+    offload->streamType = AudioStreamType(halOffload.stream_type);
+    offload->bitRatePerSecond = halOffload.bit_rate;
+    offload->durationMicroseconds = halOffload.duration_us;
+    offload->hasVideo = halOffload.has_video;
+    offload->isStreaming = halOffload.is_streaming;
+    offload->bitWidth = halOffload.bit_width;
+    offload->bufferSize = halOffload.offload_buffer_size;
+    offload->usage = static_cast<AudioUsage>(halOffload.usage);
+}
+
+void HidlUtils::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->format = static_cast<audio_format_t>(offload.format);
+    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;
+    halOffload->bit_width = offload.bitWidth;
+    halOffload->offload_buffer_size = offload.bufferSize;
+    halOffload->usage = static_cast<audio_usage_t>(offload.usage);
+}
+
+void HidlUtils::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;
+        }
+    }
+}
+
+void HidlUtils::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;
+        }
+    }
+}
+
+void HidlUtils::audioPortConfigsFromHal(unsigned int numHalConfigs,
+                                        const struct audio_port_config* halConfigs,
+                                        hidl_vec<AudioPortConfig>* configs) {
+    configs->resize(numHalConfigs);
+    for (unsigned int i = 0; i < numHalConfigs; ++i) {
+        audioPortConfigFromHal(halConfigs[i], &(*configs)[i]);
+    }
+}
+
+std::unique_ptr<audio_port_config[]> HidlUtils::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;
+}
+
+void HidlUtils::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;
+        }
+    }
+}
+
+void HidlUtils::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;
+        }
+    }
+}
+
+void HidlUtils::uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid) {
+    uuid->timeLow = halUuid.timeLow;
+    uuid->timeMid = halUuid.timeMid;
+    uuid->versionAndTimeHigh = halUuid.timeHiAndVersion;
+    uuid->variantAndClockSeqHigh = halUuid.clockSeq;
+    memcpy(uuid->node.data(), halUuid.node, uuid->node.size());
+}
+
+void HidlUtils::uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid) {
+    halUuid->timeLow = uuid.timeLow;
+    halUuid->timeMid = uuid.timeMid;
+    halUuid->timeHiAndVersion = uuid.versionAndTimeHigh;
+    halUuid->clockSeq = uuid.variantAndClockSeqHigh;
+    memcpy(halUuid->node, uuid.node.data(), uuid.node.size());
+}
+
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/common/all-versions/test/OWNERS b/audio/common/all-versions/test/OWNERS
new file mode 100644
index 0000000..6a26ae7
--- /dev/null
+++ b/audio/common/all-versions/test/OWNERS
@@ -0,0 +1,2 @@
+yim@google.com
+zhuoyao@google.com
diff --git a/audio/common/test/utility/Android.bp b/audio/common/all-versions/test/utility/Android.bp
similarity index 100%
rename from audio/common/test/utility/Android.bp
rename to audio/common/all-versions/test/utility/Android.bp
diff --git a/audio/common/test/utility/include/utility/AssertOk.h b/audio/common/all-versions/test/utility/include/utility/AssertOk.h
similarity index 88%
rename from audio/common/test/utility/include/utility/AssertOk.h
rename to audio/common/all-versions/test/utility/include/utility/AssertOk.h
index d8aa451..11e1c24 100644
--- a/audio/common/test/utility/include/utility/AssertOk.h
+++ b/audio/common/all-versions/test/utility/include/utility/AssertOk.h
@@ -17,7 +17,7 @@
 #define ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_ASSERTOK_H
 
 #include <algorithm>
-#include <vector>
+#include <initializer_list>
 
 #include <hidl/Status.h>
 
@@ -33,7 +33,6 @@
 // This is a detail namespace, thus it is OK to import a class as nobody else is
 // allowed to use it
 using ::android::hardware::Return;
-using ::android::hardware::audio::V2_0::Result;
 
 template <class T>
 inline ::testing::AssertionResult assertIsOk(const char* expr, const Return<T>& ret) {
@@ -50,6 +49,7 @@
 }
 
 // Expect two equal Results
+template <class Result>
 inline ::testing::AssertionResult assertResult(const char* e_expr, const char* r_expr,
                                                Result expected, Result result) {
     return ::testing::AssertionResult(expected == result)
@@ -58,6 +58,7 @@
 }
 
 // Expect two equal Results one being wrapped in an OK Return
+template <class Result>
 inline ::testing::AssertionResult assertResult(const char* e_expr, const char* r_expr,
                                                Result expected, const Return<Result>& ret) {
     return continueIfIsOk(r_expr, ret,
@@ -65,8 +66,10 @@
 }
 
 // Expect a Result to be part of a list of Results
+template <class Result>
 inline ::testing::AssertionResult assertResult(const char* e_expr, const char* r_expr,
-                                               const std::vector<Result>& expected, Result result) {
+                                               const std::initializer_list<Result>& expected,
+                                               Result result) {
     if (std::find(expected.begin(), expected.end(), result) != expected.end()) {
         return ::testing::AssertionSuccess();  // result is in expected
     }
@@ -77,8 +80,9 @@
 }
 
 // Expect a Result wrapped in an OK Return to be part of a list of Results
+template <class Result>
 inline ::testing::AssertionResult assertResult(const char* e_expr, const char* r_expr,
-                                               const std::vector<Result>& expected,
+                                               const std::initializer_list<Result>& expected,
                                                const Return<Result>& ret) {
     return continueIfIsOk(r_expr, ret,
                           [&] { return assertResult(e_expr, r_expr, expected, Result{ret}); });
@@ -88,15 +92,17 @@
     return assertIsOk(expr, ret);
 }
 
+template <class Result>
 inline ::testing::AssertionResult assertOk(const char* expr, Result result) {
     return ::testing::AssertionResult(result == Result::OK)
            << "Expected success: " << expr << "\nActual: " << ::testing::PrintToString(result);
 }
 
+template <class Result>
 inline ::testing::AssertionResult assertOk(const char* expr, const Return<Result>& ret) {
     return continueIfIsOk(expr, ret, [&] { return assertOk(expr, Result{ret}); });
 }
-}
+}  // namespace detail
 
 #define ASSERT_IS_OK(ret) ASSERT_PRED_FORMAT1(detail::assertIsOk, ret)
 #define EXPECT_IS_OK(ret) EXPECT_PRED_FORMAT1(detail::assertIsOk, ret)
@@ -108,11 +114,11 @@
 #define ASSERT_RESULT(expected, ret) ASSERT_PRED_FORMAT2(detail::assertResult, expected, ret)
 #define EXPECT_RESULT(expected, ret) EXPECT_PRED_FORMAT2(detail::assertResult, expected, ret)
 
-}  // utility
-}  // test
-}  // common
-}  // audio
-}  // test
-}  // utility
+}  // namespace utility
+}  // namespace test
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
 
 #endif  // ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_ASSERTOK_H
diff --git a/audio/common/test/utility/include/utility/Documentation.h b/audio/common/all-versions/test/utility/include/utility/Documentation.h
similarity index 93%
rename from audio/common/test/utility/include/utility/Documentation.h
rename to audio/common/all-versions/test/utility/include/utility/Documentation.h
index a45cad6..e10cf79 100644
--- a/audio/common/test/utility/include/utility/Documentation.h
+++ b/audio/common/all-versions/test/utility/include/utility/Documentation.h
@@ -60,11 +60,11 @@
 }
 }  // namespace doc
 
-}  // utility
-}  // test
-}  // common
-}  // audio
-}  // test
-}  // utility
+}  // namespace utility
+}  // namespace test
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
 
 #endif  // ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_ENVIRONMENT_TEARDOWN
diff --git a/audio/common/test/utility/include/utility/EnvironmentTearDown.h b/audio/common/all-versions/test/utility/include/utility/EnvironmentTearDown.h
similarity index 85%
rename from audio/common/test/utility/include/utility/EnvironmentTearDown.h
rename to audio/common/all-versions/test/utility/include/utility/EnvironmentTearDown.h
index 15b0bd8..a96d06e 100644
--- a/audio/common/test/utility/include/utility/EnvironmentTearDown.h
+++ b/audio/common/all-versions/test/utility/include/utility/EnvironmentTearDown.h
@@ -20,6 +20,7 @@
 #include <functional>
 #include <list>
 
+#include <VtsHalHidlTargetTestEnvBase.h>
 #include <gtest/gtest.h>
 
 namespace android {
@@ -33,13 +34,13 @@
  * Avoid destroying static objects after main return.
  * Post main return destruction leads to incorrect gtest timing measurements as
  * well as harder debuging if anything goes wrong during destruction. */
-class Environment : public ::testing::Environment {
+class Environment : public ::testing::VtsHalHidlTargetTestEnvBase {
    public:
     using TearDownFunc = std::function<void()>;
     void registerTearDown(TearDownFunc&& tearDown) { tearDowns.push_back(std::move(tearDown)); }
 
    private:
-    void TearDown() override {
+    void HidlTearDown() override {
         // Call the tear downs in reverse order of insertion
         for (auto& tearDown : tearDowns) {
             tearDown();
@@ -48,11 +49,11 @@
     std::list<TearDownFunc> tearDowns;
 };
 
-}  // utility
-}  // test
-}  // common
-}  // audio
-}  // test
-}  // utility
+}  // namespace utility
+}  // namespace test
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
 
 #endif  // ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_ENVIRONMENT_TEARDOWN_H
diff --git a/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h b/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h
new file mode 100644
index 0000000..88a67e0
--- /dev/null
+++ b/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 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 AUDIO_HAL_VERSION
+#error "AUDIO_HAL_VERSION must be set before including this file."
+#endif
+
+#ifndef ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_PRETTY_PRINT_AUDIO_TYPES_H
+#define ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_PRETTY_PRINT_AUDIO_TYPES_H
+
+#include <iosfwd>
+#include <utility>
+
+/** @file Use HIDL generated toString methods to pretty print gtest errors
+ *        Unfortunately Gtest does not offer a template to specialize, only
+ *        overloading PrintTo.
+ *  @note that this overload can NOT be template because
+ *        the fallback is already template, resulting in ambiguity.
+ *  @note that the overload MUST be in the exact namespace
+ *        the type is declared in, as per the ADL rules.
+ */
+
+namespace android {
+namespace hardware {
+namespace audio {
+
+#define DEFINE_GTEST_PRINT_TO(T) \
+    inline void PrintTo(const T& val, ::std::ostream* os) { *os << toString(val); }
+
+namespace AUDIO_HAL_VERSION {
+DEFINE_GTEST_PRINT_TO(Result)
+}  // namespace AUDIO_HAL_VERSION
+
+namespace common {
+namespace AUDIO_HAL_VERSION {
+DEFINE_GTEST_PRINT_TO(AudioConfig)
+DEFINE_GTEST_PRINT_TO(AudioDevice)
+DEFINE_GTEST_PRINT_TO(AudioChannelMask)
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace common
+
+#undef DEFINE_GTEST_PRINT_TO
+
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_PRETTY_PRINT_AUDIO_TYPES_H
diff --git a/audio/common/test/utility/include/utility/ReturnIn.h b/audio/common/all-versions/test/utility/include/utility/ReturnIn.h
similarity index 94%
rename from audio/common/test/utility/include/utility/ReturnIn.h
rename to audio/common/all-versions/test/utility/include/utility/ReturnIn.h
index 08d502f..2b92a21 100644
--- a/audio/common/test/utility/include/utility/ReturnIn.h
+++ b/audio/common/all-versions/test/utility/include/utility/ReturnIn.h
@@ -65,11 +65,11 @@
     return {ts...};
 }
 
-}  // utility
-}  // test
-}  // common
-}  // audio
-}  // test
-}  // utility
+}  // namespace utility
+}  // namespace test
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
 
 #endif  // ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_RETURN_IN_H
diff --git a/audio/common/test/utility/include/utility/ValidateXml.h b/audio/common/all-versions/test/utility/include/utility/ValidateXml.h
similarity index 95%
rename from audio/common/test/utility/include/utility/ValidateXml.h
rename to audio/common/all-versions/test/utility/include/utility/ValidateXml.h
index d718839..95080d1 100644
--- a/audio/common/test/utility/include/utility/ValidateXml.h
+++ b/audio/common/all-versions/test/utility/include/utility/ValidateXml.h
@@ -70,11 +70,11 @@
         ::android::hardware::audio::common::test::utility::validateXmlMultipleLocations,    \
         xmlFileName, xmlFileLocations, xsdFilePath)
 
-}  // utility
-}  // test
-}  // common
-}  // audio
-}  // test
-}  // utility
+}  // namespace utility
+}  // namespace test
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
 
 #endif  // ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_VALIDATE_XML_H
diff --git a/audio/common/test/utility/src/ValidateXml.cpp b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
similarity index 97%
rename from audio/common/test/utility/src/ValidateXml.cpp
rename to audio/common/all-versions/test/utility/src/ValidateXml.cpp
index 30dec30..5030af5 100644
--- a/audio/common/test/utility/src/ValidateXml.cpp
+++ b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
@@ -163,9 +163,9 @@
            << "\n                 Which is: " << ::testing::PrintToString(xmlFileLocations);
 }
 
-}  // utility
-}  // test
-}  // common
-}  // audio
-}  // test
-}  // utility
+}  // namespace utility
+}  // namespace test
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/common/all-versions/util/Android.bp b/audio/common/all-versions/util/Android.bp
new file mode 100644
index 0000000..5d33a3a
--- /dev/null
+++ b/audio/common/all-versions/util/Android.bp
@@ -0,0 +1,10 @@
+cc_library_headers {
+    name: "android.hardware.audio.common.util@all-versions",
+    defaults: ["hidl_defaults"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+
+    export_include_dirs: ["include"],
+}
diff --git a/audio/common/all-versions/util/include/common/all-versions/IncludeGuard.h b/audio/common/all-versions/util/include/common/all-versions/IncludeGuard.h
new file mode 100644
index 0000000..2d54816
--- /dev/null
+++ b/audio/common/all-versions/util/include/common/all-versions/IncludeGuard.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 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 AUDIO_HAL_VERSION
+#error "AUDIO_HAL_VERSION must be set before including this file."
+#endif
diff --git a/audio/common/test/OWNERS b/audio/common/test/OWNERS
deleted file mode 100644
index 8711a9f..0000000
--- a/audio/common/test/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-elaurent@google.com
-krocard@google.com
-mnaganov@google.com
-yim@google.com
-zhuoyao@google.com
\ No newline at end of file
diff --git a/audio/common/test/utility/OWNERS b/audio/common/test/utility/OWNERS
deleted file mode 100644
index 6fdc97c..0000000
--- a/audio/common/test/utility/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-elaurent@google.com
-krocard@google.com
-mnaganov@google.com
diff --git a/audio/common/test/utility/include/utility/PrettyPrintAudioTypes.h b/audio/common/test/utility/include/utility/PrettyPrintAudioTypes.h
deleted file mode 100644
index 37059e7..0000000
--- a/audio/common/test/utility/include/utility/PrettyPrintAudioTypes.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2017 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_COMMON_TEST_UTILITY_PRETTY_PRINT_AUDIO_TYPES_H
-#define ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_PRETTY_PRINT_AUDIO_TYPES_H
-
-#include <iosfwd>
-#include <type_traits>
-
-#include <android/hardware/audio/2.0/types.h>
-#include <android/hardware/audio/common/2.0/types.h>
-
-/** @file Use HIDL generated toString methods to pretty print gtest errors */
-
-namespace prettyPrintAudioTypesDetail {
-
-// Print the value of an enum as hex
-template <class Enum>
-inline void printUnderlyingValue(Enum value, ::std::ostream* os) {
-    *os << std::hex << " (0x" << static_cast<std::underlying_type_t<Enum>>(value) << ")";
-}
-
-}  // namespace detail
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace V2_0 {
-
-inline void PrintTo(const Result& result, ::std::ostream* os) {
-    *os << toString(result);
-    prettyPrintAudioTypesDetail::printUnderlyingValue(result, os);
-}
-
-}  // namespace V2_0
-namespace common {
-namespace V2_0 {
-
-inline void PrintTo(const AudioConfig& config, ::std::ostream* os) {
-    *os << toString(config);
-}
-
-inline void PrintTo(const AudioDevice& device, ::std::ostream* os) {
-    *os << toString(device);
-    prettyPrintAudioTypesDetail::printUnderlyingValue(device, os);
-}
-
-inline void PrintTo(const AudioChannelMask& channelMask, ::std::ostream* os) {
-    *os << toString(channelMask);
-    prettyPrintAudioTypesDetail::printUnderlyingValue(channelMask, os);
-}
-
-}  // namespace V2_0
-}  // namespace common
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_PRETTY_PRINT_AUDIO_TYPES_H
diff --git a/audio/core/2.0/default/Android.bp b/audio/core/2.0/default/Android.bp
new file mode 100644
index 0000000..9847886
--- /dev/null
+++ b/audio/core/2.0/default/Android.bp
@@ -0,0 +1,49 @@
+cc_library_shared {
+    name: "android.hardware.audio@2.0-impl",
+    relative_install_path: "hw",
+    proprietary: true,
+    vendor: true,
+    srcs: [
+        "Conversions.cpp",
+        "Device.cpp",
+        "DevicesFactory.cpp",
+        "ParametersUtil.cpp",
+        "PrimaryDevice.cpp",
+        "Stream.cpp",
+        "StreamIn.cpp",
+        "StreamOut.cpp",
+    ],
+
+    defaults: ["hidl_defaults"],
+
+    export_include_dirs: ["include"],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libfmq",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.audio@2.0",
+        "android.hardware.audio.common@2.0",
+        "android.hardware.audio.common@2.0-util",
+        "android.hardware.audio.common-util",
+    ],
+
+    header_libs: [
+        "android.hardware.audio.common.util@all-versions",
+        "android.hardware.audio.core@all-versions-impl",
+        "libaudioclient_headers",
+        "libaudio_system_headers",
+        "libhardware_headers",
+        "libmedia_headers",
+    ],
+
+    whole_static_libs: [
+        "libmedia_helper",
+    ],
+
+}
diff --git a/audio/core/2.0/default/Conversions.cpp b/audio/core/2.0/default/Conversions.cpp
new file mode 100644
index 0000000..6c32090
--- /dev/null
+++ b/audio/core/2.0/default/Conversions.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 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 "core/2.0/default/Conversions.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/Conversions.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/2.0/default/Device.cpp b/audio/core/2.0/default/Device.cpp
new file mode 100644
index 0000000..221ea5c
--- /dev/null
+++ b/audio/core/2.0/default/Device.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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 "core/2.0/default/Device.h"
+#include <HidlUtils.h>
+#include "core/2.0/default/Conversions.h"
+#include "core/2.0/default/StreamIn.h"
+#include "core/2.0/default/StreamOut.h"
+#include "core/all-versions/default/Util.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/Device.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/2.0/default/DevicesFactory.cpp b/audio/core/2.0/default/DevicesFactory.cpp
new file mode 100644
index 0000000..65a9ccd
--- /dev/null
+++ b/audio/core/2.0/default/DevicesFactory.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 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 "core/2.0/default/DevicesFactory.h"
+#include "core/2.0/default/Device.h"
+#include "core/2.0/default/PrimaryDevice.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/DevicesFactory.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/common/2.0/default/OWNERS b/audio/core/2.0/default/OWNERS
similarity index 100%
rename from audio/common/2.0/default/OWNERS
rename to audio/core/2.0/default/OWNERS
diff --git a/audio/core/2.0/default/ParametersUtil.cpp b/audio/core/2.0/default/ParametersUtil.cpp
new file mode 100644
index 0000000..33a3ad9
--- /dev/null
+++ b/audio/core/2.0/default/ParametersUtil.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 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 "core/2.0/default/ParametersUtil.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/ParametersUtil.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/2.0/default/PrimaryDevice.cpp b/audio/core/2.0/default/PrimaryDevice.cpp
new file mode 100644
index 0000000..ce57403
--- /dev/null
+++ b/audio/core/2.0/default/PrimaryDevice.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2017 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 "core/2.0/default/PrimaryDevice.h"
+#include "core/all-versions/default/Util.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/PrimaryDevice.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/2.0/default/Stream.cpp b/audio/core/2.0/default/Stream.cpp
new file mode 100644
index 0000000..69ee659
--- /dev/null
+++ b/audio/core/2.0/default/Stream.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 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 "StreamHAL"
+
+#include "core/2.0/default/Stream.h"
+#include "common/all-versions/default/EffectMap.h"
+#include "core/2.0/default/Conversions.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/Stream.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/2.0/default/StreamIn.cpp b/audio/core/2.0/default/StreamIn.cpp
new file mode 100644
index 0000000..6b8776e
--- /dev/null
+++ b/audio/core/2.0/default/StreamIn.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2017 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 "core/2.0/default/StreamIn.h"
+#include "core/all-versions/default/Util.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/StreamIn.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/2.0/default/StreamOut.cpp b/audio/core/2.0/default/StreamOut.cpp
new file mode 100644
index 0000000..7f1461a
--- /dev/null
+++ b/audio/core/2.0/default/StreamOut.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2017 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 "core/2.0/default/StreamOut.h"
+#include "core/all-versions/default/Util.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/StreamOut.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/2.0/default/include/core/2.0/default/Conversions.h b/audio/core/2.0/default/include/core/2.0/default/Conversions.h
new file mode 100644
index 0000000..b3a6ea8
--- /dev/null
+++ b/audio/core/2.0/default/include/core/2.0/default/Conversions.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 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 <android/hardware/audio/2.0/types.h>
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/Conversions.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_CONVERSIONS_H_
diff --git a/audio/core/2.0/default/include/core/2.0/default/Device.h b/audio/core/2.0/default/include/core/2.0/default/Device.h
new file mode 100644
index 0000000..3ec7464
--- /dev/null
+++ b/audio/core/2.0/default/include/core/2.0/default/Device.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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_DEVICE_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_DEVICE_H
+
+#include <android/hardware/audio/2.0/IDevice.h>
+
+#include "ParametersUtil.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/Device.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_DEVICE_H
diff --git a/audio/core/2.0/default/include/core/2.0/default/DevicesFactory.h b/audio/core/2.0/default/include/core/2.0/default/DevicesFactory.h
new file mode 100644
index 0000000..8e8ee88
--- /dev/null
+++ b/audio/core/2.0/default/include/core/2.0/default/DevicesFactory.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 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_DEVICESFACTORY_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_DEVICESFACTORY_H
+
+#include <android/hardware/audio/2.0/IDevicesFactory.h>
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/DevicesFactory.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_DEVICESFACTORY_H
diff --git a/audio/core/2.0/default/include/core/2.0/default/ParametersUtil.h b/audio/core/2.0/default/include/core/2.0/default/ParametersUtil.h
new file mode 100644
index 0000000..a5c1c78
--- /dev/null
+++ b/audio/core/2.0/default/include/core/2.0/default/ParametersUtil.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 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_PARAMETERS_UTIL_H_
+#define ANDROID_HARDWARE_AUDIO_V2_0_PARAMETERS_UTIL_H_
+
+#include <android/hardware/audio/2.0/types.h>
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/ParametersUtil.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_PARAMETERS_UTIL_H_
diff --git a/audio/core/2.0/default/include/core/2.0/default/PrimaryDevice.h b/audio/core/2.0/default/include/core/2.0/default/PrimaryDevice.h
new file mode 100644
index 0000000..f898597
--- /dev/null
+++ b/audio/core/2.0/default/include/core/2.0/default/PrimaryDevice.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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_PRIMARYDEVICE_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_PRIMARYDEVICE_H
+
+#include <android/hardware/audio/2.0/IPrimaryDevice.h>
+
+#include "Device.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/PrimaryDevice.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_PRIMARYDEVICE_H
diff --git a/audio/core/2.0/default/include/core/2.0/default/Stream.h b/audio/core/2.0/default/include/core/2.0/default/Stream.h
new file mode 100644
index 0000000..a2d8456
--- /dev/null
+++ b/audio/core/2.0/default/include/core/2.0/default/Stream.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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_STREAM_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_STREAM_H
+
+#include <android/hardware/audio/2.0/IStream.h>
+
+#include "ParametersUtil.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/Stream.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_STREAM_H
diff --git a/audio/core/2.0/default/include/core/2.0/default/StreamIn.h b/audio/core/2.0/default/include/core/2.0/default/StreamIn.h
new file mode 100644
index 0000000..c36abbd
--- /dev/null
+++ b/audio/core/2.0/default/include/core/2.0/default/StreamIn.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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_STREAMIN_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_STREAMIN_H
+
+#include <android/hardware/audio/2.0/IStreamIn.h>
+
+#include "Device.h"
+#include "Stream.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/StreamIn.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_STREAMIN_H
diff --git a/audio/core/2.0/default/include/core/2.0/default/StreamOut.h b/audio/core/2.0/default/include/core/2.0/default/StreamOut.h
new file mode 100644
index 0000000..ab35687
--- /dev/null
+++ b/audio/core/2.0/default/include/core/2.0/default/StreamOut.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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_STREAMOUT_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_STREAMOUT_H
+
+#include <android/hardware/audio/2.0/IStreamOut.h>
+
+#include "Device.h"
+#include "Stream.h"
+
+#define AUDIO_HAL_VERSION V2_0
+#include <core/all-versions/default/StreamOut.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_STREAMOUT_H
diff --git a/audio/2.0/vts/OWNERS b/audio/core/2.0/vts/OWNERS
similarity index 100%
rename from audio/2.0/vts/OWNERS
rename to audio/core/2.0/vts/OWNERS
diff --git a/audio/2.0/vts/functional/Android.bp b/audio/core/2.0/vts/functional/Android.bp
similarity index 100%
rename from audio/2.0/vts/functional/Android.bp
rename to audio/core/2.0/vts/functional/Android.bp
diff --git a/audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
similarity index 78%
rename from audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
rename to audio/core/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index fd175de..bb1d26f 100644
--- a/audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -20,6 +20,7 @@
 #include <cmath>
 #include <cstddef>
 #include <cstdio>
+#include <initializer_list>
 #include <limits>
 #include <string>
 #include <vector>
@@ -40,9 +41,11 @@
 #include "utility/AssertOk.h"
 #include "utility/Documentation.h"
 #include "utility/EnvironmentTearDown.h"
+#define AUDIO_HAL_VERSION V2_0
 #include "utility/PrettyPrintAudioTypes.h"
 #include "utility/ReturnIn.h"
 
+using std::initializer_list;
 using std::string;
 using std::to_string;
 using std::vector;
@@ -85,8 +88,13 @@
 
 using namespace ::android::hardware::audio::common::test::utility;
 
+class AudioHidlTestEnvironment : public ::Environment {
+   public:
+    virtual void registerTestServices() override { registerTestService<IDevicesFactory>(); }
+};
+
 // Instance to register global tearDown
-static Environment* environment;
+static AudioHidlTestEnvironment* environment;
 
 class HidlTest : public ::testing::VtsHalHidlTargetTestBase {
    protected:
@@ -106,8 +114,8 @@
 
         if (devicesFactory == nullptr) {
             environment->registerTearDown([] { devicesFactory.clear(); });
-            devicesFactory = ::testing::VtsHalHidlTargetTestBase::getService<
-                IDevicesFactory>();
+            devicesFactory = ::testing::VtsHalHidlTargetTestBase::getService<IDevicesFactory>(
+                environment->getServiceName<IDevicesFactory>("default"));
         }
         ASSERT_TRUE(devicesFactory != nullptr);
     }
@@ -126,8 +134,7 @@
     doc::test("test passing an invalid parameter to openDevice");
     IDevicesFactory::Result result;
     sp<IDevice> device;
-    ASSERT_OK(devicesFactory->openDevice(IDevicesFactory::Device(-1),
-                                         returnIn(result, device)));
+    ASSERT_OK(devicesFactory->openDevice(IDevicesFactory::Device(-1), returnIn(result, device)));
     ASSERT_EQ(IDevicesFactory::Result::INVALID_ARGUMENTS, result);
     ASSERT_TRUE(device == nullptr);
 }
@@ -146,9 +153,8 @@
         if (device == nullptr) {
             IDevicesFactory::Result result;
             sp<IDevice> baseDevice;
-            ASSERT_OK(
-                devicesFactory->openDevice(IDevicesFactory::Device::PRIMARY,
-                                           returnIn(result, baseDevice)));
+            ASSERT_OK(devicesFactory->openDevice(IDevicesFactory::Device::PRIMARY,
+                                                 returnIn(result, baseDevice)));
             ASSERT_OK(result);
             ASSERT_TRUE(baseDevice != nullptr);
 
@@ -182,10 +188,8 @@
    protected:
     /** Test a property getter and setter. */
     template <class Getter, class Setter>
-    void testAccessors(const string& propertyName,
-                       const vector<Property>& valuesToTest, Setter setter,
-                       Getter getter,
-                       const vector<Property>& invalidValues = {}) {
+    void testAccessors(const string& propertyName, const vector<Property>& valuesToTest,
+                       Setter setter, Getter getter, const vector<Property>& invalidValues = {}) {
         Property initialValue;  // Save initial value to restore it at the end
                                 // of the test
         ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue)));
@@ -203,21 +207,17 @@
         }
 
         for (Property invalidValue : invalidValues) {
-            SCOPED_TRACE("Try to set " + propertyName +
-                         " with the invalid value " +
+            SCOPED_TRACE("Try to set " + propertyName + " with the invalid value " +
                          testing::PrintToString(invalidValue));
-            EXPECT_RESULT(Result::INVALID_ARGUMENTS,
-                          (device.get()->*setter)(invalidValue));
+            EXPECT_RESULT(Result::INVALID_ARGUMENTS, (device.get()->*setter)(invalidValue));
         }
 
-        ASSERT_OK(
-            (device.get()->*setter)(initialValue));  // restore initial value
+        ASSERT_OK((device.get()->*setter)(initialValue));  // restore initial value
     }
 
     /** Test the getter and setter of an optional feature. */
     template <class Getter, class Setter>
-    void testOptionalAccessors(const string& propertyName,
-                               const vector<Property>& valuesToTest,
+    void testOptionalAccessors(const string& propertyName, const vector<Property>& valuesToTest,
                                Setter setter, Getter getter,
                                const vector<Property>& invalidValues = {}) {
         doc::test("Test the optional " + propertyName + " getters and setter");
@@ -232,8 +232,7 @@
             ASSERT_OK(res);  // If it is supported it must succeed
         }
         // The feature is supported, test it
-        testAccessors(propertyName, valuesToTest, setter, getter,
-                      invalidValues);
+        testAccessors(propertyName, valuesToTest, setter, getter, invalidValues);
     }
 };
 
@@ -241,8 +240,7 @@
 
 TEST_F(BoolAccessorPrimaryHidlTest, MicMuteTest) {
     doc::test("Check that the mic can be muted and unmuted");
-    testAccessors("mic mute", {true, false, true}, &IDevice::setMicMute,
-                  &IDevice::getMicMute);
+    testAccessors("mic mute", {true, false, true}, &IDevice::setMicMute, &IDevice::getMicMute);
     // TODO: check that the mic is really muted (all sample are 0)
 }
 
@@ -250,18 +248,17 @@
     doc::test(
         "If master mute is supported, try to mute and unmute the master "
         "output");
-    testOptionalAccessors("master mute", {true, false, true},
-                          &IDevice::setMasterMute, &IDevice::getMasterMute);
+    testOptionalAccessors("master mute", {true, false, true}, &IDevice::setMasterMute,
+                          &IDevice::getMasterMute);
     // TODO: check that the master volume is really muted
 }
 
 using FloatAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<float>;
 TEST_F(FloatAccessorPrimaryHidlTest, MasterVolumeTest) {
     doc::test("Test the master volume if supported");
-    testOptionalAccessors("master volume", {0, 0.5, 1},
-                          &IDevice::setMasterVolume, &IDevice::getMasterVolume,
-                          {-0.1, 1.1, NAN, INFINITY, -INFINITY,
-                           1 + std::numeric_limits<float>::epsilon()});
+    testOptionalAccessors(
+        "master volume", {0, 0.5, 1}, &IDevice::setMasterVolume, &IDevice::getMasterVolume,
+        {-0.1, 1.1, NAN, INFINITY, -INFINITY, 1 + std::numeric_limits<float>::epsilon()});
     // TODO: check that the master volume is really changed
 }
 
@@ -300,17 +297,14 @@
    public:
     // Cache result ?
     static const vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
-        return combineAudioConfig(
-            {AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
-            {8000, 11025, 16000, 22050, 32000, 44100},
-            {AudioFormat::PCM_16_BIT});
+        return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
+                                  {8000, 11025, 16000, 22050, 32000, 44100},
+                                  {AudioFormat::PCM_16_BIT});
     }
 
-    static const vector<AudioConfig>
-    getRecommendedSupportPlaybackAudioConfig() {
-        return combineAudioConfig(
-            {AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
-            {24000, 48000}, {AudioFormat::PCM_16_BIT});
+    static const vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
+        return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
+                                  {24000, 48000}, {AudioFormat::PCM_16_BIT});
     }
 
     static const vector<AudioConfig> getSupportedPlaybackAudioConfig() {
@@ -320,8 +314,7 @@
     }
 
     static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
-        return combineAudioConfig({AudioChannelMask::IN_MONO},
-                                  {8000, 11025, 16000, 44100},
+        return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100},
                                   {AudioFormat::PCM_16_BIT});
     }
     static const vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
@@ -335,9 +328,9 @@
     }
 
    private:
-    static const vector<AudioConfig> combineAudioConfig(
-        vector<AudioChannelMask> channelMasks, vector<uint32_t> sampleRates,
-        vector<AudioFormat> formats) {
+    static const vector<AudioConfig> combineAudioConfig(vector<AudioChannelMask> channelMasks,
+                                                        vector<uint32_t> sampleRates,
+                                                        vector<AudioFormat> formats) {
         vector<AudioConfig> configs;
         for (auto channelMask : channelMasks) {
             for (auto sampleRate : sampleRates) {
@@ -361,8 +354,7 @@
  * As the only parameter changing are channel mask and sample rate,
  * only print those ones in the test name.
  */
-static string generateTestName(
-    const testing::TestParamInfo<AudioConfig>& info) {
+static string generateTestName(const testing::TestParamInfo<AudioConfig>& info) {
     const AudioConfig& config = info.param;
     return to_string(info.index) + "__" + to_string(config.sampleRateHz) + "_" +
            // "MONO" is more clear than "FRONT_LEFT"
@@ -380,15 +372,12 @@
 // android.hardware.microphone
 //        how to get this value ? is it a property ???
 
-class AudioCaptureConfigPrimaryTest
-    : public AudioConfigPrimaryTest,
-      public ::testing::WithParamInterface<AudioConfig> {
+class AudioCaptureConfigPrimaryTest : public AudioConfigPrimaryTest,
+                                      public ::testing::WithParamInterface<AudioConfig> {
    protected:
-    void inputBufferSizeTest(const AudioConfig& audioConfig,
-                             bool supportRequired) {
+    void inputBufferSizeTest(const AudioConfig& audioConfig, bool supportRequired) {
         uint64_t bufferSize;
-        ASSERT_OK(
-            device->getInputBufferSize(audioConfig, returnIn(res, bufferSize)));
+        ASSERT_OK(device->getInputBufferSize(audioConfig, returnIn(res, bufferSize)));
 
         switch (res) {
             case Result::INVALID_ARGUMENTS:
@@ -400,8 +389,7 @@
                 EXPECT_GT(bufferSize, uint64_t(0));
                 break;
             default:
-                FAIL() << "Invalid return status: "
-                       << ::testing::PrintToString(res);
+                FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
         }
     }
 };
@@ -417,13 +405,11 @@
 }
 INSTANTIATE_TEST_CASE_P(
     RequiredInputBufferSize, RequiredInputBufferSizeTest,
-    ::testing::ValuesIn(
-        AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
     &generateTestName);
 INSTANTIATE_TEST_CASE_P(
     SupportedInputBufferSize, RequiredInputBufferSizeTest,
-    ::testing::ValuesIn(
-        AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
     &generateTestName);
 
 // Test that the recommended capture config are supported or lead to a
@@ -437,8 +423,7 @@
 }
 INSTANTIATE_TEST_CASE_P(
     RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
-    ::testing::ValuesIn(
-        AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
     &generateTestName);
 
 //////////////////////////////////////////////////////////////////////////////
@@ -530,11 +515,9 @@
     void testOpen(Open openStream, const AudioConfig& config) {
         // FIXME: Open a stream without an IOHandle
         //        This is not required to be accepted by hal implementations
-        AudioIoHandle ioHandle =
-            (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
+        AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
         AudioConfig suggestedConfig{};
-        ASSERT_OK(openStream(ioHandle, config,
-                             returnIn(res, stream, suggestedConfig)));
+        ASSERT_OK(openStream(ioHandle, config, returnIn(res, stream, suggestedConfig)));
 
         // TODO: only allow failure for RecommendedPlaybackAudioConfig
         switch (res) {
@@ -547,17 +530,15 @@
                 AudioConfig suggestedConfigRetry;
                 // Could not open stream with config, try again with the
                 // suggested one
-                ASSERT_OK(
-                    openStream(ioHandle, suggestedConfig,
-                               returnIn(res, stream, suggestedConfigRetry)));
+                ASSERT_OK(openStream(ioHandle, suggestedConfig,
+                                     returnIn(res, stream, suggestedConfigRetry)));
                 // This time it must succeed
                 ASSERT_OK(res);
                 ASSERT_TRUE(stream != nullptr);
                 audioConfig = suggestedConfig;
                 break;
             default:
-                FAIL() << "Invalid return status: "
-                       << ::testing::PrintToString(res);
+                FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
         }
         open = true;
     }
@@ -588,12 +569,10 @@
         ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
         address.device = AudioDevice::OUT_DEFAULT;
         const AudioConfig& config = GetParam();
-        AudioOutputFlag flags =
-            AudioOutputFlag::NONE;  // TODO: test all flag combination
+        AudioOutputFlag flags = AudioOutputFlag::NONE;  // TODO: test all flag combination
         testOpen(
             [&](AudioIoHandle handle, AudioConfig config, auto cb) {
-                return device->openOutputStream(handle, address, config, flags,
-                                                cb);
+                return device->openOutputStream(handle, address, config, flags, cb);
             },
             config);
     }
@@ -606,19 +585,16 @@
 }
 INSTANTIATE_TEST_CASE_P(
     RequiredOutputStreamConfigSupport, OutputStreamTest,
-    ::testing::ValuesIn(
-        AudioConfigPrimaryTest::getRequiredSupportPlaybackAudioConfig()),
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportPlaybackAudioConfig()),
     &generateTestName);
 INSTANTIATE_TEST_CASE_P(
     SupportedOutputStreamConfig, OutputStreamTest,
-    ::testing::ValuesIn(
-        AudioConfigPrimaryTest::getSupportedPlaybackAudioConfig()),
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedPlaybackAudioConfig()),
     &generateTestName);
 
 INSTANTIATE_TEST_CASE_P(
     RecommendedOutputStreamConfigSupport, OutputStreamTest,
-    ::testing::ValuesIn(
-        AudioConfigPrimaryTest::getRecommendedSupportPlaybackAudioConfig()),
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportPlaybackAudioConfig()),
     &generateTestName);
 
 ////////////////////////////// openInputStream //////////////////////////////
@@ -628,14 +604,11 @@
         ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
         address.device = AudioDevice::IN_DEFAULT;
         const AudioConfig& config = GetParam();
-        AudioInputFlag flags =
-            AudioInputFlag::NONE;  // TODO: test all flag combination
-        AudioSource source =
-            AudioSource::DEFAULT;  // TODO: test all flag combination
+        AudioInputFlag flags = AudioInputFlag::NONE;  // TODO: test all flag combination
+        AudioSource source = AudioSource::DEFAULT;    // TODO: test all flag combination
         testOpen(
             [&](AudioIoHandle handle, AudioConfig config, auto cb) {
-                return device->openInputStream(handle, address, config, flags,
-                                               source, cb);
+                return device->openInputStream(handle, address, config, flags, source, cb);
             },
             config);
     }
@@ -649,19 +622,16 @@
 }
 INSTANTIATE_TEST_CASE_P(
     RequiredInputStreamConfigSupport, InputStreamTest,
-    ::testing::ValuesIn(
-        AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
     &generateTestName);
 INSTANTIATE_TEST_CASE_P(
     SupportedInputStreamConfig, InputStreamTest,
-    ::testing::ValuesIn(
-        AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
     &generateTestName);
 
 INSTANTIATE_TEST_CASE_P(
     RecommendedInputStreamConfigSupport, InputStreamTest,
-    ::testing::ValuesIn(
-        AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
     &generateTestName);
 
 //////////////////////////////////////////////////////////////////////////////
@@ -691,10 +661,8 @@
         code;                                          \
     }
 
-TEST_IO_STREAM(
-    GetFrameCount,
-    "Check that the stream frame count == the one it was opened with",
-    ASSERT_EQ(audioConfig.frameCount, extract(stream->getFrameCount())))
+TEST_IO_STREAM(GetFrameCount, "Check that the stream frame count == the one it was opened with",
+               ASSERT_EQ(audioConfig.frameCount, extract(stream->getFrameCount())))
 
 TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with",
                ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
@@ -702,19 +670,15 @@
 TEST_IO_STREAM(GetChannelMask, "Check that the stream channel mask == the one it was opened with",
                ASSERT_EQ(audioConfig.channelMask, extract(stream->getChannelMask())))
 
-TEST_IO_STREAM(GetFormat,
-               "Check that the stream format == the one it was opened with",
+TEST_IO_STREAM(GetFormat, "Check that the stream format == the one it was opened with",
                ASSERT_EQ(audioConfig.format, extract(stream->getFormat())))
 
 // TODO: for now only check that the framesize is not incoherent
-TEST_IO_STREAM(GetFrameSize,
-               "Check that the stream frame size == the one it was opened with",
+TEST_IO_STREAM(GetFrameSize, "Check that the stream frame size == the one it was opened with",
                ASSERT_GT(extract(stream->getFrameSize()), 0U))
 
-TEST_IO_STREAM(GetBufferSize,
-               "Check that the stream buffer size== the one it was opened with",
-               ASSERT_GE(extract(stream->getBufferSize()),
-                         extract(stream->getFrameSize())));
+TEST_IO_STREAM(GetBufferSize, "Check that the stream buffer size== the one it was opened with",
+               ASSERT_GE(extract(stream->getBufferSize()), extract(stream->getFrameSize())));
 
 template <class Property, class CapabilityGetter>
 static void testCapabilityGetter(const string& name, IStream* stream,
@@ -754,29 +718,24 @@
     }
 }
 
-TEST_IO_STREAM(SupportedSampleRate,
-               "Check that the stream sample rate is declared as supported",
+TEST_IO_STREAM(SupportedSampleRate, "Check that the stream sample rate is declared as supported",
                testCapabilityGetter("getSupportedSampleRate", stream.get(),
-                                    &IStream::getSupportedSampleRates,
-                                    &IStream::getSampleRate,
+                                    &IStream::getSupportedSampleRates, &IStream::getSampleRate,
                                     &IStream::setSampleRate,
                                     // getSupportedSampleRate returns the native sampling rates,
                                     // (the sampling rates that can be played without resampling)
                                     // but other sampling rates can be supported by the HAL.
                                     false))
 
-TEST_IO_STREAM(SupportedChannelMask,
-               "Check that the stream channel mask is declared as supported",
+TEST_IO_STREAM(SupportedChannelMask, "Check that the stream channel mask is declared as supported",
                testCapabilityGetter("getSupportedChannelMask", stream.get(),
-                                    &IStream::getSupportedChannelMasks,
-                                    &IStream::getChannelMask,
+                                    &IStream::getSupportedChannelMasks, &IStream::getChannelMask,
                                     &IStream::setChannelMask))
 
-TEST_IO_STREAM(SupportedFormat,
-               "Check that the stream format is declared as supported",
+TEST_IO_STREAM(SupportedFormat, "Check that the stream format is declared as supported",
                testCapabilityGetter("getSupportedFormat", stream.get(),
-                                    &IStream::getSupportedFormats,
-                                    &IStream::getFormat, &IStream::setFormat))
+                                    &IStream::getSupportedFormats, &IStream::getFormat,
+                                    &IStream::setFormat))
 
 static void testGetDevice(IStream* stream, AudioDevice expectedDevice) {
     // Unfortunately the interface does not allow the implementation to return
@@ -790,27 +749,22 @@
         << "\n  Actual: " << ::testing::PrintToString(device);
 }
 
-TEST_IO_STREAM(GetDevice,
-               "Check that the stream device == the one it was opened with",
-               areAudioPatchesSupported()
-                   ? doc::partialTest("Audio patches are supported")
-                   : testGetDevice(stream.get(), address.device))
+TEST_IO_STREAM(GetDevice, "Check that the stream device == the one it was opened with",
+               areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
+                                          : testGetDevice(stream.get(), address.device))
 
 static void testSetDevice(IStream* stream, const DeviceAddress& address) {
     DeviceAddress otherAddress = address;
-    otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0
-                              ? AudioDevice::OUT_SPEAKER
-                              : AudioDevice::IN_BUILTIN_MIC;
+    otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0 ? AudioDevice::OUT_SPEAKER
+                                                                      : AudioDevice::IN_BUILTIN_MIC;
     EXPECT_OK(stream->setDevice(otherAddress));
 
     ASSERT_OK(stream->setDevice(address));  // Go back to the original value
 }
 
-TEST_IO_STREAM(
-    SetDevice,
-    "Check that the stream can be rerouted to SPEAKER or BUILTIN_MIC",
-    areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
-                               : testSetDevice(stream.get(), address))
+TEST_IO_STREAM(SetDevice, "Check that the stream can be rerouted to SPEAKER or BUILTIN_MIC",
+               areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
+                                          : testSetDevice(stream.get(), address))
 
 static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
     uint32_t sampleRateHz;
@@ -833,8 +787,7 @@
 static void testConnectedState(IStream* stream) {
     DeviceAddress address = {};
     using AD = AudioDevice;
-    for (auto device :
-         {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
+    for (auto device : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
         address.device = device;
 
         ASSERT_OK(stream->setConnectedState(address, true));
@@ -846,17 +799,15 @@
                "deconnection",
                testConnectedState(stream.get()))
 
-static auto invalidArgsOrNotSupportedOrOK = {Result::INVALID_ARGUMENTS,
-                                             Result::NOT_SUPPORTED, Result::OK};
+static auto invalidArgsOrNotSupportedOrOK = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED,
+                                             Result::OK};
 TEST_IO_STREAM(SetHwAvSync, "Try to set hardware sync to an invalid value",
-               ASSERT_RESULT(invalidArgsOrNotSupportedOrOK,
-                             stream->setHwAvSync(666)))
+               ASSERT_RESULT(invalidArgsOrNotSupportedOrOK, stream->setHwAvSync(666)))
 
-TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail",
-               ASSERT_IS_OK(device->getHwAvSync()));
+TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail", ASSERT_IS_OK(device->getHwAvSync()));
 
 static void checkGetNoParameter(IStream* stream, hidl_vec<hidl_string> keys,
-                                vector<Result> expectedResults) {
+                                initializer_list<Result> expectedResults) {
     hidl_vec<ParameterValue> parameters;
     Result res;
     ASSERT_OK(stream->getParameters(keys, returnIn(res, parameters)));
@@ -875,30 +826,23 @@
 TEST_IO_STREAM(getEmptySetParameter, "Retrieve the values of an empty set",
                checkGetNoParameter(stream.get(), {} /* keys */, {Result::OK}))
 
-TEST_IO_STREAM(getNonExistingParameter,
-               "Retrieve the values of an non existing parameter",
-               checkGetNoParameter(stream.get(),
-                                   {"Non existing key"} /* keys */,
+TEST_IO_STREAM(getNonExistingParameter, "Retrieve the values of an non existing parameter",
+               checkGetNoParameter(stream.get(), {"Non existing key"} /* keys */,
                                    {Result::NOT_SUPPORTED}))
 
-TEST_IO_STREAM(setEmptySetParameter,
-               "Set the values of an empty set of parameters",
+TEST_IO_STREAM(setEmptySetParameter, "Set the values of an empty set of parameters",
                ASSERT_RESULT(Result::OK, stream->setParameters({})))
 
-TEST_IO_STREAM(
-    setNonExistingParameter, "Set the values of an non existing parameter",
-    // Unfortunately, the set_parameter legacy interface did not return any
-    // error code when a key is not supported.
-    // To allow implementation to just wrapped the legacy one, consider OK as a
-    // valid result for setting a non existing parameter.
-    ASSERT_RESULT(invalidArgsOrNotSupportedOrOK,
-                  stream->setParameters({{"non existing key", "0"}})))
+TEST_IO_STREAM(setNonExistingParameter, "Set the values of an non existing parameter",
+               // Unfortunately, the set_parameter legacy interface did not return any
+               // error code when a key is not supported.
+               // To allow implementation to just wrapped the legacy one, consider OK as a
+               // valid result for setting a non existing parameter.
+               ASSERT_RESULT(invalidArgsOrNotSupportedOrOK,
+                             stream->setParameters({{"non existing key", "0"}})))
 
-TEST_IO_STREAM(DebugDump,
-               "Check that a stream can dump its state without error",
-               testDebugDump([this](const auto& handle) {
-                   return stream->debugDump(handle);
-               }))
+TEST_IO_STREAM(DebugDump, "Check that a stream can dump its state without error",
+               testDebugDump([this](const auto& handle) { return stream->debugDump(handle); }))
 
 TEST_IO_STREAM(DebugDumpInvalidArguments,
                "Check that the stream dump doesn't crash on invalid arguments",
@@ -910,10 +854,8 @@
 
 TEST_IO_STREAM(AddNonExistingEffect, "Adding a non existing effect should fail",
                ASSERT_RESULT(Result::INVALID_ARGUMENTS, stream->addEffect(666)))
-TEST_IO_STREAM(RemoveNonExistingEffect,
-               "Removing a non existing effect should fail",
-               ASSERT_RESULT(Result::INVALID_ARGUMENTS,
-                             stream->removeEffect(666)))
+TEST_IO_STREAM(RemoveNonExistingEffect, "Removing a non existing effect should fail",
+               ASSERT_RESULT(Result::INVALID_ARGUMENTS, stream->removeEffect(666)))
 
 // TODO: positive tests
 
@@ -924,29 +866,22 @@
 TEST_IO_STREAM(standby, "Make sure the stream can be put in stanby",
                ASSERT_OK(stream->standby()))  // can not fail
 
-static vector<Result> invalidStateOrNotSupported = {Result::INVALID_STATE,
-                                                    Result::NOT_SUPPORTED};
+static constexpr auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUPPORTED};
 
-TEST_IO_STREAM(startNoMmap,
-               "Starting a mmaped stream before mapping it should fail",
+TEST_IO_STREAM(startNoMmap, "Starting a mmaped stream before mapping it should fail",
                ASSERT_RESULT(invalidStateOrNotSupported, stream->start()))
 
-TEST_IO_STREAM(stopNoMmap,
-               "Stopping a mmaped stream before mapping it should fail",
+TEST_IO_STREAM(stopNoMmap, "Stopping a mmaped stream before mapping it should fail",
                ASSERT_RESULT(invalidStateOrNotSupported, stream->stop()))
 
-TEST_IO_STREAM(getMmapPositionNoMmap,
-               "Get a stream Mmap position before mapping it should fail",
+TEST_IO_STREAM(getMmapPositionNoMmap, "Get a stream Mmap position before mapping it should fail",
                ASSERT_RESULT(invalidStateOrNotSupported, stream->stop()))
 
-TEST_IO_STREAM(close, "Make sure a stream can be closed",
-               ASSERT_OK(closeStream()))
-TEST_IO_STREAM(closeTwice, "Make sure a stream can not be closed twice",
-               ASSERT_OK(closeStream());
+TEST_IO_STREAM(close, "Make sure a stream can be closed", ASSERT_OK(closeStream()))
+TEST_IO_STREAM(closeTwice, "Make sure a stream can not be closed twice", ASSERT_OK(closeStream());
                ASSERT_RESULT(Result::INVALID_STATE, closeStream()))
 
-static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS,
-                                         Result::NOT_SUPPORTED};
+static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
 static void testCreateTooBigMmapBuffer(IStream* stream) {
     MmapBufferInfo info;
     Result res;
@@ -968,18 +903,16 @@
     ASSERT_RESULT(invalidArgsOrNotSupported, res);
 }
 
-TEST_IO_STREAM(
-    GetMmapPositionOfNonMmapedStream,
-    "Retrieving the mmap position of a non mmaped stream should fail",
-    testGetMmapPositionOfNonMmapedStream(stream.get()))
+TEST_IO_STREAM(GetMmapPositionOfNonMmapedStream,
+               "Retrieving the mmap position of a non mmaped stream should fail",
+               testGetMmapPositionOfNonMmapedStream(stream.get()))
 
 //////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////// StreamIn ///////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
 TEST_P(InputStreamTest, GetAudioSource) {
-    doc::test(
-        "Retrieving the audio source of an input stream should always succeed");
+    doc::test("Retrieving the audio source of an input stream should always succeed");
     AudioSource source;
     ASSERT_OK(stream->getAudioSource(returnIn(res, source)));
     if (res == Result::NOT_SUPPORTED) {
@@ -991,11 +924,9 @@
 }
 
 static void testUnitaryGain(std::function<Return<Result>(float)> setGain) {
-    for (float value :
-         (float[]){-INFINITY, -1.0, 1.0 + std::numeric_limits<float>::epsilon(),
-                   2.0, INFINITY, NAN}) {
-        EXPECT_RESULT(Result::INVALID_ARGUMENTS, setGain(value)) << "value="
-                                                                 << value;
+    for (float value : (float[]){-INFINITY, -1.0, 1.0 + std::numeric_limits<float>::epsilon(), 2.0,
+                                 INFINITY, NAN}) {
+        EXPECT_RESULT(Result::INVALID_ARGUMENTS, setGain(value)) << "value=" << value;
     }
     // Do not consider -0.0 as an invalid value as it is == with 0.0
     for (float value : {-0.0, 0.0, 0.01, 0.5, 0.09, 1.0 /* Restore volume*/}) {
@@ -1003,8 +934,8 @@
     }
 }
 
-static void testOptionalUnitaryGain(
-    std::function<Return<Result>(float)> setGain, string debugName) {
+static void testOptionalUnitaryGain(std::function<Return<Result>(float)> setGain,
+                                    string debugName) {
     auto result = setGain(1);
     ASSERT_IS_OK(result);
     if (result == Result::NOT_SUPPORTED) {
@@ -1016,32 +947,26 @@
 
 TEST_P(InputStreamTest, SetGain) {
     doc::test("The gain of an input stream should only be set between [0,1]");
-    testOptionalUnitaryGain(
-        [this](float volume) { return stream->setGain(volume); },
-        "InputStream::setGain");
+    testOptionalUnitaryGain([this](float volume) { return stream->setGain(volume); },
+                            "InputStream::setGain");
 }
 
-static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize,
-                                  uint32_t framesCount) {
+static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize, uint32_t framesCount) {
     Result res;
     // Ignore output parameters as the call should fail
-    ASSERT_OK(stream->prepareForReading(
-        frameSize, framesCount,
-        [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
+    ASSERT_OK(stream->prepareForReading(frameSize, framesCount,
+                                        [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
     EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
 }
 
 TEST_P(InputStreamTest, PrepareForReadingWithZeroBuffer) {
-    doc::test(
-        "Preparing a stream for reading with a 0 sized buffer should fail");
+    doc::test("Preparing a stream for reading with a 0 sized buffer should fail");
     testPrepareForReading(stream.get(), 0, 0);
 }
 
 TEST_P(InputStreamTest, PrepareForReadingWithHugeBuffer) {
-    doc::test(
-        "Preparing a stream for reading with a 2^32 sized buffer should fail");
-    testPrepareForReading(stream.get(), 1,
-                          std::numeric_limits<uint32_t>::max());
+    doc::test("Preparing a stream for reading with a 2^32 sized buffer should fail");
+    testPrepareForReading(stream.get(), 1, std::numeric_limits<uint32_t>::max());
 }
 
 TEST_P(InputStreamTest, PrepareForReadingCheckOverflow) {
@@ -1053,8 +978,7 @@
 }
 
 TEST_P(InputStreamTest, GetInputFramesLost) {
-    doc::test(
-        "The number of frames lost on a never started stream should be 0");
+    doc::test("The number of frames lost on a never started stream should be 0");
     auto ret = stream->getInputFramesLost();
     ASSERT_IS_OK(ret);
     uint32_t framesLost{ret};
@@ -1084,32 +1008,26 @@
 
 TEST_P(OutputStreamTest, setVolume) {
     doc::test("Try to set the output volume");
-    testOptionalUnitaryGain(
-        [this](float volume) { return stream->setVolume(volume, volume); },
-        "setVolume");
+    testOptionalUnitaryGain([this](float volume) { return stream->setVolume(volume, volume); },
+                            "setVolume");
 }
 
-static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize,
-                                  uint32_t framesCount) {
+static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize, uint32_t framesCount) {
     Result res;
     // Ignore output parameters as the call should fail
-    ASSERT_OK(stream->prepareForWriting(
-        frameSize, framesCount,
-        [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
+    ASSERT_OK(stream->prepareForWriting(frameSize, framesCount,
+                                        [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
     EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
 }
 
 TEST_P(OutputStreamTest, PrepareForWriteWithZeroBuffer) {
-    doc::test(
-        "Preparing a stream for writing with a 0 sized buffer should fail");
+    doc::test("Preparing a stream for writing with a 0 sized buffer should fail");
     testPrepareForWriting(stream.get(), 0, 0);
 }
 
 TEST_P(OutputStreamTest, PrepareForWriteWithHugeBuffer) {
-    doc::test(
-        "Preparing a stream for writing with a 2^32 sized buffer should fail");
-    testPrepareForWriting(stream.get(), 1,
-                          std::numeric_limits<uint32_t>::max());
+    doc::test("Preparing a stream for writing with a 2^32 sized buffer should fail");
+    testPrepareForWriting(stream.get(), 1, std::numeric_limits<uint32_t>::max());
 }
 
 TEST_P(OutputStreamTest, PrepareForWritingCheckOverflow) {
@@ -1135,8 +1053,7 @@
 };
 
 TEST_P(OutputStreamTest, SupportsPauseAndResumeAndDrain) {
-    doc::test(
-        "Implementation must expose pause, resume and drain capabilities");
+    doc::test("Implementation must expose pause, resume and drain capabilities");
     Capability(stream.get());
 }
 
@@ -1290,13 +1207,10 @@
     struct timespec currentTS;
     ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &currentTS)) << errno;
 
-    auto toMicroSec = [](uint64_t sec, auto nsec) {
-        return sec * 1e+6 + nsec / 1e+3;
-    };
+    auto toMicroSec = [](uint64_t sec, auto nsec) { return sec * 1e+6 + nsec / 1e+3; };
     auto currentTime = toMicroSec(currentTS.tv_sec, currentTS.tv_nsec);
     auto mesureTime = toMicroSec(mesureTS.tvSec, mesureTS.tvNSec);
-    ASSERT_PRED2([](auto c, auto m) { return c - m < 1e+6; }, currentTime,
-                 mesureTime);
+    ASSERT_PRED2([](auto c, auto m) { return c - m < 1e+6; }, currentTime, mesureTime);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1313,15 +1227,13 @@
         "Make sure setMode always succeeds if mode is valid "
         "and fails otherwise");
     // Test Invalid values
-    for (AudioMode mode :
-         {AudioMode::INVALID, AudioMode::CURRENT, AudioMode::CNT}) {
+    for (AudioMode mode : {AudioMode::INVALID, AudioMode::CURRENT, AudioMode::CNT}) {
         SCOPED_TRACE("mode=" + toString(mode));
         ASSERT_RESULT(Result::INVALID_ARGUMENTS, device->setMode(mode));
     }
     // Test valid values
-    for (AudioMode mode :
-         {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE,
-          AudioMode::NORMAL /* Make sure to leave the test in normal mode */}) {
+    for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE,
+                           AudioMode::NORMAL /* Make sure to leave the test in normal mode */}) {
         SCOPED_TRACE("mode=" + toString(mode));
         ASSERT_OK(device->setMode(mode));
     }
@@ -1344,15 +1256,13 @@
 using TtyModeAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<TtyMode>;
 TEST_F(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
     doc::test("Query and set the TTY mode state");
-    testOptionalAccessors(
-        "TTY mode", {TtyMode::OFF, TtyMode::HCO, TtyMode::VCO, TtyMode::FULL},
-        &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
+    testOptionalAccessors("TTY mode", {TtyMode::OFF, TtyMode::HCO, TtyMode::VCO, TtyMode::FULL},
+                          &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
 }
 
 TEST_F(BoolAccessorPrimaryHidlTest, setGetHac) {
     doc::test("Query and set the HAC state");
-    testOptionalAccessors("HAC", {true, false, true},
-                          &IPrimaryDevice::setHacEnabled,
+    testOptionalAccessors("HAC", {true, false, true}, &IPrimaryDevice::setHacEnabled,
                           &IPrimaryDevice::getHacEnabled);
 }
 
@@ -1361,9 +1271,10 @@
 //////////////////////////////////////////////////////////////////////////////
 
 int main(int argc, char** argv) {
-    environment = new Environment;
+    environment = new AudioHidlTestEnvironment;
     ::testing::AddGlobalTestEnvironment(environment);
     ::testing::InitGoogleTest(&argc, argv);
+    environment->init(&argc, argv);
     int status = RUN_ALL_TESTS();
     return status;
 }
diff --git a/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp b/audio/core/2.0/vts/functional/ValidateAudioConfiguration.cpp
similarity index 99%
rename from audio/2.0/vts/functional/ValidateAudioConfiguration.cpp
rename to audio/core/2.0/vts/functional/ValidateAudioConfiguration.cpp
index 4e280f5..bef0e82 100644
--- a/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp
+++ b/audio/core/2.0/vts/functional/ValidateAudioConfiguration.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include <string>
 #include <unistd.h>
+#include <string>
 
 #include "utility/ValidateXml.h"
 
diff --git a/audio/common/2.0/default/OWNERS b/audio/core/all-versions/OWNERS
similarity index 100%
copy from audio/common/2.0/default/OWNERS
copy to audio/core/all-versions/OWNERS
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
new file mode 100644
index 0000000..214b8d5
--- /dev/null
+++ b/audio/core/all-versions/default/Android.bp
@@ -0,0 +1,30 @@
+cc_library_headers {
+    name: "android.hardware.audio.core@all-versions-impl",
+    relative_install_path: "hw",
+    proprietary: true,
+    vendor: true,
+
+    defaults: ["hidl_defaults"],
+
+    export_include_dirs: ["include"],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libfmq",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.audio.common-util",
+    ],
+
+    header_libs: [
+        "libaudioclient_headers",
+        "libaudio_system_headers",
+        "libhardware_headers",
+        "libmedia_headers",
+         "android.hardware.audio.common.util@all-versions",
+    ],
+}
diff --git a/audio/2.0/default/Conversions.h b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
similarity index 75%
rename from audio/2.0/default/Conversions.h
rename to audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
index ebda5c5..fa05350 100644
--- a/audio/2.0/default/Conversions.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
@@ -14,28 +14,24 @@
  * limitations under the License.
  */
 
-#ifndef android_hardware_audio_V2_0_Conversions_H_
-#define android_hardware_audio_V2_0_Conversions_H_
+#include <common/all-versions/IncludeGuard.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 AUDIO_HAL_VERSION {
 namespace implementation {
 
-using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress;
 
 std::string deviceAddressToHal(const DeviceAddress& address);
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
-
-#endif  // android_hardware_audio_V2_0_Conversions_H_
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Conversions.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.impl.h
new file mode 100644
index 0000000..3f3f936
--- /dev/null
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.impl.h
@@ -0,0 +1,61 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <stdio.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace AUDIO_HAL_VERSION {
+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);
+    const bool isInput = (halDevice & AUDIO_DEVICE_BIT_IN) != 0;
+    if (isInput) halDevice &= ~AUDIO_DEVICE_BIT_IN;
+    if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) ||
+        (isInput && (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 ((!isInput && (halDevice & AUDIO_DEVICE_OUT_IP) != 0) ||
+               (isInput && (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 ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_USB) != 0) ||
+               (isInput && (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 ((!isInput && (halDevice & AUDIO_DEVICE_OUT_BUS) != 0) ||
+               (isInput && (halDevice & AUDIO_DEVICE_IN_BUS) != 0)) {
+        snprintf(halAddress, sizeof(halAddress), "%s", address.busAddress.c_str());
+    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0 ||
+               (isInput && (halDevice & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
+        snprintf(halAddress, sizeof(halAddress), "%s", address.rSubmixAddress.c_str());
+    }
+    return halAddress;
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Device.h b/audio/core/all-versions/default/include/core/all-versions/default/Device.h
new file mode 100644
index 0000000..224823c
--- /dev/null
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.h
@@ -0,0 +1,109 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <memory>
+
+#include <hardware/audio.h>
+#include <media/AudioParameter.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioConfig;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioHwSync;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioInputFlag;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioOutputFlag;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPatchHandle;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPort;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPortConfig;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IDevice;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamIn;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamOut;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::ParameterValue;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::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::AUDIO_HAL_VERSION::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<bool> supportsAudioPatches() 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 hidl_handle& fd) override;
+
+    // Utility methods for extending interfaces.
+    Result analyzeStatus(const char* funcName, int status);
+    void closeInputStream(audio_stream_in_t* stream);
+    void closeOutputStream(audio_stream_out_t* stream);
+    audio_hw_device_t* device() const { return mDevice; }
+
+   private:
+    audio_hw_device_t* mDevice;
+
+    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 AUDIO_HAL_VERSION
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/Device.cpp b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
similarity index 64%
rename from audio/2.0/default/Device.cpp
rename to audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
index 3727966..b295082 100644
--- a/audio/2.0/default/Device.cpp
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
@@ -1,49 +1,43 @@
 /*
-* 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.
-*/
+ * 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 <common/all-versions/IncludeGuard.h>
+
 //#define LOG_NDEBUG 0
 
-#include <algorithm>
 #include <memory.h>
 #include <string.h>
+#include <algorithm>
 
 #include <android/log.h>
 
-#include "Conversions.h"
-#include "Device.h"
-#include "HidlUtils.h"
-#include "StreamIn.h"
-#include "StreamOut.h"
-#include "Util.h"
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::HidlUtils;
+using ::android::hardware::audio::all_versions::implementation::isGainNormalized;
 
 namespace android {
 namespace hardware {
 namespace audio {
-namespace V2_0 {
+namespace AUDIO_HAL_VERSION {
 namespace implementation {
 
-Device::Device(audio_hw_device_t* device)
-        : mDevice(device) {
-}
+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));
+    ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice, strerror(-status));
     mDevice = nullptr;
 }
 
@@ -83,7 +77,7 @@
     return mDevice->set_parameters(mDevice, keysAndValues);
 }
 
-// Methods from ::android::hardware::audio::V2_0::IDevice follow.
+// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IDevice follow.
 Return<Result> Device::initCheck() {
     return analyzeStatus("init_check", mDevice->init_check(mDevice));
 }
@@ -96,16 +90,14 @@
         ALOGW("Can not set a master volume (%f) outside [0,1]", volume);
         return Result::INVALID_ARGUMENTS;
     }
-    return analyzeStatus("set_master_volume",
-                         mDevice->set_master_volume(mDevice, volume));
+    return analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume));
 }
 
 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));
+        retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume));
     }
     _hidl_cb(retval, volume);
     return Void();
@@ -117,8 +109,7 @@
 
 Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
     bool mute = false;
-    Result retval =
-        analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
+    Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
     _hidl_cb(retval, mute);
     return Void();
 }
@@ -126,8 +117,7 @@
 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));
+        retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute));
     }
     return retval;
 }
@@ -136,15 +126,13 @@
     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));
+        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) {
+Return<void> Device::getInputBufferSize(const AudioConfig& config, getInputBufferSize_cb _hidl_cb) {
     audio_config_t halConfig;
     HidlUtils::audioConfigToHal(config, &halConfig);
     size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
@@ -158,10 +146,8 @@
     return Void();
 }
 
-Return<void> Device::openOutputStream(int32_t ioHandle,
-                                      const DeviceAddress& device,
-                                      const AudioConfig& config,
-                                      AudioOutputFlag flags,
+Return<void> Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
+                                      const AudioConfig& config, AudioOutputFlag flags,
                                       openOutputStream_cb _hidl_cb) {
     audio_config_t halConfig;
     HidlUtils::audioConfigToHal(config, &halConfig);
@@ -170,13 +156,12 @@
         "open_output_stream handle: %d devices: %x flags: %#x "
         "srate: %d format %#x channels %x address %s",
         ioHandle, static_cast<audio_devices_t>(device.device),
-        static_cast<audio_output_flags_t>(flags), halConfig.sample_rate,
-        halConfig.format, halConfig.channel_mask,
-        deviceAddressToHal(device).c_str());
-    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());
+        static_cast<audio_output_flags_t>(flags), halConfig.sample_rate, halConfig.format,
+        halConfig.channel_mask, deviceAddressToHal(device).c_str());
+    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());
     ALOGV("open_output_stream status %d stream %p", status, halStream);
     sp<IStreamOut> streamOut;
     if (status == OK) {
@@ -184,16 +169,13 @@
     }
     AudioConfig suggestedConfig;
     HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
-    _hidl_cb(analyzeStatus("open_output_stream", status), streamOut,
-             suggestedConfig);
+    _hidl_cb(analyzeStatus("open_output_stream", status), streamOut, suggestedConfig);
     return Void();
 }
 
-Return<void> Device::openInputStream(int32_t ioHandle,
-                                     const DeviceAddress& device,
-                                     const AudioConfig& config,
-                                     AudioInputFlag flags, AudioSource source,
-                                     openInputStream_cb _hidl_cb) {
+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;
     HidlUtils::audioConfigToHal(config, &halConfig);
     audio_stream_in_t* halStream;
@@ -201,14 +183,12 @@
         "open_input_stream handle: %d devices: %x flags: %#x "
         "srate: %d format %#x channels %x address %s source %d",
         ioHandle, static_cast<audio_devices_t>(device.device),
-        static_cast<audio_input_flags_t>(flags), halConfig.sample_rate,
-        halConfig.format, halConfig.channel_mask,
-        deviceAddressToHal(device).c_str(),
+        static_cast<audio_input_flags_t>(flags), halConfig.sample_rate, halConfig.format,
+        halConfig.channel_mask, deviceAddressToHal(device).c_str(),
         static_cast<audio_source_t>(source));
     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(),
+        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));
     ALOGV("open_input_stream status %d stream %p", status, halStream);
     sp<IStreamIn> streamIn;
@@ -217,8 +197,7 @@
     }
     AudioConfig suggestedConfig;
     HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
-    _hidl_cb(analyzeStatus("open_input_stream", status), streamIn,
-             suggestedConfig);
+    _hidl_cb(analyzeStatus("open_input_stream", status), streamIn, suggestedConfig);
     return Void();
 }
 
@@ -232,15 +211,12 @@
     Result retval(Result::NOT_SUPPORTED);
     AudioPatchHandle patch = 0;
     if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
-        std::unique_ptr<audio_port_config[]> halSources(
-            HidlUtils::audioPortConfigsToHal(sources));
-        std::unique_ptr<audio_port_config[]> halSinks(
-            HidlUtils::audioPortConfigsToHal(sinks));
+        std::unique_ptr<audio_port_config[]> halSources(HidlUtils::audioPortConfigsToHal(sources));
+        std::unique_ptr<audio_port_config[]> halSinks(HidlUtils::audioPortConfigsToHal(sinks));
         audio_patch_handle_t halPatch = AUDIO_PATCH_HANDLE_NONE;
-        retval = analyzeStatus(
-            "create_audio_patch",
-            mDevice->create_audio_patch(mDevice, sources.size(), &halSources[0],
-                                        sinks.size(), &halSinks[0], &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);
         }
@@ -253,18 +229,15 @@
     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)));
+            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) {
+Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
     audio_port halPort;
     HidlUtils::audioPortToHal(port, &halPort);
-    Result retval = analyzeStatus("get_audio_port",
-                                  mDevice->get_audio_port(mDevice, &halPort));
+    Result retval = analyzeStatus("get_audio_port", mDevice->get_audio_port(mDevice, &halPort));
     AudioPort resultPort = port;
     if (retval == Result::OK) {
         HidlUtils::audioPortFromHal(halPort, &resultPort);
@@ -277,9 +250,8 @@
     if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
         struct audio_port_config halPortConfig;
         HidlUtils::audioPortConfigToHal(config, &halPortConfig);
-        return analyzeStatus(
-            "set_audio_port_config",
-            mDevice->set_audio_port_config(mDevice, &halPortConfig));
+        return analyzeStatus("set_audio_port_config",
+                             mDevice->set_audio_port_config(mDevice, &halPortConfig));
     }
     return Result::NOT_SUPPORTED;
 }
@@ -294,14 +266,12 @@
     return setParam(AudioParameter::keyScreenState, turnedOn);
 }
 
-Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys,
-                                   getParameters_cb _hidl_cb) {
+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<Result> Device::setParameters(const hidl_vec<ParameterValue>& parameters) {
     return setParametersImpl(parameters);
 }
 
@@ -313,7 +283,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
diff --git a/audio/2.0/default/DevicesFactory.h b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.h
similarity index 68%
rename from audio/2.0/default/DevicesFactory.h
rename to audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.h
index b046f9f..769adaa 100644
--- a/audio/2.0/default/DevicesFactory.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.h
@@ -14,24 +14,22 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HARDWARE_AUDIO_V2_0_DEVICESFACTORY_H
-#define ANDROID_HARDWARE_AUDIO_V2_0_DEVICESFACTORY_H
+#include <common/all-versions/IncludeGuard.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 AUDIO_HAL_VERSION {
 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::audio::AUDIO_HAL_VERSION::IDevice;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IDevicesFactory;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::Result;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hardware::hidl_vec;
@@ -39,21 +37,18 @@
 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;
+    // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IDevicesFactory follow.
+    Return<void> openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) override;
 
-  private:
+   private:
     static const char* deviceToString(IDevicesFactory::Device device);
-    static int loadAudioInterface(const char *if_name, audio_hw_device_t **dev);
-
+    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_HAL_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
-
-#endif  // ANDROID_HARDWARE_AUDIO_V2_0_DEVICESFACTORY_H
diff --git a/audio/2.0/default/DevicesFactory.cpp b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
similarity index 67%
rename from audio/2.0/default/DevicesFactory.cpp
rename to audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
index b913bc7..014b4d8 100644
--- a/audio/2.0/default/DevicesFactory.cpp
+++ b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
@@ -14,50 +14,50 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "DevicesFactoryHAL"
+#include <common/all-versions/IncludeGuard.h>
 
 #include <string.h>
 
 #include <android/log.h>
 
-#include "Device.h"
-#include "DevicesFactory.h"
-#include "PrimaryDevice.h"
-
 namespace android {
 namespace hardware {
 namespace audio {
-namespace V2_0 {
+namespace AUDIO_HAL_VERSION {
 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;
-        case IDevicesFactory::Device::STUB: return AUDIO_HARDWARE_MODULE_ID_STUB;
+        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;
+        case IDevicesFactory::Device::STUB:
+            return AUDIO_HARDWARE_MODULE_ID_STUB;
     }
     return nullptr;
 }
 
 // static
-int DevicesFactory::loadAudioInterface(const char *if_name, audio_hw_device_t **dev)
-{
-    const hw_module_t *mod;
+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));
+        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));
+        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) {
@@ -73,9 +73,9 @@
     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;
+// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IDevicesFactory follow.
+Return<void> DevicesFactory::openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) {
+    audio_hw_device_t* halDevice;
     Result retval(Result::INVALID_ARGUMENTS);
     sp<IDevice> result;
     const char* moduleName = deviceToString(device);
@@ -85,8 +85,8 @@
             if (device == IDevicesFactory::Device::PRIMARY) {
                 result = new PrimaryDevice(halDevice);
             } else {
-                result = new ::android::hardware::audio::V2_0::implementation::
-                    Device(halDevice);
+                result = new ::android::hardware::audio::AUDIO_HAL_VERSION::implementation::Device(
+                    halDevice);
             }
             retval = Result::OK;
         } else if (halStatus == -EINVAL) {
@@ -102,7 +102,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
diff --git a/audio/2.0/default/ParametersUtil.h b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h
similarity index 76%
rename from audio/2.0/default/ParametersUtil.h
rename to audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h
index 49036dc..df5adee 100644
--- a/audio/2.0/default/ParametersUtil.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h
@@ -14,35 +14,33 @@
  * limitations under the License.
  */
 
-#ifndef android_hardware_audio_V2_0_ParametersUtil_H_
-#define android_hardware_audio_V2_0_ParametersUtil_H_
+#include <common/all-versions/IncludeGuard.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 AUDIO_HAL_VERSION {
 namespace implementation {
 
-using ::android::hardware::audio::V2_0::ParameterValue;
-using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::ParameterValue;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::Result;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 
 class ParametersUtil {
-  public:
+   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);
+        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);
@@ -50,7 +48,7 @@
     Result setParametersImpl(const hidl_vec<ParameterValue>& parameters);
     Result setParams(const AudioParameter& param);
 
-  protected:
+   protected:
     virtual ~ParametersUtil() {}
 
     virtual char* halGetParameters(const char* keys) = 0;
@@ -58,9 +56,7 @@
 };
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
-
-#endif  // android_hardware_audio_V2_0_ParametersUtil_H_
diff --git a/audio/2.0/default/ParametersUtil.cpp b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h
similarity index 81%
rename from audio/2.0/default/ParametersUtil.cpp
rename to audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h
index c113ac7..a858a48 100644
--- a/audio/2.0/default/ParametersUtil.cpp
+++ b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-#include "ParametersUtil.h"
+#include <common/all-versions/IncludeGuard.h>
 
 namespace android {
 namespace hardware {
 namespace audio {
-namespace V2_0 {
+namespace AUDIO_HAL_VERSION {
 namespace implementation {
 
 /** Converts a status_t in Result according to the rules of AudioParameter::get*
@@ -72,17 +72,14 @@
 
 void ParametersUtil::getParametersImpl(
     const hidl_vec<hidl_string>& keys,
-    std::function<void(Result retval,
-                       const hidl_vec<ParameterValue>& parameters)>
-        cb) {
+    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 = (keys.size() == 0 || halValues->size() != 0)
-                        ? Result::OK
-                        : Result::NOT_SUPPORTED;
+    Result retval =
+        (keys.size() == 0 || halValues->size() != 0) ? Result::OK : Result::NOT_SUPPORTED;
     hidl_vec<ParameterValue> result;
     result.resize(halValues->size());
     String8 halKey, halValue;
@@ -99,8 +96,7 @@
     cb(retval, result);
 }
 
-std::unique_ptr<AudioParameter> ParametersUtil::getParams(
-    const AudioParameter& keys) {
+std::unique_ptr<AudioParameter> ParametersUtil::getParams(const AudioParameter& keys) {
     String8 paramsAndValues;
     char* halValues = halGetParameters(keys.keysToString().string());
     if (halValues != NULL) {
@@ -114,8 +110,7 @@
 
 Result ParametersUtil::setParam(const char* name, bool value) {
     AudioParameter param;
-    param.add(String8(name), String8(value ? AudioParameter::valueOn
-                                           : AudioParameter::valueOff));
+    param.add(String8(name), String8(value ? AudioParameter::valueOn : AudioParameter::valueOff));
     return setParams(param);
 }
 
@@ -131,12 +126,10 @@
     return setParams(param);
 }
 
-Result ParametersUtil::setParametersImpl(
-    const hidl_vec<ParameterValue>& parameters) {
+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()));
+        params.add(String8(parameters[i].key.c_str()), String8(parameters[i].value.c_str()));
     }
     return setParams(params);
 }
@@ -144,23 +137,29 @@
 Result ParametersUtil::setParams(const AudioParameter& param) {
     int halStatus = halSetParameters(param.toString().string());
     switch (halStatus) {
-        case OK: return Result::OK;
-        case -EINVAL: return Result::INVALID_ARGUMENTS;
-        case -ENODATA: return Result::INVALID_STATE;
-        case -ENODEV: return Result::NOT_INITIALIZED;
+        case OK:
+            return Result::OK;
+        case -EINVAL:
+            return Result::INVALID_ARGUMENTS;
+        case -ENODATA:
+            return Result::INVALID_STATE;
+        case -ENODEV:
+            return Result::NOT_INITIALIZED;
         // The rest of the API (*::analyseStatus) returns NOT_SUPPORTED
         // when the legacy API returns -ENOSYS
         // However the legacy API explicitly state that for get_paramers,
         // -ENOSYS should be returned if
         // "the implementation does not accept a parameter change while the
         //  output is active but the parameter is acceptable otherwise"
-        case -ENOSYS: return Result::INVALID_STATE;
-        default: return Result::INVALID_ARGUMENTS;
+        case -ENOSYS:
+            return Result::INVALID_STATE;
+        default:
+            return Result::INVALID_ARGUMENTS;
     }
 }
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.h b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.h
new file mode 100644
index 0000000..240b221
--- /dev/null
+++ b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.h
@@ -0,0 +1,104 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioConfig;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioInputFlag;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMode;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioOutputFlag;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPort;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPortConfig;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IDevice;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IPrimaryDevice;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamIn;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamOut;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::ParameterValue;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::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::AUDIO_HAL_VERSION::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<bool> supportsAudioPatches() 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 hidl_handle& fd) override;
+
+    // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::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 AUDIO_HAL_VERSION
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/PrimaryDevice.cpp b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h
similarity index 71%
rename from audio/2.0/default/PrimaryDevice.cpp
rename to audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h
index a4a8206..3ce047a 100644
--- a/audio/2.0/default/PrimaryDevice.cpp
+++ b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h
@@ -14,24 +14,19 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "PrimaryDeviceHAL"
-
-#include "PrimaryDevice.h"
-#include "Util.h"
+#include <common/all-versions/IncludeGuard.h>
 
 namespace android {
 namespace hardware {
 namespace audio {
-namespace V2_0 {
+namespace AUDIO_HAL_VERSION {
 namespace implementation {
 
-PrimaryDevice::PrimaryDevice(audio_hw_device_t* device)
-        : mDevice(new Device(device)) {
-}
+PrimaryDevice::PrimaryDevice(audio_hw_device_t* device) : mDevice(new Device(device)) {}
 
 PrimaryDevice::~PrimaryDevice() {}
 
-// Methods from ::android::hardware::audio::V2_0::IDevice follow.
+// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IDevice follow.
 Return<Result> PrimaryDevice::initCheck() {
     return mDevice->initCheck();
 }
@@ -65,28 +60,25 @@
     return mDevice->getInputBufferSize(config, _hidl_cb);
 }
 
-Return<void> PrimaryDevice::openOutputStream(int32_t ioHandle,
-                                             const DeviceAddress& device,
-                                             const AudioConfig& config,
-                                             AudioOutputFlag flags,
+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::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<bool> PrimaryDevice::supportsAudioPatches() {
     return mDevice->supportsAudioPatches();
 }
 
-Return<void> PrimaryDevice::createAudioPatch(
-    const hidl_vec<AudioPortConfig>& sources,
-    const hidl_vec<AudioPortConfig>& sinks, createAudioPatch_cb _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);
 }
 
@@ -94,13 +86,11 @@
     return mDevice->releaseAudioPatch(patch);
 }
 
-Return<void> PrimaryDevice::getAudioPort(const AudioPort& port,
-                                         getAudioPort_cb _hidl_cb) {
+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<Result> PrimaryDevice::setAudioPortConfig(const AudioPortConfig& config) {
     return mDevice->setAudioPortConfig(config);
 }
 
@@ -117,8 +107,7 @@
     return mDevice->getParameters(keys, _hidl_cb);
 }
 
-Return<Result> PrimaryDevice::setParameters(
-    const hidl_vec<ParameterValue>& parameters) {
+Return<Result> PrimaryDevice::setParameters(const hidl_vec<ParameterValue>& parameters) {
     return mDevice->setParameters(parameters);
 }
 
@@ -126,15 +115,14 @@
     return mDevice->debugDump(fd);
 }
 
-// Methods from ::android::hardware::audio::V2_0::IPrimaryDevice follow.
+// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IPrimaryDevice follow.
 Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
-    if (!isGainNormalized(volume)) {
+    if (!all_versions::implementation::isGainNormalized(volume)) {
         ALOGW("Can not set a voice volume (%f) outside [0,1]", volume);
         return Result::INVALID_ARGUMENTS;
     }
-    return mDevice->analyzeStatus(
-        "set_voice_volume",
-        mDevice->device()->set_voice_volume(mDevice->device(), volume));
+    return mDevice->analyzeStatus("set_voice_volume",
+                                  mDevice->device()->set_voice_volume(mDevice->device(), volume));
 }
 
 Return<Result> PrimaryDevice::setMode(AudioMode mode) {
@@ -151,12 +139,11 @@
     };
 
     return mDevice->analyzeStatus(
-        "set_mode", mDevice->device()->set_mode(
-                        mDevice->device(), static_cast<audio_mode_t>(mode)));
+        "set_mode",
+        mDevice->device()->set_mode(mDevice->device(), static_cast<audio_mode_t>(mode)));
 }
 
-Return<void> PrimaryDevice::getBtScoNrecEnabled(
-    getBtScoNrecEnabled_cb _hidl_cb) {
+Return<void> PrimaryDevice::getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb) {
     bool enabled;
     Result retval = mDevice->getParam(AudioParameter::keyBtNrec, &enabled);
     _hidl_cb(retval, enabled);
@@ -167,8 +154,7 @@
     return mDevice->setParam(AudioParameter::keyBtNrec, enabled);
 }
 
-Return<void> PrimaryDevice::getBtScoWidebandEnabled(
-    getBtScoWidebandEnabled_cb _hidl_cb) {
+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);
@@ -188,8 +174,7 @@
 }
 
 Return<Result> PrimaryDevice::setTtyMode(IPrimaryDevice::TtyMode mode) {
-    return mDevice->setParam(AUDIO_PARAMETER_KEY_TTY_MODE,
-                             static_cast<int>(mode));
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_TTY_MODE, static_cast<int>(mode));
 }
 
 Return<void> PrimaryDevice::getHacEnabled(getHacEnabled_cb _hidl_cb) {
@@ -204,7 +189,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
diff --git a/audio/2.0/default/Stream.h b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h
similarity index 64%
rename from audio/2.0/default/Stream.h
rename to audio/core/all-versions/default/include/core/all-versions/default/Stream.h
index e29af53..4196dec 100644
--- a/audio/2.0/default/Stream.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h
@@ -14,32 +14,28 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HARDWARE_AUDIO_V2_0_STREAM_H
-#define ANDROID_HARDWARE_AUDIO_V2_0_STREAM_H
+#include <common/all-versions/IncludeGuard.h>
 
 #include <vector>
 
-#include <android/hardware/audio/2.0/IStream.h>
 #include <hardware/audio.h>
 #include <hidl/Status.h>
 
 #include <hidl/MQDescriptor.h>
 
-#include "ParametersUtil.h"
-
 namespace android {
 namespace hardware {
 namespace audio {
-namespace V2_0 {
+namespace AUDIO_HAL_VERSION {
 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::audio::common::AUDIO_HAL_VERSION::AudioChannelMask;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioFormat;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IStream;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::ParameterValue;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::Result;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hardware::hidl_vec;
@@ -56,36 +52,36 @@
      */
     static constexpr uint32_t MAX_BUFFER_SIZE = 2 << 30 /* == 1GiB */;
 
-    // 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 hidl_handle& fd)  override;
+    // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::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 hidl_handle& fd) override;
     Return<Result> start() override;
     Return<Result> stop() override;
     Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
     Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
-    Return<Result> close()  override;
+    Return<Result> close() override;
 
     // Utility methods for extending interfaces.
     static Result analyzeStatus(const char* funcName, int status);
@@ -93,7 +89,7 @@
                                 const std::vector<int>& ignoreErrors);
 
    private:
-    audio_stream_t *mStream;
+    audio_stream_t* mStream;
 
     virtual ~Stream();
 
@@ -102,21 +98,20 @@
     int halSetParameters(const char* keysAndValues) override;
 };
 
-
 template <typename T>
 struct StreamMmap : public RefBase {
     explicit StreamMmap(T* stream) : mStream(stream) {}
 
     Return<Result> start();
     Return<Result> stop();
-    Return<void> createMmapBuffer(
-            int32_t minSizeFrames, size_t frameSize, IStream::createMmapBuffer_cb _hidl_cb);
+    Return<void> createMmapBuffer(int32_t minSizeFrames, size_t frameSize,
+                                  IStream::createMmapBuffer_cb _hidl_cb);
     Return<void> getMmapPosition(IStream::getMmapPosition_cb _hidl_cb);
 
- private:
-   StreamMmap() {}
+   private:
+    StreamMmap() {}
 
-   T *mStream;
+    T* mStream;
 };
 
 template <typename T>
@@ -143,13 +138,12 @@
     if (mStream->create_mmap_buffer != NULL) {
         struct audio_mmap_buffer_info halInfo;
         retval = Stream::analyzeStatus(
-                "create_mmap_buffer",
-                mStream->create_mmap_buffer(mStream, minSizeFrames, &halInfo));
+            "create_mmap_buffer", mStream->create_mmap_buffer(mStream, minSizeFrames, &halInfo));
         if (retval == Result::OK) {
             hidlHandle = native_handle_create(1, 0);
             hidlHandle->data[0] = halInfo.shared_memory_fd;
-            info.sharedMemory = hidl_memory("audio_buffer", hidlHandle,
-                                            frameSize *halInfo.buffer_size_frames);
+            info.sharedMemory =
+                hidl_memory("audio_buffer", hidlHandle, frameSize * halInfo.buffer_size_frames);
             info.bufferSizeFrames = halInfo.buffer_size_frames;
             info.burstSizeFrames = halInfo.burst_size_frames;
         }
@@ -168,9 +162,8 @@
 
     if (mStream->get_mmap_position != NULL) {
         struct audio_mmap_position halPosition;
-        retval = Stream::analyzeStatus(
-                "get_mmap_position",
-                mStream->get_mmap_position(mStream, &halPosition));
+        retval = Stream::analyzeStatus("get_mmap_position",
+                                       mStream->get_mmap_position(mStream, &halPosition));
         if (retval == Result::OK) {
             position.timeNanoseconds = halPosition.time_nanoseconds;
             position.positionFrames = halPosition.position_frames;
@@ -181,9 +174,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
-
-#endif  // ANDROID_HARDWARE_AUDIO_V2_0_STREAM_H
diff --git a/audio/2.0/default/Stream.cpp b/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h
similarity index 69%
rename from audio/2.0/default/Stream.cpp
rename to audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h
index effdd28..92cff72 100644
--- a/audio/2.0/default/Stream.cpp
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h
@@ -14,30 +14,24 @@
  * limitations under the License.
  */
 
+#include <common/all-versions/IncludeGuard.h>
+
 #include <inttypes.h>
 
-#define LOG_TAG "StreamHAL"
-
+#include <android/log.h>
 #include <hardware/audio.h>
 #include <hardware/audio_effect.h>
 #include <media/TypeConverter.h>
-#include <android/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 AUDIO_HAL_VERSION {
 namespace implementation {
 
-Stream::Stream(audio_stream_t* stream)
-        : mStream(stream) {
-}
+Stream::Stream(audio_stream_t* stream) : mStream(stream) {}
 
 Stream::~Stream() {
     mStream = nullptr;
@@ -61,12 +55,18 @@
         ALOGW("Error from HAL stream in function %s: %s", 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;
+        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;
     }
 }
 
@@ -78,76 +78,76 @@
     return mStream->set_parameters(mStream, keysAndValues);
 }
 
-// Methods from ::android::hardware::audio::V2_0::IStream follow.
-Return<uint64_t> Stream::getFrameSize()  {
+// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::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{};
 }
 
-Return<uint64_t> Stream::getFrameCount()  {
+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<uint64_t> Stream::getBufferSize() {
     return mStream->get_buffer_size(mStream);
 }
 
-Return<uint32_t> Stream::getSampleRate()  {
+Return<uint32_t> Stream::getSampleRate() {
     return mStream->get_sample_rate(mStream);
 }
 
-Return<void> Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  {
+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);
+        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<Result> Stream::setSampleRate(uint32_t sampleRateHz) {
     return setParam(AudioParameter::keySamplingRate, static_cast<int>(sampleRateHz));
 }
 
-Return<AudioChannelMask> Stream::getChannelMask()  {
+Return<AudioChannelMask> Stream::getChannelMask() {
     return AudioChannelMask(mStream->get_channels(mStream));
 }
 
-Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  {
+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);
+        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);
+    _hidl_cb(channelMasks);
     return Void();
 }
 
-Return<Result> Stream::setChannelMask(AudioChannelMask mask)  {
+Return<Result> Stream::setChannelMask(AudioChannelMask mask) {
     return setParam(AudioParameter::keyChannels, static_cast<int>(mask));
 }
 
-Return<AudioFormat> Stream::getFormat()  {
+Return<AudioFormat> Stream::getFormat() {
     return AudioFormat(mStream->get_format(mStream));
 }
 
-Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb)  {
+Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
     String8 halListValue;
     Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
     hidl_vec<AudioFormat> formats;
@@ -159,15 +159,15 @@
             formats[i] = AudioFormat(halFormats[i]);
         }
     }
-     _hidl_cb(formats);
+    _hidl_cb(formats);
     return Void();
 }
 
-Return<Result> Stream::setFormat(AudioFormat format)  {
+Return<Result> Stream::setFormat(AudioFormat format) {
     return setParam(AudioParameter::keyFormat, static_cast<int>(format));
 }
 
-Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb)  {
+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);
@@ -175,7 +175,7 @@
     return Void();
 }
 
-Return<Result> Stream::addEffect(uint64_t effectId)  {
+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));
@@ -185,94 +185,92 @@
     }
 }
 
-Return<Result> Stream::removeEffect(uint64_t effectId)  {
+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));
+        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<Result> Stream::standby() {
     return analyzeStatus("standby", mStream->standby(mStream));
 }
 
-Return<AudioDevice> Stream::getDevice()  {
+Return<AudioDevice> Stream::getDevice() {
     int device;
     Result retval = getParam(AudioParameter::keyRouting, &device);
     return retval == Result::OK ? static_cast<AudioDevice>(device) : AudioDevice::NONE;
 }
 
-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());
+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));
+    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<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected) {
     return setParam(
-            connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect,
-            deviceAddressToHal(address).c_str());
+        connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect,
+        deviceAddressToHal(address).c_str());
 }
 
-Return<Result> Stream::setHwAvSync(uint32_t hwAvSync)  {
+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)  {
+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<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters) {
     return setParametersImpl(parameters);
 }
 
-Return<void> Stream::debugDump(const hidl_handle& fd)  {
+Return<void> Stream::debugDump(const hidl_handle& fd) {
     if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
         analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
     }
     return Void();
 }
 
-Return<Result>  Stream::start() {
+Return<Result> Stream::start() {
     return Result::NOT_SUPPORTED;
 }
 
-Return<Result>  Stream::stop() {
+Return<Result> Stream::stop() {
     return Result::NOT_SUPPORTED;
 }
 
-Return<void>  Stream::createMmapBuffer(int32_t minSizeFrames __unused,
-                                       createMmapBuffer_cb _hidl_cb) {
+Return<void> Stream::createMmapBuffer(int32_t minSizeFrames __unused,
+                                      createMmapBuffer_cb _hidl_cb) {
     Result retval(Result::NOT_SUPPORTED);
     MmapBufferInfo info;
     _hidl_cb(retval, info);
     return Void();
 }
 
-Return<void>  Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) {
+Return<void> Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) {
     Result retval(Result::NOT_SUPPORTED);
     MmapPosition position;
     _hidl_cb(retval, position);
     return Void();
 }
 
-Return<Result> Stream::close()  {
+Return<Result> Stream::close() {
     return Result::NOT_SUPPORTED;
 }
 
-} // namespace implementation
-}  // namespace V2_0
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.h b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.h
new file mode 100644
index 0000000..7380dae
--- /dev/null
+++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.h
@@ -0,0 +1,118 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <atomic>
+#include <memory>
+
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <utils/Thread.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioFormat;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IStream;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamIn;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::ParameterValue;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::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 {
+    typedef MessageQueue<ReadParameters, kSynchronizedReadWrite> CommandMQ;
+    typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
+    typedef MessageQueue<ReadStatus, kSynchronizedReadWrite> StatusMQ;
+
+    StreamIn(const sp<Device>& device, audio_stream_in_t* stream);
+
+    // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::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 hidl_handle& fd) override;
+    Return<Result> close() override;
+
+    // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamIn follow.
+    Return<void> getAudioSource(getAudioSource_cb _hidl_cb) override;
+    Return<Result> setGain(float gain) override;
+    Return<void> prepareForReading(uint32_t frameSize, uint32_t framesCount,
+                                   prepareForReading_cb _hidl_cb) override;
+    Return<uint32_t> getInputFramesLost() override;
+    Return<void> getCapturePosition(getCapturePosition_cb _hidl_cb) override;
+    Return<Result> start() override;
+    Return<Result> stop() override;
+    Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
+    Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
+
+    static Result getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames,
+                                         uint64_t* time);
+
+   private:
+    bool mIsClosed;
+    const sp<Device> mDevice;
+    audio_stream_in_t* mStream;
+    const sp<Stream> mStreamCommon;
+    const sp<StreamMmap<audio_stream_in_t>> mStreamMmap;
+    std::unique_ptr<CommandMQ> mCommandMQ;
+    std::unique_ptr<DataMQ> mDataMQ;
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    EventFlag* mEfGroup;
+    std::atomic<bool> mStopReadThread;
+    sp<Thread> mReadThread;
+
+    virtual ~StreamIn();
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/StreamIn.cpp b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
similarity index 82%
rename from audio/2.0/default/StreamIn.cpp
rename to audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
index 61d5d8e..abee225 100644
--- a/audio/2.0/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "StreamInHAL"
+#include <common/all-versions/IncludeGuard.h>
+
 //#define LOG_NDEBUG 0
 #define ATRACE_TAG ATRACE_TAG_AUDIO
 
@@ -23,27 +24,24 @@
 #include <utils/Trace.h>
 #include <memory>
 
-#include "StreamIn.h"
-#include "Util.h"
-
-using ::android::hardware::audio::V2_0::MessageQueueFlagBits;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::MessageQueueFlagBits;
+using ::android::hardware::audio::all_versions::implementation::isGainNormalized;
 
 namespace android {
 namespace hardware {
 namespace audio {
-namespace V2_0 {
+namespace AUDIO_HAL_VERSION {
 namespace implementation {
 
-using ::android::hardware::audio::common::V2_0::ThreadInfo;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::ThreadInfo;
 
 namespace {
 
 class ReadThread : public Thread {
    public:
     // ReadThread's lifespan never exceeds StreamIn's lifespan.
-    ReadThread(std::atomic<bool>* stop, audio_stream_in_t* stream,
-               StreamIn::CommandMQ* commandMQ, StreamIn::DataMQ* dataMQ,
-               StreamIn::StatusMQ* statusMQ, EventFlag* efGroup)
+    ReadThread(std::atomic<bool>* stop, audio_stream_in_t* stream, StreamIn::CommandMQ* commandMQ,
+               StreamIn::DataMQ* dataMQ, StreamIn::StatusMQ* statusMQ, EventFlag* efGroup)
         : Thread(false /*canCallJava*/),
           mStop(stop),
           mStream(stream),
@@ -99,8 +97,7 @@
 
 void ReadThread::doGetCapturePosition() {
     mStatus.retval = StreamIn::getCapturePositionImpl(
-        mStream, &mStatus.reply.capturePosition.frames,
-        &mStatus.reply.capturePosition.time);
+        mStream, &mStatus.reply.capturePosition.frames, &mStatus.reply.capturePosition.time);
 }
 
 bool ReadThread::threadLoop() {
@@ -109,10 +106,8 @@
     // as the Thread uses mutexes, and this can lead to priority inversion.
     while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
         uint32_t efState = 0;
-        mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL),
-                       &efState);
-        if (!(efState &
-              static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) {
+        mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
+        if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) {
             continue;  // Nothing to do.
         }
         if (!mCommandMQ->read(&mParameters)) {
@@ -127,8 +122,7 @@
                 doGetCapturePosition();
                 break;
             default:
-                ALOGE("Unknown read thread command code %d",
-                      mParameters.command);
+                ALOGE("Unknown read thread command code %d", mParameters.command);
                 mStatus.retval = Result::NOT_SUPPORTED;
                 break;
         }
@@ -162,14 +156,13 @@
     }
     if (mEfGroup) {
         status_t status = EventFlag::deleteEventFlag(&mEfGroup);
-        ALOGE_IF(status, "read MQ event flag deletion error: %s",
-                 strerror(-status));
+        ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
     }
     mDevice->closeInputStream(mStream);
     mStream = nullptr;
 }
 
-// Methods from ::android::hardware::audio::V2_0::IStream follow.
+// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStream follow.
 Return<uint64_t> StreamIn::getFrameSize() {
     return audio_stream_in_frame_size(mStream);
 }
@@ -186,8 +179,7 @@
     return mStreamCommon->getSampleRate();
 }
 
-Return<void> StreamIn::getSupportedSampleRates(
-    getSupportedSampleRates_cb _hidl_cb) {
+Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
     return mStreamCommon->getSupportedSampleRates(_hidl_cb);
 }
 
@@ -199,8 +191,7 @@
     return mStreamCommon->getChannelMask();
 }
 
-Return<void> StreamIn::getSupportedChannelMasks(
-    getSupportedChannelMasks_cb _hidl_cb) {
+Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
     return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
 }
 
@@ -244,8 +235,7 @@
     return mStreamCommon->setDevice(address);
 }
 
-Return<Result> StreamIn::setConnectedState(const DeviceAddress& address,
-                                           bool connected) {
+Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected) {
     return mStreamCommon->setConnectedState(address, connected);
 }
 
@@ -253,13 +243,11 @@
     return mStreamCommon->setHwAvSync(hwAvSync);
 }
 
-Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys,
-                                     getParameters_cb _hidl_cb) {
+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<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& parameters) {
     return mStreamCommon->setParameters(parameters);
 }
 
@@ -275,10 +263,9 @@
     return mStreamMmap->stop();
 }
 
-Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames,
-                                        createMmapBuffer_cb _hidl_cb) {
-    return mStreamMmap->createMmapBuffer(
-        minSizeFrames, audio_stream_in_frame_size(mStream), _hidl_cb);
+Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
+    return mStreamMmap->createMmapBuffer(minSizeFrames, audio_stream_in_frame_size(mStream),
+                                         _hidl_cb);
 }
 
 Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
@@ -297,11 +284,10 @@
     return Result::OK;
 }
 
-// Methods from ::android::hardware::audio::V2_0::IStreamIn follow.
+// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamIn follow.
 Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb) {
     int halSource;
-    Result retval =
-        mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource);
+    Result retval = mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource);
     AudioSource source(AudioSource::DEFAULT);
     if (retval == Result::OK) {
         source = AudioSource(halSource);
@@ -318,16 +304,15 @@
     return Stream::analyzeStatus("set_gain", mStream->set_gain(mStream, gain));
 }
 
-Return<void> StreamIn::prepareForReading(uint32_t frameSize,
-                                         uint32_t framesCount,
+Return<void> StreamIn::prepareForReading(uint32_t frameSize, uint32_t framesCount,
                                          prepareForReading_cb _hidl_cb) {
     status_t status;
     ThreadInfo threadInfo = {0, 0};
 
     // Wrap the _hidl_cb to return an error
     auto sendError = [&threadInfo, &_hidl_cb](Result result) {
-        _hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(),
-                 StatusMQ::Descriptor(), threadInfo);
+        _hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(),
+                 threadInfo);
 
     };
 
@@ -341,8 +326,7 @@
 
     // Check frameSize and framesCount
     if (frameSize == 0 || framesCount == 0) {
-        ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize,
-              framesCount);
+        ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize, framesCount);
         sendError(Result::INVALID_ARGUMENTS);
         return Void();
     }
@@ -353,12 +337,10 @@
         sendError(Result::INVALID_ARGUMENTS);
         return Void();
     }
-    std::unique_ptr<DataMQ> tempDataMQ(
-        new DataMQ(frameSize * framesCount, true /* EventFlag */));
+    std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */));
 
     std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
-    if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() ||
-        !tempStatusMQ->isValid()) {
+    if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
         ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid");
         ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
         ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
@@ -366,8 +348,7 @@
         return Void();
     }
     EventFlag* tempRawEfGroup{};
-    status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(),
-                                        &tempRawEfGroup);
+    status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &tempRawEfGroup);
     std::unique_ptr<EventFlag, void (*)(EventFlag*)> tempElfGroup(
         tempRawEfGroup, [](auto* ef) { EventFlag::deleteEventFlag(&ef); });
     if (status != OK || !tempElfGroup) {
@@ -377,9 +358,9 @@
     }
 
     // Create and launch the thread.
-    auto tempReadThread = std::make_unique<ReadThread>(
-        &mStopReadThread, mStream, tempCommandMQ.get(), tempDataMQ.get(),
-        tempStatusMQ.get(), tempElfGroup.get());
+    auto tempReadThread =
+        std::make_unique<ReadThread>(&mStopReadThread, mStream, tempCommandMQ.get(),
+                                     tempDataMQ.get(), tempStatusMQ.get(), tempElfGroup.get());
     if (!tempReadThread->init()) {
         ALOGW("failed to start reader thread: %s", strerror(-status));
         sendError(Result::INVALID_ARGUMENTS);
@@ -399,8 +380,8 @@
     mEfGroup = tempElfGroup.release();
     threadInfo.pid = getpid();
     threadInfo.tid = mReadThread->getTid();
-    _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(),
-             *mStatusMQ->getDesc(), threadInfo);
+    _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
+             threadInfo);
     return Void();
 }
 
@@ -409,8 +390,8 @@
 }
 
 // static
-Result StreamIn::getCapturePositionImpl(audio_stream_in_t* stream,
-                                        uint64_t* frames, uint64_t* time) {
+Result StreamIn::getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames,
+                                        uint64_t* time) {
     // HAL may have a stub function, always returning ENOSYS, don't
     // spam the log in this case.
     static const std::vector<int> ignoredErrors{ENOSYS};
@@ -435,7 +416,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.h b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.h
new file mode 100644
index 0000000..4cfe2e3
--- /dev/null
+++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.h
@@ -0,0 +1,132 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <atomic>
+#include <memory>
+
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <utils/Thread.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioFormat;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::AudioDrain;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IStream;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamOut;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamOutCallback;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::ParameterValue;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::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 {
+    typedef MessageQueue<WriteCommand, kSynchronizedReadWrite> CommandMQ;
+    typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
+    typedef MessageQueue<WriteStatus, kSynchronizedReadWrite> StatusMQ;
+
+    StreamOut(const sp<Device>& device, audio_stream_out_t* stream);
+
+    // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::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 hidl_handle& fd) override;
+    Return<Result> close() override;
+
+    // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamOut follow.
+    Return<uint32_t> getLatency() override;
+    Return<Result> setVolume(float left, float right) override;
+    Return<void> prepareForWriting(uint32_t frameSize, uint32_t framesCount,
+                                   prepareForWriting_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<Result> clearCallback() 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;
+    Return<Result> start() override;
+    Return<Result> stop() override;
+    Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
+    Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
+
+    static Result getPresentationPositionImpl(audio_stream_out_t* stream, uint64_t* frames,
+                                              TimeSpec* timeStamp);
+
+   private:
+    bool mIsClosed;
+    const sp<Device> mDevice;
+    audio_stream_out_t* mStream;
+    const sp<Stream> mStreamCommon;
+    const sp<StreamMmap<audio_stream_out_t>> mStreamMmap;
+    sp<IStreamOutCallback> mCallback;
+    std::unique_ptr<CommandMQ> mCommandMQ;
+    std::unique_ptr<DataMQ> mDataMQ;
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    EventFlag* mEfGroup;
+    std::atomic<bool> mStopWriteThread;
+    sp<Thread> mWriteThread;
+
+    virtual ~StreamOut();
+
+    static int asyncCallback(stream_callback_event_t event, void* param, void* cookie);
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/StreamOut.cpp b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h
similarity index 80%
rename from audio/2.0/default/StreamOut.cpp
rename to audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h
index 49a6b12..bdbeb38 100644
--- a/audio/2.0/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "StreamOutHAL"
+#include <common/all-versions/IncludeGuard.h>
+
 //#define LOG_NDEBUG 0
 #define ATRACE_TAG ATRACE_TAG_AUDIO
 
@@ -24,16 +25,14 @@
 #include <hardware/audio.h>
 #include <utils/Trace.h>
 
-#include "StreamOut.h"
-#include "Util.h"
-
 namespace android {
 namespace hardware {
 namespace audio {
-namespace V2_0 {
+namespace AUDIO_HAL_VERSION {
 namespace implementation {
 
-using ::android::hardware::audio::common::V2_0::ThreadInfo;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::ThreadInfo;
+using ::android::hardware::audio::all_versions::implementation::isGainNormalized;
 
 namespace {
 
@@ -89,9 +88,9 @@
 }
 
 void WriteThread::doGetPresentationPosition() {
-    mStatus.retval = StreamOut::getPresentationPositionImpl(
-        mStream, &mStatus.reply.presentationPosition.frames,
-        &mStatus.reply.presentationPosition.timeStamp);
+    mStatus.retval =
+        StreamOut::getPresentationPositionImpl(mStream, &mStatus.reply.presentationPosition.frames,
+                                               &mStatus.reply.presentationPosition.timeStamp);
 }
 
 void WriteThread::doGetLatency() {
@@ -105,10 +104,8 @@
     // as the Thread uses mutexes, and this can lead to priority inversion.
     while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
         uint32_t efState = 0;
-        mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY),
-                       &efState);
-        if (!(efState &
-              static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) {
+        mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
+        if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) {
             continue;  // Nothing to do.
         }
         if (!mCommandMQ->read(&mStatus.replyTo)) {
@@ -159,8 +156,7 @@
     }
     if (mEfGroup) {
         status_t status = EventFlag::deleteEventFlag(&mEfGroup);
-        ALOGE_IF(status, "write MQ event flag deletion error: %s",
-                 strerror(-status));
+        ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status));
     }
     mCallback.clear();
     mDevice->closeOutputStream(mStream);
@@ -170,7 +166,7 @@
     mStream = nullptr;
 }
 
-// Methods from ::android::hardware::audio::V2_0::IStream follow.
+// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStream follow.
 Return<uint64_t> StreamOut::getFrameSize() {
     return audio_stream_out_frame_size(mStream);
 }
@@ -187,8 +183,7 @@
     return mStreamCommon->getSampleRate();
 }
 
-Return<void> StreamOut::getSupportedSampleRates(
-    getSupportedSampleRates_cb _hidl_cb) {
+Return<void> StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
     return mStreamCommon->getSupportedSampleRates(_hidl_cb);
 }
 
@@ -200,8 +195,7 @@
     return mStreamCommon->getChannelMask();
 }
 
-Return<void> StreamOut::getSupportedChannelMasks(
-    getSupportedChannelMasks_cb _hidl_cb) {
+Return<void> StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
     return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
 }
 
@@ -245,8 +239,7 @@
     return mStreamCommon->setDevice(address);
 }
 
-Return<Result> StreamOut::setConnectedState(const DeviceAddress& address,
-                                            bool connected) {
+Return<Result> StreamOut::setConnectedState(const DeviceAddress& address, bool connected) {
     return mStreamCommon->setConnectedState(address, connected);
 }
 
@@ -259,8 +252,7 @@
     return mStreamCommon->getParameters(keys, _hidl_cb);
 }
 
-Return<Result> StreamOut::setParameters(
-    const hidl_vec<ParameterValue>& parameters) {
+Return<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& parameters) {
     return mStreamCommon->setParameters(parameters);
 }
 
@@ -280,7 +272,7 @@
     return Result::OK;
 }
 
-// Methods from ::android::hardware::audio::V2_0::IStreamOut follow.
+// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamOut follow.
 Return<uint32_t> StreamOut::getLatency() {
     return mStream->get_latency(mStream);
 }
@@ -290,24 +282,21 @@
         return Result::NOT_SUPPORTED;
     }
     if (!isGainNormalized(left)) {
-        ALOGW("Can not set a stream output volume {%f, %f} outside [0,1]", left,
-              right);
+        ALOGW("Can not set a stream output volume {%f, %f} outside [0,1]", left, right);
         return Result::INVALID_ARGUMENTS;
     }
-    return Stream::analyzeStatus("set_volume",
-                                 mStream->set_volume(mStream, left, right));
+    return Stream::analyzeStatus("set_volume", mStream->set_volume(mStream, left, right));
 }
 
-Return<void> StreamOut::prepareForWriting(uint32_t frameSize,
-                                          uint32_t framesCount,
+Return<void> StreamOut::prepareForWriting(uint32_t frameSize, uint32_t framesCount,
                                           prepareForWriting_cb _hidl_cb) {
     status_t status;
     ThreadInfo threadInfo = {0, 0};
 
     // Wrap the _hidl_cb to return an error
     auto sendError = [&threadInfo, &_hidl_cb](Result result) {
-        _hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(),
-                 StatusMQ::Descriptor(), threadInfo);
+        _hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(),
+                 threadInfo);
 
     };
 
@@ -321,8 +310,7 @@
 
     // Check frameSize and framesCount
     if (frameSize == 0 || framesCount == 0) {
-        ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize,
-              framesCount);
+        ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize, framesCount);
         sendError(Result::INVALID_ARGUMENTS);
         return Void();
     }
@@ -332,12 +320,10 @@
         sendError(Result::INVALID_ARGUMENTS);
         return Void();
     }
-    std::unique_ptr<DataMQ> tempDataMQ(
-        new DataMQ(frameSize * framesCount, true /* EventFlag */));
+    std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */));
 
     std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
-    if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() ||
-        !tempStatusMQ->isValid()) {
+    if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
         ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid");
         ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
         ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
@@ -345,8 +331,7 @@
         return Void();
     }
     EventFlag* tempRawEfGroup{};
-    status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(),
-                                        &tempRawEfGroup);
+    status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &tempRawEfGroup);
     std::unique_ptr<EventFlag, void (*)(EventFlag*)> tempElfGroup(
         tempRawEfGroup, [](auto* ef) { EventFlag::deleteEventFlag(&ef); });
     if (status != OK || !tempElfGroup) {
@@ -356,9 +341,9 @@
     }
 
     // Create and launch the thread.
-    auto tempWriteThread = std::make_unique<WriteThread>(
-        &mStopWriteThread, mStream, tempCommandMQ.get(), tempDataMQ.get(),
-        tempStatusMQ.get(), tempElfGroup.get());
+    auto tempWriteThread =
+        std::make_unique<WriteThread>(&mStopWriteThread, mStream, tempCommandMQ.get(),
+                                      tempDataMQ.get(), tempStatusMQ.get(), tempElfGroup.get());
     if (!tempWriteThread->init()) {
         ALOGW("failed to start writer thread: %s", strerror(-status));
         sendError(Result::INVALID_ARGUMENTS);
@@ -378,28 +363,25 @@
     mEfGroup = tempElfGroup.release();
     threadInfo.pid = getpid();
     threadInfo.tid = mWriteThread->getTid();
-    _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(),
-             *mStatusMQ->getDesc(), threadInfo);
+    _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
+             threadInfo);
     return Void();
 }
 
 Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) {
     uint32_t halDspFrames;
-    Result retval = Stream::analyzeStatus(
-        "get_render_position",
-        mStream->get_render_position(mStream, &halDspFrames));
+    Result retval = Stream::analyzeStatus("get_render_position",
+                                          mStream->get_render_position(mStream, &halDspFrames));
     _hidl_cb(retval, halDspFrames);
     return Void();
 }
 
-Return<void> StreamOut::getNextWriteTimestamp(
-    getNextWriteTimestamp_cb _hidl_cb) {
+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 = Stream::analyzeStatus(
-            "get_next_write_timestamp",
-            mStream->get_next_write_timestamp(mStream, &timestampUs));
+        retval = Stream::analyzeStatus("get_next_write_timestamp",
+                                       mStream->get_next_write_timestamp(mStream, &timestampUs));
     }
     _hidl_cb(retval, timestampUs);
     return Void();
@@ -423,14 +405,13 @@
 }
 
 // static
-int StreamOut::asyncCallback(stream_callback_event_t event, void*,
-                             void* cookie) {
+int StreamOut::asyncCallback(stream_callback_event_t event, void*, void* cookie) {
     // It is guaranteed that the callback thread is joined prior
     // to exiting from StreamOut's destructor. Must *not* use sp<StreamOut>
     // here because it can make this code the last owner of StreamOut,
     // and an attempt to run the destructor on the callback thread
     // will cause a deadlock in the legacy HAL code.
-    StreamOut *self = reinterpret_cast<StreamOut*>(cookie);
+    StreamOut* self = reinterpret_cast<StreamOut*>(cookie);
     // It's correct to hold an sp<> to callback because the reference
     // in the StreamOut instance can be cleared in the meantime. There is
     // no difference on which thread to run IStreamOutCallback's destructor.
@@ -454,22 +435,19 @@
     return 0;
 }
 
-Return<void> StreamOut::supportsPauseAndResume(
-    supportsPauseAndResume_cb _hidl_cb) {
+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
-               ? Stream::analyzeStatus("pause", mStream->pause(mStream))
-               : Result::NOT_SUPPORTED;
+    return mStream->pause != NULL ? Stream::analyzeStatus("pause", mStream->pause(mStream))
+                                  : Result::NOT_SUPPORTED;
 }
 
 Return<Result> StreamOut::resume() {
-    return mStream->resume != NULL
-               ? Stream::analyzeStatus("resume", mStream->resume(mStream))
-               : Result::NOT_SUPPORTED;
+    return mStream->resume != NULL ? Stream::analyzeStatus("resume", mStream->resume(mStream))
+                                   : Result::NOT_SUPPORTED;
 }
 
 Return<bool> StreamOut::supportsDrain() {
@@ -479,21 +457,17 @@
 Return<Result> StreamOut::drain(AudioDrain type) {
     return mStream->drain != NULL
                ? Stream::analyzeStatus(
-                     "drain",
-                     mStream->drain(mStream,
-                                    static_cast<audio_drain_type_t>(type)))
+                     "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type)))
                : Result::NOT_SUPPORTED;
 }
 
 Return<Result> StreamOut::flush() {
-    return mStream->flush != NULL
-               ? Stream::analyzeStatus("flush", mStream->flush(mStream))
-               : Result::NOT_SUPPORTED;
+    return mStream->flush != NULL ? Stream::analyzeStatus("flush", mStream->flush(mStream))
+                                  : Result::NOT_SUPPORTED;
 }
 
 // static
-Result StreamOut::getPresentationPositionImpl(audio_stream_out_t* stream,
-                                              uint64_t* frames,
+Result StreamOut::getPresentationPositionImpl(audio_stream_out_t* stream, uint64_t* frames,
                                               TimeSpec* timeStamp) {
     // Don't logspam on EINVAL--it's normal for get_presentation_position
     // to return it sometimes. EAGAIN may be returned by A2DP audio HAL
@@ -513,8 +487,7 @@
     return retval;
 }
 
-Return<void> StreamOut::getPresentationPosition(
-    getPresentationPosition_cb _hidl_cb) {
+Return<void> StreamOut::getPresentationPosition(getPresentationPosition_cb _hidl_cb) {
     uint64_t frames = 0;
     TimeSpec timeStamp = {0, 0};
     Result retval = getPresentationPositionImpl(mStream, &frames, &timeStamp);
@@ -530,10 +503,9 @@
     return mStreamMmap->stop();
 }
 
-Return<void> StreamOut::createMmapBuffer(int32_t minSizeFrames,
-                                         createMmapBuffer_cb _hidl_cb) {
-    return mStreamMmap->createMmapBuffer(
-        minSizeFrames, audio_stream_out_frame_size(mStream), _hidl_cb);
+Return<void> StreamOut::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
+    return mStreamMmap->createMmapBuffer(minSizeFrames, audio_stream_out_frame_size(mStream),
+                                         _hidl_cb);
 }
 
 Return<void> StreamOut::getMmapPosition(getMmapPosition_cb _hidl_cb) {
@@ -541,7 +513,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
diff --git a/audio/2.0/default/Util.h b/audio/core/all-versions/default/include/core/all-versions/default/Util.h
similarity index 80%
rename from audio/2.0/default/Util.h
rename to audio/core/all-versions/default/include/core/all-versions/default/Util.h
index 72eea50..39d9dbd 100644
--- a/audio/2.0/default/Util.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Util.h
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HARDWARE_AUDIO_V2_0_UTIL_H
-#define ANDROID_HARDWARE_AUDIO_V2_0_UTIL_H
+#ifndef ANDROID_HARDWARE_AUDIO_DEVICE_ALL_VERSIONS_UTIL_H
+#define ANDROID_HARDWARE_AUDIO_DEVICE_ALL_VERSIONS_UTIL_H
 
 namespace android {
 namespace hardware {
 namespace audio {
-namespace V2_0 {
+namespace all_versions {
 namespace implementation {
 
 /** @return true if gain is between 0 and 1 included. */
@@ -29,9 +29,9 @@
 }
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace all_versions
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_AUDIO_V2_0_UTIL_H
+#endif  // ANDROID_HARDWARE_AUDIO_DEVICE_ALL_VERSIONS_UTIL_H
diff --git a/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp b/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp
index 7b9ca30..cadc2f1 100644
--- a/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp
+++ b/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -15,177 +15,9 @@
  */
 
 #define LOG_TAG "AEC_Effect_HAL"
-#include <system/audio_effects/effect_aec.h>
-#include <android/log.h>
 
 #include "AcousticEchoCancelerEffect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-AcousticEchoCancelerEffect::AcousticEchoCancelerEffect(effect_handle_t handle)
-        : mEffect(new Effect(handle)) {
-}
-
-AcousticEchoCancelerEffect::~AcousticEchoCancelerEffect() {}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> AcousticEchoCancelerEffect::init() {
-    return mEffect->init();
-}
-
-Return<Result> AcousticEchoCancelerEffect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> AcousticEchoCancelerEffect::reset() {
-    return mEffect->reset();
-}
-
-Return<Result> AcousticEchoCancelerEffect::enable() {
-    return mEffect->enable();
-}
-
-Return<Result> AcousticEchoCancelerEffect::disable() {
-    return mEffect->disable();
-}
-
-Return<Result> AcousticEchoCancelerEffect::setDevice(AudioDevice device) {
-    return mEffect->setDevice(device);
-}
-
-Return<void> AcousticEchoCancelerEffect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
-    return mEffect->setAndGetVolume(volumes, _hidl_cb);
-}
-
-Return<Result> AcousticEchoCancelerEffect::volumeChangeNotification(
-        const hidl_vec<uint32_t>& volumes) {
-    return mEffect->volumeChangeNotification(volumes);
-}
-
-Return<Result> AcousticEchoCancelerEffect::setAudioMode(AudioMode mode) {
-    return mEffect->setAudioMode(mode);
-}
-
-Return<Result> AcousticEchoCancelerEffect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> AcousticEchoCancelerEffect::setInputDevice(AudioDevice device) {
-    return mEffect->setInputDevice(device);
-}
-
-Return<void> AcousticEchoCancelerEffect::getConfig(getConfig_cb _hidl_cb) {
-    return mEffect->getConfig(_hidl_cb);
-}
-
-Return<void> AcousticEchoCancelerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    return mEffect->getConfigReverse(_hidl_cb);
-}
-
-Return<void> AcousticEchoCancelerEffect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
-    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
-}
-
-Return<void> AcousticEchoCancelerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    return mEffect->getAuxChannelsConfig(_hidl_cb);
-}
-
-Return<Result> AcousticEchoCancelerEffect::setAuxChannelsConfig(
-        const EffectAuxChannelsConfig& config) {
-    return mEffect->setAuxChannelsConfig(config);
-}
-
-Return<Result> AcousticEchoCancelerEffect::setAudioSource(AudioSource source) {
-    return mEffect->setAudioSource(source);
-}
-
-Return<Result> AcousticEchoCancelerEffect::offload(const EffectOffloadParameter& param) {
-    return mEffect->offload(param);
-}
-
-Return<void> AcousticEchoCancelerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
-    return mEffect->getDescriptor(_hidl_cb);
-}
-
-Return<void> AcousticEchoCancelerEffect::prepareForProcessing(
-        prepareForProcessing_cb _hidl_cb) {
-    return mEffect->prepareForProcessing(_hidl_cb);
-}
-
-Return<Result> AcousticEchoCancelerEffect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    return mEffect->setProcessBuffers(inBuffer, outBuffer);
-}
-
-Return<void> AcousticEchoCancelerEffect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb) {
-    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
-}
-
-Return<Result> AcousticEchoCancelerEffect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
-    return mEffect->setParameter(parameter, value);
-}
-
-Return<void> AcousticEchoCancelerEffect::getParameter(
-        const hidl_vec<uint8_t>& parameter,
-        uint32_t valueMaxSize,
-        getParameter_cb _hidl_cb) {
-    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
-}
-
-Return<void> AcousticEchoCancelerEffect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb) {
-    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
-}
-
-Return<void> AcousticEchoCancelerEffect::getCurrentConfigForFeature(
-        uint32_t featureId,
-        uint32_t configSize,
-        getCurrentConfigForFeature_cb _hidl_cb) {
-    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
-}
-
-Return<Result> AcousticEchoCancelerEffect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
-    return mEffect->setCurrentConfigForFeature(featureId, configData);
-}
-
-Return<Result> AcousticEchoCancelerEffect::close() {
-    return mEffect->close();
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow.
-Return<Result> AcousticEchoCancelerEffect::setEchoDelay(uint32_t echoDelayMs)  {
-    return mEffect->setParam(AEC_PARAM_ECHO_DELAY, echoDelayMs);
-}
-
-Return<void> AcousticEchoCancelerEffect::getEchoDelay(getEchoDelay_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(AEC_PARAM_ECHO_DELAY, _hidl_cb);
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/AcousticEchoCancelerEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/AcousticEchoCancelerEffect.h b/audio/effect/2.0/default/AcousticEchoCancelerEffect.h
index 1ac925d..d36335c 100644
--- a/audio/effect/2.0/default/AcousticEchoCancelerEffect.h
+++ b/audio/effect/2.0/default/AcousticEchoCancelerEffect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -18,100 +18,11 @@
 #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_ACOUSTICECHOCANCELEREFFECT_H
 
 #include <android/hardware/audio/effect/2.0/IAcousticEchoCancelerEffect.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
 
 #include "Effect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect;
-using ::android::hardware::audio::effect::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 AcousticEchoCancelerEffect : public IAcousticEchoCancelerEffect {
-    explicit AcousticEchoCancelerEffect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow.
-    Return<Result> setEchoDelay(uint32_t echoDelayMs)  override;
-    Return<void> getEchoDelay(getEchoDelay_cb _hidl_cb)  override;
-
-  private:
-    sp<Effect> mEffect;
-
-    virtual ~AcousticEchoCancelerEffect();
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/AcousticEchoCancelerEffect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_ACOUSTICECHOCANCELEREFFECT_H
diff --git a/audio/effect/2.0/default/Android.bp b/audio/effect/2.0/default/Android.bp
index e1072b4..db00988 100644
--- a/audio/effect/2.0/default/Android.bp
+++ b/audio/effect/2.0/default/Android.bp
@@ -31,6 +31,7 @@
         "libhidltransport",
         "liblog",
         "libutils",
+        "android.hardware.audio.common-util",
         "android.hardware.audio.common@2.0",
         "android.hardware.audio.common@2.0-util",
         "android.hardware.audio.effect@2.0",
@@ -38,6 +39,8 @@
     ],
 
     header_libs: [
+        "android.hardware.audio.common.util@all-versions",
+        "android.hardware.audio.effect@all-versions-impl",
         "libaudio_system_headers",
         "libaudioclient_headers",
         "libeffects_headers",
diff --git a/audio/effect/2.0/default/AudioBufferManager.cpp b/audio/effect/2.0/default/AudioBufferManager.cpp
index bba0c4a..39918dd 100644
--- a/audio/effect/2.0/default/AudioBufferManager.cpp
+++ b/audio/effect/2.0/default/AudioBufferManager.cpp
@@ -14,78 +14,8 @@
  * limitations under the License.
  */
 
-#include <atomic>
-
-#include <hidlmemory/mapping.h>
-
 #include "AudioBufferManager.h"
 
-namespace android {
-
-ANDROID_SINGLETON_STATIC_INSTANCE(AudioBufferManager);
-
-bool AudioBufferManager::wrap(const AudioBuffer& buffer, sp<AudioBufferWrapper>* wrapper) {
-    // Check if we have this buffer already
-    std::lock_guard<std::mutex> lock(mLock);
-    ssize_t idx = mBuffers.indexOfKey(buffer.id);
-    if (idx >= 0) {
-        *wrapper = mBuffers[idx].promote();
-        if (*wrapper != nullptr) {
-            (*wrapper)->getHalBuffer()->frameCount = buffer.frameCount;
-            return true;
-        }
-        mBuffers.removeItemsAt(idx);
-    }
-    // Need to create and init a new AudioBufferWrapper.
-    sp<AudioBufferWrapper> tempBuffer(new AudioBufferWrapper(buffer));
-    if (!tempBuffer->init()) return false;
-    *wrapper = tempBuffer;
-    mBuffers.add(buffer.id, *wrapper);
-    return true;
-}
-
-void AudioBufferManager::removeEntry(uint64_t id) {
-    std::lock_guard<std::mutex> lock(mLock);
-    ssize_t idx = mBuffers.indexOfKey(id);
-    if (idx >= 0) mBuffers.removeItemsAt(idx);
-}
-
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-AudioBufferWrapper::AudioBufferWrapper(const AudioBuffer& buffer) :
-        mHidlBuffer(buffer), mHalBuffer{ 0, { nullptr } } {
-}
-
-AudioBufferWrapper::~AudioBufferWrapper() {
-    AudioBufferManager::getInstance().removeEntry(mHidlBuffer.id);
-}
-
-bool AudioBufferWrapper::init() {
-    if (mHalBuffer.raw != nullptr) {
-        ALOGE("An attempt to init AudioBufferWrapper twice");
-        return false;
-    }
-    mHidlMemory = mapMemory(mHidlBuffer.data);
-    if (mHidlMemory == nullptr) {
-        ALOGE("Could not map HIDL memory to IMemory");
-        return false;
-    }
-    mHalBuffer.raw = static_cast<void*>(mHidlMemory->getPointer());
-    if (mHalBuffer.raw == nullptr) {
-        ALOGE("IMemory buffer pointer is null");
-        return false;
-    }
-    mHalBuffer.frameCount = mHidlBuffer.frameCount;
-    return true;
-}
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/AudioBufferManager.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/AudioBufferManager.h b/audio/effect/2.0/default/AudioBufferManager.h
index 6d65995..789fbd1 100644
--- a/audio/effect/2.0/default/AudioBufferManager.h
+++ b/audio/effect/2.0/default/AudioBufferManager.h
@@ -14,69 +14,13 @@
  * limitations under the License.
  */
 
-#ifndef android_hardware_audio_effect_V2_0_AudioBufferManager_H_
-#define android_hardware_audio_effect_V2_0_AudioBufferManager_H_
-
-#include <mutex>
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_AUDIO_BUFFER_MANAGER_H_
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_AUDIO_BUFFER_MANAGER_H_
 
 #include <android/hardware/audio/effect/2.0/types.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <system/audio_effect.h>
-#include <utils/RefBase.h>
-#include <utils/KeyedVector.h>
-#include <utils/Singleton.h>
 
-using ::android::hardware::audio::effect::V2_0::AudioBuffer;
-using ::android::hidl::memory::V1_0::IMemory;
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/AudioBufferManager.h>
+#undef AUDIO_HAL_VERSION
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-class AudioBufferWrapper : public RefBase {
-  public:
-    explicit AudioBufferWrapper(const AudioBuffer& buffer);
-    virtual ~AudioBufferWrapper();
-    bool init();
-    audio_buffer_t* getHalBuffer() { return &mHalBuffer; }
-  private:
-    AudioBufferWrapper(const AudioBufferWrapper&) = delete;
-    void operator=(AudioBufferWrapper) = delete;
-
-    AudioBuffer mHidlBuffer;
-    sp<IMemory> mHidlMemory;
-    audio_buffer_t mHalBuffer;
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
-
-using ::android::hardware::audio::effect::V2_0::implementation::AudioBufferWrapper;
-
-namespace android {
-
-// This class needs to be in 'android' ns because Singleton macros require that.
-class AudioBufferManager : public Singleton<AudioBufferManager> {
-  public:
-    bool wrap(const AudioBuffer& buffer, sp<AudioBufferWrapper>* wrapper);
-
-  private:
-    friend class hardware::audio::effect::V2_0::implementation::AudioBufferWrapper;
-
-    // Called by AudioBufferWrapper.
-    void removeEntry(uint64_t id);
-
-    std::mutex mLock;
-    KeyedVector<uint64_t, wp<AudioBufferWrapper>> mBuffers;
-};
-
-}  // namespace android
-
-#endif  // android_hardware_audio_effect_V2_0_AudioBufferManager_H_
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_AUDIO_BUFFER_MANAGER_H_
diff --git a/audio/effect/2.0/default/AutomaticGainControlEffect.cpp b/audio/effect/2.0/default/AutomaticGainControlEffect.cpp
index 62fe5f7..7e00a80 100644
--- a/audio/effect/2.0/default/AutomaticGainControlEffect.cpp
+++ b/audio/effect/2.0/default/AutomaticGainControlEffect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -15,223 +15,9 @@
  */
 
 #define LOG_TAG "AGC_Effect_HAL"
-#include <android/log.h>
 
 #include "AutomaticGainControlEffect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-AutomaticGainControlEffect::AutomaticGainControlEffect(effect_handle_t handle)
-        : mEffect(new Effect(handle)) {
-}
-
-AutomaticGainControlEffect::~AutomaticGainControlEffect() {}
-
-void AutomaticGainControlEffect::propertiesFromHal(
-        const t_agc_settings& halProperties,
-        IAutomaticGainControlEffect::AllProperties* properties) {
-    properties->targetLevelMb = halProperties.targetLevel;
-    properties->compGainMb = halProperties.compGain;
-    properties->limiterEnabled = halProperties.limiterEnabled;
-}
-
-void AutomaticGainControlEffect::propertiesToHal(
-        const IAutomaticGainControlEffect::AllProperties& properties,
-        t_agc_settings* halProperties) {
-    halProperties->targetLevel = properties.targetLevelMb;
-    halProperties->compGain = properties.compGainMb;
-    halProperties->limiterEnabled = properties.limiterEnabled;
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> AutomaticGainControlEffect::init() {
-    return mEffect->init();
-}
-
-Return<Result> AutomaticGainControlEffect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> AutomaticGainControlEffect::reset() {
-    return mEffect->reset();
-}
-
-Return<Result> AutomaticGainControlEffect::enable() {
-    return mEffect->enable();
-}
-
-Return<Result> AutomaticGainControlEffect::disable() {
-    return mEffect->disable();
-}
-
-Return<Result> AutomaticGainControlEffect::setDevice(AudioDevice device) {
-    return mEffect->setDevice(device);
-}
-
-Return<void> AutomaticGainControlEffect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
-    return mEffect->setAndGetVolume(volumes, _hidl_cb);
-}
-
-Return<Result> AutomaticGainControlEffect::volumeChangeNotification(
-        const hidl_vec<uint32_t>& volumes) {
-    return mEffect->volumeChangeNotification(volumes);
-}
-
-Return<Result> AutomaticGainControlEffect::setAudioMode(AudioMode mode) {
-    return mEffect->setAudioMode(mode);
-}
-
-Return<Result> AutomaticGainControlEffect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> AutomaticGainControlEffect::setInputDevice(AudioDevice device) {
-    return mEffect->setInputDevice(device);
-}
-
-Return<void> AutomaticGainControlEffect::getConfig(getConfig_cb _hidl_cb) {
-    return mEffect->getConfig(_hidl_cb);
-}
-
-Return<void> AutomaticGainControlEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    return mEffect->getConfigReverse(_hidl_cb);
-}
-
-Return<void> AutomaticGainControlEffect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
-    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
-}
-
-Return<void> AutomaticGainControlEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    return mEffect->getAuxChannelsConfig(_hidl_cb);
-}
-
-Return<Result> AutomaticGainControlEffect::setAuxChannelsConfig(
-        const EffectAuxChannelsConfig& config) {
-    return mEffect->setAuxChannelsConfig(config);
-}
-
-Return<Result> AutomaticGainControlEffect::setAudioSource(AudioSource source) {
-    return mEffect->setAudioSource(source);
-}
-
-Return<Result> AutomaticGainControlEffect::offload(const EffectOffloadParameter& param) {
-    return mEffect->offload(param);
-}
-
-Return<void> AutomaticGainControlEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
-    return mEffect->getDescriptor(_hidl_cb);
-}
-
-Return<void> AutomaticGainControlEffect::prepareForProcessing(
-        prepareForProcessing_cb _hidl_cb) {
-    return mEffect->prepareForProcessing(_hidl_cb);
-}
-
-Return<Result> AutomaticGainControlEffect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    return mEffect->setProcessBuffers(inBuffer, outBuffer);
-}
-
-Return<void> AutomaticGainControlEffect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb) {
-    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
-}
-
-Return<Result> AutomaticGainControlEffect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
-    return mEffect->setParameter(parameter, value);
-}
-
-Return<void> AutomaticGainControlEffect::getParameter(
-        const hidl_vec<uint8_t>& parameter,
-        uint32_t valueMaxSize,
-        getParameter_cb _hidl_cb) {
-    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
-}
-
-Return<void> AutomaticGainControlEffect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb) {
-    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
-}
-
-Return<void> AutomaticGainControlEffect::getCurrentConfigForFeature(
-        uint32_t featureId,
-        uint32_t configSize,
-        getCurrentConfigForFeature_cb _hidl_cb) {
-    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
-}
-
-Return<Result> AutomaticGainControlEffect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
-    return mEffect->setCurrentConfigForFeature(featureId, configData);
-}
-
-Return<Result> AutomaticGainControlEffect::close() {
-    return mEffect->close();
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect follow.
-Return<Result> AutomaticGainControlEffect::setTargetLevel(int16_t targetLevelMb)  {
-    return mEffect->setParam(AGC_PARAM_TARGET_LEVEL, targetLevelMb);
-}
-
-Return<void> AutomaticGainControlEffect::getTargetLevel(getTargetLevel_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(AGC_PARAM_TARGET_LEVEL, _hidl_cb);
-}
-
-Return<Result> AutomaticGainControlEffect::setCompGain(int16_t compGainMb)  {
-    return mEffect->setParam(AGC_PARAM_COMP_GAIN, compGainMb);
-}
-
-Return<void> AutomaticGainControlEffect::getCompGain(getCompGain_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(AGC_PARAM_COMP_GAIN, _hidl_cb);
-}
-
-Return<Result> AutomaticGainControlEffect::setLimiterEnabled(bool enabled)  {
-    return mEffect->setParam(AGC_PARAM_LIMITER_ENA, enabled);
-}
-
-Return<void> AutomaticGainControlEffect::isLimiterEnabled(isLimiterEnabled_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(AGC_PARAM_LIMITER_ENA, _hidl_cb);
-}
-
-Return<Result> AutomaticGainControlEffect::setAllProperties(const IAutomaticGainControlEffect::AllProperties& properties)  {
-    t_agc_settings halProperties;
-    propertiesToHal(properties, &halProperties);
-    return mEffect->setParam(AGC_PARAM_PROPERTIES, halProperties);
-}
-
-Return<void> AutomaticGainControlEffect::getAllProperties(getAllProperties_cb _hidl_cb)  {
-    t_agc_settings halProperties;
-    Result retval = mEffect->getParam(AGC_PARAM_PROPERTIES, halProperties);
-    AllProperties properties;
-    propertiesFromHal(halProperties, &properties);
-    _hidl_cb(retval, properties);
-    return Void();
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/AutomaticGainControlEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/AutomaticGainControlEffect.h b/audio/effect/2.0/default/AutomaticGainControlEffect.h
index 5e1f279..ef440d2 100644
--- a/audio/effect/2.0/default/AutomaticGainControlEffect.h
+++ b/audio/effect/2.0/default/AutomaticGainControlEffect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -17,117 +17,12 @@
 #ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_AUTOMATICGAINCONTROLEFFECT_H
 #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_AUTOMATICGAINCONTROLEFFECT_H
 
-#include <system/audio_effects/effect_agc.h>
-
 #include <android/hardware/audio/effect/2.0/IAutomaticGainControlEffect.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
 
 #include "Effect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect;
-using ::android::hardware::audio::effect::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 AutomaticGainControlEffect : public IAutomaticGainControlEffect {
-    explicit AutomaticGainControlEffect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect follow.
-    Return<Result> setTargetLevel(int16_t targetLevelMb)  override;
-    Return<void> getTargetLevel(getTargetLevel_cb _hidl_cb)  override;
-    Return<Result> setCompGain(int16_t compGainMb)  override;
-    Return<void> getCompGain(getCompGain_cb _hidl_cb)  override;
-    Return<Result> setLimiterEnabled(bool enabled)  override;
-    Return<void> isLimiterEnabled(isLimiterEnabled_cb _hidl_cb)  override;
-    Return<Result> setAllProperties(
-            const IAutomaticGainControlEffect::AllProperties& properties)  override;
-    Return<void> getAllProperties(getAllProperties_cb _hidl_cb)  override;
-
-  private:
-    sp<Effect> mEffect;
-
-    virtual ~AutomaticGainControlEffect();
-
-    void propertiesFromHal(
-            const t_agc_settings& halProperties,
-            IAutomaticGainControlEffect::AllProperties* properties);
-    void propertiesToHal(
-            const IAutomaticGainControlEffect::AllProperties& properties,
-            t_agc_settings* halProperties);
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/AutomaticGainControlEffect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_AUTOMATICGAINCONTROLEFFECT_H
diff --git a/audio/effect/2.0/default/BassBoostEffect.cpp b/audio/effect/2.0/default/BassBoostEffect.cpp
index 8f35e5f..df9e892 100644
--- a/audio/effect/2.0/default/BassBoostEffect.cpp
+++ b/audio/effect/2.0/default/BassBoostEffect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -15,181 +15,9 @@
  */
 
 #define LOG_TAG "BassBoost_HAL"
-#include <system/audio_effects/effect_bassboost.h>
-#include <android/log.h>
 
 #include "BassBoostEffect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-BassBoostEffect::BassBoostEffect(effect_handle_t handle)
-        : mEffect(new Effect(handle)) {
-}
-
-BassBoostEffect::~BassBoostEffect() {}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> BassBoostEffect::init() {
-    return mEffect->init();
-}
-
-Return<Result> BassBoostEffect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> BassBoostEffect::reset() {
-    return mEffect->reset();
-}
-
-Return<Result> BassBoostEffect::enable() {
-    return mEffect->enable();
-}
-
-Return<Result> BassBoostEffect::disable() {
-    return mEffect->disable();
-}
-
-Return<Result> BassBoostEffect::setDevice(AudioDevice device) {
-    return mEffect->setDevice(device);
-}
-
-Return<void> BassBoostEffect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
-    return mEffect->setAndGetVolume(volumes, _hidl_cb);
-}
-
-Return<Result> BassBoostEffect::volumeChangeNotification(
-        const hidl_vec<uint32_t>& volumes) {
-    return mEffect->volumeChangeNotification(volumes);
-}
-
-Return<Result> BassBoostEffect::setAudioMode(AudioMode mode) {
-    return mEffect->setAudioMode(mode);
-}
-
-Return<Result> BassBoostEffect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> BassBoostEffect::setInputDevice(AudioDevice device) {
-    return mEffect->setInputDevice(device);
-}
-
-Return<void> BassBoostEffect::getConfig(getConfig_cb _hidl_cb) {
-    return mEffect->getConfig(_hidl_cb);
-}
-
-Return<void> BassBoostEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    return mEffect->getConfigReverse(_hidl_cb);
-}
-
-Return<void> BassBoostEffect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
-    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
-}
-
-Return<void> BassBoostEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    return mEffect->getAuxChannelsConfig(_hidl_cb);
-}
-
-Return<Result> BassBoostEffect::setAuxChannelsConfig(
-        const EffectAuxChannelsConfig& config) {
-    return mEffect->setAuxChannelsConfig(config);
-}
-
-Return<Result> BassBoostEffect::setAudioSource(AudioSource source) {
-    return mEffect->setAudioSource(source);
-}
-
-Return<Result> BassBoostEffect::offload(const EffectOffloadParameter& param) {
-    return mEffect->offload(param);
-}
-
-Return<void> BassBoostEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
-    return mEffect->getDescriptor(_hidl_cb);
-}
-
-Return<void> BassBoostEffect::prepareForProcessing(
-        prepareForProcessing_cb _hidl_cb) {
-    return mEffect->prepareForProcessing(_hidl_cb);
-}
-
-Return<Result> BassBoostEffect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    return mEffect->setProcessBuffers(inBuffer, outBuffer);
-}
-
-Return<void> BassBoostEffect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb) {
-    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
-}
-
-Return<Result> BassBoostEffect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
-    return mEffect->setParameter(parameter, value);
-}
-
-Return<void> BassBoostEffect::getParameter(
-        const hidl_vec<uint8_t>& parameter,
-        uint32_t valueMaxSize,
-        getParameter_cb _hidl_cb) {
-    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
-}
-
-Return<void> BassBoostEffect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb) {
-    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
-}
-
-Return<void> BassBoostEffect::getCurrentConfigForFeature(
-        uint32_t featureId,
-        uint32_t configSize,
-        getCurrentConfigForFeature_cb _hidl_cb) {
-    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
-}
-
-Return<Result> BassBoostEffect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
-    return mEffect->setCurrentConfigForFeature(featureId, configData);
-}
-
-Return<Result> BassBoostEffect::close() {
-    return mEffect->close();
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IBassBoostEffect follow.
-Return<void> BassBoostEffect::isStrengthSupported(isStrengthSupported_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(BASSBOOST_PARAM_STRENGTH_SUPPORTED, _hidl_cb);
-}
-
-Return<Result> BassBoostEffect::setStrength(uint16_t strength)  {
-    return mEffect->setParam(BASSBOOST_PARAM_STRENGTH, strength);
-}
-
-Return<void> BassBoostEffect::getStrength(getStrength_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(BASSBOOST_PARAM_STRENGTH, _hidl_cb);
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/BassBoostEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/BassBoostEffect.h b/audio/effect/2.0/default/BassBoostEffect.h
index 1e5053b..83179e2 100644
--- a/audio/effect/2.0/default/BassBoostEffect.h
+++ b/audio/effect/2.0/default/BassBoostEffect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -18,101 +18,13 @@
 #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_BASSBOOSTEFFECT_H
 
 #include <android/hardware/audio/effect/2.0/IBassBoostEffect.h>
-#include <hidl/Status.h>
 
 #include <hidl/MQDescriptor.h>
 
 #include "Effect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::effect::V2_0::IBassBoostEffect;
-using ::android::hardware::audio::effect::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 BassBoostEffect : public IBassBoostEffect {
-    explicit BassBoostEffect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IBassBoostEffect follow.
-    Return<void> isStrengthSupported(isStrengthSupported_cb _hidl_cb)  override;
-    Return<Result> setStrength(uint16_t strength)  override;
-    Return<void> getStrength(getStrength_cb _hidl_cb)  override;
-
-  private:
-    sp<Effect> mEffect;
-
-    virtual ~BassBoostEffect();
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/BassBoostEffect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_BASSBOOSTEFFECT_H
diff --git a/audio/effect/2.0/default/Conversions.cpp b/audio/effect/2.0/default/Conversions.cpp
index e7d4c46..b59752c 100644
--- a/audio/effect/2.0/default/Conversions.cpp
+++ b/audio/effect/2.0/default/Conversions.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -14,50 +14,11 @@
  * limitations under the License.
  */
 
-#include <memory.h>
-#include <stdio.h>
-
 #include "Conversions.h"
 #include "HidlUtils.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
+using ::android::hardware::audio::common::V2_0::HidlUtils;
 
-void effectDescriptorFromHal(
-        const effect_descriptor_t& halDescriptor, EffectDescriptor* descriptor) {
-    HidlUtils::uuidFromHal(halDescriptor.type, &descriptor->type);
-    HidlUtils::uuidFromHal(halDescriptor.uuid, &descriptor->uuid);
-    descriptor->flags = EffectFlags(halDescriptor.flags);
-    descriptor->cpuLoad = halDescriptor.cpuLoad;
-    descriptor->memoryUsage = halDescriptor.memoryUsage;
-    memcpy(descriptor->name.data(), halDescriptor.name, descriptor->name.size());
-    memcpy(descriptor->implementor.data(),
-            halDescriptor.implementor, descriptor->implementor.size());
-}
-
-std::string uuidToString(const effect_uuid_t& halUuid) {
-    char str[64];
-    snprintf(str, sizeof(str), "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
-            halUuid.timeLow,
-            halUuid.timeMid,
-            halUuid.timeHiAndVersion,
-            halUuid.clockSeq,
-            halUuid.node[0],
-            halUuid.node[1],
-            halUuid.node[2],
-            halUuid.node[3],
-            halUuid.node[4],
-            halUuid.node[5]);
-    return str;
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/Conversions.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/Conversions.h b/audio/effect/2.0/default/Conversions.h
index 7cef362..94c7f66 100644
--- a/audio/effect/2.0/default/Conversions.h
+++ b/audio/effect/2.0/default/Conversions.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -14,32 +14,13 @@
  * limitations under the License.
  */
 
-#ifndef android_hardware_audio_effect_V2_0_Conversions_H_
-#define android_hardware_audio_effect_V2_0_Conversions_H_
-
-#include <string>
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_CONVERSIONS_H_
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_CONVERSIONS_H_
 
 #include <android/hardware/audio/effect/2.0/types.h>
-#include <system/audio_effect.h>
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/Conversions.h>
+#undef AUDIO_HAL_VERSION
 
-using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
-
-void effectDescriptorFromHal(
-        const effect_descriptor_t& halDescriptor, EffectDescriptor* descriptor);
-std::string uuidToString(const effect_uuid_t& halUuid);
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
-
-#endif  // android_hardware_audio_effect_V2_0_Conversions_H_
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_CONVERSIONS_H_
diff --git a/audio/effect/2.0/default/DownmixEffect.cpp b/audio/effect/2.0/default/DownmixEffect.cpp
index 92f15bd..1a51e13 100644
--- a/audio/effect/2.0/default/DownmixEffect.cpp
+++ b/audio/effect/2.0/default/DownmixEffect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -15,180 +15,9 @@
  */
 
 #define LOG_TAG "Downmix_HAL"
-#include <system/audio_effects/effect_downmix.h>
-#include <android/log.h>
 
 #include "DownmixEffect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-DownmixEffect::DownmixEffect(effect_handle_t handle)
-        : mEffect(new Effect(handle)) {
-}
-
-DownmixEffect::~DownmixEffect() {}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> DownmixEffect::init() {
-    return mEffect->init();
-}
-
-Return<Result> DownmixEffect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> DownmixEffect::reset() {
-    return mEffect->reset();
-}
-
-Return<Result> DownmixEffect::enable() {
-    return mEffect->enable();
-}
-
-Return<Result> DownmixEffect::disable() {
-    return mEffect->disable();
-}
-
-Return<Result> DownmixEffect::setDevice(AudioDevice device) {
-    return mEffect->setDevice(device);
-}
-
-Return<void> DownmixEffect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
-    return mEffect->setAndGetVolume(volumes, _hidl_cb);
-}
-
-Return<Result> DownmixEffect::volumeChangeNotification(
-        const hidl_vec<uint32_t>& volumes) {
-    return mEffect->volumeChangeNotification(volumes);
-}
-
-Return<Result> DownmixEffect::setAudioMode(AudioMode mode) {
-    return mEffect->setAudioMode(mode);
-}
-
-Return<Result> DownmixEffect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> DownmixEffect::setInputDevice(AudioDevice device) {
-    return mEffect->setInputDevice(device);
-}
-
-Return<void> DownmixEffect::getConfig(getConfig_cb _hidl_cb) {
-    return mEffect->getConfig(_hidl_cb);
-}
-
-Return<void> DownmixEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    return mEffect->getConfigReverse(_hidl_cb);
-}
-
-Return<void> DownmixEffect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
-    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
-}
-
-Return<void> DownmixEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    return mEffect->getAuxChannelsConfig(_hidl_cb);
-}
-
-Return<Result> DownmixEffect::setAuxChannelsConfig(
-        const EffectAuxChannelsConfig& config) {
-    return mEffect->setAuxChannelsConfig(config);
-}
-
-Return<Result> DownmixEffect::setAudioSource(AudioSource source) {
-    return mEffect->setAudioSource(source);
-}
-
-Return<Result> DownmixEffect::offload(const EffectOffloadParameter& param) {
-    return mEffect->offload(param);
-}
-
-Return<void> DownmixEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
-    return mEffect->getDescriptor(_hidl_cb);
-}
-
-Return<void> DownmixEffect::prepareForProcessing(
-        prepareForProcessing_cb _hidl_cb) {
-    return mEffect->prepareForProcessing(_hidl_cb);
-}
-
-Return<Result> DownmixEffect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    return mEffect->setProcessBuffers(inBuffer, outBuffer);
-}
-
-Return<void> DownmixEffect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb) {
-    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
-}
-
-Return<Result> DownmixEffect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
-    return mEffect->setParameter(parameter, value);
-}
-
-Return<void> DownmixEffect::getParameter(
-        const hidl_vec<uint8_t>& parameter,
-        uint32_t valueMaxSize,
-        getParameter_cb _hidl_cb) {
-    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
-}
-
-Return<void> DownmixEffect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb) {
-    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
-}
-
-Return<void> DownmixEffect::getCurrentConfigForFeature(
-        uint32_t featureId,
-        uint32_t configSize,
-        getCurrentConfigForFeature_cb _hidl_cb) {
-    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
-}
-
-Return<Result> DownmixEffect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
-    return mEffect->setCurrentConfigForFeature(featureId, configData);
-}
-
-Return<Result> DownmixEffect::close() {
-    return mEffect->close();
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IDownmixEffect follow.
-Return<Result> DownmixEffect::setType(IDownmixEffect::Type preset)  {
-    return mEffect->setParam(DOWNMIX_PARAM_TYPE, static_cast<downmix_type_t>(preset));
-}
-
-Return<void> DownmixEffect::getType(getType_cb _hidl_cb)  {
-    downmix_type_t halPreset = DOWNMIX_TYPE_INVALID;
-    Result retval = mEffect->getParam(DOWNMIX_PARAM_TYPE, halPreset);
-    _hidl_cb(retval, Type(halPreset));
-    return Void();
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/DownmixEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/DownmixEffect.h b/audio/effect/2.0/default/DownmixEffect.h
index 125f34d..6dbbb32 100644
--- a/audio/effect/2.0/default/DownmixEffect.h
+++ b/audio/effect/2.0/default/DownmixEffect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -18,100 +18,11 @@
 #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_DOWNMIXEFFECT_H
 
 #include <android/hardware/audio/effect/2.0/IDownmixEffect.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
 
 #include "Effect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::effect::V2_0::IDownmixEffect;
-using ::android::hardware::audio::effect::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 DownmixEffect : public IDownmixEffect {
-    explicit DownmixEffect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IDownmixEffect follow.
-    Return<Result> setType(IDownmixEffect::Type preset)  override;
-    Return<void> getType(getType_cb _hidl_cb)  override;
-
-  private:
-    sp<Effect> mEffect;
-
-    virtual ~DownmixEffect();
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/DownmixEffect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_DOWNMIXEFFECT_H
diff --git a/audio/effect/2.0/default/Effect.cpp b/audio/effect/2.0/default/Effect.cpp
index 184607e..e234e52 100644
--- a/audio/effect/2.0/default/Effect.cpp
+++ b/audio/effect/2.0/default/Effect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -19,746 +19,10 @@
 #define LOG_TAG "EffectHAL"
 #define ATRACE_TAG ATRACE_TAG_AUDIO
 
-#include <android/log.h>
-#include <media/EffectsFactoryApi.h>
-#include <utils/Trace.h>
-
 #include "Conversions.h"
 #include "Effect.h"
-#include "EffectMap.h"
+#include "common/all-versions/default/EffectMap.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::common::V2_0::AudioChannelMask;
-using ::android::hardware::audio::common::V2_0::AudioFormat;
-using ::android::hardware::audio::effect::V2_0::MessageQueueFlagBits;
-
-namespace {
-
-class ProcessThread : public Thread {
-  public:
-    // ProcessThread's lifespan never exceeds Effect's lifespan.
-    ProcessThread(std::atomic<bool>* stop,
-            effect_handle_t effect,
-            std::atomic<audio_buffer_t*>* inBuffer,
-            std::atomic<audio_buffer_t*>* outBuffer,
-            Effect::StatusMQ* statusMQ,
-            EventFlag* efGroup)
-            : Thread(false /*canCallJava*/),
-              mStop(stop),
-              mEffect(effect),
-              mHasProcessReverse((*mEffect)->process_reverse != NULL),
-              mInBuffer(inBuffer),
-              mOutBuffer(outBuffer),
-              mStatusMQ(statusMQ),
-              mEfGroup(efGroup) {
-    }
-    virtual ~ProcessThread() {}
-
-  private:
-    std::atomic<bool>* mStop;
-    effect_handle_t mEffect;
-    bool mHasProcessReverse;
-    std::atomic<audio_buffer_t*>* mInBuffer;
-    std::atomic<audio_buffer_t*>* mOutBuffer;
-    Effect::StatusMQ* mStatusMQ;
-    EventFlag* mEfGroup;
-
-    bool threadLoop() override;
-};
-
-bool ProcessThread::threadLoop() {
-    // This implementation doesn't return control back to the Thread until it decides to stop,
-    // as the Thread uses mutexes, and this can lead to priority inversion.
-    while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
-        uint32_t efState = 0;
-        mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL), &efState);
-        if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL))
-                || (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT))) {
-            continue;  // Nothing to do or time to quit.
-        }
-        Result retval = Result::OK;
-        if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE)
-                && !mHasProcessReverse) {
-            retval = Result::NOT_SUPPORTED;
-        }
-
-        if (retval == Result::OK) {
-            // affects both buffer pointers and their contents.
-            std::atomic_thread_fence(std::memory_order_acquire);
-            int32_t processResult;
-            audio_buffer_t* inBuffer =
-                    std::atomic_load_explicit(mInBuffer, std::memory_order_relaxed);
-            audio_buffer_t* outBuffer =
-                    std::atomic_load_explicit(mOutBuffer, std::memory_order_relaxed);
-            if (inBuffer != nullptr && outBuffer != nullptr) {
-                if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS)) {
-                    processResult = (*mEffect)->process(mEffect, inBuffer, outBuffer);
-                } else {
-                    processResult = (*mEffect)->process_reverse(mEffect, inBuffer, outBuffer);
-                }
-                std::atomic_thread_fence(std::memory_order_release);
-            } else {
-                ALOGE("processing buffers were not set before calling 'process'");
-                processResult = -ENODEV;
-            }
-            switch(processResult) {
-                case 0: retval = Result::OK; break;
-                case -ENODATA: retval = Result::INVALID_STATE; break;
-                case -EINVAL: retval = Result::INVALID_ARGUMENTS; break;
-                default: retval = Result::NOT_INITIALIZED;
-            }
-        }
-        if (!mStatusMQ->write(&retval)) {
-            ALOGW("status message queue write failed");
-        }
-        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING));
-    }
-
-    return false;
-}
-
-}  // namespace
-
-// static
-const char *Effect::sContextResultOfCommand = "returned status";
-const char *Effect::sContextCallToCommand = "error";
-const char *Effect::sContextCallFunction = sContextCallToCommand;
-
-Effect::Effect(effect_handle_t handle)
-        : mIsClosed(false), mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) {
-}
-
-Effect::~Effect() {
-    ATRACE_CALL();
-    close();
-    if (mProcessThread.get()) {
-        ATRACE_NAME("mProcessThread->join");
-        status_t status = mProcessThread->join();
-        ALOGE_IF(status, "processing thread exit error: %s", strerror(-status));
-    }
-    if (mEfGroup) {
-        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
-        ALOGE_IF(status, "processing MQ event flag deletion error: %s", strerror(-status));
-    }
-    mInBuffer.clear();
-    mOutBuffer.clear();
-    int status = EffectRelease(mHandle);
-    ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
-    EffectMap::getInstance().remove(mHandle);
-    mHandle = 0;
-}
-
-// static
-template<typename T> size_t Effect::alignedSizeIn(size_t s) {
-    return (s + sizeof(T) - 1) / sizeof(T);
-}
-
-// static
-template<typename T> std::unique_ptr<uint8_t[]> Effect::hidlVecToHal(
-        const hidl_vec<T>& vec, uint32_t* halDataSize) {
-    // Due to bugs in HAL, they may attempt to write into the provided
-    // input buffer. The original binder buffer is r/o, thus it is needed
-    // to create a r/w version.
-    *halDataSize = vec.size() * sizeof(T);
-    std::unique_ptr<uint8_t[]> halData(new uint8_t[*halDataSize]);
-    memcpy(&halData[0], &vec[0], *halDataSize);
-    return halData;
-}
-
-// static
-void Effect::effectAuxChannelsConfigFromHal(
-        const channel_config_t& halConfig, EffectAuxChannelsConfig* config) {
-    config->mainChannels = AudioChannelMask(halConfig.main_channels);
-    config->auxChannels = AudioChannelMask(halConfig.aux_channels);
-}
-
-// static
-void Effect::effectAuxChannelsConfigToHal(
-        const EffectAuxChannelsConfig& config, channel_config_t* halConfig) {
-    halConfig->main_channels = static_cast<audio_channel_mask_t>(config.mainChannels);
-    halConfig->aux_channels = static_cast<audio_channel_mask_t>(config.auxChannels);
-}
-
-// static
-void Effect::effectBufferConfigFromHal(
-        const buffer_config_t& halConfig, EffectBufferConfig* config) {
-    config->buffer.id = 0;
-    config->buffer.frameCount = 0;
-    config->samplingRateHz = halConfig.samplingRate;
-    config->channels = AudioChannelMask(halConfig.channels);
-    config->format = AudioFormat(halConfig.format);
-    config->accessMode = EffectBufferAccess(halConfig.accessMode);
-    config->mask = EffectConfigParameters(halConfig.mask);
-}
-
-// static
-void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) {
-    // Note: setting the buffers directly is considered obsolete. They need to be set
-    // using 'setProcessBuffers'.
-    halConfig->buffer.frameCount = 0;
-    halConfig->buffer.raw = NULL;
-    halConfig->samplingRate = config.samplingRateHz;
-    halConfig->channels = static_cast<uint32_t>(config.channels);
-    // Note: The framework code does not use BP.
-    halConfig->bufferProvider.cookie = NULL;
-    halConfig->bufferProvider.getBuffer = NULL;
-    halConfig->bufferProvider.releaseBuffer = NULL;
-    halConfig->format = static_cast<uint8_t>(config.format);
-    halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
-    halConfig->mask = static_cast<uint8_t>(config.mask);
-}
-
-// static
-void Effect::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) {
-    effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg);
-    effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg);
-}
-
-// static
-void Effect::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
-    effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg);
-    effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg);
-}
-
-// static
-void Effect::effectOffloadParamToHal(
-        const EffectOffloadParameter& offload, effect_offload_param_t* halOffload) {
-    halOffload->isOffload = offload.isOffload;
-    halOffload->ioHandle = offload.ioHandle;
-}
-
-// static
-std::vector<uint8_t> Effect::parameterToHal(
-        uint32_t paramSize,
-        const void* paramData,
-        uint32_t valueSize,
-        const void** valueData) {
-    size_t valueOffsetFromData = alignedSizeIn<uint32_t>(paramSize) * sizeof(uint32_t);
-    size_t halParamBufferSize = sizeof(effect_param_t) + valueOffsetFromData + valueSize;
-    std::vector<uint8_t> halParamBuffer(halParamBufferSize, 0);
-    effect_param_t *halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
-    halParam->psize = paramSize;
-    halParam->vsize = valueSize;
-    memcpy(halParam->data, paramData, paramSize);
-    if (valueData) {
-        if (*valueData) {
-            // Value data is provided.
-            memcpy(halParam->data + valueOffsetFromData, *valueData, valueSize);
-        } else {
-            // The caller needs the pointer to the value data location.
-            *valueData = halParam->data + valueOffsetFromData;
-        }
-    }
-    return halParamBuffer;
-}
-
-Result Effect::analyzeCommandStatus(const char* commandName, const char* context, status_t status) {
-    return analyzeStatus("command", commandName, context, status);
-}
-
-Result Effect::analyzeStatus(
-        const char* funcName,
-        const char* subFuncName,
-        const char* contextDescription,
-        status_t status) {
-    if (status != OK) {
-        ALOGW("Effect %p %s %s %s: %s",
-                mHandle, funcName, subFuncName, contextDescription, strerror(-status));
-    }
-    switch (status) {
-        case OK: return Result::OK;
-        case -EINVAL: return Result::INVALID_ARGUMENTS;
-        case -ENODATA: return Result::INVALID_STATE;
-        case -ENODEV: return Result::NOT_INITIALIZED;
-        case -ENOMEM: return Result::RESULT_TOO_BIG;
-        case -ENOSYS: return Result::NOT_SUPPORTED;
-        default: return Result::INVALID_STATE;
-    }
-}
-
-void Effect::getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb) {
-    uint32_t halResultSize = sizeof(effect_config_t);
-    effect_config_t halConfig{};
-    status_t status = (*mHandle)->command(
-            mHandle, commandCode, 0, NULL, &halResultSize, &halConfig);
-    EffectConfig config;
-    if (status == OK) {
-        effectConfigFromHal(halConfig, &config);
-    }
-    cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
-}
-
-Result Effect::getCurrentConfigImpl(
-        uint32_t featureId, uint32_t configSize, GetCurrentConfigSuccessCallback onSuccess) {
-    uint32_t halCmd = featureId;
-    uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configSize)];
-    memset(halResult, 0, sizeof(halResult));
-    uint32_t halResultSize = 0;
-    return sendCommandReturningStatusAndData(
-            EFFECT_CMD_GET_FEATURE_CONFIG, "GET_FEATURE_CONFIG",
-            sizeof(uint32_t), &halCmd,
-            &halResultSize, halResult,
-            sizeof(uint32_t),
-            [&]{ onSuccess(&halResult[1]); });
-}
-
-Result Effect::getParameterImpl(
-        uint32_t paramSize,
-        const void* paramData,
-        uint32_t requestValueSize,
-        uint32_t replyValueSize,
-        GetParameterSuccessCallback onSuccess) {
-    // As it is unknown what method HAL uses for copying the provided parameter data,
-    // it is safer to make sure that input and output buffers do not overlap.
-    std::vector<uint8_t> halCmdBuffer =
-            parameterToHal(paramSize, paramData, requestValueSize, nullptr);
-    const void *valueData = nullptr;
-    std::vector<uint8_t> halParamBuffer =
-            parameterToHal(paramSize, paramData, replyValueSize, &valueData);
-    uint32_t halParamBufferSize = halParamBuffer.size();
-
-    return sendCommandReturningStatusAndData(
-            EFFECT_CMD_GET_PARAM, "GET_PARAM",
-            halCmdBuffer.size(), &halCmdBuffer[0],
-            &halParamBufferSize, &halParamBuffer[0],
-            sizeof(effect_param_t),
-            [&]{
-                effect_param_t *halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
-                onSuccess(halParam->vsize, valueData);
-            });
-}
-
-Result Effect::getSupportedConfigsImpl(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        GetSupportedConfigsSuccessCallback onSuccess) {
-    uint32_t halCmd[2] = { featureId, maxConfigs };
-    uint32_t halResultSize = 2 * sizeof(uint32_t) + maxConfigs * sizeof(configSize);
-    uint8_t halResult[halResultSize];
-    memset(&halResult[0], 0, halResultSize);
-    return sendCommandReturningStatusAndData(
-            EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS, "GET_FEATURE_SUPPORTED_CONFIGS",
-            sizeof(halCmd), halCmd,
-            &halResultSize, &halResult[0],
-            2 * sizeof(uint32_t),
-            [&]{
-                uint32_t *halResult32 = reinterpret_cast<uint32_t*>(&halResult[0]);
-                uint32_t supportedConfigs = *(++halResult32); // skip status field
-                if (supportedConfigs > maxConfigs) supportedConfigs = maxConfigs;
-                onSuccess(supportedConfigs, ++halResult32);
-            });
-}
-
-Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
-    status_t status;
-    // Create message queue.
-    if (mStatusMQ) {
-        ALOGE("the client attempts to call prepareForProcessing_cb twice");
-        _hidl_cb(Result::INVALID_STATE, StatusMQ::Descriptor());
-        return Void();
-    }
-    std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1, true /*EventFlag*/));
-    if (!tempStatusMQ->isValid()) {
-        ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
-        _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
-        return Void();
-    }
-    status = EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &mEfGroup);
-    if (status != OK || !mEfGroup) {
-        ALOGE("failed creating event flag for status MQ: %s", strerror(-status));
-        _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
-        return Void();
-    }
-
-    // Create and launch the thread.
-    mProcessThread = new ProcessThread(
-            &mStopProcessThread,
-            mHandle,
-            &mHalInBufferPtr,
-            &mHalOutBufferPtr,
-            tempStatusMQ.get(),
-            mEfGroup);
-    status = mProcessThread->run("effect", PRIORITY_URGENT_AUDIO);
-    if (status != OK) {
-        ALOGW("failed to start effect processing thread: %s", strerror(-status));
-        _hidl_cb(Result::INVALID_ARGUMENTS, MQDescriptorSync<Result>());
-        return Void();
-    }
-
-    mStatusMQ = std::move(tempStatusMQ);
-    _hidl_cb(Result::OK, *mStatusMQ->getDesc());
-    return Void();
-}
-
-Return<Result> Effect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    AudioBufferManager& manager = AudioBufferManager::getInstance();
-    sp<AudioBufferWrapper> tempInBuffer, tempOutBuffer;
-    if (!manager.wrap(inBuffer, &tempInBuffer)) {
-        ALOGE("Could not map memory of the input buffer");
-        return Result::INVALID_ARGUMENTS;
-    }
-    if (!manager.wrap(outBuffer, &tempOutBuffer)) {
-        ALOGE("Could not map memory of the output buffer");
-        return Result::INVALID_ARGUMENTS;
-    }
-    mInBuffer = tempInBuffer;
-    mOutBuffer = tempOutBuffer;
-    // The processing thread only reads these pointers after waking up by an event flag,
-    // so it's OK to update the pair non-atomically.
-    mHalInBufferPtr.store(mInBuffer->getHalBuffer(), std::memory_order_release);
-    mHalOutBufferPtr.store(mOutBuffer->getHalBuffer(), std::memory_order_release);
-    return Result::OK;
-}
-
-Result Effect::sendCommand(int commandCode, const char* commandName) {
-    return sendCommand(commandCode, commandName, 0, NULL);
-}
-
-Result Effect::sendCommand(
-        int commandCode, const char* commandName, uint32_t size, void* data) {
-    status_t status = (*mHandle)->command(mHandle, commandCode, size, data, 0, NULL);
-    return analyzeCommandStatus(commandName, sContextCallToCommand, status);
-}
-
-Result Effect::sendCommandReturningData(
-        int commandCode, const char* commandName,
-        uint32_t* replySize, void* replyData) {
-    return sendCommandReturningData(commandCode, commandName, 0, NULL, replySize, replyData);
-}
-
-Result Effect::sendCommandReturningData(
-        int commandCode, const char* commandName,
-        uint32_t size, void* data,
-        uint32_t* replySize, void* replyData) {
-    uint32_t expectedReplySize = *replySize;
-    status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
-    if (status == OK && *replySize != expectedReplySize) {
-        status = -ENODATA;
-    }
-    return analyzeCommandStatus(commandName, sContextCallToCommand, status);
-}
-
-Result Effect::sendCommandReturningStatus(int commandCode, const char* commandName) {
-    return sendCommandReturningStatus(commandCode, commandName, 0, NULL);
-}
-
-Result Effect::sendCommandReturningStatus(
-        int commandCode, const char* commandName, uint32_t size, void* data) {
-    uint32_t replyCmdStatus;
-    uint32_t replySize = sizeof(uint32_t);
-    return sendCommandReturningStatusAndData(
-            commandCode, commandName, size, data, &replySize, &replyCmdStatus, replySize, []{});
-}
-
-Result Effect::sendCommandReturningStatusAndData(
-        int commandCode, const char* commandName,
-        uint32_t size, void* data,
-        uint32_t* replySize, void* replyData,
-        uint32_t minReplySize,
-        CommandSuccessCallback onSuccess) {
-    status_t status =
-            (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
-    Result retval;
-    if (status == OK && minReplySize >= sizeof(uint32_t) && *replySize >= minReplySize) {
-        uint32_t commandStatus = *reinterpret_cast<uint32_t*>(replyData);
-        retval = analyzeCommandStatus(commandName, sContextResultOfCommand, commandStatus);
-        if (commandStatus == OK) {
-            onSuccess();
-        }
-    } else {
-        retval = analyzeCommandStatus(commandName, sContextCallToCommand, status);
-    }
-    return retval;
-}
-
-Result Effect::setConfigImpl(
-        int commandCode, const char* commandName,
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    effect_config_t halConfig;
-    effectConfigToHal(config, &halConfig);
-    if (inputBufferProvider != 0) {
-        LOG_FATAL("Using input buffer provider is not supported");
-    }
-    if (outputBufferProvider != 0) {
-        LOG_FATAL("Using output buffer provider is not supported");
-    }
-    return sendCommandReturningStatus(
-            commandCode, commandName, sizeof(effect_config_t), &halConfig);
-}
-
-
-Result Effect::setParameterImpl(
-        uint32_t paramSize, const void* paramData, uint32_t valueSize, const void* valueData) {
-    std::vector<uint8_t> halParamBuffer = parameterToHal(
-            paramSize, paramData, valueSize, &valueData);
-    return sendCommandReturningStatus(
-            EFFECT_CMD_SET_PARAM, "SET_PARAM", halParamBuffer.size(), &halParamBuffer[0]);
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> Effect::init()  {
-    return sendCommandReturningStatus(EFFECT_CMD_INIT, "INIT");
-}
-
-Return<Result> Effect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider)  {
-    return setConfigImpl(
-            EFFECT_CMD_SET_CONFIG, "SET_CONFIG", config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> Effect::reset()  {
-    return sendCommand(EFFECT_CMD_RESET, "RESET");
-}
-
-Return<Result> Effect::enable()  {
-    return sendCommandReturningStatus(EFFECT_CMD_ENABLE, "ENABLE");
-}
-
-Return<Result> Effect::disable()  {
-    return sendCommandReturningStatus(EFFECT_CMD_DISABLE, "DISABLE");
-}
-
-Return<Result> Effect::setDevice(AudioDevice device)  {
-    uint32_t halDevice = static_cast<uint32_t>(device);
-    return sendCommand(EFFECT_CMD_SET_DEVICE, "SET_DEVICE", sizeof(uint32_t), &halDevice);
-}
-
-Return<void> Effect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  {
-    uint32_t halDataSize;
-    std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
-    uint32_t halResultSize = halDataSize;
-    uint32_t halResult[volumes.size()];
-    Result retval = sendCommandReturningData(
-            EFFECT_CMD_SET_VOLUME, "SET_VOLUME",
-            halDataSize, &halData[0],
-            &halResultSize, halResult);
-    hidl_vec<uint32_t> result;
-    if (retval == Result::OK) {
-        result.setToExternal(&halResult[0], halResultSize);
-    }
-    _hidl_cb(retval, result);
-    return Void();
-}
-
-Return<Result> Effect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  {
-    uint32_t halDataSize;
-    std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
-    return sendCommand(
-            EFFECT_CMD_SET_VOLUME, "SET_VOLUME",
-            halDataSize, &halData[0]);
-}
-
-Return<Result> Effect::setAudioMode(AudioMode mode)  {
-    uint32_t halMode = static_cast<uint32_t>(mode);
-    return sendCommand(
-            EFFECT_CMD_SET_AUDIO_MODE, "SET_AUDIO_MODE", sizeof(uint32_t), &halMode);
-}
-
-Return<Result> Effect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider)  {
-    return setConfigImpl(EFFECT_CMD_SET_CONFIG_REVERSE, "SET_CONFIG_REVERSE",
-            config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> Effect::setInputDevice(AudioDevice device)  {
-    uint32_t halDevice = static_cast<uint32_t>(device);
-    return sendCommand(
-            EFFECT_CMD_SET_INPUT_DEVICE, "SET_INPUT_DEVICE", sizeof(uint32_t), &halDevice);
-}
-
-Return<void> Effect::getConfig(getConfig_cb _hidl_cb)  {
-    getConfigImpl(EFFECT_CMD_GET_CONFIG, "GET_CONFIG", _hidl_cb);
-    return Void();
-}
-
-Return<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb)  {
-    getConfigImpl(EFFECT_CMD_GET_CONFIG_REVERSE, "GET_CONFIG_REVERSE", _hidl_cb);
-    return Void();
-}
-
-Return<void> Effect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  {
-    hidl_vec<EffectAuxChannelsConfig> result;
-    Result retval = getSupportedConfigsImpl(
-            EFFECT_FEATURE_AUX_CHANNELS,
-            maxConfigs,
-            sizeof(channel_config_t),
-            [&] (uint32_t supportedConfigs, void* configsData) {
-                result.resize(supportedConfigs);
-                channel_config_t *config = reinterpret_cast<channel_config_t*>(configsData);
-                for (size_t i = 0; i < result.size(); ++i) {
-                    effectAuxChannelsConfigFromHal(*config++, &result[i]);
-                }
-            });
-    _hidl_cb(retval, result);
-    return Void();
-}
-
-Return<void> Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  {
-    uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
-    memset(halResult, 0, sizeof(halResult));
-    EffectAuxChannelsConfig result;
-    Result retval = getCurrentConfigImpl(
-            EFFECT_FEATURE_AUX_CHANNELS,
-            sizeof(channel_config_t),
-            [&] (void* configData) {
-                effectAuxChannelsConfigFromHal(
-                        *reinterpret_cast<channel_config_t*>(configData), &result);
-            });
-    _hidl_cb(retval, result);
-    return Void();
-}
-
-Return<Result> Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  {
-    uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
-    halCmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
-    effectAuxChannelsConfigToHal(config, reinterpret_cast<channel_config_t*>(&halCmd[1]));
-    return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG,
-            "SET_FEATURE_CONFIG AUX_CHANNELS", sizeof(halCmd), halCmd);
-}
-
-Return<Result> Effect::setAudioSource(AudioSource source)  {
-    uint32_t halSource = static_cast<uint32_t>(source);
-    return sendCommand(
-            EFFECT_CMD_SET_AUDIO_SOURCE, "SET_AUDIO_SOURCE", sizeof(uint32_t), &halSource);
-}
-
-Return<Result> Effect::offload(const EffectOffloadParameter& param)  {
-    effect_offload_param_t halParam;
-    effectOffloadParamToHal(param, &halParam);
-    return sendCommandReturningStatus(
-            EFFECT_CMD_OFFLOAD, "OFFLOAD", sizeof(effect_offload_param_t), &halParam);
-}
-
-Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb)  {
-    effect_descriptor_t halDescriptor;
-    memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
-    status_t status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
-    EffectDescriptor descriptor;
-    if (status == OK) {
-        effectDescriptorFromHal(halDescriptor, &descriptor);
-    }
-    _hidl_cb(analyzeStatus("get_descriptor", "", sContextCallFunction, status), descriptor);
-    return Void();
-}
-
-Return<void> Effect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb)  {
-    uint32_t halDataSize;
-    std::unique_ptr<uint8_t[]> halData = hidlVecToHal(data, &halDataSize);
-    uint32_t halResultSize = resultMaxSize;
-    std::unique_ptr<uint8_t[]> halResult(new uint8_t[halResultSize]);
-    memset(&halResult[0], 0, halResultSize);
-
-    void* dataPtr = halDataSize > 0 ? &halData[0] : NULL;
-    void* resultPtr = halResultSize > 0 ? &halResult[0] : NULL;
-    status_t status = (*mHandle)->command(
-            mHandle, commandId, halDataSize, dataPtr, &halResultSize, resultPtr);
-    hidl_vec<uint8_t> result;
-    if (status == OK && resultPtr != NULL) {
-        result.setToExternal(&halResult[0], halResultSize);
-    }
-    _hidl_cb(status, result);
-    return Void();
-}
-
-Return<Result> Effect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  {
-    return setParameterImpl(parameter.size(), &parameter[0], value.size(), &value[0]);
-}
-
-Return<void> Effect::getParameter(
-        const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize, getParameter_cb _hidl_cb)  {
-    hidl_vec<uint8_t> value;
-    Result retval = getParameterImpl(
-            parameter.size(),
-            &parameter[0],
-            valueMaxSize,
-            [&] (uint32_t valueSize, const void* valueData) {
-                value.setToExternal(
-                        reinterpret_cast<uint8_t*>(const_cast<void*>(valueData)), valueSize);
-            });
-    _hidl_cb(retval, value);
-    return Void();
-}
-
-Return<void> Effect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb)  {
-    uint32_t configCount = 0;
-    hidl_vec<uint8_t> result;
-    Result retval = getSupportedConfigsImpl(
-            featureId,
-            maxConfigs,
-            configSize,
-            [&] (uint32_t supportedConfigs, void* configsData) {
-                configCount = supportedConfigs;
-                result.resize(configCount * configSize);
-                memcpy(&result[0], configsData, result.size());
-            });
-    _hidl_cb(retval, configCount, result);
-    return Void();
-}
-
-Return<void> Effect::getCurrentConfigForFeature(
-        uint32_t featureId, uint32_t configSize, getCurrentConfigForFeature_cb _hidl_cb)  {
-    hidl_vec<uint8_t> result;
-    Result retval = getCurrentConfigImpl(
-            featureId,
-            configSize,
-            [&] (void* configData) {
-                result.resize(configSize);
-                memcpy(&result[0], configData, result.size());
-            });
-    _hidl_cb(retval, result);
-    return Void();
-}
-
-Return<Result> Effect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData)  {
-    uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configData.size())];
-    memset(halCmd, 0, sizeof(halCmd));
-    halCmd[0] = featureId;
-    memcpy(&halCmd[1], &configData[0], configData.size());
-    return sendCommandReturningStatus(
-            EFFECT_CMD_SET_FEATURE_CONFIG, "SET_FEATURE_CONFIG", sizeof(halCmd), halCmd);
-}
-
-Return<Result> Effect::close() {
-    if (mIsClosed) return Result::INVALID_STATE;
-    mIsClosed = true;
-    if (mProcessThread.get()) {
-        mStopProcessThread.store(true, std::memory_order_release);
-    }
-    if (mEfGroup) {
-        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT));
-    }
-    return Result::OK;
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/Effect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/Effect.h b/audio/effect/2.0/default/Effect.h
index 0918cd8..a4d194d 100644
--- a/audio/effect/2.0/default/Effect.h
+++ b/audio/effect/2.0/default/Effect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -17,259 +17,12 @@
 #ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECT_H
 #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECT_H
 
-#include <atomic>
-#include <memory>
-#include <vector>
-
 #include <android/hardware/audio/effect/2.0/IEffect.h>
-#include <fmq/EventFlag.h>
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-#include <utils/Thread.h>
-
-#include <hardware/audio_effect.h>
 
 #include "AudioBufferManager.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::common::V2_0::AudioDevice;
-using ::android::hardware::audio::common::V2_0::AudioMode;
-using ::android::hardware::audio::common::V2_0::AudioSource;
-using ::android::hardware::audio::common::V2_0::Uuid;
-using ::android::hardware::audio::effect::V2_0::AudioBuffer;
-using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
-using ::android::hardware::audio::effect::V2_0::EffectConfig;
-using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
-using ::android::hardware::audio::effect::V2_0::EffectFeature;
-using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
-using ::android::hardware::audio::effect::V2_0::IEffect;
-using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
-using ::android::hardware::audio::effect::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 Effect : public IEffect {
-    typedef MessageQueue<Result, kSynchronizedReadWrite> StatusMQ;
-    using GetParameterSuccessCallback =
-            std::function<void(uint32_t valueSize, const void* valueData)>;
-
-    explicit Effect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Utility methods for extending interfaces.
-    template<typename T> Return<void> getIntegerParam(
-            uint32_t paramId, std::function<void(Result retval, T paramValue)> cb) {
-        T value;
-        Result retval = getParameterImpl(
-                sizeof(uint32_t), &paramId,
-                sizeof(T),
-                [&] (uint32_t valueSize, const void* valueData) {
-                    if (valueSize > sizeof(T)) valueSize = sizeof(T);
-                    memcpy(&value, valueData, valueSize);
-                });
-        cb(retval, value);
-        return Void();
-    }
-
-    template<typename T> Result getParam(uint32_t paramId, T& paramValue) {
-        return getParameterImpl(
-                sizeof(uint32_t), &paramId,
-                sizeof(T),
-                [&] (uint32_t valueSize, const void* valueData) {
-                    if (valueSize > sizeof(T)) valueSize = sizeof(T);
-                    memcpy(&paramValue, valueData, valueSize);
-                });
-    }
-
-    template<typename T> Result getParam(uint32_t paramId, uint32_t paramArg, T& paramValue) {
-        uint32_t params[2] = { paramId, paramArg };
-        return getParameterImpl(
-                sizeof(params), params,
-                sizeof(T),
-                [&] (uint32_t valueSize, const void* valueData) {
-                    if (valueSize > sizeof(T)) valueSize = sizeof(T);
-                    memcpy(&paramValue, valueData, valueSize);
-                });
-    }
-
-    template<typename T> Result setParam(uint32_t paramId, const T& paramValue) {
-        return setParameterImpl(sizeof(uint32_t), &paramId, sizeof(T), &paramValue);
-    }
-
-    template<typename T> Result setParam(uint32_t paramId, uint32_t paramArg, const T& paramValue) {
-        uint32_t params[2] = { paramId, paramArg };
-        return setParameterImpl(sizeof(params), params, sizeof(T), &paramValue);
-    }
-
-    Result getParameterImpl(
-            uint32_t paramSize,
-            const void* paramData,
-            uint32_t valueSize,
-            GetParameterSuccessCallback onSuccess) {
-        return getParameterImpl(paramSize, paramData, valueSize, valueSize, onSuccess);
-    }
-    Result getParameterImpl(
-            uint32_t paramSize,
-            const void* paramData,
-            uint32_t requestValueSize,
-            uint32_t replyValueSize,
-            GetParameterSuccessCallback onSuccess);
-    Result setParameterImpl(
-            uint32_t paramSize, const void* paramData, uint32_t valueSize, const void* valueData);
-
-  private:
-    friend struct VirtualizerEffect;  // for getParameterImpl
-    friend struct VisualizerEffect;   // to allow executing commands
-
-    using CommandSuccessCallback = std::function<void()>;
-    using GetConfigCallback = std::function<void(Result retval, const EffectConfig& config)>;
-    using GetCurrentConfigSuccessCallback = std::function<void(void* configData)>;
-    using GetSupportedConfigsSuccessCallback =
-            std::function<void(uint32_t supportedConfigs, void* configsData)>;
-
-    static const char *sContextResultOfCommand;
-    static const char *sContextCallToCommand;
-    static const char *sContextCallFunction;
-
-    bool mIsClosed;
-    effect_handle_t mHandle;
-    sp<AudioBufferWrapper> mInBuffer;
-    sp<AudioBufferWrapper> mOutBuffer;
-    std::atomic<audio_buffer_t*> mHalInBufferPtr;
-    std::atomic<audio_buffer_t*> mHalOutBufferPtr;
-    std::unique_ptr<StatusMQ> mStatusMQ;
-    EventFlag* mEfGroup;
-    std::atomic<bool> mStopProcessThread;
-    sp<Thread> mProcessThread;
-
-    virtual ~Effect();
-
-    template<typename T> static size_t alignedSizeIn(size_t s);
-    template<typename T> std::unique_ptr<uint8_t[]> hidlVecToHal(
-            const hidl_vec<T>& vec, uint32_t* halDataSize);
-    static void effectAuxChannelsConfigFromHal(
-            const channel_config_t& halConfig, EffectAuxChannelsConfig* config);
-    static void effectAuxChannelsConfigToHal(
-            const EffectAuxChannelsConfig& config, channel_config_t* halConfig);
-    static void effectBufferConfigFromHal(
-            const buffer_config_t& halConfig, EffectBufferConfig* config);
-    static void effectBufferConfigToHal(
-            const EffectBufferConfig& config, buffer_config_t* halConfig);
-    static void effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config);
-    static void effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig);
-    static void effectOffloadParamToHal(
-            const EffectOffloadParameter& offload, effect_offload_param_t* halOffload);
-    static std::vector<uint8_t> parameterToHal(
-            uint32_t paramSize, const void* paramData, uint32_t valueSize, const void** valueData);
-
-    Result analyzeCommandStatus(
-            const char* commandName, const char* context, status_t status);
-    Result analyzeStatus(
-            const char* funcName,
-            const char* subFuncName,
-            const char* contextDescription,
-            status_t status);
-    void getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb);
-    Result getCurrentConfigImpl(
-            uint32_t featureId, uint32_t configSize, GetCurrentConfigSuccessCallback onSuccess);
-    Result getSupportedConfigsImpl(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            GetSupportedConfigsSuccessCallback onSuccess);
-    Result sendCommand(int commandCode, const char* commandName);
-    Result sendCommand(int commandCode, const char* commandName, uint32_t size, void* data);
-    Result sendCommandReturningData(
-            int commandCode, const char* commandName, uint32_t* replySize, void* replyData);
-    Result sendCommandReturningData(
-            int commandCode, const char* commandName,
-            uint32_t size, void* data,
-            uint32_t* replySize, void* replyData);
-    Result sendCommandReturningStatus(int commandCode, const char* commandName);
-    Result sendCommandReturningStatus(
-            int commandCode, const char* commandName, uint32_t size, void* data);
-    Result sendCommandReturningStatusAndData(
-            int commandCode, const char* commandName,
-            uint32_t size, void* data,
-            uint32_t* replySize, void* replyData,
-            uint32_t minReplySize,
-            CommandSuccessCallback onSuccess);
-    Result setConfigImpl(
-            int commandCode, const char* commandName,
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider);
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/Effect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECT_H
diff --git a/audio/effect/2.0/default/EffectsFactory.cpp b/audio/effect/2.0/default/EffectsFactory.cpp
index 922a922..a48a85f 100644
--- a/audio/effect/2.0/default/EffectsFactory.cpp
+++ b/audio/effect/2.0/default/EffectsFactory.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -15,191 +15,25 @@
  */
 
 #define LOG_TAG "EffectFactoryHAL"
-#include <media/EffectsFactoryApi.h>
-#include <system/audio_effects/effect_aec.h>
-#include <system/audio_effects/effect_agc.h>
-#include <system/audio_effects/effect_bassboost.h>
-#include <system/audio_effects/effect_downmix.h>
-#include <system/audio_effects/effect_environmentalreverb.h>
-#include <system/audio_effects/effect_equalizer.h>
-#include <system/audio_effects/effect_loudnessenhancer.h>
-#include <system/audio_effects/effect_ns.h>
-#include <system/audio_effects/effect_presetreverb.h>
-#include <system/audio_effects/effect_virtualizer.h>
-#include <system/audio_effects/effect_visualizer.h>
-#include <android/log.h>
-
+#include "EffectsFactory.h"
 #include "AcousticEchoCancelerEffect.h"
 #include "AutomaticGainControlEffect.h"
 #include "BassBoostEffect.h"
 #include "Conversions.h"
 #include "DownmixEffect.h"
-#include "EffectsFactory.h"
-#include "HidlUtils.h"
 #include "Effect.h"
-#include "EffectMap.h"
 #include "EnvironmentalReverbEffect.h"
 #include "EqualizerEffect.h"
+#include "HidlUtils.h"
 #include "LoudnessEnhancerEffect.h"
 #include "NoiseSuppressionEffect.h"
 #include "PresetReverbEffect.h"
 #include "VirtualizerEffect.h"
 #include "VisualizerEffect.h"
+#include "common/all-versions/default/EffectMap.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
+using ::android::hardware::audio::common::V2_0::HidlUtils;
 
-// static
-sp<IEffect> EffectsFactory::dispatchEffectInstanceCreation(
-        const effect_descriptor_t& halDescriptor, effect_handle_t handle) {
-    const effect_uuid_t *halUuid = &halDescriptor.type;
-    if (memcmp(halUuid, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
-        return new AcousticEchoCancelerEffect(handle);
-    } else if (memcmp(halUuid, FX_IID_AGC, sizeof(effect_uuid_t)) == 0) {
-        return new AutomaticGainControlEffect(handle);
-    } else if (memcmp(halUuid, SL_IID_BASSBOOST, sizeof(effect_uuid_t)) == 0) {
-        return new BassBoostEffect(handle);
-    } else if (memcmp(halUuid, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
-        return new DownmixEffect(handle);
-    } else if (memcmp(halUuid, SL_IID_ENVIRONMENTALREVERB, sizeof(effect_uuid_t)) == 0) {
-        return new EnvironmentalReverbEffect(handle);
-    } else if (memcmp(halUuid, SL_IID_EQUALIZER, sizeof(effect_uuid_t)) == 0) {
-        return new EqualizerEffect(handle);
-    } else if (memcmp(halUuid, FX_IID_LOUDNESS_ENHANCER, sizeof(effect_uuid_t)) == 0) {
-        return new LoudnessEnhancerEffect(handle);
-    } else if (memcmp(halUuid, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
-        return new NoiseSuppressionEffect(handle);
-    } else if (memcmp(halUuid, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
-        return new PresetReverbEffect(handle);
-    } else if (memcmp(halUuid, SL_IID_VIRTUALIZER, sizeof(effect_uuid_t)) == 0) {
-        return new VirtualizerEffect(handle);
-    } else if (memcmp(halUuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) {
-        return new VisualizerEffect(handle);
-    }
-    return new Effect(handle);
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffectsFactory follow.
-Return<void> EffectsFactory::getAllDescriptors(getAllDescriptors_cb _hidl_cb)  {
-    Result retval(Result::OK);
-    hidl_vec<EffectDescriptor> result;
-    uint32_t numEffects;
-    status_t status;
-
-restart:
-    numEffects = 0;
-    status = EffectQueryNumberEffects(&numEffects);
-    if (status != OK) {
-        retval = Result::NOT_INITIALIZED;
-        ALOGE("Error querying number of effects: %s", strerror(-status));
-        goto exit;
-    }
-    result.resize(numEffects);
-    for (uint32_t i = 0; i < numEffects; ++i) {
-        effect_descriptor_t halDescriptor;
-        status = EffectQueryEffect(i, &halDescriptor);
-        if (status == OK) {
-            effectDescriptorFromHal(halDescriptor, &result[i]);
-        } else {
-            ALOGE("Error querying effect at position %d / %d: %s",
-                    i, numEffects, strerror(-status));
-            switch (status) {
-                case -ENOSYS: {
-                    // Effect list has changed.
-                    goto restart;
-                }
-                case -ENOENT: {
-                    // No more effects available.
-                    result.resize(i);
-                }
-                default: {
-                    result.resize(0);
-                    retval = Result::NOT_INITIALIZED;
-                }
-            }
-            break;
-        }
-    }
-
-exit:
-    _hidl_cb(retval, result);
-    return Void();
-}
-
-Return<void> EffectsFactory::getDescriptor(const Uuid& uid, getDescriptor_cb _hidl_cb)  {
-    effect_uuid_t halUuid;
-    HidlUtils::uuidToHal(uid, &halUuid);
-    effect_descriptor_t halDescriptor;
-    status_t status = EffectGetDescriptor(&halUuid, &halDescriptor);
-    EffectDescriptor descriptor;
-    effectDescriptorFromHal(halDescriptor, &descriptor);
-    Result retval(Result::OK);
-    if (status != OK) {
-        ALOGE("Error querying effect descriptor for %s: %s",
-                uuidToString(halUuid).c_str(), strerror(-status));
-        if (status == -ENOENT) {
-            retval = Result::INVALID_ARGUMENTS;
-        } else {
-            retval = Result::NOT_INITIALIZED;
-        }
-    }
-    _hidl_cb(retval, descriptor);
-    return Void();
-}
-
-Return<void> EffectsFactory::createEffect(
-        const Uuid& uid, int32_t session, int32_t ioHandle, createEffect_cb _hidl_cb)  {
-    effect_uuid_t halUuid;
-    HidlUtils::uuidToHal(uid, &halUuid);
-    effect_handle_t handle;
-    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 {
-            ALOGE("Error querying effect descriptor for %s: %s",
-                    uuidToString(halUuid).c_str(), strerror(-status));
-            EffectRelease(handle);
-        }
-    }
-    if (status != OK) {
-        ALOGE("Error creating effect %s: %s", uuidToString(halUuid).c_str(), strerror(-status));
-        if (status == -ENOENT) {
-            retval = Result::INVALID_ARGUMENTS;
-        } else {
-            retval = Result::NOT_INITIALIZED;
-        }
-    }
-    _hidl_cb(retval, effect, effectId);
-    return Void();
-}
-
-Return<void> EffectsFactory::debugDump(const hidl_handle& fd)  {
-    if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
-        EffectDumpEffects(fd->data[0]);
-    }
-    return Void();
-}
-
-
-IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* /* name */) {
-    return new EffectsFactory();
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/EffectsFactory.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/EffectsFactory.h b/audio/effect/2.0/default/EffectsFactory.h
index 829a534..f1bfbcf 100644
--- a/audio/effect/2.0/default/EffectsFactory.h
+++ b/audio/effect/2.0/default/EffectsFactory.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -20,47 +20,10 @@
 #include <system/audio_effect.h>
 
 #include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
-#include <hidl/Status.h>
 
 #include <hidl/MQDescriptor.h>
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-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::Void;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_string;
-using ::android::sp;
-
-struct EffectsFactory : public IEffectsFactory {
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffectsFactory follow.
-    Return<void> getAllDescriptors(getAllDescriptors_cb _hidl_cb)  override;
-    Return<void> getDescriptor(const Uuid& uid, getDescriptor_cb _hidl_cb)  override;
-    Return<void> createEffect(
-            const Uuid& uid, int32_t session, int32_t ioHandle, createEffect_cb _hidl_cb)  override;
-    Return<void> debugDump(const hidl_handle& fd)  override;
-
-  private:
-    static sp<IEffect> dispatchEffectInstanceCreation(
-            const effect_descriptor_t& halDescriptor, effect_handle_t handle);
-};
-
-extern "C" IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* name);
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/EffectsFactory.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECTSFACTORY_H
diff --git a/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp b/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp
index 86ff368..017dd1f 100644
--- a/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp
+++ b/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -19,298 +19,6 @@
 
 #include "EnvironmentalReverbEffect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-EnvironmentalReverbEffect::EnvironmentalReverbEffect(effect_handle_t handle)
-        : mEffect(new Effect(handle)) {
-}
-
-EnvironmentalReverbEffect::~EnvironmentalReverbEffect() {}
-
-void EnvironmentalReverbEffect::propertiesFromHal(
-        const t_reverb_settings& halProperties,
-        IEnvironmentalReverbEffect::AllProperties* properties) {
-    properties->roomLevel = halProperties.roomLevel;
-    properties->roomHfLevel = halProperties.roomHFLevel;
-    properties->decayTime = halProperties.decayTime;
-    properties->decayHfRatio = halProperties.decayHFRatio;
-    properties->reflectionsLevel = halProperties.reflectionsLevel;
-    properties->reflectionsDelay = halProperties.reflectionsDelay;
-    properties->reverbLevel = halProperties.reverbLevel;
-    properties->reverbDelay = halProperties.reverbDelay;
-    properties->diffusion = halProperties.diffusion;
-    properties->density = halProperties.density;
-}
-
-void EnvironmentalReverbEffect::propertiesToHal(
-        const IEnvironmentalReverbEffect::AllProperties& properties,
-        t_reverb_settings* halProperties) {
-    halProperties->roomLevel = properties.roomLevel;
-    halProperties->roomHFLevel = properties.roomHfLevel;
-    halProperties->decayTime = properties.decayTime;
-    halProperties->decayHFRatio = properties.decayHfRatio;
-    halProperties->reflectionsLevel = properties.reflectionsLevel;
-    halProperties->reflectionsDelay = properties.reflectionsDelay;
-    halProperties->reverbLevel = properties.reverbLevel;
-    halProperties->reverbDelay = properties.reverbDelay;
-    halProperties->diffusion = properties.diffusion;
-    halProperties->density = properties.density;
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> EnvironmentalReverbEffect::init() {
-    return mEffect->init();
-}
-
-Return<Result> EnvironmentalReverbEffect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> EnvironmentalReverbEffect::reset() {
-    return mEffect->reset();
-}
-
-Return<Result> EnvironmentalReverbEffect::enable() {
-    return mEffect->enable();
-}
-
-Return<Result> EnvironmentalReverbEffect::disable() {
-    return mEffect->disable();
-}
-
-Return<Result> EnvironmentalReverbEffect::setDevice(AudioDevice device) {
-    return mEffect->setDevice(device);
-}
-
-Return<void> EnvironmentalReverbEffect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
-    return mEffect->setAndGetVolume(volumes, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::volumeChangeNotification(
-        const hidl_vec<uint32_t>& volumes) {
-    return mEffect->volumeChangeNotification(volumes);
-}
-
-Return<Result> EnvironmentalReverbEffect::setAudioMode(AudioMode mode) {
-    return mEffect->setAudioMode(mode);
-}
-
-Return<Result> EnvironmentalReverbEffect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> EnvironmentalReverbEffect::setInputDevice(AudioDevice device) {
-    return mEffect->setInputDevice(device);
-}
-
-Return<void> EnvironmentalReverbEffect::getConfig(getConfig_cb _hidl_cb) {
-    return mEffect->getConfig(_hidl_cb);
-}
-
-Return<void> EnvironmentalReverbEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    return mEffect->getConfigReverse(_hidl_cb);
-}
-
-Return<void> EnvironmentalReverbEffect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
-    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
-}
-
-Return<void> EnvironmentalReverbEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    return mEffect->getAuxChannelsConfig(_hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setAuxChannelsConfig(
-        const EffectAuxChannelsConfig& config) {
-    return mEffect->setAuxChannelsConfig(config);
-}
-
-Return<Result> EnvironmentalReverbEffect::setAudioSource(AudioSource source) {
-    return mEffect->setAudioSource(source);
-}
-
-Return<Result> EnvironmentalReverbEffect::offload(const EffectOffloadParameter& param) {
-    return mEffect->offload(param);
-}
-
-Return<void> EnvironmentalReverbEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
-    return mEffect->getDescriptor(_hidl_cb);
-}
-
-Return<void> EnvironmentalReverbEffect::prepareForProcessing(
-        prepareForProcessing_cb _hidl_cb) {
-    return mEffect->prepareForProcessing(_hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    return mEffect->setProcessBuffers(inBuffer, outBuffer);
-}
-
-Return<void> EnvironmentalReverbEffect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb) {
-    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
-    return mEffect->setParameter(parameter, value);
-}
-
-Return<void> EnvironmentalReverbEffect::getParameter(
-        const hidl_vec<uint8_t>& parameter,
-        uint32_t valueMaxSize,
-        getParameter_cb _hidl_cb) {
-    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
-}
-
-Return<void> EnvironmentalReverbEffect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb) {
-    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
-}
-
-Return<void> EnvironmentalReverbEffect::getCurrentConfigForFeature(
-        uint32_t featureId,
-        uint32_t configSize,
-        getCurrentConfigForFeature_cb _hidl_cb) {
-    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
-    return mEffect->setCurrentConfigForFeature(featureId, configData);
-}
-
-Return<Result> EnvironmentalReverbEffect::close() {
-    return mEffect->close();
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect follow.
-Return<Result> EnvironmentalReverbEffect::setBypass(bool bypass)  {
-    return mEffect->setParam(REVERB_PARAM_BYPASS, bypass);
-}
-
-Return<void> EnvironmentalReverbEffect::getBypass(getBypass_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(REVERB_PARAM_BYPASS, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setRoomLevel(int16_t roomLevel)  {
-    return mEffect->setParam(REVERB_PARAM_ROOM_LEVEL, roomLevel);
-}
-
-Return<void> EnvironmentalReverbEffect::getRoomLevel(getRoomLevel_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(REVERB_PARAM_ROOM_LEVEL, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setRoomHfLevel(int16_t roomHfLevel)  {
-    return mEffect->setParam(REVERB_PARAM_ROOM_HF_LEVEL, roomHfLevel);
-}
-
-Return<void> EnvironmentalReverbEffect::getRoomHfLevel(getRoomHfLevel_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(REVERB_PARAM_ROOM_HF_LEVEL, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setDecayTime(uint32_t decayTime)  {
-    return mEffect->setParam(REVERB_PARAM_DECAY_TIME, decayTime);
-}
-
-Return<void> EnvironmentalReverbEffect::getDecayTime(getDecayTime_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(REVERB_PARAM_DECAY_TIME, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setDecayHfRatio(int16_t decayHfRatio)  {
-    return mEffect->setParam(REVERB_PARAM_DECAY_HF_RATIO, decayHfRatio);
-}
-
-Return<void> EnvironmentalReverbEffect::getDecayHfRatio(getDecayHfRatio_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(REVERB_PARAM_DECAY_HF_RATIO, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setReflectionsLevel(int16_t reflectionsLevel)  {
-    return mEffect->setParam(REVERB_PARAM_REFLECTIONS_LEVEL, reflectionsLevel);
-}
-
-Return<void> EnvironmentalReverbEffect::getReflectionsLevel(getReflectionsLevel_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(REVERB_PARAM_REFLECTIONS_LEVEL, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setReflectionsDelay(uint32_t reflectionsDelay)  {
-    return mEffect->setParam(REVERB_PARAM_REFLECTIONS_DELAY, reflectionsDelay);
-}
-
-Return<void> EnvironmentalReverbEffect::getReflectionsDelay(getReflectionsDelay_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(REVERB_PARAM_REFLECTIONS_DELAY, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setReverbLevel(int16_t reverbLevel)  {
-    return mEffect->setParam(REVERB_PARAM_REVERB_LEVEL, reverbLevel);
-}
-
-Return<void> EnvironmentalReverbEffect::getReverbLevel(getReverbLevel_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(REVERB_PARAM_REVERB_LEVEL, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setReverbDelay(uint32_t reverbDelay) {
-    return mEffect->setParam(REVERB_PARAM_REVERB_DELAY, reverbDelay);
-}
-
-Return<void> EnvironmentalReverbEffect::getReverbDelay(getReverbDelay_cb _hidl_cb) {
-    return mEffect->getIntegerParam(REVERB_PARAM_REVERB_DELAY, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setDiffusion(int16_t diffusion)  {
-    return mEffect->setParam(REVERB_PARAM_DIFFUSION, diffusion);
-}
-
-Return<void> EnvironmentalReverbEffect::getDiffusion(getDiffusion_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(REVERB_PARAM_DIFFUSION, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setDensity(int16_t density)  {
-    return mEffect->setParam(REVERB_PARAM_DENSITY, density);
-}
-
-Return<void> EnvironmentalReverbEffect::getDensity(getDensity_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(REVERB_PARAM_DENSITY, _hidl_cb);
-}
-
-Return<Result> EnvironmentalReverbEffect::setAllProperties(
-        const IEnvironmentalReverbEffect::AllProperties& properties)  {
-    t_reverb_settings halProperties;
-    propertiesToHal(properties, &halProperties);
-    return mEffect->setParam(REVERB_PARAM_PROPERTIES, halProperties);
-}
-
-Return<void> EnvironmentalReverbEffect::getAllProperties(getAllProperties_cb _hidl_cb)  {
-    t_reverb_settings halProperties;
-    Result retval = mEffect->getParam(REVERB_PARAM_PROPERTIES, halProperties);
-    AllProperties properties;
-    propertiesFromHal(halProperties, &properties);
-    _hidl_cb(retval, properties);
-    return Void();
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/EnvironmentalReverbEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/EnvironmentalReverbEffect.h b/audio/effect/2.0/default/EnvironmentalReverbEffect.h
index 794caac..d93a53f 100644
--- a/audio/effect/2.0/default/EnvironmentalReverbEffect.h
+++ b/audio/effect/2.0/default/EnvironmentalReverbEffect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -20,140 +20,11 @@
 #include <system/audio_effects/effect_environmentalreverb.h>
 
 #include <android/hardware/audio/effect/2.0/IEnvironmentalReverbEffect.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
 
 #include "Effect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::common::V2_0::AudioDevice;
-using ::android::hardware::audio::common::V2_0::AudioMode;
-using ::android::hardware::audio::common::V2_0::AudioSource;
-using ::android::hardware::audio::effect::V2_0::AudioBuffer;
-using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
-using ::android::hardware::audio::effect::V2_0::EffectConfig;
-using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
-using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
-using ::android::hardware::audio::effect::V2_0::IEffect;
-using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
-using ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect;
-using ::android::hardware::audio::effect::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 EnvironmentalReverbEffect : public IEnvironmentalReverbEffect {
-    explicit EnvironmentalReverbEffect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect follow.
-    Return<Result> setBypass(bool bypass)  override;
-    Return<void> getBypass(getBypass_cb _hidl_cb)  override;
-    Return<Result> setRoomLevel(int16_t roomLevel)  override;
-    Return<void> getRoomLevel(getRoomLevel_cb _hidl_cb)  override;
-    Return<Result> setRoomHfLevel(int16_t roomHfLevel)  override;
-    Return<void> getRoomHfLevel(getRoomHfLevel_cb _hidl_cb)  override;
-    Return<Result> setDecayTime(uint32_t decayTime)  override;
-    Return<void> getDecayTime(getDecayTime_cb _hidl_cb)  override;
-    Return<Result> setDecayHfRatio(int16_t decayHfRatio)  override;
-    Return<void> getDecayHfRatio(getDecayHfRatio_cb _hidl_cb)  override;
-    Return<Result> setReflectionsLevel(int16_t reflectionsLevel)  override;
-    Return<void> getReflectionsLevel(getReflectionsLevel_cb _hidl_cb)  override;
-    Return<Result> setReflectionsDelay(uint32_t reflectionsDelay)  override;
-    Return<void> getReflectionsDelay(getReflectionsDelay_cb _hidl_cb)  override;
-    Return<Result> setReverbLevel(int16_t reverbLevel)  override;
-    Return<void> getReverbLevel(getReverbLevel_cb _hidl_cb)  override;
-    Return<Result> setReverbDelay(uint32_t reverbDelay)  override;
-    Return<void> getReverbDelay(getReverbDelay_cb _hidl_cb)  override;
-    Return<Result> setDiffusion(int16_t diffusion)  override;
-    Return<void> getDiffusion(getDiffusion_cb _hidl_cb)  override;
-    Return<Result> setDensity(int16_t density)  override;
-    Return<void> getDensity(getDensity_cb _hidl_cb)  override;
-    Return<Result> setAllProperties(
-            const IEnvironmentalReverbEffect::AllProperties& properties)  override;
-    Return<void> getAllProperties(getAllProperties_cb _hidl_cb)  override;
-
-  private:
-    sp<Effect> mEffect;
-
-    virtual ~EnvironmentalReverbEffect();
-
-    void propertiesFromHal(
-            const t_reverb_settings& halProperties,
-            IEnvironmentalReverbEffect::AllProperties* properties);
-    void propertiesToHal(
-            const IEnvironmentalReverbEffect::AllProperties& properties,
-            t_reverb_settings* halProperties);
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/EnvironmentalReverbEffect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_ENVIRONMENTALREVERBEFFECT_H
diff --git a/audio/effect/2.0/default/EqualizerEffect.cpp b/audio/effect/2.0/default/EqualizerEffect.cpp
index 808d8eb..d6e056c 100644
--- a/audio/effect/2.0/default/EqualizerEffect.cpp
+++ b/audio/effect/2.0/default/EqualizerEffect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -14,298 +14,10 @@
  * limitations under the License.
  */
 
-#include <memory.h>
-
 #define LOG_TAG "Equalizer_HAL"
-#include <android/log.h>
 
 #include "EqualizerEffect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-EqualizerEffect::EqualizerEffect(effect_handle_t handle)
-        : mEffect(new Effect(handle)) {
-}
-
-EqualizerEffect::~EqualizerEffect() {}
-
-void EqualizerEffect::propertiesFromHal(
-        const t_equalizer_settings& halProperties,
-        IEqualizerEffect::AllProperties* properties) {
-    properties->curPreset = halProperties.curPreset;
-    // t_equalizer_settings incorrectly defines bandLevels as uint16_t,
-    // whereas the actual type of values used by effects is int16_t.
-    const int16_t* signedBandLevels =
-            reinterpret_cast<const int16_t*>(&halProperties.bandLevels[0]);
-    properties->bandLevels.setToExternal(
-            const_cast<int16_t*>(signedBandLevels), halProperties.numBands);
-}
-
-std::vector<uint8_t> EqualizerEffect::propertiesToHal(
-        const IEqualizerEffect::AllProperties& properties,
-        t_equalizer_settings** halProperties) {
-    size_t bandsSize = properties.bandLevels.size() * sizeof(uint16_t);
-    std::vector<uint8_t> halBuffer(sizeof(t_equalizer_settings) + bandsSize, 0);
-    *halProperties = reinterpret_cast<t_equalizer_settings*>(&halBuffer[0]);
-    (*halProperties)->curPreset = properties.curPreset;
-    (*halProperties)->numBands = properties.bandLevels.size();
-    memcpy((*halProperties)->bandLevels, &properties.bandLevels[0], bandsSize);
-    return halBuffer;
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> EqualizerEffect::init() {
-    return mEffect->init();
-}
-
-Return<Result> EqualizerEffect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> EqualizerEffect::reset() {
-    return mEffect->reset();
-}
-
-Return<Result> EqualizerEffect::enable() {
-    return mEffect->enable();
-}
-
-Return<Result> EqualizerEffect::disable() {
-    return mEffect->disable();
-}
-
-Return<Result> EqualizerEffect::setDevice(AudioDevice device) {
-    return mEffect->setDevice(device);
-}
-
-Return<void> EqualizerEffect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
-    return mEffect->setAndGetVolume(volumes, _hidl_cb);
-}
-
-Return<Result> EqualizerEffect::volumeChangeNotification(
-        const hidl_vec<uint32_t>& volumes) {
-    return mEffect->volumeChangeNotification(volumes);
-}
-
-Return<Result> EqualizerEffect::setAudioMode(AudioMode mode) {
-    return mEffect->setAudioMode(mode);
-}
-
-Return<Result> EqualizerEffect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> EqualizerEffect::setInputDevice(AudioDevice device) {
-    return mEffect->setInputDevice(device);
-}
-
-Return<void> EqualizerEffect::getConfig(getConfig_cb _hidl_cb) {
-    return mEffect->getConfig(_hidl_cb);
-}
-
-Return<void> EqualizerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    return mEffect->getConfigReverse(_hidl_cb);
-}
-
-Return<void> EqualizerEffect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
-    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
-}
-
-Return<void> EqualizerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    return mEffect->getAuxChannelsConfig(_hidl_cb);
-}
-
-Return<Result> EqualizerEffect::setAuxChannelsConfig(
-        const EffectAuxChannelsConfig& config) {
-    return mEffect->setAuxChannelsConfig(config);
-}
-
-Return<Result> EqualizerEffect::setAudioSource(AudioSource source) {
-    return mEffect->setAudioSource(source);
-}
-
-Return<Result> EqualizerEffect::offload(const EffectOffloadParameter& param) {
-    return mEffect->offload(param);
-}
-
-Return<void> EqualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
-    return mEffect->getDescriptor(_hidl_cb);
-}
-
-Return<void> EqualizerEffect::prepareForProcessing(
-        prepareForProcessing_cb _hidl_cb) {
-    return mEffect->prepareForProcessing(_hidl_cb);
-}
-
-Return<Result> EqualizerEffect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    return mEffect->setProcessBuffers(inBuffer, outBuffer);
-}
-
-Return<void> EqualizerEffect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb) {
-    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
-}
-
-Return<Result> EqualizerEffect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
-    return mEffect->setParameter(parameter, value);
-}
-
-Return<void> EqualizerEffect::getParameter(
-        const hidl_vec<uint8_t>& parameter,
-        uint32_t valueMaxSize,
-        getParameter_cb _hidl_cb) {
-    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
-}
-
-Return<void> EqualizerEffect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb) {
-    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
-}
-
-Return<void> EqualizerEffect::getCurrentConfigForFeature(
-        uint32_t featureId,
-        uint32_t configSize,
-        getCurrentConfigForFeature_cb _hidl_cb) {
-    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
-}
-
-Return<Result> EqualizerEffect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
-    return mEffect->setCurrentConfigForFeature(featureId, configData);
-}
-
-Return<Result> EqualizerEffect::close() {
-    return mEffect->close();
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEqualizerEffect follow.
-Return<void> EqualizerEffect::getNumBands(getNumBands_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(EQ_PARAM_NUM_BANDS, _hidl_cb);
-}
-
-Return<void> EqualizerEffect::getLevelRange(getLevelRange_cb _hidl_cb)  {
-    int16_t halLevels[2] = { 0, 0 };
-    Result retval = mEffect->getParam(EQ_PARAM_LEVEL_RANGE, halLevels);
-    _hidl_cb(retval, halLevels[0], halLevels[1]);
-    return Void();
-}
-
-Return<Result> EqualizerEffect::setBandLevel(uint16_t band, int16_t level)  {
-    return mEffect->setParam(EQ_PARAM_BAND_LEVEL, band, level);
-}
-
-Return<void> EqualizerEffect::getBandLevel(uint16_t band, getBandLevel_cb _hidl_cb)  {
-    int16_t halLevel = 0;
-    Result retval = mEffect->getParam(EQ_PARAM_BAND_LEVEL, band, halLevel);
-    _hidl_cb(retval, halLevel);
-    return Void();
-}
-
-Return<void> EqualizerEffect::getBandCenterFrequency(
-        uint16_t band, getBandCenterFrequency_cb _hidl_cb)  {
-    uint32_t halFreq = 0;
-    Result retval = mEffect->getParam(EQ_PARAM_CENTER_FREQ, band, halFreq);
-    _hidl_cb(retval, halFreq);
-    return Void();
-}
-
-Return<void> EqualizerEffect::getBandFrequencyRange(
-        uint16_t band, getBandFrequencyRange_cb _hidl_cb)  {
-    uint32_t halFreqs[2] = { 0, 0 };
-    Result retval = mEffect->getParam(EQ_PARAM_BAND_FREQ_RANGE, band, halFreqs);
-    _hidl_cb(retval, halFreqs[0], halFreqs[1]);
-    return Void();
-}
-
-Return<void> EqualizerEffect::getBandForFrequency(uint32_t freq, getBandForFrequency_cb _hidl_cb)  {
-    uint16_t halBand = 0;
-    Result retval = mEffect->getParam(EQ_PARAM_GET_BAND, freq, halBand);
-    _hidl_cb(retval, halBand);
-    return Void();
-}
-
-Return<void> EqualizerEffect::getPresetNames(getPresetNames_cb _hidl_cb)  {
-    uint16_t halPresetCount = 0;
-    Result retval = mEffect->getParam(EQ_PARAM_GET_NUM_OF_PRESETS, halPresetCount);
-    hidl_vec<hidl_string> presetNames;
-    if (retval == Result::OK) {
-        presetNames.resize(halPresetCount);
-        for (uint16_t i = 0; i < halPresetCount; ++i) {
-            char halPresetName[EFFECT_STRING_LEN_MAX];
-            retval = mEffect->getParam(EQ_PARAM_GET_PRESET_NAME, i, halPresetName);
-            if (retval == Result::OK) {
-                presetNames[i] = halPresetName;
-            } else {
-                presetNames.resize(i);
-            }
-        }
-    }
-    _hidl_cb(retval, presetNames);
-    return Void();
-}
-
-Return<Result> EqualizerEffect::setCurrentPreset(uint16_t preset)  {
-    return mEffect->setParam(EQ_PARAM_CUR_PRESET, preset);
-}
-
-Return<void> EqualizerEffect::getCurrentPreset(getCurrentPreset_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(EQ_PARAM_CUR_PRESET, _hidl_cb);
-}
-
-Return<Result> EqualizerEffect::setAllProperties(
-        const IEqualizerEffect::AllProperties& properties)  {
-    t_equalizer_settings *halPropertiesPtr = nullptr;
-    std::vector<uint8_t> halBuffer = propertiesToHal(properties, &halPropertiesPtr);
-    uint32_t paramId = EQ_PARAM_PROPERTIES;
-    return mEffect->setParameterImpl(
-            sizeof(paramId), &paramId, halBuffer.size(), halPropertiesPtr);
-}
-
-Return<void> EqualizerEffect::getAllProperties(getAllProperties_cb _hidl_cb)  {
-    uint16_t numBands = 0;
-    Result retval = mEffect->getParam(EQ_PARAM_NUM_BANDS, numBands);
-    AllProperties properties;
-    if (retval != Result::OK) {
-        _hidl_cb(retval, properties);
-        return Void();
-    }
-    size_t valueSize = sizeof(t_equalizer_settings) + sizeof(int16_t) * numBands;
-    uint32_t paramId = EQ_PARAM_PROPERTIES;
-    retval = mEffect->getParameterImpl(
-            sizeof(paramId), &paramId, valueSize,
-            [&] (uint32_t, const void* valueData) {
-                const t_equalizer_settings* halProperties =
-                        reinterpret_cast<const t_equalizer_settings*>(valueData);
-                propertiesFromHal(*halProperties, &properties);
-            });
-    _hidl_cb(retval, properties);
-    return Void();
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/EqualizerEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/EqualizerEffect.h b/audio/effect/2.0/default/EqualizerEffect.h
index 9e8d75b..54cdd50 100644
--- a/audio/effect/2.0/default/EqualizerEffect.h
+++ b/audio/effect/2.0/default/EqualizerEffect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -17,133 +17,12 @@
 #ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EQUALIZEREFFECT_H
 #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EQUALIZEREFFECT_H
 
-#include <vector>
-
-#include <system/audio_effects/effect_equalizer.h>
-
 #include <android/hardware/audio/effect/2.0/IEqualizerEffect.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
 
 #include "Effect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::common::V2_0::AudioDevice;
-using ::android::hardware::audio::common::V2_0::AudioMode;
-using ::android::hardware::audio::common::V2_0::AudioSource;
-using ::android::hardware::audio::effect::V2_0::AudioBuffer;
-using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
-using ::android::hardware::audio::effect::V2_0::EffectConfig;
-using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
-using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
-using ::android::hardware::audio::effect::V2_0::IEffect;
-using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
-using ::android::hardware::audio::effect::V2_0::IEqualizerEffect;
-using ::android::hardware::audio::effect::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 EqualizerEffect : public IEqualizerEffect {
-    explicit EqualizerEffect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEqualizerEffect follow.
-    Return<void> getNumBands(getNumBands_cb _hidl_cb)  override;
-    Return<void> getLevelRange(getLevelRange_cb _hidl_cb)  override;
-    Return<Result> setBandLevel(uint16_t band, int16_t level)  override;
-    Return<void> getBandLevel(uint16_t band, getBandLevel_cb _hidl_cb)  override;
-    Return<void> getBandCenterFrequency(
-            uint16_t band, getBandCenterFrequency_cb _hidl_cb)  override;
-    Return<void> getBandFrequencyRange(uint16_t band, getBandFrequencyRange_cb _hidl_cb)  override;
-    Return<void> getBandForFrequency(uint32_t freq, getBandForFrequency_cb _hidl_cb)  override;
-    Return<void> getPresetNames(getPresetNames_cb _hidl_cb)  override;
-    Return<Result> setCurrentPreset(uint16_t preset)  override;
-    Return<void> getCurrentPreset(getCurrentPreset_cb _hidl_cb)  override;
-    Return<Result> setAllProperties(const IEqualizerEffect::AllProperties& properties)  override;
-    Return<void> getAllProperties(getAllProperties_cb _hidl_cb)  override;
-
-  private:
-    sp<Effect> mEffect;
-
-    virtual ~EqualizerEffect();
-
-    void propertiesFromHal(
-            const t_equalizer_settings& halProperties,
-            IEqualizerEffect::AllProperties* properties);
-    std::vector<uint8_t> propertiesToHal(
-            const IEqualizerEffect::AllProperties& properties,
-            t_equalizer_settings** halProperties);
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/EqualizerEffect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EQUALIZEREFFECT_H
diff --git a/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp b/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp
index fda5eb0..2dca0f4 100644
--- a/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp
+++ b/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -14,191 +14,10 @@
  * limitations under the License.
  */
 
-#include <system/audio_effects/effect_loudnessenhancer.h>
-
 #define LOG_TAG "LoudnessEnhancer_HAL"
-#include <system/audio_effects/effect_aec.h>
-#include <android/log.h>
 
 #include "LoudnessEnhancerEffect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-LoudnessEnhancerEffect::LoudnessEnhancerEffect(effect_handle_t handle)
-        : mEffect(new Effect(handle)) {
-}
-
-LoudnessEnhancerEffect::~LoudnessEnhancerEffect() {}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> LoudnessEnhancerEffect::init() {
-    return mEffect->init();
-}
-
-Return<Result> LoudnessEnhancerEffect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> LoudnessEnhancerEffect::reset() {
-    return mEffect->reset();
-}
-
-Return<Result> LoudnessEnhancerEffect::enable() {
-    return mEffect->enable();
-}
-
-Return<Result> LoudnessEnhancerEffect::disable() {
-    return mEffect->disable();
-}
-
-Return<Result> LoudnessEnhancerEffect::setDevice(AudioDevice device) {
-    return mEffect->setDevice(device);
-}
-
-Return<void> LoudnessEnhancerEffect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
-    return mEffect->setAndGetVolume(volumes, _hidl_cb);
-}
-
-Return<Result> LoudnessEnhancerEffect::volumeChangeNotification(
-        const hidl_vec<uint32_t>& volumes) {
-    return mEffect->volumeChangeNotification(volumes);
-}
-
-Return<Result> LoudnessEnhancerEffect::setAudioMode(AudioMode mode) {
-    return mEffect->setAudioMode(mode);
-}
-
-Return<Result> LoudnessEnhancerEffect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> LoudnessEnhancerEffect::setInputDevice(AudioDevice device) {
-    return mEffect->setInputDevice(device);
-}
-
-Return<void> LoudnessEnhancerEffect::getConfig(getConfig_cb _hidl_cb) {
-    return mEffect->getConfig(_hidl_cb);
-}
-
-Return<void> LoudnessEnhancerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    return mEffect->getConfigReverse(_hidl_cb);
-}
-
-Return<void> LoudnessEnhancerEffect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
-    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
-}
-
-Return<void> LoudnessEnhancerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    return mEffect->getAuxChannelsConfig(_hidl_cb);
-}
-
-Return<Result> LoudnessEnhancerEffect::setAuxChannelsConfig(
-        const EffectAuxChannelsConfig& config) {
-    return mEffect->setAuxChannelsConfig(config);
-}
-
-Return<Result> LoudnessEnhancerEffect::setAudioSource(AudioSource source) {
-    return mEffect->setAudioSource(source);
-}
-
-Return<Result> LoudnessEnhancerEffect::offload(const EffectOffloadParameter& param) {
-    return mEffect->offload(param);
-}
-
-Return<void> LoudnessEnhancerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
-    return mEffect->getDescriptor(_hidl_cb);
-}
-
-Return<void> LoudnessEnhancerEffect::prepareForProcessing(
-        prepareForProcessing_cb _hidl_cb) {
-    return mEffect->prepareForProcessing(_hidl_cb);
-}
-
-Return<Result> LoudnessEnhancerEffect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    return mEffect->setProcessBuffers(inBuffer, outBuffer);
-}
-
-Return<void> LoudnessEnhancerEffect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb) {
-    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
-}
-
-Return<Result> LoudnessEnhancerEffect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
-    return mEffect->setParameter(parameter, value);
-}
-
-Return<void> LoudnessEnhancerEffect::getParameter(
-        const hidl_vec<uint8_t>& parameter,
-        uint32_t valueMaxSize,
-        getParameter_cb _hidl_cb) {
-    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
-}
-
-Return<void> LoudnessEnhancerEffect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb) {
-    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
-}
-
-Return<void> LoudnessEnhancerEffect::getCurrentConfigForFeature(
-        uint32_t featureId,
-        uint32_t configSize,
-        getCurrentConfigForFeature_cb _hidl_cb) {
-    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
-}
-
-Return<Result> LoudnessEnhancerEffect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
-    return mEffect->setCurrentConfigForFeature(featureId, configData);
-}
-
-Return<Result> LoudnessEnhancerEffect::close() {
-    return mEffect->close();
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect follow.
-Return<Result> LoudnessEnhancerEffect::setTargetGain(int32_t targetGainMb)  {
-    return mEffect->setParam(LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB, targetGainMb);
-}
-
-Return<void> LoudnessEnhancerEffect::getTargetGain(getTargetGain_cb _hidl_cb)  {
-    // AOSP Loudness Enhancer expects the size of the request to not include the
-    // size of the parameter.
-    uint32_t paramId = LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB;
-    uint32_t targetGainMb = 0;
-    Result retval = mEffect->getParameterImpl(
-            sizeof(paramId), &paramId,
-            0, sizeof(targetGainMb),
-            [&] (uint32_t, const void* valueData) {
-                memcpy(&targetGainMb, valueData, sizeof(targetGainMb));
-            });
-    _hidl_cb(retval, targetGainMb);
-    return Void();
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/LoudnessEnhancerEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/LoudnessEnhancerEffect.h b/audio/effect/2.0/default/LoudnessEnhancerEffect.h
index 039b8d6..992e238 100644
--- a/audio/effect/2.0/default/LoudnessEnhancerEffect.h
+++ b/audio/effect/2.0/default/LoudnessEnhancerEffect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -18,110 +18,11 @@
 #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_LOUDNESSENHANCEREFFECT_H
 
 #include <android/hardware/audio/effect/2.0/ILoudnessEnhancerEffect.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
 
 #include "Effect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::common::V2_0::AudioDevice;
-using ::android::hardware::audio::common::V2_0::AudioMode;
-using ::android::hardware::audio::common::V2_0::AudioSource;
-using ::android::hardware::audio::effect::V2_0::AudioBuffer;
-using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
-using ::android::hardware::audio::effect::V2_0::EffectConfig;
-using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
-using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
-using ::android::hardware::audio::effect::V2_0::IEffect;
-using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
-using ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect;
-using ::android::hardware::audio::effect::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 LoudnessEnhancerEffect : public ILoudnessEnhancerEffect {
-    explicit LoudnessEnhancerEffect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Methods from ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect follow.
-    Return<Result> setTargetGain(int32_t targetGainMb)  override;
-    Return<void> getTargetGain(getTargetGain_cb _hidl_cb)  override;
-
-  private:
-    sp<Effect> mEffect;
-
-    virtual ~LoudnessEnhancerEffect();
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/LoudnessEnhancerEffect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_LOUDNESSENHANCEREFFECT_H
diff --git a/audio/effect/2.0/default/NoiseSuppressionEffect.cpp b/audio/effect/2.0/default/NoiseSuppressionEffect.cpp
index 7c4e06d..089e811 100644
--- a/audio/effect/2.0/default/NoiseSuppressionEffect.cpp
+++ b/audio/effect/2.0/default/NoiseSuppressionEffect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -15,220 +15,9 @@
  */
 
 #define LOG_TAG "NS_Effect_HAL"
-#include <android/log.h>
 
 #include "NoiseSuppressionEffect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-NoiseSuppressionEffect::NoiseSuppressionEffect(effect_handle_t handle)
-        : mEffect(new Effect(handle)) {
-}
-
-NoiseSuppressionEffect::~NoiseSuppressionEffect() {}
-
-void NoiseSuppressionEffect::propertiesFromHal(
-        const t_ns_settings& halProperties,
-        INoiseSuppressionEffect::AllProperties* properties) {
-    properties->level = Level(halProperties.level);
-    properties->type = Type(halProperties.type);
-}
-
-void NoiseSuppressionEffect::propertiesToHal(
-        const INoiseSuppressionEffect::AllProperties& properties,
-        t_ns_settings* halProperties) {
-    halProperties->level = static_cast<uint32_t>(properties.level);
-    halProperties->type = static_cast<uint32_t>(properties.type);
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> NoiseSuppressionEffect::init() {
-    return mEffect->init();
-}
-
-Return<Result> NoiseSuppressionEffect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> NoiseSuppressionEffect::reset() {
-    return mEffect->reset();
-}
-
-Return<Result> NoiseSuppressionEffect::enable() {
-    return mEffect->enable();
-}
-
-Return<Result> NoiseSuppressionEffect::disable() {
-    return mEffect->disable();
-}
-
-Return<Result> NoiseSuppressionEffect::setDevice(AudioDevice device) {
-    return mEffect->setDevice(device);
-}
-
-Return<void> NoiseSuppressionEffect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
-    return mEffect->setAndGetVolume(volumes, _hidl_cb);
-}
-
-Return<Result> NoiseSuppressionEffect::volumeChangeNotification(
-        const hidl_vec<uint32_t>& volumes) {
-    return mEffect->volumeChangeNotification(volumes);
-}
-
-Return<Result> NoiseSuppressionEffect::setAudioMode(AudioMode mode) {
-    return mEffect->setAudioMode(mode);
-}
-
-Return<Result> NoiseSuppressionEffect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> NoiseSuppressionEffect::setInputDevice(AudioDevice device) {
-    return mEffect->setInputDevice(device);
-}
-
-Return<void> NoiseSuppressionEffect::getConfig(getConfig_cb _hidl_cb) {
-    return mEffect->getConfig(_hidl_cb);
-}
-
-Return<void> NoiseSuppressionEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    return mEffect->getConfigReverse(_hidl_cb);
-}
-
-Return<void> NoiseSuppressionEffect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
-    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
-}
-
-Return<void> NoiseSuppressionEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    return mEffect->getAuxChannelsConfig(_hidl_cb);
-}
-
-Return<Result> NoiseSuppressionEffect::setAuxChannelsConfig(
-        const EffectAuxChannelsConfig& config) {
-    return mEffect->setAuxChannelsConfig(config);
-}
-
-Return<Result> NoiseSuppressionEffect::setAudioSource(AudioSource source) {
-    return mEffect->setAudioSource(source);
-}
-
-Return<Result> NoiseSuppressionEffect::offload(const EffectOffloadParameter& param) {
-    return mEffect->offload(param);
-}
-
-Return<void> NoiseSuppressionEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
-    return mEffect->getDescriptor(_hidl_cb);
-}
-
-Return<void> NoiseSuppressionEffect::prepareForProcessing(
-        prepareForProcessing_cb _hidl_cb) {
-    return mEffect->prepareForProcessing(_hidl_cb);
-}
-
-Return<Result> NoiseSuppressionEffect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    return mEffect->setProcessBuffers(inBuffer, outBuffer);
-}
-
-Return<void> NoiseSuppressionEffect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb) {
-    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
-}
-
-Return<Result> NoiseSuppressionEffect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
-    return mEffect->setParameter(parameter, value);
-}
-
-Return<void> NoiseSuppressionEffect::getParameter(
-        const hidl_vec<uint8_t>& parameter,
-        uint32_t valueMaxSize,
-        getParameter_cb _hidl_cb) {
-    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
-}
-
-Return<void> NoiseSuppressionEffect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb) {
-    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
-}
-
-Return<void> NoiseSuppressionEffect::getCurrentConfigForFeature(
-        uint32_t featureId,
-        uint32_t configSize,
-        getCurrentConfigForFeature_cb _hidl_cb) {
-    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
-}
-
-Return<Result> NoiseSuppressionEffect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
-    return mEffect->setCurrentConfigForFeature(featureId, configData);
-}
-
-Return<Result> NoiseSuppressionEffect::close() {
-    return mEffect->close();
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect follow.
-Return<Result> NoiseSuppressionEffect::setSuppressionLevel(INoiseSuppressionEffect::Level level)  {
-    return mEffect->setParam(NS_PARAM_LEVEL, static_cast<int32_t>(level));
-}
-
-Return<void> NoiseSuppressionEffect::getSuppressionLevel(getSuppressionLevel_cb _hidl_cb)  {
-    int32_t halLevel = 0;
-    Result retval = mEffect->getParam(NS_PARAM_LEVEL, halLevel);
-    _hidl_cb(retval, Level(halLevel));
-    return Void();
-}
-
-Return<Result> NoiseSuppressionEffect::setSuppressionType(INoiseSuppressionEffect::Type type)  {
-    return mEffect->setParam(NS_PARAM_TYPE, static_cast<int32_t>(type));
-}
-
-Return<void> NoiseSuppressionEffect::getSuppressionType(getSuppressionType_cb _hidl_cb)  {
-    int32_t halType = 0;
-    Result retval = mEffect->getParam(NS_PARAM_TYPE, halType);
-    _hidl_cb(retval, Type(halType));
-    return Void();
-}
-
-Return<Result> NoiseSuppressionEffect::setAllProperties(
-        const INoiseSuppressionEffect::AllProperties& properties)  {
-    t_ns_settings halProperties;
-    propertiesToHal(properties, &halProperties);
-    return mEffect->setParam(NS_PARAM_PROPERTIES, halProperties);
-}
-
-Return<void> NoiseSuppressionEffect::getAllProperties(getAllProperties_cb _hidl_cb)  {
-    t_ns_settings halProperties;
-    Result retval = mEffect->getParam(NS_PARAM_PROPERTIES, halProperties);
-    AllProperties properties;
-    propertiesFromHal(halProperties, &properties);
-    _hidl_cb(retval, properties);
-    return Void();
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/NoiseSuppressionEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/NoiseSuppressionEffect.h b/audio/effect/2.0/default/NoiseSuppressionEffect.h
index 5491201..0eee4b5 100644
--- a/audio/effect/2.0/default/NoiseSuppressionEffect.h
+++ b/audio/effect/2.0/default/NoiseSuppressionEffect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -17,125 +17,12 @@
 #ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_NOISESUPPRESSIONEFFECT_H
 #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_NOISESUPPRESSIONEFFECT_H
 
-#include <system/audio_effects/effect_ns.h>
-
 #include <android/hardware/audio/effect/2.0/INoiseSuppressionEffect.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
 
 #include "Effect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::common::V2_0::AudioDevice;
-using ::android::hardware::audio::common::V2_0::AudioMode;
-using ::android::hardware::audio::common::V2_0::AudioSource;
-using ::android::hardware::audio::effect::V2_0::AudioBuffer;
-using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
-using ::android::hardware::audio::effect::V2_0::EffectConfig;
-using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
-using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
-using ::android::hardware::audio::effect::V2_0::IEffect;
-using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
-using ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect;
-using ::android::hardware::audio::effect::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 NoiseSuppressionEffect : public INoiseSuppressionEffect {
-    explicit NoiseSuppressionEffect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Methods from ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect follow.
-    Return<Result> setSuppressionLevel(INoiseSuppressionEffect::Level level)  override;
-    Return<void> getSuppressionLevel(getSuppressionLevel_cb _hidl_cb)  override;
-    Return<Result> setSuppressionType(INoiseSuppressionEffect::Type type)  override;
-    Return<void> getSuppressionType(getSuppressionType_cb _hidl_cb)  override;
-    Return<Result> setAllProperties(
-            const INoiseSuppressionEffect::AllProperties& properties)  override;
-    Return<void> getAllProperties(getAllProperties_cb _hidl_cb)  override;
-
-  private:
-    sp<Effect> mEffect;
-
-    virtual ~NoiseSuppressionEffect();
-
-    void propertiesFromHal(
-            const t_ns_settings& halProperties,
-            INoiseSuppressionEffect::AllProperties* properties);
-    void propertiesToHal(
-            const INoiseSuppressionEffect::AllProperties& properties,
-            t_ns_settings* halProperties);
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/NoiseSuppressionEffect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_NOISESUPPRESSIONEFFECT_H
diff --git a/audio/effect/2.0/default/PresetReverbEffect.cpp b/audio/effect/2.0/default/PresetReverbEffect.cpp
index 5f17791..0648f6a 100644
--- a/audio/effect/2.0/default/PresetReverbEffect.cpp
+++ b/audio/effect/2.0/default/PresetReverbEffect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -15,180 +15,9 @@
  */
 
 #define LOG_TAG "PresetReverb_HAL"
-#include <system/audio_effects/effect_presetreverb.h>
-#include <android/log.h>
 
 #include "PresetReverbEffect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-PresetReverbEffect::PresetReverbEffect(effect_handle_t handle)
-        : mEffect(new Effect(handle)) {
-}
-
-PresetReverbEffect::~PresetReverbEffect() {}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> PresetReverbEffect::init() {
-    return mEffect->init();
-}
-
-Return<Result> PresetReverbEffect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> PresetReverbEffect::reset() {
-    return mEffect->reset();
-}
-
-Return<Result> PresetReverbEffect::enable() {
-    return mEffect->enable();
-}
-
-Return<Result> PresetReverbEffect::disable() {
-    return mEffect->disable();
-}
-
-Return<Result> PresetReverbEffect::setDevice(AudioDevice device) {
-    return mEffect->setDevice(device);
-}
-
-Return<void> PresetReverbEffect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
-    return mEffect->setAndGetVolume(volumes, _hidl_cb);
-}
-
-Return<Result> PresetReverbEffect::volumeChangeNotification(
-        const hidl_vec<uint32_t>& volumes) {
-    return mEffect->volumeChangeNotification(volumes);
-}
-
-Return<Result> PresetReverbEffect::setAudioMode(AudioMode mode) {
-    return mEffect->setAudioMode(mode);
-}
-
-Return<Result> PresetReverbEffect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> PresetReverbEffect::setInputDevice(AudioDevice device) {
-    return mEffect->setInputDevice(device);
-}
-
-Return<void> PresetReverbEffect::getConfig(getConfig_cb _hidl_cb) {
-    return mEffect->getConfig(_hidl_cb);
-}
-
-Return<void> PresetReverbEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    return mEffect->getConfigReverse(_hidl_cb);
-}
-
-Return<void> PresetReverbEffect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
-    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
-}
-
-Return<void> PresetReverbEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    return mEffect->getAuxChannelsConfig(_hidl_cb);
-}
-
-Return<Result> PresetReverbEffect::setAuxChannelsConfig(
-        const EffectAuxChannelsConfig& config) {
-    return mEffect->setAuxChannelsConfig(config);
-}
-
-Return<Result> PresetReverbEffect::setAudioSource(AudioSource source) {
-    return mEffect->setAudioSource(source);
-}
-
-Return<Result> PresetReverbEffect::offload(const EffectOffloadParameter& param) {
-    return mEffect->offload(param);
-}
-
-Return<void> PresetReverbEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
-    return mEffect->getDescriptor(_hidl_cb);
-}
-
-Return<void> PresetReverbEffect::prepareForProcessing(
-        prepareForProcessing_cb _hidl_cb) {
-    return mEffect->prepareForProcessing(_hidl_cb);
-}
-
-Return<Result> PresetReverbEffect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    return mEffect->setProcessBuffers(inBuffer, outBuffer);
-}
-
-Return<void> PresetReverbEffect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb) {
-    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
-}
-
-Return<Result> PresetReverbEffect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
-    return mEffect->setParameter(parameter, value);
-}
-
-Return<void> PresetReverbEffect::getParameter(
-        const hidl_vec<uint8_t>& parameter,
-        uint32_t valueMaxSize,
-        getParameter_cb _hidl_cb) {
-    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
-}
-
-Return<void> PresetReverbEffect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb) {
-    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
-}
-
-Return<void> PresetReverbEffect::getCurrentConfigForFeature(
-        uint32_t featureId,
-        uint32_t configSize,
-        getCurrentConfigForFeature_cb _hidl_cb) {
-    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
-}
-
-Return<Result> PresetReverbEffect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
-    return mEffect->setCurrentConfigForFeature(featureId, configData);
-}
-
-Return<Result> PresetReverbEffect::close() {
-    return mEffect->close();
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IPresetReverbEffect follow.
-Return<Result> PresetReverbEffect::setPreset(IPresetReverbEffect::Preset preset)  {
-    return mEffect->setParam(REVERB_PARAM_PRESET, static_cast<t_reverb_presets>(preset));
-}
-
-Return<void> PresetReverbEffect::getPreset(getPreset_cb _hidl_cb)  {
-    t_reverb_presets halPreset = REVERB_PRESET_NONE;
-    Result retval = mEffect->getParam(REVERB_PARAM_PRESET, halPreset);
-    _hidl_cb(retval, Preset(halPreset));
-    return Void();
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/PresetReverbEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/PresetReverbEffect.h b/audio/effect/2.0/default/PresetReverbEffect.h
index 4eb074a..1ea1626 100644
--- a/audio/effect/2.0/default/PresetReverbEffect.h
+++ b/audio/effect/2.0/default/PresetReverbEffect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -18,110 +18,11 @@
 #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_PRESETREVERBEFFECT_H
 
 #include <android/hardware/audio/effect/2.0/IPresetReverbEffect.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
 
 #include "Effect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::common::V2_0::AudioDevice;
-using ::android::hardware::audio::common::V2_0::AudioMode;
-using ::android::hardware::audio::common::V2_0::AudioSource;
-using ::android::hardware::audio::effect::V2_0::AudioBuffer;
-using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
-using ::android::hardware::audio::effect::V2_0::EffectConfig;
-using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
-using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
-using ::android::hardware::audio::effect::V2_0::IEffect;
-using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
-using ::android::hardware::audio::effect::V2_0::IPresetReverbEffect;
-using ::android::hardware::audio::effect::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 PresetReverbEffect : public IPresetReverbEffect {
-    explicit PresetReverbEffect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IPresetReverbEffect follow.
-    Return<Result> setPreset(IPresetReverbEffect::Preset preset)  override;
-    Return<void> getPreset(getPreset_cb _hidl_cb)  override;
-
-  private:
-    sp<Effect> mEffect;
-
-    virtual ~PresetReverbEffect();
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/PresetReverbEffect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_PRESETREVERBEFFECT_H
diff --git a/audio/effect/2.0/default/VirtualizerEffect.cpp b/audio/effect/2.0/default/VirtualizerEffect.cpp
index c1fe52f..63d3eb9 100644
--- a/audio/effect/2.0/default/VirtualizerEffect.cpp
+++ b/audio/effect/2.0/default/VirtualizerEffect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -14,235 +14,10 @@
  * limitations under the License.
  */
 
-#include <memory.h>
-
 #define LOG_TAG "Virtualizer_HAL"
-#include <system/audio_effects/effect_virtualizer.h>
-#include <android/log.h>
 
 #include "VirtualizerEffect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-VirtualizerEffect::VirtualizerEffect(effect_handle_t handle)
-        : mEffect(new Effect(handle)) {
-}
-
-VirtualizerEffect::~VirtualizerEffect() {}
-
-void VirtualizerEffect::speakerAnglesFromHal(
-        const int32_t* halAngles, uint32_t channelCount, hidl_vec<SpeakerAngle>& speakerAngles) {
-    speakerAngles.resize(channelCount);
-    for (uint32_t i = 0; i < channelCount; ++i) {
-        speakerAngles[i].mask = AudioChannelMask(*halAngles++);
-        speakerAngles[i].azimuth = *halAngles++;
-        speakerAngles[i].elevation = *halAngles++;
-    }
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> VirtualizerEffect::init() {
-    return mEffect->init();
-}
-
-Return<Result> VirtualizerEffect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> VirtualizerEffect::reset() {
-    return mEffect->reset();
-}
-
-Return<Result> VirtualizerEffect::enable() {
-    return mEffect->enable();
-}
-
-Return<Result> VirtualizerEffect::disable() {
-    return mEffect->disable();
-}
-
-Return<Result> VirtualizerEffect::setDevice(AudioDevice device) {
-    return mEffect->setDevice(device);
-}
-
-Return<void> VirtualizerEffect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
-    return mEffect->setAndGetVolume(volumes, _hidl_cb);
-}
-
-Return<Result> VirtualizerEffect::volumeChangeNotification(
-        const hidl_vec<uint32_t>& volumes) {
-    return mEffect->volumeChangeNotification(volumes);
-}
-
-Return<Result> VirtualizerEffect::setAudioMode(AudioMode mode) {
-    return mEffect->setAudioMode(mode);
-}
-
-Return<Result> VirtualizerEffect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> VirtualizerEffect::setInputDevice(AudioDevice device) {
-    return mEffect->setInputDevice(device);
-}
-
-Return<void> VirtualizerEffect::getConfig(getConfig_cb _hidl_cb) {
-    return mEffect->getConfig(_hidl_cb);
-}
-
-Return<void> VirtualizerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    return mEffect->getConfigReverse(_hidl_cb);
-}
-
-Return<void> VirtualizerEffect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
-    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
-}
-
-Return<void> VirtualizerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    return mEffect->getAuxChannelsConfig(_hidl_cb);
-}
-
-Return<Result> VirtualizerEffect::setAuxChannelsConfig(
-        const EffectAuxChannelsConfig& config) {
-    return mEffect->setAuxChannelsConfig(config);
-}
-
-Return<Result> VirtualizerEffect::setAudioSource(AudioSource source) {
-    return mEffect->setAudioSource(source);
-}
-
-Return<Result> VirtualizerEffect::offload(const EffectOffloadParameter& param) {
-    return mEffect->offload(param);
-}
-
-Return<void> VirtualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
-    return mEffect->getDescriptor(_hidl_cb);
-}
-
-Return<void> VirtualizerEffect::prepareForProcessing(
-        prepareForProcessing_cb _hidl_cb) {
-    return mEffect->prepareForProcessing(_hidl_cb);
-}
-
-Return<Result> VirtualizerEffect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    return mEffect->setProcessBuffers(inBuffer, outBuffer);
-}
-
-Return<void> VirtualizerEffect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb) {
-    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
-}
-
-Return<Result> VirtualizerEffect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
-    return mEffect->setParameter(parameter, value);
-}
-
-Return<void> VirtualizerEffect::getParameter(
-        const hidl_vec<uint8_t>& parameter,
-        uint32_t valueMaxSize,
-        getParameter_cb _hidl_cb) {
-    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
-}
-
-Return<void> VirtualizerEffect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb) {
-    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
-}
-
-Return<void> VirtualizerEffect::getCurrentConfigForFeature(
-        uint32_t featureId,
-        uint32_t configSize,
-        getCurrentConfigForFeature_cb _hidl_cb) {
-    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
-}
-
-Return<Result> VirtualizerEffect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
-    return mEffect->setCurrentConfigForFeature(featureId, configData);
-}
-
-Return<Result> VirtualizerEffect::close() {
-    return mEffect->close();
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IVirtualizerEffect follow.
-Return<bool> VirtualizerEffect::isStrengthSupported()  {
-    bool halSupported = false;
-    mEffect->getParam(VIRTUALIZER_PARAM_STRENGTH_SUPPORTED, halSupported);
-    return halSupported;
-}
-
-Return<Result> VirtualizerEffect::setStrength(uint16_t strength)  {
-    return mEffect->setParam(VIRTUALIZER_PARAM_STRENGTH, strength);
-}
-
-Return<void> VirtualizerEffect::getStrength(getStrength_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(VIRTUALIZER_PARAM_STRENGTH, _hidl_cb);
-}
-
-Return<void> VirtualizerEffect::getVirtualSpeakerAngles(
-        AudioChannelMask mask, AudioDevice device, getVirtualSpeakerAngles_cb _hidl_cb)  {
-    uint32_t channelCount = audio_channel_count_from_out_mask(
-            static_cast<audio_channel_mask_t>(mask));
-    size_t halSpeakerAnglesSize = sizeof(int32_t) * 3 * channelCount;
-    uint32_t halParam[3] = {
-        VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES,
-        static_cast<audio_channel_mask_t>(mask),
-        static_cast<audio_devices_t>(device)
-    };
-    hidl_vec<SpeakerAngle> speakerAngles;
-    Result retval = mEffect->getParameterImpl(
-            sizeof(halParam), halParam,
-            halSpeakerAnglesSize,
-            [&] (uint32_t valueSize, const void* valueData) {
-                if (valueSize > halSpeakerAnglesSize) {
-                    valueSize = halSpeakerAnglesSize;
-                } else if (valueSize < halSpeakerAnglesSize) {
-                    channelCount = valueSize / (sizeof(int32_t) * 3);
-                }
-                speakerAnglesFromHal(
-                        reinterpret_cast<const int32_t*>(valueData), channelCount, speakerAngles);
-            });
-    _hidl_cb(retval, speakerAngles);
-    return Void();
-}
-
-Return<Result> VirtualizerEffect::forceVirtualizationMode(AudioDevice device)  {
-    return mEffect->setParam(
-            VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE, static_cast<audio_devices_t>(device));
-}
-
-Return<void> VirtualizerEffect::getVirtualizationMode(getVirtualizationMode_cb _hidl_cb)  {
-    uint32_t halMode = 0;
-    Result retval = mEffect->getParam(VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE, halMode);
-    _hidl_cb(retval, AudioDevice(halMode));
-    return Void();
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/VirtualizerEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/VirtualizerEffect.h b/audio/effect/2.0/default/VirtualizerEffect.h
index 536775f..04f93c4 100644
--- a/audio/effect/2.0/default/VirtualizerEffect.h
+++ b/audio/effect/2.0/default/VirtualizerEffect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -18,121 +18,11 @@
 #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_VIRTUALIZEREFFECT_H
 
 #include <android/hardware/audio/effect/2.0/IVirtualizerEffect.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
 
 #include "Effect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-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::AudioMode;
-using ::android::hardware::audio::common::V2_0::AudioSource;
-using ::android::hardware::audio::effect::V2_0::AudioBuffer;
-using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
-using ::android::hardware::audio::effect::V2_0::EffectConfig;
-using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
-using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
-using ::android::hardware::audio::effect::V2_0::IEffect;
-using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
-using ::android::hardware::audio::effect::V2_0::IVirtualizerEffect;
-using ::android::hardware::audio::effect::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 VirtualizerEffect : public IVirtualizerEffect {
-    explicit VirtualizerEffect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IVirtualizerEffect follow.
-    Return<bool> isStrengthSupported()  override;
-    Return<Result> setStrength(uint16_t strength)  override;
-    Return<void> getStrength(getStrength_cb _hidl_cb)  override;
-    Return<void> getVirtualSpeakerAngles(
-            AudioChannelMask mask,
-            AudioDevice device,
-            getVirtualSpeakerAngles_cb _hidl_cb)  override;
-    Return<Result> forceVirtualizationMode(AudioDevice device)  override;
-    Return<void> getVirtualizationMode(getVirtualizationMode_cb _hidl_cb)  override;
-
-  private:
-    sp<Effect> mEffect;
-
-    virtual ~VirtualizerEffect();
-
-    void speakerAnglesFromHal(
-            const int32_t* halAngles, uint32_t channelCount, hidl_vec<SpeakerAngle>& speakerAngles);
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/VirtualizerEffect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_VIRTUALIZEREFFECT_H
diff --git a/audio/effect/2.0/default/VisualizerEffect.cpp b/audio/effect/2.0/default/VisualizerEffect.cpp
index 2cd3240..5235524 100644
--- a/audio/effect/2.0/default/VisualizerEffect.cpp
+++ b/audio/effect/2.0/default/VisualizerEffect.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -15,254 +15,9 @@
  */
 
 #define LOG_TAG "Visualizer_HAL"
-#include <system/audio_effects/effect_visualizer.h>
-#include <android/log.h>
 
 #include "VisualizerEffect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-VisualizerEffect::VisualizerEffect(effect_handle_t handle)
-        : mEffect(new Effect(handle)), mCaptureSize(0), mMeasurementMode(MeasurementMode::NONE) {
-}
-
-VisualizerEffect::~VisualizerEffect() {}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-Return<Result> VisualizerEffect::init() {
-    return mEffect->init();
-}
-
-Return<Result> VisualizerEffect::setConfig(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> VisualizerEffect::reset() {
-    return mEffect->reset();
-}
-
-Return<Result> VisualizerEffect::enable() {
-    return mEffect->enable();
-}
-
-Return<Result> VisualizerEffect::disable() {
-    return mEffect->disable();
-}
-
-Return<Result> VisualizerEffect::setDevice(AudioDevice device) {
-    return mEffect->setDevice(device);
-}
-
-Return<void> VisualizerEffect::setAndGetVolume(
-        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
-    return mEffect->setAndGetVolume(volumes, _hidl_cb);
-}
-
-Return<Result> VisualizerEffect::volumeChangeNotification(
-        const hidl_vec<uint32_t>& volumes) {
-    return mEffect->volumeChangeNotification(volumes);
-}
-
-Return<Result> VisualizerEffect::setAudioMode(AudioMode mode) {
-    return mEffect->setAudioMode(mode);
-}
-
-Return<Result> VisualizerEffect::setConfigReverse(
-        const EffectConfig& config,
-        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
-    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
-}
-
-Return<Result> VisualizerEffect::setInputDevice(AudioDevice device) {
-    return mEffect->setInputDevice(device);
-}
-
-Return<void> VisualizerEffect::getConfig(getConfig_cb _hidl_cb) {
-    return mEffect->getConfig(_hidl_cb);
-}
-
-Return<void> VisualizerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    return mEffect->getConfigReverse(_hidl_cb);
-}
-
-Return<void> VisualizerEffect::getSupportedAuxChannelsConfigs(
-        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
-    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
-}
-
-Return<void> VisualizerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    return mEffect->getAuxChannelsConfig(_hidl_cb);
-}
-
-Return<Result> VisualizerEffect::setAuxChannelsConfig(
-        const EffectAuxChannelsConfig& config) {
-    return mEffect->setAuxChannelsConfig(config);
-}
-
-Return<Result> VisualizerEffect::setAudioSource(AudioSource source) {
-    return mEffect->setAudioSource(source);
-}
-
-Return<Result> VisualizerEffect::offload(const EffectOffloadParameter& param) {
-    return mEffect->offload(param);
-}
-
-Return<void> VisualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
-    return mEffect->getDescriptor(_hidl_cb);
-}
-
-Return<void> VisualizerEffect::prepareForProcessing(
-        prepareForProcessing_cb _hidl_cb) {
-    return mEffect->prepareForProcessing(_hidl_cb);
-}
-
-Return<Result> VisualizerEffect::setProcessBuffers(
-        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
-    return mEffect->setProcessBuffers(inBuffer, outBuffer);
-}
-
-Return<void> VisualizerEffect::command(
-        uint32_t commandId,
-        const hidl_vec<uint8_t>& data,
-        uint32_t resultMaxSize,
-        command_cb _hidl_cb) {
-    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
-}
-
-Return<Result> VisualizerEffect::setParameter(
-        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
-    return mEffect->setParameter(parameter, value);
-}
-
-Return<void> VisualizerEffect::getParameter(
-        const hidl_vec<uint8_t>& parameter,
-        uint32_t valueMaxSize,
-        getParameter_cb _hidl_cb) {
-    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
-}
-
-Return<void> VisualizerEffect::getSupportedConfigsForFeature(
-        uint32_t featureId,
-        uint32_t maxConfigs,
-        uint32_t configSize,
-        getSupportedConfigsForFeature_cb _hidl_cb) {
-    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
-}
-
-Return<void> VisualizerEffect::getCurrentConfigForFeature(
-        uint32_t featureId,
-        uint32_t configSize,
-        getCurrentConfigForFeature_cb _hidl_cb) {
-    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
-}
-
-Return<Result> VisualizerEffect::setCurrentConfigForFeature(
-        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
-    return mEffect->setCurrentConfigForFeature(featureId, configData);
-}
-
-Return<Result> VisualizerEffect::close() {
-    return mEffect->close();
-}
-
-// Methods from ::android::hardware::audio::effect::V2_0::IVisualizerEffect follow.
-Return<Result> VisualizerEffect::setCaptureSize(uint16_t captureSize)  {
-    Result retval = mEffect->setParam(VISUALIZER_PARAM_CAPTURE_SIZE, captureSize);
-    if (retval == Result::OK) {
-        mCaptureSize = captureSize;
-    }
-    return retval;
-}
-
-Return<void> VisualizerEffect::getCaptureSize(getCaptureSize_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(VISUALIZER_PARAM_CAPTURE_SIZE, _hidl_cb);
-}
-
-Return<Result> VisualizerEffect::setScalingMode(IVisualizerEffect::ScalingMode scalingMode)  {
-    return mEffect->setParam(VISUALIZER_PARAM_SCALING_MODE, static_cast<int32_t>(scalingMode));
-}
-
-Return<void> VisualizerEffect::getScalingMode(getScalingMode_cb _hidl_cb)  {
-    int32_t halMode;
-    Result retval = mEffect->getParam(VISUALIZER_PARAM_SCALING_MODE, halMode);
-    _hidl_cb(retval, ScalingMode(halMode));
-    return Void();
-}
-
-Return<Result> VisualizerEffect::setLatency(uint32_t latencyMs)  {
-    return mEffect->setParam(VISUALIZER_PARAM_LATENCY, latencyMs);
-}
-
-Return<void> VisualizerEffect::getLatency(getLatency_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(VISUALIZER_PARAM_LATENCY, _hidl_cb);
-}
-
-Return<Result> VisualizerEffect::setMeasurementMode(
-        IVisualizerEffect::MeasurementMode measurementMode)  {
-    Result retval = mEffect->setParam(
-            VISUALIZER_PARAM_MEASUREMENT_MODE, static_cast<int32_t>(measurementMode));
-    if (retval == Result::OK) {
-        mMeasurementMode = measurementMode;
-    }
-    return retval;
-}
-
-Return<void> VisualizerEffect::getMeasurementMode(getMeasurementMode_cb _hidl_cb)  {
-    int32_t halMode;
-    Result retval = mEffect->getParam(VISUALIZER_PARAM_MEASUREMENT_MODE, halMode);
-    _hidl_cb(retval, MeasurementMode(halMode));
-    return Void();
-}
-
-Return<void> VisualizerEffect::capture(capture_cb _hidl_cb)  {
-    if (mCaptureSize == 0) {
-        _hidl_cb(Result::NOT_INITIALIZED, hidl_vec<uint8_t>());
-        return Void();
-    }
-    uint32_t halCaptureSize = mCaptureSize;
-    uint8_t halCapture[mCaptureSize];
-    Result retval = mEffect->sendCommandReturningData(
-            VISUALIZER_CMD_CAPTURE, "VISUALIZER_CAPTURE", &halCaptureSize, halCapture);
-    hidl_vec<uint8_t> capture;
-    if (retval == Result::OK) {
-        capture.setToExternal(&halCapture[0], halCaptureSize);
-    }
-    _hidl_cb(retval, capture);
-    return Void();
-}
-
-Return<void> VisualizerEffect::measure(measure_cb _hidl_cb)  {
-    if (mMeasurementMode == MeasurementMode::NONE) {
-        _hidl_cb(Result::NOT_INITIALIZED, Measurement());
-        return Void();
-    }
-    int32_t halMeasurement[MEASUREMENT_COUNT];
-    uint32_t halMeasurementSize = sizeof(halMeasurement);
-    Result retval = mEffect->sendCommandReturningData(
-            VISUALIZER_CMD_MEASURE, "VISUALIZER_MEASURE", &halMeasurementSize, halMeasurement);
-    Measurement measurement = { .mode = MeasurementMode::PEAK_RMS };
-    measurement.value.peakAndRms.peakMb = 0;
-    measurement.value.peakAndRms.rmsMb = 0;
-    if (retval == Result::OK) {
-        measurement.value.peakAndRms.peakMb = halMeasurement[MEASUREMENT_IDX_PEAK];
-        measurement.value.peakAndRms.rmsMb = halMeasurement[MEASUREMENT_IDX_RMS];
-    }
-    _hidl_cb(retval, measurement);
-    return Void();
-}
-
-} // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/VisualizerEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/2.0/default/VisualizerEffect.h b/audio/effect/2.0/default/VisualizerEffect.h
index fd40ca8..940f15d 100644
--- a/audio/effect/2.0/default/VisualizerEffect.h
+++ b/audio/effect/2.0/default/VisualizerEffect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -18,120 +18,11 @@
 #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_VISUALIZEREFFECT_H
 
 #include <android/hardware/audio/effect/2.0/IVisualizerEffect.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
 
 #include "Effect.h"
 
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::audio::common::V2_0::AudioDevice;
-using ::android::hardware::audio::common::V2_0::AudioMode;
-using ::android::hardware::audio::common::V2_0::AudioSource;
-using ::android::hardware::audio::effect::V2_0::AudioBuffer;
-using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
-using ::android::hardware::audio::effect::V2_0::EffectConfig;
-using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
-using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
-using ::android::hardware::audio::effect::V2_0::IEffect;
-using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
-using ::android::hardware::audio::effect::V2_0::IVisualizerEffect;
-using ::android::hardware::audio::effect::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 VisualizerEffect : public IVisualizerEffect {
-    explicit VisualizerEffect(effect_handle_t handle);
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
-    Return<Result> init()  override;
-    Return<Result> setConfig(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> reset()  override;
-    Return<Result> enable()  override;
-    Return<Result> disable()  override;
-    Return<Result> setDevice(AudioDevice device)  override;
-    Return<void> setAndGetVolume(
-            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
-    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
-    Return<Result> setAudioMode(AudioMode mode)  override;
-    Return<Result> setConfigReverse(
-            const EffectConfig& config,
-            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
-            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
-    Return<Result> setInputDevice(AudioDevice device)  override;
-    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
-    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
-    Return<void> getSupportedAuxChannelsConfigs(
-            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
-    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
-    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
-    Return<Result> setAudioSource(AudioSource source)  override;
-    Return<Result> offload(const EffectOffloadParameter& param)  override;
-    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
-    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
-    Return<Result> setProcessBuffers(
-            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
-    Return<void> command(
-            uint32_t commandId,
-            const hidl_vec<uint8_t>& data,
-            uint32_t resultMaxSize,
-            command_cb _hidl_cb)  override;
-    Return<Result> setParameter(
-            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
-    Return<void> getParameter(
-            const hidl_vec<uint8_t>& parameter,
-            uint32_t valueMaxSize,
-            getParameter_cb _hidl_cb)  override;
-    Return<void> getSupportedConfigsForFeature(
-            uint32_t featureId,
-            uint32_t maxConfigs,
-            uint32_t configSize,
-            getSupportedConfigsForFeature_cb _hidl_cb)  override;
-    Return<void> getCurrentConfigForFeature(
-            uint32_t featureId,
-            uint32_t configSize,
-            getCurrentConfigForFeature_cb _hidl_cb)  override;
-    Return<Result> setCurrentConfigForFeature(
-            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
-    Return<Result> close()  override;
-
-    // Methods from ::android::hardware::audio::effect::V2_0::IVisualizerEffect follow.
-    Return<Result> setCaptureSize(uint16_t captureSize)  override;
-    Return<void> getCaptureSize(getCaptureSize_cb _hidl_cb)  override;
-    Return<Result> setScalingMode(IVisualizerEffect::ScalingMode scalingMode)  override;
-    Return<void> getScalingMode(getScalingMode_cb _hidl_cb)  override;
-    Return<Result> setLatency(uint32_t latencyMs)  override;
-    Return<void> getLatency(getLatency_cb _hidl_cb)  override;
-    Return<Result> setMeasurementMode(IVisualizerEffect::MeasurementMode measurementMode)  override;
-    Return<void> getMeasurementMode(getMeasurementMode_cb _hidl_cb)  override;
-    Return<void> capture(capture_cb _hidl_cb)  override;
-    Return<void> measure(measure_cb _hidl_cb)  override;
-
-  private:
-    sp<Effect> mEffect;
-    uint16_t mCaptureSize;
-    MeasurementMode mMeasurementMode;
-
-    virtual ~VisualizerEffect();
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
+#define AUDIO_HAL_VERSION V2_0
+#include <effect/all-versions/default/VisualizerEffect.h>
+#undef AUDIO_HAL_VERSION
 
 #endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_VISUALIZEREFFECT_H
diff --git a/audio/2.0/default/OWNERS b/audio/effect/all-versions/OWNERS
similarity index 100%
rename from audio/2.0/default/OWNERS
rename to audio/effect/all-versions/OWNERS
diff --git a/audio/effect/all-versions/default/Android.bp b/audio/effect/all-versions/default/Android.bp
new file mode 100644
index 0000000..ed2a093
--- /dev/null
+++ b/audio/effect/all-versions/default/Android.bp
@@ -0,0 +1,31 @@
+cc_library_headers {
+    name: "android.hardware.audio.effect@all-versions-impl",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+
+    export_include_dirs: ["include"],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libeffects",
+        "libfmq",
+        "libhidlbase",
+        "libhidlmemory",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.audio.common-util",
+        "android.hidl.memory@1.0",
+    ],
+
+    header_libs: [
+        "libaudio_system_headers",
+        "libaudioclient_headers",
+        "libeffects_headers",
+        "libhardware_headers",
+        "libmedia_headers",
+        "android.hardware.audio.common.util@all-versions",
+    ],
+}
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.h
new file mode 100644
index 0000000..b63f2fb
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.h
@@ -0,0 +1,101 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IAcousticEchoCancelerEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct AcousticEchoCancelerEffect : public IAcousticEchoCancelerEffect {
+    explicit AcousticEchoCancelerEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Methods from
+    // ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IAcousticEchoCancelerEffect follow.
+    Return<Result> setEchoDelay(uint32_t echoDelayMs) override;
+    Return<void> getEchoDelay(getEchoDelay_cb _hidl_cb) override;
+
+   private:
+    sp<Effect> mEffect;
+
+    virtual ~AcousticEchoCancelerEffect();
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.impl.h
new file mode 100644
index 0000000..bee3607
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.impl.h
@@ -0,0 +1,179 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <android/log.h>
+#include <system/audio_effects/effect_aec.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+AcousticEchoCancelerEffect::AcousticEchoCancelerEffect(effect_handle_t handle)
+    : mEffect(new Effect(handle)) {}
+
+AcousticEchoCancelerEffect::~AcousticEchoCancelerEffect() {}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> AcousticEchoCancelerEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> AcousticEchoCancelerEffect::setConfig(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> AcousticEchoCancelerEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> AcousticEchoCancelerEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> AcousticEchoCancelerEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> AcousticEchoCancelerEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> AcousticEchoCancelerEffect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                                         setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> AcousticEchoCancelerEffect::volumeChangeNotification(
+    const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> AcousticEchoCancelerEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::getSupportedAuxChannelsConfigs(
+    uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setAuxChannelsConfig(
+    const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> AcousticEchoCancelerEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> AcousticEchoCancelerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                                             const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> AcousticEchoCancelerEffect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                                                 uint32_t resultMaxSize, command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                                        const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> AcousticEchoCancelerEffect::getParameter(const hidl_vec<uint8_t>& parameter,
+                                                      uint32_t valueMaxSize,
+                                                      getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::getSupportedConfigsForFeature(
+    uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+    getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::getCurrentConfigForFeature(
+    uint32_t featureId, uint32_t configSize, getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setCurrentConfigForFeature(
+    uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> AcousticEchoCancelerEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IAcousticEchoCancelerEffect
+// follow.
+Return<Result> AcousticEchoCancelerEffect::setEchoDelay(uint32_t echoDelayMs) {
+    return mEffect->setParam(AEC_PARAM_ECHO_DELAY, echoDelayMs);
+}
+
+Return<void> AcousticEchoCancelerEffect::getEchoDelay(getEchoDelay_cb _hidl_cb) {
+    return mEffect->getIntegerParam(AEC_PARAM_ECHO_DELAY, _hidl_cb);
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/AudioBufferManager.h b/audio/effect/all-versions/default/include/effect/all-versions/default/AudioBufferManager.h
new file mode 100644
index 0000000..34dea2d
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/AudioBufferManager.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 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 <common/all-versions/IncludeGuard.h>
+
+#include <mutex>
+
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <system/audio_effect.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/Singleton.h>
+
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::AudioBuffer;
+using ::android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+class AudioBufferWrapper : public RefBase {
+   public:
+    explicit AudioBufferWrapper(const AudioBuffer& buffer);
+    virtual ~AudioBufferWrapper();
+    bool init();
+    audio_buffer_t* getHalBuffer() { return &mHalBuffer; }
+
+   private:
+    AudioBufferWrapper(const AudioBufferWrapper&) = delete;
+    void operator=(AudioBufferWrapper) = delete;
+
+    AudioBuffer mHidlBuffer;
+    sp<IMemory> mHidlMemory;
+    audio_buffer_t mHalBuffer;
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::implementation::AudioBufferWrapper;
+
+namespace android {
+
+// This class needs to be in 'android' ns because Singleton macros require that.
+class AudioBufferManager : public Singleton<AudioBufferManager> {
+   public:
+    bool wrap(const AudioBuffer& buffer, sp<AudioBufferWrapper>* wrapper);
+
+   private:
+    friend class hardware::audio::effect::AUDIO_HAL_VERSION::implementation::AudioBufferWrapper;
+
+    // Called by AudioBufferWrapper.
+    void removeEntry(uint64_t id);
+
+    std::mutex mLock;
+    KeyedVector<uint64_t, wp<AudioBufferWrapper>> mBuffers;
+};
+
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/AudioBufferManager.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/AudioBufferManager.impl.h
new file mode 100644
index 0000000..71ccd2d
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/AudioBufferManager.impl.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 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 <common/all-versions/IncludeGuard.h>
+
+#include <atomic>
+
+#include <hidlmemory/mapping.h>
+
+namespace android {
+
+ANDROID_SINGLETON_STATIC_INSTANCE(AudioBufferManager);
+
+bool AudioBufferManager::wrap(const AudioBuffer& buffer, sp<AudioBufferWrapper>* wrapper) {
+    // Check if we have this buffer already
+    std::lock_guard<std::mutex> lock(mLock);
+    ssize_t idx = mBuffers.indexOfKey(buffer.id);
+    if (idx >= 0) {
+        *wrapper = mBuffers[idx].promote();
+        if (*wrapper != nullptr) {
+            (*wrapper)->getHalBuffer()->frameCount = buffer.frameCount;
+            return true;
+        }
+        mBuffers.removeItemsAt(idx);
+    }
+    // Need to create and init a new AudioBufferWrapper.
+    sp<AudioBufferWrapper> tempBuffer(new AudioBufferWrapper(buffer));
+    if (!tempBuffer->init()) return false;
+    *wrapper = tempBuffer;
+    mBuffers.add(buffer.id, *wrapper);
+    return true;
+}
+
+void AudioBufferManager::removeEntry(uint64_t id) {
+    std::lock_guard<std::mutex> lock(mLock);
+    ssize_t idx = mBuffers.indexOfKey(id);
+    if (idx >= 0) mBuffers.removeItemsAt(idx);
+}
+
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+AudioBufferWrapper::AudioBufferWrapper(const AudioBuffer& buffer)
+    : mHidlBuffer(buffer), mHalBuffer{0, {nullptr}} {}
+
+AudioBufferWrapper::~AudioBufferWrapper() {
+    AudioBufferManager::getInstance().removeEntry(mHidlBuffer.id);
+}
+
+bool AudioBufferWrapper::init() {
+    if (mHalBuffer.raw != nullptr) {
+        ALOGE("An attempt to init AudioBufferWrapper twice");
+        return false;
+    }
+    mHidlMemory = mapMemory(mHidlBuffer.data);
+    if (mHidlMemory == nullptr) {
+        ALOGE("Could not map HIDL memory to IMemory");
+        return false;
+    }
+    mHalBuffer.raw = static_cast<void*>(mHidlMemory->getPointer());
+    if (mHalBuffer.raw == nullptr) {
+        ALOGE("IMemory buffer pointer is null");
+        return false;
+    }
+    mHalBuffer.frameCount = mHidlBuffer.frameCount;
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.h
new file mode 100644
index 0000000..941f45d
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.h
@@ -0,0 +1,115 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <system/audio_effects/effect_agc.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IAutomaticGainControlEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct AutomaticGainControlEffect : public IAutomaticGainControlEffect {
+    explicit AutomaticGainControlEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Methods from
+    // ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IAutomaticGainControlEffect follow.
+    Return<Result> setTargetLevel(int16_t targetLevelMb) override;
+    Return<void> getTargetLevel(getTargetLevel_cb _hidl_cb) override;
+    Return<Result> setCompGain(int16_t compGainMb) override;
+    Return<void> getCompGain(getCompGain_cb _hidl_cb) override;
+    Return<Result> setLimiterEnabled(bool enabled) override;
+    Return<void> isLimiterEnabled(isLimiterEnabled_cb _hidl_cb) override;
+    Return<Result> setAllProperties(
+        const IAutomaticGainControlEffect::AllProperties& properties) override;
+    Return<void> getAllProperties(getAllProperties_cb _hidl_cb) override;
+
+   private:
+    sp<Effect> mEffect;
+
+    virtual ~AutomaticGainControlEffect();
+
+    void propertiesFromHal(const t_agc_settings& halProperties,
+                           IAutomaticGainControlEffect::AllProperties* properties);
+    void propertiesToHal(const IAutomaticGainControlEffect::AllProperties& properties,
+                         t_agc_settings* halProperties);
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.impl.h
new file mode 100644
index 0000000..af05d9b
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.impl.h
@@ -0,0 +1,224 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <android/log.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+AutomaticGainControlEffect::AutomaticGainControlEffect(effect_handle_t handle)
+    : mEffect(new Effect(handle)) {}
+
+AutomaticGainControlEffect::~AutomaticGainControlEffect() {}
+
+void AutomaticGainControlEffect::propertiesFromHal(
+    const t_agc_settings& halProperties, IAutomaticGainControlEffect::AllProperties* properties) {
+    properties->targetLevelMb = halProperties.targetLevel;
+    properties->compGainMb = halProperties.compGain;
+    properties->limiterEnabled = halProperties.limiterEnabled;
+}
+
+void AutomaticGainControlEffect::propertiesToHal(
+    const IAutomaticGainControlEffect::AllProperties& properties, t_agc_settings* halProperties) {
+    halProperties->targetLevel = properties.targetLevelMb;
+    halProperties->compGain = properties.compGainMb;
+    halProperties->limiterEnabled = properties.limiterEnabled;
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> AutomaticGainControlEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> AutomaticGainControlEffect::setConfig(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> AutomaticGainControlEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> AutomaticGainControlEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> AutomaticGainControlEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> AutomaticGainControlEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> AutomaticGainControlEffect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                                         setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::volumeChangeNotification(
+    const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> AutomaticGainControlEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> AutomaticGainControlEffect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> AutomaticGainControlEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> AutomaticGainControlEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::getSupportedAuxChannelsConfigs(
+    uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setAuxChannelsConfig(
+    const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> AutomaticGainControlEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> AutomaticGainControlEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> AutomaticGainControlEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                                             const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> AutomaticGainControlEffect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                                                 uint32_t resultMaxSize, command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                                        const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> AutomaticGainControlEffect::getParameter(const hidl_vec<uint8_t>& parameter,
+                                                      uint32_t valueMaxSize,
+                                                      getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::getSupportedConfigsForFeature(
+    uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+    getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::getCurrentConfigForFeature(
+    uint32_t featureId, uint32_t configSize, getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setCurrentConfigForFeature(
+    uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> AutomaticGainControlEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IAutomaticGainControlEffect
+// follow.
+Return<Result> AutomaticGainControlEffect::setTargetLevel(int16_t targetLevelMb) {
+    return mEffect->setParam(AGC_PARAM_TARGET_LEVEL, targetLevelMb);
+}
+
+Return<void> AutomaticGainControlEffect::getTargetLevel(getTargetLevel_cb _hidl_cb) {
+    return mEffect->getIntegerParam(AGC_PARAM_TARGET_LEVEL, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setCompGain(int16_t compGainMb) {
+    return mEffect->setParam(AGC_PARAM_COMP_GAIN, compGainMb);
+}
+
+Return<void> AutomaticGainControlEffect::getCompGain(getCompGain_cb _hidl_cb) {
+    return mEffect->getIntegerParam(AGC_PARAM_COMP_GAIN, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setLimiterEnabled(bool enabled) {
+    return mEffect->setParam(AGC_PARAM_LIMITER_ENA, enabled);
+}
+
+Return<void> AutomaticGainControlEffect::isLimiterEnabled(isLimiterEnabled_cb _hidl_cb) {
+    return mEffect->getIntegerParam(AGC_PARAM_LIMITER_ENA, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setAllProperties(
+    const IAutomaticGainControlEffect::AllProperties& properties) {
+    t_agc_settings halProperties;
+    propertiesToHal(properties, &halProperties);
+    return mEffect->setParam(AGC_PARAM_PROPERTIES, halProperties);
+}
+
+Return<void> AutomaticGainControlEffect::getAllProperties(getAllProperties_cb _hidl_cb) {
+    t_agc_settings halProperties;
+    Result retval = mEffect->getParam(AGC_PARAM_PROPERTIES, halProperties);
+    AllProperties properties;
+    propertiesFromHal(halProperties, &properties);
+    _hidl_cb(retval, properties);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.h
new file mode 100644
index 0000000..0092621
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.h
@@ -0,0 +1,101 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IBassBoostEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct BassBoostEffect : public IBassBoostEffect {
+    explicit BassBoostEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IBassBoostEffect follow.
+    Return<void> isStrengthSupported(isStrengthSupported_cb _hidl_cb) override;
+    Return<Result> setStrength(uint16_t strength) override;
+    Return<void> getStrength(getStrength_cb _hidl_cb) override;
+
+   private:
+    sp<Effect> mEffect;
+
+    virtual ~BassBoostEffect();
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.impl.h
new file mode 100644
index 0000000..1fc8d1b
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.impl.h
@@ -0,0 +1,178 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <android/log.h>
+#include <system/audio_effects/effect_bassboost.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+BassBoostEffect::BassBoostEffect(effect_handle_t handle) : mEffect(new Effect(handle)) {}
+
+BassBoostEffect::~BassBoostEffect() {}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> BassBoostEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> BassBoostEffect::setConfig(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> BassBoostEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> BassBoostEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> BassBoostEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> BassBoostEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> BassBoostEffect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                              setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> BassBoostEffect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> BassBoostEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> BassBoostEffect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> BassBoostEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> BassBoostEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> BassBoostEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> BassBoostEffect::getSupportedAuxChannelsConfigs(
+    uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> BassBoostEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> BassBoostEffect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> BassBoostEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> BassBoostEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> BassBoostEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> BassBoostEffect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> BassBoostEffect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                                  const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> BassBoostEffect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                                      uint32_t resultMaxSize, command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> BassBoostEffect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                             const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> BassBoostEffect::getParameter(const hidl_vec<uint8_t>& parameter,
+                                           uint32_t valueMaxSize, getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> BassBoostEffect::getSupportedConfigsForFeature(
+    uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+    getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> BassBoostEffect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                                         getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> BassBoostEffect::setCurrentConfigForFeature(uint32_t featureId,
+                                                           const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> BassBoostEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IBassBoostEffect follow.
+Return<void> BassBoostEffect::isStrengthSupported(isStrengthSupported_cb _hidl_cb) {
+    return mEffect->getIntegerParam(BASSBOOST_PARAM_STRENGTH_SUPPORTED, _hidl_cb);
+}
+
+Return<Result> BassBoostEffect::setStrength(uint16_t strength) {
+    return mEffect->setParam(BASSBOOST_PARAM_STRENGTH, strength);
+}
+
+Return<void> BassBoostEffect::getStrength(getStrength_cb _hidl_cb) {
+    return mEffect->getIntegerParam(BASSBOOST_PARAM_STRENGTH, _hidl_cb);
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/Conversions.h b/audio/effect/all-versions/default/include/effect/all-versions/default/Conversions.h
similarity index 64%
copy from audio/2.0/default/Conversions.h
copy to audio/effect/all-versions/default/include/effect/all-versions/default/Conversions.h
index ebda5c5..3f9317f 100644
--- a/audio/2.0/default/Conversions.h
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/Conversions.h
@@ -14,28 +14,28 @@
  * limitations under the License.
  */
 
-#ifndef android_hardware_audio_V2_0_Conversions_H_
-#define android_hardware_audio_V2_0_Conversions_H_
+#include <common/all-versions/IncludeGuard.h>
 
 #include <string>
 
-#include <android/hardware/audio/2.0/types.h>
-#include <system/audio.h>
+#include <system/audio_effect.h>
 
 namespace android {
 namespace hardware {
 namespace audio {
-namespace V2_0 {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
 namespace implementation {
 
-using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectDescriptor;
 
-std::string deviceAddressToHal(const DeviceAddress& address);
+void effectDescriptorFromHal(const effect_descriptor_t& halDescriptor,
+                             EffectDescriptor* descriptor);
+std::string uuidToString(const effect_uuid_t& halUuid);
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
-
-#endif  // android_hardware_audio_V2_0_Conversions_H_
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/Conversions.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/Conversions.impl.h
new file mode 100644
index 0000000..44adf4b
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/Conversions.impl.h
@@ -0,0 +1,56 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <memory.h>
+#include <stdio.h>
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::HidlUtils;
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+void effectDescriptorFromHal(const effect_descriptor_t& halDescriptor,
+                             EffectDescriptor* descriptor) {
+    HidlUtils::uuidFromHal(halDescriptor.type, &descriptor->type);
+    HidlUtils::uuidFromHal(halDescriptor.uuid, &descriptor->uuid);
+    descriptor->flags = EffectFlags(halDescriptor.flags);
+    descriptor->cpuLoad = halDescriptor.cpuLoad;
+    descriptor->memoryUsage = halDescriptor.memoryUsage;
+    memcpy(descriptor->name.data(), halDescriptor.name, descriptor->name.size());
+    memcpy(descriptor->implementor.data(), halDescriptor.implementor,
+           descriptor->implementor.size());
+}
+
+std::string uuidToString(const effect_uuid_t& halUuid) {
+    char str[64];
+    snprintf(str, sizeof(str), "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", halUuid.timeLow,
+             halUuid.timeMid, halUuid.timeHiAndVersion, halUuid.clockSeq, halUuid.node[0],
+             halUuid.node[1], halUuid.node[2], halUuid.node[3], halUuid.node[4], halUuid.node[5]);
+    return str;
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.h
new file mode 100644
index 0000000..e461ca8
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.h
@@ -0,0 +1,100 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IDownmixEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct DownmixEffect : public IDownmixEffect {
+    explicit DownmixEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IDownmixEffect follow.
+    Return<Result> setType(IDownmixEffect::Type preset) override;
+    Return<void> getType(getType_cb _hidl_cb) override;
+
+   private:
+    sp<Effect> mEffect;
+
+    virtual ~DownmixEffect();
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.impl.h
new file mode 100644
index 0000000..98710f8
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.impl.h
@@ -0,0 +1,177 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <android/log.h>
+#include <system/audio_effects/effect_downmix.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+DownmixEffect::DownmixEffect(effect_handle_t handle) : mEffect(new Effect(handle)) {}
+
+DownmixEffect::~DownmixEffect() {}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> DownmixEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> DownmixEffect::setConfig(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> DownmixEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> DownmixEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> DownmixEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> DownmixEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> DownmixEffect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                            setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> DownmixEffect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> DownmixEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> DownmixEffect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> DownmixEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> DownmixEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> DownmixEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> DownmixEffect::getSupportedAuxChannelsConfigs(
+    uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> DownmixEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> DownmixEffect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> DownmixEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> DownmixEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> DownmixEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> DownmixEffect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> DownmixEffect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                                const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> DownmixEffect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                                    uint32_t resultMaxSize, command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> DownmixEffect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                           const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> DownmixEffect::getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                                         getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> DownmixEffect::getSupportedConfigsForFeature(
+    uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+    getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> DownmixEffect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                                       getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> DownmixEffect::setCurrentConfigForFeature(uint32_t featureId,
+                                                         const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> DownmixEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IDownmixEffect follow.
+Return<Result> DownmixEffect::setType(IDownmixEffect::Type preset) {
+    return mEffect->setParam(DOWNMIX_PARAM_TYPE, static_cast<downmix_type_t>(preset));
+}
+
+Return<void> DownmixEffect::getType(getType_cb _hidl_cb) {
+    downmix_type_t halPreset = DOWNMIX_TYPE_INVALID;
+    Result retval = mEffect->getParam(DOWNMIX_PARAM_TYPE, halPreset);
+    _hidl_cb(retval, Type(halPreset));
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.h
new file mode 100644
index 0000000..81b0b24
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.h
@@ -0,0 +1,238 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <atomic>
+#include <memory>
+#include <vector>
+
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <utils/Thread.h>
+
+#include <hardware/audio_effect.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMode;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::Uuid;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::AudioBuffer;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectDescriptor;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectFeature;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectOffloadParameter;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Effect : public IEffect {
+    typedef MessageQueue<Result, kSynchronizedReadWrite> StatusMQ;
+    using GetParameterSuccessCallback =
+        std::function<void(uint32_t valueSize, const void* valueData)>;
+
+    explicit Effect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Utility methods for extending interfaces.
+    template <typename T>
+    Return<void> getIntegerParam(uint32_t paramId,
+                                 std::function<void(Result retval, T paramValue)> cb) {
+        T value;
+        Result retval = getParameterImpl(sizeof(uint32_t), &paramId, sizeof(T),
+                                         [&](uint32_t valueSize, const void* valueData) {
+                                             if (valueSize > sizeof(T)) valueSize = sizeof(T);
+                                             memcpy(&value, valueData, valueSize);
+                                         });
+        cb(retval, value);
+        return Void();
+    }
+
+    template <typename T>
+    Result getParam(uint32_t paramId, T& paramValue) {
+        return getParameterImpl(sizeof(uint32_t), &paramId, sizeof(T),
+                                [&](uint32_t valueSize, const void* valueData) {
+                                    if (valueSize > sizeof(T)) valueSize = sizeof(T);
+                                    memcpy(&paramValue, valueData, valueSize);
+                                });
+    }
+
+    template <typename T>
+    Result getParam(uint32_t paramId, uint32_t paramArg, T& paramValue) {
+        uint32_t params[2] = {paramId, paramArg};
+        return getParameterImpl(sizeof(params), params, sizeof(T),
+                                [&](uint32_t valueSize, const void* valueData) {
+                                    if (valueSize > sizeof(T)) valueSize = sizeof(T);
+                                    memcpy(&paramValue, valueData, valueSize);
+                                });
+    }
+
+    template <typename T>
+    Result setParam(uint32_t paramId, const T& paramValue) {
+        return setParameterImpl(sizeof(uint32_t), &paramId, sizeof(T), &paramValue);
+    }
+
+    template <typename T>
+    Result setParam(uint32_t paramId, uint32_t paramArg, const T& paramValue) {
+        uint32_t params[2] = {paramId, paramArg};
+        return setParameterImpl(sizeof(params), params, sizeof(T), &paramValue);
+    }
+
+    Result getParameterImpl(uint32_t paramSize, const void* paramData, uint32_t valueSize,
+                            GetParameterSuccessCallback onSuccess) {
+        return getParameterImpl(paramSize, paramData, valueSize, valueSize, onSuccess);
+    }
+    Result getParameterImpl(uint32_t paramSize, const void* paramData, uint32_t requestValueSize,
+                            uint32_t replyValueSize, GetParameterSuccessCallback onSuccess);
+    Result setParameterImpl(uint32_t paramSize, const void* paramData, uint32_t valueSize,
+                            const void* valueData);
+
+   private:
+    friend struct VirtualizerEffect;  // for getParameterImpl
+    friend struct VisualizerEffect;   // to allow executing commands
+
+    using CommandSuccessCallback = std::function<void()>;
+    using GetConfigCallback = std::function<void(Result retval, const EffectConfig& config)>;
+    using GetCurrentConfigSuccessCallback = std::function<void(void* configData)>;
+    using GetSupportedConfigsSuccessCallback =
+        std::function<void(uint32_t supportedConfigs, void* configsData)>;
+
+    static const char* sContextResultOfCommand;
+    static const char* sContextCallToCommand;
+    static const char* sContextCallFunction;
+
+    bool mIsClosed;
+    effect_handle_t mHandle;
+    sp<AudioBufferWrapper> mInBuffer;
+    sp<AudioBufferWrapper> mOutBuffer;
+    std::atomic<audio_buffer_t*> mHalInBufferPtr;
+    std::atomic<audio_buffer_t*> mHalOutBufferPtr;
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    EventFlag* mEfGroup;
+    std::atomic<bool> mStopProcessThread;
+    sp<Thread> mProcessThread;
+
+    virtual ~Effect();
+
+    template <typename T>
+    static size_t alignedSizeIn(size_t s);
+    template <typename T>
+    std::unique_ptr<uint8_t[]> hidlVecToHal(const hidl_vec<T>& vec, uint32_t* halDataSize);
+    static void effectAuxChannelsConfigFromHal(const channel_config_t& halConfig,
+                                               EffectAuxChannelsConfig* config);
+    static void effectAuxChannelsConfigToHal(const EffectAuxChannelsConfig& config,
+                                             channel_config_t* halConfig);
+    static void effectBufferConfigFromHal(const buffer_config_t& halConfig,
+                                          EffectBufferConfig* config);
+    static void effectBufferConfigToHal(const EffectBufferConfig& config,
+                                        buffer_config_t* halConfig);
+    static void effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config);
+    static void effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig);
+    static void effectOffloadParamToHal(const EffectOffloadParameter& offload,
+                                        effect_offload_param_t* halOffload);
+    static std::vector<uint8_t> parameterToHal(uint32_t paramSize, const void* paramData,
+                                               uint32_t valueSize, const void** valueData);
+
+    Result analyzeCommandStatus(const char* commandName, const char* context, status_t status);
+    Result analyzeStatus(const char* funcName, const char* subFuncName,
+                         const char* contextDescription, status_t status);
+    void getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb);
+    Result getCurrentConfigImpl(uint32_t featureId, uint32_t configSize,
+                                GetCurrentConfigSuccessCallback onSuccess);
+    Result getSupportedConfigsImpl(uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+                                   GetSupportedConfigsSuccessCallback onSuccess);
+    Result sendCommand(int commandCode, const char* commandName);
+    Result sendCommand(int commandCode, const char* commandName, uint32_t size, void* data);
+    Result sendCommandReturningData(int commandCode, const char* commandName, uint32_t* replySize,
+                                    void* replyData);
+    Result sendCommandReturningData(int commandCode, const char* commandName, uint32_t size,
+                                    void* data, uint32_t* replySize, void* replyData);
+    Result sendCommandReturningStatus(int commandCode, const char* commandName);
+    Result sendCommandReturningStatus(int commandCode, const char* commandName, uint32_t size,
+                                      void* data);
+    Result sendCommandReturningStatusAndData(int commandCode, const char* commandName,
+                                             uint32_t size, void* data, uint32_t* replySize,
+                                             void* replyData, uint32_t minReplySize,
+                                             CommandSuccessCallback onSuccess);
+    Result setConfigImpl(int commandCode, const char* commandName, const EffectConfig& config,
+                         const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+                         const sp<IEffectBufferProviderCallback>& outputBufferProvider);
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.impl.h
new file mode 100644
index 0000000..d376146
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.impl.h
@@ -0,0 +1,711 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <memory.h>
+
+#define ATRACE_TAG ATRACE_TAG_AUDIO
+
+#include <android/log.h>
+#include <media/EffectsFactoryApi.h>
+#include <utils/Trace.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioFormat;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::MessageQueueFlagBits;
+
+namespace {
+
+class ProcessThread : public Thread {
+   public:
+    // ProcessThread's lifespan never exceeds Effect's lifespan.
+    ProcessThread(std::atomic<bool>* stop, effect_handle_t effect,
+                  std::atomic<audio_buffer_t*>* inBuffer, std::atomic<audio_buffer_t*>* outBuffer,
+                  Effect::StatusMQ* statusMQ, EventFlag* efGroup)
+        : Thread(false /*canCallJava*/),
+          mStop(stop),
+          mEffect(effect),
+          mHasProcessReverse((*mEffect)->process_reverse != NULL),
+          mInBuffer(inBuffer),
+          mOutBuffer(outBuffer),
+          mStatusMQ(statusMQ),
+          mEfGroup(efGroup) {}
+    virtual ~ProcessThread() {}
+
+   private:
+    std::atomic<bool>* mStop;
+    effect_handle_t mEffect;
+    bool mHasProcessReverse;
+    std::atomic<audio_buffer_t*>* mInBuffer;
+    std::atomic<audio_buffer_t*>* mOutBuffer;
+    Effect::StatusMQ* mStatusMQ;
+    EventFlag* mEfGroup;
+
+    bool threadLoop() override;
+};
+
+bool ProcessThread::threadLoop() {
+    // This implementation doesn't return control back to the Thread until it decides to stop,
+    // as the Thread uses mutexes, and this can lead to priority inversion.
+    while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
+        uint32_t efState = 0;
+        mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL), &efState);
+        if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL)) ||
+            (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT))) {
+            continue;  // Nothing to do or time to quit.
+        }
+        Result retval = Result::OK;
+        if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE) &&
+            !mHasProcessReverse) {
+            retval = Result::NOT_SUPPORTED;
+        }
+
+        if (retval == Result::OK) {
+            // affects both buffer pointers and their contents.
+            std::atomic_thread_fence(std::memory_order_acquire);
+            int32_t processResult;
+            audio_buffer_t* inBuffer =
+                std::atomic_load_explicit(mInBuffer, std::memory_order_relaxed);
+            audio_buffer_t* outBuffer =
+                std::atomic_load_explicit(mOutBuffer, std::memory_order_relaxed);
+            if (inBuffer != nullptr && outBuffer != nullptr) {
+                if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS)) {
+                    processResult = (*mEffect)->process(mEffect, inBuffer, outBuffer);
+                } else {
+                    processResult = (*mEffect)->process_reverse(mEffect, inBuffer, outBuffer);
+                }
+                std::atomic_thread_fence(std::memory_order_release);
+            } else {
+                ALOGE("processing buffers were not set before calling 'process'");
+                processResult = -ENODEV;
+            }
+            switch (processResult) {
+                case 0:
+                    retval = Result::OK;
+                    break;
+                case -ENODATA:
+                    retval = Result::INVALID_STATE;
+                    break;
+                case -EINVAL:
+                    retval = Result::INVALID_ARGUMENTS;
+                    break;
+                default:
+                    retval = Result::NOT_INITIALIZED;
+            }
+        }
+        if (!mStatusMQ->write(&retval)) {
+            ALOGW("status message queue write failed");
+        }
+        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING));
+    }
+
+    return false;
+}
+
+}  // namespace
+
+// static
+const char* Effect::sContextResultOfCommand = "returned status";
+const char* Effect::sContextCallToCommand = "error";
+const char* Effect::sContextCallFunction = sContextCallToCommand;
+
+Effect::Effect(effect_handle_t handle)
+    : mIsClosed(false), mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) {}
+
+Effect::~Effect() {
+    ATRACE_CALL();
+    close();
+    if (mProcessThread.get()) {
+        ATRACE_NAME("mProcessThread->join");
+        status_t status = mProcessThread->join();
+        ALOGE_IF(status, "processing thread exit error: %s", strerror(-status));
+    }
+    if (mEfGroup) {
+        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
+        ALOGE_IF(status, "processing MQ event flag deletion error: %s", strerror(-status));
+    }
+    mInBuffer.clear();
+    mOutBuffer.clear();
+    int status = EffectRelease(mHandle);
+    ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
+    EffectMap::getInstance().remove(mHandle);
+    mHandle = 0;
+}
+
+// static
+template <typename T>
+size_t Effect::alignedSizeIn(size_t s) {
+    return (s + sizeof(T) - 1) / sizeof(T);
+}
+
+// static
+template <typename T>
+std::unique_ptr<uint8_t[]> Effect::hidlVecToHal(const hidl_vec<T>& vec, uint32_t* halDataSize) {
+    // Due to bugs in HAL, they may attempt to write into the provided
+    // input buffer. The original binder buffer is r/o, thus it is needed
+    // to create a r/w version.
+    *halDataSize = vec.size() * sizeof(T);
+    std::unique_ptr<uint8_t[]> halData(new uint8_t[*halDataSize]);
+    memcpy(&halData[0], &vec[0], *halDataSize);
+    return halData;
+}
+
+// static
+void Effect::effectAuxChannelsConfigFromHal(const channel_config_t& halConfig,
+                                            EffectAuxChannelsConfig* config) {
+    config->mainChannels = AudioChannelMask(halConfig.main_channels);
+    config->auxChannels = AudioChannelMask(halConfig.aux_channels);
+}
+
+// static
+void Effect::effectAuxChannelsConfigToHal(const EffectAuxChannelsConfig& config,
+                                          channel_config_t* halConfig) {
+    halConfig->main_channels = static_cast<audio_channel_mask_t>(config.mainChannels);
+    halConfig->aux_channels = static_cast<audio_channel_mask_t>(config.auxChannels);
+}
+
+// static
+void Effect::effectBufferConfigFromHal(const buffer_config_t& halConfig,
+                                       EffectBufferConfig* config) {
+    config->buffer.id = 0;
+    config->buffer.frameCount = 0;
+    config->samplingRateHz = halConfig.samplingRate;
+    config->channels = AudioChannelMask(halConfig.channels);
+    config->format = AudioFormat(halConfig.format);
+    config->accessMode = EffectBufferAccess(halConfig.accessMode);
+    config->mask = EffectConfigParameters(halConfig.mask);
+}
+
+// static
+void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) {
+    // Note: setting the buffers directly is considered obsolete. They need to be set
+    // using 'setProcessBuffers'.
+    halConfig->buffer.frameCount = 0;
+    halConfig->buffer.raw = NULL;
+    halConfig->samplingRate = config.samplingRateHz;
+    halConfig->channels = static_cast<uint32_t>(config.channels);
+    // Note: The framework code does not use BP.
+    halConfig->bufferProvider.cookie = NULL;
+    halConfig->bufferProvider.getBuffer = NULL;
+    halConfig->bufferProvider.releaseBuffer = NULL;
+    halConfig->format = static_cast<uint8_t>(config.format);
+    halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
+    halConfig->mask = static_cast<uint8_t>(config.mask);
+}
+
+// static
+void Effect::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) {
+    effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg);
+    effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg);
+}
+
+// static
+void Effect::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
+    effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg);
+    effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg);
+}
+
+// static
+void Effect::effectOffloadParamToHal(const EffectOffloadParameter& offload,
+                                     effect_offload_param_t* halOffload) {
+    halOffload->isOffload = offload.isOffload;
+    halOffload->ioHandle = offload.ioHandle;
+}
+
+// static
+std::vector<uint8_t> Effect::parameterToHal(uint32_t paramSize, const void* paramData,
+                                            uint32_t valueSize, const void** valueData) {
+    size_t valueOffsetFromData = alignedSizeIn<uint32_t>(paramSize) * sizeof(uint32_t);
+    size_t halParamBufferSize = sizeof(effect_param_t) + valueOffsetFromData + valueSize;
+    std::vector<uint8_t> halParamBuffer(halParamBufferSize, 0);
+    effect_param_t* halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
+    halParam->psize = paramSize;
+    halParam->vsize = valueSize;
+    memcpy(halParam->data, paramData, paramSize);
+    if (valueData) {
+        if (*valueData) {
+            // Value data is provided.
+            memcpy(halParam->data + valueOffsetFromData, *valueData, valueSize);
+        } else {
+            // The caller needs the pointer to the value data location.
+            *valueData = halParam->data + valueOffsetFromData;
+        }
+    }
+    return halParamBuffer;
+}
+
+Result Effect::analyzeCommandStatus(const char* commandName, const char* context, status_t status) {
+    return analyzeStatus("command", commandName, context, status);
+}
+
+Result Effect::analyzeStatus(const char* funcName, const char* subFuncName,
+                             const char* contextDescription, status_t status) {
+    if (status != OK) {
+        ALOGW("Effect %p %s %s %s: %s", mHandle, funcName, subFuncName, contextDescription,
+              strerror(-status));
+    }
+    switch (status) {
+        case OK:
+            return Result::OK;
+        case -EINVAL:
+            return Result::INVALID_ARGUMENTS;
+        case -ENODATA:
+            return Result::INVALID_STATE;
+        case -ENODEV:
+            return Result::NOT_INITIALIZED;
+        case -ENOMEM:
+            return Result::RESULT_TOO_BIG;
+        case -ENOSYS:
+            return Result::NOT_SUPPORTED;
+        default:
+            return Result::INVALID_STATE;
+    }
+}
+
+void Effect::getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb) {
+    uint32_t halResultSize = sizeof(effect_config_t);
+    effect_config_t halConfig{};
+    status_t status =
+        (*mHandle)->command(mHandle, commandCode, 0, NULL, &halResultSize, &halConfig);
+    EffectConfig config;
+    if (status == OK) {
+        effectConfigFromHal(halConfig, &config);
+    }
+    cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
+}
+
+Result Effect::getCurrentConfigImpl(uint32_t featureId, uint32_t configSize,
+                                    GetCurrentConfigSuccessCallback onSuccess) {
+    uint32_t halCmd = featureId;
+    uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configSize)];
+    memset(halResult, 0, sizeof(halResult));
+    uint32_t halResultSize = 0;
+    return sendCommandReturningStatusAndData(EFFECT_CMD_GET_FEATURE_CONFIG, "GET_FEATURE_CONFIG",
+                                             sizeof(uint32_t), &halCmd, &halResultSize, halResult,
+                                             sizeof(uint32_t), [&] { onSuccess(&halResult[1]); });
+}
+
+Result Effect::getParameterImpl(uint32_t paramSize, const void* paramData,
+                                uint32_t requestValueSize, uint32_t replyValueSize,
+                                GetParameterSuccessCallback onSuccess) {
+    // As it is unknown what method HAL uses for copying the provided parameter data,
+    // it is safer to make sure that input and output buffers do not overlap.
+    std::vector<uint8_t> halCmdBuffer =
+        parameterToHal(paramSize, paramData, requestValueSize, nullptr);
+    const void* valueData = nullptr;
+    std::vector<uint8_t> halParamBuffer =
+        parameterToHal(paramSize, paramData, replyValueSize, &valueData);
+    uint32_t halParamBufferSize = halParamBuffer.size();
+
+    return sendCommandReturningStatusAndData(
+        EFFECT_CMD_GET_PARAM, "GET_PARAM", halCmdBuffer.size(), &halCmdBuffer[0],
+        &halParamBufferSize, &halParamBuffer[0], sizeof(effect_param_t), [&] {
+            effect_param_t* halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
+            onSuccess(halParam->vsize, valueData);
+        });
+}
+
+Result Effect::getSupportedConfigsImpl(uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+                                       GetSupportedConfigsSuccessCallback onSuccess) {
+    uint32_t halCmd[2] = {featureId, maxConfigs};
+    uint32_t halResultSize = 2 * sizeof(uint32_t) + maxConfigs * sizeof(configSize);
+    uint8_t halResult[halResultSize];
+    memset(&halResult[0], 0, halResultSize);
+    return sendCommandReturningStatusAndData(
+        EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS, "GET_FEATURE_SUPPORTED_CONFIGS", sizeof(halCmd),
+        halCmd, &halResultSize, &halResult[0], 2 * sizeof(uint32_t), [&] {
+            uint32_t* halResult32 = reinterpret_cast<uint32_t*>(&halResult[0]);
+            uint32_t supportedConfigs = *(++halResult32);  // skip status field
+            if (supportedConfigs > maxConfigs) supportedConfigs = maxConfigs;
+            onSuccess(supportedConfigs, ++halResult32);
+        });
+}
+
+Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    status_t status;
+    // Create message queue.
+    if (mStatusMQ) {
+        ALOGE("the client attempts to call prepareForProcessing_cb twice");
+        _hidl_cb(Result::INVALID_STATE, StatusMQ::Descriptor());
+        return Void();
+    }
+    std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1, true /*EventFlag*/));
+    if (!tempStatusMQ->isValid()) {
+        ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
+        _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
+        return Void();
+    }
+    status = EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &mEfGroup);
+    if (status != OK || !mEfGroup) {
+        ALOGE("failed creating event flag for status MQ: %s", strerror(-status));
+        _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
+        return Void();
+    }
+
+    // Create and launch the thread.
+    mProcessThread = new ProcessThread(&mStopProcessThread, mHandle, &mHalInBufferPtr,
+                                       &mHalOutBufferPtr, tempStatusMQ.get(), mEfGroup);
+    status = mProcessThread->run("effect", PRIORITY_URGENT_AUDIO);
+    if (status != OK) {
+        ALOGW("failed to start effect processing thread: %s", strerror(-status));
+        _hidl_cb(Result::INVALID_ARGUMENTS, MQDescriptorSync<Result>());
+        return Void();
+    }
+
+    mStatusMQ = std::move(tempStatusMQ);
+    _hidl_cb(Result::OK, *mStatusMQ->getDesc());
+    return Void();
+}
+
+Return<Result> Effect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                         const AudioBuffer& outBuffer) {
+    AudioBufferManager& manager = AudioBufferManager::getInstance();
+    sp<AudioBufferWrapper> tempInBuffer, tempOutBuffer;
+    if (!manager.wrap(inBuffer, &tempInBuffer)) {
+        ALOGE("Could not map memory of the input buffer");
+        return Result::INVALID_ARGUMENTS;
+    }
+    if (!manager.wrap(outBuffer, &tempOutBuffer)) {
+        ALOGE("Could not map memory of the output buffer");
+        return Result::INVALID_ARGUMENTS;
+    }
+    mInBuffer = tempInBuffer;
+    mOutBuffer = tempOutBuffer;
+    // The processing thread only reads these pointers after waking up by an event flag,
+    // so it's OK to update the pair non-atomically.
+    mHalInBufferPtr.store(mInBuffer->getHalBuffer(), std::memory_order_release);
+    mHalOutBufferPtr.store(mOutBuffer->getHalBuffer(), std::memory_order_release);
+    return Result::OK;
+}
+
+Result Effect::sendCommand(int commandCode, const char* commandName) {
+    return sendCommand(commandCode, commandName, 0, NULL);
+}
+
+Result Effect::sendCommand(int commandCode, const char* commandName, uint32_t size, void* data) {
+    status_t status = (*mHandle)->command(mHandle, commandCode, size, data, 0, NULL);
+    return analyzeCommandStatus(commandName, sContextCallToCommand, status);
+}
+
+Result Effect::sendCommandReturningData(int commandCode, const char* commandName,
+                                        uint32_t* replySize, void* replyData) {
+    return sendCommandReturningData(commandCode, commandName, 0, NULL, replySize, replyData);
+}
+
+Result Effect::sendCommandReturningData(int commandCode, const char* commandName, uint32_t size,
+                                        void* data, uint32_t* replySize, void* replyData) {
+    uint32_t expectedReplySize = *replySize;
+    status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
+    if (status == OK && *replySize != expectedReplySize) {
+        status = -ENODATA;
+    }
+    return analyzeCommandStatus(commandName, sContextCallToCommand, status);
+}
+
+Result Effect::sendCommandReturningStatus(int commandCode, const char* commandName) {
+    return sendCommandReturningStatus(commandCode, commandName, 0, NULL);
+}
+
+Result Effect::sendCommandReturningStatus(int commandCode, const char* commandName, uint32_t size,
+                                          void* data) {
+    uint32_t replyCmdStatus;
+    uint32_t replySize = sizeof(uint32_t);
+    return sendCommandReturningStatusAndData(commandCode, commandName, size, data, &replySize,
+                                             &replyCmdStatus, replySize, [] {});
+}
+
+Result Effect::sendCommandReturningStatusAndData(int commandCode, const char* commandName,
+                                                 uint32_t size, void* data, uint32_t* replySize,
+                                                 void* replyData, uint32_t minReplySize,
+                                                 CommandSuccessCallback onSuccess) {
+    status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
+    Result retval;
+    if (status == OK && minReplySize >= sizeof(uint32_t) && *replySize >= minReplySize) {
+        uint32_t commandStatus = *reinterpret_cast<uint32_t*>(replyData);
+        retval = analyzeCommandStatus(commandName, sContextResultOfCommand, commandStatus);
+        if (commandStatus == OK) {
+            onSuccess();
+        }
+    } else {
+        retval = analyzeCommandStatus(commandName, sContextCallToCommand, status);
+    }
+    return retval;
+}
+
+Result Effect::setConfigImpl(int commandCode, const char* commandName, const EffectConfig& config,
+                             const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+                             const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    effect_config_t halConfig;
+    effectConfigToHal(config, &halConfig);
+    if (inputBufferProvider != 0) {
+        LOG_FATAL("Using input buffer provider is not supported");
+    }
+    if (outputBufferProvider != 0) {
+        LOG_FATAL("Using output buffer provider is not supported");
+    }
+    return sendCommandReturningStatus(commandCode, commandName, sizeof(effect_config_t),
+                                      &halConfig);
+}
+
+Result Effect::setParameterImpl(uint32_t paramSize, const void* paramData, uint32_t valueSize,
+                                const void* valueData) {
+    std::vector<uint8_t> halParamBuffer =
+        parameterToHal(paramSize, paramData, valueSize, &valueData);
+    return sendCommandReturningStatus(EFFECT_CMD_SET_PARAM, "SET_PARAM", halParamBuffer.size(),
+                                      &halParamBuffer[0]);
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> Effect::init() {
+    return sendCommandReturningStatus(EFFECT_CMD_INIT, "INIT");
+}
+
+Return<Result> Effect::setConfig(const EffectConfig& config,
+                                 const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+                                 const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return setConfigImpl(EFFECT_CMD_SET_CONFIG, "SET_CONFIG", config, inputBufferProvider,
+                         outputBufferProvider);
+}
+
+Return<Result> Effect::reset() {
+    return sendCommand(EFFECT_CMD_RESET, "RESET");
+}
+
+Return<Result> Effect::enable() {
+    return sendCommandReturningStatus(EFFECT_CMD_ENABLE, "ENABLE");
+}
+
+Return<Result> Effect::disable() {
+    return sendCommandReturningStatus(EFFECT_CMD_DISABLE, "DISABLE");
+}
+
+Return<Result> Effect::setDevice(AudioDevice device) {
+    uint32_t halDevice = static_cast<uint32_t>(device);
+    return sendCommand(EFFECT_CMD_SET_DEVICE, "SET_DEVICE", sizeof(uint32_t), &halDevice);
+}
+
+Return<void> Effect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                     setAndGetVolume_cb _hidl_cb) {
+    uint32_t halDataSize;
+    std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
+    uint32_t halResultSize = halDataSize;
+    uint32_t halResult[volumes.size()];
+    Result retval = sendCommandReturningData(EFFECT_CMD_SET_VOLUME, "SET_VOLUME", halDataSize,
+                                             &halData[0], &halResultSize, halResult);
+    hidl_vec<uint32_t> result;
+    if (retval == Result::OK) {
+        result.setToExternal(&halResult[0], halResultSize);
+    }
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+Return<Result> Effect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
+    uint32_t halDataSize;
+    std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
+    return sendCommand(EFFECT_CMD_SET_VOLUME, "SET_VOLUME", halDataSize, &halData[0]);
+}
+
+Return<Result> Effect::setAudioMode(AudioMode mode) {
+    uint32_t halMode = static_cast<uint32_t>(mode);
+    return sendCommand(EFFECT_CMD_SET_AUDIO_MODE, "SET_AUDIO_MODE", sizeof(uint32_t), &halMode);
+}
+
+Return<Result> Effect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return setConfigImpl(EFFECT_CMD_SET_CONFIG_REVERSE, "SET_CONFIG_REVERSE", config,
+                         inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> Effect::setInputDevice(AudioDevice device) {
+    uint32_t halDevice = static_cast<uint32_t>(device);
+    return sendCommand(EFFECT_CMD_SET_INPUT_DEVICE, "SET_INPUT_DEVICE", sizeof(uint32_t),
+                       &halDevice);
+}
+
+Return<void> Effect::getConfig(getConfig_cb _hidl_cb) {
+    getConfigImpl(EFFECT_CMD_GET_CONFIG, "GET_CONFIG", _hidl_cb);
+    return Void();
+}
+
+Return<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    getConfigImpl(EFFECT_CMD_GET_CONFIG_REVERSE, "GET_CONFIG_REVERSE", _hidl_cb);
+    return Void();
+}
+
+Return<void> Effect::getSupportedAuxChannelsConfigs(uint32_t maxConfigs,
+                                                    getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    hidl_vec<EffectAuxChannelsConfig> result;
+    Result retval = getSupportedConfigsImpl(
+        EFFECT_FEATURE_AUX_CHANNELS, maxConfigs, sizeof(channel_config_t),
+        [&](uint32_t supportedConfigs, void* configsData) {
+            result.resize(supportedConfigs);
+            channel_config_t* config = reinterpret_cast<channel_config_t*>(configsData);
+            for (size_t i = 0; i < result.size(); ++i) {
+                effectAuxChannelsConfigFromHal(*config++, &result[i]);
+            }
+        });
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+Return<void> Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
+    memset(halResult, 0, sizeof(halResult));
+    EffectAuxChannelsConfig result;
+    Result retval = getCurrentConfigImpl(
+        EFFECT_FEATURE_AUX_CHANNELS, sizeof(channel_config_t), [&](void* configData) {
+            effectAuxChannelsConfigFromHal(*reinterpret_cast<channel_config_t*>(configData),
+                                           &result);
+        });
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+Return<Result> Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
+    uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
+    halCmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
+    effectAuxChannelsConfigToHal(config, reinterpret_cast<channel_config_t*>(&halCmd[1]));
+    return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG,
+                                      "SET_FEATURE_CONFIG AUX_CHANNELS", sizeof(halCmd), halCmd);
+}
+
+Return<Result> Effect::setAudioSource(AudioSource source) {
+    uint32_t halSource = static_cast<uint32_t>(source);
+    return sendCommand(EFFECT_CMD_SET_AUDIO_SOURCE, "SET_AUDIO_SOURCE", sizeof(uint32_t),
+                       &halSource);
+}
+
+Return<Result> Effect::offload(const EffectOffloadParameter& param) {
+    effect_offload_param_t halParam;
+    effectOffloadParamToHal(param, &halParam);
+    return sendCommandReturningStatus(EFFECT_CMD_OFFLOAD, "OFFLOAD", sizeof(effect_offload_param_t),
+                                      &halParam);
+}
+
+Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    effect_descriptor_t halDescriptor;
+    memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
+    status_t status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
+    EffectDescriptor descriptor;
+    if (status == OK) {
+        effectDescriptorFromHal(halDescriptor, &descriptor);
+    }
+    _hidl_cb(analyzeStatus("get_descriptor", "", sContextCallFunction, status), descriptor);
+    return Void();
+}
+
+Return<void> Effect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                             uint32_t resultMaxSize, command_cb _hidl_cb) {
+    uint32_t halDataSize;
+    std::unique_ptr<uint8_t[]> halData = hidlVecToHal(data, &halDataSize);
+    uint32_t halResultSize = resultMaxSize;
+    std::unique_ptr<uint8_t[]> halResult(new uint8_t[halResultSize]);
+    memset(&halResult[0], 0, halResultSize);
+
+    void* dataPtr = halDataSize > 0 ? &halData[0] : NULL;
+    void* resultPtr = halResultSize > 0 ? &halResult[0] : NULL;
+    status_t status =
+        (*mHandle)->command(mHandle, commandId, halDataSize, dataPtr, &halResultSize, resultPtr);
+    hidl_vec<uint8_t> result;
+    if (status == OK && resultPtr != NULL) {
+        result.setToExternal(&halResult[0], halResultSize);
+    }
+    _hidl_cb(status, result);
+    return Void();
+}
+
+Return<Result> Effect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                    const hidl_vec<uint8_t>& value) {
+    return setParameterImpl(parameter.size(), &parameter[0], value.size(), &value[0]);
+}
+
+Return<void> Effect::getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                                  getParameter_cb _hidl_cb) {
+    hidl_vec<uint8_t> value;
+    Result retval = getParameterImpl(
+        parameter.size(), &parameter[0], valueMaxSize,
+        [&](uint32_t valueSize, const void* valueData) {
+            value.setToExternal(reinterpret_cast<uint8_t*>(const_cast<void*>(valueData)),
+                                valueSize);
+        });
+    _hidl_cb(retval, value);
+    return Void();
+}
+
+Return<void> Effect::getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                                   uint32_t configSize,
+                                                   getSupportedConfigsForFeature_cb _hidl_cb) {
+    uint32_t configCount = 0;
+    hidl_vec<uint8_t> result;
+    Result retval = getSupportedConfigsImpl(featureId, maxConfigs, configSize,
+                                            [&](uint32_t supportedConfigs, void* configsData) {
+                                                configCount = supportedConfigs;
+                                                result.resize(configCount * configSize);
+                                                memcpy(&result[0], configsData, result.size());
+                                            });
+    _hidl_cb(retval, configCount, result);
+    return Void();
+}
+
+Return<void> Effect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                                getCurrentConfigForFeature_cb _hidl_cb) {
+    hidl_vec<uint8_t> result;
+    Result retval = getCurrentConfigImpl(featureId, configSize, [&](void* configData) {
+        result.resize(configSize);
+        memcpy(&result[0], configData, result.size());
+    });
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+Return<Result> Effect::setCurrentConfigForFeature(uint32_t featureId,
+                                                  const hidl_vec<uint8_t>& configData) {
+    uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configData.size())];
+    memset(halCmd, 0, sizeof(halCmd));
+    halCmd[0] = featureId;
+    memcpy(&halCmd[1], &configData[0], configData.size());
+    return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG, "SET_FEATURE_CONFIG",
+                                      sizeof(halCmd), halCmd);
+}
+
+Return<Result> Effect::close() {
+    if (mIsClosed) return Result::INVALID_STATE;
+    mIsClosed = true;
+    if (mProcessThread.get()) {
+        mStopProcessThread.store(true, std::memory_order_release);
+    }
+    if (mEfGroup) {
+        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT));
+    }
+    return Result::OK;
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.h
new file mode 100644
index 0000000..e586abb
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.h
@@ -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 <common/all-versions/IncludeGuard.h>
+
+#include <hardware/audio_effect.h>
+#include <system/audio_effect.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::Uuid;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectDescriptor;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffectsFactory;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct EffectsFactory : public IEffectsFactory {
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffectsFactory follow.
+    Return<void> getAllDescriptors(getAllDescriptors_cb _hidl_cb) override;
+    Return<void> getDescriptor(const Uuid& uid, getDescriptor_cb _hidl_cb) override;
+    Return<void> createEffect(const Uuid& uid, int32_t session, int32_t ioHandle,
+                              createEffect_cb _hidl_cb) override;
+    Return<void> debugDump(const hidl_handle& fd) override;
+
+   private:
+    static sp<IEffect> dispatchEffectInstanceCreation(const effect_descriptor_t& halDescriptor,
+                                                      effect_handle_t handle);
+};
+
+extern "C" IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
new file mode 100644
index 0000000..b2a36a9
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
@@ -0,0 +1,190 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <android/log.h>
+#include <media/EffectsFactoryApi.h>
+#include <system/audio_effects/effect_aec.h>
+#include <system/audio_effects/effect_agc.h>
+#include <system/audio_effects/effect_bassboost.h>
+#include <system/audio_effects/effect_downmix.h>
+#include <system/audio_effects/effect_environmentalreverb.h>
+#include <system/audio_effects/effect_equalizer.h>
+#include <system/audio_effects/effect_loudnessenhancer.h>
+#include <system/audio_effects/effect_ns.h>
+#include <system/audio_effects/effect_presetreverb.h>
+#include <system/audio_effects/effect_virtualizer.h>
+#include <system/audio_effects/effect_visualizer.h>
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::HidlUtils;
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+// static
+sp<IEffect> EffectsFactory::dispatchEffectInstanceCreation(const effect_descriptor_t& halDescriptor,
+                                                           effect_handle_t handle) {
+    const effect_uuid_t* halUuid = &halDescriptor.type;
+    if (memcmp(halUuid, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
+        return new AcousticEchoCancelerEffect(handle);
+    } else if (memcmp(halUuid, FX_IID_AGC, sizeof(effect_uuid_t)) == 0) {
+        return new AutomaticGainControlEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_BASSBOOST, sizeof(effect_uuid_t)) == 0) {
+        return new BassBoostEffect(handle);
+    } else if (memcmp(halUuid, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
+        return new DownmixEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_ENVIRONMENTALREVERB, sizeof(effect_uuid_t)) == 0) {
+        return new EnvironmentalReverbEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_EQUALIZER, sizeof(effect_uuid_t)) == 0) {
+        return new EqualizerEffect(handle);
+    } else if (memcmp(halUuid, FX_IID_LOUDNESS_ENHANCER, sizeof(effect_uuid_t)) == 0) {
+        return new LoudnessEnhancerEffect(handle);
+    } else if (memcmp(halUuid, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
+        return new NoiseSuppressionEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
+        return new PresetReverbEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_VIRTUALIZER, sizeof(effect_uuid_t)) == 0) {
+        return new VirtualizerEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) {
+        return new VisualizerEffect(handle);
+    }
+    return new Effect(handle);
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffectsFactory follow.
+Return<void> EffectsFactory::getAllDescriptors(getAllDescriptors_cb _hidl_cb) {
+    Result retval(Result::OK);
+    hidl_vec<EffectDescriptor> result;
+    uint32_t numEffects;
+    status_t status;
+
+restart:
+    numEffects = 0;
+    status = EffectQueryNumberEffects(&numEffects);
+    if (status != OK) {
+        retval = Result::NOT_INITIALIZED;
+        ALOGE("Error querying number of effects: %s", strerror(-status));
+        goto exit;
+    }
+    result.resize(numEffects);
+    for (uint32_t i = 0; i < numEffects; ++i) {
+        effect_descriptor_t halDescriptor;
+        status = EffectQueryEffect(i, &halDescriptor);
+        if (status == OK) {
+            effectDescriptorFromHal(halDescriptor, &result[i]);
+        } else {
+            ALOGE("Error querying effect at position %d / %d: %s", i, numEffects,
+                  strerror(-status));
+            switch (status) {
+                case -ENOSYS: {
+                    // Effect list has changed.
+                    goto restart;
+                }
+                case -ENOENT: {
+                    // No more effects available.
+                    result.resize(i);
+                }
+                default: {
+                    result.resize(0);
+                    retval = Result::NOT_INITIALIZED;
+                }
+            }
+            break;
+        }
+    }
+
+exit:
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+Return<void> EffectsFactory::getDescriptor(const Uuid& uid, getDescriptor_cb _hidl_cb) {
+    effect_uuid_t halUuid;
+    HidlUtils::uuidToHal(uid, &halUuid);
+    effect_descriptor_t halDescriptor;
+    status_t status = EffectGetDescriptor(&halUuid, &halDescriptor);
+    EffectDescriptor descriptor;
+    effectDescriptorFromHal(halDescriptor, &descriptor);
+    Result retval(Result::OK);
+    if (status != OK) {
+        ALOGE("Error querying effect descriptor for %s: %s", uuidToString(halUuid).c_str(),
+              strerror(-status));
+        if (status == -ENOENT) {
+            retval = Result::INVALID_ARGUMENTS;
+        } else {
+            retval = Result::NOT_INITIALIZED;
+        }
+    }
+    _hidl_cb(retval, descriptor);
+    return Void();
+}
+
+Return<void> EffectsFactory::createEffect(const Uuid& uid, int32_t session, int32_t ioHandle,
+                                          createEffect_cb _hidl_cb) {
+    effect_uuid_t halUuid;
+    HidlUtils::uuidToHal(uid, &halUuid);
+    effect_handle_t handle;
+    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 {
+            ALOGE("Error querying effect descriptor for %s: %s", uuidToString(halUuid).c_str(),
+                  strerror(-status));
+            EffectRelease(handle);
+        }
+    }
+    if (status != OK) {
+        ALOGE("Error creating effect %s: %s", uuidToString(halUuid).c_str(), strerror(-status));
+        if (status == -ENOENT) {
+            retval = Result::INVALID_ARGUMENTS;
+        } else {
+            retval = Result::NOT_INITIALIZED;
+        }
+    }
+    _hidl_cb(retval, effect, effectId);
+    return Void();
+}
+
+Return<void> EffectsFactory::debugDump(const hidl_handle& fd) {
+    if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
+        EffectDumpEffects(fd->data[0]);
+    }
+    return Void();
+}
+
+IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* /* name */) {
+    return new EffectsFactory();
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.h
new file mode 100644
index 0000000..8351e55
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.h
@@ -0,0 +1,141 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <system/audio_effects/effect_environmentalreverb.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMode;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::AudioBuffer;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectDescriptor;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectOffloadParameter;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEnvironmentalReverbEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct EnvironmentalReverbEffect : public IEnvironmentalReverbEffect {
+    explicit EnvironmentalReverbEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Methods from
+    // ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEnvironmentalReverbEffect follow.
+    Return<Result> setBypass(bool bypass) override;
+    Return<void> getBypass(getBypass_cb _hidl_cb) override;
+    Return<Result> setRoomLevel(int16_t roomLevel) override;
+    Return<void> getRoomLevel(getRoomLevel_cb _hidl_cb) override;
+    Return<Result> setRoomHfLevel(int16_t roomHfLevel) override;
+    Return<void> getRoomHfLevel(getRoomHfLevel_cb _hidl_cb) override;
+    Return<Result> setDecayTime(uint32_t decayTime) override;
+    Return<void> getDecayTime(getDecayTime_cb _hidl_cb) override;
+    Return<Result> setDecayHfRatio(int16_t decayHfRatio) override;
+    Return<void> getDecayHfRatio(getDecayHfRatio_cb _hidl_cb) override;
+    Return<Result> setReflectionsLevel(int16_t reflectionsLevel) override;
+    Return<void> getReflectionsLevel(getReflectionsLevel_cb _hidl_cb) override;
+    Return<Result> setReflectionsDelay(uint32_t reflectionsDelay) override;
+    Return<void> getReflectionsDelay(getReflectionsDelay_cb _hidl_cb) override;
+    Return<Result> setReverbLevel(int16_t reverbLevel) override;
+    Return<void> getReverbLevel(getReverbLevel_cb _hidl_cb) override;
+    Return<Result> setReverbDelay(uint32_t reverbDelay) override;
+    Return<void> getReverbDelay(getReverbDelay_cb _hidl_cb) override;
+    Return<Result> setDiffusion(int16_t diffusion) override;
+    Return<void> getDiffusion(getDiffusion_cb _hidl_cb) override;
+    Return<Result> setDensity(int16_t density) override;
+    Return<void> getDensity(getDensity_cb _hidl_cb) override;
+    Return<Result> setAllProperties(
+        const IEnvironmentalReverbEffect::AllProperties& properties) override;
+    Return<void> getAllProperties(getAllProperties_cb _hidl_cb) override;
+
+   private:
+    sp<Effect> mEffect;
+
+    virtual ~EnvironmentalReverbEffect();
+
+    void propertiesFromHal(const t_reverb_settings& halProperties,
+                           IEnvironmentalReverbEffect::AllProperties* properties);
+    void propertiesToHal(const IEnvironmentalReverbEffect::AllProperties& properties,
+                         t_reverb_settings* halProperties);
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.impl.h
new file mode 100644
index 0000000..9090b8a
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.impl.h
@@ -0,0 +1,302 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <android/log.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+EnvironmentalReverbEffect::EnvironmentalReverbEffect(effect_handle_t handle)
+    : mEffect(new Effect(handle)) {}
+
+EnvironmentalReverbEffect::~EnvironmentalReverbEffect() {}
+
+void EnvironmentalReverbEffect::propertiesFromHal(
+    const t_reverb_settings& halProperties, IEnvironmentalReverbEffect::AllProperties* properties) {
+    properties->roomLevel = halProperties.roomLevel;
+    properties->roomHfLevel = halProperties.roomHFLevel;
+    properties->decayTime = halProperties.decayTime;
+    properties->decayHfRatio = halProperties.decayHFRatio;
+    properties->reflectionsLevel = halProperties.reflectionsLevel;
+    properties->reflectionsDelay = halProperties.reflectionsDelay;
+    properties->reverbLevel = halProperties.reverbLevel;
+    properties->reverbDelay = halProperties.reverbDelay;
+    properties->diffusion = halProperties.diffusion;
+    properties->density = halProperties.density;
+}
+
+void EnvironmentalReverbEffect::propertiesToHal(
+    const IEnvironmentalReverbEffect::AllProperties& properties, t_reverb_settings* halProperties) {
+    halProperties->roomLevel = properties.roomLevel;
+    halProperties->roomHFLevel = properties.roomHfLevel;
+    halProperties->decayTime = properties.decayTime;
+    halProperties->decayHFRatio = properties.decayHfRatio;
+    halProperties->reflectionsLevel = properties.reflectionsLevel;
+    halProperties->reflectionsDelay = properties.reflectionsDelay;
+    halProperties->reverbLevel = properties.reverbLevel;
+    halProperties->reverbDelay = properties.reverbDelay;
+    halProperties->diffusion = properties.diffusion;
+    halProperties->density = properties.density;
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> EnvironmentalReverbEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> EnvironmentalReverbEffect::setConfig(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> EnvironmentalReverbEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> EnvironmentalReverbEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> EnvironmentalReverbEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> EnvironmentalReverbEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> EnvironmentalReverbEffect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                                        setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::volumeChangeNotification(
+    const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> EnvironmentalReverbEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> EnvironmentalReverbEffect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> EnvironmentalReverbEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> EnvironmentalReverbEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::getSupportedAuxChannelsConfigs(
+    uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setAuxChannelsConfig(
+    const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> EnvironmentalReverbEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> EnvironmentalReverbEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> EnvironmentalReverbEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                                            const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> EnvironmentalReverbEffect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                                                uint32_t resultMaxSize, command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                                       const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> EnvironmentalReverbEffect::getParameter(const hidl_vec<uint8_t>& parameter,
+                                                     uint32_t valueMaxSize,
+                                                     getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::getSupportedConfigsForFeature(
+    uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+    getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::getCurrentConfigForFeature(
+    uint32_t featureId, uint32_t configSize, getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setCurrentConfigForFeature(
+    uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> EnvironmentalReverbEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEnvironmentalReverbEffect
+// follow.
+Return<Result> EnvironmentalReverbEffect::setBypass(bool bypass) {
+    return mEffect->setParam(REVERB_PARAM_BYPASS, bypass);
+}
+
+Return<void> EnvironmentalReverbEffect::getBypass(getBypass_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_BYPASS, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setRoomLevel(int16_t roomLevel) {
+    return mEffect->setParam(REVERB_PARAM_ROOM_LEVEL, roomLevel);
+}
+
+Return<void> EnvironmentalReverbEffect::getRoomLevel(getRoomLevel_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_ROOM_LEVEL, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setRoomHfLevel(int16_t roomHfLevel) {
+    return mEffect->setParam(REVERB_PARAM_ROOM_HF_LEVEL, roomHfLevel);
+}
+
+Return<void> EnvironmentalReverbEffect::getRoomHfLevel(getRoomHfLevel_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_ROOM_HF_LEVEL, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setDecayTime(uint32_t decayTime) {
+    return mEffect->setParam(REVERB_PARAM_DECAY_TIME, decayTime);
+}
+
+Return<void> EnvironmentalReverbEffect::getDecayTime(getDecayTime_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_DECAY_TIME, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setDecayHfRatio(int16_t decayHfRatio) {
+    return mEffect->setParam(REVERB_PARAM_DECAY_HF_RATIO, decayHfRatio);
+}
+
+Return<void> EnvironmentalReverbEffect::getDecayHfRatio(getDecayHfRatio_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_DECAY_HF_RATIO, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setReflectionsLevel(int16_t reflectionsLevel) {
+    return mEffect->setParam(REVERB_PARAM_REFLECTIONS_LEVEL, reflectionsLevel);
+}
+
+Return<void> EnvironmentalReverbEffect::getReflectionsLevel(getReflectionsLevel_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_REFLECTIONS_LEVEL, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setReflectionsDelay(uint32_t reflectionsDelay) {
+    return mEffect->setParam(REVERB_PARAM_REFLECTIONS_DELAY, reflectionsDelay);
+}
+
+Return<void> EnvironmentalReverbEffect::getReflectionsDelay(getReflectionsDelay_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_REFLECTIONS_DELAY, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setReverbLevel(int16_t reverbLevel) {
+    return mEffect->setParam(REVERB_PARAM_REVERB_LEVEL, reverbLevel);
+}
+
+Return<void> EnvironmentalReverbEffect::getReverbLevel(getReverbLevel_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_REVERB_LEVEL, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setReverbDelay(uint32_t reverbDelay) {
+    return mEffect->setParam(REVERB_PARAM_REVERB_DELAY, reverbDelay);
+}
+
+Return<void> EnvironmentalReverbEffect::getReverbDelay(getReverbDelay_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_REVERB_DELAY, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setDiffusion(int16_t diffusion) {
+    return mEffect->setParam(REVERB_PARAM_DIFFUSION, diffusion);
+}
+
+Return<void> EnvironmentalReverbEffect::getDiffusion(getDiffusion_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_DIFFUSION, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setDensity(int16_t density) {
+    return mEffect->setParam(REVERB_PARAM_DENSITY, density);
+}
+
+Return<void> EnvironmentalReverbEffect::getDensity(getDensity_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_DENSITY, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setAllProperties(
+    const IEnvironmentalReverbEffect::AllProperties& properties) {
+    t_reverb_settings halProperties;
+    propertiesToHal(properties, &halProperties);
+    return mEffect->setParam(REVERB_PARAM_PROPERTIES, halProperties);
+}
+
+Return<void> EnvironmentalReverbEffect::getAllProperties(getAllProperties_cb _hidl_cb) {
+    t_reverb_settings halProperties;
+    Result retval = mEffect->getParam(REVERB_PARAM_PROPERTIES, halProperties);
+    AllProperties properties;
+    propertiesFromHal(halProperties, &properties);
+    _hidl_cb(retval, properties);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.h
new file mode 100644
index 0000000..c2b8ef8
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.h
@@ -0,0 +1,129 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <vector>
+
+#include <system/audio_effects/effect_equalizer.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMode;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::AudioBuffer;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectDescriptor;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectOffloadParameter;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEqualizerEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct EqualizerEffect : public IEqualizerEffect {
+    explicit EqualizerEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEqualizerEffect follow.
+    Return<void> getNumBands(getNumBands_cb _hidl_cb) override;
+    Return<void> getLevelRange(getLevelRange_cb _hidl_cb) override;
+    Return<Result> setBandLevel(uint16_t band, int16_t level) override;
+    Return<void> getBandLevel(uint16_t band, getBandLevel_cb _hidl_cb) override;
+    Return<void> getBandCenterFrequency(uint16_t band, getBandCenterFrequency_cb _hidl_cb) override;
+    Return<void> getBandFrequencyRange(uint16_t band, getBandFrequencyRange_cb _hidl_cb) override;
+    Return<void> getBandForFrequency(uint32_t freq, getBandForFrequency_cb _hidl_cb) override;
+    Return<void> getPresetNames(getPresetNames_cb _hidl_cb) override;
+    Return<Result> setCurrentPreset(uint16_t preset) override;
+    Return<void> getCurrentPreset(getCurrentPreset_cb _hidl_cb) override;
+    Return<Result> setAllProperties(const IEqualizerEffect::AllProperties& properties) override;
+    Return<void> getAllProperties(getAllProperties_cb _hidl_cb) override;
+
+   private:
+    sp<Effect> mEffect;
+
+    virtual ~EqualizerEffect();
+
+    void propertiesFromHal(const t_equalizer_settings& halProperties,
+                           IEqualizerEffect::AllProperties* properties);
+    std::vector<uint8_t> propertiesToHal(const IEqualizerEffect::AllProperties& properties,
+                                         t_equalizer_settings** halProperties);
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.impl.h
new file mode 100644
index 0000000..78485e4
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.impl.h
@@ -0,0 +1,290 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <memory.h>
+
+#include <android/log.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+EqualizerEffect::EqualizerEffect(effect_handle_t handle) : mEffect(new Effect(handle)) {}
+
+EqualizerEffect::~EqualizerEffect() {}
+
+void EqualizerEffect::propertiesFromHal(const t_equalizer_settings& halProperties,
+                                        IEqualizerEffect::AllProperties* properties) {
+    properties->curPreset = halProperties.curPreset;
+    // t_equalizer_settings incorrectly defines bandLevels as uint16_t,
+    // whereas the actual type of values used by effects is int16_t.
+    const int16_t* signedBandLevels =
+        reinterpret_cast<const int16_t*>(&halProperties.bandLevels[0]);
+    properties->bandLevels.setToExternal(const_cast<int16_t*>(signedBandLevels),
+                                         halProperties.numBands);
+}
+
+std::vector<uint8_t> EqualizerEffect::propertiesToHal(
+    const IEqualizerEffect::AllProperties& properties, t_equalizer_settings** halProperties) {
+    size_t bandsSize = properties.bandLevels.size() * sizeof(uint16_t);
+    std::vector<uint8_t> halBuffer(sizeof(t_equalizer_settings) + bandsSize, 0);
+    *halProperties = reinterpret_cast<t_equalizer_settings*>(&halBuffer[0]);
+    (*halProperties)->curPreset = properties.curPreset;
+    (*halProperties)->numBands = properties.bandLevels.size();
+    memcpy((*halProperties)->bandLevels, &properties.bandLevels[0], bandsSize);
+    return halBuffer;
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> EqualizerEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> EqualizerEffect::setConfig(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> EqualizerEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> EqualizerEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> EqualizerEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> EqualizerEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> EqualizerEffect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                              setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> EqualizerEffect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> EqualizerEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> EqualizerEffect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> EqualizerEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> EqualizerEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> EqualizerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> EqualizerEffect::getSupportedAuxChannelsConfigs(
+    uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> EqualizerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> EqualizerEffect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> EqualizerEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> EqualizerEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> EqualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> EqualizerEffect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> EqualizerEffect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                                  const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> EqualizerEffect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                                      uint32_t resultMaxSize, command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> EqualizerEffect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                             const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> EqualizerEffect::getParameter(const hidl_vec<uint8_t>& parameter,
+                                           uint32_t valueMaxSize, getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> EqualizerEffect::getSupportedConfigsForFeature(
+    uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+    getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> EqualizerEffect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                                         getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> EqualizerEffect::setCurrentConfigForFeature(uint32_t featureId,
+                                                           const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> EqualizerEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEqualizerEffect follow.
+Return<void> EqualizerEffect::getNumBands(getNumBands_cb _hidl_cb) {
+    return mEffect->getIntegerParam(EQ_PARAM_NUM_BANDS, _hidl_cb);
+}
+
+Return<void> EqualizerEffect::getLevelRange(getLevelRange_cb _hidl_cb) {
+    int16_t halLevels[2] = {0, 0};
+    Result retval = mEffect->getParam(EQ_PARAM_LEVEL_RANGE, halLevels);
+    _hidl_cb(retval, halLevels[0], halLevels[1]);
+    return Void();
+}
+
+Return<Result> EqualizerEffect::setBandLevel(uint16_t band, int16_t level) {
+    return mEffect->setParam(EQ_PARAM_BAND_LEVEL, band, level);
+}
+
+Return<void> EqualizerEffect::getBandLevel(uint16_t band, getBandLevel_cb _hidl_cb) {
+    int16_t halLevel = 0;
+    Result retval = mEffect->getParam(EQ_PARAM_BAND_LEVEL, band, halLevel);
+    _hidl_cb(retval, halLevel);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getBandCenterFrequency(uint16_t band,
+                                                     getBandCenterFrequency_cb _hidl_cb) {
+    uint32_t halFreq = 0;
+    Result retval = mEffect->getParam(EQ_PARAM_CENTER_FREQ, band, halFreq);
+    _hidl_cb(retval, halFreq);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getBandFrequencyRange(uint16_t band,
+                                                    getBandFrequencyRange_cb _hidl_cb) {
+    uint32_t halFreqs[2] = {0, 0};
+    Result retval = mEffect->getParam(EQ_PARAM_BAND_FREQ_RANGE, band, halFreqs);
+    _hidl_cb(retval, halFreqs[0], halFreqs[1]);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getBandForFrequency(uint32_t freq, getBandForFrequency_cb _hidl_cb) {
+    uint16_t halBand = 0;
+    Result retval = mEffect->getParam(EQ_PARAM_GET_BAND, freq, halBand);
+    _hidl_cb(retval, halBand);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getPresetNames(getPresetNames_cb _hidl_cb) {
+    uint16_t halPresetCount = 0;
+    Result retval = mEffect->getParam(EQ_PARAM_GET_NUM_OF_PRESETS, halPresetCount);
+    hidl_vec<hidl_string> presetNames;
+    if (retval == Result::OK) {
+        presetNames.resize(halPresetCount);
+        for (uint16_t i = 0; i < halPresetCount; ++i) {
+            char halPresetName[EFFECT_STRING_LEN_MAX];
+            retval = mEffect->getParam(EQ_PARAM_GET_PRESET_NAME, i, halPresetName);
+            if (retval == Result::OK) {
+                presetNames[i] = halPresetName;
+            } else {
+                presetNames.resize(i);
+            }
+        }
+    }
+    _hidl_cb(retval, presetNames);
+    return Void();
+}
+
+Return<Result> EqualizerEffect::setCurrentPreset(uint16_t preset) {
+    return mEffect->setParam(EQ_PARAM_CUR_PRESET, preset);
+}
+
+Return<void> EqualizerEffect::getCurrentPreset(getCurrentPreset_cb _hidl_cb) {
+    return mEffect->getIntegerParam(EQ_PARAM_CUR_PRESET, _hidl_cb);
+}
+
+Return<Result> EqualizerEffect::setAllProperties(
+    const IEqualizerEffect::AllProperties& properties) {
+    t_equalizer_settings* halPropertiesPtr = nullptr;
+    std::vector<uint8_t> halBuffer = propertiesToHal(properties, &halPropertiesPtr);
+    uint32_t paramId = EQ_PARAM_PROPERTIES;
+    return mEffect->setParameterImpl(sizeof(paramId), &paramId, halBuffer.size(), halPropertiesPtr);
+}
+
+Return<void> EqualizerEffect::getAllProperties(getAllProperties_cb _hidl_cb) {
+    uint16_t numBands = 0;
+    Result retval = mEffect->getParam(EQ_PARAM_NUM_BANDS, numBands);
+    AllProperties properties;
+    if (retval != Result::OK) {
+        _hidl_cb(retval, properties);
+        return Void();
+    }
+    size_t valueSize = sizeof(t_equalizer_settings) + sizeof(int16_t) * numBands;
+    uint32_t paramId = EQ_PARAM_PROPERTIES;
+    retval = mEffect->getParameterImpl(
+        sizeof(paramId), &paramId, valueSize, [&](uint32_t, const void* valueData) {
+            const t_equalizer_settings* halProperties =
+                reinterpret_cast<const t_equalizer_settings*>(valueData);
+            propertiesFromHal(*halProperties, &properties);
+        });
+    _hidl_cb(retval, properties);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.h
new file mode 100644
index 0000000..e4f1bd5
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.h
@@ -0,0 +1,111 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMode;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::AudioBuffer;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectDescriptor;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectOffloadParameter;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::ILoudnessEnhancerEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct LoudnessEnhancerEffect : public ILoudnessEnhancerEffect {
+    explicit LoudnessEnhancerEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::ILoudnessEnhancerEffect
+    // follow.
+    Return<Result> setTargetGain(int32_t targetGainMb) override;
+    Return<void> getTargetGain(getTargetGain_cb _hidl_cb) override;
+
+   private:
+    sp<Effect> mEffect;
+
+    virtual ~LoudnessEnhancerEffect();
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.impl.h
new file mode 100644
index 0000000..3f4f379
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.impl.h
@@ -0,0 +1,187 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <system/audio_effects/effect_loudnessenhancer.h>
+
+#include <android/log.h>
+#include <system/audio_effects/effect_aec.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+LoudnessEnhancerEffect::LoudnessEnhancerEffect(effect_handle_t handle)
+    : mEffect(new Effect(handle)) {}
+
+LoudnessEnhancerEffect::~LoudnessEnhancerEffect() {}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> LoudnessEnhancerEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> LoudnessEnhancerEffect::setConfig(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> LoudnessEnhancerEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> LoudnessEnhancerEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> LoudnessEnhancerEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> LoudnessEnhancerEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> LoudnessEnhancerEffect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                                     setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> LoudnessEnhancerEffect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> LoudnessEnhancerEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> LoudnessEnhancerEffect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> LoudnessEnhancerEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> LoudnessEnhancerEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::getSupportedAuxChannelsConfigs(
+    uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> LoudnessEnhancerEffect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> LoudnessEnhancerEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> LoudnessEnhancerEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> LoudnessEnhancerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> LoudnessEnhancerEffect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                                         const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> LoudnessEnhancerEffect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                                             uint32_t resultMaxSize, command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> LoudnessEnhancerEffect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                                    const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> LoudnessEnhancerEffect::getParameter(const hidl_vec<uint8_t>& parameter,
+                                                  uint32_t valueMaxSize, getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::getSupportedConfigsForFeature(
+    uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+    getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::getCurrentConfigForFeature(
+    uint32_t featureId, uint32_t configSize, getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> LoudnessEnhancerEffect::setCurrentConfigForFeature(
+    uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> LoudnessEnhancerEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::ILoudnessEnhancerEffect
+// follow.
+Return<Result> LoudnessEnhancerEffect::setTargetGain(int32_t targetGainMb) {
+    return mEffect->setParam(LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB, targetGainMb);
+}
+
+Return<void> LoudnessEnhancerEffect::getTargetGain(getTargetGain_cb _hidl_cb) {
+    // AOSP Loudness Enhancer expects the size of the request to not include the
+    // size of the parameter.
+    uint32_t paramId = LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB;
+    uint32_t targetGainMb = 0;
+    Result retval = mEffect->getParameterImpl(
+        sizeof(paramId), &paramId, 0, sizeof(targetGainMb), [&](uint32_t, const void* valueData) {
+            memcpy(&targetGainMb, valueData, sizeof(targetGainMb));
+        });
+    _hidl_cb(retval, targetGainMb);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.h
new file mode 100644
index 0000000..7b64ba0
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.h
@@ -0,0 +1,123 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <system/audio_effects/effect_ns.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMode;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::AudioBuffer;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectDescriptor;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectOffloadParameter;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::INoiseSuppressionEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct NoiseSuppressionEffect : public INoiseSuppressionEffect {
+    explicit NoiseSuppressionEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::INoiseSuppressionEffect
+    // follow.
+    Return<Result> setSuppressionLevel(INoiseSuppressionEffect::Level level) override;
+    Return<void> getSuppressionLevel(getSuppressionLevel_cb _hidl_cb) override;
+    Return<Result> setSuppressionType(INoiseSuppressionEffect::Type type) override;
+    Return<void> getSuppressionType(getSuppressionType_cb _hidl_cb) override;
+    Return<Result> setAllProperties(
+        const INoiseSuppressionEffect::AllProperties& properties) override;
+    Return<void> getAllProperties(getAllProperties_cb _hidl_cb) override;
+
+   private:
+    sp<Effect> mEffect;
+
+    virtual ~NoiseSuppressionEffect();
+
+    void propertiesFromHal(const t_ns_settings& halProperties,
+                           INoiseSuppressionEffect::AllProperties* properties);
+    void propertiesToHal(const INoiseSuppressionEffect::AllProperties& properties,
+                         t_ns_settings* halProperties);
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.impl.h
new file mode 100644
index 0000000..e5fc454
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.impl.h
@@ -0,0 +1,217 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <android/log.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+NoiseSuppressionEffect::NoiseSuppressionEffect(effect_handle_t handle)
+    : mEffect(new Effect(handle)) {}
+
+NoiseSuppressionEffect::~NoiseSuppressionEffect() {}
+
+void NoiseSuppressionEffect::propertiesFromHal(const t_ns_settings& halProperties,
+                                               INoiseSuppressionEffect::AllProperties* properties) {
+    properties->level = Level(halProperties.level);
+    properties->type = Type(halProperties.type);
+}
+
+void NoiseSuppressionEffect::propertiesToHal(
+    const INoiseSuppressionEffect::AllProperties& properties, t_ns_settings* halProperties) {
+    halProperties->level = static_cast<uint32_t>(properties.level);
+    halProperties->type = static_cast<uint32_t>(properties.type);
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> NoiseSuppressionEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> NoiseSuppressionEffect::setConfig(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> NoiseSuppressionEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> NoiseSuppressionEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> NoiseSuppressionEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> NoiseSuppressionEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> NoiseSuppressionEffect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                                     setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> NoiseSuppressionEffect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> NoiseSuppressionEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> NoiseSuppressionEffect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> NoiseSuppressionEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> NoiseSuppressionEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::getSupportedAuxChannelsConfigs(
+    uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> NoiseSuppressionEffect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> NoiseSuppressionEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> NoiseSuppressionEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> NoiseSuppressionEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> NoiseSuppressionEffect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                                         const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> NoiseSuppressionEffect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                                             uint32_t resultMaxSize, command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> NoiseSuppressionEffect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                                    const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> NoiseSuppressionEffect::getParameter(const hidl_vec<uint8_t>& parameter,
+                                                  uint32_t valueMaxSize, getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::getSupportedConfigsForFeature(
+    uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+    getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::getCurrentConfigForFeature(
+    uint32_t featureId, uint32_t configSize, getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> NoiseSuppressionEffect::setCurrentConfigForFeature(
+    uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> NoiseSuppressionEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::INoiseSuppressionEffect
+// follow.
+Return<Result> NoiseSuppressionEffect::setSuppressionLevel(INoiseSuppressionEffect::Level level) {
+    return mEffect->setParam(NS_PARAM_LEVEL, static_cast<int32_t>(level));
+}
+
+Return<void> NoiseSuppressionEffect::getSuppressionLevel(getSuppressionLevel_cb _hidl_cb) {
+    int32_t halLevel = 0;
+    Result retval = mEffect->getParam(NS_PARAM_LEVEL, halLevel);
+    _hidl_cb(retval, Level(halLevel));
+    return Void();
+}
+
+Return<Result> NoiseSuppressionEffect::setSuppressionType(INoiseSuppressionEffect::Type type) {
+    return mEffect->setParam(NS_PARAM_TYPE, static_cast<int32_t>(type));
+}
+
+Return<void> NoiseSuppressionEffect::getSuppressionType(getSuppressionType_cb _hidl_cb) {
+    int32_t halType = 0;
+    Result retval = mEffect->getParam(NS_PARAM_TYPE, halType);
+    _hidl_cb(retval, Type(halType));
+    return Void();
+}
+
+Return<Result> NoiseSuppressionEffect::setAllProperties(
+    const INoiseSuppressionEffect::AllProperties& properties) {
+    t_ns_settings halProperties;
+    propertiesToHal(properties, &halProperties);
+    return mEffect->setParam(NS_PARAM_PROPERTIES, halProperties);
+}
+
+Return<void> NoiseSuppressionEffect::getAllProperties(getAllProperties_cb _hidl_cb) {
+    t_ns_settings halProperties;
+    Result retval = mEffect->getParam(NS_PARAM_PROPERTIES, halProperties);
+    AllProperties properties;
+    propertiesFromHal(halProperties, &properties);
+    _hidl_cb(retval, properties);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.h
new file mode 100644
index 0000000..3114acd
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.h
@@ -0,0 +1,111 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMode;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::AudioBuffer;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectDescriptor;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectOffloadParameter;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IPresetReverbEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct PresetReverbEffect : public IPresetReverbEffect {
+    explicit PresetReverbEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IPresetReverbEffect
+    // follow.
+    Return<Result> setPreset(IPresetReverbEffect::Preset preset) override;
+    Return<void> getPreset(getPreset_cb _hidl_cb) override;
+
+   private:
+    sp<Effect> mEffect;
+
+    virtual ~PresetReverbEffect();
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.impl.h
new file mode 100644
index 0000000..32198d5
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.impl.h
@@ -0,0 +1,177 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <android/log.h>
+#include <system/audio_effects/effect_presetreverb.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+PresetReverbEffect::PresetReverbEffect(effect_handle_t handle) : mEffect(new Effect(handle)) {}
+
+PresetReverbEffect::~PresetReverbEffect() {}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> PresetReverbEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> PresetReverbEffect::setConfig(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> PresetReverbEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> PresetReverbEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> PresetReverbEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> PresetReverbEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> PresetReverbEffect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                                 setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> PresetReverbEffect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> PresetReverbEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> PresetReverbEffect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> PresetReverbEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> PresetReverbEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> PresetReverbEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> PresetReverbEffect::getSupportedAuxChannelsConfigs(
+    uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> PresetReverbEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> PresetReverbEffect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> PresetReverbEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> PresetReverbEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> PresetReverbEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> PresetReverbEffect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> PresetReverbEffect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                                     const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> PresetReverbEffect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                                         uint32_t resultMaxSize, command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> PresetReverbEffect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                                const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> PresetReverbEffect::getParameter(const hidl_vec<uint8_t>& parameter,
+                                              uint32_t valueMaxSize, getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> PresetReverbEffect::getSupportedConfigsForFeature(
+    uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+    getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> PresetReverbEffect::getCurrentConfigForFeature(
+    uint32_t featureId, uint32_t configSize, getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> PresetReverbEffect::setCurrentConfigForFeature(uint32_t featureId,
+                                                              const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> PresetReverbEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IPresetReverbEffect follow.
+Return<Result> PresetReverbEffect::setPreset(IPresetReverbEffect::Preset preset) {
+    return mEffect->setParam(REVERB_PARAM_PRESET, static_cast<t_reverb_presets>(preset));
+}
+
+Return<void> PresetReverbEffect::getPreset(getPreset_cb _hidl_cb) {
+    t_reverb_presets halPreset = REVERB_PRESET_NONE;
+    Result retval = mEffect->getParam(REVERB_PARAM_PRESET, halPreset);
+    _hidl_cb(retval, Preset(halPreset));
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.h
new file mode 100644
index 0000000..3715894
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.h
@@ -0,0 +1,120 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMode;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::AudioBuffer;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectDescriptor;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectOffloadParameter;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IVirtualizerEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct VirtualizerEffect : public IVirtualizerEffect {
+    explicit VirtualizerEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IVirtualizerEffect
+    // follow.
+    Return<bool> isStrengthSupported() override;
+    Return<Result> setStrength(uint16_t strength) override;
+    Return<void> getStrength(getStrength_cb _hidl_cb) override;
+    Return<void> getVirtualSpeakerAngles(AudioChannelMask mask, AudioDevice device,
+                                         getVirtualSpeakerAngles_cb _hidl_cb) override;
+    Return<Result> forceVirtualizationMode(AudioDevice device) override;
+    Return<void> getVirtualizationMode(getVirtualizationMode_cb _hidl_cb) override;
+
+   private:
+    sp<Effect> mEffect;
+
+    virtual ~VirtualizerEffect();
+
+    void speakerAnglesFromHal(const int32_t* halAngles, uint32_t channelCount,
+                              hidl_vec<SpeakerAngle>& speakerAngles);
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.impl.h
new file mode 100644
index 0000000..6fb8005
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.impl.h
@@ -0,0 +1,228 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <memory.h>
+
+#include <android/log.h>
+#include <system/audio_effects/effect_virtualizer.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+VirtualizerEffect::VirtualizerEffect(effect_handle_t handle) : mEffect(new Effect(handle)) {}
+
+VirtualizerEffect::~VirtualizerEffect() {}
+
+void VirtualizerEffect::speakerAnglesFromHal(const int32_t* halAngles, uint32_t channelCount,
+                                             hidl_vec<SpeakerAngle>& speakerAngles) {
+    speakerAngles.resize(channelCount);
+    for (uint32_t i = 0; i < channelCount; ++i) {
+        speakerAngles[i].mask = AudioChannelMask(*halAngles++);
+        speakerAngles[i].azimuth = *halAngles++;
+        speakerAngles[i].elevation = *halAngles++;
+    }
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> VirtualizerEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> VirtualizerEffect::setConfig(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> VirtualizerEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> VirtualizerEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> VirtualizerEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> VirtualizerEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> VirtualizerEffect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                                setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> VirtualizerEffect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> VirtualizerEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> VirtualizerEffect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> VirtualizerEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> VirtualizerEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getSupportedAuxChannelsConfigs(
+    uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> VirtualizerEffect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> VirtualizerEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> VirtualizerEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> VirtualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> VirtualizerEffect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> VirtualizerEffect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                                    const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> VirtualizerEffect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                                        uint32_t resultMaxSize, command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> VirtualizerEffect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                               const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> VirtualizerEffect::getParameter(const hidl_vec<uint8_t>& parameter,
+                                             uint32_t valueMaxSize, getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getSupportedConfigsForFeature(
+    uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+    getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                                           getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> VirtualizerEffect::setCurrentConfigForFeature(uint32_t featureId,
+                                                             const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> VirtualizerEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IVirtualizerEffect follow.
+Return<bool> VirtualizerEffect::isStrengthSupported() {
+    bool halSupported = false;
+    mEffect->getParam(VIRTUALIZER_PARAM_STRENGTH_SUPPORTED, halSupported);
+    return halSupported;
+}
+
+Return<Result> VirtualizerEffect::setStrength(uint16_t strength) {
+    return mEffect->setParam(VIRTUALIZER_PARAM_STRENGTH, strength);
+}
+
+Return<void> VirtualizerEffect::getStrength(getStrength_cb _hidl_cb) {
+    return mEffect->getIntegerParam(VIRTUALIZER_PARAM_STRENGTH, _hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getVirtualSpeakerAngles(AudioChannelMask mask, AudioDevice device,
+                                                        getVirtualSpeakerAngles_cb _hidl_cb) {
+    uint32_t channelCount =
+        audio_channel_count_from_out_mask(static_cast<audio_channel_mask_t>(mask));
+    size_t halSpeakerAnglesSize = sizeof(int32_t) * 3 * channelCount;
+    uint32_t halParam[3] = {VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES,
+                            static_cast<audio_channel_mask_t>(mask),
+                            static_cast<audio_devices_t>(device)};
+    hidl_vec<SpeakerAngle> speakerAngles;
+    Result retval = mEffect->getParameterImpl(
+        sizeof(halParam), halParam, halSpeakerAnglesSize,
+        [&](uint32_t valueSize, const void* valueData) {
+            if (valueSize > halSpeakerAnglesSize) {
+                valueSize = halSpeakerAnglesSize;
+            } else if (valueSize < halSpeakerAnglesSize) {
+                channelCount = valueSize / (sizeof(int32_t) * 3);
+            }
+            speakerAnglesFromHal(reinterpret_cast<const int32_t*>(valueData), channelCount,
+                                 speakerAngles);
+        });
+    _hidl_cb(retval, speakerAngles);
+    return Void();
+}
+
+Return<Result> VirtualizerEffect::forceVirtualizationMode(AudioDevice device) {
+    return mEffect->setParam(VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE,
+                             static_cast<audio_devices_t>(device));
+}
+
+Return<void> VirtualizerEffect::getVirtualizationMode(getVirtualizationMode_cb _hidl_cb) {
+    uint32_t halMode = 0;
+    Result retval = mEffect->getParam(VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE, halMode);
+    _hidl_cb(retval, AudioDevice(halMode));
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.h
new file mode 100644
index 0000000..8050221
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.h
@@ -0,0 +1,120 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMode;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::AudioBuffer;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectConfig;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectDescriptor;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectOffloadParameter;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IVisualizerEffect;
+using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct VisualizerEffect : public IVisualizerEffect {
+    explicit VisualizerEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+    Return<Result> init() override;
+    Return<Result> setConfig(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> reset() override;
+    Return<Result> enable() override;
+    Return<Result> disable() override;
+    Return<Result> setDevice(AudioDevice device) override;
+    Return<void> setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                 setAndGetVolume_cb _hidl_cb) override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes) override;
+    Return<Result> setAudioMode(AudioMode mode) override;
+    Return<Result> setConfigReverse(
+        const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    Return<void> getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config) override;
+    Return<Result> setAudioSource(AudioSource source) override;
+    Return<Result> offload(const EffectOffloadParameter& param) override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+    Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                     const AudioBuffer& outBuffer) override;
+    Return<void> command(uint32_t commandId, const hidl_vec<uint8_t>& data, uint32_t resultMaxSize,
+                         command_cb _hidl_cb) override;
+    Return<Result> setParameter(const hidl_vec<uint8_t>& parameter,
+                                const hidl_vec<uint8_t>& value) override;
+    Return<void> getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                              getParameter_cb _hidl_cb) override;
+    Return<void> getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                               uint32_t configSize,
+                                               getSupportedConfigsForFeature_cb _hidl_cb) override;
+    Return<void> getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                            getCurrentConfigForFeature_cb _hidl_cb) override;
+    Return<Result> setCurrentConfigForFeature(uint32_t featureId,
+                                              const hidl_vec<uint8_t>& configData) override;
+    Return<Result> close() override;
+
+    // Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IVisualizerEffect follow.
+    Return<Result> setCaptureSize(uint16_t captureSize) override;
+    Return<void> getCaptureSize(getCaptureSize_cb _hidl_cb) override;
+    Return<Result> setScalingMode(IVisualizerEffect::ScalingMode scalingMode) override;
+    Return<void> getScalingMode(getScalingMode_cb _hidl_cb) override;
+    Return<Result> setLatency(uint32_t latencyMs) override;
+    Return<void> getLatency(getLatency_cb _hidl_cb) override;
+    Return<Result> setMeasurementMode(IVisualizerEffect::MeasurementMode measurementMode) override;
+    Return<void> getMeasurementMode(getMeasurementMode_cb _hidl_cb) override;
+    Return<void> capture(capture_cb _hidl_cb) override;
+    Return<void> measure(measure_cb _hidl_cb) override;
+
+   private:
+    sp<Effect> mEffect;
+    uint16_t mCaptureSize;
+    MeasurementMode mMeasurementMode;
+
+    virtual ~VisualizerEffect();
+};
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.impl.h
new file mode 100644
index 0000000..0351453
--- /dev/null
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.impl.h
@@ -0,0 +1,252 @@
+/*
+ * 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 <common/all-versions/IncludeGuard.h>
+
+#include <android/log.h>
+#include <system/audio_effects/effect_visualizer.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace AUDIO_HAL_VERSION {
+namespace implementation {
+
+VisualizerEffect::VisualizerEffect(effect_handle_t handle)
+    : mEffect(new Effect(handle)), mCaptureSize(0), mMeasurementMode(MeasurementMode::NONE) {}
+
+VisualizerEffect::~VisualizerEffect() {}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IEffect follow.
+Return<Result> VisualizerEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> VisualizerEffect::setConfig(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> VisualizerEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> VisualizerEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> VisualizerEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> VisualizerEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> VisualizerEffect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                               setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> VisualizerEffect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> VisualizerEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> VisualizerEffect::setConfigReverse(
+    const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+    const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> VisualizerEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> VisualizerEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> VisualizerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> VisualizerEffect::getSupportedAuxChannelsConfigs(
+    uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> VisualizerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> VisualizerEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> VisualizerEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> VisualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> VisualizerEffect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                                   const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> VisualizerEffect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                                       uint32_t resultMaxSize, command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                              const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> VisualizerEffect::getParameter(const hidl_vec<uint8_t>& parameter,
+                                            uint32_t valueMaxSize, getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> VisualizerEffect::getSupportedConfigsForFeature(
+    uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+    getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> VisualizerEffect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                                          getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setCurrentConfigForFeature(uint32_t featureId,
+                                                            const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> VisualizerEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::AUDIO_HAL_VERSION::IVisualizerEffect follow.
+Return<Result> VisualizerEffect::setCaptureSize(uint16_t captureSize) {
+    Result retval = mEffect->setParam(VISUALIZER_PARAM_CAPTURE_SIZE, captureSize);
+    if (retval == Result::OK) {
+        mCaptureSize = captureSize;
+    }
+    return retval;
+}
+
+Return<void> VisualizerEffect::getCaptureSize(getCaptureSize_cb _hidl_cb) {
+    return mEffect->getIntegerParam(VISUALIZER_PARAM_CAPTURE_SIZE, _hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setScalingMode(IVisualizerEffect::ScalingMode scalingMode) {
+    return mEffect->setParam(VISUALIZER_PARAM_SCALING_MODE, static_cast<int32_t>(scalingMode));
+}
+
+Return<void> VisualizerEffect::getScalingMode(getScalingMode_cb _hidl_cb) {
+    int32_t halMode;
+    Result retval = mEffect->getParam(VISUALIZER_PARAM_SCALING_MODE, halMode);
+    _hidl_cb(retval, ScalingMode(halMode));
+    return Void();
+}
+
+Return<Result> VisualizerEffect::setLatency(uint32_t latencyMs) {
+    return mEffect->setParam(VISUALIZER_PARAM_LATENCY, latencyMs);
+}
+
+Return<void> VisualizerEffect::getLatency(getLatency_cb _hidl_cb) {
+    return mEffect->getIntegerParam(VISUALIZER_PARAM_LATENCY, _hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setMeasurementMode(
+    IVisualizerEffect::MeasurementMode measurementMode) {
+    Result retval =
+        mEffect->setParam(VISUALIZER_PARAM_MEASUREMENT_MODE, static_cast<int32_t>(measurementMode));
+    if (retval == Result::OK) {
+        mMeasurementMode = measurementMode;
+    }
+    return retval;
+}
+
+Return<void> VisualizerEffect::getMeasurementMode(getMeasurementMode_cb _hidl_cb) {
+    int32_t halMode;
+    Result retval = mEffect->getParam(VISUALIZER_PARAM_MEASUREMENT_MODE, halMode);
+    _hidl_cb(retval, MeasurementMode(halMode));
+    return Void();
+}
+
+Return<void> VisualizerEffect::capture(capture_cb _hidl_cb) {
+    if (mCaptureSize == 0) {
+        _hidl_cb(Result::NOT_INITIALIZED, hidl_vec<uint8_t>());
+        return Void();
+    }
+    uint32_t halCaptureSize = mCaptureSize;
+    uint8_t halCapture[mCaptureSize];
+    Result retval = mEffect->sendCommandReturningData(VISUALIZER_CMD_CAPTURE, "VISUALIZER_CAPTURE",
+                                                      &halCaptureSize, halCapture);
+    hidl_vec<uint8_t> capture;
+    if (retval == Result::OK) {
+        capture.setToExternal(&halCapture[0], halCaptureSize);
+    }
+    _hidl_cb(retval, capture);
+    return Void();
+}
+
+Return<void> VisualizerEffect::measure(measure_cb _hidl_cb) {
+    if (mMeasurementMode == MeasurementMode::NONE) {
+        _hidl_cb(Result::NOT_INITIALIZED, Measurement());
+        return Void();
+    }
+    int32_t halMeasurement[MEASUREMENT_COUNT];
+    uint32_t halMeasurementSize = sizeof(halMeasurement);
+    Result retval = mEffect->sendCommandReturningData(VISUALIZER_CMD_MEASURE, "VISUALIZER_MEASURE",
+                                                      &halMeasurementSize, halMeasurement);
+    Measurement measurement = {.mode = MeasurementMode::PEAK_RMS};
+    measurement.value.peakAndRms.peakMb = 0;
+    measurement.value.peakAndRms.rmsMb = 0;
+    if (retval == Result::OK) {
+        measurement.value.peakAndRms.peakMb = halMeasurement[MEASUREMENT_IDX_PEAK];
+        measurement.value.peakAndRms.rmsMb = halMeasurement[MEASUREMENT_IDX_RMS];
+    }
+    _hidl_cb(retval, measurement);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace AUDIO_HAL_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/authsecret/1.0/Android.bp b/authsecret/1.0/Android.bp
new file mode 100644
index 0000000..9cde99a
--- /dev/null
+++ b/authsecret/1.0/Android.bp
@@ -0,0 +1,17 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.authsecret@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IAuthSecret.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/authsecret/1.0/IAuthSecret.hal b/authsecret/1.0/IAuthSecret.hal
new file mode 100644
index 0000000..d2cb5da
--- /dev/null
+++ b/authsecret/1.0/IAuthSecret.hal
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 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.authsecret@1.0;
+
+/**
+ * This security HAL allows vendor components to be cryptographically tied to
+ * the primary user's credential. For example, security hardware could require
+ * proof that the credential is known before applying updates.
+ *
+ * This HAL is optional so does not require an implementation on device.
+ */
+interface IAuthSecret {
+    /**
+     * When the primary user correctly enters their credential, this method is
+     * passed a secret derived from that credential to prove that their
+     * credential is known.
+     *
+     * The first time this is called, the secret must be used to provision state
+     * that depends on the primary user's credential. The same secret is passed
+     * on each call until a factory reset after which there must be a new
+     * secret.
+     *
+     * The secret must be at lesat 16 bytes.
+     *
+     * @param secret blob derived from the primary user's credential.
+     */
+    primaryUserCredential(vec<uint8_t> secret);
+
+    /**
+     * Called from recovery during factory reset. The secret is now lost and can
+     * no longer be derived. Any data linked to the secret must be destroyed and
+     * any dependence on the secret must be removed.
+     */
+    factoryReset();
+};
diff --git a/authsecret/1.0/default/Android.bp b/authsecret/1.0/default/Android.bp
new file mode 100644
index 0000000..5c3234f
--- /dev/null
+++ b/authsecret/1.0/default/Android.bp
@@ -0,0 +1,21 @@
+cc_binary {
+    name: "android.hardware.authsecret@1.0-service",
+    init_rc: ["android.hardware.authsecret@1.0-service.rc"],
+    relative_install_path: "hw",
+    vendor: true,
+    srcs: [
+        "service.cpp",
+        "AuthSecret.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.authsecret@1.0",
+    ],
+}
diff --git a/authsecret/1.0/default/AuthSecret.cpp b/authsecret/1.0/default/AuthSecret.cpp
new file mode 100644
index 0000000..46a3ec1
--- /dev/null
+++ b/authsecret/1.0/default/AuthSecret.cpp
@@ -0,0 +1,47 @@
+#include "AuthSecret.h"
+
+namespace android {
+namespace hardware {
+namespace authsecret {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::authsecret::V1_0::IAuthSecret follow.
+Return<void> AuthSecret::primaryUserCredential(const hidl_vec<uint8_t>& secret) {
+    (void)secret;
+
+    // To create a dependency on the credential, it is recommended to derive a
+    // different value from the provided secret for each purpose e.g.
+    //
+    //     purpose1_secret = hash( "purpose1" || secret )
+    //     purpose2_secret = hash( "purpose2" || secret )
+    //
+    // The derived values can then be used as cryptographic keys or stored
+    // securely for comparison in a future call.
+    //
+    // For example, a security module might require that the credential has been
+    // entered before it applies any updates. This can be achieved by storing a
+    // derived value in the module and only applying updates when the same
+    // derived value is presented again.
+    //
+    // This implementation does nothing.
+
+    return Void();
+}
+
+Return<void> AuthSecret::factoryReset() {
+    // Clear all dependency on the secret.
+    //
+    // With the example of updating a security module, the stored value must be
+    // cleared so that the new primary user enrolled as the approver of updates.
+    //
+    // This implementation does nothing as there is no dependence on the secret.
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace authsecret
+}  // namespace hardware
+}  // namespace android
diff --git a/authsecret/1.0/default/AuthSecret.h b/authsecret/1.0/default/AuthSecret.h
new file mode 100644
index 0000000..edb49b8
--- /dev/null
+++ b/authsecret/1.0/default/AuthSecret.h
@@ -0,0 +1,36 @@
+#ifndef ANDROID_HARDWARE_AUTHSECRET_V1_0_AUTHSECRET_H
+#define ANDROID_HARDWARE_AUTHSECRET_V1_0_AUTHSECRET_H
+
+#include <android/hardware/authsecret/1.0/IAuthSecret.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace authsecret {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct AuthSecret : public IAuthSecret {
+    // Methods from ::android::hardware::authsecret::V1_0::IAuthSecret follow.
+    Return<void> primaryUserCredential(const hidl_vec<uint8_t>& secret) override;
+    Return<void> factoryReset() override;
+
+    // Methods from ::android::hidl::base::V1_0::IBase follow.
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace authsecret
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUTHSECRET_V1_0_AUTHSECRET_H
diff --git a/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc b/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc
new file mode 100644
index 0000000..e82da7e
--- /dev/null
+++ b/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.authsecret-1-0 /vendor/bin/hw/android.hardware.authsecret@1.0-service
+    class hal
+    user system
+    group system
diff --git a/authsecret/1.0/default/service.cpp b/authsecret/1.0/default/service.cpp
new file mode 100644
index 0000000..4acd16c
--- /dev/null
+++ b/authsecret/1.0/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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 "android.hardware.authsecret@1.0-service"
+
+#include <android/hardware/authsecret/1.0/IAuthSecret.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "AuthSecret.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::authsecret::V1_0::IAuthSecret;
+using android::hardware::authsecret::V1_0::implementation::AuthSecret;
+using android::sp;
+using android::status_t;
+using android::OK;
+
+int main() {
+    configureRpcThreadpool(1, true);
+
+    sp<IAuthSecret> authSecret = new AuthSecret;
+    status_t status = authSecret->registerAsService();
+    LOG_ALWAYS_FATAL_IF(status != OK, "Could not register IAuthSecret");
+
+    joinRpcThreadpool();
+    return 0;
+}
diff --git a/authsecret/1.0/vts/functional/Android.bp b/authsecret/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..de9f560
--- /dev/null
+++ b/authsecret/1.0/vts/functional/Android.bp
@@ -0,0 +1,22 @@
+//
+// Copyright (C) 2018 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: "VtsHalAuthSecretV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalAuthSecretV1_0TargetTest.cpp"],
+    static_libs: ["android.hardware.authsecret@1.0"],
+}
diff --git a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
new file mode 100644
index 0000000..b0cbd91
--- /dev/null
+++ b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 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 <android/hardware/authsecret/1.0/IAuthSecret.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::authsecret::V1_0::IAuthSecret;
+using ::android::sp;
+
+/**
+ * There is no expected behaviour that can be tested so these tests check the
+ * HAL doesn't crash with different execution orders.
+ */
+struct AuthSecretHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+    virtual void SetUp() override {
+        authsecret = ::testing::VtsHalHidlTargetTestBase::getService<IAuthSecret>();
+        ASSERT_NE(authsecret, nullptr);
+        authsecret->factoryReset();
+    }
+
+    sp<IAuthSecret> authsecret;
+};
+
+/* Provision the primary user with a secret. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredential) {
+    hidl_vec<uint8_t> secret{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+    authsecret->primaryUserCredential(secret);
+}
+
+/* Provision the primary user with a large secret. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialWithLargeSecret) {
+    hidl_vec<uint8_t> secret{89,  233, 52,  29,  130, 210, 229, 170, 124, 102, 56,  238, 198,
+                             199, 246, 152, 185, 123, 155, 215, 29,  252, 30,  70,  118, 29,
+                             149, 36,  222, 203, 163, 7,   72,  56,  247, 19,  198, 76,  71,
+                             37,  120, 201, 220, 70,  150, 18,  23,  22,  236, 57,  184, 86,
+                             190, 122, 210, 207, 74,  51,  222, 157, 74,  196, 86,  208};
+    authsecret->primaryUserCredential(secret);
+}
+
+/* Provision the primary user with a secret and pass the secret again. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndPassAgain) {
+    hidl_vec<uint8_t> secret{64, 2, 3, 0, 5, 6, 7, 172, 9, 10, 11, 255, 13, 14, 15, 83};
+    authsecret->primaryUserCredential(secret);
+    authsecret->primaryUserCredential(secret);
+}
+
+/* Provision the primary user with a secret and pass the secret again repeatedly. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndPassAgainMultipleTimes) {
+    hidl_vec<uint8_t> secret{1, 2, 34, 4, 5, 6, 7, 8, 9, 105, 11, 12, 13, 184, 15, 16};
+    authsecret->primaryUserCredential(secret);
+    constexpr int N = 5;
+    for (int i = 0; i < N; ++i) {
+        authsecret->primaryUserCredential(secret);
+    }
+}
+
+/* Factory reset before provisioning the primary user with a secret. */
+TEST_F(AuthSecretHidlTest, factoryResetWithoutProvisioningPrimaryUserCredential) {
+    authsecret->factoryReset();
+}
+
+/* Provision the primary user with a secret then factory reset. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndFactoryReset) {
+    hidl_vec<uint8_t> secret{1, 24, 124, 240, 5, 6, 7, 8, 9, 13, 11, 12, 189, 14, 195, 16};
+    authsecret->primaryUserCredential(secret);
+    authsecret->factoryReset();
+}
+
+/* Provision the primary differently after factory reset. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialDifferentlyAfterFactoryReset) {
+    {
+        hidl_vec<uint8_t> secret1{19, 0, 65, 20, 65, 12, 7, 8, 9, 13, 29, 12, 189, 32, 195, 16};
+        authsecret->primaryUserCredential(secret1);
+    }
+
+    authsecret->factoryReset();
+
+    {
+        hidl_vec<uint8_t> secret2{61, 93, 124, 240, 5, 0, 7, 201, 9, 129, 11, 12, 0, 14, 0, 16};
+        authsecret->primaryUserCredential(secret2);
+    }
+}
diff --git a/automotive/audiocontrol/1.0/Android.bp b/automotive/audiocontrol/1.0/Android.bp
new file mode 100644
index 0000000..a967049
--- /dev/null
+++ b/automotive/audiocontrol/1.0/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.automotive.audiocontrol@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IAudioControl.hal",
+        "IAudioControlCallback.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "AudioResult",
+        "ContextNumber",
+    ],
+    gen_java: true,
+}
+
diff --git a/automotive/audiocontrol/1.0/IAudioControl.hal b/automotive/audiocontrol/1.0/IAudioControl.hal
new file mode 100644
index 0000000..fe9ea8e
--- /dev/null
+++ b/automotive/audiocontrol/1.0/IAudioControl.hal
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 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.automotive.audiocontrol@1.0;
+
+import IAudioControlCallback;
+
+
+/**
+ * Interacts with the car's audio subsystem to manage audio sources and volumes
+ */
+interface IAudioControl {
+
+    /**
+     * Registers the required callback object so that we can be notified when the state
+     * of the car's audio system changes. This call must be made when the interface is
+     * initialized.
+     */
+    setCallback(IAudioControlCallback notificationObject)
+        generates (AudioResult result);
+
+
+    /**
+     * Called at startup once per context to get the mapping from ContextNumber to
+     * busAddress. This lets the car tell the framework to which physical output stream
+     * each context should be routed.
+     *
+     * For every context, a valid bus number (0 - num busses-1) must be returned. If an
+     * unrecognized contextNumber is encountered, then -1 shall be returned.
+     *
+     * Any context for which an invalid busNumber is returned must be routed to bus 0.
+     */
+    getBusForContext(uint32_t contextNumber)
+        generates (int32_t busNumber);
+
+
+    /**
+     * Control the right/left balance setting of the car speakers.
+     *
+     * This is intended to shift the speaker volume toward the right (+) or left (-) side of
+     * the car. 0.0 means "centered". +1.0 means fully right. -1.0 means fully left.
+     *
+     * A value outside the range -1 to 1 must be clamped by the implementation to the -1 to 1
+     * range.
+     */
+    oneway setBalanceTowardRight(float value);
+
+
+    /**
+     * Control the fore/aft fade setting of the car speakers.
+     *
+     * This is intended to shift the speaker volume toward the front (+) or back (-) of the car.
+     * 0.0 means "centered". +1.0 means fully forward. -1.0 means fully rearward.
+     *
+     * A value outside the range -1 to 1 must be clamped by the implementation to the -1 to 1
+     * range.
+     */
+    oneway setFadeTowardFront(float value);
+};
+
diff --git a/automotive/audiocontrol/1.0/IAudioControlCallback.hal b/automotive/audiocontrol/1.0/IAudioControlCallback.hal
new file mode 100644
index 0000000..f5c227e
--- /dev/null
+++ b/automotive/audiocontrol/1.0/IAudioControlCallback.hal
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 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.automotive.audiocontrol@1.0;
+
+
+/**
+ * Implemented on client (framework) side to receive asynchronous updates from the car.
+ */
+interface IAudioControlCallback {
+
+    /**
+     * When the HAL makes this call, any apps currently playing must be asked to
+     * temporarily suspend playback (via an AudioManager::AUDIOFOCUS_LOSS_TRANSIENT event).
+     *
+     * This is only a suggestion. Apps may be slow to react or even ignore this message
+     * entirely. Enforcement, if necessary, must be done at the AudioHAL level as the
+     * samples are delivered. In most instances, this is the way a car should ask for
+     * quiet if it needs it for some important situation, such as warning alarms or chimes.
+     */
+    oneway suggestPausePlayers();
+
+
+    /**
+     * When the HAL makes this case, any apps currently playing must be asked to stop
+     * playing (via an AudioManager::AUDIOFOCUS_LOSS event). Once stopped, the apps must
+     * not resume their playback.
+     *
+     * It should be noted that not all apps or sound sources honor this request, but this
+     * at least gives an app the chance to do the right thing.
+     * Because it premanently stops media, this call is expected to be used only rarely.
+     * Perhaps in the event of an E-call, where resuming music might be undesirable assuming
+     * the driver is now dealing with whatever the emergency is?
+     */
+    oneway suggestStopPlayers();
+
+
+    /**
+     * Receives calls from the HAL when Android should resume normal operations. If the previous
+     * action was a requestPausePlayers, then things that were paused must be told they may
+     * resume.
+     */
+    oneway resumePlayers();
+};
diff --git a/automotive/audiocontrol/1.0/default/Android.bp b/automotive/audiocontrol/1.0/default/Android.bp
new file mode 100644
index 0000000..614c58b
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/Android.bp
@@ -0,0 +1,40 @@
+// Copyright (C) 2017 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_binary {
+    name: "android.hardware.automotive.audiocontrol@1.0-service",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: [
+        "AudioControl.cpp",
+        "AudioControlCallback.cpp",
+        "service.cpp"
+    ],
+    init_rc: ["android.hardware.automotive.audiocontrol@1.0-service.rc"],
+
+    shared_libs: [
+        "android.hardware.automotive.audiocontrol@1.0",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+    ],
+
+    cflags: [
+        "-DLOG_TAG=\"AudCntrlDrv\"",
+        "-O0",
+        "-g",
+    ],
+}
diff --git a/automotive/audiocontrol/1.0/default/AudioControl.cpp b/automotive/audiocontrol/1.0/default/AudioControl.cpp
new file mode 100644
index 0000000..419225d
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/AudioControl.cpp
@@ -0,0 +1,86 @@
+#include "AudioControl.h"
+
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace audiocontrol {
+namespace V1_0 {
+namespace implementation {
+
+
+// This is the static map we're using to associate a ContextNumber with a
+// bus number from the audio_policy_configuration.xml setup.  Every valid context needs
+// to be mapped to a bus address that actually exists in the platforms configuration.
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))  // Would be nice if this were common...
+static int sContextToBusMap[] = {
+    -1,     // INVALID
+     0,     // MUSIC_CONTEXT
+     1,     // NAVIGATION_CONTEXT
+     2,     // VOICE_COMMAND_CONTEXT
+     3,     // CALL_RING_CONTEXT
+     4,     // CALL_CONTEXT
+     5,     // ALARM_CONTEXT
+     6,     // NOTIFICATION_CONTEXT
+     7,     // SYSTEM_SOUND_CONTEXT
+};
+static const unsigned sContextMapSize = ARRAY_SIZE(sContextToBusMap);
+static const unsigned sContextCount = sContextMapSize - 1;  // Less one for the INVALID entry
+static const unsigned sContextNumberMax = sContextCount;    // contextNumber is counted from 1
+
+
+AudioControl::AudioControl() {
+};
+
+
+// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControl follow.
+Return<AudioResult> AudioControl::setCallback(const sp<IAudioControlCallback>& notificationObject) {
+    // Hang onto the provided callback object for future use
+    callback = notificationObject;
+
+    return AudioResult::OK;
+}
+
+
+Return<int32_t> AudioControl::getBusForContext(uint32_t contextNumber) {
+    if (contextNumber > sContextNumberMax) {
+        ALOGE("Unexpected context number %d (max expected is %d)", contextNumber, sContextCount);
+        return -1;
+    } else {
+        return sContextToBusMap[contextNumber];
+    }
+}
+
+
+Return<void> AudioControl::setBalanceTowardRight(float value) {
+    // For completeness, lets bounds check the input...
+    if ((value > 1.0f) || (value < -1.0f)) {
+        ALOGE("Balance value out of range -1 to 1 at %0.2f", value);
+    } else {
+        // Just log in this default mock implementation
+        ALOGI("Balance set to %0.2f", value);
+    }
+    return Void();
+}
+
+
+Return<void> AudioControl::setFadeTowardFront(float value) {
+    // For completeness, lets bounds check the input...
+    if ((value > 1.0f) || (value < -1.0f)) {
+        ALOGE("Fader value out of range -1 to 1 at %0.2f", value);
+    } else {
+        // Just log in this default mock implementation
+        ALOGI("Fader set to %0.2f", value);
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace audiocontrol
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/audiocontrol/1.0/default/AudioControl.h b/automotive/audiocontrol/1.0/default/AudioControl.h
new file mode 100644
index 0000000..3383875
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/AudioControl.h
@@ -0,0 +1,45 @@
+#ifndef ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROL_H
+#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROL_H
+
+#include <android/hardware/automotive/audiocontrol/1.0/IAudioControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace audiocontrol {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct AudioControl : public IAudioControl {
+public:
+    // Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControl follow.
+    Return<AudioResult> setCallback(const sp<IAudioControlCallback>& notificationObject) override;
+    Return<int32_t> getBusForContext(uint32_t contextNumber) override;
+    Return<void> setBalanceTowardRight(float value) override;
+    Return<void> setFadeTowardFront(float value) override;
+
+    // Implementation details
+    AudioControl();
+
+private:
+    sp<IAudioControlCallback> callback;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace audiocontrol
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROL_H
diff --git a/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp b/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp
new file mode 100644
index 0000000..ea79cad
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp
@@ -0,0 +1,31 @@
+#include "AudioControlCallback.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace audiocontrol {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControlCallback follow.
+Return<void> AudioControlCallback::suggestPausePlayers() {
+    // TODO implement in framework (this is called by the HAL implementation when needed)
+    return Void();
+}
+
+Return<void> AudioControlCallback::suggestStopPlayers() {
+    // TODO implement in framework (this is called by the HAL implementation when needed)
+    return Void();
+}
+
+Return<void> AudioControlCallback::resumePlayers() {
+    // TODO implement in framework (this is called by the HAL implementation when needed)
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace audiocontrol
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/audiocontrol/1.0/default/AudioControlCallback.h b/automotive/audiocontrol/1.0/default/AudioControlCallback.h
new file mode 100644
index 0000000..1054548
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/AudioControlCallback.h
@@ -0,0 +1,41 @@
+#ifndef ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
+#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
+
+#include <android/hardware/automotive/audiocontrol/1.0/IAudioControlCallback.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace audiocontrol {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+// TODO:  Move this into packages/services/Car...
+struct AudioControlCallback : public IAudioControlCallback {
+    // Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControlCallback follow.
+    Return<void> suggestPausePlayers() override;
+    Return<void> suggestStopPlayers() override;
+    Return<void> resumePlayers() override;
+
+    // Methods from ::android::hidl::base::V1_0::IBase follow.
+
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace audiocontrol
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
diff --git a/automotive/audiocontrol/1.0/default/android.hardware.automotive.audiocontrol@1.0-service.rc b/automotive/audiocontrol/1.0/default/android.hardware.automotive.audiocontrol@1.0-service.rc
new file mode 100644
index 0000000..79edad6
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/android.hardware.automotive.audiocontrol@1.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.evs-hal-mock /vendor/bin/hw/android.hardware.automotive.audiocontrol@1.0-service
+    class hal
+    user audioserver
+    group system
diff --git a/automotive/audiocontrol/1.0/default/service.cpp b/automotive/audiocontrol/1.0/default/service.cpp
new file mode 100644
index 0000000..a033fd9
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/service.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <unistd.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+#include "AudioControl.h"
+
+
+// libhidl:
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+// Generated HIDL files
+using android::hardware::automotive::audiocontrol::V1_0::IAudioControl;
+
+// The namespace in which all our implementation code lives
+using namespace android::hardware::automotive::audiocontrol::V1_0::implementation;
+using namespace android;
+
+
+// Main service entry point
+int main() {
+    // Create an instance of our service class
+    android::sp<IAudioControl> service = new AudioControl();
+    configureRpcThreadpool(1, true /*callerWillJoin*/);
+
+    if (service->registerAsService() != OK) {
+        ALOGE("registerAsService failed");
+        return 1;
+    }
+
+    // Join (forever) the thread pool we created for the service above
+    joinRpcThreadpool();
+
+    // We don't ever actually expect to return, so return an error if we do get here
+    return 2;
+}
\ No newline at end of file
diff --git a/automotive/audiocontrol/1.0/types.hal b/automotive/audiocontrol/1.0/types.hal
new file mode 100644
index 0000000..6301d3a
--- /dev/null
+++ b/automotive/audiocontrol/1.0/types.hal
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 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.automotive.audiocontrol@1.0;
+
+
+/**
+ * Predefined flags to identifying audio contexts
+ */
+enum ContextNumber : uint32_t {
+    INVALID = 0,    /* Shouldn't be used */
+
+    // Sounds from Android (counting from 1 coincidentally lets us match AudioAttributes usages)
+    MUSIC,          /* Music playback */
+    NAVIGATION,     /* Navigation directions */
+    VOICE_COMMAND,  /* Voice command session */
+    CALL_RING,      /* Voice call ringing */
+    CALL,           /* Voice call */
+    ALARM,          /* Alarm sound from Android */
+    NOTIFICATION,   /* Notifications */
+    SYSTEM_SOUND,   /* User interaction sounds (button clicks, etc) */
+};
+
+
+/** Error codes used in AudioControl HAL interface. */
+enum AudioResult : uint32_t {
+    OK = 0,
+    NOT_AVAILABLE,
+    INVALID_ARGUMENT,
+    UNDERLYING_SERVICE_ERROR,
+};
diff --git a/automotive/evs/1.0/default/Android.bp b/automotive/evs/1.0/default/Android.bp
index 2574e86..7286478 100644
--- a/automotive/evs/1.0/default/Android.bp
+++ b/automotive/evs/1.0/default/Android.bp
@@ -13,7 +13,6 @@
 
     shared_libs: [
         "android.hardware.automotive.evs@1.0",
-        "libui",
         "libbase",
         "libbinder",
         "libcutils",
@@ -21,6 +20,7 @@
         "libhidlbase",
         "libhidltransport",
         "liblog",
+        "libui",
         "libutils",
     ],
 
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index 6b5221f..a0d20f3 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -42,19 +42,6 @@
         "VehicleAreaSeat",
         "VehicleAreaWindow",
         "VehicleAreaZone",
-        "VehicleAudioContextFlag",
-        "VehicleAudioExtFocusFlag",
-        "VehicleAudioFocusIndex",
-        "VehicleAudioFocusRequest",
-        "VehicleAudioFocusState",
-        "VehicleAudioHwVariantConfigFlag",
-        "VehicleAudioRoutingPolicyIndex",
-        "VehicleAudioStream",
-        "VehicleAudioStreamFlag",
-        "VehicleAudioVolumeCapabilityFlag",
-        "VehicleAudioVolumeIndex",
-        "VehicleAudioVolumeLimitIndex",
-        "VehicleAudioVolumeState",
         "VehicleDisplay",
         "VehicleDrivingStatus",
         "VehicleGear",
@@ -80,6 +67,7 @@
         "VmsMessageWithLayerAndPublisherIdIntegerValuesIndex",
         "VmsMessageWithLayerIntegerValuesIndex",
         "VmsOfferingMessageIntegerValuesIndex",
+        "VmsPublisherInformationIntegerValuesIndex",
         "VmsSubscriptionsStateIntegerValuesIndex",
         "Wheel",
     ],
diff --git a/automotive/vehicle/2.0/IVehicle.hal b/automotive/vehicle/2.0/IVehicle.hal
index d962de0..1b1d391 100644
--- a/automotive/vehicle/2.0/IVehicle.hal
+++ b/automotive/vehicle/2.0/IVehicle.hal
@@ -43,7 +43,7 @@
    * For VehiclePropertyChangeMode::ON_CHANGE properties, it must return the
    * latest available value.
    *
-   * Some properties like AUDIO_VOLUME requires to pass additional data in
+   * Some properties like RADIO_PRESET requires to pass additional data in
    * GET request in VehiclePropValue object.
    *
    * If there is no data available yet, which can happen during initial stage,
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 1690163..774bc4f 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -35,7 +35,7 @@
 }
 
 // Vehicle reference implementation lib
-cc_library_static {
+cc_library {
     name: "android.hardware.automotive.vehicle@2.0-manager-lib",
     vendor: true,
     defaults: ["vhal_v2_0_defaults"],
@@ -46,18 +46,12 @@
         "common/src/VehicleObjectPool.cpp",
         "common/src/VehiclePropertyStore.cpp",
         "common/src/VehicleUtils.cpp",
+        "common/src/VmsUtils.cpp",
     ],
     local_include_dirs: ["common/include/vhal_v2_0"],
     export_include_dirs: ["common/include"],
 }
 
-cc_library_shared {
-    name: "android.hardware.automotive.vehicle@2.0-manager-lib-shared",
-    vendor: true,
-    static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
-    export_static_lib_headers: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
-}
-
 // Vehicle default VehicleHAL implementation
 cc_library_static {
     name: "android.hardware.automotive.vehicle@2.0-default-impl-lib",
@@ -93,6 +87,7 @@
         "tests/VehicleHalManager_test.cpp",
         "tests/VehicleObjectPool_test.cpp",
         "tests/VehiclePropConfigIndex_test.cpp",
+        "tests/VmsUtils_test.cpp",
     ],
     header_libs: ["libbase_headers"],
 }
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
new file mode 100644
index 0000000..9e32bb5
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2018 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_automotive_vehicle_V2_0_VmsUtils_H_
+#define android_hardware_automotive_vehicle_V2_0_VmsUtils_H_
+
+#include <memory>
+#include <string>
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+namespace vms {
+
+// VmsUtils are a set of abstractions for creating and parsing Vehicle Property
+// updates to VehicleProperty::VEHICLE_MAP_SERVICE. The format for parsing a
+// VehiclePropValue update with a VMS message is specified in the Vehicle HIDL.
+//
+// This interface is meant for use by HAL clients of VMS; corresponding
+// functionality is also provided by VMS in the embedded car service.
+
+// A VmsLayer is comprised of a type, subtype, and version.
+struct VmsLayer {
+    VmsLayer(int type, int subtype, int version) : type(type), subtype(subtype), version(version) {}
+    int type;
+    int subtype;
+    int version;
+};
+
+struct VmsLayerAndPublisher {
+    VmsLayer layer;
+    int publisher_id;
+};
+
+// A VmsAssociatedLayer is used by subscribers to specify which publisher IDs
+// are acceptable for a given layer.
+struct VmsAssociatedLayer {
+    VmsLayer layer;
+    std::vector<int> publisher_ids;
+};
+
+// A VmsLayerOffering refers to a single layer that can be published, along with
+// its dependencies. Dependencies can be empty.
+struct VmsLayerOffering {
+    VmsLayerOffering(VmsLayer layer, std::vector<VmsLayer> dependencies)
+        : layer(layer), dependencies(dependencies) {}
+    VmsLayerOffering(VmsLayer layer) : layer(layer), dependencies() {}
+    VmsLayer layer;
+    std::vector<VmsLayer> dependencies;
+};
+
+// A VmsSubscriptionsState is delivered in response to a
+// VmsMessageType.SUBSCRIPTIONS_REQUEST or on the first SUBSCRIBE or last
+// UNSUBSCRIBE for a layer. It indicates which layers or associated_layers are
+// currently being subscribed to in the system.
+struct VmsSubscriptionsState {
+    int sequence_number;
+    std::vector<VmsLayer> layers;
+    std::vector<VmsAssociatedLayer> associated_layers;
+};
+
+struct VmsAvailabilityState {
+    int sequence_number;
+    std::vector<VmsAssociatedLayer> associated_layers;
+};
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.SUBSCRIBE, specifying to the VMS service
+// which layer to subscribe to.
+std::unique_ptr<VehiclePropValue> createSubscribeMessage(const VmsLayer& layer);
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.SUBSCRIBE_TO_PUBLISHER, specifying to the VMS service
+// which layer and publisher_id to subscribe to.
+std::unique_ptr<VehiclePropValue> createSubscribeToPublisherMessage(
+    const VmsLayerAndPublisher& layer);
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.UNSUBSCRIBE, specifying to the VMS service
+// which layer to unsubscribe from.
+std::unique_ptr<VehiclePropValue> createUnsubscribeMessage(const VmsLayer& layer);
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER, specifying to the VMS service
+// which layer and publisher_id to unsubscribe from.
+std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage(
+    const VmsLayerAndPublisher& layer);
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.OFFERING, specifying to the VMS service which layers are being
+// offered and their dependencies, if any.
+std::unique_ptr<VehiclePropValue> createOfferingMessage(
+    const std::vector<VmsLayerOffering>& offering);
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.AVAILABILITY_REQUEST.
+std::unique_ptr<VehiclePropValue> createAvailabilityRequest();
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.AVAILABILITY_REQUEST.
+std::unique_ptr<VehiclePropValue> createSubscriptionsRequest();
+
+// Creates a VehiclePropValue containing a message of type VmsMessageType.DATA.
+// Returns a nullptr if the byte string in bytes is empty.
+//
+// For example, to build a VehiclePropMessage containing a proto, the caller
+// should convert the proto to a byte string using the SerializeToString proto
+// API, then use this inteface to build the VehicleProperty.
+std::unique_ptr<VehiclePropValue> createDataMessage(const std::string& bytes);
+
+// Returns true if the VehiclePropValue pointed to by value contains a valid Vms
+// message, i.e. the VehicleProperty, VehicleArea, and VmsMessageType are all
+// valid. Note: If the VmsMessageType enum is extended, this function will
+// return false for any new message types added.
+bool isValidVmsMessage(const VehiclePropValue& value);
+
+// Returns the message type. Expects that the VehiclePropValue contains a valid
+// Vms message, as verified by isValidVmsMessage.
+VmsMessageType parseMessageType(const VehiclePropValue& value);
+
+// Constructs a string byte array from a message of type VmsMessageType.DATA.
+// Returns an empty string if the message type doesn't match or if the
+// VehiclePropValue does not contain a byte array.
+//
+// A proto message can then be constructed by passing the result of this
+// function to ParseFromString.
+std::string parseData(const VehiclePropValue& value);
+
+// TODO(aditin): Need to implement additional parsing functions per message
+// type.
+
+}  // namespace vms
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_VmsUtils_H_
diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
new file mode 100644
index 0000000..abf425f
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2018 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 "VmsUtils.h"
+
+#include <common/include/vhal_v2_0/VehicleUtils.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+namespace vms {
+
+static constexpr int kMessageIndex = toInt(VmsBaseMessageIntegerValuesIndex::MESSAGE_TYPE);
+static constexpr int kMessageTypeSize = 1;
+static constexpr int kLayerNumberSize = 1;
+static constexpr int kLayerSize = 3;
+static constexpr int kLayerAndPublisherSize = 4;
+
+// TODO(aditin): We should extend the VmsMessageType enum to include a first and
+// last, which would prevent breakages in this API. However, for all of the
+// functions in this module, we only need to guarantee that the message type is
+// between SUBSCRIBE and DATA.
+static constexpr int kFirstMessageType = toInt(VmsMessageType::SUBSCRIBE);
+static constexpr int kLastMessageType = toInt(VmsMessageType::DATA);
+
+std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size) {
+    auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size);
+    result->prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE);
+    result->areaId = toInt(VehicleArea::GLOBAL);
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createSubscribeMessage(const VmsLayer& layer) {
+    auto result = createBaseVmsMessage(kMessageTypeSize + kLayerSize);
+    result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIBE), layer.type,
+                                                  layer.subtype, layer.version};
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createSubscribeToPublisherMessage(
+    const VmsLayerAndPublisher& layer_publisher) {
+    auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize);
+    result->value.int32Values = hidl_vec<int32_t>{
+        toInt(VmsMessageType::SUBSCRIBE_TO_PUBLISHER), layer_publisher.layer.type,
+        layer_publisher.layer.subtype, layer_publisher.layer.version, layer_publisher.publisher_id};
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createUnsubscribeMessage(const VmsLayer& layer) {
+    auto result = createBaseVmsMessage(kMessageTypeSize + kLayerSize);
+    result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::UNSUBSCRIBE), layer.type,
+                                                  layer.subtype, layer.version};
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage(
+    const VmsLayerAndPublisher& layer_publisher) {
+    auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize);
+    result->value.int32Values = hidl_vec<int32_t>{
+        toInt(VmsMessageType::UNSUBSCRIBE_TO_PUBLISHER), layer_publisher.layer.type,
+        layer_publisher.layer.subtype, layer_publisher.layer.version, layer_publisher.publisher_id};
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createOfferingMessage(
+    const std::vector<VmsLayerOffering>& offering) {
+    int message_size = kMessageTypeSize + kLayerNumberSize;
+    for (const auto& offer : offering) {
+        message_size += kLayerNumberSize + (1 + offer.dependencies.size()) * kLayerSize;
+    }
+    auto result = createBaseVmsMessage(message_size);
+
+    std::vector<int32_t> offers = {toInt(VmsMessageType::OFFERING),
+                                   static_cast<int>(offering.size())};
+    for (const auto& offer : offering) {
+        std::vector<int32_t> layer_vector = {offer.layer.type, offer.layer.subtype,
+                                             offer.layer.version,
+                                             static_cast<int32_t>(offer.dependencies.size())};
+        for (const auto& dependency : offer.dependencies) {
+            std::vector<int32_t> dependency_layer = {dependency.type, dependency.subtype,
+                                                     dependency.version};
+            layer_vector.insert(layer_vector.end(), dependency_layer.begin(),
+                                dependency_layer.end());
+        }
+        offers.insert(offers.end(), layer_vector.begin(), layer_vector.end());
+    }
+    result->value.int32Values = offers;
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createAvailabilityRequest() {
+    auto result = createBaseVmsMessage(kMessageTypeSize);
+    result->value.int32Values = hidl_vec<int32_t>{
+        toInt(VmsMessageType::AVAILABILITY_REQUEST),
+    };
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createSubscriptionsRequest() {
+    auto result = createBaseVmsMessage(kMessageTypeSize);
+    result->value.int32Values = hidl_vec<int32_t>{
+        toInt(VmsMessageType::SUBSCRIPTIONS_REQUEST),
+    };
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createDataMessage(const std::string& bytes) {
+    auto result = createBaseVmsMessage(kMessageTypeSize);
+    result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::DATA)};
+    result->value.bytes = std::vector<uint8_t>(bytes.begin(), bytes.end());
+    return result;
+}
+
+bool verifyPropertyAndArea(const VehiclePropValue& value) {
+    return (value.prop == toInt(VehicleProperty::VEHICLE_MAP_SERVICE) &&
+            value.areaId == toInt(VehicleArea::GLOBAL));
+}
+
+bool verifyMessageType(const VehiclePropValue& value) {
+    return (value.value.int32Values.size() > 0 &&
+            value.value.int32Values[kMessageIndex] >= kFirstMessageType &&
+            value.value.int32Values[kMessageIndex] <= kLastMessageType);
+}
+
+bool isValidVmsMessage(const VehiclePropValue& value) {
+    return (verifyPropertyAndArea(value) && verifyMessageType(value));
+}
+
+VmsMessageType parseMessageType(const VehiclePropValue& value) {
+    return static_cast<VmsMessageType>(value.value.int32Values[kMessageIndex]);
+}
+
+std::string parseData(const VehiclePropValue& value) {
+    if (isValidVmsMessage(value) && parseMessageType(value) == VmsMessageType::DATA &&
+        value.value.bytes.size() > 0) {
+        return std::string(value.value.bytes.begin(), value.value.bytes.end());
+    } else {
+        return std::string();
+    }
+}
+
+}  // namespace vms
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
new file mode 100644
index 0000000..c102ce8
--- /dev/null
+++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2018 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 <android/hardware/automotive/vehicle/2.0/IVehicle.h>
+#include <gtest/gtest.h>
+
+#include "VehicleHalTestUtils.h"
+#include "vhal_v2_0/VmsUtils.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+namespace vms {
+
+namespace {
+
+TEST(VmsUtilsTest, subscribeMessage) {
+    VmsLayer layer(1, 0, 2);
+    auto message = createSubscribeMessage(layer);
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x4ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::SUBSCRIBE);
+
+    // Layer
+    EXPECT_EQ(message->value.int32Values[1], 1);
+    EXPECT_EQ(message->value.int32Values[2], 0);
+    EXPECT_EQ(message->value.int32Values[3], 2);
+}
+
+TEST(VmsUtilsTest, unsubscribeMessage) {
+    VmsLayer layer(1, 0, 2);
+    auto message = createUnsubscribeMessage(layer);
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x4ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::UNSUBSCRIBE);
+
+    // Layer
+    EXPECT_EQ(message->value.int32Values[1], 1);
+    EXPECT_EQ(message->value.int32Values[2], 0);
+    EXPECT_EQ(message->value.int32Values[3], 2);
+}
+
+TEST(VmsUtilsTest, singleOfferingMessage) {
+    std::vector<VmsLayerOffering> offering = {VmsLayerOffering(VmsLayer(1, 0, 2))};
+    auto message = createOfferingMessage(offering);
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x6ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);
+
+    // Number of layer offerings
+    EXPECT_EQ(message->value.int32Values[1], 1);
+
+    // Layer
+    EXPECT_EQ(message->value.int32Values[2], 1);
+    EXPECT_EQ(message->value.int32Values[3], 0);
+    EXPECT_EQ(message->value.int32Values[4], 2);
+
+    // Number of dependencies
+    EXPECT_EQ(message->value.int32Values[5], 0);
+}
+
+TEST(VmsUtilsTest, offeringWithDependencies) {
+    VmsLayer layer(1, 0, 2);
+    std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2)};
+    std::vector<VmsLayerOffering> offering = {VmsLayerOffering(layer, dependencies)};
+    auto message = createOfferingMessage(offering);
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x9ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);
+
+    // Number of layer offerings
+    EXPECT_EQ(message->value.int32Values[1], 1);
+
+    // Layer
+    EXPECT_EQ(message->value.int32Values[2], 1);
+    EXPECT_EQ(message->value.int32Values[3], 0);
+    EXPECT_EQ(message->value.int32Values[4], 2);
+
+    // Number of dependencies
+    EXPECT_EQ(message->value.int32Values[5], 1);
+
+    // Dependency 1
+    EXPECT_EQ(message->value.int32Values[6], 2);
+    EXPECT_EQ(message->value.int32Values[7], 0);
+    EXPECT_EQ(message->value.int32Values[8], 2);
+}
+
+TEST(VmsUtilsTest, availabilityMessage) {
+    auto message = createAvailabilityRequest();
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x1ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::AVAILABILITY_REQUEST);
+}
+
+TEST(VmsUtilsTest, subscriptionsMessage) {
+    auto message = createSubscriptionsRequest();
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x1ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::SUBSCRIPTIONS_REQUEST);
+}
+
+TEST(VmsUtilsTest, dataMessage) {
+    std::string bytes = "aaa";
+    auto message = createDataMessage(bytes);
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x1ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::DATA);
+    EXPECT_EQ(message->value.bytes.size(), bytes.size());
+    EXPECT_EQ(memcmp(message->value.bytes.data(), bytes.data(), bytes.size()), 0);
+}
+
+TEST(VmsUtilsTest, emptyMessageInvalid) {
+    VehiclePropValue empty_prop;
+    EXPECT_FALSE(isValidVmsMessage(empty_prop));
+}
+
+TEST(VmsUtilsTest, invalidMessageType) {
+    VmsLayer layer(1, 0, 2);
+    auto message = createSubscribeMessage(layer);
+    message->value.int32Values[0] = 0;
+
+    EXPECT_FALSE(isValidVmsMessage(*message));
+}
+
+TEST(VmsUtilsTest, parseDataMessage) {
+    std::string bytes = "aaa";
+    auto message = createDataMessage(bytes);
+    auto data_str = parseData(*message);
+    ASSERT_FALSE(data_str.empty());
+    EXPECT_EQ(data_str, bytes);
+}
+
+TEST(VmsUtilsTest, parseInvalidDataMessage) {
+    VmsLayer layer(1, 0, 2);
+    auto message = createSubscribeMessage(layer);
+    auto data_str = parseData(*message);
+    EXPECT_TRUE(data_str.empty());
+}
+
+}  // namespace
+
+}  // namespace vms
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 9c093dc..f673d1a 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -907,346 +907,6 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Represents audio focus state of Android side. Note that car's audio
-     * module must own audio focus and grant audio focus to Android side when
-     * requested by Android side. The focus has both per stream characteristics
-     * and global characteristics.
-     *
-     * Focus request (get of this property) must take the following form with indices defined
-     * by VehicleAudioFocusIndex:
-     *   int32Values[0]: VehicleAudioFocusRequest type
-     *   int32Values[1]: bit flags of streams requested by this focus request.
-     *                   There can be up to 32 streams.
-     *   int32Values[2]: External focus state flags. For request, only flag like
-     *                   VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG or
-     *                   VehicleAudioExtFocusFlag#MUTE_MEDIA_FLAG can be
-     *                   used.
-     *                   VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG is for case
-     *                   like radio where android side app still needs to hold
-     *                   focus but playback is done outside Android.
-     *                   VehicleAudioExtFocusFlag#MUTE_MEDIA_FLAG is for
-     *                   muting media channel including radio.
-     *                   VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG can be set
-     *                   even if android side releases focus (request type
-     *                   REQUEST_RELEASE). In that case, audio module must
-     *                   maintain mute state until user's explicit action to
-     *                   play some media.
-     *   int32Values[3]: Audio contexts wishing to be active. Use combination of
-     *                   flags from VehicleAudioContextFlag.
-     *                   This can be used as a hint to adjust audio policy or
-     *                   other policy decision.
-     *                   Note that there can be multiple context active at the
-     *                   same time. And android can send the same focus request
-     *                   type gain due to change in audio contexts.
-     * Note that each focus request can request multiple streams that is
-     * expected to be used for the current request. But focus request itself
-     * is global behavior as GAIN or GAIN_TRANSIENT expects all sounds played
-     * by car's audio module to stop. Note that stream already allocated to
-     * android before this focus request must not be affected by focus
-     * request.
-     *
-     * Focus response (set and subscription callback for this property) must
-     * take the following form with indices defined by VehicleAudioFocusIndex:
-     *   int32Values[0]: VehicleAudioFocusState type
-     *   int32Values[1]: bit flags of streams allowed.
-     *   int32Values[2]: External focus state: bit flags of currently active
-     *                   audio focus in car side (outside Android). Active
-     *                   audio focus does not necessarily mean currently
-     *                   playing, but represents the state of having focus or
-     *                   waiting for focus (pause state).
-     *                   One or combination of flags from
-     *                   VehicleAudioExtFocusFlag.
-     *                   0 means no active audio focus holder outside Android.
-     *                   The state must have following values for each
-     *                   VehicleAudioFocusState:
-     *                   GAIN: VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG
-     *                       when radio is active in Android side. Otherwise,
-     *                       VehicleAudioExtFocusFlag#NONE_FLAG.
-     *                   GAIN_TRANSIENT: Can be
-     *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG or
-     *                       VehicleAudioExtFocusFlag#TRANSIENT_FLAG if android
-     *                       side has requested
-     *                       REQUEST_GAIN_TRANSIENT_MAY_DUCK and car side is
-     *                       ducking. Otherwise
-     *                       VehicleAudioExtFocusFlag#NONE_FLAG.
-     *                   LOSS: VehicleAudioExtFocusFlag#NONE_FLAG when no focus
-     *                       is active in car side.
-     *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG when car
-     *                       side is playing something permanent.
-     *                   LOSS_TRANSIENT: must always be
-     *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG
-     *   int32Values[3]: Audio context(s) allowed to be active. When responding positively to a
-     *                   focus request from Android, the request's original context must be
-     *                   repeated here. When taking focus away, or denying a request, the
-     *                   rejected or stopped context would have its corresponding bit cleared.
-     *
-     * A focus response must be sent per each focus request even if there is
-     * no change in focus state. This can happen in case like focus request
-     * only involving context change where android side still needs matching
-     * focus response to confirm that audio module has made necessary changes.
-     *
-     * If car does not support AUDIO_FOCUS, focus is assumed to be granted
-     * always.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    AUDIO_FOCUS = (
-        0x0900
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * A property to allow external component to control audio focus. Depending on
-     * H/W architecture, audio HAL may need to control audio focus while vehicle
-     * HAL is still interacting with upper layer. In such case, audio HAL may set
-     * this property and vehicle HAL may use this property value to decide
-     * response sent through AUDIO_FOCUS property.
-     * Data format is the same as AUDIO_FOCUS property.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    AUDIO_FOCUS_EXT_SYNC = (
-        0x0910
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to control audio volume of each audio context.
-     *
-     * VehiclePropConfig
-     *   configArray[0] : bit flags of all supported audio contexts from
-     *                    VehicleAudioContextFlag. If this is 0, audio volume
-     *                    is controlled per physical stream.
-     *   configArray[1] : flags defined in VehicleAudioVolumeCapabilityFlag to
-     *                    represent audio module's capability.
-     *   configArray[2..3] : reserved
-     *   configArray[4..N+3] : maximum values for each audio context, where N is
-     *                         the number of audio contexts provided in
-     *                         configArray[0], minimum value is always 0 which
-     *                         indicates mute state.
-     *
-     * Data type looks like:
-     *   int32Values[0] : audio context as defined in VehicleAudioContextFlag.
-     *                    If only physical stream is supported
-     *                    (configArray[0] == 0), this must represent physical
-     *                    stream number.
-     *   int32Values[1] : volume level, valid range is 0 (mute) to max level
-     *                    defined in the config.
-     *   int32Values[2] : One of VehicleAudioVolumeState.
-     *
-     * HAL implementations must check the incoming value of audio context
-     * field in get call to return the right volume.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @config_flags all audio contexts supported.
-     */
-    AUDIO_VOLUME = (
-        0x0901
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to allow audio volume sync from external components like audio HAL.
-     * Some vehicle HAL implementation may get volume control from audio HAL and in such
-     * case, setting AUDIO_VOLUME_EXT_SYNC property may trigger event in AUDIO_VOLUME property.
-     * Data format for this property is the same as AUDIO_VOLUME property.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @config_flags all audio contexts supported.
-     */
-    AUDIO_VOLUME_EXT_SYNC = (
-        0x0911
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property for handling volume limit set by user. This limits maximum
-     * volume that can be set per each context or physical stream.
-     *
-     * VehiclePropConfig
-     *   configArray[0] : bit flags of all supported audio contexts. If this is
-     *                    0, audio volume is controlled per physical stream.
-     *   configArray[1] : flags defined in VehicleAudioVolumeCapabilityFlag
-     *                    to represent audio module's capability.
-     *
-     * Data type looks like:
-     *   int32Values[0] : audio context as defined in VehicleAudioContextFlag.
-     *                    If only physical stream is supported
-     *                    (configArray[0] == 0), this must represent physical
-     *                    stream number.
-     *   int32Values[1] : maximum volume set to the stream. If there is no
-     *                    restriction, this value must be equal to
-     *                    AUDIO_VOLUME's max value.
-     *
-     * If car does not support this feature, this property must not be
-     * populated by HAL.
-     * HAL implementations must check the incoming value of audio context
-     * field in get call to return the right volume.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @config_flags all audio contexts supported.
-     */
-    AUDIO_VOLUME_LIMIT = (
-        0x0902
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to share audio routing policy of android side. This property is
-     * set at startup to pass audio policy in android side down to
-     * vehicle HAL and car audio module.
-     *
-     *   int32Values[0] : audio stream where the audio for the application
-     *                    context must be routed by default. Note that this is
-     *                    the default setting from system, but each app may
-     *                    still use different audio stream for whatever reason.
-     *   int32Values[1] : All audio contexts that must be sent through the
-     *                     physical stream. Flag is defined in
-     *                     VehicleAudioContextFlag.
-
-     * Setting of this property must be done for all available physical streams
-     * based on audio H/W variant information acquired from AUDIO_HW_VARIANT
-     * property.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:WRITE
-     */
-    AUDIO_ROUTING_POLICY = (
-        0x0903
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to return audio H/W variant type used in this car. This is a
-     * zero based index into the set of audio routing policies defined in
-     * R.array.audioRoutingPolicy on CarService, which  may be overlaid to
-     * support multiple variants. If this property does not exist, the default
-     * audio policy must be used.
-     *
-     * @change_mode VehiclePropertyChangeMode:STATIC
-     * @access VehiclePropertyAccess:READ
-     * @config_flags Additional info on audio H/W. Must use
-     *               VehicleAudioHwVariantConfigFlag for this.
-     */
-    AUDIO_HW_VARIANT = (
-        0x0904
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to pass hint on external audio routing. When android side
-     * request focus with VehicleAudioExtFocusflag, this
-     * property must be set before setting AUDIO_FOCUS property as a hint for
-     * external audio source routing.
-     * Note that setting this property alone must not trigger any change.
-     * Audio routing must be changed only when AUDIO_FOCUS property is set.
-     * Note that this property allows passing custom value as long as it is
-     * defined in VehiclePropConfig#configString. This allows supporting
-     * non-standard routing options through this property.
-     * It is recommended to use separate name space for custom property to
-     * prevent conflict in future android releases.
-     * Enabling each external routing option is done by enabling each bit flag
-     * for the routing.
-     * This property can support up to 128 external routings.
-     * To give full flexibility, there is no standard definition for each bit
-     * flag and assigning each bit flag to specific routing type is decided by
-     * VehiclePropConfig#configString.  VehiclePropConfig#configString has
-     * format of each entry separated by ',' and each entry has format of
-     * bitFlagPositon:typeString[:physicalStreamNumber].
-     *  bitFlagPosition: represents which bit flag will be set to enable this
-     *    routing. 0 means LSB in int32Values[0]. 31 will be MSB in
-     *    int32Values[0]. 127 will MSB in int32Values[3].
-     *  typeString: string representation of external routing. Some types are
-     *    already defined in AUDIO_EXT_ROUTING_SOURCE_* and use them first
-     *    before adding something custom. Applications will find each routing
-     *    using this string.
-     *  physicalStreamNumber: This part is optional and represents physical
-     *    stream to android which will be disabled when this routing is enabled.
-     *    If not specified, this routing must not affect physical streams to
-     *    android.
-     * As an example, let's assume a system with two physical streams, 0 for
-     * media and 1 for nav guidance. And let's assume external routing option
-     * of am fm radio, external navigation guidance, satellite radio, and one
-     * custom. Let's assume that radio and satellite replaces physical stream 0
-     * and external navigation replaces physical stream 1. And bit flag will be
-     * assigned in the order listed above. This configuration will look like
-     * this in config_string:
-     *  "0:RADIO_AM_FM:0,1:EXT_NAV_GUIDANCE:1,2:RADIO_SATELLITE:0,3:com.test.SOMETHING_CUSTOM"
-     * When android requests RADIO_AM_FM, int32Values[0] will be set to 0x1.
-     * When android requests RADIO_SATELLITE + EXT_NAV_GUIDANCE, int32Values[0]
-     * will be set to 0x2|0x4.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @config_string List of all avaiable external source in the system.
-     */
-    AUDIO_EXT_ROUTING_HINT = (
-        0x0905
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Represents state of audio stream. Audio HAL should set this when a stream is starting or
-     * ending. Car service can request focus for audio played without focus. If such feature
-     * is not required, this property does not need to be implemented.
-     * Car service only monitors setting of this property. It is up to each vehicle HAL
-     * implementation to add necessary action but default implementation will be doing nothing on
-     * this propery's set from audio HAL.
-     * Actual streaming of data should be done only after getting focus for the given stream from
-     * car audio module. Focus can be already granted when stream is started. Focus state can be
-     * monitored by monitoring AUDIO_FOCUS property. If car does not support
-     * AUDIO_FOCUS property, there is no need to monitor focus as focus is assumed to be
-     * granted always.
-     * Data has the following format:
-     *   int32_array[0] : vehicle_audio_stream_state, 0: stopped, 1: started
-     *   int32_array[1] : stream number like 0, 1, 2, ...
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    AUDIO_STREAM_STATE  = (
-        0x0906
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to control car specific audio parameters. Each parameter is defined as string key-
-     * value pair.
-     * set and event notification can pass multiple parameters using the
-     * following format:
-     *   key1=value1;key2=value2;...
-     * get call can request multiple parameters using the following format:
-     *   key1;key2;...
-     * Response for get call has the same format as set.
-     *
-     * VehiclePropConfig
-     *   configString: give list of all supported keys with ; as separator. For example:
-     *     key1;key2;...
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    AUDIO_PARAMETERS = (
-        0x907
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:STRING
-        | VehicleArea:GLOBAL),
-
-    /**
      * Property to control power state of application processor
      *
      * It is assumed that AP's power state is controller by separate power
@@ -2244,256 +1904,6 @@
     VEHICLE_RADIO_PRESET_MIN_VALUE = 1,
 };
 
-enum VehicleAudioFocusRequest : int32_t {
-    REQUEST_GAIN = 0x1,
-    REQUEST_GAIN_TRANSIENT = 0x2,
-    REQUEST_GAIN_TRANSIENT_MAY_DUCK = 0x3,
-    /**
-     * This is for the case where android side plays sound like UI feedback
-     * and car side does not need to duck existing playback as long as
-     * requested stream is available.
-     */
-    REQUEST_GAIN_TRANSIENT_NO_DUCK = 0x4,
-    REQUEST_RELEASE = 0x5,
-};
-
-enum VehicleAudioFocusState : int32_t {
-    /**
-     * Android side has permanent focus and can play allowed streams.
-     */
-    STATE_GAIN = 0x1,
-
-    /**
-     * Android side has transient focus and can play allowed streams.
-     */
-    STATE_GAIN_TRANSIENT = 0x2,
-
-    /**
-     * Car audio module is playing guidance kind of sound outside Android.
-     * Android side can still play through allowed streams with ducking.
-     */
-    STATE_LOSS_TRANSIENT_CAN_DUCK = 0x3,
-
-    /**
-     * Car audio module is playing transient sound outside Android. Android side
-     * must stop playing any sounds.
-     */
-    STATE_LOSS_TRANSIENT = 0x4,
-
-    /**
-     * Android side has lost focus and cannot play any sound.
-     */
-    STATE_LOSS = 0x5,
-
-    /**
-     * car audio module is playing safety critical sound, and Android side cannot
-     * request focus until the current state is finished. car audio module
-     * restore it to the previous state when it can allow Android to play.
-     */
-    STATE_LOSS_TRANSIENT_EXLCUSIVE = 0x6,
-};
-
-/**
- * Flags to represent multiple streams by combining these.
- */
-enum VehicleAudioStreamFlag : int32_t {
-    STREAM0_FLAG = (0x1 << 0),
-    STREAM1_FLAG = (0x1 << 1),
-    STREAM2_FLAG = (0x1 << 2),
-};
-
-/**
- * Represents stream number (always 0 to N -1 where N is max number of streams).
- * Can be used for audio related property expecting one stream.
- */
-enum VehicleAudioStream : int32_t {
-    STREAM0 = 0,
-    STREAM1 = 1,
-};
-
-/**
- * Flag to represent external focus state (outside Android).
- */
-enum VehicleAudioExtFocusFlag : int32_t {
-    /**
-     * No external focus holder.
-     */
-    NONE_FLAG = 0x0,
-
-    /**
-     * Car side (outside Android) has component holding GAIN kind of focus state.
-     */
-    PERMANENT_FLAG = 0x1,
-
-    /**
-     * Car side (outside Android) has component holding GAIN_TRANSIENT kind of
-     * focus state.
-     */
-    TRANSIENT_FLAG = 0x2,
-
-    /**
-     * Car side is expected to play something while focus is held by Android side.
-     * One example can be radio attached in car side. But Android's radio app
-     * still must have focus, and Android side must be in GAIN state, but
-     * media stream will not be allocated to Android side and car side can play
-     * radio any time while this flag is active.
-     */
-    PLAY_ONLY_FLAG = 0x4,
-
-    /**
-     * Car side must mute any media including radio. This can be used with any
-     * focus request including GAIN* and RELEASE.
-     */
-    MUTE_MEDIA_FLAG = 0x8,
-};
-
-/**
- * Index in int32Values for VehicleProperty#AUDIO_FOCUS property.
- */
-enum VehicleAudioFocusIndex : int32_t {
-    FOCUS = 0,
-    STREAMS = 1,
-    EXTERNAL_FOCUS_STATE = 2,
-    AUDIO_CONTEXTS = 3,
-};
-
-/**
- * Flags to tell the current audio context.
- */
-enum VehicleAudioContextFlag : int32_t {
-    /** Music playback is currently active. */
-    MUSIC_FLAG = 0x1,
-
-    /** Navigation is currently running. */
-    NAVIGATION_FLAG = 0x2,
-
-    /** Voice command session is currently running. */
-    VOICE_COMMAND_FLAG = 0x4,
-
-    /** Voice call is currently active. */
-    CALL_FLAG = 0x8,
-
-    /**
-     * Alarm is active.
-     * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
-     */
-    ALARM_FLAG = 0x10,
-
-    /**
-     * Notification sound is active.
-     * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
-     */
-    NOTIFICATION_FLAG = 0x20,
-
-    /**
-     * Context unknown. Only used for VehicleProperty#AUDIO_ROUTING_POLICY to
-     * represent default stream for unknown contents.
-     */
-    UNKNOWN_FLAG = 0x40,
-
-    /** Safety alert / warning is played. */
-    SAFETY_ALERT_FLAG = 0x80,
-
-    /** CD / DVD kind of audio is played */
-    CD_ROM_FLAG = 0x100,
-
-    /** Aux audio input is played */
-    AUX_AUDIO_FLAG = 0x200,
-
-    /** system sound like UI feedback */
-    SYSTEM_SOUND_FLAG = 0x400,
-
-    /** Radio is played */
-    RADIO_FLAG = 0x800,
-
-    /** Ext source is played. This is for tagging generic ext sources. */
-    EXT_SOURCE_FLAG = 0x1000,
-
-    /** The phone ring tone is played */
-    RINGTONE_FLAG = 0x2000
-};
-
-/**
- * flags to represent capability of audio volume property.
- * used in configArray[1] of VehiclePropConfig.
- */
-enum VehicleAudioVolumeCapabilityFlag : int32_t {
-    /**
-     * External audio module or vehicle hal has persistent storage to keep the
-     * volume level. When this is set, the audio volume level for each context
-     * will be retrieved from the property when the system starts up.
-     * And external audio module is also expected to adjust volume automatically
-     * whenever there is an audio context change.
-     * When this flag is not set, android side will assume that there is no
-     * persistent storage and the value stored in the android side will be used to
-     * initialize the volume level, and android side will set volume level
-     * of each physical stream whenever there is an audio context change.
-     */
-    PERSISTENT_STORAGE = 0x1,
-
-    /**
-     * [DEPRECATED]
-     * When this flag is set, the H/W can support only single master volume for
-     * all streams. There is no way to set volume level differently for each stream
-     * or context.
-     */
-    MASTER_VOLUME_ONLY = 0x2,
-};
-
-/**
- * enum to represent audio volume state.
- */
-enum VehicleAudioVolumeState : int32_t {
-    STATE_OK = 0,
-
-    /**
-     * Audio volume has reached volume limit set in
-     * VehicleProperty#AUDIO_VOLUME_LIMIT and user's request to increase volume
-     * further is not allowed.
-     */
-    STATE_LIMIT_REACHED = 1,
-};
-
-/**
- * Index in int32Values for VehicleProperty#AUDIO_VOLUME property.
- */
-enum VehicleAudioVolumeIndex : int32_t {
-    STREAM = 0,
-    VOLUME = 1,
-    STATE = 2,
-};
-
-/**
- * Index in int32Values for VehicleProperty#AUDIO_VOLUME_LIMIT property.
- */
-enum VehicleAudioVolumeLimitIndex : int32_t {
-    STREAM = 0,
-    MAX_VOLUME = 1,
-};
-
-/**
- * Index in int32Values for VehicleProperty#AUDIO_ROUTING_POLICY property.
- */
-enum VehicleAudioRoutingPolicyIndex : int32_t {
-    STREAM = 0,
-    CONTEXTS = 1,
-};
-
-/**
- * Flag to be used in VehiclePropConfig#configFlags for
- * VehicleProperty#AUDIO_HW_VARIANT.
- */
-enum VehicleAudioHwVariantConfigFlag : int32_t {
-  /**
-   * Flag to tell that radio is internal to android and radio must
-   * be treated like other android stream like media.
-   * When this flag is not set or AUDIO_HW_VARIANT does not exist,
-   * radio is treated as external module. This may affect audio focus
-   * handling as well.
-   */
-  INTERNAL_RADIO_FLAG = 0x1,
-};
-
 enum VehicleApPowerStateConfigFlag : int32_t /* NOTE: type is guessed */ {
     /**
      * AP can enter deep sleep state. If not set, AP will always shutdown from
@@ -3485,9 +2895,42 @@
      * A message from the VMS service to the subscribers or from the publishers to the VMS service
      * with a serialized VMS data packet as defined in the VMS protocol.
      *
-     * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+     * This message type uses enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.
      */
     DATA = 12,
+
+    /**
+     * A request from the publishers to the VMS service to get a Publisher ID for a serialized VMS
+     * provider description packet as defined in the VMS protocol.
+     *
+     * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+     */
+    PUBLISHER_ID_REQUEST = 13,
+
+    /**
+     * A response from the VMS service to the publisher that contains a provider description packet
+     * and the publisher ID assigned to it.
+     *
+     * This message type uses enum VmsPublisherInformationIntegerValuesIndex.
+     */
+    PUBLISHER_ID_RESPONSE = 14,
+
+    /**
+     * A request from the subscribers to the VMS service to get information for a Publisher ID.
+     *
+     * This message type uses enum VmsPublisherInformationIntegerValuesIndex.
+     */
+    PUBLISHER_INFORMATION_REQUEST = 15,
+
+    /**
+     * A response from the VMS service to the subscribers that contains a provider description packet
+     * and the publisher ID assigned to it.
+     *
+     * This message type uses enum VmsPublisherInformationIntegerValuesIndex.
+     */
+    PUBLISHER_INFORMATION_RESPONSE = 16,
+
+    LAST_VMS_MESSAGE_TYPE = PUBLISHER_INFORMATION_RESPONSE,
 };
 
 /**
@@ -3515,7 +2958,8 @@
 
 /*
  * A VMS message with a layer and publisher ID is sent as part of a
- * VmsMessageType.SUBSCRIBE_TO_PUBLISHER and VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER messages.
+ * VmsMessageType.SUBSCRIBE_TO_PUBLISHER, VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER messages and
+ * VmsMessageType.DATA .
  */
 enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex : VmsMessageWithLayerIntegerValuesIndex {
     PUBLISHER_ID = 4,
@@ -3584,3 +3028,11 @@
     LAYERS_START = 3,
 };
 
+/*
+ * Publishers send the VMS service their information and assigned in response a publisher ID.
+ * Subscribers can request the publisher information for a publisher ID they received in other messages.
+ */
+enum VmsPublisherInformationIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
+    PUBLISHER_ID = 1,
+};
+
diff --git a/bluetooth/1.0/default/h4_protocol.cc b/bluetooth/1.0/default/h4_protocol.cc
index 163cc33..df40507 100644
--- a/bluetooth/1.0/default/h4_protocol.cc
+++ b/bluetooth/1.0/default/h4_protocol.cc
@@ -71,8 +71,10 @@
     ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, 1));
     if (bytes_read != 1) {
       if (bytes_read == 0) {
-        LOG_ALWAYS_FATAL("%s: Unexpected EOF reading the packet type!",
-                         __func__);
+        // This is only expected if the UART got closed when shutting down.
+        ALOGE("%s: Unexpected EOF reading the packet type!", __func__);
+        sleep(5);  // Expect to be shut down within 5 seconds.
+        return;
       } else if (bytes_read < 0) {
         LOG_ALWAYS_FATAL("%s: Read packet type error: %s", __func__,
                          strerror(errno));
diff --git a/bluetooth/1.0/default/hci_packetizer.cc b/bluetooth/1.0/default/hci_packetizer.cc
index fde08ac..71f4328 100644
--- a/bluetooth/1.0/default/hci_packetizer.cc
+++ b/bluetooth/1.0/default/hci_packetizer.cc
@@ -56,9 +56,13 @@
       ssize_t bytes_read = TEMP_FAILURE_RETRY(
           read(fd, preamble_ + bytes_read_,
                preamble_size_for_type[packet_type] - bytes_read_));
-      if (bytes_read <= 0) {
-        LOG_ALWAYS_FATAL_IF((bytes_read == 0),
-                            "%s: Unexpected EOF reading the header!", __func__);
+      if (bytes_read == 0) {
+        // This is only expected if the UART got closed when shutting down.
+        ALOGE("%s: Unexpected EOF reading the header!", __func__);
+        sleep(5);  // Expect to be shut down within 5 seconds.
+        return;
+      }
+      if (bytes_read < 0) {
         LOG_ALWAYS_FATAL("%s: Read header error: %s", __func__,
                          strerror(errno));
       }
@@ -80,10 +84,13 @@
           fd,
           packet_.data() + preamble_size_for_type[packet_type] + bytes_read_,
           bytes_remaining_));
-      if (bytes_read <= 0) {
-        LOG_ALWAYS_FATAL_IF((bytes_read == 0),
-                            "%s: Unexpected EOF reading the payload!",
-                            __func__);
+      if (bytes_read == 0) {
+        // This is only expected if the UART got closed when shutting down.
+        ALOGE("%s: Unexpected EOF reading the payload!", __func__);
+        sleep(5);  // Expect to be shut down within 5 seconds.
+        return;
+      }
+      if (bytes_read < 0) {
         LOG_ALWAYS_FATAL("%s: Read payload error: %s", __func__,
                          strerror(errno));
       }
diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc
index 6ce2f11..a8f5bb4 100644
--- a/bluetooth/1.0/default/vendor_interface.cc
+++ b/bluetooth/1.0/default/vendor_interface.cc
@@ -49,6 +49,7 @@
 bool recent_activity_flag;
 
 VendorInterface* g_vendor_interface = nullptr;
+std::mutex wakeup_mutex_;
 
 HC_BT_HDR* WrapPacketAndCopy(uint16_t event, const hidl_vec<uint8_t>& data) {
   size_t packet_size = data.size() + sizeof(HC_BT_HDR);
@@ -308,6 +309,7 @@
 }
 
 size_t VendorInterface::Send(uint8_t type, const uint8_t* data, size_t length) {
+  std::unique_lock<std::mutex> lock(wakeup_mutex_);
   recent_activity_flag = true;
 
   if (lpm_wake_deasserted == true) {
@@ -350,6 +352,7 @@
 
 void VendorInterface::OnTimeout() {
   ALOGV("%s", __func__);
+  std::unique_lock<std::mutex> lock(wakeup_mutex_);
   if (recent_activity_flag == false) {
     lpm_wake_deasserted = true;
     bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_DEASSERT;
diff --git a/broadcastradio/1.2/default/BroadcastRadio.cpp b/broadcastradio/1.2/default/BroadcastRadio.cpp
index 5164e47..74f6589 100644
--- a/broadcastradio/1.2/default/BroadcastRadio.cpp
+++ b/broadcastradio/1.2/default/BroadcastRadio.cpp
@@ -107,7 +107,7 @@
     prop10.numTuners = 1;
     prop10.numAudioSources = 1;
     prop10.supportsCapture = false;
-    prop11.supportsBackgroundScanning = false;
+    prop11.supportsBackgroundScanning = true;
     prop11.supportedProgramTypes = hidl_vec<uint32_t>({
         static_cast<uint32_t>(ProgramType::AM), static_cast<uint32_t>(ProgramType::FM),
         static_cast<uint32_t>(ProgramType::AM_HD), static_cast<uint32_t>(ProgramType::FM_HD),
diff --git a/broadcastradio/1.2/default/Tuner.cpp b/broadcastradio/1.2/default/Tuner.cpp
index f589332..e95a132 100644
--- a/broadcastradio/1.2/default/Tuner.cpp
+++ b/broadcastradio/1.2/default/Tuner.cpp
@@ -343,7 +343,11 @@
     lock_guard<mutex> lk(mMut);
     if (mIsClosed) return ProgramListResult::NOT_INITIALIZED;
 
-    return ProgramListResult::UNAVAILABLE;
+    if (mCallback1_1 != nullptr) {
+        mCallback1_1->backgroundScanComplete(ProgramListResult::OK);
+    }
+
+    return ProgramListResult::OK;
 }
 
 Return<void> Tuner::getProgramList(const hidl_vec<VendorKeyValue>& vendorFilter,
diff --git a/broadcastradio/2.0/Android.bp b/broadcastradio/2.0/Android.bp
index 7409005..2434fdc 100644
--- a/broadcastradio/2.0/Android.bp
+++ b/broadcastradio/2.0/Android.bp
@@ -8,7 +8,7 @@
     },
     srcs: [
         "types.hal",
-        "IAnnouncementObserver.hal",
+        "IAnnouncementListener.hal",
         "IBroadcastRadio.hal",
         "ICloseHandle.hal",
         "ITunerCallback.hal",
diff --git a/broadcastradio/2.0/IAnnouncementObserver.hal b/broadcastradio/2.0/IAnnouncementListener.hal
similarity index 85%
rename from broadcastradio/2.0/IAnnouncementObserver.hal
rename to broadcastradio/2.0/IAnnouncementListener.hal
index c91e29a..1b4960c 100644
--- a/broadcastradio/2.0/IAnnouncementObserver.hal
+++ b/broadcastradio/2.0/IAnnouncementListener.hal
@@ -16,11 +16,11 @@
 package android.hardware.broadcastradio@2.0;
 
 /**
- * Callback interface for announcement observer.
+ * Callback interface for announcement listener.
  *
- * For typical configuration, the observer is a broadcast radio service.
+ * For typical configuration, the listener is a broadcast radio service.
  */
-interface IAnnouncementObserver {
+interface IAnnouncementListener {
     /**
      * Called whenever announcement list has changed.
      *
diff --git a/broadcastradio/2.0/IBroadcastRadio.hal b/broadcastradio/2.0/IBroadcastRadio.hal
index 7578f44..bedc362 100644
--- a/broadcastradio/2.0/IBroadcastRadio.hal
+++ b/broadcastradio/2.0/IBroadcastRadio.hal
@@ -15,7 +15,7 @@
 
 package android.hardware.broadcastradio@2.0;
 
-import IAnnouncementObserver;
+import IAnnouncementListener;
 import ICloseHandle;
 import ITunerCallback;
 import ITunerSession;
@@ -104,7 +104,7 @@
     getImage(uint32_t id) generates (vec<uint8_t> image);
 
     /**
-     * Registers announcement observer.
+     * Registers announcement listener.
      *
      * If there is at least one observer registered, HAL implementation must
      * notify about announcements even if no sessions are active.
@@ -113,15 +113,15 @@
      * automatically.
      *
      * @param enabled The list of announcement types to watch for.
-     * @param cb The callback interface.
+     * @param listener The listener interface.
      * @return result OK in case of success.
      *                NOT_SUPPORTED if the tuner doesn't support announcements.
      * @return closeHandle A handle to unregister observer,
      *                     nullptr if result was not OK.
      */
-    registerAnnouncementObserver(
+    registerAnnouncementListener(
             vec<AnnouncementType> enabled,
-            IAnnouncementObserver cb
+            IAnnouncementListener listener
         ) generates (
             Result result,
             ICloseHandle closeHandle
diff --git a/broadcastradio/2.0/ITunerSession.hal b/broadcastradio/2.0/ITunerSession.hal
index a58fa62..e891a23 100644
--- a/broadcastradio/2.0/ITunerSession.hal
+++ b/broadcastradio/2.0/ITunerSession.hal
@@ -113,12 +113,12 @@
      *                NOT_SUPPORTED if the flag is not supported at all.
      * @return value The current value of the flag, if result is OK.
      */
-    getConfigFlag(ConfigFlag flag) generates (Result result, bool value);
+    isConfigFlagSet(ConfigFlag flag) generates (Result result, bool value);
 
     /**
      * Sets the config flag.
      *
-     * The success/failure result must be consistent with getConfigFlag.
+     * The success/failure result must be consistent with isConfigFlagSet.
      *
      * @param flag Flag to set.
      * @param value The new value of a given flag.
diff --git a/broadcastradio/2.0/default/BroadcastRadio.cpp b/broadcastradio/2.0/default/BroadcastRadio.cpp
index d16aaff..0148fec 100644
--- a/broadcastradio/2.0/default/BroadcastRadio.cpp
+++ b/broadcastradio/2.0/default/BroadcastRadio.cpp
@@ -112,6 +112,12 @@
 Return<void> BroadcastRadio::openSession(const sp<ITunerCallback>& callback,
                                          openSession_cb _hidl_cb) {
     ALOGV("%s", __func__);
+
+    /* For the needs of default implementation it's fine to instantiate new session object
+     * out of the lock scope. If your implementation needs it, use reentrant lock.
+     */
+    sp<TunerSession> newSession = new TunerSession(*this, callback);
+
     lock_guard<mutex> lk(mMut);
 
     auto oldSession = mSession.promote();
@@ -121,7 +127,6 @@
         mSession = nullptr;
     }
 
-    sp<TunerSession> newSession = new TunerSession(*this, callback);
     mSession = newSession;
 
     _hidl_cb(Result::OK, newSession);
@@ -141,9 +146,9 @@
     return {};
 }
 
-Return<void> BroadcastRadio::registerAnnouncementObserver(
-    const hidl_vec<AnnouncementType>& enabled, const sp<IAnnouncementObserver>& /* cb */,
-    registerAnnouncementObserver_cb _hidl_cb) {
+Return<void> BroadcastRadio::registerAnnouncementListener(
+    const hidl_vec<AnnouncementType>& enabled, const sp<IAnnouncementListener>& /* listener */,
+    registerAnnouncementListener_cb _hidl_cb) {
     ALOGV("%s(%s)", __func__, toString(enabled).c_str());
 
     _hidl_cb(Result::NOT_SUPPORTED, nullptr);
diff --git a/broadcastradio/2.0/default/BroadcastRadio.h b/broadcastradio/2.0/default/BroadcastRadio.h
index 7904946..8c14d9e 100644
--- a/broadcastradio/2.0/default/BroadcastRadio.h
+++ b/broadcastradio/2.0/default/BroadcastRadio.h
@@ -36,9 +36,9 @@
     Return<void> getDabRegionConfig(getDabRegionConfig_cb _hidl_cb);
     Return<void> openSession(const sp<ITunerCallback>& callback, openSession_cb _hidl_cb) override;
     Return<void> getImage(uint32_t id, getImage_cb _hidl_cb);
-    Return<void> registerAnnouncementObserver(const hidl_vec<AnnouncementType>& enabled,
-                                              const sp<IAnnouncementObserver>& cb,
-                                              registerAnnouncementObserver_cb _hidl_cb);
+    Return<void> registerAnnouncementListener(const hidl_vec<AnnouncementType>& enabled,
+                                              const sp<IAnnouncementListener>& listener,
+                                              registerAnnouncementListener_cb _hidl_cb);
 
     std::reference_wrapper<const VirtualRadio> mVirtualRadio;
     Properties mProperties;
diff --git a/broadcastradio/2.0/default/TunerSession.cpp b/broadcastradio/2.0/default/TunerSession.cpp
index 3166d86..56a3508 100644
--- a/broadcastradio/2.0/default/TunerSession.cpp
+++ b/broadcastradio/2.0/default/TunerSession.cpp
@@ -50,7 +50,12 @@
 }  // namespace delay
 
 TunerSession::TunerSession(BroadcastRadio& module, const sp<ITunerCallback>& callback)
-    : mCallback(callback), mModule(module) {}
+    : mCallback(callback), mModule(module) {
+    auto&& ranges = module.getAmFmConfig().ranges;
+    if (ranges.size() > 0) {
+        tuneInternalLocked(utils::make_selector_amfm(ranges[0].lowerBound));
+    }
+}
 
 // makes ProgramInfo that points to no program
 static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
@@ -63,6 +68,8 @@
 }
 
 void TunerSession::tuneInternalLocked(const ProgramSelector& sel) {
+    ALOGV("%s(%s)", __func__, toString(sel).c_str());
+
     VirtualProgram virtualProgram;
     ProgramInfo programInfo;
     if (virtualRadio().getProgram(sel, virtualProgram)) {
@@ -100,6 +107,8 @@
         return Result::INVALID_ARGUMENTS;
     }
 
+    cancelLocked();
+
     mIsTuneCompleted = false;
     auto task = [this, sel]() {
         lock_guard<mutex> lk(mMut);
@@ -115,6 +124,8 @@
     lock_guard<mutex> lk(mMut);
     if (mIsClosed) return Result::INVALID_STATE;
 
+    cancelLocked();
+
     auto list = virtualRadio().getProgramList();
 
     if (list.empty()) {
@@ -166,13 +177,13 @@
     lock_guard<mutex> lk(mMut);
     if (mIsClosed) return Result::INVALID_STATE;
 
+    cancelLocked();
+
     if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) {
         ALOGE("Can't step in anything else than AM/FM");
         return Result::NOT_SUPPORTED;
     }
 
-    mIsTuneCompleted = false;
-
     auto stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
     auto range = getAmFmRangeLocked();
     if (!range) {
@@ -188,6 +199,7 @@
     if (stepTo > range->upperBound) stepTo = range->lowerBound;
     if (stepTo < range->lowerBound) stepTo = range->upperBound;
 
+    mIsTuneCompleted = false;
     auto task = [this, stepTo]() {
         ALOGI("Performing step to %s", std::to_string(stepTo).c_str());
 
@@ -200,12 +212,22 @@
     return Result::OK;
 }
 
+void TunerSession::cancelLocked() {
+    ALOGV("%s", __func__);
+
+    mThread.cancelAll();
+    if (utils::getType(mCurrentProgram.primaryId) != IdentifierType::INVALID) {
+        mIsTuneCompleted = true;
+    }
+}
+
 Return<void> TunerSession::cancel() {
     ALOGV("%s", __func__);
     lock_guard<mutex> lk(mMut);
     if (mIsClosed) return {};
 
-    mThread.cancelAll();
+    cancelLocked();
+
     return {};
 }
 
@@ -241,7 +263,7 @@
     return {};
 }
 
-Return<void> TunerSession::getConfigFlag(ConfigFlag flag, getConfigFlag_cb _hidl_cb) {
+Return<void> TunerSession::isConfigFlagSet(ConfigFlag flag, isConfigFlagSet_cb _hidl_cb) {
     ALOGV("%s(%s)", __func__, toString(flag).c_str());
 
     _hidl_cb(Result::NOT_SUPPORTED, false);
@@ -281,7 +303,10 @@
 }
 
 std::optional<AmFmBandRange> TunerSession::getAmFmRangeLocked() const {
-    if (!mIsTuneCompleted) return {};
+    if (!mIsTuneCompleted) {
+        ALOGW("tune operation in process");
+        return {};
+    }
     if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) return {};
 
     auto freq = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
diff --git a/broadcastradio/2.0/default/TunerSession.h b/broadcastradio/2.0/default/TunerSession.h
index 5d27b1e..bf7c607 100644
--- a/broadcastradio/2.0/default/TunerSession.h
+++ b/broadcastradio/2.0/default/TunerSession.h
@@ -42,7 +42,7 @@
     virtual Return<void> cancel() override;
     virtual Return<Result> startProgramListUpdates(const ProgramFilter& filter);
     virtual Return<void> stopProgramListUpdates();
-    virtual Return<void> getConfigFlag(ConfigFlag flag, getConfigFlag_cb _hidl_cb);
+    virtual Return<void> isConfigFlagSet(ConfigFlag flag, isConfigFlagSet_cb _hidl_cb);
     virtual Return<Result> setConfigFlag(ConfigFlag flag, bool value);
     virtual Return<void> setParameters(const hidl_vec<VendorKeyValue>& parameters,
                                        setParameters_cb _hidl_cb) override;
@@ -63,6 +63,7 @@
     bool mIsTuneCompleted = false;
     ProgramSelector mCurrentProgram = {};
 
+    void cancelLocked();
     void tuneInternalLocked(const ProgramSelector& sel);
     const VirtualRadio& virtualRadio() const;
     const BroadcastRadio& module() const;
diff --git a/broadcastradio/2.0/types.hal b/broadcastradio/2.0/types.hal
index 1fd3715..9fd0738 100644
--- a/broadcastradio/2.0/types.hal
+++ b/broadcastradio/2.0/types.hal
@@ -40,7 +40,7 @@
 };
 
 /**
- * Configuration flags to be used with getConfigFlag and setConfigFlag methods
+ * Configuration flags to be used with isConfigFlagSet and setConfigFlag methods
  * of ITunerSession.
  */
 enum ConfigFlag : uint32_t {
@@ -215,7 +215,9 @@
     /**
      * Channel name, i.e. 5A, 7B.
      *
-     * It must match the following regular expression: /^[A-Z0-9]{2,5}$/.
+     * It must match the following regular expression:
+     * /^[A-Z0-9][A-Z0-9 ]{0,5}[A-Z0-9]$/ (2-7 uppercase alphanumeric characters
+     * without spaces allowed at the beginning nor end).
      */
     string label;
 
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index 1111478..37095d4 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -15,6 +15,8 @@
  */
 
 #define LOG_TAG "BcRadio.vts"
+#define LOG_NDEBUG 0
+#define EGMOCK_VERBOSE 1
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
@@ -90,7 +92,7 @@
     utils::ProgramInfoSet mProgramList;
 };
 
-struct AnnouncementObserverMock : public IAnnouncementObserver {
+struct AnnouncementListenerMock : public IAnnouncementListener {
     MOCK_METHOD1(onListUpdated, Return<void>(const hidl_vec<Announcement>&));
 };
 
@@ -113,7 +115,15 @@
     std::cout << "[  SKIPPED ] " << msg << std::endl;
 }
 
+MATCHER_P(InfoHasId, id,
+          std::string(negation ? "does not contain" : "contains") + " " + toString(id)) {
+    auto ids = utils::getAllIds(arg.selector, utils::getType(id));
+    return ids.end() != find(ids.begin(), ids.end(), id.value);
+}
+
 TunerCallbackMock::TunerCallbackMock() {
+    EXPECT_TIMEOUT_CALL(*this, onCurrentProgramInfoChanged, _).Times(AnyNumber());
+
     // we expect the antenna is connected through the whole test
     EXPECT_CALL(*this, onAntennaStateChange(false)).Times(0);
 }
@@ -332,11 +342,13 @@
     }
     ASSERT_EQ(Result::OK, halResult);
 
-    std::regex re("^[A-Z0-9]{2,5}$");
+    std::regex re("^[A-Z0-9][A-Z0-9 ]{0,5}[A-Z0-9]$");
     // double-check correctness of the test
     ASSERT_TRUE(std::regex_match("5A", re));
     ASSERT_FALSE(std::regex_match("5a", re));
-    ASSERT_FALSE(std::regex_match("123ABC", re));
+    ASSERT_FALSE(std::regex_match("1234ABCD", re));
+    ASSERT_TRUE(std::regex_match("CN 12D", re));
+    ASSERT_FALSE(std::regex_match(" 5A", re));
 
     for (auto&& entry : config) {
         EXPECT_TRUE(std::regex_match(std::string(entry.label), re));
@@ -362,9 +374,19 @@
     uint64_t freq = 100100;  // 100.1 FM
     auto sel = make_selector_amfm(freq);
 
+    /* TODO(b/69958777): there is a race condition between tune() and onCurrentProgramInfoChanged
+     * callback setting infoCb, because egmock cannot distinguish calls with different matchers
+     * (there is one here and one in callback constructor).
+     *
+     * This sleep workaround will fix default implementation, but the real HW tests will still be
+     * flaky. We probably need to implement egmock alternative based on actions.
+     */
+    std::this_thread::sleep_for(100ms);
+
     // try tuning
     ProgramInfo infoCb = {};
-    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _)
+    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged,
+                        InfoHasId(utils::make_identifier(IdentifierType::AMFM_FREQUENCY, freq)))
         .Times(AnyNumber())
         .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
     auto result = mSession->tune(sel);
@@ -379,6 +401,8 @@
     EXPECT_EQ(Result::OK, result);
     EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
 
+    ALOGD("current program info: %s", toString(infoCb).c_str());
+
     // it should tune exactly to what was requested
     auto freqs = utils::getAllIds(infoCb.selector, IdentifierType::AMFM_FREQUENCY);
     EXPECT_NE(freqs.end(), find(freqs.begin(), freqs.end(), freq));
@@ -442,6 +466,9 @@
 TEST_F(BroadcastRadioHalTest, Scan) {
     ASSERT_TRUE(openSession());
 
+    // TODO(b/69958777): see FmTune workaround
+    std::this_thread::sleep_for(100ms);
+
     EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _);
     auto result = mSession->scan(true /* up */, true /* skip subchannel */);
     EXPECT_EQ(Result::OK, result);
@@ -464,9 +491,15 @@
 TEST_F(BroadcastRadioHalTest, Step) {
     ASSERT_TRUE(openSession());
 
+    // TODO(b/69958777): see FmTune workaround
+    std::this_thread::sleep_for(100ms);
+
     EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _).Times(AnyNumber());
     auto result = mSession->step(true /* up */);
-    if (result == Result::NOT_SUPPORTED) return;
+    if (result == Result::NOT_SUPPORTED) {
+        printSkipped("step not supported");
+        return;
+    }
     EXPECT_EQ(Result::OK, result);
     EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
 
@@ -584,16 +617,16 @@
  * Test getting config flags.
  *
  * Verifies that:
- * - getConfigFlag either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
+ * - isConfigFlagSet either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
  * - call success or failure is consistent with setConfigFlag.
  */
-TEST_F(BroadcastRadioHalTest, GetConfigFlags) {
+TEST_F(BroadcastRadioHalTest, FetchConfigFlags) {
     ASSERT_TRUE(openSession());
 
     for (auto flag : gConfigFlagValues) {
         auto halResult = Result::UNKNOWN_ERROR;
         auto cb = [&](Result result, bool) { halResult = result; };
-        auto hidlResult = mSession->getConfigFlag(flag, cb);
+        auto hidlResult = mSession->isConfigFlagSet(flag, cb);
         EXPECT_TRUE(hidlResult.isOk());
 
         if (halResult != Result::NOT_SUPPORTED && halResult != Result::INVALID_STATE) {
@@ -613,7 +646,7 @@
  *
  * Verifies that:
  * - setConfigFlag either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
- * - getConfigFlag reflects the state requested immediately after the set call.
+ * - isConfigFlagSet reflects the state requested immediately after the set call.
  */
 TEST_F(BroadcastRadioHalTest, SetConfigFlags) {
     ASSERT_TRUE(openSession());
@@ -625,7 +658,7 @@
             halResult = result;
             gotValue = value;
         };
-        auto hidlResult = mSession->getConfigFlag(flag, cb);
+        auto hidlResult = mSession->isConfigFlagSet(flag, cb);
         EXPECT_TRUE(hidlResult.isOk());
         EXPECT_EQ(Result::OK, halResult);
         return gotValue;
@@ -702,15 +735,15 @@
 }
 
 /**
- * Test announcement observer registration.
+ * Test announcement listener registration.
  *
  * Verifies that:
- *  - registerAnnouncementObserver either succeeds or returns NOT_SUPPORTED;
+ *  - registerAnnouncementListener either succeeds or returns NOT_SUPPORTED;
  *  - if it succeeds, it returns a valid close handle (which is a nullptr otherwise);
  *  - closing handle does not crash.
  */
-TEST_F(BroadcastRadioHalTest, AnnouncementObserverRegistration) {
-    sp<AnnouncementObserverMock> observer = new AnnouncementObserverMock();
+TEST_F(BroadcastRadioHalTest, AnnouncementListenerRegistration) {
+    sp<AnnouncementListenerMock> listener = new AnnouncementListenerMock();
 
     Result halResult = Result::UNKNOWN_ERROR;
     sp<ICloseHandle> closeHandle = nullptr;
@@ -720,7 +753,7 @@
     };
 
     auto hidlResult =
-        mModule->registerAnnouncementObserver({AnnouncementType::EMERGENCY}, observer, cb);
+        mModule->registerAnnouncementListener({AnnouncementType::EMERGENCY}, listener, cb);
     ASSERT_TRUE(hidlResult.isOk());
 
     if (halResult == Result::NOT_SUPPORTED) {
diff --git a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
index 12453bb..1f716f1 100644
--- a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
+++ b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
@@ -13,12 +13,27 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
-#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_VTS_MOCK_TIMEOUT
+#define ANDROID_HARDWARE_BROADCASTRADIO_VTS_MOCK_TIMEOUT
 
 #include <gmock/gmock.h>
 #include <thread>
 
+#ifndef EGMOCK_VERBOSE
+#define EGMOCK_VERBOSE 0
+#endif
+
+/**
+ * Print log message.
+ *
+ * INTERNAL IMPLEMENTATION - don't use in user code.
+ */
+#if EGMOCK_VERBOSE
+#define EGMOCK_LOG_(...) ALOGV("egmock: " __VA_ARGS__)
+#else
+#define EGMOCK_LOG_(...)
+#endif
+
 /**
  * Common helper objects for gmock timeout extension.
  *
@@ -61,6 +76,7 @@
     auto invokeMock = [&]() { return egmock_##Method(__VA_ARGS__); }; \
     auto notify = [&]() {                                             \
         std::lock_guard<std::mutex> lk(egmock_mut_##Method);          \
+        EGMOCK_LOG_(#Method " called");                               \
         egmock_called_##Method = true;                                \
         egmock_cond_##Method.notify_all();                            \
     };                                                                \
@@ -105,6 +121,7 @@
  *     EXPECT_TIMEOUT_CALL(account, charge, 100, Currency::USD);
  */
 #define EXPECT_TIMEOUT_CALL(obj, Method, ...) \
+    EGMOCK_LOG_(#Method " expected to call"); \
     (obj).egmock_called_##Method = false;     \
     EXPECT_CALL(obj, egmock_##Method(__VA_ARGS__))
 
@@ -124,6 +141,7 @@
  */
 #define EXPECT_TIMEOUT_CALL_WAIT(obj, Method, timeout)                      \
     {                                                                       \
+        EGMOCK_LOG_("waiting for " #Method " call");                        \
         std::unique_lock<std::mutex> lk((obj).egmock_mut_##Method);         \
         if (!(obj).egmock_called_##Method) {                                \
             auto status = (obj).egmock_cond_##Method.wait_for(lk, timeout); \
@@ -131,4 +149,4 @@
         }                                                                   \
     }
 
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_VTS_MOCK_TIMEOUT
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
index 3a4bc9c..9217a82 100644
--- a/camera/common/1.0/default/CameraModule.cpp
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -425,6 +425,13 @@
     return -ENODEV;
 }
 
+void CameraModule::removeCamera(int cameraId) {
+    free_camera_metadata(
+        const_cast<camera_metadata_t*>(mCameraInfoMap[cameraId].static_camera_characteristics));
+    mCameraInfoMap.removeItem(cameraId);
+    mDeviceVersionMap.removeItem(cameraId);
+}
+
 uint16_t CameraModule::getModuleApiVersion() const {
     return mModule->common.module_api_version;
 }
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
index fd8b943..e9741ef 100644
--- a/camera/common/1.0/default/HandleImporter.cpp
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -134,6 +134,65 @@
     }
 }
 
+YCbCrLayout HandleImporter::lockYCbCr(
+        buffer_handle_t& buf, uint64_t cpuUsage,
+        const IMapper::Rect& accessRegion) {
+    Mutex::Autolock lock(mLock);
+    YCbCrLayout layout = {};
+
+    if (!mInitialized) {
+        initializeLocked();
+    }
+
+    if (mMapper == nullptr) {
+        ALOGE("%s: mMapper is null!", __FUNCTION__);
+        return layout;
+    }
+
+    hidl_handle acquireFenceHandle;
+    auto buffer = const_cast<native_handle_t*>(buf);
+    mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+            [&](const auto& tmpError, const auto& tmpLayout) {
+                if (tmpError == MapperError::NONE) {
+                    layout = tmpLayout;
+                } else {
+                    ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
+                }
+           });
+
+    ALOGV("%s: layout y %p cb %p cr %p y_str %d c_str %d c_step %d",
+            __FUNCTION__, layout.y, layout.cb, layout.cr,
+            layout.yStride, layout.cStride, layout.chromaStep);
+    return layout;
+}
+
+int HandleImporter::unlock(buffer_handle_t& buf) {
+    int releaseFence = -1;
+    auto buffer = const_cast<native_handle_t*>(buf);
+    mMapper->unlock(
+        buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+            if (tmpError == MapperError::NONE) {
+                auto fenceHandle = tmpReleaseFence.getNativeHandle();
+                if (fenceHandle) {
+                    if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
+                        ALOGE("%s: bad release fence numInts %d numFds %d",
+                                __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
+                        return;
+                    }
+                    releaseFence = dup(fenceHandle->data[0]);
+                    if (releaseFence <= 0) {
+                        ALOGE("%s: bad release fence FD %d",
+                                __FUNCTION__, releaseFence);
+                    }
+                }
+            } else {
+                ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
+            }
+        });
+
+    return releaseFence;
+}
+
 } // namespace helper
 } // namespace V1_0
 } // namespace common
diff --git a/camera/common/1.0/default/OWNERS b/camera/common/1.0/default/OWNERS
new file mode 100644
index 0000000..18acfee
--- /dev/null
+++ b/camera/common/1.0/default/OWNERS
@@ -0,0 +1,6 @@
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h
index 9fbfbd5..deebd09 100644
--- a/camera/common/1.0/default/include/CameraModule.h
+++ b/camera/common/1.0/default/include/CameraModule.h
@@ -63,6 +63,8 @@
     const char* getModuleAuthor() const;
     // Only used by CameraModuleFixture native test. Do NOT use elsewhere.
     void *getDso();
+    // Only used by CameraProvider
+    void removeCamera(int cameraId);
 
 private:
     // Derive camera characteristics keys defined after HAL device version
diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h
index e47397c..443362d 100644
--- a/camera/common/1.0/default/include/HandleImporter.h
+++ b/camera/common/1.0/default/include/HandleImporter.h
@@ -22,6 +22,7 @@
 #include <cutils/native_handle.h>
 
 using android::hardware::graphics::mapper::V2_0::IMapper;
+using android::hardware::graphics::mapper::V2_0::YCbCrLayout;
 
 namespace android {
 namespace hardware {
@@ -43,6 +44,12 @@
     bool importFence(const native_handle_t* handle, int& fd) const;
     void closeFence(int fd) const;
 
+    // Assume caller has done waiting for acquire fences
+    YCbCrLayout lockYCbCr(buffer_handle_t& buf, uint64_t cpuUsage,
+                          const IMapper::Rect& accessRegion);
+
+    int unlock(buffer_handle_t& buf); // returns release fence
+
 private:
     void initializeLocked();
     void cleanup();
@@ -60,4 +67,4 @@
 } // namespace hardware
 } // namespace android
 
-#endif // CAMERA_COMMON_1_0_HANDLEIMPORTED_H
\ No newline at end of file
+#endif // CAMERA_COMMON_1_0_HANDLEIMPORTED_H
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index 295ee32..dfbb976 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -40,9 +40,11 @@
         mCameraDeviceNames(cameraDeviceNames) {
     mCameraIdInt = atoi(mCameraId.c_str());
     // Should not reach here as provider also validate ID
-    if (mCameraIdInt < 0 || mCameraIdInt >= module->getNumberOfCameras()) {
+    if (mCameraIdInt < 0) {
         ALOGE("%s: Invalid camera id: %s", __FUNCTION__, mCameraId.c_str());
         mInitFail = true;
+    } else if (mCameraIdInt >= mModule->getNumberOfCameras()) {
+        ALOGI("%s: Adding a new camera id: %s", __FUNCTION__, mCameraId.c_str());
     }
 
     mDeviceVersion = mModule->getDeviceVersion(mCameraIdInt);
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 631404e..ae275ae 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -333,11 +333,10 @@
     mResultMetadataQueue = q;
 }
 
-void CameraDeviceSession::ResultBatcher::registerBatch(
-        const hidl_vec<CaptureRequest>& requests) {
+void CameraDeviceSession::ResultBatcher::registerBatch(uint32_t frameNumber, uint32_t batchSize) {
     auto batch = std::make_shared<InflightBatch>();
-    batch->mFirstFrame = requests[0].frameNumber;
-    batch->mBatchSize = requests.size();
+    batch->mFirstFrame = frameNumber;
+    batch->mBatchSize = batchSize;
     batch->mLastFrame = batch->mFirstFrame + batch->mBatchSize - 1;
     batch->mNumPartialResults = mNumPartialResults;
     for (int id : mStreamsToBatch) {
@@ -739,8 +738,14 @@
 // Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
 Return<void> CameraDeviceSession::constructDefaultRequestSettings(
         RequestTemplate type, ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb)  {
-    Status status = initStatus();
     CameraMetadata outMetadata;
+    Status status = constructDefaultRequestSettingsRaw( (int) type, &outMetadata);
+    _hidl_cb(status, outMetadata);
+    return Void();
+}
+
+Status CameraDeviceSession::constructDefaultRequestSettingsRaw(int type, CameraMetadata *outMetadata) {
+    Status status = initStatus();
     const camera_metadata_t *rawRequest;
     if (status == Status::OK) {
         ATRACE_BEGIN("camera3->construct_default_request_settings");
@@ -762,15 +767,14 @@
                         defaultBoost, 1);
                 const camera_metadata_t *metaBuffer =
                         mOverridenRequest.getAndLock();
-                convertToHidl(metaBuffer, &outMetadata);
+                convertToHidl(metaBuffer, outMetadata);
                 mOverridenRequest.unlock(metaBuffer);
             } else {
-                convertToHidl(rawRequest, &outMetadata);
+                convertToHidl(rawRequest, outMetadata);
             }
         }
     }
-    _hidl_cb(status, outMetadata);
-    return Void();
+    return status;
 }
 
 /**
@@ -1010,7 +1014,7 @@
     }
 
     if (s == Status::OK && requests.size() > 1) {
-        mResultBatcher.registerBatch(requests);
+        mResultBatcher.registerBatch(requests[0].frameNumber, requests.size());
     }
 
     _hidl_cb(s, numRequestProcessed);
@@ -1111,6 +1115,7 @@
             halRequest.settings = settingsOverride.getAndLock();
         }
     }
+    halRequest.num_physcam_settings = 0;
 
     ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
     ATRACE_BEGIN("camera3->process_capture_request");
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index c5a63c8..dd73b39 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -112,7 +112,9 @@
     Return<Status> flush();
     Return<void> close();
 
-    //Helper methods
+    // Helper methods
+    Status constructDefaultRequestSettingsRaw(int type, CameraMetadata *outMetadata);
+
     bool preProcessConfigurationLocked(const StreamConfiguration& requestedConfiguration,
             camera3_stream_configuration_t *stream_list /*out*/,
             hidl_vec<camera3_stream_t*> *streams /*out*/);
@@ -184,7 +186,7 @@
         void setBatchedStreams(const std::vector<int>& streamsToBatch);
         void setResultMetadataQueue(std::shared_ptr<ResultMetadataQueue> q);
 
-        void registerBatch(const hidl_vec<CaptureRequest>& requests);
+        void registerBatch(uint32_t frameNumber, uint32_t batchSize);
         void notify(NotifyMsg& msg);
         void processCaptureResult(CaptureResult& result);
 
diff --git a/camera/device/3.4/Android.bp b/camera/device/3.4/Android.bp
index 2523fa8..b3757c0 100644
--- a/camera/device/3.4/Android.bp
+++ b/camera/device/3.4/Android.bp
@@ -18,6 +18,12 @@
         "android.hidl.base@1.0",
     ],
     types: [
+        "CaptureRequest",
+        "HalStream",
+        "HalStreamConfiguration",
+        "PhysicalCameraSetting",
+        "RequestTemplate",
+        "Stream",
         "StreamConfiguration",
     ],
     gen_java: false,
diff --git a/camera/device/3.4/ICameraDeviceSession.hal b/camera/device/3.4/ICameraDeviceSession.hal
index e5693b2..7afcf94 100644
--- a/camera/device/3.4/ICameraDeviceSession.hal
+++ b/camera/device/3.4/ICameraDeviceSession.hal
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2017-2018 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.
@@ -17,8 +17,10 @@
 package android.hardware.camera.device@3.4;
 
 import android.hardware.camera.common@1.0::Status;
+import @3.2::CameraMetadata;
 import @3.3::ICameraDeviceSession;
 import @3.3::HalStreamConfiguration;
+import @3.2::BufferCache;
 
 /**
  * Camera device active session interface.
@@ -29,6 +31,43 @@
 interface ICameraDeviceSession extends @3.3::ICameraDeviceSession {
 
     /**
+     * constructDefaultRequestSettings_3_4:
+     *
+     * Create capture settings for standard camera use cases. Supports the
+     * new template enums added in @3.4.
+     *
+     * The device must return a settings buffer that is configured to meet the
+     * requested use case, which must be one of the CAMERA3_TEMPLATE_*
+     * enums. All request control fields must be included.
+     *
+     * Performance requirements:
+     *
+     * This must be a non-blocking call. The HAL should return from this call
+     * in 1ms, and must return from this call in 5ms.
+     *
+     * Return values:
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful construction of default settings.
+     *     INTERNAL_ERROR:
+     *         An unexpected internal error occurred, and the default settings
+     *         are not available.
+     *     ILLEGAL_ARGUMENT:
+     *         The camera HAL does not support the input template type
+     *     CAMERA_DISCONNECTED:
+     *         An external camera device has been disconnected, and is no longer
+     *         available. This camera device interface is now stale, and a new
+     *         instance must be acquired if the device is reconnected. All
+     *         subsequent calls on this interface must return
+     *         CAMERA_DISCONNECTED.
+     * @return requestTemplate The default capture request settings for the requested
+     *     use case, or an empty metadata structure if status is not OK.
+     *
+     */
+    constructDefaultRequestSettings_3_4(RequestTemplate type) generates
+            (Status status, @3.2::CameraMetadata requestTemplate);
+
+    /**
      * configureStreams_3_4:
      *
      * Identical to @3.3::ICameraDeviceSession.configureStreams, except that:
@@ -69,6 +108,39 @@
      */
     configureStreams_3_4(@3.4::StreamConfiguration requestedConfiguration)
             generates (Status status,
-                       @3.3::HalStreamConfiguration halConfiguration);
+                       @3.4::HalStreamConfiguration halConfiguration);
 
+    /**
+     * processCaptureRequest_3_4:
+     *
+     * Identical to @3.2::ICameraDeviceSession.processCaptureRequest, except that:
+     *
+     * - The capture request can include individual settings for physical camera devices
+     *   backing a logical multi-camera.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful start to processing the capture request
+     *     ILLEGAL_ARGUMENT:
+     *         If the input is malformed (the settings are empty when not
+     *         allowed, the physical camera settings are invalid, there are 0
+     *         output buffers, etc) and capture processing
+     *         cannot start. Failures during request processing must be
+     *         handled by calling ICameraDeviceCallback::notify(). In case of
+     *         this error, the framework retains responsibility for the
+     *         stream buffers' fences and the buffer handles; the HAL must not
+     *         close the fences or return these buffers with
+     *         ICameraDeviceCallback::processCaptureResult().
+     *     INTERNAL_ERROR:
+     *         If the camera device has encountered a serious error. After this
+     *         error is returned, only the close() method can be successfully
+     *         called by the framework.
+     * @return numRequestProcessed Number of requests successfully processed by
+     *     camera HAL. When status is OK, this must be equal to the size of
+     *     requests. When the call fails, this number is the number of requests
+     *     that HAL processed successfully before HAL runs into an error.
+     *
+     */
+    processCaptureRequest_3_4(vec<CaptureRequest> requests, vec<BufferCache> cachesToRemove)
+            generates (Status status, uint32_t numRequestProcessed);
 };
diff --git a/camera/device/3.4/default/Android.bp b/camera/device/3.4/default/Android.bp
index c0ce838..61ac244 100644
--- a/camera/device/3.4/default/Android.bp
+++ b/camera/device/3.4/default/Android.bp
@@ -17,7 +17,13 @@
 cc_library_headers {
     name: "camera.device@3.4-impl_headers",
     vendor: true,
-    export_include_dirs: ["include/device_v3_4_impl"],
+    export_include_dirs: ["include/device_v3_4_impl"]
+}
+
+cc_library_headers {
+    name: "camera.device@3.4-external-impl_headers",
+    vendor: true,
+    export_include_dirs: ["include/ext_device_v3_4_impl"]
 }
 
 cc_library_shared {
@@ -28,6 +34,7 @@
     srcs: [
         "CameraDevice.cpp",
         "CameraDeviceSession.cpp",
+        "convert.cpp",
     ],
     shared_libs: [
         "libhidlbase",
@@ -54,3 +61,40 @@
         "libfmq",
     ],
 }
+
+cc_library_shared {
+    name: "camera.device@3.4-external-impl",
+    defaults: ["hidl_defaults"],
+    proprietary: true,
+    vendor: true,
+    srcs: [
+        "ExternalCameraDevice.cpp",
+        "ExternalCameraDeviceSession.cpp"
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "libcutils",
+        "camera.device@3.2-impl",
+        "camera.device@3.3-impl",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.3",
+        "android.hardware.camera.device@3.4",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.graphics.mapper@2.0",
+        "liblog",
+        "libhardware",
+        "libcamera_metadata",
+        "libfmq",
+        "libsync",
+        "libyuv",
+    ],
+    static_libs: [
+        "android.hardware.camera.common@1.0-helper",
+    ],
+    local_include_dirs: ["include/ext_device_v3_4_impl"],
+    export_shared_lib_headers: [
+        "libfmq",
+    ],
+}
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index 0ae470f..d054788 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2017-2018 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.
@@ -40,9 +40,17 @@
 CameraDeviceSession::~CameraDeviceSession() {
 }
 
+Return<void> CameraDeviceSession::constructDefaultRequestSettings_3_4(
+        RequestTemplate type, ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb)  {
+    V3_2::CameraMetadata outMetadata;
+    Status status = constructDefaultRequestSettingsRaw( (int) type, &outMetadata);
+    _hidl_cb(status, outMetadata);
+    return Void();
+}
+
 Return<void> CameraDeviceSession::configureStreams_3_4(
-        const V3_4::StreamConfiguration& requestedConfiguration,
-        ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb)  {
+        const StreamConfiguration& requestedConfiguration,
+        ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb)  {
     Status status = initStatus();
     HalStreamConfiguration outStreams;
 
@@ -86,7 +94,7 @@
     camera3_stream_configuration_t stream_list{};
     hidl_vec<camera3_stream_t*> streams;
     stream_list.session_parameters = paramBuffer;
-    if (!preProcessConfigurationLocked(requestedConfiguration.v3_2, &stream_list, &streams)) {
+    if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
         _hidl_cb(Status::INTERNAL_ERROR, outStreams);
         return Void();
     }
@@ -98,7 +106,7 @@
     // In case Hal returns error most likely it was not able to release
     // the corresponding resources of the deleted streams.
     if (ret == OK) {
-        postProcessConfigurationLocked(requestedConfiguration.v3_2);
+        postProcessConfigurationLocked_3_4(requestedConfiguration);
     }
 
     if (ret == -EINVAL) {
@@ -106,7 +114,7 @@
     } else if (ret != OK) {
         status = Status::INTERNAL_ERROR;
     } else {
-        V3_3::implementation::convertToHidl(stream_list, &outStreams);
+        V3_4::implementation::convertToHidl(stream_list, &outStreams);
         mFirstRequest = true;
     }
 
@@ -114,6 +122,291 @@
     return Void();
 }
 
+bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
+        const StreamConfiguration& requestedConfiguration,
+        camera3_stream_configuration_t *stream_list /*out*/,
+        hidl_vec<camera3_stream_t*> *streams /*out*/) {
+
+    if ((stream_list == nullptr) || (streams == nullptr)) {
+        return false;
+    }
+
+    stream_list->operation_mode = (uint32_t) requestedConfiguration.operationMode;
+    stream_list->num_streams = requestedConfiguration.streams.size();
+    streams->resize(stream_list->num_streams);
+    stream_list->streams = streams->data();
+
+    for (uint32_t i = 0; i < stream_list->num_streams; i++) {
+        int id = requestedConfiguration.streams[i].v3_2.id;
+
+        if (mStreamMap.count(id) == 0) {
+            Camera3Stream stream;
+            convertFromHidl(requestedConfiguration.streams[i], &stream);
+            mStreamMap[id] = stream;
+            mPhysicalCameraIdMap[id] = requestedConfiguration.streams[i].physicalCameraId;
+            mStreamMap[id].data_space = mapToLegacyDataspace(
+                    mStreamMap[id].data_space);
+            mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str();
+            mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
+        } else {
+            // width/height/format must not change, but usage/rotation might need to change
+            if (mStreamMap[id].stream_type !=
+                    (int) requestedConfiguration.streams[i].v3_2.streamType ||
+                    mStreamMap[id].width != requestedConfiguration.streams[i].v3_2.width ||
+                    mStreamMap[id].height != requestedConfiguration.streams[i].v3_2.height ||
+                    mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format ||
+                    mStreamMap[id].data_space !=
+                            mapToLegacyDataspace( static_cast<android_dataspace_t> (
+                                    requestedConfiguration.streams[i].v3_2.dataSpace)) ||
+                    mPhysicalCameraIdMap[id] != requestedConfiguration.streams[i].physicalCameraId) {
+                ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
+                return false;
+            }
+            mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation;
+            mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage;
+        }
+        (*streams)[i] = &mStreamMap[id];
+    }
+
+    return true;
+}
+
+void CameraDeviceSession::postProcessConfigurationLocked_3_4(
+        const StreamConfiguration& requestedConfiguration) {
+    // delete unused streams, note we do this after adding new streams to ensure new stream
+    // will not have the same address as deleted stream, and HAL has a chance to reference
+    // the to be deleted stream in configure_streams call
+    for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
+        int id = it->first;
+        bool found = false;
+        for (const auto& stream : requestedConfiguration.streams) {
+            if (id == stream.v3_2.id) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            // Unmap all buffers of deleted stream
+            // in case the configuration call succeeds and HAL
+            // is able to release the corresponding resources too.
+            cleanupBuffersLocked(id);
+            it = mStreamMap.erase(it);
+        } else {
+            ++it;
+        }
+    }
+
+    // Track video streams
+    mVideoStreamIds.clear();
+    for (const auto& stream : requestedConfiguration.streams) {
+        if (stream.v3_2.streamType == StreamType::OUTPUT &&
+            stream.v3_2.usage &
+                graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
+            mVideoStreamIds.push_back(stream.v3_2.id);
+        }
+    }
+    mResultBatcher.setBatchedStreams(mVideoStreamIds);
+}
+
+Return<void> CameraDeviceSession::processCaptureRequest_3_4(
+        const hidl_vec<V3_4::CaptureRequest>& requests,
+        const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+        ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb)  {
+    updateBufferCaches(cachesToRemove);
+
+    uint32_t numRequestProcessed = 0;
+    Status s = Status::OK;
+    for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
+        s = processOneCaptureRequest_3_4(requests[i]);
+        if (s != Status::OK) {
+            break;
+        }
+    }
+
+    if (s == Status::OK && requests.size() > 1) {
+        mResultBatcher.registerBatch(requests[0].v3_2.frameNumber, requests.size());
+    }
+
+    _hidl_cb(s, numRequestProcessed);
+    return Void();
+}
+
+Status CameraDeviceSession::processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request)  {
+    Status status = initStatus();
+    if (status != Status::OK) {
+        ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
+        return status;
+    }
+
+    camera3_capture_request_t halRequest;
+    halRequest.frame_number = request.v3_2.frameNumber;
+
+    bool converted = true;
+    V3_2::CameraMetadata settingsFmq;  // settings from FMQ
+    if (request.v3_2.fmqSettingsSize > 0) {
+        // non-blocking read; client must write metadata before calling
+        // processOneCaptureRequest
+        settingsFmq.resize(request.v3_2.fmqSettingsSize);
+        bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.v3_2.fmqSettingsSize);
+        if (read) {
+            converted = V3_2::implementation::convertFromHidl(settingsFmq, &halRequest.settings);
+        } else {
+            ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
+            converted = false;
+        }
+    } else {
+        converted = V3_2::implementation::convertFromHidl(request.v3_2.settings,
+                &halRequest.settings);
+    }
+
+    if (!converted) {
+        ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    if (mFirstRequest && halRequest.settings == nullptr) {
+        ALOGE("%s: capture request settings must not be null for first request!",
+                __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    hidl_vec<buffer_handle_t*> allBufPtrs;
+    hidl_vec<int> allFences;
+    bool hasInputBuf = (request.v3_2.inputBuffer.streamId != -1 &&
+            request.v3_2.inputBuffer.bufferId != 0);
+    size_t numOutputBufs = request.v3_2.outputBuffers.size();
+    size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
+
+    if (numOutputBufs == 0) {
+        ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    status = importRequest(request.v3_2, allBufPtrs, allFences);
+    if (status != Status::OK) {
+        return status;
+    }
+
+    hidl_vec<camera3_stream_buffer_t> outHalBufs;
+    outHalBufs.resize(numOutputBufs);
+    bool aeCancelTriggerNeeded = false;
+    ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
+    {
+        Mutex::Autolock _l(mInflightLock);
+        if (hasInputBuf) {
+            auto streamId = request.v3_2.inputBuffer.streamId;
+            auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
+            auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
+            convertFromHidl(
+                    allBufPtrs[numOutputBufs], request.v3_2.inputBuffer.status,
+                    &mStreamMap[request.v3_2.inputBuffer.streamId], allFences[numOutputBufs],
+                    &bufCache);
+            bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
+            halRequest.input_buffer = &bufCache;
+        } else {
+            halRequest.input_buffer = nullptr;
+        }
+
+        halRequest.num_output_buffers = numOutputBufs;
+        for (size_t i = 0; i < numOutputBufs; i++) {
+            auto streamId = request.v3_2.outputBuffers[i].streamId;
+            auto key = std::make_pair(streamId, request.v3_2.frameNumber);
+            auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
+            convertFromHidl(
+                    allBufPtrs[i], request.v3_2.outputBuffers[i].status,
+                    &mStreamMap[streamId], allFences[i],
+                    &bufCache);
+            bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
+            outHalBufs[i] = bufCache;
+        }
+        halRequest.output_buffers = outHalBufs.data();
+
+        AETriggerCancelOverride triggerOverride;
+        aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
+                halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
+        if (aeCancelTriggerNeeded) {
+            mInflightAETriggerOverrides[halRequest.frame_number] =
+                    triggerOverride;
+            halRequest.settings = settingsOverride.getAndLock();
+        }
+    }
+
+    std::vector<const char *> physicalCameraIds;
+    std::vector<const camera_metadata_t *> physicalCameraSettings;
+    std::vector<V3_2::CameraMetadata> physicalFmq;
+    size_t settingsCount = request.physicalCameraSettings.size();
+    if (settingsCount > 0) {
+        physicalCameraIds.reserve(settingsCount);
+        physicalCameraSettings.reserve(settingsCount);
+        physicalFmq.reserve(settingsCount);
+
+        for (size_t i = 0; i < settingsCount; i++) {
+            uint64_t settingsSize = request.physicalCameraSettings[i].fmqSettingsSize;
+            const camera_metadata_t *settings;
+            if (settingsSize > 0) {
+                physicalFmq.push_back(V3_2::CameraMetadata(settingsSize));
+                bool read = mRequestMetadataQueue->read(physicalFmq[i].data(), settingsSize);
+                if (read) {
+                    converted = V3_2::implementation::convertFromHidl(physicalFmq[i], &settings);
+                    physicalCameraSettings.push_back(settings);
+                } else {
+                    ALOGE("%s: physical camera settings metadata couldn't be read from fmq!",
+                            __FUNCTION__);
+                    converted = false;
+                }
+            } else {
+                converted = V3_2::implementation::convertFromHidl(
+                        request.physicalCameraSettings[i].settings, &settings);
+                physicalCameraSettings.push_back(settings);
+            }
+
+            if (!converted) {
+                ALOGE("%s: physical camera settings metadata is corrupt!", __FUNCTION__);
+                return Status::ILLEGAL_ARGUMENT;
+            }
+            physicalCameraIds.push_back(request.physicalCameraSettings[i].physicalCameraId.c_str());
+        }
+    }
+    halRequest.num_physcam_settings = settingsCount;
+    halRequest.physcam_id = physicalCameraIds.data();
+    halRequest.physcam_settings = physicalCameraSettings.data();
+
+    ATRACE_ASYNC_BEGIN("frame capture", request.v3_2.frameNumber);
+    ATRACE_BEGIN("camera3->process_capture_request");
+    status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
+    ATRACE_END();
+    if (aeCancelTriggerNeeded) {
+        settingsOverride.unlock(halRequest.settings);
+    }
+    if (ret != OK) {
+        Mutex::Autolock _l(mInflightLock);
+        ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
+
+        cleanupInflightFences(allFences, numBufs);
+        if (hasInputBuf) {
+            auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
+            mInflightBuffers.erase(key);
+        }
+        for (size_t i = 0; i < numOutputBufs; i++) {
+            auto key = std::make_pair(request.v3_2.outputBuffers[i].streamId,
+                    request.v3_2.frameNumber);
+            mInflightBuffers.erase(key);
+        }
+        if (aeCancelTriggerNeeded) {
+            mInflightAETriggerOverrides.erase(request.v3_2.frameNumber);
+        }
+
+        if (ret == BAD_VALUE) {
+            return Status::ILLEGAL_ARGUMENT;
+        } else {
+            return Status::INTERNAL_ERROR;
+        }
+    }
+
+    mFirstRequest = false;
+    return Status::OK;
+}
+
 } // namespace implementation
 }  // namespace V3_4
 }  // namespace device
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
new file mode 100644
index 0000000..4ad1768
--- /dev/null
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -0,0 +1,793 @@
+/*
+ * Copyright (C) 2018 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 "ExtCamDev@3.4"
+#define LOG_NDEBUG 0
+#include <log/log.h>
+
+#include <array>
+#include <linux/videodev2.h>
+#include "android-base/macros.h"
+#include "CameraMetadata.h"
+#include "../../3.2/default/include/convert.h"
+#include "ExternalCameraDevice_3_4.h"
+
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_4 {
+namespace implementation {
+
+namespace {
+// Only support MJPEG for now as it seems to be the one supports higher fps
+// Other formats to consider in the future:
+// * V4L2_PIX_FMT_YVU420 (== YV12)
+// * V4L2_PIX_FMT_YVYU (YVYU: can be converted to YV12 or other YUV420_888 formats)
+const std::array<uint32_t, /*size*/1> kSupportedFourCCs {{
+    V4L2_PIX_FMT_MJPEG
+}}; // double braces required in C++11
+
+// TODO: b/72261897
+//       Define max size/fps this Android device can advertise (and streaming at reasonable speed)
+//       Also make sure that can be done without editing source code
+
+// TODO: b/72261675: make it dynamic since this affects memory usage
+const int kMaxJpegSize = {13 * 1024 * 1024};  // 13MB
+} // anonymous namespace
+
+ExternalCameraDevice::ExternalCameraDevice(const std::string& cameraId) :
+        mCameraId(cameraId) {
+    status_t ret = initCameraCharacteristics();
+    if (ret != OK) {
+        ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret);
+        mInitFailed = true;
+    }
+}
+
+ExternalCameraDevice::~ExternalCameraDevice() {}
+
+bool ExternalCameraDevice::isInitFailed() {
+    return mInitFailed;
+}
+
+Return<void> ExternalCameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) {
+    CameraResourceCost resCost;
+    resCost.resourceCost = 100;
+    _hidl_cb(Status::OK, resCost);
+    return Void();
+}
+
+Return<void> ExternalCameraDevice::getCameraCharacteristics(
+        getCameraCharacteristics_cb _hidl_cb) {
+    Mutex::Autolock _l(mLock);
+    V3_2::CameraMetadata hidlChars;
+
+    if (isInitFailed()) {
+        _hidl_cb(Status::INTERNAL_ERROR, hidlChars);
+        return Void();
+    }
+
+    const camera_metadata_t* rawMetadata = mCameraCharacteristics.getAndLock();
+    V3_2::implementation::convertToHidl(rawMetadata, &hidlChars);
+    _hidl_cb(Status::OK, hidlChars);
+    mCameraCharacteristics.unlock(rawMetadata);
+    return Void();
+}
+
+Return<Status> ExternalCameraDevice::setTorchMode(TorchMode) {
+    return Status::METHOD_NOT_SUPPORTED;
+}
+
+Return<void> ExternalCameraDevice::open(
+        const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) {
+    Status status = Status::OK;
+    sp<ExternalCameraDeviceSession> session = nullptr;
+
+    if (callback == nullptr) {
+        ALOGE("%s: cannot open camera %s. callback is null!",
+                __FUNCTION__, mCameraId.c_str());
+        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+        return Void();
+    }
+
+    if (isInitFailed()) {
+        ALOGE("%s: cannot open camera %s. camera init failed!",
+                __FUNCTION__, mCameraId.c_str());
+        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+        return Void();
+    }
+
+    mLock.lock();
+
+    ALOGV("%s: Initializing device for camera %s", __FUNCTION__, mCameraId.c_str());
+    session = mSession.promote();
+    if (session != nullptr && !session->isClosed()) {
+        ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
+        mLock.unlock();
+        _hidl_cb(Status::CAMERA_IN_USE, nullptr);
+        return Void();
+    }
+
+    unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
+    if (fd.get() < 0) {
+        ALOGE("%s: v4l2 device open %s failed: %s",
+                __FUNCTION__, mCameraId.c_str(), strerror(errno));
+        mLock.unlock();
+        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+        return Void();
+    }
+
+    session = new ExternalCameraDeviceSession(
+            callback, mSupportedFormats, mCameraCharacteristics, std::move(fd));
+    if (session == nullptr) {
+        ALOGE("%s: camera device session allocation failed", __FUNCTION__);
+        mLock.unlock();
+        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+        return Void();
+    }
+    if (session->isInitFailed()) {
+        ALOGE("%s: camera device session init failed", __FUNCTION__);
+        session = nullptr;
+        mLock.unlock();
+        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+        return Void();
+    }
+    mSession = session;
+
+    mLock.unlock();
+
+    _hidl_cb(status, session->getInterface());
+    return Void();
+}
+
+Return<void> ExternalCameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) {
+    Mutex::Autolock _l(mLock);
+    if (handle.getNativeHandle() == nullptr) {
+        ALOGE("%s: handle must not be null", __FUNCTION__);
+        return Void();
+    }
+    if (handle->numFds != 1 || handle->numInts != 0) {
+        ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
+                __FUNCTION__, handle->numFds, handle->numInts);
+        return Void();
+    }
+    int fd = handle->data[0];
+    if (mSession == nullptr) {
+        dprintf(fd, "No active camera device session instance\n");
+        return Void();
+    }
+    auto session = mSession.promote();
+    if (session == nullptr) {
+        dprintf(fd, "No active camera device session instance\n");
+        return Void();
+    }
+    // Call into active session to dump states
+    session->dumpState(handle);
+    return Void();
+}
+
+
+status_t ExternalCameraDevice::initCameraCharacteristics() {
+    if (mCameraCharacteristics.isEmpty()) {
+        // init camera characteristics
+        unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
+        if (fd.get() < 0) {
+            ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mCameraId.c_str());
+            return DEAD_OBJECT;
+        }
+
+        status_t ret;
+        ret = initDefaultCharsKeys(&mCameraCharacteristics);
+        if (ret != OK) {
+            ALOGE("%s: init default characteristics key failed: errorno %d", __FUNCTION__, ret);
+            mCameraCharacteristics.clear();
+            return ret;
+        }
+
+        ret = initCameraControlsCharsKeys(fd.get(), &mCameraCharacteristics);
+        if (ret != OK) {
+            ALOGE("%s: init camera control characteristics key failed: errorno %d", __FUNCTION__, ret);
+            mCameraCharacteristics.clear();
+            return ret;
+        }
+
+        ret = initOutputCharsKeys(fd.get(), &mCameraCharacteristics);
+        if (ret != OK) {
+            ALOGE("%s: init output characteristics key failed: errorno %d", __FUNCTION__, ret);
+            mCameraCharacteristics.clear();
+            return ret;
+        }
+    }
+    return OK;
+}
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+#define UPDATE(tag, data, size)                    \
+do {                                               \
+  if (metadata->update((tag), (data), (size))) {   \
+    ALOGE("Update " #tag " failed!");              \
+    return -EINVAL;                                \
+  }                                                \
+} while (0)
+
+status_t ExternalCameraDevice::initDefaultCharsKeys(
+        ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
+    // TODO: changed to HARDWARELEVEL_EXTERNAL later
+    const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+    UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1);
+
+    // android.colorCorrection
+    const uint8_t availableAberrationModes[] = {
+        ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF};
+    UPDATE(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+           availableAberrationModes, ARRAY_SIZE(availableAberrationModes));
+
+    // android.control
+    const uint8_t antibandingMode =
+        ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
+    UPDATE(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+           &antibandingMode, 1);
+
+    const int32_t controlMaxRegions[] = {/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0};
+    UPDATE(ANDROID_CONTROL_MAX_REGIONS, controlMaxRegions,
+           ARRAY_SIZE(controlMaxRegions));
+
+    const uint8_t videoStabilizationMode =
+        ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
+    UPDATE(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+           &videoStabilizationMode, 1);
+
+    const uint8_t awbAvailableMode = ANDROID_CONTROL_AWB_MODE_AUTO;
+    UPDATE(ANDROID_CONTROL_AWB_AVAILABLE_MODES, &awbAvailableMode, 1);
+
+    const uint8_t aeAvailableMode = ANDROID_CONTROL_AE_MODE_ON;
+    UPDATE(ANDROID_CONTROL_AE_AVAILABLE_MODES, &aeAvailableMode, 1);
+
+    const uint8_t availableFffect = ANDROID_CONTROL_EFFECT_MODE_OFF;
+    UPDATE(ANDROID_CONTROL_AVAILABLE_EFFECTS, &availableFffect, 1);
+
+    const uint8_t controlAvailableModes[] = {ANDROID_CONTROL_MODE_OFF,
+                                             ANDROID_CONTROL_MODE_AUTO};
+    UPDATE(ANDROID_CONTROL_AVAILABLE_MODES, controlAvailableModes,
+           ARRAY_SIZE(controlAvailableModes));
+
+    // android.edge
+    const uint8_t edgeMode = ANDROID_EDGE_MODE_OFF;
+    UPDATE(ANDROID_EDGE_AVAILABLE_EDGE_MODES, &edgeMode, 1);
+
+    // android.flash
+    const uint8_t flashInfo = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
+    UPDATE(ANDROID_FLASH_INFO_AVAILABLE, &flashInfo, 1);
+
+    // android.hotPixel
+    const uint8_t hotPixelMode = ANDROID_HOT_PIXEL_MODE_OFF;
+    UPDATE(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, &hotPixelMode, 1);
+
+    // android.jpeg
+    // TODO: b/72261675 See if we can provide thumbnail size for all jpeg aspect ratios
+    const int32_t jpegAvailableThumbnailSizes[] = {0, 0, 240, 180};
+    UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes,
+           ARRAY_SIZE(jpegAvailableThumbnailSizes));
+
+    const int32_t jpegMaxSize = kMaxJpegSize;
+    UPDATE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
+
+    const uint8_t jpegQuality = 90;
+    UPDATE(ANDROID_JPEG_QUALITY, &jpegQuality, 1);
+    UPDATE(ANDROID_JPEG_THUMBNAIL_QUALITY, &jpegQuality, 1);
+
+    const int32_t jpegOrientation = 0;
+    UPDATE(ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1);
+
+    // android.lens
+    const uint8_t focusDistanceCalibration =
+            ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
+    UPDATE(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, &focusDistanceCalibration, 1);
+
+    const uint8_t opticalStabilizationMode =
+        ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
+    UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+           &opticalStabilizationMode, 1);
+
+    const uint8_t facing = ANDROID_LENS_FACING_EXTERNAL;
+    UPDATE(ANDROID_LENS_FACING, &facing, 1);
+
+    // android.noiseReduction
+    const uint8_t noiseReductionMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
+    UPDATE(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+           &noiseReductionMode, 1);
+    UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noiseReductionMode, 1);
+
+    // android.request
+    const uint8_t availableCapabilities[] = {
+        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE};
+    UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities,
+           ARRAY_SIZE(availableCapabilities));
+
+    const int32_t partialResultCount = 1;
+    UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount, 1);
+
+    // This means pipeline latency of X frame intervals. The maximum number is 4.
+    const uint8_t requestPipelineMaxDepth = 4;
+    UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &requestPipelineMaxDepth, 1);
+    UPDATE(ANDROID_REQUEST_PIPELINE_DEPTH, &requestPipelineMaxDepth, 1);
+
+    // Three numbers represent the maximum numbers of different types of output
+    // streams simultaneously. The types are raw sensor, processed (but not
+    // stalling), and processed (but stalling). For usb limited mode, raw sensor
+    // is not supported. Stalling stream is JPEG. Non-stalling streams are
+    // YUV_420_888 or YV12.
+    const int32_t requestMaxNumOutputStreams[] = {
+            /*RAW*/0,
+            /*Processed*/ExternalCameraDeviceSession::kMaxProcessedStream,
+            /*Stall*/ExternalCameraDeviceSession::kMaxStallStream};
+    UPDATE(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, requestMaxNumOutputStreams,
+           ARRAY_SIZE(requestMaxNumOutputStreams));
+
+    // Limited mode doesn't support reprocessing.
+    const int32_t requestMaxNumInputStreams = 0;
+    UPDATE(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &requestMaxNumInputStreams,
+           1);
+
+    // android.scaler
+    // TODO: b/72263447 V4L2_CID_ZOOM_*
+    const float scalerAvailableMaxDigitalZoom[] = {1};
+    UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+           scalerAvailableMaxDigitalZoom,
+           ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
+
+    const uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
+    UPDATE(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
+
+    const int32_t testPatternModes[] = {
+        ANDROID_SENSOR_TEST_PATTERN_MODE_OFF};
+    UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes,
+           ARRAY_SIZE(testPatternModes));
+    UPDATE(ANDROID_SENSOR_TEST_PATTERN_MODE, &testPatternModes[0], 1);
+
+    const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
+    UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestampSource, 1);
+
+    // Orientation probably isn't useful for external facing camera?
+    const int32_t orientation = 0;
+    UPDATE(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
+
+    // android.shading
+    const uint8_t availabeMode = ANDROID_SHADING_MODE_OFF;
+    UPDATE(ANDROID_SHADING_AVAILABLE_MODES, &availabeMode, 1);
+
+    // android.statistics
+    const uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
+    UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, &faceDetectMode,
+           1);
+
+    const int32_t maxFaceCount = 0;
+    UPDATE(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &maxFaceCount, 1);
+
+    const uint8_t availableHotpixelMode =
+        ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
+    UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
+           &availableHotpixelMode, 1);
+
+    const uint8_t lensShadingMapMode =
+        ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
+    UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
+           &lensShadingMapMode, 1);
+
+    // android.sync
+    const int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
+    UPDATE(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
+
+    /* Other sensor/RAW realted keys:
+     * android.sensor.info.colorFilterArrangement -> no need if we don't do RAW
+     * android.sensor.info.physicalSize           -> not available
+     * android.sensor.info.whiteLevel             -> not available/not needed
+     * android.sensor.info.lensShadingApplied     -> not needed
+     * android.sensor.info.preCorrectionActiveArraySize -> not available/not needed
+     * android.sensor.blackLevelPattern           -> not available/not needed
+     */
+
+    const int32_t availableRequestKeys[] = {
+        ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+        ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+        ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+        ANDROID_CONTROL_AE_LOCK,
+        ANDROID_CONTROL_AE_MODE,
+        ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+        ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+        ANDROID_CONTROL_AF_MODE,
+        ANDROID_CONTROL_AF_TRIGGER,
+        ANDROID_CONTROL_AWB_LOCK,
+        ANDROID_CONTROL_AWB_MODE,
+        ANDROID_CONTROL_CAPTURE_INTENT,
+        ANDROID_CONTROL_EFFECT_MODE,
+        ANDROID_CONTROL_MODE,
+        ANDROID_CONTROL_SCENE_MODE,
+        ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+        ANDROID_FLASH_MODE,
+        ANDROID_JPEG_ORIENTATION,
+        ANDROID_JPEG_QUALITY,
+        ANDROID_JPEG_THUMBNAIL_QUALITY,
+        ANDROID_JPEG_THUMBNAIL_SIZE,
+        ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+        ANDROID_NOISE_REDUCTION_MODE,
+        ANDROID_SCALER_CROP_REGION,
+        ANDROID_SENSOR_TEST_PATTERN_MODE,
+        ANDROID_STATISTICS_FACE_DETECT_MODE,
+        ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE};
+    UPDATE(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, availableRequestKeys,
+           ARRAY_SIZE(availableRequestKeys));
+
+    const int32_t availableResultKeys[] = {
+        ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+        ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+        ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+        ANDROID_CONTROL_AE_LOCK,
+        ANDROID_CONTROL_AE_MODE,
+        ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+        ANDROID_CONTROL_AE_STATE,
+        ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+        ANDROID_CONTROL_AF_MODE,
+        ANDROID_CONTROL_AF_STATE,
+        ANDROID_CONTROL_AF_TRIGGER,
+        ANDROID_CONTROL_AWB_LOCK,
+        ANDROID_CONTROL_AWB_MODE,
+        ANDROID_CONTROL_AWB_STATE,
+        ANDROID_CONTROL_CAPTURE_INTENT,
+        ANDROID_CONTROL_EFFECT_MODE,
+        ANDROID_CONTROL_MODE,
+        ANDROID_CONTROL_SCENE_MODE,
+        ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+        ANDROID_FLASH_MODE,
+        ANDROID_FLASH_STATE,
+        ANDROID_JPEG_ORIENTATION,
+        ANDROID_JPEG_QUALITY,
+        ANDROID_JPEG_THUMBNAIL_QUALITY,
+        ANDROID_JPEG_THUMBNAIL_SIZE,
+        ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+        ANDROID_NOISE_REDUCTION_MODE,
+        ANDROID_REQUEST_PIPELINE_DEPTH,
+        ANDROID_SCALER_CROP_REGION,
+        ANDROID_SENSOR_TIMESTAMP,
+        ANDROID_STATISTICS_FACE_DETECT_MODE,
+        ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+        ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+        ANDROID_STATISTICS_SCENE_FLICKER};
+    UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, availableResultKeys,
+           ARRAY_SIZE(availableResultKeys));
+
+    const int32_t availableCharacteristicsKeys[] = {
+        ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+        ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+        ANDROID_CONTROL_AE_AVAILABLE_MODES,
+        ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+        ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+        ANDROID_CONTROL_AE_COMPENSATION_STEP,
+        ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+        ANDROID_CONTROL_AF_AVAILABLE_MODES,
+        ANDROID_CONTROL_AVAILABLE_EFFECTS,
+        ANDROID_CONTROL_AVAILABLE_MODES,
+        ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
+        ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+        ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+        ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+        ANDROID_CONTROL_MAX_REGIONS,
+        ANDROID_FLASH_INFO_AVAILABLE,
+        ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
+        ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+        ANDROID_LENS_FACING,
+        ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+        ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
+        ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+        ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+        ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
+        ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+        ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
+        ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
+        ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+        ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+        ANDROID_SCALER_CROPPING_TYPE,
+        ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+        ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+        ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+        ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
+        ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
+        ANDROID_SENSOR_ORIENTATION,
+        ANDROID_SHADING_AVAILABLE_MODES,
+        ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
+        ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
+        ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
+        ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
+        ANDROID_SYNC_MAX_LATENCY};
+    UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
+           availableCharacteristicsKeys,
+           ARRAY_SIZE(availableCharacteristicsKeys));
+
+    return OK;
+}
+
+status_t ExternalCameraDevice::initCameraControlsCharsKeys(int,
+        ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
+    /**
+     * android.sensor.info.sensitivityRange   -> V4L2_CID_ISO_SENSITIVITY
+     * android.sensor.info.exposureTimeRange  -> V4L2_CID_EXPOSURE_ABSOLUTE
+     * android.sensor.info.maxFrameDuration   -> TBD
+     * android.lens.info.minimumFocusDistance -> V4L2_CID_FOCUS_ABSOLUTE
+     * android.lens.info.hyperfocalDistance
+     * android.lens.info.availableFocalLengths -> not available?
+     */
+
+    // android.control
+    // No AE compensation support for now.
+    // TODO: V4L2_CID_EXPOSURE_BIAS
+    const int32_t controlAeCompensationRange[] = {0, 0};
+    UPDATE(ANDROID_CONTROL_AE_COMPENSATION_RANGE, controlAeCompensationRange,
+           ARRAY_SIZE(controlAeCompensationRange));
+    const camera_metadata_rational_t controlAeCompensationStep[] = {{0, 1}};
+    UPDATE(ANDROID_CONTROL_AE_COMPENSATION_STEP, controlAeCompensationStep,
+           ARRAY_SIZE(controlAeCompensationStep));
+
+
+    // TODO: Check V4L2_CID_AUTO_FOCUS_*.
+    const uint8_t afAvailableModes[] = {ANDROID_CONTROL_AF_MODE_AUTO,
+                                        ANDROID_CONTROL_AF_MODE_OFF};
+    UPDATE(ANDROID_CONTROL_AF_AVAILABLE_MODES, afAvailableModes,
+           ARRAY_SIZE(afAvailableModes));
+
+    // TODO: V4L2_CID_SCENE_MODE
+    const uint8_t availableSceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
+    UPDATE(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, &availableSceneMode, 1);
+
+    // TODO: V4L2_CID_3A_LOCK
+    const uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
+    UPDATE(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailable, 1);
+    const uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
+    UPDATE(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &awbLockAvailable, 1);
+
+    // TODO: V4L2_CID_ZOOM_*
+    const float scalerAvailableMaxDigitalZoom[] = {1};
+    UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+           scalerAvailableMaxDigitalZoom,
+           ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
+
+    return OK;
+}
+
+status_t ExternalCameraDevice::initOutputCharsKeys(int fd,
+        ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
+    initSupportedFormatsLocked(fd);
+    if (mSupportedFormats.empty()) {
+        ALOGE("%s: Init supported format list failed", __FUNCTION__);
+        return UNKNOWN_ERROR;
+    }
+
+    std::vector<int32_t> streamConfigurations;
+    std::vector<int64_t> minFrameDurations;
+    std::vector<int64_t> stallDurations;
+    int64_t maxFrameDuration = 0;
+    int32_t maxFps = std::numeric_limits<int32_t>::min();
+    int32_t minFps = std::numeric_limits<int32_t>::max();
+    std::set<int32_t> framerates;
+
+    std::array<int, /*size*/3> halFormats{{
+        HAL_PIXEL_FORMAT_BLOB,
+        HAL_PIXEL_FORMAT_YCbCr_420_888,
+        HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}};
+
+    for (const auto& supportedFormat : mSupportedFormats) {
+        for (const auto& format : halFormats) {
+            streamConfigurations.push_back(format);
+            streamConfigurations.push_back(supportedFormat.width);
+            streamConfigurations.push_back(supportedFormat.height);
+            streamConfigurations.push_back(
+                    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
+        }
+
+        int64_t min_frame_duration = std::numeric_limits<int64_t>::max();
+        for (const auto& frameRate : supportedFormat.frameRates) {
+            int64_t frame_duration = 1000000000LL / frameRate;
+            if (frame_duration < min_frame_duration) {
+                min_frame_duration = frame_duration;
+            }
+            if (frame_duration > maxFrameDuration) {
+                maxFrameDuration = frame_duration;
+            }
+            int32_t frameRateInt = static_cast<int32_t>(frameRate);
+            if (minFps > frameRateInt) {
+                minFps = frameRateInt;
+            }
+            if (maxFps < frameRateInt) {
+                maxFps = frameRateInt;
+            }
+            framerates.insert(frameRateInt);
+        }
+
+        for (const auto& format : halFormats) {
+            minFrameDurations.push_back(format);
+            minFrameDurations.push_back(supportedFormat.width);
+            minFrameDurations.push_back(supportedFormat.height);
+            minFrameDurations.push_back(min_frame_duration);
+        }
+
+        // The stall duration is 0 for non-jpeg formats. For JPEG format, stall
+        // duration can be 0 if JPEG is small. Here we choose 1 sec for JPEG.
+        // TODO: b/72261675. Maybe set this dynamically
+        for (const auto& format : halFormats) {
+            const int64_t NS_TO_SECOND = 1000000000;
+            int64_t stall_duration =
+                    (format == HAL_PIXEL_FORMAT_BLOB) ? NS_TO_SECOND : 0;
+            stallDurations.push_back(format);
+            stallDurations.push_back(supportedFormat.width);
+            stallDurations.push_back(supportedFormat.height);
+            stallDurations.push_back(stall_duration);
+        }
+    }
+
+    // The document in aeAvailableTargetFpsRanges section says the minFps should
+    // not be larger than 15.
+    // We cannot support fixed 30fps but Android requires (min, max) and
+    // (max, max) ranges.
+    // TODO: populate more, right now this does not support 30,30 if the device
+    //       has higher than 30 fps modes
+    std::vector<int32_t> fpsRanges;
+    // Variable range
+    fpsRanges.push_back(minFps);
+    fpsRanges.push_back(maxFps);
+    // Fixed ranges
+    for (const auto& framerate : framerates) {
+        fpsRanges.push_back(framerate);
+        fpsRanges.push_back(framerate);
+    }
+    UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(),
+           fpsRanges.size());
+
+    UPDATE(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+           streamConfigurations.data(), streamConfigurations.size());
+
+    UPDATE(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+           minFrameDurations.data(), minFrameDurations.size());
+
+    UPDATE(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, stallDurations.data(),
+           stallDurations.size());
+
+    UPDATE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, &maxFrameDuration, 1);
+
+    SupportedV4L2Format maximumFormat {.width = 0, .height = 0};
+    for (const auto& supportedFormat : mSupportedFormats) {
+        if (supportedFormat.width >= maximumFormat.width &&
+            supportedFormat.height >= maximumFormat.height) {
+            maximumFormat = supportedFormat;
+        }
+    }
+    int32_t activeArraySize[] = {0, 0,
+                                 static_cast<int32_t>(maximumFormat.width),
+                                 static_cast<int32_t>(maximumFormat.height)};
+    UPDATE(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
+           activeArraySize, ARRAY_SIZE(activeArraySize));
+    UPDATE(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArraySize,
+           ARRAY_SIZE(activeArraySize));
+
+    int32_t pixelArraySize[] = {static_cast<int32_t>(maximumFormat.width),
+                                static_cast<int32_t>(maximumFormat.height)};
+    UPDATE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArraySize,
+           ARRAY_SIZE(pixelArraySize));
+    return OK;
+}
+
+#undef ARRAY_SIZE
+#undef UPDATE
+
+void ExternalCameraDevice::getFrameRateList(
+        int fd, SupportedV4L2Format* format) {
+    format->frameRates.clear();
+
+    v4l2_frmivalenum frameInterval {
+        .pixel_format = format->fourcc,
+        .width = format->width,
+        .height = format->height,
+        .index = 0
+    };
+
+    for (frameInterval.index = 0;
+            TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frameInterval)) == 0;
+            ++frameInterval.index) {
+        if (frameInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
+            if (frameInterval.discrete.numerator != 0) {
+                float framerate = frameInterval.discrete.denominator /
+                        static_cast<float>(frameInterval.discrete.numerator);
+                ALOGV("index:%d, format:%c%c%c%c, w %d, h %d, framerate %f",
+                    frameInterval.index,
+                    frameInterval.pixel_format & 0xFF,
+                    (frameInterval.pixel_format >> 8) & 0xFF,
+                    (frameInterval.pixel_format >> 16) & 0xFF,
+                    (frameInterval.pixel_format >> 24) & 0xFF,
+                    frameInterval.width, frameInterval.height, framerate);
+                format->frameRates.push_back(framerate);
+            }
+        }
+    }
+
+    if (format->frameRates.empty()) {
+        ALOGE("%s: failed to get supported frame rates for format:%c%c%c%c w %d h %d",
+                __FUNCTION__,
+                frameInterval.pixel_format & 0xFF,
+                (frameInterval.pixel_format >> 8) & 0xFF,
+                (frameInterval.pixel_format >> 16) & 0xFF,
+                (frameInterval.pixel_format >> 24) & 0xFF,
+                frameInterval.width, frameInterval.height);
+    }
+}
+
+void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
+    struct v4l2_fmtdesc fmtdesc {
+        .index = 0,
+        .type = V4L2_BUF_TYPE_VIDEO_CAPTURE};
+    int ret = 0;
+    while (ret == 0) {
+        ret = TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc));
+        ALOGD("index:%d,ret:%d, format:%c%c%c%c", fmtdesc.index, ret,
+                fmtdesc.pixelformat & 0xFF,
+                (fmtdesc.pixelformat >> 8) & 0xFF,
+                (fmtdesc.pixelformat >> 16) & 0xFF,
+                (fmtdesc.pixelformat >> 24) & 0xFF);
+        if (ret == 0 && !(fmtdesc.flags & V4L2_FMT_FLAG_EMULATED)) {
+            auto it = std::find (
+                    kSupportedFourCCs.begin(), kSupportedFourCCs.end(), fmtdesc.pixelformat);
+            if (it != kSupportedFourCCs.end()) {
+                // Found supported format
+                v4l2_frmsizeenum frameSize {
+                        .index = 0,
+                        .pixel_format = fmtdesc.pixelformat};
+                for (; TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frameSize)) == 0;
+                        ++frameSize.index) {
+                    if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+                        ALOGD("index:%d, format:%c%c%c%c, w %d, h %d", frameSize.index,
+                            fmtdesc.pixelformat & 0xFF,
+                            (fmtdesc.pixelformat >> 8) & 0xFF,
+                            (fmtdesc.pixelformat >> 16) & 0xFF,
+                            (fmtdesc.pixelformat >> 24) & 0xFF,
+                            frameSize.discrete.width, frameSize.discrete.height);
+                        // Disregard h > w formats so all aspect ratio (h/w) <= 1.0
+                        // This will simplify the crop/scaling logic down the road
+                        if (frameSize.discrete.height > frameSize.discrete.width) {
+                            continue;
+                        }
+                        SupportedV4L2Format format {
+                            .width = frameSize.discrete.width,
+                            .height = frameSize.discrete.height,
+                            .fourcc = fmtdesc.pixelformat
+                        };
+                        getFrameRateList(fd, &format);
+                        if (!format.frameRates.empty()) {
+                            mSupportedFormats.push_back(format);
+                        }
+                    }
+                }
+            }
+        }
+        fmtdesc.index++;
+    }
+}
+
+}  // namespace implementation
+}  // namespace V3_4
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
new file mode 100644
index 0000000..507f092
--- /dev/null
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -0,0 +1,2009 @@
+/*
+ * Copyright (C) 2018 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 "ExtCamDevSsn@3.4"
+//#define LOG_NDEBUG 0
+#include <log/log.h>
+
+#include <inttypes.h>
+#include "ExternalCameraDeviceSession.h"
+
+#include "android-base/macros.h"
+#include "algorithm"
+#include <utils/Timers.h>
+#include <cmath>
+#include <linux/videodev2.h>
+#include <sync/sync.h>
+
+#define HAVE_JPEG // required for libyuv.h to export MJPEG decode APIs
+#include <libyuv.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_4 {
+namespace implementation {
+
+// Size of request/result metadata fast message queue. Change to 0 to always use hwbinder buffer.
+static constexpr size_t kMetadataMsgQueueSize = 1 << 20 /* 1MB */;
+const int ExternalCameraDeviceSession::kMaxProcessedStream;
+const int ExternalCameraDeviceSession::kMaxStallStream;
+const Size kMaxVideoSize = {1920, 1088}; // Maybe this should be programmable
+const int kNumVideoBuffers = 4; // number of v4l2 buffers when streaming <= kMaxVideoSize
+const int kNumStillBuffers = 2; // number of v4l2 buffers when streaming > kMaxVideoSize
+const int kBadFramesAfterStreamOn = 1; // drop x frames after streamOn to get rid of some initial
+                                       // bad frames. TODO: develop a better bad frame detection
+                                       // method
+
+// Aspect ratio is defined as width/height here and ExternalCameraDevice
+// will guarantee all supported sizes has width >= height (so aspect ratio >= 1.0)
+#define ASPECT_RATIO(sz) (static_cast<float>((sz).width) / (sz).height)
+const float kMaxAspectRatio = std::numeric_limits<float>::max();
+const float kMinAspectRatio = 1.f;
+
+HandleImporter ExternalCameraDeviceSession::sHandleImporter;
+
+bool isAspectRatioClose(float ar1, float ar2) {
+    const float kAspectRatioMatchThres = 0.01f; // This threshold is good enough to distinguish
+                                                // 4:3/16:9/20:9
+    return (std::abs(ar1 - ar2) < kAspectRatioMatchThres);
+}
+
+ExternalCameraDeviceSession::ExternalCameraDeviceSession(
+        const sp<ICameraDeviceCallback>& callback,
+        const std::vector<SupportedV4L2Format>& supportedFormats,
+        const common::V1_0::helper::CameraMetadata& chars,
+        unique_fd v4l2Fd) :
+        mCallback(callback),
+        mCameraCharacteristics(chars),
+        mV4l2Fd(std::move(v4l2Fd)),
+        mSupportedFormats(sortFormats(supportedFormats)),
+        mCroppingType(initCroppingType(mSupportedFormats)),
+        mOutputThread(new OutputThread(this, mCroppingType)) {
+    mInitFail = initialize();
+}
+
+std::vector<SupportedV4L2Format> ExternalCameraDeviceSession::sortFormats(
+            const std::vector<SupportedV4L2Format>& inFmts) {
+    std::vector<SupportedV4L2Format> fmts = inFmts;
+    std::sort(fmts.begin(), fmts.end(),
+            [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
+                if (a.width == b.width) {
+                    return a.height < b.height;
+                }
+                return a.width < b.width;
+            });
+    return fmts;
+}
+
+CroppingType ExternalCameraDeviceSession::initCroppingType(
+        const std::vector<SupportedV4L2Format>& sortedFmts) {
+    const auto& maxSize = sortedFmts[sortedFmts.size() - 1];
+    float maxSizeAr = ASPECT_RATIO(maxSize);
+    float minAr = kMinAspectRatio;
+    float maxAr = kMaxAspectRatio;
+    for (const auto& fmt : sortedFmts) {
+        float ar = ASPECT_RATIO(fmt);
+        if (ar < minAr) {
+            minAr = ar;
+        }
+        if (ar > maxAr) {
+            maxAr = ar;
+        }
+    }
+
+    CroppingType ct = VERTICAL;
+    if (isAspectRatioClose(maxSizeAr, maxAr)) {
+        // Ex: 16:9 sensor, cropping horizontally to get to 4:3
+        ct = HORIZONTAL;
+    } else if (isAspectRatioClose(maxSizeAr, minAr)) {
+        // Ex: 4:3 sensor, cropping vertically to get to 16:9
+        ct = VERTICAL;
+    } else {
+        ALOGI("%s: camera maxSizeAr %f is not close to minAr %f or maxAr %f",
+                __FUNCTION__, maxSizeAr, minAr, maxAr);
+        if ((maxSizeAr - minAr) < (maxAr - maxSizeAr)) {
+            ct = VERTICAL;
+        } else {
+            ct = HORIZONTAL;
+        }
+    }
+    ALOGI("%s: camera croppingType is %d", __FUNCTION__, ct);
+    return ct;
+}
+
+
+bool ExternalCameraDeviceSession::initialize() {
+    if (mV4l2Fd.get() < 0) {
+        ALOGE("%s: invalid v4l2 device fd %d!", __FUNCTION__, mV4l2Fd.get());
+        return true;
+    }
+
+    status_t status = initDefaultRequests();
+    if (status != OK) {
+        ALOGE("%s: init default requests failed!", __FUNCTION__);
+        return true;
+    }
+
+    mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
+            kMetadataMsgQueueSize, false /* non blocking */);
+    if (!mRequestMetadataQueue->isValid()) {
+        ALOGE("%s: invalid request fmq", __FUNCTION__);
+        return true;
+    }
+    mResultMetadataQueue = std::make_shared<RequestMetadataQueue>(
+            kMetadataMsgQueueSize, false /* non blocking */);
+    if (!mResultMetadataQueue->isValid()) {
+        ALOGE("%s: invalid result fmq", __FUNCTION__);
+        return true;
+    }
+
+    // TODO: check is PRIORITY_DISPLAY enough?
+    mOutputThread->run("ExtCamOut", PRIORITY_DISPLAY);
+    return false;
+}
+
+Status ExternalCameraDeviceSession::initStatus() const {
+    Mutex::Autolock _l(mLock);
+    Status status = Status::OK;
+    if (mInitFail || mClosed) {
+        ALOGI("%s: sesssion initFailed %d closed %d", __FUNCTION__, mInitFail, mClosed);
+        status = Status::INTERNAL_ERROR;
+    }
+    return status;
+}
+
+ExternalCameraDeviceSession::~ExternalCameraDeviceSession() {
+    if (!isClosed()) {
+        ALOGE("ExternalCameraDeviceSession deleted before close!");
+        close();
+    }
+}
+
+void ExternalCameraDeviceSession::dumpState(const native_handle_t*) {
+    // TODO: b/72261676 dump more runtime information
+}
+
+Return<void> ExternalCameraDeviceSession::constructDefaultRequestSettings(
+        V3_2::RequestTemplate type,
+        V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) {
+    V3_2::CameraMetadata outMetadata;
+    Status status = constructDefaultRequestSettingsRaw(
+            static_cast<RequestTemplate>(type), &outMetadata);
+    _hidl_cb(status, outMetadata);
+    return Void();
+}
+
+Return<void> ExternalCameraDeviceSession::constructDefaultRequestSettings_3_4(
+        RequestTemplate type,
+        ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb)  {
+    V3_2::CameraMetadata outMetadata;
+    Status status = constructDefaultRequestSettingsRaw(type, &outMetadata);
+    _hidl_cb(status, outMetadata);
+    return Void();
+}
+
+Status ExternalCameraDeviceSession::constructDefaultRequestSettingsRaw(RequestTemplate type,
+        V3_2::CameraMetadata *outMetadata) {
+    CameraMetadata emptyMd;
+    Status status = initStatus();
+    if (status != Status::OK) {
+        return status;
+    }
+
+    switch (type) {
+        case RequestTemplate::PREVIEW:
+        case RequestTemplate::STILL_CAPTURE:
+        case RequestTemplate::VIDEO_RECORD:
+        case RequestTemplate::VIDEO_SNAPSHOT: {
+            *outMetadata = mDefaultRequests[type];
+            break;
+        }
+        case RequestTemplate::MANUAL:
+        case RequestTemplate::ZERO_SHUTTER_LAG:
+        case RequestTemplate::MOTION_TRACKING_PREVIEW:
+        case RequestTemplate::MOTION_TRACKING_BEST:
+            // Don't support MANUAL, ZSL, MOTION_TRACKING_* templates
+            status = Status::ILLEGAL_ARGUMENT;
+            break;
+        default:
+            ALOGE("%s: unknown request template type %d", __FUNCTION__, static_cast<int>(type));
+            status = Status::ILLEGAL_ARGUMENT;
+            break;
+    }
+    return status;
+}
+
+Return<void> ExternalCameraDeviceSession::configureStreams(
+        const V3_2::StreamConfiguration& streams,
+        ICameraDeviceSession::configureStreams_cb _hidl_cb) {
+    V3_2::HalStreamConfiguration outStreams;
+    V3_3::HalStreamConfiguration outStreams_v33;
+    Mutex::Autolock _il(mInterfaceLock);
+
+    Status status = configureStreams(streams, &outStreams_v33);
+    size_t size = outStreams_v33.streams.size();
+    outStreams.streams.resize(size);
+    for (size_t i = 0; i < size; i++) {
+        outStreams.streams[i] = outStreams_v33.streams[i].v3_2;
+    }
+    _hidl_cb(status, outStreams);
+    return Void();
+}
+
+Return<void> ExternalCameraDeviceSession::configureStreams_3_3(
+        const V3_2::StreamConfiguration& streams,
+        ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb) {
+    V3_3::HalStreamConfiguration outStreams;
+    Mutex::Autolock _il(mInterfaceLock);
+
+    Status status = configureStreams(streams, &outStreams);
+    _hidl_cb(status, outStreams);
+    return Void();
+}
+
+Return<void> ExternalCameraDeviceSession::configureStreams_3_4(
+        const V3_4::StreamConfiguration& requestedConfiguration,
+        ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb)  {
+    V3_2::StreamConfiguration config_v32;
+    V3_3::HalStreamConfiguration outStreams_v33;
+    Mutex::Autolock _il(mInterfaceLock);
+
+    config_v32.operationMode = requestedConfiguration.operationMode;
+    config_v32.streams.resize(requestedConfiguration.streams.size());
+    for (size_t i = 0; i < config_v32.streams.size(); i++) {
+        config_v32.streams[i] = requestedConfiguration.streams[i].v3_2;
+    }
+
+    // Ignore requestedConfiguration.sessionParams. External camera does not support it
+    Status status = configureStreams(config_v32, &outStreams_v33);
+
+    V3_4::HalStreamConfiguration outStreams;
+    outStreams.streams.resize(outStreams_v33.streams.size());
+    for (size_t i = 0; i < outStreams.streams.size(); i++) {
+        outStreams.streams[i].v3_3 = outStreams_v33.streams[i];
+    }
+    _hidl_cb(status, outStreams);
+    return Void();
+}
+
+Return<void> ExternalCameraDeviceSession::getCaptureRequestMetadataQueue(
+    ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) {
+    Mutex::Autolock _il(mInterfaceLock);
+    _hidl_cb(*mRequestMetadataQueue->getDesc());
+    return Void();
+}
+
+Return<void> ExternalCameraDeviceSession::getCaptureResultMetadataQueue(
+    ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) {
+    Mutex::Autolock _il(mInterfaceLock);
+    _hidl_cb(*mResultMetadataQueue->getDesc());
+    return Void();
+}
+
+Return<void> ExternalCameraDeviceSession::processCaptureRequest(
+        const hidl_vec<CaptureRequest>& requests,
+        const hidl_vec<BufferCache>& cachesToRemove,
+        ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) {
+    Mutex::Autolock _il(mInterfaceLock);
+    updateBufferCaches(cachesToRemove);
+
+    uint32_t numRequestProcessed = 0;
+    Status s = Status::OK;
+    for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
+        s = processOneCaptureRequest(requests[i]);
+        if (s != Status::OK) {
+            break;
+        }
+    }
+
+    _hidl_cb(s, numRequestProcessed);
+    return Void();
+}
+
+Return<void> ExternalCameraDeviceSession::processCaptureRequest_3_4(
+        const hidl_vec<V3_4::CaptureRequest>& requests,
+        const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+        ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) {
+    Mutex::Autolock _il(mInterfaceLock);
+    updateBufferCaches(cachesToRemove);
+
+    uint32_t numRequestProcessed = 0;
+    Status s = Status::OK;
+    for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
+        s = processOneCaptureRequest(requests[i].v3_2);
+        if (s != Status::OK) {
+            break;
+        }
+    }
+
+    _hidl_cb(s, numRequestProcessed);
+    return Void();
+}
+
+Return<Status> ExternalCameraDeviceSession::flush() {
+    return Status::OK;
+}
+
+Return<void> ExternalCameraDeviceSession::close() {
+    Mutex::Autolock _il(mInterfaceLock);
+    Mutex::Autolock _l(mLock);
+    if (!mClosed) {
+        // TODO: b/72261676 Cleanup inflight buffers/V4L2 buffer queue
+        ALOGV("%s: closing V4L2 camera FD %d", __FUNCTION__, mV4l2Fd.get());
+        mV4l2Fd.reset();
+        mOutputThread->requestExit(); // TODO: join?
+
+        // free all imported buffers
+        for(auto& pair : mCirculatingBuffers) {
+            CirculatingBuffers& buffers = pair.second;
+            for (auto& p2 : buffers) {
+                sHandleImporter.freeBuffer(p2.second);
+            }
+        }
+
+        mClosed = true;
+    }
+    return Void();
+}
+
+Status ExternalCameraDeviceSession::importRequest(
+        const CaptureRequest& request,
+        hidl_vec<buffer_handle_t*>& allBufPtrs,
+        hidl_vec<int>& allFences) {
+    size_t numOutputBufs = request.outputBuffers.size();
+    size_t numBufs = numOutputBufs;
+    // Validate all I/O buffers
+    hidl_vec<buffer_handle_t> allBufs;
+    hidl_vec<uint64_t> allBufIds;
+    allBufs.resize(numBufs);
+    allBufIds.resize(numBufs);
+    allBufPtrs.resize(numBufs);
+    allFences.resize(numBufs);
+    std::vector<int32_t> streamIds(numBufs);
+
+    for (size_t i = 0; i < numOutputBufs; i++) {
+        allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
+        allBufIds[i] = request.outputBuffers[i].bufferId;
+        allBufPtrs[i] = &allBufs[i];
+        streamIds[i] = request.outputBuffers[i].streamId;
+    }
+
+    for (size_t i = 0; i < numBufs; i++) {
+        buffer_handle_t buf = allBufs[i];
+        uint64_t bufId = allBufIds[i];
+        CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
+        if (cbs.count(bufId) == 0) {
+            if (buf == nullptr) {
+                ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
+                return Status::ILLEGAL_ARGUMENT;
+            }
+            // Register a newly seen buffer
+            buffer_handle_t importedBuf = buf;
+            sHandleImporter.importBuffer(importedBuf);
+            if (importedBuf == nullptr) {
+                ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
+                return Status::INTERNAL_ERROR;
+            } else {
+                cbs[bufId] = importedBuf;
+            }
+        }
+        allBufPtrs[i] = &cbs[bufId];
+    }
+
+    // All buffers are imported. Now validate output buffer acquire fences
+    for (size_t i = 0; i < numOutputBufs; i++) {
+        if (!sHandleImporter.importFence(
+                request.outputBuffers[i].acquireFence, allFences[i])) {
+            ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
+            cleanupInflightFences(allFences, i);
+            return Status::INTERNAL_ERROR;
+        }
+    }
+    return Status::OK;
+}
+
+void ExternalCameraDeviceSession::cleanupInflightFences(
+        hidl_vec<int>& allFences, size_t numFences) {
+    for (size_t j = 0; j < numFences; j++) {
+        sHandleImporter.closeFence(allFences[j]);
+    }
+}
+
+Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request)  {
+    Status status = initStatus();
+    if (status != Status::OK) {
+        return status;
+    }
+
+    if (request.inputBuffer.streamId != -1) {
+        ALOGE("%s: external camera does not support reprocessing!", __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    Mutex::Autolock _l(mLock);
+    if (!mV4l2Streaming) {
+        ALOGE("%s: cannot process request in streamOff state!", __FUNCTION__);
+        return Status::INTERNAL_ERROR;
+    }
+
+    const camera_metadata_t *rawSettings = nullptr;
+    bool converted = true;
+    CameraMetadata settingsFmq;  // settings from FMQ
+    if (request.fmqSettingsSize > 0) {
+        // non-blocking read; client must write metadata before calling
+        // processOneCaptureRequest
+        settingsFmq.resize(request.fmqSettingsSize);
+        bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
+        if (read) {
+            converted = V3_2::implementation::convertFromHidl(settingsFmq, &rawSettings);
+        } else {
+            ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
+            converted = false;
+        }
+    } else {
+        converted = V3_2::implementation::convertFromHidl(request.settings, &rawSettings);
+    }
+
+    if (converted && rawSettings != nullptr) {
+        mLatestReqSetting = rawSettings;
+    }
+
+    if (!converted) {
+        ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    if (mFirstRequest && rawSettings == nullptr) {
+        ALOGE("%s: capture request settings must not be null for first request!",
+                __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    hidl_vec<buffer_handle_t*> allBufPtrs;
+    hidl_vec<int> allFences;
+    size_t numOutputBufs = request.outputBuffers.size();
+
+    if (numOutputBufs == 0) {
+        ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    status = importRequest(request, allBufPtrs, allFences);
+    if (status != Status::OK) {
+        return status;
+    }
+
+    // TODO: program fps range per capture request here
+    //       or limit the set of availableFpsRange
+
+    sp<V4L2Frame> frameIn = dequeueV4l2FrameLocked();
+    if ( frameIn == nullptr) {
+        ALOGE("%s: V4L2 deque frame failed!", __FUNCTION__);
+        return Status::INTERNAL_ERROR;
+    }
+    // TODO: This can probably be replaced by use v4lbuffer timestamp
+    //       if the device supports it
+    nsecs_t shutterTs = systemTime(SYSTEM_TIME_MONOTONIC);
+
+
+    // TODO: reduce object copy in this path
+    HalRequest halReq = {
+            .frameNumber = request.frameNumber,
+            .setting = mLatestReqSetting,
+            .frameIn = frameIn,
+            .shutterTs = shutterTs};
+    halReq.buffers.resize(numOutputBufs);
+    for (size_t i = 0; i < numOutputBufs; i++) {
+        HalStreamBuffer& halBuf = halReq.buffers[i];
+        int streamId = halBuf.streamId = request.outputBuffers[i].streamId;
+        halBuf.bufferId = request.outputBuffers[i].bufferId;
+        const Stream& stream = mStreamMap[streamId];
+        halBuf.width = stream.width;
+        halBuf.height = stream.height;
+        halBuf.format = stream.format;
+        halBuf.usage = stream.usage;
+        halBuf.bufPtr = allBufPtrs[i];
+        halBuf.acquireFence = allFences[i];
+        halBuf.fenceTimeout = false;
+    }
+    mInflightFrames.insert(halReq.frameNumber);
+    // Send request to OutputThread for the rest of processing
+    mOutputThread->submitRequest(halReq);
+    mFirstRequest = false;
+    return Status::OK;
+}
+
+void ExternalCameraDeviceSession::notifyShutter(uint32_t frameNumber, nsecs_t shutterTs) {
+    NotifyMsg msg;
+    msg.type = MsgType::SHUTTER;
+    msg.msg.shutter.frameNumber = frameNumber;
+    msg.msg.shutter.timestamp = shutterTs;
+    mCallback->notify({msg});
+}
+
+void ExternalCameraDeviceSession::notifyError(
+        uint32_t frameNumber, int32_t streamId, ErrorCode ec) {
+    NotifyMsg msg;
+    msg.type = MsgType::ERROR;
+    msg.msg.error.frameNumber = frameNumber;
+    msg.msg.error.errorStreamId = streamId;
+    msg.msg.error.errorCode = ec;
+    mCallback->notify({msg});
+}
+
+//TODO: refactor with processCaptureResult
+Status ExternalCameraDeviceSession::processCaptureRequestError(HalRequest& req) {
+    // Return V4L2 buffer to V4L2 buffer queue
+    enqueueV4l2Frame(req.frameIn);
+
+    // NotifyShutter
+    notifyShutter(req.frameNumber, req.shutterTs);
+
+    notifyError(/*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_REQUEST);
+
+    // Fill output buffers
+    hidl_vec<CaptureResult> results;
+    results.resize(1);
+    CaptureResult& result = results[0];
+    result.frameNumber = req.frameNumber;
+    result.partialResult = 1;
+    result.inputBuffer.streamId = -1;
+    result.outputBuffers.resize(req.buffers.size());
+    for (size_t i = 0; i < req.buffers.size(); i++) {
+        result.outputBuffers[i].streamId = req.buffers[i].streamId;
+        result.outputBuffers[i].bufferId = req.buffers[i].bufferId;
+        result.outputBuffers[i].status = BufferStatus::ERROR;
+        if (req.buffers[i].acquireFence >= 0) {
+            native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+            handle->data[0] = req.buffers[i].acquireFence;
+            result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+        }
+    }
+
+    // update inflight records
+    {
+        Mutex::Autolock _l(mLock);
+        mInflightFrames.erase(req.frameNumber);
+    }
+
+    // Callback into framework
+    invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
+    freeReleaseFences(results);
+    return Status::OK;
+}
+
+Status ExternalCameraDeviceSession::processCaptureResult(HalRequest& req) {
+    // Return V4L2 buffer to V4L2 buffer queue
+    enqueueV4l2Frame(req.frameIn);
+
+    // NotifyShutter
+    notifyShutter(req.frameNumber, req.shutterTs);
+
+    // Fill output buffers
+    hidl_vec<CaptureResult> results;
+    results.resize(1);
+    CaptureResult& result = results[0];
+    result.frameNumber = req.frameNumber;
+    result.partialResult = 1;
+    result.inputBuffer.streamId = -1;
+    result.outputBuffers.resize(req.buffers.size());
+    for (size_t i = 0; i < req.buffers.size(); i++) {
+        result.outputBuffers[i].streamId = req.buffers[i].streamId;
+        result.outputBuffers[i].bufferId = req.buffers[i].bufferId;
+        if (req.buffers[i].fenceTimeout) {
+            result.outputBuffers[i].status = BufferStatus::ERROR;
+            native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+            handle->data[0] = req.buffers[i].acquireFence;
+            result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+            notifyError(req.frameNumber, req.buffers[i].streamId, ErrorCode::ERROR_BUFFER);
+        } else {
+            result.outputBuffers[i].status = BufferStatus::OK;
+            // TODO: refactor
+            if (req.buffers[i].acquireFence > 0) {
+                native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+                handle->data[0] = req.buffers[i].acquireFence;
+                result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+            }
+        }
+    }
+
+    // Fill capture result metadata
+    fillCaptureResult(req.setting, req.shutterTs);
+    const camera_metadata_t *rawResult = req.setting.getAndLock();
+    V3_2::implementation::convertToHidl(rawResult, &result.result);
+    req.setting.unlock(rawResult);
+
+    // update inflight records
+    {
+        Mutex::Autolock _l(mLock);
+        mInflightFrames.erase(req.frameNumber);
+    }
+
+    // Callback into framework
+    invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
+    freeReleaseFences(results);
+    return Status::OK;
+}
+
+void ExternalCameraDeviceSession::invokeProcessCaptureResultCallback(
+        hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
+    if (mProcessCaptureResultLock.tryLock() != OK) {
+        const nsecs_t NS_TO_SECOND = 1000000000;
+        ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__);
+        if (mProcessCaptureResultLock.timedLock(/* 1s */NS_TO_SECOND) != OK) {
+            ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
+                    __FUNCTION__);
+            return;
+        }
+    }
+    if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
+        for (CaptureResult &result : results) {
+            if (result.result.size() > 0) {
+                if (mResultMetadataQueue->write(result.result.data(), result.result.size())) {
+                    result.fmqResultSize = result.result.size();
+                    result.result.resize(0);
+                } else {
+                    ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
+                    result.fmqResultSize = 0;
+                }
+            } else {
+                result.fmqResultSize = 0;
+            }
+        }
+    }
+    mCallback->processCaptureResult(results);
+    mProcessCaptureResultLock.unlock();
+}
+
+void ExternalCameraDeviceSession::freeReleaseFences(hidl_vec<CaptureResult>& results) {
+    for (auto& result : results) {
+        if (result.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
+            native_handle_t* handle = const_cast<native_handle_t*>(
+                    result.inputBuffer.releaseFence.getNativeHandle());
+            native_handle_close(handle);
+            native_handle_delete(handle);
+        }
+        for (auto& buf : result.outputBuffers) {
+            if (buf.releaseFence.getNativeHandle() != nullptr) {
+                native_handle_t* handle = const_cast<native_handle_t*>(
+                        buf.releaseFence.getNativeHandle());
+                native_handle_close(handle);
+                native_handle_delete(handle);
+            }
+        }
+    }
+    return;
+}
+
+ExternalCameraDeviceSession::OutputThread::OutputThread(
+        wp<ExternalCameraDeviceSession> parent,
+        CroppingType ct) : mParent(parent), mCroppingType(ct) {}
+
+ExternalCameraDeviceSession::OutputThread::~OutputThread() {}
+
+uint32_t ExternalCameraDeviceSession::OutputThread::getFourCcFromLayout(
+        const YCbCrLayout& layout) {
+    intptr_t cb = reinterpret_cast<intptr_t>(layout.cb);
+    intptr_t cr = reinterpret_cast<intptr_t>(layout.cr);
+    if (std::abs(cb - cr) == 1 && layout.chromaStep == 2) {
+        // Interleaved format
+        if (layout.cb > layout.cr) {
+            return V4L2_PIX_FMT_NV21;
+        } else {
+            return V4L2_PIX_FMT_NV12;
+        }
+    } else if (layout.chromaStep == 1) {
+        // Planar format
+        if (layout.cb > layout.cr) {
+            return V4L2_PIX_FMT_YVU420; // YV12
+        } else {
+            return V4L2_PIX_FMT_YUV420; // YU12
+        }
+    } else {
+        return FLEX_YUV_GENERIC;
+    }
+}
+
+int ExternalCameraDeviceSession::OutputThread::getCropRect(
+        CroppingType ct, const Size& inSize, const Size& outSize, IMapper::Rect* out) {
+    if (out == nullptr) {
+        ALOGE("%s: out is null", __FUNCTION__);
+        return -1;
+    }
+    uint32_t inW = inSize.width;
+    uint32_t inH = inSize.height;
+    uint32_t outW = outSize.width;
+    uint32_t outH = outSize.height;
+
+    if (ct == VERTICAL) {
+        uint64_t scaledOutH = static_cast<uint64_t>(outH) * inW / outW;
+        if (scaledOutH > inH) {
+            ALOGE("%s: Output size %dx%d cannot be vertically cropped from input size %dx%d",
+                    __FUNCTION__, outW, outH, inW, inH);
+            return -1;
+        }
+        scaledOutH = scaledOutH & ~0x1; // make it multiple of 2
+
+        out->left = 0;
+        out->top = ((inH - scaledOutH) / 2) & ~0x1;
+        out->width = inW;
+        out->height = static_cast<int32_t>(scaledOutH);
+        ALOGV("%s: crop %dx%d to %dx%d: top %d, scaledH %d",
+                __FUNCTION__, inW, inH, outW, outH, out->top, static_cast<int32_t>(scaledOutH));
+    } else {
+        uint64_t scaledOutW = static_cast<uint64_t>(outW) * inH / outH;
+        if (scaledOutW > inW) {
+            ALOGE("%s: Output size %dx%d cannot be horizontally cropped from input size %dx%d",
+                    __FUNCTION__, outW, outH, inW, inH);
+            return -1;
+        }
+        scaledOutW = scaledOutW & ~0x1; // make it multiple of 2
+
+        out->left = ((inW - scaledOutW) / 2) & ~0x1;
+        out->top = 0;
+        out->width = static_cast<int32_t>(scaledOutW);
+        out->height = inH;
+        ALOGV("%s: crop %dx%d to %dx%d: top %d, scaledW %d",
+                __FUNCTION__, inW, inH, outW, outH, out->top, static_cast<int32_t>(scaledOutW));
+    }
+
+    return 0;
+}
+
+int ExternalCameraDeviceSession::OutputThread::cropAndScaleLocked(
+        sp<AllocatedFrame>& in, const HalStreamBuffer& halBuf, YCbCrLayout* out) {
+    Size inSz = {in->mWidth, in->mHeight};
+    Size outSz = {halBuf.width, halBuf.height};
+    int ret;
+    if (inSz == outSz) {
+        ret = in->getLayout(out);
+        if (ret != 0) {
+            ALOGE("%s: failed to get input image layout", __FUNCTION__);
+            return ret;
+        }
+        return ret;
+    }
+
+    // Cropping to output aspect ratio
+    IMapper::Rect inputCrop;
+    ret = getCropRect(mCroppingType, inSz, outSz, &inputCrop);
+    if (ret != 0) {
+        ALOGE("%s: failed to compute crop rect for output size %dx%d",
+                __FUNCTION__, outSz.width, outSz.height);
+        return ret;
+    }
+
+    YCbCrLayout croppedLayout;
+    ret = in->getCroppedLayout(inputCrop, &croppedLayout);
+    if (ret != 0) {
+        ALOGE("%s: failed to crop input image %dx%d to output size %dx%d",
+                __FUNCTION__, inSz.width, inSz.height, outSz.width, outSz.height);
+        return ret;
+    }
+
+    if ((mCroppingType == VERTICAL && inSz.width == outSz.width) ||
+            (mCroppingType == HORIZONTAL && inSz.height == outSz.height)) {
+        // No scale is needed
+        *out = croppedLayout;
+        return 0;
+    }
+
+    auto it = mScaledYu12Frames.find(outSz);
+    sp<AllocatedFrame> scaledYu12Buf;
+    if (it != mScaledYu12Frames.end()) {
+        scaledYu12Buf = it->second;
+    } else {
+        it = mIntermediateBuffers.find(outSz);
+        if (it == mIntermediateBuffers.end()) {
+            ALOGE("%s: failed to find intermediate buffer size %dx%d",
+                    __FUNCTION__, outSz.width, outSz.height);
+            return -1;
+        }
+        scaledYu12Buf = it->second;
+    }
+    // Scale
+    YCbCrLayout outLayout;
+    ret = scaledYu12Buf->getLayout(&outLayout);
+    if (ret != 0) {
+        ALOGE("%s: failed to get output buffer layout", __FUNCTION__);
+        return ret;
+    }
+
+    ret = libyuv::I420Scale(
+            static_cast<uint8_t*>(croppedLayout.y),
+            croppedLayout.yStride,
+            static_cast<uint8_t*>(croppedLayout.cb),
+            croppedLayout.cStride,
+            static_cast<uint8_t*>(croppedLayout.cr),
+            croppedLayout.cStride,
+            inputCrop.width,
+            inputCrop.height,
+            static_cast<uint8_t*>(outLayout.y),
+            outLayout.yStride,
+            static_cast<uint8_t*>(outLayout.cb),
+            outLayout.cStride,
+            static_cast<uint8_t*>(outLayout.cr),
+            outLayout.cStride,
+            outSz.width,
+            outSz.height,
+            // TODO: b/72261744 see if we can use better filter without losing too much perf
+            libyuv::FilterMode::kFilterNone);
+
+    if (ret != 0) {
+        ALOGE("%s: failed to scale buffer from %dx%d to %dx%d. Ret %d",
+                __FUNCTION__, inputCrop.width, inputCrop.height,
+                outSz.width, outSz.height, ret);
+        return ret;
+    }
+
+    *out = outLayout;
+    mScaledYu12Frames.insert({outSz, scaledYu12Buf});
+    return 0;
+}
+
+int ExternalCameraDeviceSession::OutputThread::formatConvertLocked(
+        const YCbCrLayout& in, const YCbCrLayout& out, Size sz, uint32_t format) {
+    int ret = 0;
+    switch (format) {
+        case V4L2_PIX_FMT_NV21:
+            ret = libyuv::I420ToNV21(
+                    static_cast<uint8_t*>(in.y),
+                    in.yStride,
+                    static_cast<uint8_t*>(in.cb),
+                    in.cStride,
+                    static_cast<uint8_t*>(in.cr),
+                    in.cStride,
+                    static_cast<uint8_t*>(out.y),
+                    out.yStride,
+                    static_cast<uint8_t*>(out.cr),
+                    out.cStride,
+                    sz.width,
+                    sz.height);
+            if (ret != 0) {
+                ALOGE("%s: convert to NV21 buffer failed! ret %d",
+                            __FUNCTION__, ret);
+                return ret;
+            }
+            break;
+        case V4L2_PIX_FMT_NV12:
+            ret = libyuv::I420ToNV12(
+                    static_cast<uint8_t*>(in.y),
+                    in.yStride,
+                    static_cast<uint8_t*>(in.cb),
+                    in.cStride,
+                    static_cast<uint8_t*>(in.cr),
+                    in.cStride,
+                    static_cast<uint8_t*>(out.y),
+                    out.yStride,
+                    static_cast<uint8_t*>(out.cb),
+                    out.cStride,
+                    sz.width,
+                    sz.height);
+            if (ret != 0) {
+                ALOGE("%s: convert to NV12 buffer failed! ret %d",
+                            __FUNCTION__, ret);
+                return ret;
+            }
+            break;
+        case V4L2_PIX_FMT_YVU420: // YV12
+        case V4L2_PIX_FMT_YUV420: // YU12
+            // TODO: maybe we can speed up here by somehow save this copy?
+            ret = libyuv::I420Copy(
+                    static_cast<uint8_t*>(in.y),
+                    in.yStride,
+                    static_cast<uint8_t*>(in.cb),
+                    in.cStride,
+                    static_cast<uint8_t*>(in.cr),
+                    in.cStride,
+                    static_cast<uint8_t*>(out.y),
+                    out.yStride,
+                    static_cast<uint8_t*>(out.cb),
+                    out.cStride,
+                    static_cast<uint8_t*>(out.cr),
+                    out.cStride,
+                    sz.width,
+                    sz.height);
+            if (ret != 0) {
+                ALOGE("%s: copy to YV12 or YU12 buffer failed! ret %d",
+                            __FUNCTION__, ret);
+                return ret;
+            }
+            break;
+        case FLEX_YUV_GENERIC:
+            // TODO: b/72261744 write to arbitrary flexible YUV layout. Slow.
+            ALOGE("%s: unsupported flexible yuv layout"
+                    " y %p cb %p cr %p y_str %d c_str %d c_step %d",
+                    __FUNCTION__, out.y, out.cb, out.cr,
+                    out.yStride, out.cStride, out.chromaStep);
+            return -1;
+        default:
+            ALOGE("%s: unknown YUV format 0x%x!", __FUNCTION__, format);
+            return -1;
+    }
+    return 0;
+}
+
+bool ExternalCameraDeviceSession::OutputThread::threadLoop() {
+    HalRequest req;
+    auto parent = mParent.promote();
+    if (parent == nullptr) {
+       ALOGE("%s: session has been disconnected!", __FUNCTION__);
+       return false;
+    }
+
+    // TODO: maybe we need to setup a sensor thread to dq/enq v4l frames
+    //       regularly to prevent v4l buffer queue filled with stale buffers
+    //       when app doesn't program a preveiw request
+    waitForNextRequest(&req);
+    if (req.frameIn == nullptr) {
+        // No new request, wait again
+        return true;
+    }
+
+    if (req.frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) {
+        ALOGE("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__,
+                req.frameIn->mFourcc & 0xFF,
+                (req.frameIn->mFourcc >> 8) & 0xFF,
+                (req.frameIn->mFourcc >> 16) & 0xFF,
+                (req.frameIn->mFourcc >> 24) & 0xFF);
+        parent->notifyError(
+                /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
+        return false;
+    }
+
+    std::unique_lock<std::mutex> lk(mLock);
+
+    // Convert input V4L2 frame to YU12 of the same size
+    // TODO: see if we can save some computation by converting to YV12 here
+    uint8_t* inData;
+    size_t inDataSize;
+    req.frameIn->map(&inData, &inDataSize);
+    // TODO: profile
+    // TODO: in some special case maybe we can decode jpg directly to gralloc output?
+    int res = libyuv::MJPGToI420(
+            inData, inDataSize,
+            static_cast<uint8_t*>(mYu12FrameLayout.y),
+            mYu12FrameLayout.yStride,
+            static_cast<uint8_t*>(mYu12FrameLayout.cb),
+            mYu12FrameLayout.cStride,
+            static_cast<uint8_t*>(mYu12FrameLayout.cr),
+            mYu12FrameLayout.cStride,
+            mYu12Frame->mWidth, mYu12Frame->mHeight,
+            mYu12Frame->mWidth, mYu12Frame->mHeight);
+
+    if (res != 0) {
+        // For some webcam, the first few V4L2 frames might be malformed...
+        ALOGE("%s: Convert V4L2 frame to YU12 failed! res %d", __FUNCTION__, res);
+        lk.unlock();
+        Status st = parent->processCaptureRequestError(req);
+        if (st != Status::OK) {
+            ALOGE("%s: failed to process capture request error!", __FUNCTION__);
+            parent->notifyError(
+                    /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
+            return false;
+        }
+        return true;
+    }
+
+    ALOGV("%s processing new request", __FUNCTION__);
+    const int kSyncWaitTimeoutMs = 500;
+    for (auto& halBuf : req.buffers) {
+        if (halBuf.acquireFence != -1) {
+            int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs);
+            if (ret) {
+                halBuf.fenceTimeout = true;
+            } else {
+                ::close(halBuf.acquireFence);
+            }
+        }
+
+        if (halBuf.fenceTimeout) {
+            continue;
+        }
+
+        // Gralloc lockYCbCr the buffer
+        switch (halBuf.format) {
+            case PixelFormat::BLOB:
+                // TODO: b/72261675 implement JPEG output path
+                break;
+            case PixelFormat::YCBCR_420_888:
+            case PixelFormat::YV12: {
+                IMapper::Rect outRect {0, 0,
+                        static_cast<int32_t>(halBuf.width),
+                        static_cast<int32_t>(halBuf.height)};
+                YCbCrLayout outLayout = sHandleImporter.lockYCbCr(
+                        *(halBuf.bufPtr), halBuf.usage, outRect);
+                ALOGV("%s: outLayout y %p cb %p cr %p y_str %d c_str %d c_step %d",
+                        __FUNCTION__, outLayout.y, outLayout.cb, outLayout.cr,
+                        outLayout.yStride, outLayout.cStride, outLayout.chromaStep);
+
+                // Convert to output buffer size/format
+                uint32_t outputFourcc = getFourCcFromLayout(outLayout);
+                ALOGV("%s: converting to format %c%c%c%c", __FUNCTION__,
+                        outputFourcc & 0xFF,
+                        (outputFourcc >> 8) & 0xFF,
+                        (outputFourcc >> 16) & 0xFF,
+                        (outputFourcc >> 24) & 0xFF);
+
+                YCbCrLayout cropAndScaled;
+                int ret = cropAndScaleLocked(
+                        mYu12Frame, halBuf, &cropAndScaled);
+                if (ret != 0) {
+                    ALOGE("%s: crop and scale failed!", __FUNCTION__);
+                    lk.unlock();
+                    parent->notifyError(
+                            /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
+                    return false;
+                }
+
+                Size sz {halBuf.width, halBuf.height};
+                ret = formatConvertLocked(cropAndScaled, outLayout, sz, outputFourcc);
+                if (ret != 0) {
+                    ALOGE("%s: format coversion failed!", __FUNCTION__);
+                    lk.unlock();
+                    parent->notifyError(
+                            /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
+                    return false;
+                }
+                int relFence = sHandleImporter.unlock(*(halBuf.bufPtr));
+                if (relFence > 0) {
+                    halBuf.acquireFence = relFence;
+                }
+            } break;
+            default:
+                ALOGE("%s: unknown output format %x", __FUNCTION__, halBuf.format);
+                lk.unlock();
+                parent->notifyError(
+                        /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
+                return false;
+        }
+    } // for each buffer
+    mScaledYu12Frames.clear();
+
+    // Don't hold the lock while calling back to parent
+    lk.unlock();
+    Status st = parent->processCaptureResult(req);
+    if (st != Status::OK) {
+        ALOGE("%s: failed to process capture result!", __FUNCTION__);
+        parent->notifyError(
+                /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
+        return false;
+    }
+    return true;
+}
+
+Status ExternalCameraDeviceSession::OutputThread::allocateIntermediateBuffers(
+        const Size& v4lSize, const hidl_vec<Stream>& streams) {
+    std::lock_guard<std::mutex> lk(mLock);
+    if (mScaledYu12Frames.size() != 0) {
+        ALOGE("%s: intermediate buffer pool has %zu inflight buffers! (expect 0)",
+                __FUNCTION__, mScaledYu12Frames.size());
+        return Status::INTERNAL_ERROR;
+    }
+
+    // Allocating intermediate YU12 frame
+    if (mYu12Frame == nullptr || mYu12Frame->mWidth != v4lSize.width ||
+            mYu12Frame->mHeight != v4lSize.height) {
+        mYu12Frame.clear();
+        mYu12Frame = new AllocatedFrame(v4lSize.width, v4lSize.height);
+        int ret = mYu12Frame->allocate(&mYu12FrameLayout);
+        if (ret != 0) {
+            ALOGE("%s: allocating YU12 frame failed!", __FUNCTION__);
+            return Status::INTERNAL_ERROR;
+        }
+    }
+
+    // Allocating scaled buffers
+    for (const auto& stream : streams) {
+        Size sz = {stream.width, stream.height};
+        if (sz == v4lSize) {
+            continue; // Don't need an intermediate buffer same size as v4lBuffer
+        }
+        if (mIntermediateBuffers.count(sz) == 0) {
+            // Create new intermediate buffer
+            sp<AllocatedFrame> buf = new AllocatedFrame(stream.width, stream.height);
+            int ret = buf->allocate();
+            if (ret != 0) {
+                ALOGE("%s: allocating intermediate YU12 frame %dx%d failed!",
+                            __FUNCTION__, stream.width, stream.height);
+                return Status::INTERNAL_ERROR;
+            }
+            mIntermediateBuffers[sz] = buf;
+        }
+    }
+
+    // Remove unconfigured buffers
+    auto it = mIntermediateBuffers.begin();
+    while (it != mIntermediateBuffers.end()) {
+        bool configured = false;
+        auto sz = it->first;
+        for (const auto& stream : streams) {
+            if (stream.width == sz.width && stream.height == sz.height) {
+                configured = true;
+                break;
+            }
+        }
+        if (configured) {
+            it++;
+        } else {
+            it = mIntermediateBuffers.erase(it);
+        }
+    }
+    return Status::OK;
+}
+
+Status ExternalCameraDeviceSession::OutputThread::submitRequest(const HalRequest& req) {
+    std::lock_guard<std::mutex> lk(mLock);
+    // TODO: reduce object copy in this path
+    mRequestList.push_back(req);
+    mRequestCond.notify_one();
+    return Status::OK;
+}
+
+void ExternalCameraDeviceSession::OutputThread::flush() {
+    std::lock_guard<std::mutex> lk(mLock);
+    // TODO: send buffer/request errors back to framework
+    mRequestList.clear();
+}
+
+void ExternalCameraDeviceSession::OutputThread::waitForNextRequest(HalRequest* out) {
+    if (out == nullptr) {
+        ALOGE("%s: out is null", __FUNCTION__);
+        return;
+    }
+
+    std::unique_lock<std::mutex> lk(mLock);
+    while (mRequestList.empty()) {
+        std::chrono::seconds timeout = std::chrono::seconds(kReqWaitTimeoutSec);
+        auto st = mRequestCond.wait_for(lk, timeout);
+        if (st == std::cv_status::timeout) {
+            // no new request, return
+            return;
+        }
+    }
+    *out = mRequestList.front();
+    mRequestList.pop_front();
+}
+
+void ExternalCameraDeviceSession::cleanupBuffersLocked(int id) {
+    for (auto& pair : mCirculatingBuffers.at(id)) {
+        sHandleImporter.freeBuffer(pair.second);
+    }
+    mCirculatingBuffers[id].clear();
+    mCirculatingBuffers.erase(id);
+}
+
+void ExternalCameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
+    Mutex::Autolock _l(mLock);
+    for (auto& cache : cachesToRemove) {
+        auto cbsIt = mCirculatingBuffers.find(cache.streamId);
+        if (cbsIt == mCirculatingBuffers.end()) {
+            // The stream could have been removed
+            continue;
+        }
+        CirculatingBuffers& cbs = cbsIt->second;
+        auto it = cbs.find(cache.bufferId);
+        if (it != cbs.end()) {
+            sHandleImporter.freeBuffer(it->second);
+            cbs.erase(it);
+        } else {
+            ALOGE("%s: stream %d buffer %" PRIu64 " is not cached",
+                    __FUNCTION__, cache.streamId, cache.bufferId);
+        }
+    }
+}
+
+bool ExternalCameraDeviceSession::isSupported(const Stream& stream) {
+    int32_t ds = static_cast<int32_t>(stream.dataSpace);
+    PixelFormat fmt = stream.format;
+    uint32_t width = stream.width;
+    uint32_t height = stream.height;
+    // TODO: check usage flags
+
+    if (stream.streamType != StreamType::OUTPUT) {
+        ALOGE("%s: does not support non-output stream type", __FUNCTION__);
+        return false;
+    }
+
+    if (stream.rotation != StreamRotation::ROTATION_0) {
+        ALOGE("%s: does not support stream rotation", __FUNCTION__);
+        return false;
+    }
+
+    if (ds & Dataspace::DEPTH) {
+        ALOGI("%s: does not support depth output", __FUNCTION__);
+        return false;
+    }
+
+    switch (fmt) {
+        case PixelFormat::BLOB:
+            if (ds != static_cast<int32_t>(Dataspace::V0_JFIF)) {
+                ALOGI("%s: BLOB format does not support dataSpace %x", __FUNCTION__, ds);
+                return false;
+            }
+        case PixelFormat::IMPLEMENTATION_DEFINED:
+        case PixelFormat::YCBCR_420_888:
+        case PixelFormat::YV12:
+            // TODO: check what dataspace we can support here.
+            // intentional no-ops.
+            break;
+        default:
+            ALOGI("%s: does not support format %x", __FUNCTION__, fmt);
+            return false;
+    }
+
+    // Assume we can convert any V4L2 format to any of supported output format for now, i.e,
+    // ignoring v4l2Fmt.fourcc for now. Might need more subtle check if we support more v4l format
+    // in the futrue.
+    for (const auto& v4l2Fmt : mSupportedFormats) {
+        if (width == v4l2Fmt.width && height == v4l2Fmt.height) {
+            return true;
+        }
+    }
+    ALOGI("%s: resolution %dx%d is not supported", __FUNCTION__, width, height);
+    return false;
+}
+
+int ExternalCameraDeviceSession::v4l2StreamOffLocked() {
+    if (!mV4l2Streaming) {
+        return OK;
+    }
+
+    {
+        std::lock_guard<std::mutex> lk(mV4l2BufferLock);
+        if (mNumDequeuedV4l2Buffers != 0)  {
+            ALOGE("%s: there are %zu inflight V4L buffers",
+                __FUNCTION__, mNumDequeuedV4l2Buffers);
+            return -1;
+        }
+    }
+    mV4l2Buffers.clear(); // VIDIOC_REQBUFS will fail if FDs are not clear first
+
+    // VIDIOC_STREAMOFF
+    v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMOFF, &capture_type)) < 0) {
+        ALOGE("%s: STREAMOFF failed: %s", __FUNCTION__, strerror(errno));
+        return -errno;
+    }
+
+    // VIDIOC_REQBUFS: clear buffers
+    v4l2_requestbuffers req_buffers{};
+    req_buffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    req_buffers.memory = V4L2_MEMORY_MMAP;
+    req_buffers.count = 0;
+    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_REQBUFS, &req_buffers)) < 0) {
+        ALOGE("%s: REQBUFS failed: %s", __FUNCTION__, strerror(errno));
+        return -errno;
+    }
+
+    mV4l2Streaming = false;
+    return OK;
+}
+
+int ExternalCameraDeviceSession::configureV4l2StreamLocked(const SupportedV4L2Format& v4l2Fmt) {
+    int ret = v4l2StreamOffLocked();
+    if (ret != OK) {
+        ALOGE("%s: stop v4l2 streaming failed: ret %d", __FUNCTION__, ret);
+        return ret;
+    }
+
+    // VIDIOC_S_FMT w/h/fmt
+    v4l2_format fmt;
+    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    fmt.fmt.pix.width = v4l2Fmt.width;
+    fmt.fmt.pix.height = v4l2Fmt.height;
+    fmt.fmt.pix.pixelformat = v4l2Fmt.fourcc;
+    ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt));
+    if (ret < 0) {
+        ALOGE("%s: S_FMT ioctl failed: %s", __FUNCTION__, strerror(errno));
+        return -errno;
+    }
+
+    if (v4l2Fmt.width != fmt.fmt.pix.width || v4l2Fmt.height != fmt.fmt.pix.height ||
+            v4l2Fmt.fourcc != fmt.fmt.pix.pixelformat) {
+        ALOGE("%s: S_FMT expect %c%c%c%c %dx%d, got %c%c%c%c %dx%d instead!", __FUNCTION__,
+                v4l2Fmt.fourcc & 0xFF,
+                (v4l2Fmt.fourcc >> 8) & 0xFF,
+                (v4l2Fmt.fourcc >> 16) & 0xFF,
+                (v4l2Fmt.fourcc >> 24) & 0xFF,
+                v4l2Fmt.width, v4l2Fmt.height,
+                fmt.fmt.pix.pixelformat & 0xFF,
+                (fmt.fmt.pix.pixelformat >> 8) & 0xFF,
+                (fmt.fmt.pix.pixelformat >> 16) & 0xFF,
+                (fmt.fmt.pix.pixelformat >> 24) & 0xFF,
+                fmt.fmt.pix.width, fmt.fmt.pix.height);
+        return -EINVAL;
+    }
+    uint32_t bufferSize = fmt.fmt.pix.sizeimage;
+    ALOGI("%s: V4L2 buffer size is %d", __FUNCTION__, bufferSize);
+
+    float maxFps = -1.f;
+    float fps = 1000.f;
+    const float kDefaultFps = 30.f;
+    // Try to pick the slowest fps that is at least 30
+    for (const auto& f : v4l2Fmt.frameRates) {
+        if (maxFps < f) {
+            maxFps = f;
+        }
+        if (f >= kDefaultFps && f < fps) {
+            fps = f;
+        }
+    }
+    if (fps == 1000.f) {
+        fps = maxFps;
+    }
+
+    // VIDIOC_G_PARM/VIDIOC_S_PARM: set fps
+    v4l2_streamparm streamparm = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
+    // The following line checks that the driver knows about framerate get/set.
+    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_G_PARM, &streamparm)) >= 0) {
+        // Now check if the device is able to accept a capture framerate set.
+        if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
+            // |frame_rate| is float, approximate by a fraction.
+            const int kFrameRatePrecision = 10000;
+            streamparm.parm.capture.timeperframe.numerator = kFrameRatePrecision;
+            streamparm.parm.capture.timeperframe.denominator =
+                (fps * kFrameRatePrecision);
+
+            if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_PARM, &streamparm)) < 0) {
+                ALOGE("%s: failed to set framerate to %f", __FUNCTION__, fps);
+                return UNKNOWN_ERROR;
+            }
+        }
+    }
+    float retFps = streamparm.parm.capture.timeperframe.denominator /
+                streamparm.parm.capture.timeperframe.numerator;
+    if (std::fabs(fps - retFps) > std::numeric_limits<float>::epsilon()) {
+        ALOGE("%s: expect fps %f, got %f instead", __FUNCTION__, fps, retFps);
+        return BAD_VALUE;
+    }
+
+    uint32_t v4lBufferCount = (v4l2Fmt.width <= kMaxVideoSize.width &&
+            v4l2Fmt.height <= kMaxVideoSize.height) ? kNumVideoBuffers : kNumStillBuffers;
+    // VIDIOC_REQBUFS: create buffers
+    v4l2_requestbuffers req_buffers{};
+    req_buffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    req_buffers.memory = V4L2_MEMORY_MMAP;
+    req_buffers.count = v4lBufferCount;
+    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_REQBUFS, &req_buffers)) < 0) {
+        ALOGE("%s: VIDIOC_REQBUFS failed: %s", __FUNCTION__, strerror(errno));
+        return -errno;
+    }
+
+    // Driver can indeed return more buffer if it needs more to operate
+    if (req_buffers.count < v4lBufferCount) {
+        ALOGE("%s: VIDIOC_REQBUFS expected %d buffers, got %d instead",
+                __FUNCTION__, v4lBufferCount, req_buffers.count);
+        return NO_MEMORY;
+    }
+
+    // VIDIOC_EXPBUF:  export buffers as FD
+    // VIDIOC_QBUF: send buffer to driver
+    mV4l2Buffers.resize(req_buffers.count);
+    for (uint32_t i = 0; i < req_buffers.count; i++) {
+        v4l2_exportbuffer expbuf {};
+        expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        expbuf.index = i;
+        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_EXPBUF, &expbuf)) < 0) {
+            ALOGE("%s: EXPBUF %d failed: %s", __FUNCTION__, i,  strerror(errno));
+            return -errno;
+        }
+        mV4l2Buffers[i].reset(expbuf.fd);
+
+        v4l2_buffer buffer = {
+            .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+            .index = i,
+            .memory = V4L2_MEMORY_MMAP};
+
+        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) {
+            ALOGE("%s: QBUF %d failed: %s", __FUNCTION__, i,  strerror(errno));
+            return -errno;
+        }
+    }
+
+    // VIDIOC_STREAMON: start streaming
+    v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMON, &capture_type)) < 0) {
+        ALOGE("%s: VIDIOC_STREAMON failed: %s", __FUNCTION__, strerror(errno));
+        return -errno;
+    }
+
+    // Swallow first few frames after streamOn to account for bad frames from some devices
+    for (int i = 0; i < kBadFramesAfterStreamOn; i++) {
+        v4l2_buffer buffer{};
+        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        buffer.memory = V4L2_MEMORY_MMAP;
+        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_DQBUF, &buffer)) < 0) {
+            ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno));
+            return -errno;
+        }
+
+        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) {
+            ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__, buffer.index, strerror(errno));
+            return -errno;
+        }
+    }
+
+    mV4l2StreamingFmt = v4l2Fmt;
+    mV4l2Streaming = true;
+    return OK;
+}
+
+sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked() {
+    sp<V4L2Frame> ret = nullptr;
+
+    {
+        std::unique_lock<std::mutex> lk(mV4l2BufferLock);
+        if (mNumDequeuedV4l2Buffers == mV4l2Buffers.size()) {
+            std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec);
+            mLock.unlock();
+            auto st = mV4L2BufferReturned.wait_for(lk, timeout);
+            mLock.lock();
+            if (st == std::cv_status::timeout) {
+                ALOGE("%s: wait for V4L2 buffer return timeout!", __FUNCTION__);
+                return ret;
+            }
+        }
+    }
+
+    v4l2_buffer buffer{};
+    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    buffer.memory = V4L2_MEMORY_MMAP;
+    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_DQBUF, &buffer)) < 0) {
+        ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno));
+        return ret;
+    }
+
+    if (buffer.index >= mV4l2Buffers.size()) {
+        ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index);
+        return ret;
+    }
+
+    if (buffer.flags & V4L2_BUF_FLAG_ERROR) {
+        ALOGE("%s: v4l2 buf error! buf flag 0x%x", __FUNCTION__, buffer.flags);
+        // TODO: try to dequeue again
+    }
+
+    {
+        std::lock_guard<std::mutex> lk(mV4l2BufferLock);
+        mNumDequeuedV4l2Buffers++;
+    }
+    return new V4L2Frame(
+            mV4l2StreamingFmt.width, mV4l2StreamingFmt.height, mV4l2StreamingFmt.fourcc,
+            buffer.index, mV4l2Buffers[buffer.index].get(), buffer.bytesused);
+}
+
+void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) {
+    Mutex::Autolock _l(mLock);
+    frame->unmap();
+    v4l2_buffer buffer{};
+    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    buffer.memory = V4L2_MEMORY_MMAP;
+    buffer.index = frame->mBufferIndex;
+    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) {
+        ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__, frame->mBufferIndex, strerror(errno));
+        return;
+    }
+
+    {
+        std::lock_guard<std::mutex> lk(mV4l2BufferLock);
+        mNumDequeuedV4l2Buffers--;
+        mV4L2BufferReturned.notify_one();
+    }
+}
+
+Status ExternalCameraDeviceSession::configureStreams(
+        const V3_2::StreamConfiguration& config, V3_3::HalStreamConfiguration* out) {
+    if (config.operationMode != StreamConfigurationMode::NORMAL_MODE) {
+        ALOGE("%s: unsupported operation mode: %d", __FUNCTION__, config.operationMode);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    if (config.streams.size() == 0) {
+        ALOGE("%s: cannot configure zero stream", __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    int numProcessedStream = 0;
+    int numStallStream = 0;
+    for (const auto& stream : config.streams) {
+        // Check if the format/width/height combo is supported
+        if (!isSupported(stream)) {
+            return Status::ILLEGAL_ARGUMENT;
+        }
+        if (stream.format == PixelFormat::BLOB) {
+            numStallStream++;
+        } else {
+            numProcessedStream++;
+        }
+    }
+
+    if (numProcessedStream > kMaxProcessedStream) {
+        ALOGE("%s: too many processed streams (expect <= %d, got %d)", __FUNCTION__,
+                kMaxProcessedStream, numProcessedStream);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    if (numStallStream > kMaxStallStream) {
+        ALOGE("%s: too many stall streams (expect <= %d, got %d)", __FUNCTION__,
+                kMaxStallStream, numStallStream);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    Status status = initStatus();
+    if (status != Status::OK) {
+        return status;
+    }
+
+    Mutex::Autolock _l(mLock);
+    if (!mInflightFrames.empty()) {
+        ALOGE("%s: trying to configureStreams while there are still %zu inflight frames!",
+                __FUNCTION__, mInflightFrames.size());
+        return Status::INTERNAL_ERROR;
+    }
+
+    // Add new streams
+    for (const auto& stream : config.streams) {
+        if (mStreamMap.count(stream.id) == 0) {
+            mStreamMap[stream.id] = stream;
+            mCirculatingBuffers.emplace(stream.id, CirculatingBuffers{});
+        }
+    }
+
+    // Cleanup removed streams
+    for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
+        int id = it->first;
+        bool found = false;
+        for (const auto& stream : config.streams) {
+            if (id == stream.id) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            // Unmap all buffers of deleted stream
+            cleanupBuffersLocked(id);
+            it = mStreamMap.erase(it);
+        } else {
+            ++it;
+        }
+    }
+
+    // Now select a V4L2 format to produce all output streams
+    float desiredAr = (mCroppingType == VERTICAL) ? kMaxAspectRatio : kMinAspectRatio;
+    uint32_t maxDim = 0;
+    for (const auto& stream : config.streams) {
+        float aspectRatio = ASPECT_RATIO(stream);
+        if ((mCroppingType == VERTICAL && aspectRatio < desiredAr) ||
+                (mCroppingType == HORIZONTAL && aspectRatio > desiredAr)) {
+            desiredAr = aspectRatio;
+        }
+
+        // The dimension that's not cropped
+        uint32_t dim = (mCroppingType == VERTICAL) ? stream.width : stream.height;
+        if (dim > maxDim) {
+            maxDim = dim;
+        }
+    }
+    // Find the smallest format that matches the desired aspect ratio and is wide/high enough
+    SupportedV4L2Format v4l2Fmt {.width = 0, .height = 0};
+    for (const auto& fmt : mSupportedFormats) {
+        uint32_t dim = (mCroppingType == VERTICAL) ? fmt.width : fmt.height;
+        if (dim >= maxDim) {
+            float aspectRatio = ASPECT_RATIO(fmt);
+            if (isAspectRatioClose(aspectRatio, desiredAr)) {
+                v4l2Fmt = fmt;
+                // since mSupportedFormats is sorted by width then height, the first matching fmt
+                // will be the smallest one with matching aspect ratio
+                break;
+            }
+        }
+    }
+    if (v4l2Fmt.width == 0) {
+        // Cannot find exact good aspect ratio candidate, try to find a close one
+        for (const auto& fmt : mSupportedFormats) {
+            uint32_t dim = (mCroppingType == VERTICAL) ? fmt.width : fmt.height;
+            if (dim >= maxDim) {
+                float aspectRatio = ASPECT_RATIO(fmt);
+                if ((mCroppingType == VERTICAL && aspectRatio < desiredAr) ||
+                        (mCroppingType == HORIZONTAL && aspectRatio > desiredAr)) {
+                    v4l2Fmt = fmt;
+                    break;
+                }
+            }
+        }
+    }
+
+    if (v4l2Fmt.width == 0) {
+        ALOGE("%s: unable to find a resolution matching (%s at least %d, aspect ratio %f)"
+                , __FUNCTION__, (mCroppingType == VERTICAL) ? "width" : "height",
+                maxDim, desiredAr);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    if (configureV4l2StreamLocked(v4l2Fmt) != 0) {
+        ALOGE("V4L configuration failed!, format:%c%c%c%c, w %d, h %d",
+            v4l2Fmt.fourcc & 0xFF,
+            (v4l2Fmt.fourcc >> 8) & 0xFF,
+            (v4l2Fmt.fourcc >> 16) & 0xFF,
+            (v4l2Fmt.fourcc >> 24) & 0xFF,
+            v4l2Fmt.width, v4l2Fmt.height);
+        return Status::INTERNAL_ERROR;
+    }
+
+    Size v4lSize = {v4l2Fmt.width, v4l2Fmt.height};
+    status = mOutputThread->allocateIntermediateBuffers(v4lSize, config.streams);
+    if (status != Status::OK) {
+        ALOGE("%s: allocating intermediate buffers failed!", __FUNCTION__);
+        return status;
+    }
+
+    out->streams.resize(config.streams.size());
+    for (size_t i = 0; i < config.streams.size(); i++) {
+        out->streams[i].overrideDataSpace = config.streams[i].dataSpace;
+        out->streams[i].v3_2.id = config.streams[i].id;
+        // TODO: double check should we add those CAMERA flags
+        mStreamMap[config.streams[i].id].usage =
+                out->streams[i].v3_2.producerUsage = config.streams[i].usage |
+                BufferUsage::CPU_WRITE_OFTEN |
+                BufferUsage::CAMERA_OUTPUT;
+        out->streams[i].v3_2.consumerUsage = 0;
+        out->streams[i].v3_2.maxBuffers  = mV4l2Buffers.size();
+
+        switch (config.streams[i].format) {
+            case PixelFormat::BLOB:
+            case PixelFormat::YCBCR_420_888:
+                // No override
+                out->streams[i].v3_2.overrideFormat = config.streams[i].format;
+                break;
+            case PixelFormat::IMPLEMENTATION_DEFINED:
+                // Override based on VIDEO or not
+                out->streams[i].v3_2.overrideFormat =
+                        (config.streams[i].usage & BufferUsage::VIDEO_ENCODER) ?
+                        PixelFormat::YCBCR_420_888 : PixelFormat::YV12;
+                // Save overridden formt in mStreamMap
+                mStreamMap[config.streams[i].id].format = out->streams[i].v3_2.overrideFormat;
+                break;
+            default:
+                ALOGE("%s: unsupported format %x", __FUNCTION__, config.streams[i].format);
+                return Status::ILLEGAL_ARGUMENT;
+        }
+    }
+
+    mFirstRequest = true;
+    return Status::OK;
+}
+
+bool ExternalCameraDeviceSession::isClosed() {
+    Mutex::Autolock _l(mLock);
+    return mClosed;
+}
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+#define UPDATE(md, tag, data, size)               \
+do {                                              \
+    if ((md).update((tag), (data), (size))) {     \
+        ALOGE("Update " #tag " failed!");         \
+        return BAD_VALUE;                         \
+    }                                             \
+} while (0)
+
+status_t ExternalCameraDeviceSession::initDefaultRequests() {
+    ::android::hardware::camera::common::V1_0::helper::CameraMetadata md;
+
+    const uint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;
+    UPDATE(md, ANDROID_COLOR_CORRECTION_ABERRATION_MODE, &aberrationMode, 1);
+
+    const int32_t exposureCompensation = 0;
+    UPDATE(md, ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, &exposureCompensation, 1);
+
+    const uint8_t videoStabilizationMode = ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
+    UPDATE(md, ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, &videoStabilizationMode, 1);
+
+    const uint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;
+    UPDATE(md, ANDROID_CONTROL_AWB_MODE, &awbMode, 1);
+
+    const uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
+    UPDATE(md, ANDROID_CONTROL_AE_MODE, &aeMode, 1);
+
+    const uint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
+    UPDATE(md, ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, &aePrecaptureTrigger, 1);
+
+    const uint8_t afMode = ANDROID_CONTROL_AF_MODE_AUTO;
+    UPDATE(md, ANDROID_CONTROL_AF_MODE, &afMode, 1);
+
+    const uint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;
+    UPDATE(md, ANDROID_CONTROL_AF_TRIGGER, &afTrigger, 1);
+
+    const uint8_t sceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
+    UPDATE(md, ANDROID_CONTROL_SCENE_MODE, &sceneMode, 1);
+
+    const uint8_t effectMode = ANDROID_CONTROL_EFFECT_MODE_OFF;
+    UPDATE(md, ANDROID_CONTROL_EFFECT_MODE, &effectMode, 1);
+
+    const uint8_t flashMode = ANDROID_FLASH_MODE_OFF;
+    UPDATE(md, ANDROID_FLASH_MODE, &flashMode, 1);
+
+    const int32_t thumbnailSize[] = {240, 180};
+    UPDATE(md, ANDROID_JPEG_THUMBNAIL_SIZE, thumbnailSize, 2);
+
+    const uint8_t jpegQuality = 90;
+    UPDATE(md, ANDROID_JPEG_QUALITY, &jpegQuality, 1);
+    UPDATE(md, ANDROID_JPEG_THUMBNAIL_QUALITY, &jpegQuality, 1);
+
+    const int32_t jpegOrientation = 0;
+    UPDATE(md, ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1);
+
+    const uint8_t oisMode = ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
+    UPDATE(md, ANDROID_LENS_OPTICAL_STABILIZATION_MODE, &oisMode, 1);
+
+    const uint8_t nrMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
+    UPDATE(md, ANDROID_NOISE_REDUCTION_MODE, &nrMode, 1);
+
+    const uint8_t fdMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
+    UPDATE(md, ANDROID_STATISTICS_FACE_DETECT_MODE, &fdMode, 1);
+
+    const uint8_t hotpixelMode = ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
+    UPDATE(md, ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE, &hotpixelMode, 1);
+
+    bool support30Fps = false;
+    int32_t maxFps = std::numeric_limits<int32_t>::min();
+    for (const auto& supportedFormat : mSupportedFormats) {
+        for (const auto& frameRate : supportedFormat.frameRates) {
+            int32_t framerateInt = static_cast<int32_t>(frameRate);
+            if (maxFps < framerateInt) {
+                maxFps = framerateInt;
+            }
+            if (framerateInt == 30) {
+                support30Fps = true;
+                break;
+            }
+        }
+        if (support30Fps) {
+            break;
+        }
+    }
+    int32_t defaultFramerate = support30Fps ? 30 : maxFps;
+    int32_t defaultFpsRange[] = {defaultFramerate, defaultFramerate};
+    UPDATE(md, ANDROID_CONTROL_AE_TARGET_FPS_RANGE, defaultFpsRange, ARRAY_SIZE(defaultFpsRange));
+
+    uint8_t antibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
+    UPDATE(md, ANDROID_CONTROL_AE_ANTIBANDING_MODE, &antibandingMode, 1);
+
+    const uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO;
+    UPDATE(md, ANDROID_CONTROL_MODE, &controlMode, 1);
+
+    auto requestTemplates = hidl_enum_iterator<RequestTemplate>();
+    for (RequestTemplate type : requestTemplates) {
+        ::android::hardware::camera::common::V1_0::helper::CameraMetadata mdCopy = md;
+        uint8_t intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
+        switch (type) {
+            case RequestTemplate::PREVIEW:
+                intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
+                break;
+            case RequestTemplate::STILL_CAPTURE:
+                intent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
+                break;
+            case RequestTemplate::VIDEO_RECORD:
+                intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
+                break;
+            case RequestTemplate::VIDEO_SNAPSHOT:
+                intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
+                break;
+            default:
+                ALOGE("%s: unknown template type %d", __FUNCTION__, type);
+                return BAD_VALUE;
+        }
+        UPDATE(mdCopy, ANDROID_CONTROL_CAPTURE_INTENT, &intent, 1);
+
+        camera_metadata_t* rawMd = mdCopy.release();
+        CameraMetadata hidlMd;
+        hidlMd.setToExternal(
+                (uint8_t*) rawMd, get_camera_metadata_size(rawMd));
+        mDefaultRequests[type] = hidlMd;
+        free_camera_metadata(rawMd);
+    }
+
+    return OK;
+}
+
+status_t ExternalCameraDeviceSession::fillCaptureResult(
+        common::V1_0::helper::CameraMetadata &md, nsecs_t timestamp) {
+    // android.control
+    // For USB camera, we don't know the AE state. Set the state to converged to
+    // indicate the frame should be good to use. Then apps don't have to wait the
+    // AE state.
+    const uint8_t aeState = ANDROID_CONTROL_AE_STATE_CONVERGED;
+    UPDATE(md, ANDROID_CONTROL_AE_STATE, &aeState, 1);
+
+    const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;
+    UPDATE(md, ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);
+
+
+    // TODO: b/72261912 AF should stay LOCKED until cancel is seen
+    bool afTrigger = false;
+    if (md.exists(ANDROID_CONTROL_AF_TRIGGER)) {
+        camera_metadata_entry entry = md.find(ANDROID_CONTROL_AF_TRIGGER);
+        if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) {
+            afTrigger = true;
+        } else if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_CANCEL) {
+            afTrigger = false;
+        }
+    }
+
+    // For USB camera, the USB camera handles everything and we don't have control
+    // over AF. We only simply fake the AF metadata based on the request
+    // received here.
+    uint8_t afState;
+    if (afTrigger) {
+        afState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
+    } else {
+        afState = ANDROID_CONTROL_AF_STATE_INACTIVE;
+    }
+    UPDATE(md, ANDROID_CONTROL_AF_STATE, &afState, 1);
+
+    // Set AWB state to converged to indicate the frame should be good to use.
+    const uint8_t awbState = ANDROID_CONTROL_AWB_STATE_CONVERGED;
+    UPDATE(md, ANDROID_CONTROL_AWB_STATE, &awbState, 1);
+
+    const uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
+    UPDATE(md, ANDROID_CONTROL_AWB_LOCK, &awbLock, 1);
+
+    camera_metadata_ro_entry active_array_size =
+        mCameraCharacteristics.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+
+    if (active_array_size.count == 0) {
+        ALOGE("%s: cannot find active array size!", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    // android.scaler
+    const int32_t crop_region[] = {
+          active_array_size.data.i32[0], active_array_size.data.i32[1],
+          active_array_size.data.i32[2], active_array_size.data.i32[3],
+    };
+    UPDATE(md, ANDROID_SCALER_CROP_REGION, crop_region, ARRAY_SIZE(crop_region));
+
+    // android.sensor
+    UPDATE(md, ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);
+
+    // android.statistics
+    const uint8_t lensShadingMapMode = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
+    UPDATE(md, ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, &lensShadingMapMode, 1);
+
+    const uint8_t sceneFlicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;
+    UPDATE(md, ANDROID_STATISTICS_SCENE_FLICKER, &sceneFlicker, 1);
+
+    return OK;
+}
+
+#undef ARRAY_SIZE
+#undef UPDATE
+
+V4L2Frame::V4L2Frame(
+        uint32_t w, uint32_t h, uint32_t fourcc,
+        int bufIdx, int fd, uint32_t dataSize) :
+        mWidth(w), mHeight(h), mFourcc(fourcc),
+        mBufferIndex(bufIdx), mFd(fd), mDataSize(dataSize) {}
+
+int V4L2Frame::map(uint8_t** data, size_t* dataSize) {
+    if (data == nullptr || dataSize == nullptr) {
+        ALOGI("%s: V4L2 buffer map bad argument: data %p, dataSize %p",
+                __FUNCTION__, data, dataSize);
+        return -EINVAL;
+    }
+
+    Mutex::Autolock _l(mLock);
+    if (!mMapped) {
+        void* addr = mmap(NULL, mDataSize, PROT_READ, MAP_SHARED, mFd, 0);
+        if (addr == MAP_FAILED) {
+            ALOGE("%s: V4L2 buffer map failed: %s", __FUNCTION__, strerror(errno));
+            return -EINVAL;
+        }
+        mData = static_cast<uint8_t*>(addr);
+        mMapped = true;
+    }
+    *data = mData;
+    *dataSize = mDataSize;
+    ALOGV("%s: V4L map FD %d, data %p size %zu", __FUNCTION__, mFd, mData, mDataSize);
+    return 0;
+}
+
+int V4L2Frame::unmap() {
+    Mutex::Autolock _l(mLock);
+    if (mMapped) {
+        ALOGV("%s: V4L unmap data %p size %zu", __FUNCTION__, mData, mDataSize);
+        if (munmap(mData, mDataSize) != 0) {
+            ALOGE("%s: V4L2 buffer unmap failed: %s", __FUNCTION__, strerror(errno));
+            return -EINVAL;
+        }
+        mMapped = false;
+    }
+    return 0;
+}
+
+V4L2Frame::~V4L2Frame() {
+    unmap();
+}
+
+AllocatedFrame::AllocatedFrame(
+        uint32_t w, uint32_t h) :
+        mWidth(w), mHeight(h), mFourcc(V4L2_PIX_FMT_YUV420) {};
+
+AllocatedFrame::~AllocatedFrame() {}
+
+int AllocatedFrame::allocate(YCbCrLayout* out) {
+    if ((mWidth % 2) || (mHeight % 2)) {
+        ALOGE("%s: bad dimension %dx%d (not multiple of 2)", __FUNCTION__, mWidth, mHeight);
+        return -EINVAL;
+    }
+
+    uint32_t dataSize = mWidth * mHeight * 3 / 2; // YUV420
+    if (mData.size() != dataSize) {
+        mData.resize(dataSize);
+    }
+
+    if (out != nullptr) {
+        out->y = mData.data();
+        out->yStride = mWidth;
+        uint8_t* cbStart = mData.data() + mWidth * mHeight;
+        uint8_t* crStart = cbStart + mWidth * mHeight / 4;
+        out->cb = cbStart;
+        out->cr = crStart;
+        out->cStride = mWidth / 2;
+        out->chromaStep = 1;
+    }
+    return 0;
+}
+
+int AllocatedFrame::getLayout(YCbCrLayout* out) {
+    IMapper::Rect noCrop = {0, 0,
+            static_cast<int32_t>(mWidth),
+            static_cast<int32_t>(mHeight)};
+    return getCroppedLayout(noCrop, out);
+}
+
+int AllocatedFrame::getCroppedLayout(const IMapper::Rect& rect, YCbCrLayout* out) {
+    if (out == nullptr) {
+        ALOGE("%s: null out", __FUNCTION__);
+        return -1;
+    }
+    if ((rect.left + rect.width) > static_cast<int>(mWidth) ||
+        (rect.top + rect.height) > static_cast<int>(mHeight) ||
+            (rect.left % 2) || (rect.top % 2) || (rect.width % 2) || (rect.height % 2)) {
+        ALOGE("%s: bad rect left %d top %d w %d h %d", __FUNCTION__,
+                rect.left, rect.top, rect.width, rect.height);
+        return -1;
+    }
+
+    out->y = mData.data() + mWidth * rect.top + rect.left;
+    out->yStride = mWidth;
+    uint8_t* cbStart = mData.data() + mWidth * mHeight;
+    uint8_t* crStart = cbStart + mWidth * mHeight / 4;
+    out->cb = cbStart + mWidth * rect.top / 4 + rect.left / 2;
+    out->cr = crStart + mWidth * rect.top / 4 + rect.left / 2;
+    out->cStride = mWidth / 2;
+    out->chromaStep = 1;
+    return 0;
+}
+
+}  // namespace implementation
+}  // namespace V3_4
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/device/3.4/default/convert.cpp b/camera/device/3.4/default/convert.cpp
new file mode 100644
index 0000000..f12230c
--- /dev/null
+++ b/camera/device/3.4/default/convert.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 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 "android.hardware.camera.device@3.4-convert-impl"
+#include <log/log.h>
+
+#include <cstring>
+#include "include/convert.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_4 {
+namespace implementation {
+
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
+using ::android::hardware::camera::device::V3_2::BufferUsageFlags;
+
+void convertToHidl(const Camera3Stream* src, HalStream* dst) {
+    V3_3::implementation::convertToHidl(src, &dst->v3_3);
+    dst->physicalCameraId = src->physical_camera_id;
+}
+
+void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst) {
+    dst->streams.resize(src.num_streams);
+    for (uint32_t i = 0; i < src.num_streams; i++) {
+        convertToHidl(static_cast<Camera3Stream*>(src.streams[i]), &dst->streams[i]);
+    }
+    return;
+}
+
+void convertFromHidl(const Stream &src, Camera3Stream* dst) {
+    V3_2::implementation::convertFromHidl(src.v3_2, dst);
+    // Initialize physical_camera_id
+    dst->physical_camera_id = nullptr;
+    return;
+}
+
+}  // namespace implementation
+}  // namespace V3_4
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/device/3.4/default/include/convert.h b/camera/device/3.4/default/include/convert.h
new file mode 100644
index 0000000..e8e3951
--- /dev/null
+++ b/camera/device/3.4/default/include/convert.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 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 HARDWARE_INTERFACES_CAMERA_DEVICE_V3_4_DEFAULT_INCLUDE_CONVERT_H_
+#define HARDWARE_INTERFACES_CAMERA_DEVICE_V3_4_DEFAULT_INCLUDE_CONVERT_H_
+
+#include <android/hardware/camera/device/3.4/types.h>
+#include "hardware/camera3.h"
+#include "../../3.3/default/include/convert.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_4 {
+namespace implementation {
+
+using ::android::hardware::camera::device::V3_2::implementation::Camera3Stream;
+
+void convertToHidl(const Camera3Stream* src, HalStream* dst);
+
+void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst);
+
+void convertFromHidl(const Stream &src, Camera3Stream* dst);
+
+}  // namespace implementation
+}  // namespace V3_4
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_CAMERA_DEVICE_V3_4_DEFAULT_INCLUDE_CONVERT_H_
diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
index bff1734..913bd78 100644
--- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
+++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2017-2018 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.
@@ -18,7 +18,6 @@
 #define ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_CAMERADEVICE3SESSION_H
 
 #include <android/hardware/camera/device/3.2/ICameraDevice.h>
-#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
 #include <../../3.3/default/CameraDeviceSession.h>
 #include <../../3.3/default/include/convert.h>
@@ -43,8 +42,9 @@
 
 using namespace ::android::hardware::camera::device;
 using ::android::hardware::camera::device::V3_2::CaptureRequest;
-using ::android::hardware::camera::device::V3_2::StreamConfiguration;
-using ::android::hardware::camera::device::V3_3::HalStreamConfiguration;
+using ::android::hardware::camera::device::V3_2::StreamType;
+using ::android::hardware::camera::device::V3_4::StreamConfiguration;
+using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
 using ::android::hardware::camera::device::V3_4::ICameraDeviceSession;
 using ::android::hardware::camera::common::V1_0::Status;
 using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
@@ -73,10 +73,27 @@
     // Methods from v3.3 and earlier will trampoline to inherited implementation
 
     // New methods for v3.4
+    Return<void> constructDefaultRequestSettings_3_4(
+            RequestTemplate type,
+            ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb);
 
     Return<void> configureStreams_3_4(
-            const V3_4::StreamConfiguration& requestedConfiguration,
-            ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb);
+            const StreamConfiguration& requestedConfiguration,
+            ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb);
+
+    bool preProcessConfigurationLocked_3_4(
+            const StreamConfiguration& requestedConfiguration,
+            camera3_stream_configuration_t *stream_list /*out*/,
+            hidl_vec<camera3_stream_t*> *streams /*out*/);
+    void postProcessConfigurationLocked_3_4(const StreamConfiguration& requestedConfiguration);
+
+    Return<void> processCaptureRequest_3_4(
+            const hidl_vec<V3_4::CaptureRequest>& requests,
+            const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+            ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb);
+    Status processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request);
+
+    std::map<int, std::string> mPhysicalCameraIdMap;
 private:
 
     struct TrampolineSessionInterface_3_4 : public ICameraDeviceSession {
@@ -90,11 +107,17 @@
         }
 
         virtual Return<void> configureStreams(
-                const StreamConfiguration& requestedConfiguration,
+                const V3_2::StreamConfiguration& requestedConfiguration,
                 V3_3::ICameraDeviceSession::configureStreams_cb _hidl_cb) override {
             return mParent->configureStreams(requestedConfiguration, _hidl_cb);
         }
 
+        virtual Return<void> processCaptureRequest_3_4(const hidl_vec<V3_4::CaptureRequest>& requests,
+                const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+                ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) override {
+            return mParent->processCaptureRequest_3_4(requests, cachesToRemove, _hidl_cb);
+        }
+
         virtual Return<void> processCaptureRequest(const hidl_vec<V3_2::CaptureRequest>& requests,
                 const hidl_vec<V3_2::BufferCache>& cachesToRemove,
                 V3_3::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
@@ -119,15 +142,21 @@
             return mParent->close();
         }
 
+        virtual Return<void> constructDefaultRequestSettings_3_4(
+                RequestTemplate type,
+                ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override {
+            return mParent->constructDefaultRequestSettings_3_4(type, _hidl_cb);
+        }
+
         virtual Return<void> configureStreams_3_3(
-                const StreamConfiguration& requestedConfiguration,
+                const V3_2::StreamConfiguration& requestedConfiguration,
                 configureStreams_3_3_cb _hidl_cb) override {
             return mParent->configureStreams_3_3(requestedConfiguration, _hidl_cb);
         }
 
         virtual Return<void> configureStreams_3_4(
-                const V3_4::StreamConfiguration& requestedConfiguration,
-                configureStreams_3_3_cb _hidl_cb) override {
+                const StreamConfiguration& requestedConfiguration,
+                configureStreams_3_4_cb _hidl_cb) override {
             return mParent->configureStreams_3_4(requestedConfiguration, _hidl_cb);
         }
 
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
new file mode 100644
index 0000000..d8a17f6
--- /dev/null
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2018 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_CAMERA_DEVICE_V3_4_EXTCAMERADEVICE3SESSION_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMERADEVICE3SESSION_H
+
+#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <include/convert.h>
+#include <chrono>
+#include <condition_variable>
+#include <list>
+#include <unordered_map>
+#include <unordered_set>
+#include "CameraMetadata.h"
+#include "HandleImporter.h"
+#include "utils/KeyedVector.h"
+#include "utils/Mutex.h"
+#include "utils/Thread.h"
+#include "android-base/unique_fd.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_4 {
+namespace implementation {
+
+using ::android::hardware::camera::device::V3_2::BufferCache;
+using ::android::hardware::camera::device::V3_2::BufferStatus;
+using ::android::hardware::camera::device::V3_2::CameraMetadata;
+using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::CaptureResult;
+using ::android::hardware::camera::device::V3_2::ErrorCode;
+using ::android::hardware::camera::device::V3_2::ICameraDeviceCallback;
+using ::android::hardware::camera::device::V3_2::MsgType;
+using ::android::hardware::camera::device::V3_2::NotifyMsg;
+using ::android::hardware::camera::device::V3_4::RequestTemplate;
+using ::android::hardware::camera::device::V3_2::Stream;
+using ::android::hardware::camera::device::V3_4::StreamConfiguration;
+using ::android::hardware::camera::device::V3_2::StreamConfigurationMode;
+using ::android::hardware::camera::device::V3_2::StreamRotation;
+using ::android::hardware::camera::device::V3_2::StreamType;
+using ::android::hardware::camera::device::V3_2::DataspaceFlags;
+using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
+using ::android::hardware::camera::device::V3_4::ICameraDeviceSession;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using ::android::Mutex;
+using ::android::base::unique_fd;
+
+// TODO: put V4L2 related structs into separate header?
+struct SupportedV4L2Format {
+    uint32_t width;
+    uint32_t height;
+    uint32_t fourcc;
+    // All supported frame rate for this w/h/fourcc combination
+    std::vector<float> frameRates;
+};
+
+// A class provide access to a dequeued V4L2 frame buffer (mostly in MJPG format)
+// Also contains necessary information to enqueue the buffer back to V4L2 buffer queue
+class V4L2Frame : public virtual VirtualLightRefBase {
+public:
+    V4L2Frame(uint32_t w, uint32_t h, uint32_t fourcc, int bufIdx, int fd, uint32_t dataSize);
+    ~V4L2Frame() override;
+    const uint32_t mWidth;
+    const uint32_t mHeight;
+    const uint32_t mFourcc;
+    const int mBufferIndex; // for later enqueue
+    int map(uint8_t** data, size_t* dataSize);
+    int unmap();
+private:
+    Mutex mLock;
+    const int mFd; // used for mmap but doesn't claim ownership
+    const size_t mDataSize;
+    uint8_t* mData = nullptr;
+    bool  mMapped = false;
+};
+
+// A RAII class representing a CPU allocated YUV frame used as intermeidate buffers
+// when generating output images.
+class AllocatedFrame : public virtual VirtualLightRefBase {
+public:
+    AllocatedFrame(uint32_t w, uint32_t h); // TODO: use Size?
+    ~AllocatedFrame() override;
+    const uint32_t mWidth;
+    const uint32_t mHeight;
+    const uint32_t mFourcc; // Only support YU12 format for now
+    int allocate(YCbCrLayout* out = nullptr);
+    int getLayout(YCbCrLayout* out);
+    int getCroppedLayout(const IMapper::Rect&, YCbCrLayout* out); // return non-zero for bad input
+private:
+    Mutex mLock;
+    std::vector<uint8_t> mData;
+};
+
+struct Size {
+    uint32_t width;
+    uint32_t height;
+
+    bool operator==(const Size& other) const {
+        return (width == other.width && height == other.height);
+    }
+};
+
+struct SizeHasher {
+    size_t operator()(const Size& sz) const {
+        size_t result = 1;
+        result = 31 * result + sz.width;
+        result = 31 * result + sz.height;
+        return result;
+    }
+};
+
+enum CroppingType {
+    HORIZONTAL = 0,
+    VERTICAL = 1
+};
+
+struct ExternalCameraDeviceSession : public virtual RefBase {
+
+    ExternalCameraDeviceSession(const sp<ICameraDeviceCallback>&,
+            const std::vector<SupportedV4L2Format>& supportedFormats,
+            const common::V1_0::helper::CameraMetadata& chars,
+            unique_fd v4l2Fd);
+    virtual ~ExternalCameraDeviceSession();
+    // Call by CameraDevice to dump active device states
+    void dumpState(const native_handle_t*);
+    // Caller must use this method to check if CameraDeviceSession ctor failed
+    bool isInitFailed() { return mInitFail; }
+    bool isClosed();
+
+    // Retrieve the HIDL interface, split into its own class to avoid inheritance issues when
+    // dealing with minor version revs and simultaneous implementation and interface inheritance
+    virtual sp<ICameraDeviceSession> getInterface() {
+        return new TrampolineSessionInterface_3_4(this);
+    }
+
+    static const int kMaxProcessedStream = 2;
+    static const int kMaxStallStream = 1;
+
+protected:
+
+    // Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow
+
+    Return<void> constructDefaultRequestSettings(
+            V3_2::RequestTemplate,
+            ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb);
+
+    Return<void> constructDefaultRequestSettings_3_4(
+            RequestTemplate type,
+            ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb);
+
+    Return<void> configureStreams(
+            const V3_2::StreamConfiguration&,
+            ICameraDeviceSession::configureStreams_cb);
+
+    Return<void> getCaptureRequestMetadataQueue(
+        ICameraDeviceSession::getCaptureRequestMetadataQueue_cb);
+
+    Return<void> getCaptureResultMetadataQueue(
+        ICameraDeviceSession::getCaptureResultMetadataQueue_cb);
+
+    Return<void> processCaptureRequest(
+            const hidl_vec<CaptureRequest>&,
+            const hidl_vec<BufferCache>&,
+            ICameraDeviceSession::processCaptureRequest_cb);
+
+    Return<Status> flush();
+    Return<void> close();
+
+    Return<void> configureStreams_3_3(
+            const V3_2::StreamConfiguration&,
+            ICameraDeviceSession::configureStreams_3_3_cb);
+
+    Return<void> configureStreams_3_4(
+            const V3_4::StreamConfiguration& requestedConfiguration,
+            ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb);
+
+    Return<void> processCaptureRequest_3_4(
+            const hidl_vec<V3_4::CaptureRequest>& requests,
+            const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+            ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb);
+
+protected:
+    struct HalStreamBuffer {
+        int32_t streamId;
+        uint64_t bufferId;
+        uint32_t width;
+        uint32_t height;
+        PixelFormat format;
+        V3_2::BufferUsageFlags usage;
+        buffer_handle_t* bufPtr;
+        int acquireFence;
+        bool fenceTimeout;
+    };
+
+    struct HalRequest {
+        uint32_t frameNumber;
+        common::V1_0::helper::CameraMetadata setting;
+        sp<V4L2Frame> frameIn;
+        nsecs_t shutterTs;
+        std::vector<HalStreamBuffer> buffers;
+    };
+
+    Status constructDefaultRequestSettingsRaw(RequestTemplate type,
+            V3_2::CameraMetadata *outMetadata);
+
+    static std::vector<SupportedV4L2Format> sortFormats(
+            const std::vector<SupportedV4L2Format>&);
+    static CroppingType initCroppingType(const std::vector<SupportedV4L2Format>&);
+    bool initialize();
+    Status initStatus() const;
+    status_t initDefaultRequests();
+    status_t fillCaptureResult(common::V1_0::helper::CameraMetadata& md, nsecs_t timestamp);
+    Status configureStreams(const V3_2::StreamConfiguration&, V3_3::HalStreamConfiguration* out);
+    int configureV4l2StreamLocked(const SupportedV4L2Format& fmt);
+    int v4l2StreamOffLocked();
+
+    // TODO: change to unique_ptr for better tracking
+    sp<V4L2Frame> dequeueV4l2FrameLocked(); // Called with mLock hold
+    void enqueueV4l2Frame(const sp<V4L2Frame>&);
+
+    // Check if input Stream is one of supported stream setting on this device
+    bool isSupported(const Stream&);
+
+    // Validate and import request's output buffers and acquire fence
+    Status importRequest(
+            const CaptureRequest& request,
+            hidl_vec<buffer_handle_t*>& allBufPtrs,
+            hidl_vec<int>& allFences);
+    static void cleanupInflightFences(
+            hidl_vec<int>& allFences, size_t numFences);
+    void cleanupBuffersLocked(int id);
+    void updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove);
+
+    Status processOneCaptureRequest(const CaptureRequest& request);
+
+    Status processCaptureResult(HalRequest&);
+    Status processCaptureRequestError(HalRequest&);
+    void notifyShutter(uint32_t frameNumber, nsecs_t shutterTs);
+    void notifyError(uint32_t frameNumber, int32_t streamId, ErrorCode ec);
+    void invokeProcessCaptureResultCallback(
+            hidl_vec<CaptureResult> &results, bool tryWriteFmq);
+    static void freeReleaseFences(hidl_vec<CaptureResult>&);
+
+    class OutputThread : public android::Thread {
+    public:
+        OutputThread(wp<ExternalCameraDeviceSession> parent, CroppingType);
+        ~OutputThread();
+
+        Status allocateIntermediateBuffers(
+                const Size& v4lSize, const hidl_vec<Stream>& streams);
+        Status submitRequest(const HalRequest&);
+        void flush();
+        virtual bool threadLoop() override;
+
+    private:
+        static const uint32_t FLEX_YUV_GENERIC = static_cast<uint32_t>('F') |
+                static_cast<uint32_t>('L') << 8 | static_cast<uint32_t>('E') << 16 |
+                static_cast<uint32_t>('X') << 24;
+        // returns FLEX_YUV_GENERIC for formats other than YV12/YU12/NV12/NV21
+        static uint32_t getFourCcFromLayout(const YCbCrLayout&);
+        static int getCropRect(
+                CroppingType ct, const Size& inSize, const Size& outSize, IMapper::Rect* out);
+
+        static const int kReqWaitTimeoutSec = 3;
+
+        void waitForNextRequest(HalRequest* out);
+        int cropAndScaleLocked(
+                sp<AllocatedFrame>& in, const HalStreamBuffer& halBuf,
+                YCbCrLayout* out);
+
+        int formatConvertLocked(const YCbCrLayout& in, const YCbCrLayout& out,
+                Size sz, uint32_t format);
+
+        mutable std::mutex mLock;
+        std::condition_variable mRequestCond;
+        wp<ExternalCameraDeviceSession> mParent;
+        CroppingType mCroppingType;
+        std::list<HalRequest> mRequestList;
+        // V4L2 frameIn
+        // (MJPG decode)-> mYu12Frame
+        // (Scale)-> mScaledYu12Frames
+        // (Format convert) -> output gralloc frames
+        sp<AllocatedFrame> mYu12Frame;
+        std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mIntermediateBuffers;
+        std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mScaledYu12Frames;
+        YCbCrLayout mYu12FrameLayout;
+    };
+
+    // Protect (most of) HIDL interface methods from synchronized-entering
+    mutable Mutex mInterfaceLock;
+
+    mutable Mutex mLock; // Protect all private members except otherwise noted
+    const sp<ICameraDeviceCallback> mCallback;
+    const common::V1_0::helper::CameraMetadata mCameraCharacteristics;
+    unique_fd mV4l2Fd;
+    // device is closed either
+    //    - closed by user
+    //    - init failed
+    //    - camera disconnected
+    bool mClosed = false;
+    bool mInitFail = false;
+    bool mFirstRequest = false;
+    common::V1_0::helper::CameraMetadata mLatestReqSetting;
+
+    bool mV4l2Streaming = false;
+    SupportedV4L2Format mV4l2StreamingFmt;
+    std::vector<unique_fd> mV4l2Buffers;
+
+    static const int kBufferWaitTimeoutSec = 3; // TODO: handle long exposure (or not allowing)
+    std::mutex mV4l2BufferLock; // protect the buffer count and condition below
+    std::condition_variable mV4L2BufferReturned;
+    size_t mNumDequeuedV4l2Buffers = 0;
+
+    const std::vector<SupportedV4L2Format> mSupportedFormats;
+    const CroppingType mCroppingType;
+    sp<OutputThread> mOutputThread;
+
+    // Stream ID -> Camera3Stream cache
+    std::unordered_map<int, Stream> mStreamMap;
+    std::unordered_set<uint32_t>  mInflightFrames;
+
+    // buffers currently circulating between HAL and camera service
+    // key: bufferId sent via HIDL interface
+    // value: imported buffer_handle_t
+    // Buffer will be imported during processCaptureRequest and will be freed
+    // when the its stream is deleted or camera device session is closed
+    typedef std::unordered_map<uint64_t, buffer_handle_t> CirculatingBuffers;
+    // Stream ID -> circulating buffers map
+    std::map<int, CirculatingBuffers> mCirculatingBuffers;
+
+    static HandleImporter sHandleImporter;
+
+    /* Beginning of members not changed after initialize() */
+    using RequestMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+    std::unique_ptr<RequestMetadataQueue> mRequestMetadataQueue;
+    using ResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+    std::shared_ptr<ResultMetadataQueue> mResultMetadataQueue;
+
+    // Protect against invokeProcessCaptureResultCallback()
+    Mutex mProcessCaptureResultLock;
+
+    std::unordered_map<RequestTemplate, CameraMetadata> mDefaultRequests;
+    /* End of members not changed after initialize() */
+
+private:
+
+    struct TrampolineSessionInterface_3_4 : public ICameraDeviceSession {
+        TrampolineSessionInterface_3_4(sp<ExternalCameraDeviceSession> parent) :
+                mParent(parent) {}
+
+        virtual Return<void> constructDefaultRequestSettings(
+                V3_2::RequestTemplate type,
+                V3_3::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override {
+            return mParent->constructDefaultRequestSettings(type, _hidl_cb);
+        }
+
+        virtual Return<void> configureStreams(
+                const V3_2::StreamConfiguration& requestedConfiguration,
+                V3_3::ICameraDeviceSession::configureStreams_cb _hidl_cb) override {
+            return mParent->configureStreams(requestedConfiguration, _hidl_cb);
+        }
+
+        virtual Return<void> processCaptureRequest(const hidl_vec<V3_2::CaptureRequest>& requests,
+                const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+                V3_3::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
+            return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb);
+        }
+
+        virtual Return<void> getCaptureRequestMetadataQueue(
+                V3_3::ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) override  {
+            return mParent->getCaptureRequestMetadataQueue(_hidl_cb);
+        }
+
+        virtual Return<void> getCaptureResultMetadataQueue(
+                V3_3::ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) override  {
+            return mParent->getCaptureResultMetadataQueue(_hidl_cb);
+        }
+
+        virtual Return<Status> flush() override {
+            return mParent->flush();
+        }
+
+        virtual Return<void> close() override {
+            return mParent->close();
+        }
+
+        virtual Return<void> constructDefaultRequestSettings_3_4(
+                RequestTemplate type,
+                ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override {
+            return mParent->constructDefaultRequestSettings_3_4(type, _hidl_cb);
+        }
+
+        virtual Return<void> configureStreams_3_3(
+                const V3_2::StreamConfiguration& requestedConfiguration,
+                configureStreams_3_3_cb _hidl_cb) override {
+            return mParent->configureStreams_3_3(requestedConfiguration, _hidl_cb);
+        }
+
+        virtual Return<void> configureStreams_3_4(
+                const V3_4::StreamConfiguration& requestedConfiguration,
+                configureStreams_3_4_cb _hidl_cb) override {
+            return mParent->configureStreams_3_4(requestedConfiguration, _hidl_cb);
+        }
+
+        virtual Return<void> processCaptureRequest_3_4(const hidl_vec<V3_4::CaptureRequest>& requests,
+                const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+                ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) override {
+            return mParent->processCaptureRequest_3_4(requests, cachesToRemove, _hidl_cb);
+        }
+
+    private:
+        sp<ExternalCameraDeviceSession> mParent;
+    };
+};
+
+}  // namespace implementation
+}  // namespace V3_4
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMERADEVICE3SESSION_H
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
new file mode 100644
index 0000000..606375e
--- /dev/null
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2018 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_CAMERA_DEVICE_V3_4_EXTCAMERADEVICE_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMERADEVICE_H
+
+#include "utils/Mutex.h"
+#include "CameraMetadata.h"
+
+#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+#include "ExternalCameraDeviceSession.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_4 {
+namespace implementation {
+
+using namespace ::android::hardware::camera::device;
+using ::android::hardware::camera::device::V3_2::ICameraDevice;
+using ::android::hardware::camera::device::V3_2::ICameraDeviceCallback;
+using ::android::hardware::camera::common::V1_0::CameraResourceCost;
+using ::android::hardware::camera::common::V1_0::TorchMode;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * The camera device HAL implementation is opened lazily (via the open call)
+ */
+struct ExternalCameraDevice : public ICameraDevice {
+
+    // Called by external camera provider HAL.
+    // Provider HAL must ensure the uniqueness of CameraDevice object per cameraId, or there could
+    // be multiple CameraDevice trying to access the same physical camera.  Also, provider will have
+    // to keep track of all CameraDevice objects in order to notify CameraDevice when the underlying
+    // camera is detached.
+    ExternalCameraDevice(const std::string& cameraId);
+    ~ExternalCameraDevice();
+
+    // Caller must use this method to check if CameraDevice ctor failed
+    bool isInitFailed();
+
+    /* Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow. */
+    // The following method can be called without opening the actual camera device
+    Return<void> getResourceCost(getResourceCost_cb _hidl_cb) override;
+
+    Return<void> getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb) override;
+
+    Return<Status> setTorchMode(TorchMode) override;
+
+    // Open the device HAL and also return a default capture session
+    Return<void> open(const sp<ICameraDeviceCallback>&, open_cb) override;
+
+    // Forward the dump call to the opened session, or do nothing
+    Return<void> dumpState(const ::android::hardware::hidl_handle&) override;
+    /* End of Methods from ::android::hardware::camera::device::V3_2::ICameraDevice */
+
+protected:
+    void getFrameRateList(int fd, SupportedV4L2Format* format);
+    // Init supported w/h/format/fps in mSupportedFormats. Caller still owns fd
+    void initSupportedFormatsLocked(int fd);
+
+    status_t initCameraCharacteristics();
+    // Init non-device dependent keys
+    status_t initDefaultCharsKeys(::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
+    // Init camera control chars keys. Caller still owns fd
+    status_t initCameraControlsCharsKeys(int fd,
+            ::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
+    // Init camera output configuration related keys.  Caller still owns fd
+    status_t initOutputCharsKeys(int fd,
+            ::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
+
+    Mutex mLock;
+    bool mInitFailed = false;
+    std::string mCameraId;
+    std::vector<SupportedV4L2Format> mSupportedFormats;
+
+    wp<ExternalCameraDeviceSession> mSession = nullptr;
+
+    ::android::hardware::camera::common::V1_0::helper::CameraMetadata mCameraCharacteristics;
+};
+
+}  // namespace implementation
+}  // namespace V3_4
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMERADEVICE_H
diff --git a/camera/device/3.4/types.hal b/camera/device/3.4/types.hal
index c822717..429db3e 100644
--- a/camera/device/3.4/types.hal
+++ b/camera/device/3.4/types.hal
@@ -16,19 +16,99 @@
 
 package android.hardware.camera.device@3.4;
 
-import @3.2::StreamConfiguration;
-import @3.2::types;
+import @3.2::RequestTemplate;
+import @3.2::StreamConfigurationMode;
+import @3.2::Stream;
+import @3.3::HalStream;
+import @3.2::CameraMetadata;
+import @3.2::CaptureRequest;
+
+/**
+ * Stream:
+ *
+ * A descriptor for a single camera input or output stream. A stream is defined
+ * by the framework by its buffer resolution and format, and additionally by the
+ * HAL with the gralloc usage flags and the maximum in-flight buffer count.
+ *
+ * This version extends the @3.2 Stream with the physicalCameraId field.
+ */
+struct Stream {
+    /**
+     * The definition of Stream from the prior version
+     */
+    @3.2::Stream v3_2;
+
+    /**
+     * The physical camera id this stream belongs to.
+     *
+     * If the camera device is not a logical multi camera, or if the camera is a logical
+     * multi camera but the stream is not a physical output stream, this field will point to a
+     * 0-length string.
+     *
+     * A logical multi camera is a camera device backed by multiple physical cameras that
+     * are also exposed to the application. And for a logical multi camera, a physical output
+     * stream is an output stream specifically requested on an underlying physical camera.
+     *
+     * A logical camera is a camera device backed by multiple physical camera
+     * devices. And a physical stream is a stream specifically requested on a
+     * underlying physical camera device.
+     *
+     * For an input stream, this field is guaranteed to be a 0-length string.
+     *
+     * When not empty, this field is the <id> field of one of the full-qualified device
+     * instance names returned by getCameraIdList().
+     */
+    string physicalCameraId;
+};
+
+/**
+ * New request templates, extending the @3.2 RequestTemplate
+ */
+enum RequestTemplate : @3.2::RequestTemplate {
+    /**
+     * A template for selecting camera parameters that match TEMPLATE_PREVIEW as closely as
+     * possible while improving the camera output for motion tracking use cases.
+     *
+     * This template is best used by applications that are frequently switching between motion
+     * tracking use cases and regular still capture use cases, to minimize the IQ changes
+     * when swapping use cases.
+     *
+     * This template is guaranteed to be supported on camera devices that support the
+     * REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING capability.
+     */
+    MOTION_TRACKING_PREVIEW = 7,
+
+    /**
+     * A template for selecting camera parameters that maximize the quality of camera output for
+     * motion tracking use cases.
+     *
+     * This template is best used by applications dedicated to motion tracking applications,
+     * which aren't concerned about fast switches between motion tracking and other use cases.
+     *
+     * This template is guaranteed to be supported on camera devices that support the
+     * REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING capability.
+     */
+    MOTION_TRACKING_BEST = 8,
+};
 
 /**
  * StreamConfiguration:
  *
- * Identical to @3.2::StreamConfiguration, except that it contains session parameters.
+ * Identical to @3.2::StreamConfiguration, except that it contains session
+ * parameters, and the streams vector contains @3.4::Stream.
  */
 struct StreamConfiguration {
     /**
-     * The definition of StreamConfiguration from the prior version.
+     * An array of camera stream pointers, defining the input/output
+     * configuration for the camera HAL device.
      */
-    @3.2::StreamConfiguration v3_2;
+    vec<Stream> streams;
+
+    /**
+     * The definition of operation mode from prior version.
+     *
+     */
+    StreamConfigurationMode operationMode;
 
     /**
      * Session wide camera parameters.
@@ -44,3 +124,105 @@
      */
     CameraMetadata sessionParams;
 };
+
+/**
+ * HalStream:
+ *
+ * The camera HAL's response to each requested stream configuration.
+ *
+ * This version extends the @3.3 HalStream with the physicalCameraId
+ * field
+ */
+struct HalStream {
+    /**
+     * The definition of HalStream from the prior version.
+     */
+    @3.3::HalStream v3_3;
+
+    /**
+     * The physical camera id the current Hal stream belongs to.
+     *
+     * If current camera device isn't a logical camera, or the Hal stream isn't
+     * from a physical camera of the logical camera, this must be an empty
+     * string.
+     *
+     * A logical camera is a camera device backed by multiple physical camera
+     * devices.
+     *
+     * When not empty, this field is the <id> field of one of the full-qualified device
+     * instance names returned by getCameraIdList().
+     */
+    string physicalCameraId;
+};
+
+/**
+ * HalStreamConfiguration:
+ *
+ * Identical to @3.3::HalStreamConfiguration, except that it contains @3.4::HalStream entries.
+ *
+ */
+struct HalStreamConfiguration {
+    vec<HalStream> streams;
+};
+
+/**
+ * PhysicalCameraSetting:
+ *
+ * Individual camera settings for logical camera backed by multiple physical devices.
+ * Clients are allowed to pass separate settings for each physical device.
+ */
+struct PhysicalCameraSetting {
+    /**
+     * If non-zero, read settings from request queue instead
+     * (see ICameraDeviceSession.getCaptureRequestMetadataQueue).
+     * If zero, read settings from .settings field.
+     */
+    uint64_t fmqSettingsSize;
+
+    /**
+     * Contains the physical device camera id. Any settings passed by client here
+     * should be applied for this physical device. In case the physical id is invalid
+     * Hal should fail the process request and return Status::ILLEGAL_ARGUMENT.
+     */
+    string physicalCameraId;
+
+    /**
+     * If fmqSettingsSize is zero, the settings buffer contains the capture and
+     * processing parameters for the physical device with id 'phyCamId'.
+     * In case the individual settings are empty or missing, Hal should fail the
+     * request and return Status::ILLEGAL_ARGUMENT.
+     */
+    CameraMetadata settings;
+};
+
+/**
+ * CaptureRequest:
+ *
+ * A single request for image capture/buffer reprocessing, sent to the Camera
+ * HAL device by the framework in processCaptureRequest().
+ *
+ * The request contains the settings to be used for this capture, and the set of
+ * output buffers to write the resulting image data in. It may optionally
+ * contain an input buffer, in which case the request is for reprocessing that
+ * input buffer instead of capturing a new image with the camera sensor. The
+ * capture is identified by the frameNumber.
+ *
+ * In response, the camera HAL device must send a CaptureResult
+ * structure asynchronously to the framework, using the processCaptureResult()
+ * callback.
+ *
+ * Identical to @3.2::CaptureRequest, except that it contains @3.4::physCamSettings vector.
+ *
+ */
+struct CaptureRequest {
+    /**
+     * The definition of CaptureRequest from prior version.
+     */
+    @3.2::CaptureRequest v3_2;
+
+    /**
+     * A vector containing individual camera settings for logical camera backed by multiple physical
+     * devices. In case the vector is empty, Hal should use the settings field in 'v3_2'.
+     */
+    vec<PhysicalCameraSetting> physicalCameraSettings;
+};
diff --git a/camera/metadata/3.3/Android.bp b/camera/metadata/3.3/Android.bp
index 458f895..166c2ac 100644
--- a/camera/metadata/3.3/Android.bp
+++ b/camera/metadata/3.3/Android.bp
@@ -13,7 +13,16 @@
         "android.hardware.camera.metadata@3.2",
     ],
     types: [
+        "CameraMetadataEnumAndroidControlAeMode",
         "CameraMetadataEnumAndroidControlAfSceneChange",
+        "CameraMetadataEnumAndroidControlCaptureIntent",
+        "CameraMetadataEnumAndroidInfoSupportedHardwareLevel",
+        "CameraMetadataEnumAndroidLensPoseReference",
+        "CameraMetadataEnumAndroidLogicalMultiCameraSensorSyncType",
+        "CameraMetadataEnumAndroidRequestAvailableCapabilities",
+        "CameraMetadataEnumAndroidStatisticsOisDataMode",
+        "CameraMetadataSection",
+        "CameraMetadataSectionStart",
         "CameraMetadataTag",
     ],
     gen_java: true,
diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal
index 1d167ae..d2a5886 100644
--- a/camera/metadata/3.3/types.hal
+++ b/camera/metadata/3.3/types.hal
@@ -25,7 +25,30 @@
 /* Include definitions from all prior minor HAL metadata revisions */
 import android.hardware.camera.metadata@3.2;
 
-// No new metadata sections added in this revision
+/**
+ * Top level hierarchy definitions for camera metadata. *_INFO sections are for
+ * the static metadata that can be retrived without opening the camera device.
+ */
+enum CameraMetadataSection : @3.2::CameraMetadataSection {
+    ANDROID_LOGICAL_MULTI_CAMERA =
+        android.hardware.camera.metadata@3.2::CameraMetadataSection:ANDROID_SECTION_COUNT,
+
+    ANDROID_SECTION_COUNT_3_3,
+
+    VENDOR_SECTION_3_3 = 0x8000,
+
+};
+
+/**
+ * Hierarchy positions in enum space. All vendor extension sections must be
+ * defined with tag >= VENDOR_SECTION_START
+ */
+enum CameraMetadataSectionStart : android.hardware.camera.metadata@3.2::CameraMetadataSectionStart {
+    ANDROID_LOGICAL_MULTI_CAMERA_START = CameraMetadataSection:ANDROID_LOGICAL_MULTI_CAMERA << 16,
+
+    VENDOR_SECTION_START_3_3 = CameraMetadataSection:VENDOR_SECTION_3_3 << 16,
+
+};
 
 /**
  * Main enumeration for defining camera metadata tags added in this revision
@@ -43,6 +66,70 @@
 
     ANDROID_CONTROL_END_3_3,
 
+    /** android.lens.poseReference [static, enum, public]
+     *
+     * <p>The origin for ANDROID_LENS_POSE_TRANSLATION.</p>
+     *
+     * @see ANDROID_LENS_POSE_TRANSLATION
+     */
+    ANDROID_LENS_POSE_REFERENCE = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_LENS_END,
+
+    ANDROID_LENS_END_3_3,
+
+    /** android.request.availableSessionKeys [static, int32[], ndk_public]
+     *
+     * <p>A subset of the available request keys that the camera device
+     * can pass as part of the capture session initialization.</p>
+     */
+    ANDROID_REQUEST_AVAILABLE_SESSION_KEYS = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_REQUEST_END,
+
+    /** android.request.availablePhysicalCameraRequestKeys [static, int32[], hidden]
+     *
+     * <p>A subset of the available request keys that can be overriden for
+     * physical devices backing a logical multi-camera.</p>
+     */
+    ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS,
+
+    ANDROID_REQUEST_END_3_3,
+
+    /** android.statistics.oisDataMode [dynamic, enum, public]
+     *
+     * <p>Whether the camera device outputs the OIS data in output
+     * result metadata.</p>
+     */
+    ANDROID_STATISTICS_OIS_DATA_MODE = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_STATISTICS_END,
+
+    /** android.statistics.oisTimestamps [dynamic, int64[], public]
+     *
+     * <p>An array of timestamps of OIS samples, in nanoseconds.</p>
+     */
+    ANDROID_STATISTICS_OIS_TIMESTAMPS,
+
+    /** android.statistics.oisXShifts [dynamic, float[], public]
+     *
+     * <p>An array of shifts of OIS samples, in x direction.</p>
+     */
+    ANDROID_STATISTICS_OIS_X_SHIFTS,
+
+    /** android.statistics.oisYShifts [dynamic, float[], public]
+     *
+     * <p>An array of shifts of OIS samples, in y direction.</p>
+     */
+    ANDROID_STATISTICS_OIS_Y_SHIFTS,
+
+    ANDROID_STATISTICS_END_3_3,
+
+    /** android.statistics.info.availableOisDataModes [static, byte[], public]
+     *
+     * <p>List of OIS data output modes for ANDROID_STATISTICS_OIS_DATA_MODE that
+     * are supported by this camera device.</p>
+     *
+     * @see ANDROID_STATISTICS_OIS_DATA_MODE
+     */
+    ANDROID_STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_STATISTICS_INFO_END,
+
+    ANDROID_STATISTICS_INFO_END_3_3,
+
     /** android.info.version [static, byte, public]
      *
      * <p>A short string for manufacturer version information about the camera device, such as
@@ -52,12 +139,42 @@
 
     ANDROID_INFO_END_3_3,
 
+    /** android.logicalMultiCamera.physicalIds [static, byte[], hidden]
+     *
+     * <p>String containing the ids of the underlying physical cameras.</p>
+     */
+    ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS = CameraMetadataSectionStart:ANDROID_LOGICAL_MULTI_CAMERA_START,
+
+    /** android.logicalMultiCamera.sensorSyncType [static, enum, public]
+     *
+     * <p>The accuracy of frame timestamp synchronization between physical cameras</p>
+     */
+    ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE,
+
+    ANDROID_LOGICAL_MULTI_CAMERA_END_3_3,
+
 };
 
 /*
  * Enumeration definitions for the various entries that need them
  */
 
+/** android.control.aeMode enumeration values added since v3.2
+ * @see ANDROID_CONTROL_AE_MODE
+ */
+enum CameraMetadataEnumAndroidControlAeMode :
+        @3.2::CameraMetadataEnumAndroidControlAeMode {
+    ANDROID_CONTROL_AE_MODE_ON_EXTERNAL_FLASH,
+};
+
+/** android.control.captureIntent enumeration values added since v3.2
+ * @see ANDROID_CONTROL_CAPTURE_INTENT
+ */
+enum CameraMetadataEnumAndroidControlCaptureIntent :
+        @3.2::CameraMetadataEnumAndroidControlCaptureIntent {
+    ANDROID_CONTROL_CAPTURE_INTENT_MOTION_TRACKING,
+};
+
 /** android.control.afSceneChange enumeration values
  * @see ANDROID_CONTROL_AF_SCENE_CHANGE
  */
@@ -65,3 +182,44 @@
     ANDROID_CONTROL_AF_SCENE_CHANGE_NOT_DETECTED,
     ANDROID_CONTROL_AF_SCENE_CHANGE_DETECTED,
 };
+
+/** android.lens.poseReference enumeration values
+ * @see ANDROID_LENS_POSE_REFERENCE
+ */
+enum CameraMetadataEnumAndroidLensPoseReference : uint32_t {
+    ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA,
+    ANDROID_LENS_POSE_REFERENCE_GYROSCOPE,
+};
+
+/** android.request.availableCapabilities enumeration values added since v3.2
+ * @see ANDROID_REQUEST_AVAILABLE_CAPABILITIES
+ */
+enum CameraMetadataEnumAndroidRequestAvailableCapabilities :
+        @3.2::CameraMetadataEnumAndroidRequestAvailableCapabilities {
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA,
+};
+
+/** android.logicalMultiCamera.sensorSyncType enumeration values
+ * @see ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
+ */
+enum CameraMetadataEnumAndroidLogicalMultiCameraSensorSyncType : uint32_t {
+    ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE,
+    ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED,
+};
+
+/** android.info.supportedHardwareLevel enumeration values added since v3.2
+ * @see ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL
+ */
+enum CameraMetadataEnumAndroidInfoSupportedHardwareLevel :
+        @3.2::CameraMetadataEnumAndroidInfoSupportedHardwareLevel {
+    ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL,
+};
+
+/** android.statistics.oisDataMode enumeration values
+ * @see ANDROID_STATISTICS_OIS_DATA_MODE
+ */
+enum CameraMetadataEnumAndroidStatisticsOisDataMode : uint32_t {
+    ANDROID_STATISTICS_OIS_DATA_MODE_OFF,
+    ANDROID_STATISTICS_OIS_DATA_MODE_ON,
+};
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index 99c3e92..1f46b89 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -3,7 +3,8 @@
     defaults: ["hidl_defaults"],
     proprietary: true,
     relative_install_path: "hw",
-    srcs: ["CameraProvider.cpp"],
+    srcs: ["CameraProvider.cpp",
+           "ExternalCameraProvider.cpp"],
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
@@ -17,6 +18,7 @@
         "camera.device@3.2-impl",
         "camera.device@3.3-impl",
         "camera.device@3.4-impl",
+        "camera.device@3.4-external-impl",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.common@1.0",
         "android.hardware.graphics.mapper@2.0",
@@ -28,6 +30,7 @@
     ],
     header_libs: [
         "camera.device@3.4-impl_headers",
+        "camera.device@3.4-external-impl_headers"
     ],
     static_libs: [
         "android.hardware.camera.common@1.0-helper",
@@ -56,3 +59,25 @@
         "android.hardware.camera.common@1.0",
     ],
 }
+
+cc_binary {
+    name: "android.hardware.camera.provider@2.4-external-service",
+    defaults: ["hidl_defaults"],
+    proprietary: true,
+    relative_install_path: "hw",
+    srcs: ["external-service.cpp"],
+    compile_multilib: "32",
+    init_rc: ["android.hardware.camera.provider@2.4-external-service.rc"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libbinder",
+        "liblog",
+        "libutils",
+        "android.hardware.camera.device@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.3",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.camera.common@1.0",
+    ],
+}
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
index ed974a5..8e37b26 100644
--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -19,6 +19,7 @@
 #include <android/log.h>
 
 #include "CameraProvider.h"
+#include "ExternalCameraProvider.h"
 #include "CameraDevice_1_0.h"
 #include "CameraDevice_3_3.h"
 #include "CameraDevice_3_4.h"
@@ -36,6 +37,7 @@
 
 namespace {
 const char *kLegacyProviderName = "legacy/0";
+const char *kExternalProviderName = "external/0";
 // "device@<version>/legacy/<id>"
 const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/legacy/(.+)");
 const char *kHAL3_2 = "3.2";
@@ -66,6 +68,70 @@
 using ::android::hardware::camera::common::V1_0::CameraMetadataType;
 using ::android::hardware::camera::common::V1_0::Status;
 
+void CameraProvider::addDeviceNames(int camera_id, CameraDeviceStatus status, bool cam_new)
+{
+    char cameraId[kMaxCameraIdLen];
+    snprintf(cameraId, sizeof(cameraId), "%d", camera_id);
+    std::string cameraIdStr(cameraId);
+
+    mCameraIds.add(cameraIdStr);
+
+    // initialize mCameraDeviceNames and mOpenLegacySupported
+    mOpenLegacySupported[cameraIdStr] = false;
+    int deviceVersion = mModule->getDeviceVersion(camera_id);
+    auto deviceNamePair = std::make_pair(cameraIdStr,
+                                         getHidlDeviceName(cameraIdStr, deviceVersion));
+    mCameraDeviceNames.add(deviceNamePair);
+    if (cam_new) {
+        mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+    }
+    if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
+            mModule->isOpenLegacyDefined()) {
+        // try open_legacy to see if it actually works
+        struct hw_device_t* halDev = nullptr;
+        int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
+        if (ret == 0) {
+            mOpenLegacySupported[cameraIdStr] = true;
+            halDev->close(halDev);
+            deviceNamePair = std::make_pair(cameraIdStr,
+                            getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0));
+            mCameraDeviceNames.add(deviceNamePair);
+            if (cam_new) {
+                mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+            }
+        } else if (ret == -EBUSY || ret == -EUSERS) {
+            // Looks like this provider instance is not initialized during
+            // system startup and there are other camera users already.
+            // Not a good sign but not fatal.
+            ALOGW("%s: open_legacy try failed!", __FUNCTION__);
+        }
+    }
+}
+
+void CameraProvider::removeDeviceNames(int camera_id)
+{
+    std::string cameraIdStr = std::to_string(camera_id);
+
+    mCameraIds.remove(cameraIdStr);
+
+    int deviceVersion = mModule->getDeviceVersion(camera_id);
+    auto deviceNamePair = std::make_pair(cameraIdStr,
+                                         getHidlDeviceName(cameraIdStr, deviceVersion));
+    mCameraDeviceNames.remove(deviceNamePair);
+    mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, CameraDeviceStatus::NOT_PRESENT);
+    if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
+        mModule->isOpenLegacyDefined() && mOpenLegacySupported[cameraIdStr]) {
+
+        deviceNamePair = std::make_pair(cameraIdStr,
+                            getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0));
+        mCameraDeviceNames.remove(deviceNamePair);
+        mCallbacks->cameraDeviceStatusChange(deviceNamePair.second,
+                                             CameraDeviceStatus::NOT_PRESENT);
+    }
+
+    mModule->removeCamera(camera_id);
+}
+
 /**
  * static callback forwarding methods from HAL to instance
  */
@@ -75,6 +141,7 @@
         int new_status) {
     CameraProvider* cp = const_cast<CameraProvider*>(
             static_cast<const CameraProvider*>(callbacks));
+    bool found = false;
 
     if (cp == nullptr) {
         ALOGE("%s: callback ops is null", __FUNCTION__);
@@ -92,6 +159,20 @@
             if (cameraIdStr.compare(deviceNamePair.first) == 0) {
                 cp->mCallbacks->cameraDeviceStatusChange(
                         deviceNamePair.second, status);
+                found = true;
+            }
+        }
+
+        switch (status) {
+        case CameraDeviceStatus::PRESENT:
+        case CameraDeviceStatus::ENUMERATING:
+            if (!found) {
+                cp->addDeviceNames(camera_id, status, true);
+            }
+            break;
+        case CameraDeviceStatus::NOT_PRESENT:
+            if (found) {
+                cp->removeDeviceNames(camera_id);
             }
         }
     }
@@ -251,32 +332,8 @@
         snprintf(cameraId, sizeof(cameraId), "%d", i);
         std::string cameraIdStr(cameraId);
         mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT;
-        mCameraIds.add(cameraIdStr);
 
-        // initialize mCameraDeviceNames and mOpenLegacySupported
-        mOpenLegacySupported[cameraIdStr] = false;
-        int deviceVersion = mModule->getDeviceVersion(i);
-        mCameraDeviceNames.add(
-                std::make_pair(cameraIdStr,
-                               getHidlDeviceName(cameraIdStr, deviceVersion)));
-        if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
-                mModule->isOpenLegacyDefined()) {
-            // try open_legacy to see if it actually works
-            struct hw_device_t* halDev = nullptr;
-            int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
-            if (ret == 0) {
-                mOpenLegacySupported[cameraIdStr] = true;
-                halDev->close(halDev);
-                mCameraDeviceNames.add(
-                        std::make_pair(cameraIdStr,
-                                getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0)));
-            } else if (ret == -EBUSY || ret == -EUSERS) {
-                // Looks like this provider instance is not initialized during
-                // system startup and there are other camera users already.
-                // Not a good sign but not fatal.
-                ALOGW("%s: open_legacy try failed!", __FUNCTION__);
-            }
-        }
+        addDeviceNames(i);
     }
 
     return false; // mInitFailed
@@ -549,20 +606,24 @@
 }
 
 ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) {
-    if (strcmp(name, kLegacyProviderName) != 0) {
-        return nullptr;
+    if (strcmp(name, kLegacyProviderName) == 0) {
+        CameraProvider* provider = new CameraProvider();
+        if (provider == nullptr) {
+            ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);
+            return nullptr;
+        }
+        if (provider->isInitFailed()) {
+            ALOGE("%s: camera provider init failed!", __FUNCTION__);
+            delete provider;
+            return nullptr;
+        }
+        return provider;
+    } else if (strcmp(name, kExternalProviderName) == 0) {
+        ExternalCameraProvider* provider = new ExternalCameraProvider();
+        return provider;
     }
-    CameraProvider* provider = new CameraProvider();
-    if (provider == nullptr) {
-        ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);
-        return nullptr;
-    }
-    if (provider->isInitFailed()) {
-        ALOGE("%s: camera provider init failed!", __FUNCTION__);
-        delete provider;
-        return nullptr;
-    }
-    return provider;
+    ALOGE("%s: unknown instance name: %s", __FUNCTION__, name);
+    return nullptr;
 }
 
 } // namespace implementation
diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/CameraProvider.h
index 4980711..0f0959f 100644
--- a/camera/provider/2.4/default/CameraProvider.h
+++ b/camera/provider/2.4/default/CameraProvider.h
@@ -112,6 +112,10 @@
         const struct camera_module_callbacks* callbacks,
         const char* camera_id,
         int new_status);
+
+    void addDeviceNames(int camera_id, CameraDeviceStatus status = CameraDeviceStatus::PRESENT,
+                        bool cam_new = false);
+    void removeDeviceNames(int camera_id);
 };
 
 extern "C" ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name);
diff --git a/camera/provider/2.4/default/ExternalCameraProvider.cpp b/camera/provider/2.4/default/ExternalCameraProvider.cpp
new file mode 100644
index 0000000..bb5c336
--- /dev/null
+++ b/camera/provider/2.4/default/ExternalCameraProvider.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2018 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 "CamPvdr@2.4-external"
+//#define LOG_NDEBUG 0
+#include <log/log.h>
+
+#include <regex>
+#include <sys/inotify.h>
+#include <errno.h>
+#include <linux/videodev2.h>
+#include "ExternalCameraProvider.h"
+#include "ExternalCameraDevice_3_4.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace provider {
+namespace V2_4 {
+namespace implementation {
+
+namespace {
+// "device@<version>/external/<id>"
+const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/external/(.+)");
+const int kMaxDevicePathLen = 256;
+const char* kDevicePath = "/dev/";
+
+bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion,
+                     std::string* cameraId) {
+    std::string deviceNameStd(deviceName.c_str());
+    std::smatch sm;
+    if (std::regex_match(deviceNameStd, sm, kDeviceNameRE)) {
+        if (deviceVersion != nullptr) {
+            *deviceVersion = sm[1];
+        }
+        if (cameraId != nullptr) {
+            *cameraId = sm[2];
+        }
+        return true;
+    }
+    return false;
+}
+
+} // anonymous namespace
+
+ExternalCameraProvider::ExternalCameraProvider() : mHotPlugThread(this) {
+    mHotPlugThread.run("ExtCamHotPlug", PRIORITY_BACKGROUND);
+}
+
+ExternalCameraProvider::~ExternalCameraProvider() {
+    mHotPlugThread.requestExit();
+}
+
+
+Return<Status> ExternalCameraProvider::setCallback(
+        const sp<ICameraProviderCallback>& callback) {
+    Mutex::Autolock _l(mLock);
+    mCallbacks = callback;
+    return Status::OK;
+}
+
+Return<void> ExternalCameraProvider::getVendorTags(getVendorTags_cb _hidl_cb) {
+    // No vendor tag support for USB camera
+    hidl_vec<VendorTagSection> zeroSections;
+    _hidl_cb(Status::OK, zeroSections);
+    return Void();
+}
+
+Return<void> ExternalCameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) {
+    std::vector<hidl_string> deviceNameList;
+    for (auto const& kvPair : mCameraStatusMap) {
+        if (kvPair.second == CameraDeviceStatus::PRESENT) {
+            deviceNameList.push_back(kvPair.first);
+        }
+    }
+    hidl_vec<hidl_string> hidlDeviceNameList(deviceNameList);
+    ALOGV("ExtCam: number of cameras is %zu", deviceNameList.size());
+    _hidl_cb(Status::OK, hidlDeviceNameList);
+    return Void();
+}
+
+Return<void> ExternalCameraProvider::isSetTorchModeSupported(
+        isSetTorchModeSupported_cb _hidl_cb) {
+    // No torch mode support for USB camera
+    _hidl_cb (Status::OK, false);
+    return Void();
+}
+
+Return<void> ExternalCameraProvider::getCameraDeviceInterface_V1_x(
+        const hidl_string&,
+        getCameraDeviceInterface_V1_x_cb _hidl_cb) {
+    // External Camera HAL does not support HAL1
+    _hidl_cb(Status::OPERATION_NOT_SUPPORTED, nullptr);
+    return Void();
+}
+
+Return<void> ExternalCameraProvider::getCameraDeviceInterface_V3_x(
+        const hidl_string& cameraDeviceName,
+        getCameraDeviceInterface_V3_x_cb _hidl_cb) {
+
+    std::string cameraId, deviceVersion;
+    bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId);
+    if (!match) {
+        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+        return Void();
+    }
+
+    if (mCameraStatusMap.count(cameraDeviceName) == 0 ||
+            mCameraStatusMap[cameraDeviceName] != CameraDeviceStatus::PRESENT) {
+        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+        return Void();
+    }
+
+    ALOGV("Constructing v3.4 external camera device");
+    sp<device::V3_2::ICameraDevice> device;
+    sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl =
+            new device::V3_4::implementation::ExternalCameraDevice(
+                    cameraId);
+    if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
+        ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
+        device = nullptr;
+        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+        return Void();
+    }
+    device = deviceImpl;
+
+    _hidl_cb (Status::OK, device);
+
+    return Void();
+}
+
+void ExternalCameraProvider::addExternalCamera(const char* devName) {
+    ALOGE("ExtCam: adding %s to External Camera HAL!", devName);
+    Mutex::Autolock _l(mLock);
+    std::string deviceName = std::string("device@3.4/external/") + devName;
+    mCameraStatusMap[deviceName] = CameraDeviceStatus::PRESENT;
+    if (mCallbacks != nullptr) {
+        mCallbacks->cameraDeviceStatusChange(deviceName, CameraDeviceStatus::PRESENT);
+    }
+}
+
+void ExternalCameraProvider::deviceAdded(const char* devName) {
+    int fd = -1;
+    if ((fd = ::open(devName, O_RDWR)) < 0) {
+        ALOGE("%s open v4l2 device %s failed:%s", __FUNCTION__, devName, strerror(errno));
+        return;
+    }
+
+    do {
+        struct v4l2_capability capability;
+        int ret = ioctl(fd, VIDIOC_QUERYCAP, &capability);
+        if (ret < 0) {
+            ALOGE("%s v4l2 QUERYCAP %s failed", __FUNCTION__, devName);
+            break;
+        }
+
+        if (!(capability.device_caps & V4L2_CAP_VIDEO_CAPTURE)) {
+            ALOGW("%s device %s does not support VIDEO_CAPTURE", __FUNCTION__, devName);
+            break;
+        }
+
+        addExternalCamera(devName);
+    } while (0);
+
+    close(fd);
+    return;
+}
+
+void ExternalCameraProvider::deviceRemoved(const char* devName) {
+    Mutex::Autolock _l(mLock);
+    std::string deviceName = std::string("device@3.4/external/") + devName;
+    if (mCameraStatusMap.find(deviceName) != mCameraStatusMap.end()) {
+        mCameraStatusMap.erase(deviceName);
+        if (mCallbacks != nullptr) {
+            mCallbacks->cameraDeviceStatusChange(deviceName, CameraDeviceStatus::NOT_PRESENT);
+        }
+    } else {
+        ALOGE("%s: cannot find camera device %s", __FUNCTION__, devName);
+    }
+}
+
+ExternalCameraProvider::HotplugThread::HotplugThread(ExternalCameraProvider* parent) :
+        Thread(/*canCallJava*/false), mParent(parent) {}
+
+ExternalCameraProvider::HotplugThread::~HotplugThread() {}
+
+bool ExternalCameraProvider::HotplugThread::threadLoop() {
+    // Find existing /dev/video* devices
+    DIR* devdir = opendir(kDevicePath);
+    if(devdir == 0) {
+        ALOGE("%s: cannot open %s! Exiting threadloop", __FUNCTION__, kDevicePath);
+        return false;
+    }
+
+    struct dirent* de;
+    // This list is device dependent. TODO: b/72261897 allow setting it from setprop/device boot
+    std::string internalDevices = "0,1";
+    while ((de = readdir(devdir)) != 0) {
+        // Find external v4l devices that's existing before we start watching and add them
+        if (!strncmp("video", de->d_name, 5)) {
+            // TODO: This might reject some valid devices. Ex: internal is 33 and a device named 3
+            //       is added.
+            if (internalDevices.find(de->d_name + 5) == std::string::npos) {
+                ALOGV("Non-internal v4l device %s found", de->d_name);
+                char v4l2DevicePath[kMaxDevicePathLen];
+                snprintf(v4l2DevicePath, kMaxDevicePathLen,
+                        "%s%s", kDevicePath, de->d_name);
+                mParent->deviceAdded(v4l2DevicePath);
+            }
+        }
+    }
+    closedir(devdir);
+
+    // Watch new video devices
+    mINotifyFD = inotify_init();
+    if (mINotifyFD < 0) {
+        ALOGE("%s: inotify init failed! Exiting threadloop", __FUNCTION__);
+        return true;
+    }
+
+    mWd = inotify_add_watch(mINotifyFD, kDevicePath, IN_CREATE | IN_DELETE);
+    if (mWd < 0) {
+        ALOGE("%s: inotify add watch failed! Exiting threadloop", __FUNCTION__);
+        return true;
+    }
+
+    ALOGI("%s start monitoring new V4L2 devices", __FUNCTION__);
+
+    bool done = false;
+    char eventBuf[512];
+    while (!done) {
+        int offset = 0;
+        int ret = read(mINotifyFD, eventBuf, sizeof(eventBuf));
+        if (ret >= (int)sizeof(struct inotify_event)) {
+            while (offset < ret) {
+                struct inotify_event* event = (struct inotify_event*)&eventBuf[offset];
+                if (event->wd == mWd) {
+                    if (!strncmp("video", event->name, 5)) {
+                        char v4l2DevicePath[kMaxDevicePathLen];
+                        snprintf(v4l2DevicePath, kMaxDevicePathLen,
+                                "%s%s", kDevicePath, event->name);
+                        if (event->mask & IN_CREATE) {
+                            mParent->deviceAdded(v4l2DevicePath);
+                        }
+                        if (event->mask & IN_DELETE) {
+                            mParent->deviceRemoved(v4l2DevicePath);
+                        }
+                    }
+                }
+                offset += sizeof(struct inotify_event) + event->len;
+            }
+        }
+    }
+
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V2_4
+}  // namespace provider
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/provider/2.4/default/ExternalCameraProvider.h b/camera/provider/2.4/default/ExternalCameraProvider.h
new file mode 100644
index 0000000..c7ed99e
--- /dev/null
+++ b/camera/provider/2.4/default/ExternalCameraProvider.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2018 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_CAMERA_PROVIDER_V2_4_EXTCAMERAPROVIDER_H
+#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_EXTCAMERAPROVIDER_H
+
+#include <unordered_map>
+#include "utils/Mutex.h"
+#include "utils/Thread.h"
+#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace provider {
+namespace V2_4 {
+namespace implementation {
+
+using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::VendorTagSection;
+using ::android::hardware::camera::provider::V2_4::ICameraProvider;
+using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using ::android::Mutex;
+
+struct ExternalCameraProvider : public ICameraProvider {
+    ExternalCameraProvider();
+    ~ExternalCameraProvider();
+
+    // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow.
+    Return<Status> setCallback(const sp<ICameraProviderCallback>& callback) override;
+
+    Return<void> getVendorTags(getVendorTags_cb _hidl_cb) override;
+
+    Return<void> getCameraIdList(getCameraIdList_cb _hidl_cb) override;
+
+    Return<void> isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) override;
+
+    Return<void> getCameraDeviceInterface_V1_x(
+            const hidl_string&,
+            getCameraDeviceInterface_V1_x_cb) override;
+    Return<void> getCameraDeviceInterface_V3_x(
+            const hidl_string&,
+            getCameraDeviceInterface_V3_x_cb) override;
+
+private:
+
+    void addExternalCamera(const char* devName);
+
+    void deviceAdded(const char* devName);
+
+    void deviceRemoved(const char* devName);
+
+    class HotplugThread : public android::Thread {
+    public:
+        HotplugThread(ExternalCameraProvider* parent);
+        ~HotplugThread();
+
+        virtual bool threadLoop() override;
+
+    private:
+        ExternalCameraProvider* mParent = nullptr;
+
+        int mINotifyFD = -1;
+        int mWd = -1;
+    } mHotPlugThread;
+
+    Mutex mLock;
+    sp<ICameraProviderCallback> mCallbacks = nullptr;
+    std::unordered_map<std::string, CameraDeviceStatus> mCameraStatusMap; // camera id -> status
+};
+
+
+
+}  // namespace implementation
+}  // namespace V2_4
+}  // namespace provider
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_EXTCAMERAPROVIDER_H
diff --git a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-external-service.rc b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-external-service.rc
new file mode 100644
index 0000000..acdb200
--- /dev/null
+++ b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-external-service.rc
@@ -0,0 +1,7 @@
+service vendor.camera-provider-2-4-ext /vendor/bin/hw/android.hardware.camera.provider@2.4-external-service
+    class hal
+    user cameraserver
+    group audio camera input drmrpc usb
+    ioprio rt 4
+    capabilities SYS_NICE
+    writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
diff --git a/camera/provider/2.4/default/external-service.cpp b/camera/provider/2.4/default/external-service.cpp
new file mode 100644
index 0000000..f91aa59
--- /dev/null
+++ b/camera/provider/2.4/default/external-service.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2018 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 "android.hardware.camera.provider@2.4-external-service"
+
+#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
+#include <hidl/LegacySupport.h>
+
+#include <binder/ProcessState.h>
+
+using android::hardware::camera::provider::V2_4::ICameraProvider;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main()
+{
+    ALOGI("External camera provider service is starting.");
+    // The camera HAL may communicate to other vendor components via
+    // /dev/vndbinder
+    android::ProcessState::initWithDriver("/dev/vndbinder");
+    return defaultPassthroughServiceImplementation<ICameraProvider>("external/0", /*maxThreads*/ 6);
+}
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index d44a54a..4652efd 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2016-2018 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.
@@ -47,6 +47,7 @@
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
 
+using namespace ::android::hardware::camera::device;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hardware::hidl_handle;
@@ -78,7 +79,6 @@
 using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
 using ::android::hardware::camera::device::V3_2::NotifyMsg;
 using ::android::hardware::camera::device::V3_2::RequestTemplate;
-using ::android::hardware::camera::device::V3_2::Stream;
 using ::android::hardware::camera::device::V3_2::StreamType;
 using ::android::hardware::camera::device::V3_2::StreamRotation;
 using ::android::hardware::camera::device::V3_2::StreamConfiguration;
@@ -537,6 +537,8 @@
         Return<void> notify(const hidl_vec<NotifyMsg>& msgs) override;
 
      private:
+        bool processCaptureResultLocked(const CaptureResult& results);
+
         CameraHidlTest *mParent;               // Parent object
     };
 
@@ -620,11 +622,16 @@
     void castSession(const sp<ICameraDeviceSession> &session, int32_t deviceVersion,
             sp<device::V3_3::ICameraDeviceSession> *session3_3 /*out*/,
             sp<device::V3_4::ICameraDeviceSession> *session3_4 /*out*/);
+    void createStreamConfiguration(const ::android::hardware::hidl_vec<V3_2::Stream>& streams3_2,
+            StreamConfigurationMode configMode,
+            ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2,
+            ::android::hardware::camera::device::V3_4::StreamConfiguration *config3_4);
+
     void configurePreviewStream(const std::string &name, int32_t deviceVersion,
             sp<ICameraProvider> provider,
             const AvailableStream *previewThreshold,
             sp<ICameraDeviceSession> *session /*out*/,
-            Stream *previewStream /*out*/,
+            V3_2::Stream *previewStream /*out*/,
             HalStreamConfiguration *halStreamConfig /*out*/,
             bool *supportsPartialResults /*out*/,
             uint32_t *partialResultCount /*out*/);
@@ -632,6 +639,9 @@
             std::vector<AvailableStream> &outputStreams,
             const AvailableStream *threshold = nullptr);
     static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
+    static Status isLogicalMultiCamera(camera_metadata_t *staticMeta);
+    static Status getPhysicalCameraIds(camera_metadata_t *staticMeta,
+            std::vector<std::string> *physicalIds/*out*/);
     static Status pickConstrainedModeSize(camera_metadata_t *staticMeta,
             AvailableStream &hfrStream);
     static Status isZSLModeAvailable(camera_metadata_t *staticMeta);
@@ -843,121 +853,7 @@
     bool notify = false;
     std::unique_lock<std::mutex> l(mParent->mLock);
     for (size_t i = 0 ; i < results.size(); i++) {
-        uint32_t frameNumber = results[i].frameNumber;
-
-        if ((results[i].result.size() == 0) &&
-                (results[i].outputBuffers.size() == 0) &&
-                (results[i].inputBuffer.buffer == nullptr) &&
-                (results[i].fmqResultSize == 0)) {
-            ALOGE("%s: No result data provided by HAL for frame %d result count: %d",
-                  __func__, frameNumber, (int) results[i].fmqResultSize);
-            ADD_FAILURE();
-            break;
-        }
-
-        ssize_t idx = mParent->mInflightMap.indexOfKey(frameNumber);
-        if (::android::NAME_NOT_FOUND == idx) {
-            ALOGE("%s: Unexpected frame number! received: %u",
-                  __func__, frameNumber);
-            ADD_FAILURE();
-            break;
-        }
-
-        bool isPartialResult = false;
-        bool hasInputBufferInRequest = false;
-        InFlightRequest *request = mParent->mInflightMap.editValueAt(idx);
-        ::android::hardware::camera::device::V3_2::CameraMetadata resultMetadata;
-        size_t resultSize = 0;
-        if (results[i].fmqResultSize > 0) {
-            resultMetadata.resize(results[i].fmqResultSize);
-            if (request->resultQueue == nullptr) {
-                ADD_FAILURE();
-                break;
-            }
-            if (!request->resultQueue->read(resultMetadata.data(),
-                    results[i].fmqResultSize)) {
-                ALOGE("%s: Frame %d: Cannot read camera metadata from fmq,"
-                        "size = %" PRIu64, __func__, frameNumber,
-                        results[i].fmqResultSize);
-                ADD_FAILURE();
-                break;
-            }
-            resultSize = resultMetadata.size();
-        } else if (results[i].result.size() > 0) {
-            resultMetadata.setToExternal(const_cast<uint8_t *>(
-                    results[i].result.data()), results[i].result.size());
-            resultSize = resultMetadata.size();
-        }
-
-        if (!request->usePartialResult && (resultSize > 0) &&
-                (results[i].partialResult != 1)) {
-            ALOGE("%s: Result is malformed for frame %d: partial_result %u "
-                    "must be 1  if partial result is not supported", __func__,
-                    frameNumber, results[i].partialResult);
-            ADD_FAILURE();
-            break;
-        }
-
-        if (results[i].partialResult != 0) {
-            request->partialResultCount = results[i].partialResult;
-        }
-
-        // Check if this result carries only partial metadata
-        if (request->usePartialResult && (resultSize > 0)) {
-            if ((results[i].partialResult > request->numPartialResults) ||
-                    (results[i].partialResult < 1)) {
-                ALOGE("%s: Result is malformed for frame %d: partial_result %u"
-                        " must be  in the range of [1, %d] when metadata is "
-                        "included in the result", __func__, frameNumber,
-                        results[i].partialResult, request->numPartialResults);
-                ADD_FAILURE();
-                break;
-            }
-            request->collectedResult.append(
-                    reinterpret_cast<const camera_metadata_t*>(
-                            resultMetadata.data()));
-
-            isPartialResult =
-                    (results[i].partialResult < request->numPartialResults);
-        }
-
-        hasInputBufferInRequest = request->hasInputBuffer;
-
-        // Did we get the (final) result metadata for this capture?
-        if ((resultSize > 0) && !isPartialResult) {
-            if (request->haveResultMetadata) {
-                ALOGE("%s: Called multiple times with metadata for frame %d",
-                      __func__, frameNumber);
-                ADD_FAILURE();
-                break;
-            }
-            request->haveResultMetadata = true;
-            request->collectedResult.sort();
-        }
-
-        uint32_t numBuffersReturned = results[i].outputBuffers.size();
-        if (results[i].inputBuffer.buffer != nullptr) {
-            if (hasInputBufferInRequest) {
-                numBuffersReturned += 1;
-            } else {
-                ALOGW("%s: Input buffer should be NULL if there is no input"
-                        " buffer sent in the request", __func__);
-            }
-        }
-        request->numBuffersLeft -= numBuffersReturned;
-        if (request->numBuffersLeft < 0) {
-            ALOGE("%s: Too many buffers returned for frame %d", __func__,
-                    frameNumber);
-            ADD_FAILURE();
-            break;
-        }
-
-        request->resultOutputBuffers.appendArray(results[i].outputBuffers.data(),
-                results[i].outputBuffers.size());
-        // If shutter event is received notify the pending threads.
-        if (request->shutterTimestamp != 0) {
-            notify = true;
-        }
+        notify = processCaptureResultLocked(results[i]);
     }
 
     l.unlock();
@@ -968,6 +864,126 @@
     return Void();
 }
 
+bool CameraHidlTest::DeviceCb::processCaptureResultLocked(const CaptureResult& results) {
+    bool notify = false;
+    uint32_t frameNumber = results.frameNumber;
+
+    if ((results.result.size() == 0) &&
+            (results.outputBuffers.size() == 0) &&
+            (results.inputBuffer.buffer == nullptr) &&
+            (results.fmqResultSize == 0)) {
+        ALOGE("%s: No result data provided by HAL for frame %d result count: %d",
+                __func__, frameNumber, (int) results.fmqResultSize);
+        ADD_FAILURE();
+        return notify;
+    }
+
+    ssize_t idx = mParent->mInflightMap.indexOfKey(frameNumber);
+    if (::android::NAME_NOT_FOUND == idx) {
+        ALOGE("%s: Unexpected frame number! received: %u",
+                __func__, frameNumber);
+        ADD_FAILURE();
+        return notify;
+    }
+
+    bool isPartialResult = false;
+    bool hasInputBufferInRequest = false;
+    InFlightRequest *request = mParent->mInflightMap.editValueAt(idx);
+    ::android::hardware::camera::device::V3_2::CameraMetadata resultMetadata;
+    size_t resultSize = 0;
+    if (results.fmqResultSize > 0) {
+        resultMetadata.resize(results.fmqResultSize);
+        if (request->resultQueue == nullptr) {
+            ADD_FAILURE();
+            return notify;
+        }
+        if (!request->resultQueue->read(resultMetadata.data(),
+                    results.fmqResultSize)) {
+            ALOGE("%s: Frame %d: Cannot read camera metadata from fmq,"
+                    "size = %" PRIu64, __func__, frameNumber,
+                    results.fmqResultSize);
+            ADD_FAILURE();
+            return notify;
+        }
+        resultSize = resultMetadata.size();
+    } else if (results.result.size() > 0) {
+        resultMetadata.setToExternal(const_cast<uint8_t *>(
+                    results.result.data()), results.result.size());
+        resultSize = resultMetadata.size();
+    }
+
+    if (!request->usePartialResult && (resultSize > 0) &&
+            (results.partialResult != 1)) {
+        ALOGE("%s: Result is malformed for frame %d: partial_result %u "
+                "must be 1  if partial result is not supported", __func__,
+                frameNumber, results.partialResult);
+        ADD_FAILURE();
+        return notify;
+    }
+
+    if (results.partialResult != 0) {
+        request->partialResultCount = results.partialResult;
+    }
+
+    // Check if this result carries only partial metadata
+    if (request->usePartialResult && (resultSize > 0)) {
+        if ((results.partialResult > request->numPartialResults) ||
+                (results.partialResult < 1)) {
+            ALOGE("%s: Result is malformed for frame %d: partial_result %u"
+                    " must be  in the range of [1, %d] when metadata is "
+                    "included in the result", __func__, frameNumber,
+                    results.partialResult, request->numPartialResults);
+            ADD_FAILURE();
+            return notify;
+        }
+        request->collectedResult.append(
+                reinterpret_cast<const camera_metadata_t*>(
+                    resultMetadata.data()));
+
+        isPartialResult =
+            (results.partialResult < request->numPartialResults);
+    }
+
+    hasInputBufferInRequest = request->hasInputBuffer;
+
+    // Did we get the (final) result metadata for this capture?
+    if ((resultSize > 0) && !isPartialResult) {
+        if (request->haveResultMetadata) {
+            ALOGE("%s: Called multiple times with metadata for frame %d",
+                    __func__, frameNumber);
+            ADD_FAILURE();
+            return notify;
+        }
+        request->haveResultMetadata = true;
+        request->collectedResult.sort();
+    }
+
+    uint32_t numBuffersReturned = results.outputBuffers.size();
+    if (results.inputBuffer.buffer != nullptr) {
+        if (hasInputBufferInRequest) {
+            numBuffersReturned += 1;
+        } else {
+            ALOGW("%s: Input buffer should be NULL if there is no input"
+                    " buffer sent in the request", __func__);
+        }
+    }
+    request->numBuffersLeft -= numBuffersReturned;
+    if (request->numBuffersLeft < 0) {
+        ALOGE("%s: Too many buffers returned for frame %d", __func__,
+                frameNumber);
+        ADD_FAILURE();
+        return notify;
+    }
+
+    request->resultOutputBuffers.appendArray(results.outputBuffers.data(),
+            results.outputBuffers.size());
+    // If shutter event is received notify the pending threads.
+    if (request->shutterTimestamp != 0) {
+        notify = true;
+    }
+    return notify;
+}
+
 Return<void> CameraHidlTest::DeviceCb::notify(
         const hidl_vec<NotifyMsg>& messages) {
     std::lock_guard<std::mutex> l(mParent->mLock);
@@ -2353,7 +2369,8 @@
 
         int32_t streamId = 0;
         for (auto& it : outputStreams) {
-            Stream stream = {streamId,
+            V3_2::Stream stream3_2;
+            stream3_2 = {streamId,
                              StreamType::OUTPUT,
                              static_cast<uint32_t>(it.width),
                              static_cast<uint32_t>(it.height),
@@ -2361,25 +2378,27 @@
                              GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
                              0,
                              StreamRotation::ROTATION_0};
-            ::android::hardware::hidl_vec<Stream> streams = {stream};
-            ::android::hardware::camera::device::V3_4::StreamConfiguration config;
-            config.v3_2 = {streams, StreamConfigurationMode::NORMAL_MODE};
+            ::android::hardware::hidl_vec<V3_2::Stream> streams3_2 = {stream3_2};
+            ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+            ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+            createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE,
+                                      &config3_2, &config3_4);
             if (session3_4 != nullptr) {
-                ret = session3_4->configureStreams_3_4(config,
-                        [streamId](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                ret = session3_4->configureStreams_3_4(config3_4,
+                        [streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) {
                             ASSERT_EQ(Status::OK, s);
                             ASSERT_EQ(1u, halConfig.streams.size());
-                            ASSERT_EQ(halConfig.streams[0].v3_2.id, streamId);
+                            ASSERT_EQ(halConfig.streams[0].v3_3.v3_2.id, streamId);
                         });
             } else if (session3_3 != nullptr) {
-                ret = session3_3->configureStreams_3_3(config.v3_2,
+                ret = session3_3->configureStreams_3_3(config3_2,
                         [streamId](Status s, device::V3_3::HalStreamConfiguration halConfig) {
                             ASSERT_EQ(Status::OK, s);
                             ASSERT_EQ(1u, halConfig.streams.size());
                             ASSERT_EQ(halConfig.streams[0].v3_2.id, streamId);
                         });
             } else {
-                ret = session->configureStreams(config.v3_2,
+                ret = session->configureStreams(config3_2,
                         [streamId](Status s, HalStreamConfiguration halConfig) {
                             ASSERT_EQ(Status::OK, s);
                             ASSERT_EQ(1u, halConfig.streams.size());
@@ -2424,7 +2443,7 @@
         ASSERT_NE(0u, outputStreams.size());
 
         int32_t streamId = 0;
-        Stream stream = {streamId++,
+        V3_2::Stream stream3_2 = {streamId++,
                          StreamType::OUTPUT,
                          static_cast<uint32_t>(0),
                          static_cast<uint32_t>(0),
@@ -2432,23 +2451,25 @@
                          GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
                          0,
                          StreamRotation::ROTATION_0};
-        ::android::hardware::hidl_vec<Stream> streams = {stream};
-        ::android::hardware::camera::device::V3_4::StreamConfiguration config;
-        config.v3_2 = {streams, StreamConfigurationMode::NORMAL_MODE};
+        ::android::hardware::hidl_vec<V3_2::Stream> streams = {stream3_2};
+        ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+        ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+        createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
+                                  &config3_2, &config3_4);
         if(session3_4 != nullptr) {
-            ret = session3_4->configureStreams_3_4(config,
-                [](Status s, device::V3_3::HalStreamConfiguration) {
+            ret = session3_4->configureStreams_3_4(config3_4,
+                [](Status s, device::V3_4::HalStreamConfiguration) {
                     ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
                             (Status::INTERNAL_ERROR == s));
                 });
         } else if(session3_3 != nullptr) {
-            ret = session3_3->configureStreams_3_3(config.v3_2,
+            ret = session3_3->configureStreams_3_3(config3_2,
                 [](Status s, device::V3_3::HalStreamConfiguration) {
                     ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
                             (Status::INTERNAL_ERROR == s));
                 });
         } else {
-            ret = session->configureStreams(config.v3_2,
+            ret = session->configureStreams(config3_2,
                 [](Status s, HalStreamConfiguration) {
                     ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
                             (Status::INTERNAL_ERROR == s));
@@ -2456,7 +2477,7 @@
         }
         ASSERT_TRUE(ret.isOk());
 
-        stream = {streamId++,
+        stream3_2 = {streamId++,
                   StreamType::OUTPUT,
                   static_cast<uint32_t>(UINT32_MAX),
                   static_cast<uint32_t>(UINT32_MAX),
@@ -2464,20 +2485,21 @@
                   GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
                   0,
                   StreamRotation::ROTATION_0};
-        streams[0] = stream;
-        config.v3_2 = {streams, StreamConfigurationMode::NORMAL_MODE};
+        streams[0] = stream3_2;
+        createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
+                &config3_2, &config3_4);
         if(session3_4 != nullptr) {
-            ret = session3_4->configureStreams_3_4(config, [](Status s,
-                        device::V3_3::HalStreamConfiguration) {
+            ret = session3_4->configureStreams_3_4(config3_4, [](Status s,
+                        device::V3_4::HalStreamConfiguration) {
                     ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                 });
         } else if(session3_3 != nullptr) {
-            ret = session3_3->configureStreams_3_3(config.v3_2, [](Status s,
+            ret = session3_3->configureStreams_3_3(config3_2, [](Status s,
                         device::V3_3::HalStreamConfiguration) {
                     ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                 });
         } else {
-            ret = session->configureStreams(config.v3_2, [](Status s,
+            ret = session->configureStreams(config3_2, [](Status s,
                         HalStreamConfiguration) {
                     ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                 });
@@ -2485,7 +2507,7 @@
         ASSERT_TRUE(ret.isOk());
 
         for (auto& it : outputStreams) {
-            stream = {streamId++,
+            stream3_2 = {streamId++,
                       StreamType::OUTPUT,
                       static_cast<uint32_t>(it.width),
                       static_cast<uint32_t>(it.height),
@@ -2493,27 +2515,28 @@
                       GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
                       0,
                       StreamRotation::ROTATION_0};
-            streams[0] = stream;
-            config.v3_2 = {streams, StreamConfigurationMode::NORMAL_MODE};
+            streams[0] = stream3_2;
+            createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
+                    &config3_2, &config3_4);
             if(session3_4 != nullptr) {
-                ret = session3_4->configureStreams_3_4(config,
-                        [](Status s, device::V3_3::HalStreamConfiguration) {
+                ret = session3_4->configureStreams_3_4(config3_4,
+                        [](Status s, device::V3_4::HalStreamConfiguration) {
                             ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                         });
             } else if(session3_3 != nullptr) {
-                ret = session3_3->configureStreams_3_3(config.v3_2,
+                ret = session3_3->configureStreams_3_3(config3_2,
                         [](Status s, device::V3_3::HalStreamConfiguration) {
                             ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                         });
             } else {
-                ret = session->configureStreams(config.v3_2,
+                ret = session->configureStreams(config3_2,
                         [](Status s, HalStreamConfiguration) {
                             ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                         });
             }
             ASSERT_TRUE(ret.isOk());
 
-            stream = {streamId++,
+            stream3_2 = {streamId++,
                       StreamType::OUTPUT,
                       static_cast<uint32_t>(it.width),
                       static_cast<uint32_t>(it.height),
@@ -2521,20 +2544,21 @@
                       GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
                       0,
                       static_cast<StreamRotation>(UINT32_MAX)};
-            streams[0] = stream;
-            config.v3_2 = {streams, StreamConfigurationMode::NORMAL_MODE};
+            streams[0] = stream3_2;
+            createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
+                    &config3_2, &config3_4);
             if(session3_4 != nullptr) {
-                ret = session3_4->configureStreams_3_4(config,
-                        [](Status s, device::V3_3::HalStreamConfiguration) {
+                ret = session3_4->configureStreams_3_4(config3_4,
+                        [](Status s, device::V3_4::HalStreamConfiguration) {
                             ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                         });
             } else if(session3_3 != nullptr) {
-                ret = session3_3->configureStreams_3_3(config.v3_2,
+                ret = session3_3->configureStreams_3_3(config3_2,
                         [](Status s, device::V3_3::HalStreamConfiguration) {
                             ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                         });
             } else {
-                ret = session->configureStreams(config.v3_2,
+                ret = session->configureStreams(config3_2,
                         [](Status s, HalStreamConfiguration) {
                             ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                         });
@@ -2603,7 +2627,7 @@
                       getAvailableOutputStreams(staticMeta, outputStreams,
                               &outputThreshold));
             for (auto& outputIter : outputStreams) {
-                Stream zslStream = {streamId++,
+                V3_2::Stream zslStream = {streamId++,
                                     StreamType::OUTPUT,
                                     static_cast<uint32_t>(input.width),
                                     static_cast<uint32_t>(input.height),
@@ -2611,7 +2635,7 @@
                                     GRALLOC_USAGE_HW_CAMERA_ZSL,
                                     0,
                                     StreamRotation::ROTATION_0};
-                Stream inputStream = {streamId++,
+                V3_2::Stream inputStream = {streamId++,
                                       StreamType::INPUT,
                                       static_cast<uint32_t>(input.width),
                                       static_cast<uint32_t>(input.height),
@@ -2619,7 +2643,7 @@
                                       0,
                                       0,
                                       StreamRotation::ROTATION_0};
-                Stream outputStream = {streamId++,
+                V3_2::Stream outputStream = {streamId++,
                                        StreamType::OUTPUT,
                                        static_cast<uint32_t>(outputIter.width),
                                        static_cast<uint32_t>(outputIter.height),
@@ -2628,24 +2652,26 @@
                                        0,
                                        StreamRotation::ROTATION_0};
 
-                ::android::hardware::hidl_vec<Stream> streams = {inputStream, zslStream,
+                ::android::hardware::hidl_vec<V3_2::Stream> streams = {inputStream, zslStream,
                                                                  outputStream};
-                ::android::hardware::camera::device::V3_4::StreamConfiguration config;
-                config.v3_2 = {streams, StreamConfigurationMode::NORMAL_MODE};
+                ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+                ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+                createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
+                                          &config3_2, &config3_4);
                 if (session3_4 != nullptr) {
-                    ret = session3_4->configureStreams_3_4(config,
-                            [](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                    ret = session3_4->configureStreams_3_4(config3_4,
+                            [](Status s, device::V3_4::HalStreamConfiguration halConfig) {
                                 ASSERT_EQ(Status::OK, s);
                                 ASSERT_EQ(3u, halConfig.streams.size());
                             });
                 } else if (session3_3 != nullptr) {
-                    ret = session3_3->configureStreams_3_3(config.v3_2,
+                    ret = session3_3->configureStreams_3_3(config3_2,
                             [](Status s, device::V3_3::HalStreamConfiguration halConfig) {
                                 ASSERT_EQ(Status::OK, s);
                                 ASSERT_EQ(3u, halConfig.streams.size());
                             });
                 } else {
-                    ret = session->configureStreams(config.v3_2,
+                    ret = session->configureStreams(config3_2,
                             [](Status s, HalStreamConfiguration halConfig) {
                                 ASSERT_EQ(Status::OK, s);
                                 ASSERT_EQ(3u, halConfig.streams.size());
@@ -2733,7 +2759,8 @@
                 &previewThreshold));
         ASSERT_NE(0u, outputPreviewStreams.size());
 
-        Stream previewStream = {0,
+        V3_4::Stream previewStream;
+        previewStream.v3_2 = {0,
                                 StreamType::OUTPUT,
                                 static_cast<uint32_t>(outputPreviewStreams[0].width),
                                 static_cast<uint32_t>(outputPreviewStreams[0].height),
@@ -2741,15 +2768,16 @@
                                 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
                                 0,
                                 StreamRotation::ROTATION_0};
-        ::android::hardware::hidl_vec<Stream> streams = {previewStream};
+        ::android::hardware::hidl_vec<V3_4::Stream> streams = {previewStream};
         ::android::hardware::camera::device::V3_4::StreamConfiguration config;
-        config.v3_2 = {streams, StreamConfigurationMode::NORMAL_MODE};
+        config.streams = streams;
+        config.operationMode = StreamConfigurationMode::NORMAL_MODE;
         const camera_metadata_t *sessionParamsBuffer = sessionParams.getAndLock();
         config.sessionParams.setToExternal(
                 reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (sessionParamsBuffer)),
                 get_camera_metadata_size(sessionParamsBuffer));
         ret = session3_4->configureStreams_3_4(config,
-                [](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                [](Status s, device::V3_4::HalStreamConfiguration halConfig) {
                     ASSERT_EQ(Status::OK, s);
                     ASSERT_EQ(1u, halConfig.streams.size());
                 });
@@ -2804,7 +2832,7 @@
         int32_t streamId = 0;
         for (auto& blobIter : outputBlobStreams) {
             for (auto& previewIter : outputPreviewStreams) {
-                Stream previewStream = {streamId++,
+                V3_2::Stream previewStream = {streamId++,
                                         StreamType::OUTPUT,
                                         static_cast<uint32_t>(previewIter.width),
                                         static_cast<uint32_t>(previewIter.height),
@@ -2812,7 +2840,7 @@
                                         GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
                                         0,
                                         StreamRotation::ROTATION_0};
-                Stream blobStream = {streamId++,
+                V3_2::Stream blobStream = {streamId++,
                                      StreamType::OUTPUT,
                                      static_cast<uint32_t>(blobIter.width),
                                      static_cast<uint32_t>(blobIter.height),
@@ -2820,24 +2848,26 @@
                                      GRALLOC1_CONSUMER_USAGE_CPU_READ,
                                      0,
                                      StreamRotation::ROTATION_0};
-                ::android::hardware::hidl_vec<Stream> streams = {previewStream,
+                ::android::hardware::hidl_vec<V3_2::Stream> streams = {previewStream,
                                                                  blobStream};
-                ::android::hardware::camera::device::V3_4::StreamConfiguration config;
-                config.v3_2 = {streams, StreamConfigurationMode::NORMAL_MODE};
+                ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+                ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+                createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
+                                          &config3_2, &config3_4);
                 if (session3_4 != nullptr) {
-                    ret = session3_4->configureStreams_3_4(config,
-                            [](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                    ret = session3_4->configureStreams_3_4(config3_4,
+                            [](Status s, device::V3_4::HalStreamConfiguration halConfig) {
                                 ASSERT_EQ(Status::OK, s);
                                 ASSERT_EQ(2u, halConfig.streams.size());
                             });
                 } else if (session3_3 != nullptr) {
-                    ret = session3_3->configureStreams_3_3(config.v3_2,
+                    ret = session3_3->configureStreams_3_3(config3_2,
                             [](Status s, device::V3_3::HalStreamConfiguration halConfig) {
                                 ASSERT_EQ(Status::OK, s);
                                 ASSERT_EQ(2u, halConfig.streams.size());
                             });
                 } else {
-                    ret = session->configureStreams(config.v3_2,
+                    ret = session->configureStreams(config3_2,
                             [](Status s, HalStreamConfiguration halConfig) {
                                 ASSERT_EQ(Status::OK, s);
                                 ASSERT_EQ(2u, halConfig.streams.size());
@@ -2890,7 +2920,7 @@
         ASSERT_EQ(Status::OK, rc);
 
         int32_t streamId = 0;
-        Stream stream = {streamId,
+        V3_2::Stream stream = {streamId,
                          StreamType::OUTPUT,
                          static_cast<uint32_t>(hfrStream.width),
                          static_cast<uint32_t>(hfrStream.height),
@@ -2898,25 +2928,27 @@
                          GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
                          0,
                          StreamRotation::ROTATION_0};
-        ::android::hardware::hidl_vec<Stream> streams = {stream};
-        ::android::hardware::camera::device::V3_4::StreamConfiguration config;
-        config.v3_2 = {streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+        ::android::hardware::hidl_vec<V3_2::Stream> streams = {stream};
+        ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+        ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+        createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
+                                  &config3_2, &config3_4);
         if (session3_4 != nullptr) {
-            ret = session3_4->configureStreams_3_4(config,
-                    [streamId](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+            ret = session3_4->configureStreams_3_4(config3_4,
+                    [streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) {
                         ASSERT_EQ(Status::OK, s);
                         ASSERT_EQ(1u, halConfig.streams.size());
-                        ASSERT_EQ(halConfig.streams[0].v3_2.id, streamId);
+                        ASSERT_EQ(halConfig.streams[0].v3_3.v3_2.id, streamId);
                     });
         } else if (session3_3 != nullptr) {
-            ret = session3_3->configureStreams_3_3(config.v3_2,
+            ret = session3_3->configureStreams_3_3(config3_2,
                     [streamId](Status s, device::V3_3::HalStreamConfiguration halConfig) {
                         ASSERT_EQ(Status::OK, s);
                         ASSERT_EQ(1u, halConfig.streams.size());
                         ASSERT_EQ(halConfig.streams[0].v3_2.id, streamId);
                     });
         } else {
-            ret = session->configureStreams(config.v3_2,
+            ret = session->configureStreams(config3_2,
                     [streamId](Status s, HalStreamConfiguration halConfig) {
                         ASSERT_EQ(Status::OK, s);
                         ASSERT_EQ(1u, halConfig.streams.size());
@@ -2934,21 +2966,22 @@
                   0,
                   StreamRotation::ROTATION_0};
         streams[0] = stream;
-        config.v3_2 = {streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+        createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
+                                  &config3_2, &config3_4);
         if (session3_4 != nullptr) {
-            ret = session3_4->configureStreams_3_4(config,
-                    [](Status s, device::V3_3::HalStreamConfiguration) {
+            ret = session3_4->configureStreams_3_4(config3_4,
+                    [](Status s, device::V3_4::HalStreamConfiguration) {
                         ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
                                 (Status::INTERNAL_ERROR == s));
                     });
         } else if (session3_3 != nullptr) {
-            ret = session3_3->configureStreams_3_3(config.v3_2,
+            ret = session3_3->configureStreams_3_3(config3_2,
                     [](Status s, device::V3_3::HalStreamConfiguration) {
                         ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
                                 (Status::INTERNAL_ERROR == s));
                     });
         } else {
-            ret = session->configureStreams(config.v3_2,
+            ret = session->configureStreams(config3_2,
                     [](Status s, HalStreamConfiguration) {
                         ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
                                 (Status::INTERNAL_ERROR == s));
@@ -2965,19 +2998,20 @@
                   0,
                   StreamRotation::ROTATION_0};
         streams[0] = stream;
-        config.v3_2 = {streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+        createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
+                                  &config3_2, &config3_4);
         if (session3_4 != nullptr) {
-            ret = session3_4->configureStreams_3_4(config,
-                    [](Status s, device::V3_3::HalStreamConfiguration) {
+            ret = session3_4->configureStreams_3_4(config3_4,
+                    [](Status s, device::V3_4::HalStreamConfiguration) {
                         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                     });
         } else if (session3_3 != nullptr) {
-            ret = session3_3->configureStreams_3_3(config.v3_2,
+            ret = session3_3->configureStreams_3_3(config3_2,
                     [](Status s, device::V3_3::HalStreamConfiguration) {
                         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                     });
         } else {
-            ret = session->configureStreams(config.v3_2,
+            ret = session->configureStreams(config3_2,
                     [](Status s, HalStreamConfiguration) {
                         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                     });
@@ -2993,19 +3027,20 @@
                   0,
                   StreamRotation::ROTATION_0};
         streams[0] = stream;
-        config.v3_2 = {streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+        createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
+                                  &config3_2, &config3_4);
         if (session3_4 != nullptr) {
-            ret = session3_4->configureStreams_3_4(config,
-                    [](Status s, device::V3_3::HalStreamConfiguration) {
+            ret = session3_4->configureStreams_3_4(config3_4,
+                    [](Status s, device::V3_4::HalStreamConfiguration) {
                         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                     });
         } else if (session3_3 != nullptr) {
-            ret = session3_3->configureStreams_3_3(config.v3_2,
+            ret = session3_3->configureStreams_3_3(config3_2,
                     [](Status s, device::V3_3::HalStreamConfiguration) {
                         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                     });
         } else {
-            ret = session->configureStreams(config.v3_2,
+            ret = session->configureStreams(config3_2,
                     [](Status s, HalStreamConfiguration) {
                         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                     });
@@ -3062,7 +3097,7 @@
         int32_t streamId = 0;
         for (auto& blobIter : outputBlobStreams) {
             for (auto& videoIter : outputVideoStreams) {
-                Stream videoStream = {streamId++,
+                V3_2::Stream videoStream = {streamId++,
                                       StreamType::OUTPUT,
                                       static_cast<uint32_t>(videoIter.width),
                                       static_cast<uint32_t>(videoIter.height),
@@ -3070,7 +3105,7 @@
                                       GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
                                       0,
                                       StreamRotation::ROTATION_0};
-                Stream blobStream = {streamId++,
+                V3_2::Stream blobStream = {streamId++,
                                      StreamType::OUTPUT,
                                      static_cast<uint32_t>(blobIter.width),
                                      static_cast<uint32_t>(blobIter.height),
@@ -3078,23 +3113,25 @@
                                      GRALLOC1_CONSUMER_USAGE_CPU_READ,
                                      0,
                                      StreamRotation::ROTATION_0};
-                ::android::hardware::hidl_vec<Stream> streams = {videoStream, blobStream};
-                ::android::hardware::camera::device::V3_4::StreamConfiguration config;
-                config.v3_2 = {streams, StreamConfigurationMode::NORMAL_MODE};
+                ::android::hardware::hidl_vec<V3_2::Stream> streams = {videoStream, blobStream};
+                ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+                ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+                createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
+                                          &config3_2, &config3_4);
                 if (session3_4 != nullptr) {
-                    ret = session3_4->configureStreams_3_4(config,
-                            [](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                    ret = session3_4->configureStreams_3_4(config3_4,
+                            [](Status s, device::V3_4::HalStreamConfiguration halConfig) {
                                 ASSERT_EQ(Status::OK, s);
                                 ASSERT_EQ(2u, halConfig.streams.size());
                             });
                 } else if (session3_3 != nullptr) {
-                    ret = session3_3->configureStreams_3_3(config.v3_2,
+                    ret = session3_3->configureStreams_3_3(config3_2,
                             [](Status s, device::V3_3::HalStreamConfiguration halConfig) {
                                 ASSERT_EQ(Status::OK, s);
                                 ASSERT_EQ(2u, halConfig.streams.size());
                             });
                 } else {
-                    ret = session->configureStreams(config.v3_2,
+                    ret = session->configureStreams(config3_2,
                             [](Status s, HalStreamConfiguration halConfig) {
                                 ASSERT_EQ(Status::OK, s);
                                 ASSERT_EQ(2u, halConfig.streams.size());
@@ -3129,7 +3166,7 @@
             return;
         }
 
-        Stream previewStream;
+        V3_2::Stream previewStream;
         HalStreamConfiguration halStreamConfig;
         sp<ICameraDeviceSession> session;
         bool supportsPartialResults = false;
@@ -3263,6 +3300,171 @@
     }
 }
 
+// Generate and verify a multi-camera capture request
+TEST_F(CameraHidlTest, processMultiCaptureRequestPreview) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    uint64_t bufferId = 1;
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
+    ::android::hardware::hidl_vec<uint8_t> emptySettings;
+    hidl_string invalidPhysicalId = "-1";
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_4) {
+            continue;
+        }
+        camera_metadata_t* staticMeta;
+        Return<void> ret;
+        sp<ICameraDeviceSession> session;
+        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
+
+        Status rc = isLogicalMultiCamera(staticMeta);
+        if (Status::METHOD_NOT_SUPPORTED == rc) {
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
+            continue;
+        }
+        std::vector<std::string> physicalIds;
+        rc = getPhysicalCameraIds(staticMeta, &physicalIds);
+        ASSERT_TRUE(Status::OK == rc);
+        ASSERT_TRUE(physicalIds.size() > 1);
+
+        free_camera_metadata(staticMeta);
+        ret = session->close();
+        ASSERT_TRUE(ret.isOk());
+
+        V3_2::Stream previewStream;
+        HalStreamConfiguration halStreamConfig;
+        bool supportsPartialResults = false;
+        uint32_t partialResultCount = 0;
+        configurePreviewStream(name, deviceVersion, mProvider, &previewThreshold, &session /*out*/,
+                &previewStream /*out*/, &halStreamConfig /*out*/,
+                &supportsPartialResults /*out*/,
+                &partialResultCount /*out*/);
+        sp<device::V3_3::ICameraDeviceSession> session3_3;
+        sp<device::V3_4::ICameraDeviceSession> session3_4;
+        castSession(session, deviceVersion, &session3_3, &session3_4);
+        ASSERT_NE(session3_4, nullptr);
+
+        std::shared_ptr<ResultMetadataQueue> resultQueue;
+        auto resultQueueRet =
+            session->getCaptureResultMetadataQueue(
+                [&resultQueue](const auto& descriptor) {
+                    resultQueue = std::make_shared<ResultMetadataQueue>(
+                            descriptor);
+                    if (!resultQueue->isValid() ||
+                            resultQueue->availableToWrite() <= 0) {
+                        ALOGE("%s: HAL returns empty result metadata fmq,"
+                                " not use it", __func__);
+                        resultQueue = nullptr;
+                        // Don't use the queue onwards.
+                    }
+                });
+        ASSERT_TRUE(resultQueueRet.isOk());
+
+        InFlightRequest inflightReq = {1, false, supportsPartialResults,
+                                       partialResultCount, resultQueue};
+
+        RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
+        ret = session->constructDefaultRequestSettings(reqTemplate,
+                                                       [&](auto status, const auto& req) {
+                                                           ASSERT_EQ(Status::OK, status);
+                                                           settings = req;
+                                                       });
+        ASSERT_TRUE(ret.isOk());
+
+        sp<GraphicBuffer> gb = new GraphicBuffer(
+            previewStream.width, previewStream.height,
+            static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat), 1,
+            android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
+                                            halStreamConfig.streams[0].consumerUsage));
+        ASSERT_NE(nullptr, gb.get());
+        ::android::hardware::hidl_vec<StreamBuffer> outputBuffers;
+        outputBuffers.resize(1);
+        outputBuffers[0] = {halStreamConfig.streams[0].id,
+                                     bufferId,
+                                     hidl_handle(gb->getNativeBuffer()->handle),
+                                     BufferStatus::OK,
+                                     nullptr,
+                                     nullptr};
+
+        StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
+                                         nullptr};
+        hidl_vec<V3_4::PhysicalCameraSetting> camSettings;
+        camSettings.resize(2);
+        camSettings[0] = {0, hidl_string(physicalIds[0]), settings};
+        camSettings[1] = {0, hidl_string(physicalIds[1]), settings};
+        V3_4::CaptureRequest request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
+                                  emptyInputBuffer, outputBuffers}, camSettings};
+
+        {
+            std::unique_lock<std::mutex> l(mLock);
+            mInflightMap.clear();
+            mInflightMap.add(frameNumber, &inflightReq);
+        }
+
+        Status stat = Status::INTERNAL_ERROR;
+        uint32_t numRequestProcessed = 0;
+        hidl_vec<BufferCache> cachesToRemove;
+        Return<void> returnStatus = session3_4->processCaptureRequest_3_4(
+            {request}, cachesToRemove, [&stat, &numRequestProcessed](auto s, uint32_t n) {
+                stat = s;
+                numRequestProcessed = n;
+            });
+        ASSERT_TRUE(returnStatus.isOk());
+        ASSERT_EQ(Status::OK, stat);
+        ASSERT_EQ(numRequestProcessed, 1u);
+
+        {
+            std::unique_lock<std::mutex> l(mLock);
+            while (!inflightReq.errorCodeValid &&
+                   ((0 < inflightReq.numBuffersLeft) ||
+                           (!inflightReq.haveResultMetadata))) {
+                auto timeout = std::chrono::system_clock::now() +
+                               std::chrono::seconds(kStreamBufferTimeoutSec);
+                ASSERT_NE(std::cv_status::timeout,
+                        mResultCondition.wait_until(l, timeout));
+            }
+
+            ASSERT_FALSE(inflightReq.errorCodeValid);
+            ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
+            ASSERT_EQ(halStreamConfig.streams[0].id,
+                    inflightReq.resultOutputBuffers[0].streamId);
+        }
+
+        // Empty physical camera settings should fail process requests
+        camSettings[1] = {0, hidl_string(physicalIds[1]), emptySettings};
+        frameNumber++;
+        request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
+            emptyInputBuffer, outputBuffers}, camSettings};
+        returnStatus = session3_4->processCaptureRequest_3_4(
+            {request}, cachesToRemove, [&stat, &numRequestProcessed](auto s, uint32_t n) {
+                stat = s;
+                numRequestProcessed = n;
+            });
+        ASSERT_TRUE(returnStatus.isOk());
+        ASSERT_EQ(Status::ILLEGAL_ARGUMENT, stat);
+
+        // Invalid physical camera id should fail process requests
+        camSettings[1] = {0, invalidPhysicalId, settings};
+        request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
+            emptyInputBuffer, outputBuffers}, camSettings};
+        returnStatus = session3_4->processCaptureRequest_3_4(
+            {request}, cachesToRemove, [&stat, &numRequestProcessed](auto s, uint32_t n) {
+                stat = s;
+                numRequestProcessed = n;
+            });
+        ASSERT_TRUE(returnStatus.isOk());
+        ASSERT_EQ(Status::ILLEGAL_ARGUMENT, stat);
+
+        ret = session->close();
+        ASSERT_TRUE(ret.isOk());
+    }
+}
+
 // Test whether an incorrect capture request with missing settings will
 // be reported correctly.
 TEST_F(CameraHidlTest, processCaptureRequestInvalidSinglePreview) {
@@ -3284,7 +3486,7 @@
             return;
         }
 
-        Stream previewStream;
+        V3_2::Stream previewStream;
         HalStreamConfiguration halStreamConfig;
         sp<ICameraDeviceSession> session;
         bool supportsPartialResults = false;
@@ -3351,7 +3553,7 @@
             return;
         }
 
-        Stream previewStream;
+        V3_2::Stream previewStream;
         HalStreamConfiguration halStreamConfig;
         sp<ICameraDeviceSession> session;
         bool supportsPartialResults = false;
@@ -3415,7 +3617,7 @@
             return;
         }
 
-        Stream previewStream;
+        V3_2::Stream previewStream;
         HalStreamConfiguration halStreamConfig;
         sp<ICameraDeviceSession> session;
         bool supportsPartialResults = false;
@@ -3545,7 +3747,7 @@
             return;
         }
 
-        Stream previewStream;
+        V3_2::Stream previewStream;
         HalStreamConfiguration halStreamConfig;
         sp<ICameraDeviceSession> session;
         bool supportsPartialResults = false;
@@ -3610,6 +3812,59 @@
     return Status::OK;
 }
 
+// Check if the camera device has logical multi-camera capability.
+Status CameraHidlTest::isLogicalMultiCamera(camera_metadata_t *staticMeta) {
+    Status ret = Status::METHOD_NOT_SUPPORTED;
+    if (nullptr == staticMeta) {
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    camera_metadata_ro_entry entry;
+    int rc = find_camera_metadata_ro_entry(staticMeta,
+            ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
+    if (0 != rc) {
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    for (size_t i = 0; i < entry.count; i++) {
+        if (ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA == entry.data.u8[i]) {
+            ret = Status::OK;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+// Generate a list of physical camera ids backing a logical multi-camera.
+Status CameraHidlTest::getPhysicalCameraIds(camera_metadata_t *staticMeta,
+        std::vector<std::string> *physicalIds) {
+    if ((nullptr == staticMeta) || (nullptr == physicalIds)) {
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    camera_metadata_ro_entry entry;
+    int rc = find_camera_metadata_ro_entry(staticMeta, ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS,
+            &entry);
+    if (0 != rc) {
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    const uint8_t* ids = entry.data.u8;
+    size_t start = 0;
+    for (size_t i = 0; i < entry.count; i++) {
+        if (ids[i] == '\0') {
+            if (start != i) {
+                std::string currentId(reinterpret_cast<const char *> (ids + start));
+                physicalIds->push_back(currentId);
+            }
+            start = i + 1;
+        }
+    }
+
+    return Status::OK;
+}
+
 // Check if constrained mode is supported by using the static
 // camera characteristics.
 Status CameraHidlTest::isConstrainedModeAvailable(camera_metadata_t *staticMeta) {
@@ -3754,12 +4009,31 @@
     return Status::METHOD_NOT_SUPPORTED;
 }
 
+void CameraHidlTest::createStreamConfiguration(
+        const ::android::hardware::hidl_vec<V3_2::Stream>& streams3_2,
+        StreamConfigurationMode configMode,
+        ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2 /*out*/,
+        ::android::hardware::camera::device::V3_4::StreamConfiguration *config3_4 /*out*/) {
+    ASSERT_NE(nullptr, config3_2);
+    ASSERT_NE(nullptr, config3_4);
+
+    ::android::hardware::hidl_vec<V3_4::Stream> streams3_4(streams3_2.size());
+    size_t idx = 0;
+    for (auto& stream3_2 : streams3_2) {
+        V3_4::Stream stream;
+        stream.v3_2 = stream3_2;
+        streams3_4[idx++] = stream;
+    }
+    *config3_4 = {streams3_4, configMode, {}};
+    *config3_2 = {streams3_2, configMode};
+}
+
 // Open a device session and configure a preview stream.
 void CameraHidlTest::configurePreviewStream(const std::string &name, int32_t deviceVersion,
         sp<ICameraProvider> provider,
         const AvailableStream *previewThreshold,
         sp<ICameraDeviceSession> *session /*out*/,
-        Stream *previewStream /*out*/,
+        V3_2::Stream *previewStream /*out*/,
         HalStreamConfiguration *halStreamConfig /*out*/,
         bool *supportsPartialResults /*out*/,
         uint32_t *partialResultCount /*out*/) {
@@ -3824,26 +4098,35 @@
     ASSERT_EQ(Status::OK, rc);
     ASSERT_FALSE(outputPreviewStreams.empty());
 
-    *previewStream = {0, StreamType::OUTPUT,
+    V3_2::Stream stream3_2 = {0, StreamType::OUTPUT,
             static_cast<uint32_t> (outputPreviewStreams[0].width),
             static_cast<uint32_t> (outputPreviewStreams[0].height),
             static_cast<PixelFormat> (outputPreviewStreams[0].format),
             GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0, StreamRotation::ROTATION_0};
-    ::android::hardware::hidl_vec<Stream> streams = {*previewStream};
-    ::android::hardware::camera::device::V3_4::StreamConfiguration config;
-    config.v3_2 = {streams, StreamConfigurationMode::NORMAL_MODE};
+    ::android::hardware::hidl_vec<V3_2::Stream> streams3_2 = {stream3_2};
+    ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+    ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+    createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE,
+                              &config3_2, &config3_4);
     if (session3_4 != nullptr) {
-        ret = session3_4->configureStreams_3_4(config,
-                [&] (Status s, device::V3_3::HalStreamConfiguration halConfig) {
+        RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
+        ret = session3_4->constructDefaultRequestSettings(reqTemplate,
+                                                       [&config3_4](auto status, const auto& req) {
+                                                           ASSERT_EQ(Status::OK, status);
+                                                           config3_4.sessionParams = req;
+                                                       });
+        ASSERT_TRUE(ret.isOk());
+        ret = session3_4->configureStreams_3_4(config3_4,
+                [&] (Status s, device::V3_4::HalStreamConfiguration halConfig) {
                     ASSERT_EQ(Status::OK, s);
                     ASSERT_EQ(1u, halConfig.streams.size());
                     halStreamConfig->streams.resize(halConfig.streams.size());
                     for (size_t i = 0; i < halConfig.streams.size(); i++) {
-                        halStreamConfig->streams[i] = halConfig.streams[i].v3_2;
+                        halStreamConfig->streams[i] = halConfig.streams[i].v3_3.v3_2;
                     }
                 });
     } else if (session3_3 != nullptr) {
-        ret = session3_3->configureStreams_3_3(config.v3_2,
+        ret = session3_3->configureStreams_3_3(config3_2,
                 [&] (Status s, device::V3_3::HalStreamConfiguration halConfig) {
                     ASSERT_EQ(Status::OK, s);
                     ASSERT_EQ(1u, halConfig.streams.size());
@@ -3853,13 +4136,14 @@
                     }
                 });
     } else {
-        ret = (*session)->configureStreams(config.v3_2,
+        ret = (*session)->configureStreams(config3_2,
                 [&] (Status s, HalStreamConfiguration halConfig) {
                     ASSERT_EQ(Status::OK, s);
                     ASSERT_EQ(1u, halConfig.streams.size());
                     *halStreamConfig = halConfig;
                 });
     }
+    *previewStream = stream3_2;
     ASSERT_TRUE(ret.isOk());
 }
 
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
new file mode 100644
index 0000000..1c86f11
--- /dev/null
+++ b/compatibility_matrices/Android.mk
@@ -0,0 +1,93 @@
+#
+# Copyright (C) 2017 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_FRAMEWORK_COMPATIBILITY_MATRIX := $(LOCAL_PATH)/compatibility_matrix.mk
+
+# Clear potential input variables to BUILD_FRAMEWORK_COMPATIBILITY_MATRIX
+LOCAL_ADD_VBMETA_VERSION :=
+LOCAL_ASSEMBLE_VINTF_ENV_VARS :=
+LOCAL_ASSEMBLE_VINTF_FLAGS :=
+LOCAL_KERNEL_VERSIONS :=
+LOCAL_GEN_FILE_DEPENDENCIES :=
+
+# Install all compatibility_matrix.*.xml to /system/etc/vintf
+
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_STEM := compatibility_matrix.legacy.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_KERNEL_VERSIONS := 3.18.0 4.4.0 4.9.0
+include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_STEM := compatibility_matrix.1.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_KERNEL_VERSIONS := 3.18.0 4.4.0 4.9.0
+include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_STEM := compatibility_matrix.2.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_KERNEL_VERSIONS := 3.18.0 4.4.0 4.9.0
+include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+
+# TODO(b/72409164): STOPSHIP: update kernel version requirements
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_STEM := compatibility_matrix.current.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_KERNEL_VERSIONS := 4.4.0 4.9.0
+include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+
+# Framework Compatibility Matrix (common to all FCM versions)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_STEM := compatibility_matrix.empty.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_ADD_VBMETA_VERSION := true
+LOCAL_ASSEMBLE_VINTF_ENV_VARS := \
+	POLICYVERS \
+	BOARD_SEPOLICY_VERS
+
+include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+
+# Framework Compatibility Matrix
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := framework_compatibility_matrix.xml
+LOCAL_MODULE_STEM := compatibility_matrix.xml
+LOCAL_MODULE_PATH := $(TARGET_OUT)
+LOCAL_REQUIRED_MODULES := \
+    framework_compatibility_matrix.legacy.xml \
+    framework_compatibility_matrix.1.xml \
+    framework_compatibility_matrix.2.xml \
+    framework_compatibility_matrix.current.xml \
+    framework_compatibility_matrix.empty.xml
+LOCAL_GENERATED_SOURCES := $(call module-installed-files,$(LOCAL_REQUIRED_MODULES))
+
+ifdef BUILT_VENDOR_MANIFEST
+LOCAL_GEN_FILE_DEPENDENCIES += $(BUILT_VENDOR_MANIFEST)
+LOCAL_ASSEMBLE_VINTF_FLAGS += -c "$(BUILT_VENDOR_MANIFEST)"
+endif
+
+LOCAL_ASSEMBLE_VINTF_ENV_VARS := PRODUCT_ENFORCE_VINTF_MANIFEST
+
+include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+BUILT_SYSTEM_COMPATIBILITY_MATRIX := $(LOCAL_BUILT_MODULE)
+
+BUILD_FRAMEWORK_COMPATIBILITY_MATRIX :=
diff --git a/compatibility_matrix.1.xml b/compatibility_matrices/compatibility_matrix.1.xml
similarity index 100%
rename from compatibility_matrix.1.xml
rename to compatibility_matrices/compatibility_matrix.1.xml
diff --git a/compatibility_matrix.2.xml b/compatibility_matrices/compatibility_matrix.2.xml
similarity index 100%
rename from compatibility_matrix.2.xml
rename to compatibility_matrices/compatibility_matrix.2.xml
diff --git a/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
similarity index 97%
rename from compatibility_matrix.current.xml
rename to compatibility_matrices/compatibility_matrix.current.xml
index 9287d67..c444dde 100644
--- a/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -16,6 +16,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.authsecret</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAuthSecret</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.automotive.evs</name>
         <version>1.0</version>
         <interface>
@@ -221,7 +229,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.power</name>
-        <version>1.0-1</version>
+        <version>1.0-2</version>
         <interface>
             <name>IPower</name>
             <instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.empty.xml b/compatibility_matrices/compatibility_matrix.empty.xml
new file mode 100644
index 0000000..216f5f1
--- /dev/null
+++ b/compatibility_matrices/compatibility_matrix.empty.xml
@@ -0,0 +1 @@
+<compatibility-matrix version="1.0" type="framework" />
diff --git a/compatibility_matrix.legacy.xml b/compatibility_matrices/compatibility_matrix.legacy.xml
similarity index 100%
rename from compatibility_matrix.legacy.xml
rename to compatibility_matrices/compatibility_matrix.legacy.xml
diff --git a/compatibility_matrices/compatibility_matrix.mk b/compatibility_matrices/compatibility_matrix.mk
new file mode 100644
index 0000000..14c60ab
--- /dev/null
+++ b/compatibility_matrices/compatibility_matrix.mk
@@ -0,0 +1,100 @@
+#
+# Copyright (C) 2018 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.
+#
+
+###########################################################
+## Remove minor revision from a kernel version. For example,
+## 3.18.0 becomes 3.18.
+## $(1): kernel version
+###########################################################
+define remove-minor-revision
+$(strip $(subst $(space),.,$(wordlist 1,2,$(subst .,$(space),$(strip $(1))))))
+endef
+
+# $(warning $(call remove-minor-revision,3.18.0))
+
+ifndef LOCAL_MODULE_STEM
+$(error LOCAL_MODULE_STEM must be defined.)
+endif
+
+LOCAL_MODULE := framework_$(LOCAL_MODULE_STEM)
+LOCAL_MODULE_CLASS := ETC
+
+ifndef LOCAL_MODULE_PATH
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf
+endif
+
+GEN := $(local-generated-sources-dir)/$(LOCAL_MODULE_STEM)
+
+$(GEN): PRIVATE_ENV_VARS := $(LOCAL_ASSEMBLE_VINTF_ENV_VARS)
+$(GEN): PRIVATE_FLAGS := $(LOCAL_ASSEMBLE_VINTF_FLAGS)
+
+$(GEN): $(LOCAL_GEN_FILE_DEPENDENCIES)
+
+ifeq (true,$(strip $(LOCAL_ADD_VBMETA_VERSION)))
+ifeq (true,$(BOARD_AVB_ENABLE))
+$(GEN): $(AVBTOOL)
+# INTERNAL_AVB_SYSTEM_SIGNING_ARGS consists of BOARD_AVB_SYSTEM_KEY_PATH and
+# BOARD_AVB_SYSTEM_ALGORITHM. We should add the dependency of key path, which
+# is a file, here.
+$(GEN): $(BOARD_AVB_SYSTEM_KEY_PATH)
+# Use deferred assignment (=) instead of immediate assignment (:=).
+# Otherwise, cannot get INTERNAL_AVB_SYSTEM_SIGNING_ARGS.
+$(GEN): FRAMEWORK_VBMETA_VERSION = $$("$(AVBTOOL)" add_hashtree_footer \
+                           --print_required_libavb_version \
+                           $(INTERNAL_AVB_SYSTEM_SIGNING_ARGS) \
+                           $(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS))
+else
+$(GEN): FRAMEWORK_VBMETA_VERSION := 0.0
+endif # BOARD_AVB_ENABLE
+$(GEN): PRIVATE_ENV_VARS += FRAMEWORK_VBMETA_VERSION
+endif # LOCAL_ADD_VBMETA_VERSION
+
+ifneq (,$(strip $(LOCAL_KERNEL_VERSIONS)))
+$(GEN): PRIVATE_KERNEL_CONFIG_DATA := kernel/configs
+$(GEN): PRIVATE_KERNEL_VERSIONS := $(LOCAL_KERNEL_VERSIONS)
+$(GEN): $(foreach version,$(PRIVATE_KERNEL_VERSIONS),\
+    $(wildcard $(PRIVATE_KERNEL_CONFIG_DATA)/android-$(call remove-minor-revision,$(version))/android-base*.cfg))
+$(GEN): PRIVATE_FLAGS += $(foreach version,$(PRIVATE_KERNEL_VERSIONS),\
+    --kernel=$(version):$(call normalize-path-list,\
+        $(wildcard $(PRIVATE_KERNEL_CONFIG_DATA)/android-$(call remove-minor-revision,$(version))/android-base*.cfg)))
+endif
+
+my_matrix_src_files := \
+	$(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES)) \
+	$(LOCAL_GENERATED_SOURCES)
+
+$(GEN): PRIVATE_SRC_FILES := $(my_matrix_src_files)
+$(GEN): $(my_matrix_src_files) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+	$(foreach varname,$(PRIVATE_ENV_VARS),$(varname)=$($(varname))) \
+		$(HOST_OUT_EXECUTABLES)/assemble_vintf \
+		-i $(call normalize-path-list,$(PRIVATE_SRC_FILES)) \
+		-o $@ \
+		$(PRIVATE_FLAGS)
+
+LOCAL_PREBUILT_MODULE_FILE := $(GEN)
+LOCAL_SRC_FILES :=
+LOCAL_GENERATED_SOURCES :=
+
+LOCAL_ADD_VBMETA_VERSION :=
+LOCAL_ASSEMBLE_VINTF_ENV_VARS :=
+LOCAL_ASSEMBLE_VINTF_FLAGS :=
+LOCAL_KERNEL_VERSIONS :=
+LOCAL_GEN_FILE_DEPENDENCIES :=
+my_matrix_src_files :=
+
+include $(BUILD_PREBUILT)
+
+remove-minor-revision :=
diff --git a/configstore/1.0/default/Android.mk b/configstore/1.0/default/Android.mk
index 20f4c5b..22d7c92 100644
--- a/configstore/1.0/default/Android.mk
+++ b/configstore/1.0/default/Android.mk
@@ -3,7 +3,10 @@
 ################################################################################
 include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.configstore@1.0-service
+# seccomp is not required for coverage build.
+ifneq ($(NATIVE_COVERAGE),true)
 LOCAL_REQUIRED_MODULES_arm64 := configstore@1.0.policy
+endif
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_MODULE_RELATIVE_PATH := hw
diff --git a/current.txt b/current.txt
index c18153a..a5ab307 100644
--- a/current.txt
+++ b/current.txt
@@ -255,4 +255,4 @@
 fb92e2b40f8e9d494e8fd3b4ac18499a3216342e7cff160714c3bbf3660b6e79 android.hardware.gnss@1.0::IGnssConfiguration
 251594ea9b27447bfa005ebd806e58fb0ae4aad84a69938129c9800ec0c64eda android.hardware.gnss@1.0::IGnssMeasurementCallback
 4e7169919d24fbe5573e5bcd683d0bd7abf553a4e6c34c41f9dfc1e12050db07 android.hardware.gnss@1.0::IGnssNavigationMessageCallback
-
+b280c4704dfcc548a9bf127b59b7c3578f460c50cce70a06b66fe0df8b27cff0 android.hardware.wifi@1.0::types
diff --git a/drm/1.0/default/DrmPlugin.cpp b/drm/1.0/default/DrmPlugin.cpp
index 1695ef7..809f694 100644
--- a/drm/1.0/default/DrmPlugin.cpp
+++ b/drm/1.0/default/DrmPlugin.cpp
@@ -93,6 +93,7 @@
                 requestType = KeyRequestType::RELEASE;
                 break;
             case android::DrmPlugin::kKeyRequestType_Unknown:
+            default:
                 requestType = KeyRequestType::UNKNOWN;
                 break;
             }
diff --git a/drm/1.1/Android.bp b/drm/1.1/Android.bp
new file mode 100644
index 0000000..ed8196e
--- /dev/null
+++ b/drm/1.1/Android.bp
@@ -0,0 +1,26 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.drm@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "ICryptoFactory.hal",
+        "IDrmFactory.hal",
+        "IDrmPlugin.hal",
+    ],
+    interfaces: [
+        "android.hardware.drm@1.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "HdcpLevel",
+        "KeyRequestType",
+        "SecurityLevel",
+    ],
+    gen_java: false,
+}
+
diff --git a/drm/1.1/ICryptoFactory.hal b/drm/1.1/ICryptoFactory.hal
new file mode 100644
index 0000000..a1a7480
--- /dev/null
+++ b/drm/1.1/ICryptoFactory.hal
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 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.drm@1.1;
+
+import @1.0::ICryptoFactory;
+import @1.0::ICryptoPlugin;
+
+/**
+ * ICryptoFactory is the main entry point for interacting with a vendor's
+ * crypto HAL to create crypto plugins. Crypto plugins create crypto sessions
+ * which are used by a codec to decrypt protected video content.
+ *
+ * The 1.1 factory must always create 1.1 ICryptoPlugin interfaces, which are
+ * returned via the 1.0 createPlugin method.
+ *
+ * To use 1.1 features the caller must cast the returned interface to a
+ * 1.1 HAL, using V1_1::ICryptoPlugin::castFrom().
+ */
+interface ICryptoFactory extends @1.0::ICryptoFactory {
+};
diff --git a/drm/1.1/IDrmFactory.hal b/drm/1.1/IDrmFactory.hal
new file mode 100644
index 0000000..b6d6bfb
--- /dev/null
+++ b/drm/1.1/IDrmFactory.hal
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 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.drm@1.1;
+
+import @1.0::IDrmFactory;
+import @1.0::IDrmPlugin;
+
+/**
+ * IDrmFactory is the main entry point for interacting with a vendor's
+ * drm HAL to create drm plugin instances. A drm plugin instance
+ * creates drm sessions which are used to obtain keys for a crypto
+ * session so it can decrypt protected video content.
+ *
+ * The 1.1 factory must always create 1.1 IDrmPlugin interfaces, which are
+ * returned via the 1.0 createPlugin method.
+ *
+ * To use 1.1 features the caller must cast the returned interface to a
+ * 1.1 HAL, using V1_1::IDrmPlugin::castFrom().
+ */
+
+interface IDrmFactory extends @1.0::IDrmFactory {
+};
diff --git a/drm/1.1/IDrmPlugin.hal b/drm/1.1/IDrmPlugin.hal
new file mode 100644
index 0000000..c32d2b5
--- /dev/null
+++ b/drm/1.1/IDrmPlugin.hal
@@ -0,0 +1,179 @@
+/**
+ * Copyright (C) 2017 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.drm@1.1;
+
+import @1.0::IDrmPlugin;
+import @1.0::IDrmPluginListener;
+import @1.0::KeyedVector;
+import @1.0::KeyType;
+import @1.0::Status;
+import @1.1::DrmMetricGroup;
+import @1.1::HdcpLevel;
+import @1.1::KeyRequestType;
+import @1.1::SecurityLevel;
+
+/**
+ * IDrmPlugin is used to interact with a specific drm plugin that was created by
+ * IDrm::createPlugin. A drm plugin provides methods for obtaining drm keys that
+ * may be used by a codec to decrypt protected video content.
+ */
+interface IDrmPlugin extends @1.0::IDrmPlugin {
+    /**
+     * A key request/response exchange occurs between the app and a License
+     * Server to obtain the keys required to decrypt the content.
+     * getKeyRequest_1_1() is used to obtain an opaque key request blob that is
+     * delivered to the license server.
+     *
+     * getKeyRequest_1_1() only differs from getKeyRequest() in that additional
+     * values are returned in 1.1::KeyRequestType as compared to
+     * 1.0::KeyRequestType
+     *
+     * @param scope may be a sessionId or a keySetId, depending on the
+     *        specified keyType. When the keyType is OFFLINE or STREAMING,
+     *        scope should be set to the sessionId the keys will be provided
+     *        to. When the keyType is RELEASE, scope should be set to the
+     *        keySetId of the keys being released.
+     * @param initData container-specific data, its meaning is interpreted
+     *        based on the mime type provided in the mimeType parameter.
+     *        It could contain, for example, the content ID, key ID or
+     *        other data obtained from the content metadata that is
+     *        required to generate the key request. initData may be empty
+     *        when keyType is RELEASE.
+     * @param mimeType identifies the mime type of the content
+     * @param keyType specifies if the keys are to be used for streaming,
+     *        offline or a release
+     * @param optionalParameters included in the key request message to
+     *        allow a client application to provide additional message
+     *        parameters to the server.
+     * @return status the status of the call. The status must be OK or one of
+     *         the following errors: ERROR_DRM_SESSION_NOT_OPENED if the
+     *         session is not opened, ERROR_DRM_NOT_PROVISIONED if the device
+     *         requires provisioning before it can generate a key request,
+     *         ERROR_DRM_CANNOT_HANDLE if getKeyRequest is not supported
+     *         at the time of the call, BAD_VALUE if any parameters are
+     *         invalid or ERROR_DRM_INVALID_STATE if the HAL is in a
+     *         state where a key request cannot be generated.
+     * @return request if successful, the opaque key request blob is returned
+     * @return requestType indicates type information about the returned
+     *         request. The type may be one of INITIAL, RENEWAL, RELEASE,
+     *         NONE or UPDATE. An INITIAL request is the first key request
+     *         for a license. RENEWAL is a subsequent key request used to
+     *         refresh the keys in a license. RELEASE corresponds to a
+     *         keyType of RELEASE, which indicates keys are being released.
+     *         NONE indicates that no request is needed because the keys are
+     *         already loaded. UPDATE indicates that the keys need to be
+     *         refetched after the initial license request.
+     * @return defaultUrl the URL that the request may be sent to, if
+     *         provided by the drm HAL. The app may choose to override this URL.
+     */
+    getKeyRequest_1_1(vec<uint8_t> scope, vec<uint8_t> initData,
+            string mimeType, KeyType keyType, KeyedVector optionalParameters)
+        generates (Status status, vec<uint8_t> request,
+                KeyRequestType requestType, string defaultUrl);
+
+    /**
+     * Return the currently negotiated and max supported HDCP levels.
+     *
+     * The current level is based on the display(s) the device is connected to.
+     * If multiple HDCP-capable displays are simultaneously connected to
+     * separate interfaces, this method returns the lowest negotiated HDCP level
+     * of all interfaces.
+     *
+     * The maximum HDCP level is the highest level that can potentially be
+     * negotiated. It is a constant for any device, i.e. it does not depend on
+     * downstream receiving devices that could be connected. For example, if
+     * the device has HDCP 1.x keys and is capable of negotiating HDCP 1.x, but
+     * does not have HDCP 2.x keys, then the maximum HDCP capability would be
+     * reported as 1.x. If multiple HDCP-capable interfaces are present, it
+     * indicates the highest of the maximum HDCP levels of all interfaces.
+     *
+     * This method should only be used for informational purposes, not for
+     * enforcing compliance with HDCP requirements. Trusted enforcement of HDCP
+     * policies must be handled by the DRM system.
+     *
+     * @return status the status of the call. The status must be OK or
+     *         ERROR_DRM_INVALID_STATE if the HAL is in a state where the HDCP
+     *         level cannot be queried.
+     * @return connectedLevel the lowest HDCP level for any connected
+     *         displays
+     * @return maxLevel the highest HDCP level that can be supported
+     *         by the device
+     */
+    getHdcpLevels() generates (Status status, HdcpLevel connectedLevel,
+            HdcpLevel maxLevel);
+
+    /**
+     * Return the current number of open sessions and the maximum number of
+     * sessions that may be opened simultaneosly among all DRM instances for the
+     * active DRM scheme.
+     *
+     * @return status the status of the call. The status must be OK or
+     *         ERROR_DRM_INVALID_STATE if the HAL is in a state where number of
+     *         sessions cannot be queried.
+     * @return currentSessions the number of currently opened sessions
+     * @return maxSessions the maximum number of sessions that the device
+     *         can support
+     */
+    getNumberOfSessions() generates (Status status, uint32_t currentSessions,
+             uint32_t maxSessions);
+
+    /**
+     * Return the current security level of a session. A session has an initial
+     * security level determined by the robustness of the DRM system's
+     * implementation on the device.
+     *
+     * @param sessionId the session id the call applies to
+     * @return status the status of the call. The status must be OK or one of
+     *         the following errors: ERROR_DRM_SESSION_NOT_OPENED if the
+     *         session is not opened, BAD_VALUE if the sessionId is invalid or
+     *         ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+     *         security level cannot be queried.
+     * @return level the current security level for the session
+     */
+    getSecurityLevel(vec<uint8_t> sessionId) generates(Status status,
+            SecurityLevel level);
+
+    /**
+     * Set the security level of a session. This can be useful if specific
+     * attributes of a lower security level are needed by an application, such
+     * as image manipulation or compositing which requires non-secure decoded
+     * frames. Reducing the security level may limit decryption to lower content
+     * resolutions, depending on the license policy.
+     *
+     * @param sessionId the session id the call applies to
+     * @param level the requested security level
+     * @return status the status of the call. The status must be OK or one of
+     *         the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session
+     *         is not opened, BAD_VALUE if the sessionId or security level is
+     *         invalid or ERROR_DRM_INVALID_STATE if the HAL is in a state where
+     *         the security level cannot be set.
+     */
+    setSecurityLevel(vec<uint8_t> sessionId, SecurityLevel level)
+            generates(Status status);
+
+    /**
+     * Returns the plugin-specific metrics. Multiple metric groups may be
+     * returned in one call to getMetrics(). The scope and definition of the
+     * metrics is defined by the plugin.
+     *
+     * @return status the status of the call. The status must be OK or
+     *         ERROR_DRM_INVALID_STATE if the metrics are not available to be
+     *         returned.
+     * @return metric_groups the collection of metric groups provided by the
+     *         plugin.
+     */
+    getMetrics() generates (Status status, vec<DrmMetricGroup> metric_groups);
+};
diff --git a/drm/1.1/types.hal b/drm/1.1/types.hal
new file mode 100644
index 0000000..94a6e66
--- /dev/null
+++ b/drm/1.1/types.hal
@@ -0,0 +1,212 @@
+/**
+ * Copyright (C) 2017 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.drm@1.1;
+
+import @1.0::KeyRequestType;
+
+/**
+ * This message contains plugin-specific metrics made available to the client.
+ * The message is used for making vendor-specific metrics available to an
+ * application. The framework is not consuming any of the information.
+ *
+ * Metrics are grouped in instances of DrmMetricGroup. Each group contains
+ * multiple instances of Metric.
+ *
+ * Example:
+ *
+ * Capture the timing information of a buffer copy event, "buf_copy", broken
+ * out by the "size" of the buffer.
+ *
+ * DrmMetricGroup {
+ *   metrics[0] {
+ *     name: "buf_copy"
+ *     attributes[0] {
+ *       name: "size"
+ *       type: INT64_TYPE
+ *       int64Value: 1024
+ *     }
+ *     values[0] {
+ *       componentName: "operation_count"
+ *       type: INT64_TYPE
+ *       int64Value: 75
+ *     }
+ *     values[1] {
+ *       component_name: "average_time_seconds"
+ *       type: DOUBLE_TYPE
+ *       doubleValue: 0.00000042
+ *     }
+ *   }
+ * }
+ */
+struct DrmMetricGroup {
+    /**
+     * Used to discriminate the type of value being stored in the structs
+     * below.
+     */
+    enum ValueType : uint8_t {
+        INT64_TYPE,
+        DOUBLE_TYPE,
+        STRING_TYPE,
+    };
+
+    /**
+     * A detail about the metric being captured. The fields of an Attribute
+     * are opaque to the framework.
+     */
+    struct Attribute {
+        string name;
+        /**
+         * The type field indicates which of the following values is used.
+         */
+        ValueType type;
+        int64_t int64Value;
+        double doubleValue;
+        string stringValue;
+    };
+
+    /**
+     * A value of the metric. A metric may have multiple values. The
+     * component name may be left empty if there is only supposed to be
+     * one value for the given metric. The fields of the Value are
+     * opaque to the framework.
+     */
+    struct Value {
+        string componentName;
+        /**
+         * The type field indicates which of the following values is used.
+         */
+        ValueType type;
+        int64_t int64Value;
+        double doubleValue;
+        string stringValue;
+    };
+
+    /**
+     * The metric being captured. A metric must have a name and at least one
+     * value. A metric may have 0 or more attributes. The fields of a Metric
+     * are opaque to the framework.
+     */
+    struct Metric {
+        string name;
+        vec<Attribute> attributes;
+        // A Metric may have one or more values. Multiple values are useful
+        // for capturing different aspects of the same metric. E.g. capture
+        // the min, max, average, count, and stdev of a particular metric.
+        vec<Value> values;
+    };
+
+    /**
+     * The list of metrics to be captured.
+     */
+    vec<Metric> metrics;
+};
+
+/**
+ * HDCP specifications are defined by Digital Content Protection LLC (DCP).
+ *   "HDCP Specification Rev. 2.2 Interface Independent Adaptation"
+ *   "HDCP 2.2 on HDMI Specification"
+ */
+enum HdcpLevel : uint32_t {
+    /**
+     * Unable to determine the HDCP level
+     */
+    HDCP_UNKNOWN,
+
+    /**
+     * No HDCP, output is unprotected
+     */
+    HDCP_NONE,
+
+    /**
+     * HDCP version 1.0
+     */
+    HDCP_V1,
+
+    /**
+     * HDCP version 2.0 Type 1.
+     */
+    HDCP_V2,
+
+    /**
+     * HDCP version 2.1 Type 1.
+     */
+    HDCP_V2_1,
+
+    /**
+     *  HDCP version 2.2 Type 1.
+     */
+    HDCP_V2_2,
+
+    /**
+     * No digital output, implicitly secure
+     */
+    HDCP_NO_OUTPUT
+};
+
+/**
+ * KeyRequestTypes (in addition to those from 1.0) which allow an app
+ * to determine the type of a key request returned from getKeyRequest.
+ */
+enum KeyRequestType : @1.0::KeyRequestType {
+    /**
+     * Keys are already loaded. No key request is needed.
+     */
+    NONE,
+
+    /**
+     * Keys have previously been loaded. An additional (non-renewal) license
+     * request is needed.
+     */
+    UPDATE,
+};
+
+enum SecurityLevel : uint32_t {
+    /**
+     * Unable to determine the security level
+     */
+    UNKNOWN,
+
+    /**
+     * Software-based whitebox crypto
+     */
+    SW_SECURE_CRYPTO,
+
+    /**
+     * Software-based whitebox crypto and an obfuscated decoder
+     */
+    SW_SECURE_DECODE,
+
+    /**
+     * DRM key management and crypto operations are performed within a
+     * hardware backed trusted execution environment
+     */
+    HW_SECURE_CRYPTO,
+
+    /**
+     * DRM key management, crypto operations and decoding of content
+     * are performed within a hardware backed trusted execution environment
+     */
+    HW_SECURE_DECODE,
+
+    /**
+     * DRM key management, crypto operations, decoding of content and all
+     * handling of the media (compressed and uncompressed) is handled within
+     * a hardware backed trusted execution environment.
+     */
+    HW_SECURE_ALL,
+};
+
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index 9968f41..ed2ecbb 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -1,10 +1,15 @@
 cc_library_shared {
     name: "android.hardware.graphics.allocator@2.0-impl",
     defaults: ["hidl_defaults"],
-    proprietary: true,
+    vendor: true,
     relative_install_path: "hw",
-    srcs: ["Gralloc.cpp", "Gralloc0Allocator.cpp", "Gralloc1Allocator.cpp"],
-    cppflags: ["-Wall", "-Wextra"],
+    srcs: ["passthrough.cpp"],
+    static_libs: [
+        "android.hardware.graphics.allocator@2.0-passthrough",
+    ],
+    header_libs: [
+        "android.hardware.graphics.allocator@2.0-hal",
+    ],
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
         "libbase",
@@ -15,9 +20,6 @@
         "liblog",
         "libutils",
     ],
-    header_libs: [
-        "libgrallocmapperincludes",
-    ],
 }
 
 cc_binary {
@@ -36,13 +38,3 @@
         "libutils",
     ],
 }
-
-cc_library_static {
-    name: "libgralloc1-adapter",
-    defaults: ["hidl_defaults"],
-    srcs: ["gralloc1-adapter.cpp", "Gralloc1On0Adapter.cpp"],
-    include_dirs: ["system/core/libsync/include"],
-    cflags: ["-Wall", "-Wextra"],
-    export_include_dirs: ["."],
-    whole_static_libs: ["libgrallocusage"],
-}
diff --git a/graphics/allocator/2.0/default/Gralloc.cpp b/graphics/allocator/2.0/default/Gralloc.cpp
deleted file mode 100644
index 273d3f5..0000000
--- a/graphics/allocator/2.0/default/Gralloc.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 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 "GrallocPassthrough"
-
-#include "Gralloc.h"
-#include "Gralloc0Allocator.h"
-#include "Gralloc1Allocator.h"
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
-    const hw_module_t* module = nullptr;
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    if (err) {
-        ALOGE("failed to get gralloc module");
-        return nullptr;
-    }
-
-    uint8_t major = (module->module_api_version >> 8) & 0xff;
-    switch (major) {
-        case 1:
-            return new Gralloc1Allocator(module);
-        case 0:
-            return new Gralloc0Allocator(module);
-        default:
-            ALOGE("unknown gralloc module major version %d", major);
-            return nullptr;
-    }
-}
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc.h b/graphics/allocator/2.0/default/Gralloc.h
deleted file mode 100644
index c79eeaa..0000000
--- a/graphics/allocator/2.0/default/Gralloc.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 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_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
-#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-extern "C" IAllocator* HIDL_FETCH_IAllocator(const char* name);
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.cpp b/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
deleted file mode 100644
index 3b62bb3..0000000
--- a/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 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 "Gralloc0Allocator"
-
-#include "Gralloc0Allocator.h"
-#include "GrallocBufferDescriptor.h"
-
-#include <vector>
-
-#include <string.h>
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::mapper::V2_0::implementation::
-    grallocDecodeBufferDescriptor;
-
-Gralloc0Allocator::Gralloc0Allocator(const hw_module_t* module) {
-    int result = gralloc_open(module, &mDevice);
-    if (result) {
-        LOG_ALWAYS_FATAL("failed to open gralloc0 device: %s",
-                         strerror(-result));
-    }
-}
-
-Gralloc0Allocator::~Gralloc0Allocator() {
-    gralloc_close(mDevice);
-}
-
-Return<void> Gralloc0Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
-    char buf[4096] = {};
-    if (mDevice->dump) {
-        mDevice->dump(mDevice, buf, sizeof(buf));
-        buf[sizeof(buf) - 1] = '\0';
-    }
-
-    hidl_cb(hidl_string(buf));
-
-    return Void();
-}
-
-Return<void> Gralloc0Allocator::allocate(const BufferDescriptor& descriptor,
-                                         uint32_t count, allocate_cb hidl_cb) {
-    IMapper::BufferDescriptorInfo descriptorInfo;
-    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
-        hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
-        return Void();
-    }
-
-    Error error = Error::NONE;
-    uint32_t stride = 0;
-    std::vector<hidl_handle> buffers;
-    buffers.reserve(count);
-
-    // allocate the buffers
-    for (uint32_t i = 0; i < count; i++) {
-        buffer_handle_t tmpBuffer;
-        uint32_t tmpStride;
-        error = allocateOne(descriptorInfo, &tmpBuffer, &tmpStride);
-        if (error != Error::NONE) {
-            break;
-        }
-
-        if (stride == 0) {
-            stride = tmpStride;
-        } else if (stride != tmpStride) {
-            // non-uniform strides
-            mDevice->free(mDevice, tmpBuffer);
-            stride = 0;
-            error = Error::UNSUPPORTED;
-            break;
-        }
-
-        buffers.emplace_back(hidl_handle(tmpBuffer));
-    }
-
-    // return the buffers
-    hidl_vec<hidl_handle> hidl_buffers;
-    if (error == Error::NONE) {
-        hidl_buffers.setToExternal(buffers.data(), buffers.size());
-    }
-    hidl_cb(error, stride, hidl_buffers);
-
-    // free the buffers
-    for (const auto& buffer : buffers) {
-        mDevice->free(mDevice, buffer.getNativeHandle());
-    }
-
-    return Void();
-}
-
-Error Gralloc0Allocator::allocateOne(const IMapper::BufferDescriptorInfo& info,
-                                     buffer_handle_t* outBuffer,
-                                     uint32_t* outStride) {
-    if (info.layerCount > 1 || (info.usage >> 32) != 0) {
-        return Error::BAD_VALUE;
-    }
-
-    buffer_handle_t buffer = nullptr;
-    int stride = 0;
-    int result = mDevice->alloc(mDevice, info.width, info.height,
-                                static_cast<int>(info.format), info.usage,
-                                &buffer, &stride);
-    if (result) {
-        switch (result) {
-            case -EINVAL:
-                return Error::BAD_VALUE;
-            default:
-                return Error::NO_RESOURCES;
-        }
-    }
-
-    *outBuffer = buffer;
-    *outStride = stride;
-
-    return Error::NONE;
-}
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.h b/graphics/allocator/2.0/default/Gralloc0Allocator.h
deleted file mode 100644
index 0e90527..0000000
--- a/graphics/allocator/2.0/default/Gralloc0Allocator.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 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_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
-#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <hardware/gralloc.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using android::hardware::graphics::mapper::V2_0::Error;
-
-class Gralloc0Allocator : public IAllocator {
-   public:
-    Gralloc0Allocator(const hw_module_t* module);
-    virtual ~Gralloc0Allocator();
-
-    // IAllocator interface
-    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
-    Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
-                          allocate_cb hidl_cb) override;
-
-   private:
-    Error allocateOne(const IMapper::BufferDescriptorInfo& info,
-                      buffer_handle_t* outBuffer, uint32_t* outStride);
-
-    alloc_device_t* mDevice;
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.cpp b/graphics/allocator/2.0/default/Gralloc1Allocator.cpp
deleted file mode 100644
index 6cbb791..0000000
--- a/graphics/allocator/2.0/default/Gralloc1Allocator.cpp
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright 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 "Gralloc1Allocator"
-
-#include "Gralloc1Allocator.h"
-#include "GrallocBufferDescriptor.h"
-
-#include <vector>
-
-#include <string.h>
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using android::hardware::graphics::mapper::V2_0::implementation::
-    grallocDecodeBufferDescriptor;
-
-Gralloc1Allocator::Gralloc1Allocator(const hw_module_t* module)
-    : mDevice(nullptr), mCapabilities(), mDispatch() {
-    int result = gralloc1_open(module, &mDevice);
-    if (result) {
-        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
-                         strerror(-result));
-    }
-
-    initCapabilities();
-    initDispatch();
-}
-
-Gralloc1Allocator::~Gralloc1Allocator() {
-    gralloc1_close(mDevice);
-}
-
-void Gralloc1Allocator::initCapabilities() {
-    uint32_t count = 0;
-    mDevice->getCapabilities(mDevice, &count, nullptr);
-
-    std::vector<int32_t> capabilities(count);
-    mDevice->getCapabilities(mDevice, &count, capabilities.data());
-    capabilities.resize(count);
-
-    for (auto capability : capabilities) {
-        if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
-            mCapabilities.layeredBuffers = true;
-            break;
-        }
-    }
-}
-
-template <typename T>
-void Gralloc1Allocator::initDispatch(gralloc1_function_descriptor_t desc,
-                                     T* outPfn) {
-    auto pfn = mDevice->getFunction(mDevice, desc);
-    if (!pfn) {
-        LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
-    }
-
-    *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void Gralloc1Allocator::initDispatch() {
-    initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump);
-    initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR,
-                 &mDispatch.createDescriptor);
-    initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR,
-                 &mDispatch.destroyDescriptor);
-    initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions);
-    initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat);
-    if (mCapabilities.layeredBuffers) {
-        initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT,
-                     &mDispatch.setLayerCount);
-    }
-    initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE,
-                 &mDispatch.setConsumerUsage);
-    initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE,
-                 &mDispatch.setProducerUsage);
-    initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride);
-    initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate);
-    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
-}
-
-Return<void> Gralloc1Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
-    uint32_t len = 0;
-    mDispatch.dump(mDevice, &len, nullptr);
-
-    std::vector<char> buf(len + 1);
-    mDispatch.dump(mDevice, &len, buf.data());
-    buf.resize(len + 1);
-    buf[len] = '\0';
-
-    hidl_string reply;
-    reply.setToExternal(buf.data(), len);
-    hidl_cb(reply);
-
-    return Void();
-}
-
-Return<void> Gralloc1Allocator::allocate(const BufferDescriptor& descriptor,
-                                         uint32_t count, allocate_cb hidl_cb) {
-    IMapper::BufferDescriptorInfo descriptorInfo;
-    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
-        hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
-        return Void();
-    }
-
-    gralloc1_buffer_descriptor_t desc;
-    Error error = createDescriptor(descriptorInfo, &desc);
-    if (error != Error::NONE) {
-        hidl_cb(error, 0, hidl_vec<hidl_handle>());
-        return Void();
-    }
-
-    uint32_t stride = 0;
-    std::vector<hidl_handle> buffers;
-    buffers.reserve(count);
-
-    // allocate the buffers
-    for (uint32_t i = 0; i < count; i++) {
-        buffer_handle_t tmpBuffer;
-        uint32_t tmpStride;
-        error = allocateOne(desc, &tmpBuffer, &tmpStride);
-        if (error != Error::NONE) {
-            break;
-        }
-
-        if (stride == 0) {
-            stride = tmpStride;
-        } else if (stride != tmpStride) {
-            // non-uniform strides
-            mDispatch.release(mDevice, tmpBuffer);
-            stride = 0;
-            error = Error::UNSUPPORTED;
-            break;
-        }
-
-        buffers.emplace_back(hidl_handle(tmpBuffer));
-    }
-
-    mDispatch.destroyDescriptor(mDevice, desc);
-
-    // return the buffers
-    hidl_vec<hidl_handle> hidl_buffers;
-    if (error == Error::NONE) {
-        hidl_buffers.setToExternal(buffers.data(), buffers.size());
-    }
-    hidl_cb(error, stride, hidl_buffers);
-
-    // free the buffers
-    for (const auto& buffer : buffers) {
-        mDispatch.release(mDevice, buffer.getNativeHandle());
-    }
-
-    return Void();
-}
-
-Error Gralloc1Allocator::toError(int32_t error) {
-    switch (error) {
-        case GRALLOC1_ERROR_NONE:
-            return Error::NONE;
-        case GRALLOC1_ERROR_BAD_DESCRIPTOR:
-            return Error::BAD_DESCRIPTOR;
-        case GRALLOC1_ERROR_BAD_HANDLE:
-            return Error::BAD_BUFFER;
-        case GRALLOC1_ERROR_BAD_VALUE:
-            return Error::BAD_VALUE;
-        case GRALLOC1_ERROR_NOT_SHARED:
-            return Error::NONE;  // this is fine
-        case GRALLOC1_ERROR_NO_RESOURCES:
-            return Error::NO_RESOURCES;
-        case GRALLOC1_ERROR_UNDEFINED:
-        case GRALLOC1_ERROR_UNSUPPORTED:
-        default:
-            return Error::UNSUPPORTED;
-    }
-}
-
-uint64_t Gralloc1Allocator::toProducerUsage(uint64_t usage) {
-    // this is potentially broken as we have no idea which private flags
-    // should be filtered out
-    uint64_t producerUsage =
-        usage &
-        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
-                               BufferUsage::GPU_DATA_BUFFER);
-
-    switch (usage & BufferUsage::CPU_WRITE_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    switch (usage & BufferUsage::CPU_READ_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    // BufferUsage::GPU_DATA_BUFFER is always filtered out
-
-    return producerUsage;
-}
-
-uint64_t Gralloc1Allocator::toConsumerUsage(uint64_t usage) {
-    // this is potentially broken as we have no idea which private flags
-    // should be filtered out
-    uint64_t consumerUsage =
-        usage &
-        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
-                               BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
-
-    switch (usage & BufferUsage::CPU_READ_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
-            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
-            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
-
-    if (usage & BufferUsage::GPU_DATA_BUFFER) {
-        consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
-    }
-
-    return consumerUsage;
-}
-
-Error Gralloc1Allocator::createDescriptor(
-    const IMapper::BufferDescriptorInfo& info,
-    gralloc1_buffer_descriptor_t* outDescriptor) {
-    gralloc1_buffer_descriptor_t descriptor;
-
-    int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
-
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setDimensions(mDevice, descriptor, info.width,
-                                        info.height);
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setFormat(mDevice, descriptor,
-                                    static_cast<int32_t>(info.format));
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        if (mCapabilities.layeredBuffers) {
-            error =
-                mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
-        } else if (info.layerCount > 1) {
-            error = GRALLOC1_ERROR_UNSUPPORTED;
-        }
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setProducerUsage(mDevice, descriptor,
-                                           toProducerUsage(info.usage));
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setConsumerUsage(mDevice, descriptor,
-                                           toConsumerUsage(info.usage));
-    }
-
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outDescriptor = descriptor;
-    } else {
-        mDispatch.destroyDescriptor(mDevice, descriptor);
-    }
-
-    return toError(error);
-}
-
-Error Gralloc1Allocator::allocateOne(gralloc1_buffer_descriptor_t descriptor,
-                                     buffer_handle_t* outBuffer,
-                                     uint32_t* outStride) {
-    buffer_handle_t buffer = nullptr;
-    int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
-    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
-        return toError(error);
-    }
-
-    uint32_t stride = 0;
-    error = mDispatch.getStride(mDevice, buffer, &stride);
-    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
-        mDispatch.release(mDevice, buffer);
-        return toError(error);
-    }
-
-    *outBuffer = buffer;
-    *outStride = stride;
-
-    return Error::NONE;
-}
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.h b/graphics/allocator/2.0/default/Gralloc1Allocator.h
deleted file mode 100644
index 7b5a966..0000000
--- a/graphics/allocator/2.0/default/Gralloc1Allocator.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 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_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
-#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <hardware/gralloc1.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using android::hardware::graphics::mapper::V2_0::Error;
-
-class Gralloc1Allocator : public IAllocator {
-   public:
-    Gralloc1Allocator(const hw_module_t* module);
-    virtual ~Gralloc1Allocator();
-
-    // IAllocator interface
-    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
-    Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
-                          allocate_cb hidl_cb) override;
-
-   private:
-    void initCapabilities();
-
-    template <typename T>
-    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
-    void initDispatch();
-
-    static Error toError(int32_t error);
-    static uint64_t toProducerUsage(uint64_t usage);
-    static uint64_t toConsumerUsage(uint64_t usage);
-
-    Error createDescriptor(const IMapper::BufferDescriptorInfo& info,
-                           gralloc1_buffer_descriptor_t* outDescriptor);
-    Error allocateOne(gralloc1_buffer_descriptor_t descriptor,
-                      buffer_handle_t* outBuffer, uint32_t* outStride);
-
-    gralloc1_device_t* mDevice;
-
-    struct {
-        bool layeredBuffers;
-    } mCapabilities;
-
-    struct {
-        GRALLOC1_PFN_DUMP dump;
-        GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
-        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_GET_STRIDE getStride;
-        GRALLOC1_PFN_ALLOCATE allocate;
-        GRALLOC1_PFN_RELEASE release;
-    } mDispatch;
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
diff --git a/graphics/allocator/2.0/default/passthrough.cpp b/graphics/allocator/2.0/default/passthrough.cpp
new file mode 100644
index 0000000..132cab3
--- /dev/null
+++ b/graphics/allocator/2.0/default/passthrough.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 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 <allocator-passthrough/2.0/GrallocLoader.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+using android::hardware::graphics::allocator::V2_0::passthrough::GrallocLoader;
+
+extern "C" IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
+    return GrallocLoader::load();
+}
diff --git a/graphics/allocator/2.0/default/service.cpp b/graphics/allocator/2.0/default/service.cpp
index 99f462c..bc0539a 100644
--- a/graphics/allocator/2.0/default/service.cpp
+++ b/graphics/allocator/2.0/default/service.cpp
@@ -20,8 +20,8 @@
 
 #include <hidl/LegacySupport.h>
 
-using android::hardware::graphics::allocator::V2_0::IAllocator;
 using android::hardware::defaultPassthroughServiceImplementation;
+using android::hardware::graphics::allocator::V2_0::IAllocator;
 
 int main() {
     return defaultPassthroughServiceImplementation<IAllocator>(4);
diff --git a/graphics/allocator/2.0/utils/OWNERS b/graphics/allocator/2.0/utils/OWNERS
new file mode 100644
index 0000000..3aa5fa1
--- /dev/null
+++ b/graphics/allocator/2.0/utils/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/allocator/2.0/utils/gralloc1-adapter/Android.bp b/graphics/allocator/2.0/utils/gralloc1-adapter/Android.bp
new file mode 100644
index 0000000..9cb53e3
--- /dev/null
+++ b/graphics/allocator/2.0/utils/gralloc1-adapter/Android.bp
@@ -0,0 +1,10 @@
+cc_library_static {
+    name: "libgralloc1-adapter",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    srcs: ["gralloc1-adapter.cpp", "Gralloc1On0Adapter.cpp"],
+    include_dirs: ["system/core/libsync/include"],
+    export_include_dirs: ["."],
+    whole_static_libs: ["libgrallocusage"],
+    shared_libs: ["libhardware", "liblog"],
+}
diff --git a/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp b/graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.cpp
similarity index 99%
rename from graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
rename to graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.cpp
index 041ce77..b7ed58c 100644
--- a/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
+++ b/graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.cpp
@@ -29,6 +29,7 @@
 #include <sync/sync.h>
 
 #include <inttypes.h>
+#include <unistd.h>
 
 template <typename PFN, typename T>
 static gralloc1_function_pointer_t asFP(T function)
diff --git a/graphics/allocator/2.0/default/Gralloc1On0Adapter.h b/graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.h
similarity index 100%
rename from graphics/allocator/2.0/default/Gralloc1On0Adapter.h
rename to graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.h
diff --git a/graphics/allocator/2.0/default/gralloc1-adapter.cpp b/graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.cpp
similarity index 100%
rename from graphics/allocator/2.0/default/gralloc1-adapter.cpp
rename to graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.cpp
diff --git a/graphics/allocator/2.0/default/gralloc1-adapter.h b/graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.h
similarity index 100%
rename from graphics/allocator/2.0/default/gralloc1-adapter.h
rename to graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.h
diff --git a/graphics/allocator/2.0/utils/hal/Android.bp b/graphics/allocator/2.0/utils/hal/Android.bp
new file mode 100644
index 0000000..ac642ce
--- /dev/null
+++ b/graphics/allocator/2.0/utils/hal/Android.bp
@@ -0,0 +1,14 @@
+cc_library_headers {
+    name: "android.hardware.graphics.allocator@2.0-hal",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
new file mode 100644
index 0000000..2f3022e
--- /dev/null
+++ b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Allocator.h included without LOG_TAG"
+#endif
+
+#include <memory>
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace hal {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+namespace detail {
+
+// AllocatorImpl implements IAllocator on top of AllocatorHal
+template <typename IALLOCATOR, typename ALLOCATOR_HAL>
+class AllocatorImpl : public IALLOCATOR {
+   public:
+    bool init(std::unique_ptr<ALLOCATOR_HAL> hal) {
+        mHal = std::move(hal);
+        return true;
+    }
+
+    // IAllocator 2.0 interface
+    Return<void> dumpDebugInfo(IAllocator::dumpDebugInfo_cb hidl_cb) override {
+        hidl_cb(mHal->dumpDebugInfo());
+        return Void();
+    }
+
+    Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
+                          IAllocator::allocate_cb hidl_cb) override {
+        uint32_t stride;
+        std::vector<const native_handle_t*> buffers;
+        Error error = mHal->allocateBuffers(descriptor, count, &stride, &buffers);
+        if (error != Error::NONE) {
+            hidl_cb(error, 0, hidl_vec<hidl_handle>());
+            return Void();
+        }
+
+        hidl_vec<hidl_handle> hidlBuffers(buffers.cbegin(), buffers.cend());
+        hidl_cb(Error::NONE, stride, hidlBuffers);
+
+        // free the local handles
+        mHal->freeBuffers(buffers);
+
+        return Void();
+    }
+
+   protected:
+    std::unique_ptr<ALLOCATOR_HAL> mHal;
+};
+
+}  // namespace detail
+
+using Allocator = detail::AllocatorImpl<IAllocator, AllocatorHal>;
+
+}  // namespace hal
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/AllocatorHal.h b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/AllocatorHal.h
new file mode 100644
index 0000000..dec377a
--- /dev/null
+++ b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/AllocatorHal.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace hal {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+class AllocatorHal {
+   public:
+    virtual ~AllocatorHal() = default;
+
+    // dump the debug information
+    virtual std::string dumpDebugInfo() = 0;
+
+    // allocate buffers
+    virtual Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
+                                  uint32_t* outStride,
+                                  std::vector<const native_handle_t*>* outBuffers) = 0;
+
+    // free buffers
+    virtual void freeBuffers(const std::vector<const native_handle_t*>& buffers) = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/Android.bp b/graphics/allocator/2.0/utils/passthrough/Android.bp
new file mode 100644
index 0000000..b956565
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/Android.bp
@@ -0,0 +1,29 @@
+cc_library_static {
+    name: "android.hardware.graphics.allocator@2.0-passthrough",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    srcs: [
+        "Gralloc0Hal.cpp",
+        "Gralloc1Hal.cpp",
+        "GrallocLoader.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+    ],
+    header_libs: [
+        "android.hardware.graphics.allocator@2.0-hal",
+        "libgrallocmapperincludes",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.allocator@2.0-hal",
+    ],
+    export_include_dirs: ["include"],
+    cflags: ["-DLOG_TAG=\"AllocatorHal\""],
+}
diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp
new file mode 100644
index 0000000..8edb7dc
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright 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 <allocator-passthrough/2.0/Gralloc0Hal.h>
+
+#include <string.h>
+
+#include <GrallocBufferDescriptor.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
+
+Gralloc0Hal::~Gralloc0Hal() {
+    if (mDevice) {
+        gralloc_close(mDevice);
+    }
+}
+
+bool Gralloc0Hal::initWithModule(const hw_module_t* module) {
+    int result = gralloc_open(module, &mDevice);
+    if (result) {
+        ALOGE("failed to open gralloc0 device: %s", strerror(-result));
+        mDevice = nullptr;
+        return false;
+    }
+
+    return true;
+}
+
+std::string Gralloc0Hal::dumpDebugInfo() {
+    char buf[4096] = {};
+    if (mDevice->dump) {
+        mDevice->dump(mDevice, buf, sizeof(buf));
+        buf[sizeof(buf) - 1] = '\0';
+    }
+
+    return buf;
+}
+
+Error Gralloc0Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
+                                   uint32_t* outStride,
+                                   std::vector<const native_handle_t*>* outBuffers) {
+    mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+        return Error::BAD_DESCRIPTOR;
+    }
+
+    Error error = Error::NONE;
+    uint32_t stride = 0;
+    std::vector<const native_handle_t*> buffers;
+    buffers.reserve(count);
+
+    // allocate the buffers
+    for (uint32_t i = 0; i < count; i++) {
+        const native_handle_t* tmpBuffer;
+        uint32_t tmpStride;
+        error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
+        if (error != Error::NONE) {
+            break;
+        }
+
+        buffers.push_back(tmpBuffer);
+
+        if (stride == 0) {
+            stride = tmpStride;
+        } else if (stride != tmpStride) {
+            // non-uniform strides
+            error = Error::UNSUPPORTED;
+            break;
+        }
+    }
+
+    if (error != Error::NONE) {
+        freeBuffers(buffers);
+        return error;
+    }
+
+    *outStride = stride;
+    *outBuffers = std::move(buffers);
+
+    return Error::NONE;
+}
+
+void Gralloc0Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
+    for (auto buffer : buffers) {
+        int result = mDevice->free(mDevice, buffer);
+        if (result != 0) {
+            ALOGE("failed to free buffer %p: %d", buffer, result);
+        }
+    }
+}
+
+Error Gralloc0Hal::allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                                     const native_handle_t** outBuffer, uint32_t* outStride) {
+    if (info.layerCount > 1 || (info.usage >> 32) != 0) {
+        return Error::BAD_VALUE;
+    }
+
+    const native_handle_t* buffer = nullptr;
+    int stride = 0;
+    int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
+                                info.usage, &buffer, &stride);
+    switch (result) {
+        case 0:
+            *outBuffer = buffer;
+            *outStride = stride;
+            return Error::NONE;
+        case -EINVAL:
+            return Error::BAD_VALUE;
+        default:
+            return Error::NO_RESOURCES;
+    }
+}
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp
new file mode 100644
index 0000000..e343ecd
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp
@@ -0,0 +1,323 @@
+/*
+ * Copyright 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 <allocator-passthrough/2.0/Gralloc1Hal.h>
+
+#include <string.h>
+
+#include <GrallocBufferDescriptor.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
+
+Gralloc1Hal::~Gralloc1Hal() {
+    if (mDevice) {
+        gralloc1_close(mDevice);
+    }
+}
+
+bool Gralloc1Hal::initWithModule(const hw_module_t* module) {
+    int result = gralloc1_open(module, &mDevice);
+    if (result) {
+        ALOGE("failed to open gralloc1 device: %s", strerror(-result));
+        mDevice = nullptr;
+        return false;
+    }
+
+    initCapabilities();
+    if (!initDispatch()) {
+        gralloc1_close(mDevice);
+        mDevice = nullptr;
+        return false;
+    }
+
+    return true;
+}
+
+void Gralloc1Hal::initCapabilities() {
+    uint32_t count = 0;
+    mDevice->getCapabilities(mDevice, &count, nullptr);
+
+    std::vector<int32_t> capabilities(count);
+    mDevice->getCapabilities(mDevice, &count, capabilities.data());
+    capabilities.resize(count);
+
+    for (auto capability : capabilities) {
+        if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
+            mCapabilities.layeredBuffers = true;
+            break;
+        }
+    }
+}
+
+gralloc1_function_pointer_t Gralloc1Hal::getDispatchFunction(
+    gralloc1_function_descriptor_t desc) const {
+    auto pfn = mDevice->getFunction(mDevice, desc);
+    if (!pfn) {
+        ALOGE("failed to get gralloc1 function %d", desc);
+        return nullptr;
+    }
+    return pfn;
+}
+
+bool Gralloc1Hal::initDispatch() {
+    if (!initDispatchFunction(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, &mDispatch.createDescriptor) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, &mDispatch.destroyDescriptor) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, &mDispatch.setConsumerUsage) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, &mDispatch.setProducerUsage) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release)) {
+        return false;
+    }
+
+    if (mCapabilities.layeredBuffers) {
+        if (!initDispatchFunction(GRALLOC1_FUNCTION_SET_LAYER_COUNT, &mDispatch.setLayerCount)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+std::string Gralloc1Hal::dumpDebugInfo() {
+    uint32_t len = 0;
+    mDispatch.dump(mDevice, &len, nullptr);
+
+    std::vector<char> buf(len + 1);
+    mDispatch.dump(mDevice, &len, buf.data());
+    buf.resize(len + 1);
+    buf[len] = '\0';
+
+    return buf.data();
+}
+
+Error Gralloc1Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
+                                   uint32_t* outStride,
+                                   std::vector<const native_handle_t*>* outBuffers) {
+    mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+        return Error::BAD_DESCRIPTOR;
+    }
+
+    gralloc1_buffer_descriptor_t desc;
+    Error error = createDescriptor(descriptorInfo, &desc);
+    if (error != Error::NONE) {
+        return error;
+    }
+
+    uint32_t stride = 0;
+    std::vector<const native_handle_t*> buffers;
+    buffers.reserve(count);
+
+    // allocate the buffers
+    for (uint32_t i = 0; i < count; i++) {
+        const native_handle_t* tmpBuffer;
+        uint32_t tmpStride;
+        error = allocateOneBuffer(desc, &tmpBuffer, &tmpStride);
+        if (error != Error::NONE) {
+            break;
+        }
+
+        buffers.push_back(tmpBuffer);
+
+        if (stride == 0) {
+            stride = tmpStride;
+        } else if (stride != tmpStride) {
+            // non-uniform strides
+            error = Error::UNSUPPORTED;
+            break;
+        }
+    }
+
+    mDispatch.destroyDescriptor(mDevice, desc);
+
+    if (error != Error::NONE) {
+        freeBuffers(buffers);
+        return error;
+    }
+
+    *outStride = stride;
+    *outBuffers = std::move(buffers);
+
+    return Error::NONE;
+}
+
+void Gralloc1Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
+    for (auto buffer : buffers) {
+        int32_t error = mDispatch.release(mDevice, buffer);
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGE("failed to free buffer %p: %d", buffer, error);
+        }
+    }
+}
+
+Error Gralloc1Hal::toError(int32_t error) {
+    switch (error) {
+        case GRALLOC1_ERROR_NONE:
+            return Error::NONE;
+        case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+            return Error::BAD_DESCRIPTOR;
+        case GRALLOC1_ERROR_BAD_HANDLE:
+            return Error::BAD_BUFFER;
+        case GRALLOC1_ERROR_BAD_VALUE:
+            return Error::BAD_VALUE;
+        case GRALLOC1_ERROR_NOT_SHARED:
+            return Error::NONE;  // this is fine
+        case GRALLOC1_ERROR_NO_RESOURCES:
+            return Error::NO_RESOURCES;
+        case GRALLOC1_ERROR_UNDEFINED:
+        case GRALLOC1_ERROR_UNSUPPORTED:
+        default:
+            return Error::UNSUPPORTED;
+    }
+}
+
+uint64_t Gralloc1Hal::toProducerUsage(uint64_t usage) {
+    // this is potentially broken as we have no idea which private flags
+    // should be filtered out
+    uint64_t producerUsage =
+        usage & ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+                                       BufferUsage::GPU_DATA_BUFFER);
+
+    switch (usage & BufferUsage::CPU_WRITE_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    switch (usage & BufferUsage::CPU_READ_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    // BufferUsage::GPU_DATA_BUFFER is always filtered out
+
+    return producerUsage;
+}
+
+uint64_t Gralloc1Hal::toConsumerUsage(uint64_t usage) {
+    // this is potentially broken as we have no idea which private flags
+    // should be filtered out
+    uint64_t consumerUsage =
+        usage &
+        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+                               BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
+
+    switch (usage & BufferUsage::CPU_READ_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
+
+    if (usage & BufferUsage::GPU_DATA_BUFFER) {
+        consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
+    }
+
+    return consumerUsage;
+}
+
+Error Gralloc1Hal::createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                                    gralloc1_buffer_descriptor_t* outDescriptor) {
+    gralloc1_buffer_descriptor_t descriptor;
+
+    int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setDimensions(mDevice, descriptor, info.width, info.height);
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setFormat(mDevice, descriptor, static_cast<int32_t>(info.format));
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        if (mCapabilities.layeredBuffers) {
+            error = mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
+        } else if (info.layerCount > 1) {
+            error = GRALLOC1_ERROR_UNSUPPORTED;
+        }
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setProducerUsage(mDevice, descriptor, toProducerUsage(info.usage));
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setConsumerUsage(mDevice, descriptor, toConsumerUsage(info.usage));
+    }
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        *outDescriptor = descriptor;
+    } else {
+        mDispatch.destroyDescriptor(mDevice, descriptor);
+    }
+
+    return toError(error);
+}
+
+Error Gralloc1Hal::allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
+                                     const native_handle_t** outBuffer, uint32_t* outStride) {
+    const native_handle_t* buffer = nullptr;
+    int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
+    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
+        return toError(error);
+    }
+
+    uint32_t stride = 0;
+    error = mDispatch.getStride(mDevice, buffer, &stride);
+    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
+        mDispatch.release(mDevice, buffer);
+        return toError(error);
+    }
+
+    *outBuffer = buffer;
+    *outStride = stride;
+
+    return Error::NONE;
+}
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp b/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp
new file mode 100644
index 0000000..dae7a78
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017 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 <allocator-passthrough/2.0/GrallocLoader.h>
+
+#include <allocator-hal/2.0/Allocator.h>
+#include <allocator-hal/2.0/AllocatorHal.h>
+#include <allocator-passthrough/2.0/Gralloc0Hal.h>
+#include <allocator-passthrough/2.0/Gralloc1Hal.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+const hw_module_t* GrallocLoader::loadModule() {
+    const hw_module_t* module;
+    int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    if (error) {
+        ALOGE("failed to get gralloc module");
+        return nullptr;
+    }
+
+    return module;
+}
+
+int GrallocLoader::getModuleMajorApiVersion(const hw_module_t* module) {
+    return (module->module_api_version >> 8) & 0xff;
+}
+
+std::unique_ptr<hal::AllocatorHal> GrallocLoader::createHal(const hw_module_t* module) {
+    int major = getModuleMajorApiVersion(module);
+    switch (major) {
+        case 1: {
+            auto hal = std::make_unique<Gralloc1Hal>();
+            return hal->initWithModule(module) ? std::move(hal) : nullptr;
+        }
+        case 0: {
+            auto hal = std::make_unique<Gralloc0Hal>();
+            return hal->initWithModule(module) ? std::move(hal) : nullptr;
+        }
+        default:
+            ALOGE("unknown gralloc module major version %d", major);
+            return nullptr;
+    }
+}
+
+IAllocator* GrallocLoader::createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
+    auto allocator = std::make_unique<hal::Allocator>();
+    return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
+}
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
new file mode 100644
index 0000000..8f433b0
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+
+struct alloc_device_t;
+struct hw_module_t;
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+class Gralloc0Hal : public virtual hal::AllocatorHal {
+   public:
+    ~Gralloc0Hal();
+    bool initWithModule(const hw_module_t* module);
+
+    std::string dumpDebugInfo() override;
+
+    Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
+                          std::vector<const native_handle_t*>* outBuffers) override;
+
+    void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+
+   protected:
+    Error allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                            const native_handle_t** outBuffer, uint32_t* outStride);
+
+    alloc_device_t* mDevice = nullptr;
+};
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
new file mode 100644
index 0000000..3126e91
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+#include <hardware/gralloc1.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+class Gralloc1Hal : public virtual hal::AllocatorHal {
+   public:
+    ~Gralloc1Hal();
+    bool initWithModule(const hw_module_t* module);
+
+    std::string dumpDebugInfo() override;
+
+    Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
+                          std::vector<const native_handle_t*>* outBuffers) override;
+
+    void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+
+   protected:
+    template <typename T>
+    bool initDispatchFunction(gralloc1_function_descriptor_t desc, T* outPfn) {
+        auto pfn = getDispatchFunction(desc);
+        if (pfn) {
+            *outPfn = reinterpret_cast<T>(pfn);
+            return true;
+        } else {
+            return false;
+        }
+    }
+    gralloc1_function_pointer_t getDispatchFunction(gralloc1_function_descriptor_t desc) const;
+
+    virtual void initCapabilities();
+    virtual bool initDispatch();
+
+    static Error toError(int32_t error);
+    static uint64_t toProducerUsage(uint64_t usage);
+    static uint64_t toConsumerUsage(uint64_t usage);
+
+    Error createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                           gralloc1_buffer_descriptor_t* outDescriptor);
+
+    Error allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
+                            const native_handle_t** outBuffer, uint32_t* outStride);
+
+    gralloc1_device_t* mDevice = nullptr;
+
+    struct {
+        bool layeredBuffers;
+    } mCapabilities = {};
+
+    struct {
+        GRALLOC1_PFN_DUMP dump;
+        GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
+        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_GET_STRIDE getStride;
+        GRALLOC1_PFN_ALLOCATE allocate;
+        GRALLOC1_PFN_RELEASE release;
+    } mDispatch = {};
+};
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
new file mode 100644
index 0000000..a0b9503
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+
+struct hw_module_t;
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+class GrallocLoader {
+   public:
+    static IAllocator* load() {
+        const hw_module_t* module = loadModule();
+        if (!module) {
+            return nullptr;
+        }
+        auto hal = createHal(module);
+        if (!hal) {
+            return nullptr;
+        }
+        return createAllocator(std::move(hal));
+    }
+
+    // load the gralloc module
+    static const hw_module_t* loadModule();
+
+    // return the major api version of the module
+    static int getModuleMajorApiVersion(const hw_module_t* module);
+
+    // create an AllocatorHal instance
+    static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module);
+
+    // create an IAllocator instance
+    static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal);
+};
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/common/1.1/Android.bp b/graphics/common/1.1/Android.bp
new file mode 100644
index 0000000..c319d80
--- /dev/null
+++ b/graphics/common/1.1/Android.bp
@@ -0,0 +1,24 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.graphics.common@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    srcs: [
+        "types.hal",
+    ],
+    interfaces: [
+        "android.hardware.graphics.common@1.0",
+    ],
+    types: [
+        "BufferUsage",
+        "Dataspace",
+        "PixelFormat",
+    ],
+    gen_java: true,
+    gen_java_constants: true,
+}
+
diff --git a/graphics/common/1.1/types.hal b/graphics/common/1.1/types.hal
new file mode 100644
index 0000000..b917d5e
--- /dev/null
+++ b/graphics/common/1.1/types.hal
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2018 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.graphics.common@1.1;
+
+import @1.0::PixelFormat;
+import @1.0::BufferUsage;
+import @1.0::Dataspace;
+
+/**
+ * Pixel formats for graphics buffers.
+ */
+@export(name="android_pixel_format_v1_1_t", value_prefix="HAL_PIXEL_FORMAT_",
+        export_parent="false")
+enum PixelFormat : @1.0::PixelFormat {
+    /**
+     * 16-bit format that has a single 16-bit depth component.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    DEPTH_16           = 0x30,
+
+    /**
+     * 32-bit format that has a single 24-bit depth component and, optionally,
+     * 8 bits that are unused.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    DEPTH_24           = 0x31,
+
+    /**
+     * 32-bit format that has a 24-bit depth component and an 8-bit stencil
+     * component packed into 32-bits.
+     *
+     * The depth component values are unsigned normalized to the range [0, 1],
+     * whose interpretation is defined by the dataspace. The stencil values are
+     * unsigned integers, whose interpretation is defined by the dataspace.
+     */
+    DEPTH_24_STENCIL_8  = 0x32,
+
+    /**
+     * 32-bit format that has a single 32-bit depth component.
+     *
+     * The component values are signed floats, whose interpretation is defined
+     * by the dataspace.
+     */
+    DEPTH_32F           = 0x33,
+
+    /**
+     * Two-component format that has a 32-bit depth component, an 8-bit stencil
+     * component, and optionally 24-bits unused.
+     *
+     * The depth component values are signed floats, whose interpretation is
+     * defined by the dataspace. The stencil bits are unsigned integers, whose
+     * interpretation is defined by the dataspace.
+     */
+    DEPTH_32F_STENCIL_8 = 0x34,
+
+    /**
+     * 8-bit format that has a single 8-bit stencil component.
+     *
+     * The component values are unsigned integers, whose interpretation is
+     * defined by the dataspace.
+     */
+    STENCIL_8           = 0x35,
+
+    /**
+     * P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane
+     * followed immediately by a Wx(H/2) CbCr plane. Each sample is
+     * represented by a 16-bit little-endian value, with the lower 6 bits set
+     * to zero.
+     *
+     * This format assumes
+     * - an even height
+     * - a vertical stride equal to the height
+     *
+     *   stride_in_bytes = stride * 2
+     *   y_size = stride_in_bytes * height
+     *   cbcr_size = stride_in_bytes * (height / 2)
+     *   cb_offset = y_size
+     *   cr_offset = cb_offset + 2
+     *
+     * This format must be accepted by the allocator when used with the
+     * following usage flags:
+     *
+     *    - BufferUsage::VIDEO_*
+     *    - BufferUsage::CPU_*
+     *    - BufferUsage::GPU_TEXTURE
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     *
+     * This format is appropriate for 10bit video content.
+     *
+     * Buffers with this format must be locked with IMapper::lockYCbCr
+     * or with IMapper::lock.
+     */
+    YCBCR_P010          = 0x36,
+};
+
+/**
+ * Buffer usage definitions.
+ */
+enum BufferUsage : @1.0::BufferUsage {
+    /** buffer is used as a cube map texture */
+    GPU_CUBE_MAP          = 1ULL << 25,
+
+    /** buffer contains a complete mipmap hierarchy */
+    GPU_MIPMAP_COMPLETE   = 1ULL << 26,
+
+    /** bits 27 and 32-47 must be zero and are reserved for future versions */
+};
+
+@export(name="android_dataspace_v1_1_t", value_prefix="HAL_DATASPACE_",
+        export_parent="false")
+enum Dataspace : @1.0::Dataspace {
+    /**
+     * ITU-R Recommendation 2020 (BT.2020)
+     *
+     * Ultra High-definition television
+     *
+     * Use limited range, SMPTE 2084 (PQ) transfer and BT2020 standard
+     * limited range is the preferred / normative definition for BT.2020
+     */
+    BT2020_ITU = STANDARD_BT2020 | TRANSFER_SMPTE_170M | RANGE_LIMITED,
+
+    BT2020_ITU_PQ = STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_LIMITED,
+};
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index 140e50e..b46a1de 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -17,6 +17,9 @@
         "libsync",
         "libutils",
     ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
 }
 
 cc_library_shared {
@@ -41,6 +44,9 @@
         "libhwc2on1adapter",
         "libhwc2onfbadapter",
     ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
 }
 
 cc_binary {
@@ -65,10 +71,3 @@
         "libutils",
     ],
 }
-
-cc_library_static {
-    name: "libhwcomposer-command-buffer",
-    defaults: ["hidl_defaults"],
-    shared_libs: ["android.hardware.graphics.composer@2.1"],
-    export_include_dirs: ["."],
-}
diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp
index 4e6dd4f..0fcb9de 100644
--- a/graphics/composer/2.1/default/ComposerClient.cpp
+++ b/graphics/composer/2.1/default/ComposerClient.cpp
@@ -19,9 +19,8 @@
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <log/log.h>
 
-#include "ComposerClient.h"
 #include "ComposerBase.h"
-#include "IComposerCommandBuffer.h"
+#include "ComposerClient.h"
 
 namespace android {
 namespace hardware {
@@ -299,10 +298,17 @@
     Error err = mHal.createLayer(display, &layer);
     if (err == Error::NONE) {
         std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
         auto dpy = mDisplayData.find(display);
-        auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first;
-        ly->second.Buffers.resize(bufferSlotCount);
+        // The display entry may have already been removed by onHotplug.
+        if (dpy != mDisplayData.end()) {
+            auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first;
+            ly->second.Buffers.resize(bufferSlotCount);
+        } else {
+            err = Error::BAD_DISPLAY;
+            // Note: We do not destroy the layer on this error as the hotplug
+            // disconnect invalidates the display id. The implementation should
+            // ensure all layers for the display are destroyed.
+        }
     }
 
     hidl_cb(err, layer);
@@ -316,7 +322,10 @@
         std::lock_guard<std::mutex> lock(mDisplayDataMutex);
 
         auto dpy = mDisplayData.find(display);
-        dpy->second.Layers.erase(layer);
+        // The display entry may have already been removed by onHotplug.
+        if (dpy != mDisplayData.end()) {
+            dpy->second.Layers.erase(layer);
+        }
     }
 
     return err;
diff --git a/graphics/composer/2.1/default/ComposerClient.h b/graphics/composer/2.1/default/ComposerClient.h
index fc5c223..104ed5a 100644
--- a/graphics/composer/2.1/default/ComposerClient.h
+++ b/graphics/composer/2.1/default/ComposerClient.h
@@ -21,8 +21,8 @@
 #include <unordered_map>
 #include <vector>
 
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
 #include <hardware/hwcomposer2.h>
-#include "IComposerCommandBuffer.h"
 #include "ComposerBase.h"
 
 namespace android {
diff --git a/graphics/composer/2.1/default/OWNERS b/graphics/composer/2.1/default/OWNERS
index 3aa5fa1..4714be2 100644
--- a/graphics/composer/2.1/default/OWNERS
+++ b/graphics/composer/2.1/default/OWNERS
@@ -1,4 +1,5 @@
 # Graphics team
+courtneygo@google.com
 jessehall@google.com
 olv@google.com
 stoza@google.com
diff --git a/graphics/composer/2.1/utils/OWNERS b/graphics/composer/2.1/utils/OWNERS
new file mode 100644
index 0000000..d515a23
--- /dev/null
+++ b/graphics/composer/2.1/utils/OWNERS
@@ -0,0 +1,4 @@
+courtneygo@google.com
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/composer/2.1/utils/command-buffer/Android.bp b/graphics/composer/2.1/utils/command-buffer/Android.bp
new file mode 100644
index 0000000..e8d41c2
--- /dev/null
+++ b/graphics/composer/2.1/utils/command-buffer/Android.bp
@@ -0,0 +1,7 @@
+cc_library_headers {
+    name: "android.hardware.graphics.composer@2.1-command-buffer",
+    defaults: ["hidl_defaults"],
+    vendor_available: true,
+    shared_libs: ["android.hardware.graphics.composer@2.1"],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.1/default/IComposerCommandBuffer.h b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
similarity index 69%
rename from graphics/composer/2.1/default/IComposerCommandBuffer.h
rename to graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
index c752f8a..df529ec 100644
--- a/graphics/composer/2.1/default/IComposerCommandBuffer.h
+++ b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
@@ -18,7 +18,7 @@
 #define ANDROID_HARDWARE_GRAPHICS_COMPOSER_COMMAND_BUFFER_H
 
 #ifndef LOG_TAG
-#warn "IComposerCommandBuffer.h included without LOG_TAG"
+#warn "ComposerCommandBuffer.h included without LOG_TAG"
 #endif
 
 #undef LOG_NDEBUG
@@ -33,9 +33,9 @@
 #include <string.h>
 
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <fmq/MessageQueue.h>
 #include <log/log.h>
 #include <sync/sync.h>
-#include <fmq/MessageQueue.h>
 
 namespace android {
 namespace hardware {
@@ -53,21 +53,15 @@
 // This class helps build a command queue.  Note that all sizes/lengths are in
 // units of uint32_t's.
 class CommandWriterBase {
-public:
-    CommandWriterBase(uint32_t initialMaxSize)
-        : mDataMaxSize(initialMaxSize)
-    {
+   public:
+    CommandWriterBase(uint32_t initialMaxSize) : mDataMaxSize(initialMaxSize) {
         mData = std::make_unique<uint32_t[]>(mDataMaxSize);
         reset();
     }
 
-    virtual ~CommandWriterBase()
-    {
-        reset();
-    }
+    virtual ~CommandWriterBase() { reset(); }
 
-    void reset()
-    {
+    void reset() {
         mDataWritten = 0;
         mCommandEnd = 0;
 
@@ -82,16 +76,14 @@
         mTemporaryHandles.clear();
     }
 
-    IComposerClient::Command getCommand(uint32_t offset)
-    {
+    IComposerClient::Command getCommand(uint32_t offset) {
         uint32_t val = (offset < mDataWritten) ? mData[offset] : 0;
-        return static_cast<IComposerClient::Command>(val &
-                static_cast<uint32_t>(IComposerClient::Command::OPCODE_MASK));
+        return static_cast<IComposerClient::Command>(
+            val & static_cast<uint32_t>(IComposerClient::Command::OPCODE_MASK));
     }
 
     bool writeQueue(bool* outQueueChanged, uint32_t* outCommandLength,
-            hidl_vec<hidl_handle>* outCommandHandles)
-    {
+                    hidl_vec<hidl_handle>* outCommandHandles) {
         if (mDataWritten == 0) {
             *outQueueChanged = false;
             *outCommandLength = 0;
@@ -126,8 +118,7 @@
             *outQueueChanged = false;
         } else {
             auto newQueue = std::make_unique<CommandQueueType>(mDataMaxSize);
-            if (!newQueue->isValid() ||
-                    !newQueue->write(mData.get(), mDataWritten)) {
+            if (!newQueue->isValid() || !newQueue->write(mData.get(), mDataWritten)) {
                 ALOGE("failed to prepare a new message queue ");
                 return false;
             }
@@ -137,39 +128,32 @@
         }
 
         *outCommandLength = mDataWritten;
-        outCommandHandles->setToExternal(
-                const_cast<hidl_handle*>(mDataHandles.data()),
-                mDataHandles.size());
+        outCommandHandles->setToExternal(const_cast<hidl_handle*>(mDataHandles.data()),
+                                         mDataHandles.size());
 
         return true;
     }
 
-    const MQDescriptorSync<uint32_t>* getMQDescriptor() const
-    {
+    const MQDescriptorSync<uint32_t>* getMQDescriptor() const {
         return (mQueue) ? mQueue->getDesc() : nullptr;
     }
 
     static constexpr uint16_t kSelectDisplayLength = 2;
-    void selectDisplay(Display display)
-    {
-        beginCommand(IComposerClient::Command::SELECT_DISPLAY,
-                kSelectDisplayLength);
+    void selectDisplay(Display display) {
+        beginCommand(IComposerClient::Command::SELECT_DISPLAY, kSelectDisplayLength);
         write64(display);
         endCommand();
     }
 
     static constexpr uint16_t kSelectLayerLength = 2;
-    void selectLayer(Layer layer)
-    {
-        beginCommand(IComposerClient::Command::SELECT_LAYER,
-                kSelectLayerLength);
+    void selectLayer(Layer layer) {
+        beginCommand(IComposerClient::Command::SELECT_LAYER, kSelectLayerLength);
         write64(layer);
         endCommand();
     }
 
     static constexpr uint16_t kSetErrorLength = 2;
-    void setError(uint32_t location, Error error)
-    {
+    void setError(uint32_t location, Error error) {
         beginCommand(IComposerClient::Command::SET_ERROR, kSetErrorLength);
         write(location);
         writeSigned(static_cast<int32_t>(error));
@@ -177,25 +161,23 @@
     }
 
     static constexpr uint32_t kPresentOrValidateDisplayResultLength = 1;
-    void setPresentOrValidateResult(uint32_t  state) {
-       beginCommand(IComposerClient::Command::SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT, kPresentOrValidateDisplayResultLength);
-       write(state);
-       endCommand();
+    void setPresentOrValidateResult(uint32_t state) {
+        beginCommand(IComposerClient::Command::SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT,
+                     kPresentOrValidateDisplayResultLength);
+        write(state);
+        endCommand();
     }
 
     void setChangedCompositionTypes(const std::vector<Layer>& layers,
-            const std::vector<IComposerClient::Composition>& types)
-    {
+                                    const std::vector<IComposerClient::Composition>& types) {
         size_t totalLayers = std::min(layers.size(), types.size());
         size_t currentLayer = 0;
 
         while (currentLayer < totalLayers) {
-            size_t count = std::min(totalLayers - currentLayer,
-                    static_cast<size_t>(kMaxLength) / 3);
+            size_t count =
+                std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength) / 3);
 
-            beginCommand(
-                    IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES,
-                    count * 3);
+            beginCommand(IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES, count * 3);
             for (size_t i = 0; i < count; i++) {
                 write64(layers[currentLayer + i]);
                 writeSigned(static_cast<int32_t>(types[currentLayer + i]));
@@ -206,20 +188,16 @@
         }
     }
 
-    void setDisplayRequests(uint32_t displayRequestMask,
-            const std::vector<Layer>& layers,
-            const std::vector<uint32_t>& layerRequestMasks)
-    {
-        size_t totalLayers = std::min(layers.size(),
-                layerRequestMasks.size());
+    void setDisplayRequests(uint32_t displayRequestMask, const std::vector<Layer>& layers,
+                            const std::vector<uint32_t>& layerRequestMasks) {
+        size_t totalLayers = std::min(layers.size(), layerRequestMasks.size());
         size_t currentLayer = 0;
 
         while (currentLayer < totalLayers) {
-            size_t count = std::min(totalLayers - currentLayer,
-                    static_cast<size_t>(kMaxLength - 1) / 3);
+            size_t count =
+                std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength - 1) / 3);
 
-            beginCommand(IComposerClient::Command::SET_DISPLAY_REQUESTS,
-                    1 + count * 3);
+            beginCommand(IComposerClient::Command::SET_DISPLAY_REQUESTS, 1 + count * 3);
             write(displayRequestMask);
             for (size_t i = 0; i < count; i++) {
                 write64(layers[currentLayer + i]);
@@ -232,26 +210,21 @@
     }
 
     static constexpr uint16_t kSetPresentFenceLength = 1;
-    void setPresentFence(int presentFence)
-    {
-        beginCommand(IComposerClient::Command::SET_PRESENT_FENCE,
-                kSetPresentFenceLength);
+    void setPresentFence(int presentFence) {
+        beginCommand(IComposerClient::Command::SET_PRESENT_FENCE, kSetPresentFenceLength);
         writeFence(presentFence);
         endCommand();
     }
 
-    void setReleaseFences(const std::vector<Layer>& layers,
-            const std::vector<int>& releaseFences)
-    {
+    void setReleaseFences(const std::vector<Layer>& layers, const std::vector<int>& releaseFences) {
         size_t totalLayers = std::min(layers.size(), releaseFences.size());
         size_t currentLayer = 0;
 
         while (currentLayer < totalLayers) {
-            size_t count = std::min(totalLayers - currentLayer,
-                    static_cast<size_t>(kMaxLength) / 3);
+            size_t count =
+                std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength) / 3);
 
-            beginCommand(IComposerClient::Command::SET_RELEASE_FENCES,
-                    count * 3);
+            beginCommand(IComposerClient::Command::SET_RELEASE_FENCES, count * 3);
             for (size_t i = 0; i < count; i++) {
                 write64(layers[currentLayer + i]);
                 writeFence(releaseFences[currentLayer + i]);
@@ -263,10 +236,8 @@
     }
 
     static constexpr uint16_t kSetColorTransformLength = 17;
-    void setColorTransform(const float* matrix, ColorTransform hint)
-    {
-        beginCommand(IComposerClient::Command::SET_COLOR_TRANSFORM,
-                kSetColorTransformLength);
+    void setColorTransform(const float* matrix, ColorTransform hint) {
+        beginCommand(IComposerClient::Command::SET_COLOR_TRANSFORM, kSetColorTransformLength);
         for (int i = 0; i < 16; i++) {
             writeFloat(matrix[i]);
         }
@@ -274,10 +245,8 @@
         endCommand();
     }
 
-    void setClientTarget(uint32_t slot, const native_handle_t* target,
-            int acquireFence, Dataspace dataspace,
-            const std::vector<IComposerClient::Rect>& damage)
-    {
+    void setClientTarget(uint32_t slot, const native_handle_t* target, int acquireFence,
+                         Dataspace dataspace, const std::vector<IComposerClient::Rect>& damage) {
         bool doWrite = (damage.size() <= (kMaxLength - 4) / 4);
         size_t length = 4 + ((doWrite) ? damage.size() * 4 : 0);
 
@@ -296,11 +265,8 @@
     }
 
     static constexpr uint16_t kSetOutputBufferLength = 3;
-    void setOutputBuffer(uint32_t slot, const native_handle_t* buffer,
-            int releaseFence)
-    {
-        beginCommand(IComposerClient::Command::SET_OUTPUT_BUFFER,
-                kSetOutputBufferLength);
+    void setOutputBuffer(uint32_t slot, const native_handle_t* buffer, int releaseFence) {
+        beginCommand(IComposerClient::Command::SET_OUTPUT_BUFFER, kSetOutputBufferLength);
         write(slot);
         writeHandle(buffer, true);
         writeFence(releaseFence);
@@ -308,67 +274,53 @@
     }
 
     static constexpr uint16_t kValidateDisplayLength = 0;
-    void validateDisplay()
-    {
-        beginCommand(IComposerClient::Command::VALIDATE_DISPLAY,
-                kValidateDisplayLength);
+    void validateDisplay() {
+        beginCommand(IComposerClient::Command::VALIDATE_DISPLAY, kValidateDisplayLength);
         endCommand();
     }
 
     static constexpr uint16_t kPresentOrValidateDisplayLength = 0;
-    void presentOrvalidateDisplay()
-    {
+    void presentOrvalidateDisplay() {
         beginCommand(IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY,
                      kPresentOrValidateDisplayLength);
         endCommand();
     }
 
     static constexpr uint16_t kAcceptDisplayChangesLength = 0;
-    void acceptDisplayChanges()
-    {
-        beginCommand(IComposerClient::Command::ACCEPT_DISPLAY_CHANGES,
-                kAcceptDisplayChangesLength);
+    void acceptDisplayChanges() {
+        beginCommand(IComposerClient::Command::ACCEPT_DISPLAY_CHANGES, kAcceptDisplayChangesLength);
         endCommand();
     }
 
     static constexpr uint16_t kPresentDisplayLength = 0;
-    void presentDisplay()
-    {
-        beginCommand(IComposerClient::Command::PRESENT_DISPLAY,
-                kPresentDisplayLength);
+    void presentDisplay() {
+        beginCommand(IComposerClient::Command::PRESENT_DISPLAY, kPresentDisplayLength);
         endCommand();
     }
 
     static constexpr uint16_t kSetLayerCursorPositionLength = 2;
-    void setLayerCursorPosition(int32_t x, int32_t y)
-    {
+    void setLayerCursorPosition(int32_t x, int32_t y) {
         beginCommand(IComposerClient::Command::SET_LAYER_CURSOR_POSITION,
-                kSetLayerCursorPositionLength);
+                     kSetLayerCursorPositionLength);
         writeSigned(x);
         writeSigned(y);
         endCommand();
     }
 
     static constexpr uint16_t kSetLayerBufferLength = 3;
-    void setLayerBuffer(uint32_t slot, const native_handle_t* buffer,
-            int acquireFence)
-    {
-        beginCommand(IComposerClient::Command::SET_LAYER_BUFFER,
-                kSetLayerBufferLength);
+    void setLayerBuffer(uint32_t slot, const native_handle_t* buffer, int acquireFence) {
+        beginCommand(IComposerClient::Command::SET_LAYER_BUFFER, kSetLayerBufferLength);
         write(slot);
         writeHandle(buffer, true);
         writeFence(acquireFence);
         endCommand();
     }
 
-    void setLayerSurfaceDamage(
-            const std::vector<IComposerClient::Rect>& damage)
-    {
+    void setLayerSurfaceDamage(const std::vector<IComposerClient::Rect>& damage) {
         bool doWrite = (damage.size() <= kMaxLength / 4);
         size_t length = (doWrite) ? damage.size() * 4 : 0;
 
-        beginCommand(IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE,
-                length);
+        beginCommand(IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE, length);
         // When there are too many rectangles in the damage region and doWrite
         // is false, we write no rectangle at all which means the entire
         // layer is damaged.
@@ -379,94 +331,76 @@
     }
 
     static constexpr uint16_t kSetLayerBlendModeLength = 1;
-    void setLayerBlendMode(IComposerClient::BlendMode mode)
-    {
-        beginCommand(IComposerClient::Command::SET_LAYER_BLEND_MODE,
-                kSetLayerBlendModeLength);
+    void setLayerBlendMode(IComposerClient::BlendMode mode) {
+        beginCommand(IComposerClient::Command::SET_LAYER_BLEND_MODE, kSetLayerBlendModeLength);
         writeSigned(static_cast<int32_t>(mode));
         endCommand();
     }
 
     static constexpr uint16_t kSetLayerColorLength = 1;
-    void setLayerColor(IComposerClient::Color color)
-    {
-        beginCommand(IComposerClient::Command::SET_LAYER_COLOR,
-                kSetLayerColorLength);
+    void setLayerColor(IComposerClient::Color color) {
+        beginCommand(IComposerClient::Command::SET_LAYER_COLOR, kSetLayerColorLength);
         writeColor(color);
         endCommand();
     }
 
     static constexpr uint16_t kSetLayerCompositionTypeLength = 1;
-    void setLayerCompositionType(IComposerClient::Composition type)
-    {
+    void setLayerCompositionType(IComposerClient::Composition type) {
         beginCommand(IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE,
-                kSetLayerCompositionTypeLength);
+                     kSetLayerCompositionTypeLength);
         writeSigned(static_cast<int32_t>(type));
         endCommand();
     }
 
     static constexpr uint16_t kSetLayerDataspaceLength = 1;
-    void setLayerDataspace(Dataspace dataspace)
-    {
-        beginCommand(IComposerClient::Command::SET_LAYER_DATASPACE,
-                kSetLayerDataspaceLength);
+    void setLayerDataspace(Dataspace dataspace) {
+        beginCommand(IComposerClient::Command::SET_LAYER_DATASPACE, kSetLayerDataspaceLength);
         writeSigned(static_cast<int32_t>(dataspace));
         endCommand();
     }
 
     static constexpr uint16_t kSetLayerDisplayFrameLength = 4;
-    void setLayerDisplayFrame(const IComposerClient::Rect& frame)
-    {
+    void setLayerDisplayFrame(const IComposerClient::Rect& frame) {
         beginCommand(IComposerClient::Command::SET_LAYER_DISPLAY_FRAME,
-                kSetLayerDisplayFrameLength);
+                     kSetLayerDisplayFrameLength);
         writeRect(frame);
         endCommand();
     }
 
     static constexpr uint16_t kSetLayerPlaneAlphaLength = 1;
-    void setLayerPlaneAlpha(float alpha)
-    {
-        beginCommand(IComposerClient::Command::SET_LAYER_PLANE_ALPHA,
-                kSetLayerPlaneAlphaLength);
+    void setLayerPlaneAlpha(float alpha) {
+        beginCommand(IComposerClient::Command::SET_LAYER_PLANE_ALPHA, kSetLayerPlaneAlphaLength);
         writeFloat(alpha);
         endCommand();
     }
 
     static constexpr uint16_t kSetLayerSidebandStreamLength = 1;
-    void setLayerSidebandStream(const native_handle_t* stream)
-    {
+    void setLayerSidebandStream(const native_handle_t* stream) {
         beginCommand(IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM,
-                kSetLayerSidebandStreamLength);
+                     kSetLayerSidebandStreamLength);
         writeHandle(stream);
         endCommand();
     }
 
     static constexpr uint16_t kSetLayerSourceCropLength = 4;
-    void setLayerSourceCrop(const IComposerClient::FRect& crop)
-    {
-        beginCommand(IComposerClient::Command::SET_LAYER_SOURCE_CROP,
-                kSetLayerSourceCropLength);
+    void setLayerSourceCrop(const IComposerClient::FRect& crop) {
+        beginCommand(IComposerClient::Command::SET_LAYER_SOURCE_CROP, kSetLayerSourceCropLength);
         writeFRect(crop);
         endCommand();
     }
 
     static constexpr uint16_t kSetLayerTransformLength = 1;
-    void setLayerTransform(Transform transform)
-    {
-        beginCommand(IComposerClient::Command::SET_LAYER_TRANSFORM,
-                kSetLayerTransformLength);
+    void setLayerTransform(Transform transform) {
+        beginCommand(IComposerClient::Command::SET_LAYER_TRANSFORM, kSetLayerTransformLength);
         writeSigned(static_cast<int32_t>(transform));
         endCommand();
     }
 
-    void setLayerVisibleRegion(
-            const std::vector<IComposerClient::Rect>& visible)
-    {
+    void setLayerVisibleRegion(const std::vector<IComposerClient::Rect>& visible) {
         bool doWrite = (visible.size() <= kMaxLength / 4);
         size_t length = (doWrite) ? visible.size() * 4 : 0;
 
-        beginCommand(IComposerClient::Command::SET_LAYER_VISIBLE_REGION,
-                length);
+        beginCommand(IComposerClient::Command::SET_LAYER_VISIBLE_REGION, length);
         // When there are too many rectangles in the visible region and
         // doWrite is false, we write no rectangle at all which means the
         // entire layer is visible.
@@ -477,20 +411,16 @@
     }
 
     static constexpr uint16_t kSetLayerZOrderLength = 1;
-    void setLayerZOrder(uint32_t z)
-    {
-        beginCommand(IComposerClient::Command::SET_LAYER_Z_ORDER,
-                kSetLayerZOrderLength);
+    void setLayerZOrder(uint32_t z) {
+        beginCommand(IComposerClient::Command::SET_LAYER_Z_ORDER, kSetLayerZOrderLength);
         write(z);
         endCommand();
     }
 
-protected:
-    void beginCommand(IComposerClient::Command command, uint16_t length)
-    {
+   protected:
+    void beginCommand(IComposerClient::Command command, uint16_t length) {
         if (mCommandEnd) {
-            LOG_FATAL("endCommand was not called before command 0x%x",
-                    command);
+            LOG_FATAL("endCommand was not called before command 0x%x", command);
         }
 
         growData(1 + length);
@@ -499,8 +429,7 @@
         mCommandEnd = mDataWritten + length;
     }
 
-    void endCommand()
-    {
+    void endCommand() {
         if (!mCommandEnd) {
             LOG_FATAL("beginCommand was not called");
         } else if (mDataWritten > mCommandEnd) {
@@ -516,67 +445,48 @@
         mCommandEnd = 0;
     }
 
-    void write(uint32_t val)
-    {
-        mData[mDataWritten++] = val;
-    }
+    void write(uint32_t val) { mData[mDataWritten++] = val; }
 
-    void writeSigned(int32_t val)
-    {
-        memcpy(&mData[mDataWritten++], &val, sizeof(val));
-    }
+    void writeSigned(int32_t val) { memcpy(&mData[mDataWritten++], &val, sizeof(val)); }
 
-    void writeFloat(float val)
-    {
-        memcpy(&mData[mDataWritten++], &val, sizeof(val));
-    }
+    void writeFloat(float val) { memcpy(&mData[mDataWritten++], &val, sizeof(val)); }
 
-    void write64(uint64_t val)
-    {
+    void write64(uint64_t val) {
         uint32_t lo = static_cast<uint32_t>(val & 0xffffffff);
         uint32_t hi = static_cast<uint32_t>(val >> 32);
         write(lo);
         write(hi);
     }
 
-    void writeRect(const IComposerClient::Rect& rect)
-    {
+    void writeRect(const IComposerClient::Rect& rect) {
         writeSigned(rect.left);
         writeSigned(rect.top);
         writeSigned(rect.right);
         writeSigned(rect.bottom);
     }
 
-    void writeRegion(const std::vector<IComposerClient::Rect>& region)
-    {
+    void writeRegion(const std::vector<IComposerClient::Rect>& region) {
         for (const auto& rect : region) {
             writeRect(rect);
         }
     }
 
-    void writeFRect(const IComposerClient::FRect& rect)
-    {
+    void writeFRect(const IComposerClient::FRect& rect) {
         writeFloat(rect.left);
         writeFloat(rect.top);
         writeFloat(rect.right);
         writeFloat(rect.bottom);
     }
 
-    void writeColor(const IComposerClient::Color& color)
-    {
-        write((color.r <<  0) |
-              (color.g <<  8) |
-              (color.b << 16) |
-              (color.a << 24));
+    void writeColor(const IComposerClient::Color& color) {
+        write((color.r << 0) | (color.g << 8) | (color.b << 16) | (color.a << 24));
     }
 
     // ownership of handle is not transferred
-    void writeHandle(const native_handle_t* handle, bool useCache)
-    {
+    void writeHandle(const native_handle_t* handle, bool useCache) {
         if (!handle) {
-            writeSigned(static_cast<int32_t>((useCache) ?
-                        IComposerClient::HandleIndex::CACHED :
-                        IComposerClient::HandleIndex::EMPTY));
+            writeSigned(static_cast<int32_t>((useCache) ? IComposerClient::HandleIndex::CACHED
+                                                        : IComposerClient::HandleIndex::EMPTY));
             return;
         }
 
@@ -584,14 +494,10 @@
         writeSigned(mDataHandles.size() - 1);
     }
 
-    void writeHandle(const native_handle_t* handle)
-    {
-        writeHandle(handle, false);
-    }
+    void writeHandle(const native_handle_t* handle) { writeHandle(handle, false); }
 
     // ownership of fence is transferred
-    void writeFence(int fence)
-    {
+    void writeFence(int fence) {
         native_handle_t* handle = nullptr;
         if (fence >= 0) {
             handle = getTemporaryHandle(1, 0);
@@ -607,8 +513,7 @@
         writeHandle(handle);
     }
 
-    native_handle_t* getTemporaryHandle(int numFds, int numInts)
-    {
+    native_handle_t* getTemporaryHandle(int numFds, int numInts) {
         native_handle_t* handle = native_handle_create(numFds, numInts);
         if (handle) {
             mTemporaryHandles.push_back(handle);
@@ -616,16 +521,14 @@
         return handle;
     }
 
-    static constexpr uint16_t kMaxLength =
-        std::numeric_limits<uint16_t>::max();
+    static constexpr uint16_t kMaxLength = std::numeric_limits<uint16_t>::max();
 
-private:
-    void growData(uint32_t grow)
-    {
+   private:
+    void growData(uint32_t grow) {
         uint32_t newWritten = mDataWritten + grow;
         if (newWritten < mDataWritten) {
-            LOG_ALWAYS_FATAL("buffer overflowed; data written %" PRIu32
-                    ", growing by %" PRIu32, mDataWritten, grow);
+            LOG_ALWAYS_FATAL("buffer overflowed; data written %" PRIu32 ", growing by %" PRIu32,
+                             mDataWritten, grow);
         }
 
         if (newWritten <= mDataMaxSize) {
@@ -651,7 +554,7 @@
     uint32_t mCommandEnd;
 
     std::vector<hidl_handle> mDataHandles;
-    std::vector<native_handle_t *> mTemporaryHandles;
+    std::vector<native_handle_t*> mTemporaryHandles;
 
     std::unique_ptr<CommandQueueType> mQueue;
 };
@@ -659,14 +562,10 @@
 // This class helps parse a command queue.  Note that all sizes/lengths are in
 // units of uint32_t's.
 class CommandReaderBase {
-public:
-    CommandReaderBase() : mDataMaxSize(0)
-    {
-        reset();
-    }
+   public:
+    CommandReaderBase() : mDataMaxSize(0) { reset(); }
 
-    bool setMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor)
-    {
+    bool setMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor) {
         mQueue = std::make_unique<CommandQueueType>(descriptor, false);
         if (mQueue->isValid()) {
             return true;
@@ -676,9 +575,7 @@
         }
     }
 
-    bool readQueue(uint32_t commandLength,
-            const hidl_vec<hidl_handle>& commandHandles)
-    {
+    bool readQueue(uint32_t commandLength, const hidl_vec<hidl_handle>& commandHandles) {
         if (!mQueue) {
             return false;
         }
@@ -689,8 +586,7 @@
             mData = std::make_unique<uint32_t[]>(mDataMaxSize);
         }
 
-        if (commandLength > mDataMaxSize ||
-                !mQueue->read(mData.get(), commandLength)) {
+        if (commandLength > mDataMaxSize || !mQueue->read(mData.get(), commandLength)) {
             ALOGE("failed to read commands from message queue");
             return false;
         }
@@ -699,15 +595,13 @@
         mDataRead = 0;
         mCommandBegin = 0;
         mCommandEnd = 0;
-        mDataHandles.setToExternal(
-                const_cast<hidl_handle*>(commandHandles.data()),
-                commandHandles.size());
+        mDataHandles.setToExternal(const_cast<hidl_handle*>(commandHandles.data()),
+                                   commandHandles.size());
 
         return true;
     }
 
-    void reset()
-    {
+    void reset() {
         mDataSize = 0;
         mDataRead = 0;
         mCommandBegin = 0;
@@ -715,15 +609,10 @@
         mDataHandles.setToExternal(nullptr, 0);
     }
 
-protected:
-    bool isEmpty() const
-    {
-        return (mDataRead >= mDataSize);
-    }
+   protected:
+    bool isEmpty() const { return (mDataRead >= mDataSize); }
 
-    bool beginCommand(IComposerClient::Command* outCommand,
-            uint16_t* outLength)
-    {
+    bool beginCommand(IComposerClient::Command* outCommand, uint16_t* outLength) {
         if (mCommandEnd) {
             LOG_FATAL("endCommand was not called for last command");
         }
@@ -734,13 +623,11 @@
             static_cast<uint32_t>(IComposerClient::Command::LENGTH_MASK);
 
         uint32_t val = read();
-        *outCommand = static_cast<IComposerClient::Command>(
-                val & opcode_mask);
+        *outCommand = static_cast<IComposerClient::Command>(val & opcode_mask);
         *outLength = static_cast<uint16_t>(val & length_mask);
 
         if (mDataRead + *outLength > mDataSize) {
-            ALOGE("command 0x%x has invalid command length %" PRIu16,
-                    *outCommand, *outLength);
+            ALOGE("command 0x%x has invalid command length %" PRIu16, *outCommand, *outLength);
             // undo the read() above
             mDataRead--;
             return false;
@@ -751,8 +638,7 @@
         return true;
     }
 
-    void endCommand()
-    {
+    void endCommand() {
         if (!mCommandEnd) {
             LOG_FATAL("beginCommand was not called");
         } else if (mDataRead > mCommandEnd) {
@@ -767,83 +653,68 @@
         mCommandEnd = 0;
     }
 
-    uint32_t getCommandLoc() const
-    {
-        return mCommandBegin;
-    }
+    uint32_t getCommandLoc() const { return mCommandBegin; }
 
-    uint32_t read()
-    {
-        return mData[mDataRead++];
-    }
+    uint32_t read() { return mData[mDataRead++]; }
 
-    int32_t readSigned()
-    {
+    int32_t readSigned() {
         int32_t val;
         memcpy(&val, &mData[mDataRead++], sizeof(val));
         return val;
     }
 
-    float readFloat()
-    {
+    float readFloat() {
         float val;
         memcpy(&val, &mData[mDataRead++], sizeof(val));
         return val;
     }
 
-    uint64_t read64()
-    {
+    uint64_t read64() {
         uint32_t lo = read();
         uint32_t hi = read();
         return (static_cast<uint64_t>(hi) << 32) | lo;
     }
 
-    IComposerClient::Color readColor()
-    {
+    IComposerClient::Color readColor() {
         uint32_t val = read();
         return IComposerClient::Color{
-            static_cast<uint8_t>((val >>  0) & 0xff),
-            static_cast<uint8_t>((val >>  8) & 0xff),
-            static_cast<uint8_t>((val >> 16) & 0xff),
-            static_cast<uint8_t>((val >> 24) & 0xff),
+            static_cast<uint8_t>((val >> 0) & 0xff), static_cast<uint8_t>((val >> 8) & 0xff),
+            static_cast<uint8_t>((val >> 16) & 0xff), static_cast<uint8_t>((val >> 24) & 0xff),
         };
     }
 
     // ownership of handle is not transferred
-    const native_handle_t* readHandle(bool* outUseCache)
-    {
+    const native_handle_t* readHandle(bool* outUseCache) {
         const native_handle_t* handle = nullptr;
 
         int32_t index = readSigned();
         switch (index) {
-        case static_cast<int32_t>(IComposerClient::HandleIndex::EMPTY):
-            *outUseCache = false;
-            break;
-        case static_cast<int32_t>(IComposerClient::HandleIndex::CACHED):
-            *outUseCache = true;
-            break;
-        default:
-            if (static_cast<size_t>(index) < mDataHandles.size()) {
-                handle = mDataHandles[index].getNativeHandle();
-            } else {
-                ALOGE("invalid handle index %zu", static_cast<size_t>(index));
-            }
-            *outUseCache = false;
-            break;
+            case static_cast<int32_t>(IComposerClient::HandleIndex::EMPTY):
+                *outUseCache = false;
+                break;
+            case static_cast<int32_t>(IComposerClient::HandleIndex::CACHED):
+                *outUseCache = true;
+                break;
+            default:
+                if (static_cast<size_t>(index) < mDataHandles.size()) {
+                    handle = mDataHandles[index].getNativeHandle();
+                } else {
+                    ALOGE("invalid handle index %zu", static_cast<size_t>(index));
+                }
+                *outUseCache = false;
+                break;
         }
 
         return handle;
     }
 
-    const native_handle_t* readHandle()
-    {
+    const native_handle_t* readHandle() {
         bool useCache;
         return readHandle(&useCache);
     }
 
     // ownership of fence is transferred
-    int readFence()
-    {
+    int readFence() {
         auto handle = readHandle();
         if (!handle || handle->numFds == 0) {
             return -1;
@@ -864,7 +735,7 @@
         return fd;
     }
 
-private:
+   private:
     std::unique_ptr<CommandQueueType> mQueue;
     uint32_t mDataMaxSize;
     std::unique_ptr<uint32_t[]> mData;
@@ -879,10 +750,10 @@
     hidl_vec<hidl_handle> mDataHandles;
 };
 
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
 
-#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_COMMAND_BUFFER_H
+#endif  // ANDROID_HARDWARE_GRAPHICS_COMPOSER_COMMAND_BUFFER_H
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 1ba7c9a..40f18c0 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -28,9 +28,11 @@
         "libsync",
     ],
     static_libs: [
-        "libhwcomposer-command-buffer",
         "VtsHalHidlTargetTestBase",
     ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
     cflags: [
         "-Wall",
         "-Wextra",
@@ -58,7 +60,9 @@
         "android.hardware.graphics.mapper@2.0",
         "libVtsHalGraphicsComposerTestUtils",
         "libVtsHalGraphicsMapperTestUtils",
-        "libhwcomposer-command-buffer",
         "libnativehelper",
     ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
 }
diff --git a/graphics/composer/2.1/vts/functional/TestCommandReader.h b/graphics/composer/2.1/vts/functional/TestCommandReader.h
index 657a463..ae25d2d 100644
--- a/graphics/composer/2.1/vts/functional/TestCommandReader.h
+++ b/graphics/composer/2.1/vts/functional/TestCommandReader.h
@@ -17,7 +17,7 @@
 #ifndef TEST_COMMAND_READER_H
 #define TEST_COMMAND_READER_H
 
-#include <IComposerCommandBuffer.h>
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
 
 namespace android {
 namespace hardware {
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
index 4e69f61..29b9de3 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
@@ -23,8 +23,8 @@
 #include <unordered_set>
 #include <vector>
 
-#include <IComposerCommandBuffer.h>
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
 #include <utils/StrongPointer.h>
 
 #include "TestCommandReader.h"
diff --git a/graphics/mapper/2.1/Android.bp b/graphics/mapper/2.1/Android.bp
index 7438d64..d917e59 100644
--- a/graphics/mapper/2.1/Android.bp
+++ b/graphics/mapper/2.1/Android.bp
@@ -11,7 +11,7 @@
         "IMapper.hal",
     ],
     interfaces: [
-        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.mapper@2.0",
         "android.hidl.base@1.0",
     ],
diff --git a/graphics/mapper/2.1/IMapper.hal b/graphics/mapper/2.1/IMapper.hal
index a23656d..6047e96 100644
--- a/graphics/mapper/2.1/IMapper.hal
+++ b/graphics/mapper/2.1/IMapper.hal
@@ -16,10 +16,47 @@
 
 package android.hardware.graphics.mapper@2.1;
 
-import android.hardware.graphics.mapper@2.0::Error;
-import android.hardware.graphics.mapper@2.0::IMapper;
+import android.hardware.graphics.common@1.1::BufferUsage;
+import android.hardware.graphics.common@1.1::PixelFormat;
+import @2.0::BufferDescriptor;
+import @2.0::Error;
+import @2.0::IMapper;
 
-interface IMapper extends android.hardware.graphics.mapper@2.0::IMapper {
+interface IMapper extends @2.0::IMapper {
+    /**
+     * This is the same as @2.0::IMapper::BufferDescriptorInfo except that it
+     * accepts @1.1::PixelFormat and @1.1::BufferUsage.
+     */
+    struct BufferDescriptorInfo {
+        /**
+         * 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.
+         */
+        uint32_t width;
+
+       /**
+        * 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;
+
+        /**
+         * Buffer usage mask; valid flags can be found in the definition of
+         * BufferUsage.
+         */
+        bitfield<BufferUsage> usage;
+    };
+
     /**
      * Validate that the buffer can be safely accessed by a caller who assumes
      * the specified descriptorInfo and stride. This must at least validate
@@ -58,4 +95,30 @@
             generates (Error error,
                        uint32_t numFds,
                        uint32_t numInts);
+
+    /**
+     * This is the same as @2.0::IMapper::createDescriptor except that it
+     * accepts @2.1::IMapper::BufferDescriptorInfo.
+     *
+     * Creates a buffer descriptor. The descriptor can be used with IAllocator
+     * to allocate buffers.
+     *
+     * Since the buffer descriptor fully describes a buffer, any device
+     * dependent or device independent checks must be performed here whenever
+     * possible. Specifically, when layered buffers are not supported, this
+     * function must return UNSUPPORTED if layerCount is great than 1.
+     *
+     * @param descriptorInfo specifies the attributes of the descriptor.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_VALUE when any of the specified attributes is
+     *                            invalid or conflicting.
+     *                  NO_RESOURCES when the creation cannot be fullfilled at
+     *                               this time.
+     *                  UNSUPPORTED when any of the specified attributes is
+     *                              not supported.
+     * @return descriptor is the newly created buffer descriptor.
+     */
+    createDescriptor_2_1(BufferDescriptorInfo descriptorInfo)
+              generates (Error error,
+                         BufferDescriptor descriptor);
 };
diff --git a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
index 4067c8d..88b96ae 100644
--- a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
+++ b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
@@ -30,10 +30,27 @@
 namespace tests {
 namespace {
 
+using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
 using android::hardware::graphics::mapper::V2_0::Error;
 
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using android::hardware::graphics::common::V1_0::PixelFormat;
+using android::hardware::graphics::common::V1_1::BufferUsage;
+using android::hardware::graphics::common::V1_1::PixelFormat;
+
+// abuse VTS to check binary compatibility between BufferDescriptorInfos
+using OldBufferDescriptorInfo =
+    android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo;
+static_assert(sizeof(OldBufferDescriptorInfo) == sizeof(IMapper::BufferDescriptorInfo) &&
+                  offsetof(OldBufferDescriptorInfo, width) ==
+                      offsetof(IMapper::BufferDescriptorInfo, width) &&
+                  offsetof(OldBufferDescriptorInfo, height) ==
+                      offsetof(IMapper::BufferDescriptorInfo, height) &&
+                  offsetof(OldBufferDescriptorInfo, layerCount) ==
+                      offsetof(IMapper::BufferDescriptorInfo, layerCount) &&
+                  offsetof(OldBufferDescriptorInfo, format) ==
+                      offsetof(IMapper::BufferDescriptorInfo, format) &&
+                  offsetof(OldBufferDescriptorInfo, usage) ==
+                      offsetof(IMapper::BufferDescriptorInfo, usage),
+              "");
 
 class Gralloc : public V2_0::tests::Gralloc {
    public:
@@ -72,6 +89,32 @@
         });
     }
 
+    BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
+        BufferDescriptor descriptor;
+        mMapper->createDescriptor_2_1(
+            descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+                ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
+                descriptor = tmpDescriptor;
+            });
+
+        return descriptor;
+    }
+
+    const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                    bool import, uint32_t* outStride = nullptr) {
+        BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+        if (::testing::Test::HasFatalFailure()) {
+            return nullptr;
+        }
+
+        auto buffers = V2_0::tests::Gralloc::allocate(descriptor, 1, import, outStride);
+        if (::testing::Test::HasFatalFailure()) {
+            return nullptr;
+        }
+
+        return buffers[0];
+    }
+
    private:
     void init() {
         mMapper = IMapper::castFrom(V2_0::tests::Gralloc::getMapper());
@@ -229,6 +272,24 @@
     native_handle_delete(rawBufferHandle);
 }
 
+/**
+ * Test IMapper::createDescriptor with valid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptor_2_1Basic) {
+    ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
+}
+
+/**
+ * Test IMapper::createDescriptor with invalid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptor_2_1Negative) {
+    auto info = mDummyDescriptorInfo;
+    info.width = 0;
+    mGralloc->getMapper()->createDescriptor_2_1(info, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_VALUE, tmpError) << "createDescriptor did not fail with BAD_VALUE";
+    });
+}
+
 }  // namespace
 }  // namespace tests
 }  // namespace V2_1
@@ -238,7 +299,10 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
+    using android::hardware::graphics::mapper::V2_0::tests::GraphicsMapperHidlEnvironment;
+    ::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
+    GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
 
     int status = RUN_ALL_TESTS();
     LOG(INFO) << "Test result = " << status;
diff --git a/health/2.0/Android.bp b/health/2.0/Android.bp
index 1080df1..0325467 100644
--- a/health/2.0/Android.bp
+++ b/health/2.0/Android.bp
@@ -16,7 +16,11 @@
         "android.hidl.base@1.0",
     ],
     types: [
+        "DiskStats",
+        "HealthInfo",
         "Result",
+        "StorageAttribute",
+        "StorageInfo",
     ],
     gen_java: true,
 }
diff --git a/health/2.0/IHealth.hal b/health/2.0/IHealth.hal
index 3e10701..230b5d0 100644
--- a/health/2.0/IHealth.hal
+++ b/health/2.0/IHealth.hal
@@ -69,7 +69,7 @@
      *                NOT_SUPPORTED if this property is not supported
      *                 (e.g. the file that stores this property does not exist),
      *                UNKNOWN for other errors.
-     * @return value battery capacity, or INT32_MIN if not successful.
+     * @return value battery capacity, or 0 if not successful.
      */
     getChargeCounter() generates (Result result, int32_t value);
 
@@ -84,7 +84,7 @@
      *                NOT_SUPPORTED if this property is not supported
      *                 (e.g. the file that stores this property does not exist),
      *                UNKNOWN for other errors.
-     * @return value instantaneous battery current, or INT32_MIN if not
+     * @return value instantaneous battery current, or 0 if not
      *               successful.
      */
     getCurrentNow() generates (Result result, int32_t value);
@@ -101,7 +101,7 @@
      *                NOT_SUPPORTED if this property is not supported
      *                 (e.g. the file that stores this property does not exist),
      *                UNKNOWN for other errors.
-     * @return value average battery current, or INT32_MIN if not successful.
+     * @return value average battery current, or 0 if not successful.
      */
     getCurrentAverage() generates (Result result, int32_t value);
 
@@ -113,7 +113,7 @@
      *                NOT_SUPPORTED if this property is not supported
      *                 (e.g. the file that stores this property does not exist),
      *                UNKNOWN for other errors.
-     * @return value remaining battery capacity, or INT32_MIN if not successful.
+     * @return value remaining battery capacity, or 0 if not successful.
      */
     getCapacity() generates (Result result, int32_t value);
 
@@ -123,7 +123,7 @@
      * @return result SUCCESS if successful,
      *                NOT_SUPPORTED if this property is not supported,
      *                UNKNOWN for other errors.
-     * @return value remaining energy, or INT64_MIN if not successful.
+     * @return value remaining energy, or 0 if not successful.
      */
     getEnergyCounter() generates (Result result, int64_t value);
 
@@ -137,4 +137,38 @@
      * @return value charge status, or UNKNOWN if not successful.
      */
     getChargeStatus() generates (Result result, BatteryStatus value);
+
+    /**
+     * Get storage info.
+     *
+     * @return result SUCCESS if successful,
+     *                NOT_SUPPORTED if this property is not supported,
+     *                UNKNOWN other errors.
+     * @return value vector of StorageInfo structs, to be ignored if result is not
+     *               SUCCESS.
+     */
+    getStorageInfo() generates (Result result, vec<StorageInfo> value);
+
+    /**
+     * Gets disk statistics (number of reads/writes processed, number of I/O
+     * operations in flight etc).
+     *
+     * @return result SUCCESS if successful,
+     *                NOT_SUPPORTED if this property is not supported,
+     *                UNKNOWN other errors.
+     * @return value vector of disk statistics, to be ignored if result is not SUCCESS.
+     *               The mapping is index 0->sda, 1->sdb and so on.
+     */
+    getDiskStats() generates (Result result, vec<DiskStats> value);
+
+    /**
+     * Get Health Information.
+     *
+     * @return result SUCCESS if successful,
+     *                NOT_SUPPORTED if this API is not supported,
+     *                UNKNOWN for other errors.
+     * @return value  Health information, to be ignored if result is not
+     *                SUCCESS.
+     */
+    getHealthInfo() generates (Result result, @2.0::HealthInfo value);
 };
diff --git a/health/2.0/IHealthInfoCallback.hal b/health/2.0/IHealthInfoCallback.hal
index 8e17bb9..15352ee 100644
--- a/health/2.0/IHealthInfoCallback.hal
+++ b/health/2.0/IHealthInfoCallback.hal
@@ -16,8 +16,6 @@
 
 package android.hardware.health@2.0;
 
-import @1.0::HealthInfo;
-
 /**
  * IHealthInfoCallback is the callback interface to
  * {@link IHealthInfoBus.registerCallback}.
diff --git a/health/2.0/README b/health/2.0/README
new file mode 100644
index 0000000..a0a5f08
--- /dev/null
+++ b/health/2.0/README
@@ -0,0 +1,99 @@
+Upgrading from health@1.0 HAL
+
+0. Remove android.hardware.health@1.0* from PRDOUCT_PACKAGES
+   in device/<manufacturer>/<device>/device.mk
+
+1. If the device does not have a vendor-specific libhealthd AND does not
+   implement storage-related APIs, just add the following to PRODUCT_PACKAGES:
+   android.hardware.health@2.0-service
+   Otherwise, continue to Step 2.
+
+2. Create directory
+   device/<manufacturer>/<device>/health
+
+3. Create device/<manufacturer>/<device>/health/Android.bp
+   (or equivalent device/<manufacturer>/<device>/health/Android.mk)
+
+cc_binary {
+    name: "android.hardware.health@2.0-service.<device>",
+    init_rc: ["android.hardware.health@2.0-service.<device>.rc"],
+    proprietary: true,
+    relative_install_path: "hw",
+    srcs: [
+        "HealthService.cpp",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    static_libs: [
+        "android.hardware.health@2.0-impl",
+        "android.hardware.health@1.0-convert",
+        "libhealthservice",
+        "libbatterymonitor",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.hardware.health@2.0",
+    ],
+
+    header_libs: ["libhealthd_headers"],
+}
+
+4. Create device/<manufacturer>/<device>/health/android.hardware.health@2.0-service.<device>.rc
+
+service vendor.health-hal-2-0 /vendor/bin/hw/android.hardware.health@2.0-service.<device>
+    class hal
+    user system
+    group system
+
+5. Create device/<manufacturer>/<device>/health/HealthService.cpp:
+
+#include <health2/service.h>
+int main() { return health_service_main(); }
+
+6. libhealthd dependency:
+
+6.1 If the device has a vendor-specific libhealthd.<soc>, add it to static_libs.
+
+6.2 If the device does not have a vendor-specific libhealthd, add the following
+    lines to HealthService.cpp:
+
+#include <healthd/healthd.h>
+void healthd_board_init(struct healthd_config*) {}
+
+int healthd_board_battery_update(struct android::BatteryProperties*) {
+    // return 0 to log periodic polled battery status to kernel log
+    return 0;
+}
+
+7. Storage related APIs:
+
+7.1 If the device does not implement IHealth.getDiskStats and
+    IHealth.getStorageInfo, add libstoragehealthdefault to static_libs.
+
+7.2 If the device implements one of these two APIs, add and implement the
+    following functions in HealthService.cpp:
+
+void get_storage_info(std::vector<struct StorageInfo>& info) {
+    // ...
+}
+void get_disk_stats(std::vector<struct DiskStats>& stats) {
+    // ...
+}
+
+8. Update necessary SELinux permissions. For example,
+
+# device/<manufacturer>/<device>/sepolicy/vendor/file_contexts
+/vendor/bin/hw/android\.hardware\.health@2\.0-service.<device> u:object_r:hal_health_default_exec:s0
+
+# device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te
+# Add device specific permissions to hal_health_default domain, especially
+# if Step 6.2 or Step 7.2 is done.
diff --git a/health/2.0/default/Health.cpp b/health/2.0/default/Health.cpp
index 4710c90..7a3e650 100644
--- a/health/2.0/default/Health.cpp
+++ b/health/2.0/default/Health.cpp
@@ -1,8 +1,24 @@
+/*
+ * Copyright (C) 2018 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 "android.hardware.health@2.0-impl"
 #include <android-base/logging.h>
 
 #include <health2/Health.h>
 
+#include <hal_conversion.h>
 #include <hidl/HidlTransportSupport.h>
 
 extern void healthd_battery_update_internal(bool);
@@ -93,27 +109,27 @@
 }
 
 Return<void> Health::getChargeCounter(getChargeCounter_cb _hidl_cb) {
-    getProperty(battery_monitor_, BATTERY_PROP_CHARGE_COUNTER, INT32_MIN, _hidl_cb);
+    getProperty<int32_t>(battery_monitor_, BATTERY_PROP_CHARGE_COUNTER, 0, _hidl_cb);
     return Void();
 }
 
 Return<void> Health::getCurrentNow(getCurrentNow_cb _hidl_cb) {
-    getProperty(battery_monitor_, BATTERY_PROP_CURRENT_NOW, INT32_MIN, _hidl_cb);
+    getProperty<int32_t>(battery_monitor_, BATTERY_PROP_CURRENT_NOW, 0, _hidl_cb);
     return Void();
 }
 
 Return<void> Health::getCurrentAverage(getCurrentAverage_cb _hidl_cb) {
-    getProperty(battery_monitor_, BATTERY_PROP_CURRENT_AVG, INT32_MIN, _hidl_cb);
+    getProperty<int32_t>(battery_monitor_, BATTERY_PROP_CURRENT_AVG, 0, _hidl_cb);
     return Void();
 }
 
 Return<void> Health::getCapacity(getCapacity_cb _hidl_cb) {
-    getProperty(battery_monitor_, BATTERY_PROP_CAPACITY, INT32_MIN, _hidl_cb);
+    getProperty<int32_t>(battery_monitor_, BATTERY_PROP_CAPACITY, 0, _hidl_cb);
     return Void();
 }
 
 Return<void> Health::getEnergyCounter(getEnergyCounter_cb _hidl_cb) {
-    getProperty(battery_monitor_, BATTERY_PROP_ENERGY_COUNTER, INT64_MIN, _hidl_cb);
+    getProperty<int64_t>(battery_monitor_, BATTERY_PROP_ENERGY_COUNTER, 0, _hidl_cb);
     return Void();
 }
 
@@ -139,10 +155,28 @@
     return Result::SUCCESS;
 }
 
-void Health::notifyListeners(const HealthInfo& info) {
+void Health::notifyListeners(HealthInfo* healthInfo) {
+    std::vector<StorageInfo> info;
+    get_storage_info(info);
+
+    std::vector<DiskStats> stats;
+    get_disk_stats(stats);
+
+    int32_t currentAvg = 0;
+
+    struct BatteryProperty prop;
+    status_t ret = battery_monitor_->getProperty(BATTERY_PROP_CURRENT_AVG, &prop);
+    if (ret == OK) {
+        currentAvg = static_cast<int32_t>(prop.valueInt64);
+    }
+
+    healthInfo->batteryCurrentAverage = currentAvg;
+    healthInfo->diskStats = stats;
+    healthInfo->storageInfos = info;
+
     std::lock_guard<std::mutex> _lock(callbacks_lock_);
     for (auto it = callbacks_.begin(); it != callbacks_.end();) {
-        auto ret = (*it)->healthInfoChanged(info);
+        auto ret = (*it)->healthInfoChanged(*healthInfo);
         if (!ret.isOk() && ret.isDeadObject()) {
             it = callbacks_.erase(it);
         } else {
@@ -160,6 +194,63 @@
     return Void();
 }
 
+Return<void> Health::getStorageInfo(getStorageInfo_cb _hidl_cb) {
+    std::vector<struct StorageInfo> info;
+    get_storage_info(info);
+    hidl_vec<struct StorageInfo> info_vec(info);
+    if (!info.size()) {
+        _hidl_cb(Result::NOT_SUPPORTED, info_vec);
+    } else {
+        _hidl_cb(Result::SUCCESS, info_vec);
+    }
+    return Void();
+}
+
+Return<void> Health::getDiskStats(getDiskStats_cb _hidl_cb) {
+    std::vector<struct DiskStats> stats;
+    get_disk_stats(stats);
+    hidl_vec<struct DiskStats> stats_vec(stats);
+    if (!stats.size()) {
+        _hidl_cb(Result::NOT_SUPPORTED, stats_vec);
+    } else {
+        _hidl_cb(Result::SUCCESS, stats_vec);
+    }
+    return Void();
+}
+
+Return<void> Health::getHealthInfo(getHealthInfo_cb _hidl_cb) {
+    using android::hardware::health::V1_0::hal_conversion::convertToHealthInfo;
+
+    update();
+    struct android::BatteryProperties p = getBatteryProperties(battery_monitor_.get());
+
+    V1_0::HealthInfo batteryInfo;
+    convertToHealthInfo(&p, batteryInfo);
+
+    std::vector<StorageInfo> info;
+    get_storage_info(info);
+
+    std::vector<DiskStats> stats;
+    get_disk_stats(stats);
+
+    int32_t currentAvg = 0;
+
+    struct BatteryProperty prop;
+    status_t ret = battery_monitor_->getProperty(BATTERY_PROP_CURRENT_AVG, &prop);
+    if (ret == OK) {
+        currentAvg = static_cast<int32_t>(prop.valueInt64);
+    }
+
+    V2_0::HealthInfo healthInfo = {};
+    healthInfo.legacy = std::move(batteryInfo);
+    healthInfo.batteryCurrentAverage = currentAvg;
+    healthInfo.diskStats = stats;
+    healthInfo.storageInfos = info;
+
+    _hidl_cb(Result::SUCCESS, healthInfo);
+    return Void();
+}
+
 void Health::serviceDied(uint64_t /* cookie */, const wp<IBase>& who) {
     (void)unregisterCallbackInternal(who.promote());
 }
diff --git a/health/2.0/default/include/health2/Health.h b/health/2.0/default/include/health2/Health.h
index ab42ae7..134cdc6 100644
--- a/health/2.0/default/include/health2/Health.h
+++ b/health/2.0/default/include/health2/Health.h
@@ -9,6 +9,12 @@
 #include <healthd/BatteryMonitor.h>
 #include <hidl/Status.h>
 
+using android::hardware::health::V2_0::StorageInfo;
+using android::hardware::health::V2_0::DiskStats;
+
+void get_storage_info(std::vector<struct StorageInfo>& info);
+void get_disk_stats(std::vector<struct DiskStats>& stats);
+
 namespace android {
 namespace hardware {
 namespace health {
@@ -16,7 +22,6 @@
 namespace implementation {
 
 using V1_0::BatteryStatus;
-using V1_0::HealthInfo;
 
 using ::android::hidl::base::V1_0::IBase;
 
@@ -32,7 +37,7 @@
     Health(struct healthd_config* c);
 
     // TODO(b/62229583): clean up and hide these functions after update() logic is simplified.
-    void notifyListeners(const HealthInfo& info);
+    void notifyListeners(HealthInfo* info);
 
     // Methods from IHealth follow.
     Return<Result> registerCallback(const sp<IHealthInfoCallback>& callback) override;
@@ -44,6 +49,9 @@
     Return<void> getCapacity(getCapacity_cb _hidl_cb) override;
     Return<void> getEnergyCounter(getEnergyCounter_cb _hidl_cb) override;
     Return<void> getChargeStatus(getChargeStatus_cb _hidl_cb) override;
+    Return<void> getStorageInfo(getStorageInfo_cb _hidl_cb) override;
+    Return<void> getDiskStats(getDiskStats_cb _hidl_cb) override;
+    Return<void> getHealthInfo(getHealthInfo_cb _hidl_cb) override;
 
     // Methods from ::android::hidl::base::V1_0::IBase follow.
     Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override;
diff --git a/health/2.0/types.hal b/health/2.0/types.hal
index 8c6d88f..fe33c88 100644
--- a/health/2.0/types.hal
+++ b/health/2.0/types.hal
@@ -26,3 +26,129 @@
     NOT_FOUND,
     CALLBACK_DIED,
 };
+
+/*
+ * Identification attributes for a storage device.
+ */
+struct StorageAttribute {
+    /**
+     * Set to true if internal storage
+     */
+    bool isInternal;
+    /**
+     * Set to true if this is the boot device.
+     */
+    bool isBootDevice;
+    /**
+     * Name of the storage device.
+     */
+    string name;
+};
+
+/*
+ * Information on storage device including life time estimates, end of life
+ * information and other attributes.
+ */
+struct StorageInfo {
+    /**
+     * Attributes of the storage device whose info is contained by the struct.
+     */
+    StorageAttribute attr;
+    /**
+     * pre-eol (end of life) information. Follows JEDEC standard No.84-B50.
+     */
+    uint16_t eol;
+    /**
+     * device life time estimation (type A). Follows JEDEC standard No.84-B50.
+     */
+    uint16_t lifetimeA;
+    /**
+     * device life time estimation (type B). Follows JEDEC standard No.84-B50.
+     */
+    uint16_t lifetimeB;
+    /**
+     * version string
+     */
+    string version;
+};
+/*
+ * Disk statistics since boot.
+ */
+struct DiskStats {
+    /**
+     * Number of reads processed.
+     */
+    uint64_t reads;
+    /**
+     * number of read I/Os merged with in-queue I/Os.
+     */
+    uint64_t readMerges;
+    /**
+     * number of sectors read.
+     */
+    uint64_t readSectors;
+    /**
+     * total wait time for read requests.
+     */
+    uint64_t readTicks;
+    /**
+     * number of writes processed.
+     */
+    uint64_t writes;
+    /**
+     * number of writes merged with in-queue I/Os.
+     */
+    uint64_t writeMerges;
+    /**
+     * number of sectors written.
+     */
+    uint64_t writeSectors;
+    /**
+     * total wait time for write requests.
+     */
+    uint64_t writeTicks;
+    /**
+     * number of I/Os currently in flight.
+     */
+    uint64_t ioInFlight;
+    /**
+     * total time this block device has been active.
+     */
+    uint64_t ioTicks;
+    /**
+     * total wait time for all requests.
+     */
+    uint64_t ioInQueue;
+    /**
+     * Attributes of the memory device.
+     */
+    StorageAttribute attr;
+};
+
+/**
+ * Combined Health Information.
+ */
+struct HealthInfo {
+    /**
+     * V1.0 HealthInfo.
+     * If a member is unsupported, it is filled with:
+     * - 0 (for integers);
+     * - false (for booleans);
+     * - empty string (for strings);
+     * - UNKNOWN (for BatteryStatus and BatteryHealth).
+     */
+    @1.0::HealthInfo legacy;
+    /**
+     * Average battery current in uA. Will be 0 if unsupported.
+     */
+    int32_t batteryCurrentAverage;
+    /**
+     * Disk Statistics. Will be an empty vector if unsupported.
+     */
+    vec<DiskStats> diskStats;
+    /**
+     * Information on storage devices. Will be an empty vector if
+     * unsupported.
+     */
+    vec<StorageInfo> storageInfos;
+};
diff --git a/health/2.0/utils/README b/health/2.0/utils/README
new file mode 100644
index 0000000..1d5c27f
--- /dev/null
+++ b/health/2.0/utils/README
@@ -0,0 +1,28 @@
+* libhealthhalutils
+
+A convenience library for (hwbinder) clients of health HAL to choose between
+the "default" instance (served by vendor service) or "backup" instance (served
+by healthd). C++ clients of health HAL should use this library instead of
+calling IHealth::getService() directly.
+
+Its Java equivalent can be found in BatteryService.HealthServiceWrapper.
+
+* libhealthservice
+
+Common code for all (hwbinder) services of the health HAL, including healthd and
+vendor health service android.hardware.health@2.0-service(.<vendor>). main() in
+those binaries calls health_service_main() directly.
+
+* libhealthstoragedefault
+
+Default implementation for storage related APIs for (hwbinder) services of the
+health HAL. If an implementation of the health HAL do not wish to provide any
+storage info, include this library. Otherwise, it should implement the following
+two functions:
+
+void get_storage_info(std::vector<struct StorageInfo>& info) {
+    // ...
+}
+void get_disk_stats(std::vector<struct DiskStats>& stats) {
+    // ...
+}
diff --git a/health/2.0/utils/libhealthhalutils/Android.bp b/health/2.0/utils/libhealthhalutils/Android.bp
new file mode 100644
index 0000000..5686520
--- /dev/null
+++ b/health/2.0/utils/libhealthhalutils/Android.bp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+// Convenience library for (hwbinder) clients to choose the correct health
+// service instance.
+cc_library_static {
+    name: "libhealthhalutils",
+    srcs: ["HealthHalUtils.cpp"],
+    cflags: ["-Wall", "-Werror"],
+    vendor_available: true,
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "android.hardware.health@2.0",
+        "libbase",
+        "libhidlbase",
+    ],
+}
diff --git a/health/2.0/utils/libhealthhalutils/HealthHalUtils.cpp b/health/2.0/utils/libhealthhalutils/HealthHalUtils.cpp
new file mode 100644
index 0000000..9e1cc70
--- /dev/null
+++ b/health/2.0/utils/libhealthhalutils/HealthHalUtils.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 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 "HealthHalUtils"
+
+#include <android-base/logging.h>
+#include <healthhalutils/HealthHalUtils.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace V2_0 {
+
+sp<IHealth> get_health_service() {
+    for (auto&& instanceName : {"default", "backup"}) {
+        auto ret = IHealth::getService(instanceName);
+        if (ret != nullptr) {
+            return ret;
+        }
+        LOG(INFO) << "health: cannot get " << instanceName << " service";
+    }
+    return nullptr;
+}
+
+}  // namespace V2_0
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
diff --git a/health/2.0/utils/libhealthhalutils/include/healthhalutils/HealthHalUtils.h b/health/2.0/utils/libhealthhalutils/include/healthhalutils/HealthHalUtils.h
new file mode 100644
index 0000000..66acc7c
--- /dev/null
+++ b/health/2.0/utils/libhealthhalutils/include/healthhalutils/HealthHalUtils.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 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 HEALTHD_HEALTH_HAL_UTILS_H
+#define HEALTHD_HEALTH_HAL_UTILS_H
+
+#include <android/hardware/health/2.0/IHealth.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace V2_0 {
+
+// Simplified version of BatteryService.HealthServiceWrapper.init().
+// Returns the "default" health instance when it is available, and "backup" instance
+// otherwise. Before health 1.0 HAL is removed, this function should be used instead
+// of IHealth::getService().
+sp<IHealth> get_health_service();
+
+}  // namespace V2_0
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HEALTHD_HEALTH_HAL_UTILS_H
diff --git a/health/2.0/utils/libhealthservice/Android.bp b/health/2.0/utils/libhealthservice/Android.bp
new file mode 100644
index 0000000..88c38f2
--- /dev/null
+++ b/health/2.0/utils/libhealthservice/Android.bp
@@ -0,0 +1,29 @@
+// Reasonable defaults for android.hardware.health@2.0-service.<device>.
+// Vendor service can customize by implementing functions defined in
+// libhealthd and libhealthstoragedefault.
+
+
+cc_library_static {
+    name: "libhealthservice",
+    vendor_available: true,
+    srcs: ["HealthServiceCommon.cpp"],
+
+    export_include_dirs: ["include"],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "android.hardware.health@2.0",
+    ],
+    static_libs: [
+        "android.hardware.health@2.0-impl",
+        "android.hardware.health@1.0-convert",
+    ],
+    export_static_lib_headers: [
+        "android.hardware.health@1.0-convert",
+    ],
+    header_libs: ["libhealthd_headers"],
+    export_header_lib_headers: ["libhealthd_headers"],
+}
diff --git a/health/2.0/utils/libhealthservice/HealthServiceCommon.cpp b/health/2.0/utils/libhealthservice/HealthServiceCommon.cpp
new file mode 100644
index 0000000..acb4501
--- /dev/null
+++ b/health/2.0/utils/libhealthservice/HealthServiceCommon.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2017 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 "health@2.0/"
+#include <android-base/logging.h>
+
+#include <android/hardware/health/1.0/types.h>
+#include <hal_conversion.h>
+#include <health2/Health.h>
+#include <health2/service.h>
+#include <healthd/healthd.h>
+#include <hidl/HidlTransportSupport.h>
+
+using android::hardware::IPCThreadState;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::handleTransportPoll;
+using android::hardware::setupTransportPolling;
+using android::hardware::health::V2_0::HealthInfo;
+using android::hardware::health::V1_0::hal_conversion::convertToHealthInfo;
+using android::hardware::health::V2_0::IHealth;
+using android::hardware::health::V2_0::implementation::Health;
+
+extern int healthd_main(void);
+
+static int gBinderFd = -1;
+static std::string gInstanceName;
+
+static void binder_event(uint32_t /*epevents*/) {
+    if (gBinderFd >= 0) handleTransportPoll(gBinderFd);
+}
+
+void healthd_mode_service_2_0_init(struct healthd_config* config) {
+    LOG(INFO) << LOG_TAG << gInstanceName << " Hal is starting up...";
+
+    gBinderFd = setupTransportPolling();
+
+    if (gBinderFd >= 0) {
+        if (healthd_register_event(gBinderFd, binder_event))
+            LOG(ERROR) << LOG_TAG << gInstanceName << ": Register for binder events failed";
+    }
+
+    android::sp<IHealth> service = Health::initInstance(config);
+    CHECK_EQ(service->registerAsService(gInstanceName), android::OK)
+        << LOG_TAG << gInstanceName << ": Failed to register HAL";
+
+    LOG(INFO) << LOG_TAG << gInstanceName << ": Hal init done";
+}
+
+int healthd_mode_service_2_0_preparetowait(void) {
+    IPCThreadState::self()->flushCommands();
+    return -1;
+}
+
+void healthd_mode_service_2_0_heartbeat(void) {
+    // noop
+}
+
+void healthd_mode_service_2_0_battery_update(struct android::BatteryProperties* prop) {
+    HealthInfo info;
+    convertToHealthInfo(prop, info.legacy);
+    Health::getImplementation()->notifyListeners(&info);
+}
+
+static struct healthd_mode_ops healthd_mode_service_2_0_ops = {
+    .init = healthd_mode_service_2_0_init,
+    .preparetowait = healthd_mode_service_2_0_preparetowait,
+    .heartbeat = healthd_mode_service_2_0_heartbeat,
+    .battery_update = healthd_mode_service_2_0_battery_update,
+};
+
+int health_service_main(const char* instance) {
+    gInstanceName = instance;
+    if (gInstanceName.empty()) {
+        gInstanceName = "default";
+    }
+    healthd_mode_ops = &healthd_mode_service_2_0_ops;
+    LOG(INFO) << LOG_TAG << gInstanceName << ": Hal starting main loop...";
+    return healthd_main();
+}
diff --git a/health/2.0/utils/libhealthservice/include/health2/service.h b/health/2.0/utils/libhealthservice/include/health2/service.h
new file mode 100644
index 0000000..d260568
--- /dev/null
+++ b/health/2.0/utils/libhealthservice/include/health2/service.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2018 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_HEALTH_V2_0_SERVICE_COMMON
+#define ANDROID_HARDWARE_HEALTH_V2_0_SERVICE_COMMON
+
+int health_service_main(const char* instance = "");
+
+#endif  // ANDROID_HARDWARE_HEALTH_V2_0_SERVICE_COMMON
diff --git a/health/2.0/utils/libhealthstoragedefault/Android.bp b/health/2.0/utils/libhealthstoragedefault/Android.bp
new file mode 100644
index 0000000..cef04fe
--- /dev/null
+++ b/health/2.0/utils/libhealthstoragedefault/Android.bp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+// Default implementation for (passthrough) clients that statically links to
+// android.hardware.health@2.0-impl but do no query for storage related
+// information.
+cc_library_static {
+    srcs: ["StorageHealthDefault.cpp"],
+    name: "libhealthstoragedefault",
+    vendor_available: true,
+    cflags: ["-Werror"],
+    shared_libs: [
+        "android.hardware.health@2.0",
+    ],
+}
diff --git a/health/2.0/utils/libhealthstoragedefault/StorageHealthDefault.cpp b/health/2.0/utils/libhealthstoragedefault/StorageHealthDefault.cpp
new file mode 100644
index 0000000..aba6cc3
--- /dev/null
+++ b/health/2.0/utils/libhealthstoragedefault/StorageHealthDefault.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2018 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 "include/StorageHealthDefault.h"
+
+void get_storage_info(std::vector<struct StorageInfo>&) {
+    // Use defaults.
+}
+
+void get_disk_stats(std::vector<struct DiskStats>&) {
+    // Use defaults
+}
diff --git a/health/2.0/utils/libhealthstoragedefault/include/StorageHealthDefault.h b/health/2.0/utils/libhealthstoragedefault/include/StorageHealthDefault.h
new file mode 100644
index 0000000..85eb210
--- /dev/null
+++ b/health/2.0/utils/libhealthstoragedefault/include/StorageHealthDefault.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 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_HEALTH_V2_0_STORAGE_HEALTH_H
+#define ANDROID_HARDWARE_HEALTH_V2_0_STORAGE_HEALTH_H
+
+#include <android/hardware/health/2.0/types.h>
+
+using android::hardware::health::V2_0::StorageInfo;
+using android::hardware::health::V2_0::DiskStats;
+
+/*
+ * Get storage information.
+ */
+void get_storage_info(std::vector<struct StorageInfo>& info);
+
+/*
+ * Get disk statistics.
+ */
+void get_disk_stats(std::vector<struct DiskStats>& stats);
+
+#endif  // ANDROID_HARDWARE_HEALTH_V2_0_STORAGE_HEALTH_H
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
index bf8548c..972bc7f 100644
--- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
+++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
@@ -35,7 +35,6 @@
 namespace V2_0 {
 
 using V1_0::BatteryStatus;
-using V1_0::HealthInfo;
 
 // Test environment for graphics.composer
 class HealthHidlEnvironment : public VtsHalHidlTargetTestEnvBase {
@@ -180,6 +179,66 @@
     return AssertionFailure() << "Result is not SUCCESS or NOT_SUPPORTED: " << toString(res);
 }
 
+bool verifyStorageInfo(const hidl_vec<struct StorageInfo>& info) {
+    for (size_t i = 0; i < info.size(); i++) {
+        if (!(0 <= info[i].eol && info[i].eol <= 3 && 0 <= info[i].lifetimeA &&
+              info[i].lifetimeA <= 0x0B && 0 <= info[i].lifetimeB && info[i].lifetimeB <= 0x0B)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool verifyDiskStats(const hidl_vec<struct DiskStats>& stats) {
+    for (size_t i = 0; i < stats.size(); i++) {
+        if (!(stats[i].reads > 0 && stats[i].readMerges > 0 && stats[i].readSectors > 0 &&
+              stats[i].readTicks > 0 && stats[i].writes > 0 && stats[i].writeMerges > 0 &&
+              stats[i].writeSectors > 0 && stats[i].writeTicks > 0 && stats[i].ioTicks > 0)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+template <typename T>
+bool verifyEnum(T value) {
+    for (auto it : hidl_enum_iterator<T>()) {
+        if (it == value) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool verifyHealthInfo(const HealthInfo& health_info) {
+    if (!verifyStorageInfo(health_info.storageInfos) || !verifyDiskStats(health_info.diskStats)) {
+        return false;
+    }
+
+    using V1_0::BatteryStatus;
+    using V1_0::BatteryHealth;
+
+    if (!((health_info.legacy.batteryChargeCounter > 0) &&
+          (health_info.legacy.batteryCurrent != INT32_MIN) &&
+          (0 <= health_info.legacy.batteryLevel && health_info.legacy.batteryLevel <= 100) &&
+          verifyEnum<BatteryHealth>(health_info.legacy.batteryHealth) &&
+          (health_info.legacy.batteryStatus != BatteryStatus::UNKNOWN) &&
+          verifyEnum<BatteryStatus>(health_info.legacy.batteryStatus))) {
+        return false;
+    }
+
+    return true;
+}
+
+/*
+ * Tests the values returned by getChargeCounter(),
+ * getCurrentNow(), getCurrentAverage(), getCapacity(), getEnergyCounter(),
+ * getChargeStatus(), getStorageInfo(), getDiskStats() and getHealthInfo() from
+ * interface IHealth.
+ */
 TEST_F(HealthHidlTest, Properties) {
     EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
@@ -199,8 +258,16 @@
     EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(
             result, toString(value),
-            value == BatteryStatus::CHARGING || value == BatteryStatus::DISCHARGING ||
-                value == BatteryStatus::NOT_CHARGING || value == BatteryStatus::FULL);
+            value != BatteryStatus::UNKNOWN && verifyEnum<BatteryStatus>(value));
+    }));
+    EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyStorageInfo(value));
+    }));
+    EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyDiskStats(value));
+    }));
+    EXPECT_OK(mHealth->getHealthInfo([](auto result, auto& value) {
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyHealthInfo(value));
     }));
 }
 
diff --git a/keymaster/4.0/Android.bp b/keymaster/4.0/Android.bp
index 20c40a0..2daad41 100644
--- a/keymaster/4.0/Android.bp
+++ b/keymaster/4.0/Android.bp
@@ -15,16 +15,26 @@
         "android.hidl.base@1.0",
     ],
     types: [
+        "Algorithm",
+        "BlockMode",
         "Constants",
+        "Digest",
+        "EcCurve",
         "ErrorCode",
         "HardwareAuthToken",
+        "HardwareAuthenticatorType",
         "HmacSharingParameters",
+        "KeyBlobUsageRequirements",
         "KeyCharacteristics",
+        "KeyDerivationFunction",
+        "KeyFormat",
         "KeyOrigin",
         "KeyParameter",
         "KeyPurpose",
+        "PaddingMode",
         "SecurityLevel",
         "Tag",
+        "TagType",
         "VerificationToken",
     ],
     gen_java: false,
diff --git a/keymaster/4.0/IKeymasterDevice.hal b/keymaster/4.0/IKeymasterDevice.hal
index 14c9c35..aef81c7 100644
--- a/keymaster/4.0/IKeymasterDevice.hal
+++ b/keymaster/4.0/IKeymasterDevice.hal
@@ -274,6 +274,23 @@
      * @param maskingKey The 32-byte value XOR'd with the transport key in the SecureWrappedKey
      *        structure.
      *
+     * @param unwrappingParams must contain any parameters needed to perform the unwrapping
+     *        operation.  For example, if the wrapping key is an AES key the block and padding modes
+     *        must be specified in this argument.
+     *
+     * @param passwordSid specifies the password secure ID (SID) of the user that owns the key being
+     *        installed.  If the authorization list in wrappedKeyData contains a Tag::USER_SECURE_ID
+     *        with a value that has the HardwareAuthenticatorType::PASSWORD bit set, the constructed
+     *        key must be bound to the SID value provided by this argument.  If the wrappedKeyData
+     *        does not contain such a tag and value, this argument must be ignored.
+     *
+     * @param biometricSid specifies the biometric secure ID (SID) of the user that owns the key
+     *        being installed.  If the authorization list in wrappedKeyData contains a
+     *        Tag::USER_SECURE_ID with a value that has the HardwareAuthenticatorType::FINGERPRINT
+     *        bit set, the constructed key must be bound to the SID value provided by this argument.
+     *        If the wrappedKeyData does not contain such a tag and value, this argument must be
+     *        ignored.
+     *
      * @return error See the ErrorCode enum.
      *
      * @return keyBlob Opaque descriptor of the imported key.  It is recommended that the keyBlob
@@ -281,8 +298,9 @@
      *         hardware.
      */
     importWrappedKey(vec<uint8_t> wrappedKeyData, vec<uint8_t> wrappingKeyBlob,
-                     vec<uint8_t> maskingKey)
-        generates (ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
+                     vec<uint8_t> maskingKey, vec<KeyParameter> unwrappingParams,
+                     uint64_t passwordSid, uint64_t biometricSid)
+        generates(ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
 
     /**
      * Returns the characteristics of the specified key, if the keyBlob is valid (implementations
@@ -356,10 +374,27 @@
     /**
      * Upgrades an old key blob.  Keys can become "old" in two ways: Keymaster can be upgraded to a
      * new version with an incompatible key blob format, or the system can be updated to invalidate
-     * the OS version and/or patch level.  In either case, attempts to use an old key blob with
-     * getKeyCharacteristics(), exportKey(), attestKey() or begin() must result in Keymaster
-     * returning ErrorCode::KEY_REQUIRES_UPGRADE.  The caller must use this method to upgrade the
-     * key blob.
+     * the OS version (OS_VERSION tag), system patch level (OS_PATCHLEVEL tag), vendor patch level
+     * (VENDOR_PATCH_LEVEL tag), boot patch level (BOOT_PATCH_LEVEL tag) or other,
+     * implementation-defined patch level (keymaster implementers are encouraged to extend this HAL
+     * with a minor version extension to define validatable patch levels for other images; tags
+     * must be defined in the implemeter's namespace, starting at 10000).  In either case,
+     * attempts to use an old key blob with getKeyCharacteristics(), exportKey(), attestKey() or
+     * begin() must result in Keymaster returning ErrorCode::KEY_REQUIRES_UPGRADE.  The caller must
+     * use this method to upgrade the key blob.
+     *
+     * If upgradeKey is asked to update a key with any version or patch level that is higher than
+     * the current system version or patch level, it must return ErrorCode::INVALID_ARGUMENT.  There
+     * is one exception: it is always permissible to "upgrade" from any OS_VERSION number to
+     * OS_VERSION 0.  For example, if the key has OS_VERSION 080001, it is permisible to upgrade the
+     * key if the current system version is 080100, because the new version is larger, or if the
+     * current system version is 0, because upgrades to 0 are always allowed.  If the system version
+     * were 080000, however, keymaster must return ErrorCode::INVALID_ARGUMENT because that value is
+     * smaller than 080001.
+     *
+     * Note that Keymaster versions 2 and 3 required that the system and boot images have the same
+     * patch level and OS version.  This requirement is relaxed for Keymaster 4, and the OS version
+     * in the boot image footer is no longer used.
      *
      * @param keyBlobToUpgrade The opaque descriptor returned by generateKey() or importKey();
      *
diff --git a/keymaster/4.0/default/service.cpp b/keymaster/4.0/default/service.cpp
index f4b5fd3..cfb960a 100644
--- a/keymaster/4.0/default/service.cpp
+++ b/keymaster/4.0/default/service.cpp
@@ -21,8 +21,10 @@
 
 #include <AndroidKeymaster4Device.h>
 
+using android::hardware::keymaster::V4_0::SecurityLevel;
+
 int main() {
-    auto keymaster = ::keymaster::V4_0::ng::CreateKeymasterDevice();
+    auto keymaster = ::keymaster::V4_0::ng::CreateKeymasterDevice(SecurityLevel::SOFTWARE);
     auto status = keymaster->registerAsService();
     if (status != android::OK) {
         LOG(FATAL) << "Could not register service for Keymaster 4.0 (" << status << ")";
diff --git a/keymaster/4.0/support/Android.bp b/keymaster/4.0/support/Android.bp
index 748fed3..6b8dcdc 100644
--- a/keymaster/4.0/support/Android.bp
+++ b/keymaster/4.0/support/Android.bp
@@ -26,11 +26,18 @@
         "attestation_record.cpp",
         "authorization_set.cpp",
         "key_param_output.cpp",
+        "Keymaster3.cpp",
+        "Keymaster4.cpp",
     ],
     export_include_dirs: ["include"],
     shared_libs: [
+        "android.hardware.keymaster@3.0",
         "android.hardware.keymaster@4.0",
+        "libbase",
         "libcrypto",
+        "libhardware",
         "libhidlbase",
+        "libhidltransport",
+        "libutils",
     ]
 }
diff --git a/keymaster/4.0/support/Keymaster3.cpp b/keymaster/4.0/support/Keymaster3.cpp
new file mode 100644
index 0000000..6dfe85b
--- /dev/null
+++ b/keymaster/4.0/support/Keymaster3.cpp
@@ -0,0 +1,325 @@
+/*
+ **
+ ** Copyright 2017, 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 <keymasterV4_0/Keymaster3.h>
+
+#include <android-base/logging.h>
+#include <hardware/hw_auth_token.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+using android::hardware::details::StatusOf;
+
+namespace {
+
+ErrorCode convert(V3_0::ErrorCode error) {
+    return static_cast<ErrorCode>(error);
+}
+
+V3_0::KeyPurpose convert(KeyPurpose purpose) {
+    return static_cast<V3_0::KeyPurpose>(purpose);
+}
+
+V3_0::KeyFormat convert(KeyFormat purpose) {
+    return static_cast<V3_0::KeyFormat>(purpose);
+}
+
+V3_0::KeyParameter convert(const KeyParameter& param) {
+    V3_0::KeyParameter converted;
+    converted.tag = static_cast<V3_0::Tag>(param.tag);
+    static_assert(sizeof(converted.f) == sizeof(param.f), "This function assumes sizes match");
+    memcpy(&converted.f, &param.f, sizeof(param.f));
+    converted.blob = param.blob;
+    return converted;
+}
+
+KeyParameter convert(const V3_0::KeyParameter& param) {
+    KeyParameter converted;
+    converted.tag = static_cast<Tag>(param.tag);
+    static_assert(sizeof(converted.f) == sizeof(param.f), "This function assumes sizes match");
+    memcpy(&converted.f, &param.f, sizeof(param.f));
+    converted.blob = param.blob;
+    return converted;
+}
+
+hidl_vec<V3_0::KeyParameter> convert(const hidl_vec<KeyParameter>& params) {
+    hidl_vec<V3_0::KeyParameter> converted(params.size());
+    for (size_t i = 0; i < params.size(); ++i) {
+        converted[i] = convert(params[i]);
+    }
+    return converted;
+}
+
+hidl_vec<KeyParameter> convert(const hidl_vec<V3_0::KeyParameter>& params) {
+    hidl_vec<KeyParameter> converted(params.size());
+    for (size_t i = 0; i < params.size(); ++i) {
+        converted[i] = convert(params[i]);
+    }
+    return converted;
+}
+
+template <typename T, typename OutIter>
+inline static OutIter copy_bytes_to_iterator(const T& value, OutIter dest) {
+    const uint8_t* value_ptr = reinterpret_cast<const uint8_t*>(&value);
+    return std::copy(value_ptr, value_ptr + sizeof(value), dest);
+}
+
+constexpr size_t kHmacSize = 32;
+
+inline static hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token) {
+    static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
+                          sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
+                          sizeof(token.timestamp) + kHmacSize ==
+                      sizeof(hw_auth_token_t),
+                  "HardwareAuthToken content size does not match hw_auth_token_t size");
+
+    hidl_vec<uint8_t> result;
+    result.resize(sizeof(hw_auth_token_t));
+    auto pos = result.begin();
+    *pos++ = 0;  // Version byte
+    pos = copy_bytes_to_iterator(token.challenge, pos);
+    pos = copy_bytes_to_iterator(token.userId, pos);
+    pos = copy_bytes_to_iterator(token.authenticatorId, pos);
+    auto auth_type = htonl(static_cast<uint32_t>(token.authenticatorType));
+    pos = copy_bytes_to_iterator(auth_type, pos);
+    auto timestamp = htonq(token.timestamp);
+    pos = copy_bytes_to_iterator(timestamp, pos);
+    if (token.mac.size() != kHmacSize) {
+        std::fill(pos, pos + kHmacSize, 0);
+    } else {
+        std::copy(token.mac.begin(), token.mac.end(), pos);
+    }
+
+    return result;
+}
+
+hidl_vec<V3_0::KeyParameter> convertAndAddAuthToken(const hidl_vec<KeyParameter>& params,
+                                                    const HardwareAuthToken& authToken) {
+    hidl_vec<V3_0::KeyParameter> converted(params.size() + 1);
+    for (size_t i = 0; i < params.size(); ++i) {
+        converted[i] = convert(params[i]);
+    }
+    converted[params.size()].tag = V3_0::Tag::AUTH_TOKEN;
+    converted[params.size()].blob = authToken2HidlVec(authToken);
+
+    return converted;
+}
+
+KeyCharacteristics convert(const V3_0::KeyCharacteristics& chars) {
+    KeyCharacteristics converted;
+    converted.hardwareEnforced = convert(chars.teeEnforced);
+    converted.softwareEnforced = convert(chars.softwareEnforced);
+    return converted;
+}
+
+}  // namespace
+
+void Keymaster3::getVersionIfNeeded() {
+    if (haveVersion_) return;
+
+    auto rc = km3_dev_->getHardwareFeatures(
+        [&](bool isSecure, bool supportsEllipticCurve, bool supportsSymmetricCryptography,
+            bool supportsAttestation, bool supportsAllDigests, const hidl_string& keymasterName,
+            const hidl_string& keymasterAuthorName) {
+            securityLevel_ =
+                isSecure ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE;
+            supportsEllipticCurve_ = supportsEllipticCurve;
+            supportsSymmetricCryptography_ = supportsSymmetricCryptography;
+            supportsAttestation_ = supportsAttestation;
+            supportsAllDigests_ = supportsAllDigests;
+            keymasterName_ = keymasterName;
+            authorName_ = keymasterAuthorName;
+        });
+
+    CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware features";
+
+    if (securityLevel_ == SecurityLevel::SOFTWARE) {
+        majorVersion_ = 3;
+    } else if (supportsAttestation_) {
+        majorVersion_ = 3;  // Could be 2, doesn't matter.
+    } else if (supportsSymmetricCryptography_) {
+        majorVersion_ = 1;
+    } else {
+        majorVersion_ = 0;
+    }
+}
+
+Keymaster::VersionResult Keymaster3::halVersion() {
+    getVersionIfNeeded();
+    return {ErrorCode::OK, majorVersion_, securityLevel_, supportsEllipticCurve_};
+}
+
+Return<void> Keymaster3::getHardwareInfo(Keymaster3::getHardwareInfo_cb _hidl_cb) {
+    getVersionIfNeeded();
+    _hidl_cb(securityLevel_, keymasterName_ + " (wrapped by keystore::Keymaster3)", authorName_);
+    return Void();
+}
+
+Return<ErrorCode> Keymaster3::addRngEntropy(const hidl_vec<uint8_t>& data) {
+    auto rc = km3_dev_->addRngEntropy(data);
+    if (!rc.isOk()) {
+        return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    }
+    return convert(rc);
+}
+
+Return<void> Keymaster3::generateKey(const hidl_vec<KeyParameter>& keyParams,
+                                     generateKey_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
+                  const V3_0::KeyCharacteristics& characteristics) {
+        _hidl_cb(convert(error), keyBlob, convert(characteristics));
+    };
+    auto rc = km3_dev_->generateKey(convert(keyParams), cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                               const hidl_vec<uint8_t>& clientId,
+                                               const hidl_vec<uint8_t>& appData,
+                                               getKeyCharacteristics_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const V3_0::KeyCharacteristics& chars) {
+        _hidl_cb(convert(error), convert(chars));
+    };
+
+    auto rc = km3_dev_->getKeyCharacteristics(keyBlob, clientId, appData, cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                                   const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
+                  const V3_0::KeyCharacteristics& chars) {
+        _hidl_cb(convert(error), keyBlob, convert(chars));
+    };
+    auto rc = km3_dev_->importKey(convert(params), convert(keyFormat), keyData, cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                                   const hidl_vec<uint8_t>& clientId,
+                                   const hidl_vec<uint8_t>& appData, exportKey_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<uint8_t>& keyMaterial) {
+        _hidl_cb(convert(error), keyMaterial);
+    };
+    auto rc = km3_dev_->exportKey(convert(exportFormat), keyBlob, clientId, appData, cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                                   const hidl_vec<KeyParameter>& attestParams,
+                                   attestKey_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<hidl_vec<uint8_t>>& certChain) {
+        _hidl_cb(convert(error), certChain);
+    };
+    auto rc = km3_dev_->attestKey(keyToAttest, convert(attestParams), cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                                    const hidl_vec<KeyParameter>& upgradeParams,
+                                    upgradeKey_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<uint8_t>& upgradedKeyBlob) {
+        _hidl_cb(convert(error), upgradedKeyBlob);
+    };
+    auto rc = km3_dev_->upgradeKey(keyBlobToUpgrade, convert(upgradeParams), cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<ErrorCode> Keymaster3::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
+    auto rc = km3_dev_->deleteKey(keyBlob);
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    return convert(rc);
+}
+
+Return<ErrorCode> Keymaster3::deleteAllKeys() {
+    auto rc = km3_dev_->deleteAllKeys();
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    return convert(rc);
+}
+
+Return<ErrorCode> Keymaster3::destroyAttestationIds() {
+    auto rc = km3_dev_->destroyAttestationIds();
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    return convert(rc);
+}
+
+Return<void> Keymaster3::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                               const hidl_vec<KeyParameter>& inParams,
+                               const HardwareAuthToken& authToken, begin_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<V3_0::KeyParameter>& outParams,
+                  OperationHandle operationHandle) {
+        _hidl_cb(convert(error), convert(outParams), operationHandle);
+    };
+
+    auto rc =
+        km3_dev_->begin(convert(purpose), key, convertAndAddAuthToken(inParams, authToken), cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                                const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
+                                const VerificationToken& /* verificationToken */,
+                                update_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, uint32_t inputConsumed,
+                  const hidl_vec<V3_0::KeyParameter>& outParams, const hidl_vec<uint8_t>& output) {
+        _hidl_cb(convert(error), inputConsumed, convert(outParams), output);
+    };
+
+    auto rc =
+        km3_dev_->update(operationHandle, convertAndAddAuthToken(inParams, authToken), input, cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                                const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                                const HardwareAuthToken& authToken,
+                                const VerificationToken& /* verificationToken */,
+                                finish_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<V3_0::KeyParameter>& outParams,
+                  const hidl_vec<uint8_t>& output) {
+        _hidl_cb(convert(error), convert(outParams), output);
+    };
+
+    auto rc = km3_dev_->finish(operationHandle, convertAndAddAuthToken(inParams, authToken), input,
+                               signature, cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<ErrorCode> Keymaster3::abort(uint64_t operationHandle) {
+    auto rc = km3_dev_->abort(operationHandle);
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    return convert(rc);
+}
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/support/Keymaster4.cpp b/keymaster/4.0/support/Keymaster4.cpp
new file mode 100644
index 0000000..fdf78ae
--- /dev/null
+++ b/keymaster/4.0/support/Keymaster4.cpp
@@ -0,0 +1,48 @@
+/*
+**
+** Copyright 2017, 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 <keymasterV4_0/Keymaster4.h>
+
+#include <android-base/logging.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+void Keymaster4::getVersionIfNeeded() {
+    if (haveVersion_) return;
+
+    auto rc = dev_->getHardwareInfo([&](SecurityLevel securityLevel, auto...) {
+        securityLevel_ = securityLevel;
+        haveVersion_ = true;
+    });
+
+    CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware info";
+}
+
+Keymaster::VersionResult Keymaster4::halVersion() {
+    getVersionIfNeeded();
+    return {ErrorCode::OK, halMajorVersion(), securityLevel_, true};
+}
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/support/authorization_set.cpp b/keymaster/4.0/support/authorization_set.cpp
index de3e270..81cf365 100644
--- a/keymaster/4.0/support/authorization_set.cpp
+++ b/keymaster/4.0/support/authorization_set.cpp
@@ -441,6 +441,11 @@
     return Authorization(TAG_KEY_SIZE, key_size);
 }
 
+AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesKey(uint32_t key_size) {
+    Authorization(TAG_ALGORITHM, Algorithm::TRIPLE_DES);
+    return Authorization(TAG_KEY_SIZE, key_size);
+}
+
 AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
     Authorization(TAG_ALGORITHM, Algorithm::HMAC);
     Authorization(TAG_KEY_SIZE, key_size);
@@ -474,6 +479,11 @@
     return EncryptionKey();
 }
 
+AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesEncryptionKey(uint32_t key_size) {
+    TripleDesKey(key_size);
+    return EncryptionKey();
+}
+
 AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
     Authorization(TAG_PURPOSE, KeyPurpose::SIGN);
     return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY);
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
new file mode 100644
index 0000000..2686fcd
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
@@ -0,0 +1,58 @@
+/*
+ **
+ ** Copyright 2017, 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 HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
+#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
+
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+/**
+ * Keymaster abstracts the underlying V4_0::IKeymasterDevice.  There is one implementation
+ * (Keymaster4) which is a trivial passthrough and one that wraps a V3_0::IKeymasterDevice.
+ *
+ * The reason for adding this additional layer, rather than simply using the latest HAL directly and
+ * subclassing it to wrap any older HAL, is because this provides a place to put additional methods
+ * which clients can use when they need to distinguish between different underlying HAL versions,
+ * while still having to use only the latest interface.
+ */
+class Keymaster : public IKeymasterDevice {
+   public:
+    virtual ~Keymaster() {}
+
+    struct VersionResult {
+        ErrorCode error;
+        uint8_t majorVersion;
+        SecurityLevel securityLevel;
+        bool supportsEc;
+    };
+
+    virtual VersionResult halVersion() = 0;
+};
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
new file mode 100644
index 0000000..4054620
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
@@ -0,0 +1,133 @@
+/*
+ **
+ ** Copyright 2017, 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 HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
+#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
+
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+
+#include "Keymaster.h"
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+using IKeymaster3Device = ::android::hardware::keymaster::V3_0::IKeymasterDevice;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::details::return_status;
+
+class Keymaster3 : public Keymaster {
+   public:
+    using WrappedIKeymasterDevice = IKeymaster3Device;
+    Keymaster3(sp<IKeymaster3Device> km3_dev) : km3_dev_(km3_dev), haveVersion_(false) {}
+
+    VersionResult halVersion() override;
+
+    Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb);
+
+    Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override {
+        _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+        return Void();
+    }
+
+    Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>&,
+                                   computeSharedHmac_cb _hidl_cb) override {
+        _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+        return Void();
+    }
+
+    Return<void> verifyAuthorization(uint64_t, const hidl_vec<KeyParameter>&,
+                                     const HardwareAuthToken&,
+                                     verifyAuthorization_cb _hidl_cb) override {
+        _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+        return Void();
+    }
+
+    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
+    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+                             generateKey_cb _hidl_cb) override;
+    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                       const hidl_vec<uint8_t>& clientId,
+                                       const hidl_vec<uint8_t>& appData,
+                                       getKeyCharacteristics_cb _hidl_cb) override;
+    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                           const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override;
+
+    Return<void> importWrappedKey(const hidl_vec<uint8_t>& /* wrappedKeyData */,
+                                  const hidl_vec<uint8_t>& /* wrappingKeyBlob */,
+                                  const hidl_vec<uint8_t>& /* maskingKey */,
+                                  const hidl_vec<KeyParameter>& /* unwrappingParams */,
+                                  uint64_t /* passwordSid */, uint64_t /* biometricSid */,
+                                  importWrappedKey_cb _hidl_cb) {
+        _hidl_cb(ErrorCode::UNIMPLEMENTED, {}, {});
+        return Void();
+    }
+
+    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+                           exportKey_cb _hidl_cb) override;
+    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                           const hidl_vec<KeyParameter>& attestParams,
+                           attestKey_cb _hidl_cb) override;
+    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                            const hidl_vec<KeyParameter>& upgradeParams,
+                            upgradeKey_cb _hidl_cb) override;
+    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
+    Return<ErrorCode> deleteAllKeys() override;
+    Return<ErrorCode> destroyAttestationIds() override;
+    Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                       const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+                       begin_cb _hidl_cb) override;
+    Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, update_cb _hidl_cb) override;
+    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                        const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, finish_cb _hidl_cb) override;
+    Return<ErrorCode> abort(uint64_t operationHandle) override;
+
+   private:
+    void getVersionIfNeeded();
+
+    sp<IKeymaster3Device> km3_dev_;
+
+    bool haveVersion_;
+    uint8_t majorVersion_;
+    SecurityLevel securityLevel_;
+    bool supportsEllipticCurve_;
+    bool supportsSymmetricCryptography_;
+    bool supportsAttestation_;
+    bool supportsAllDigests_;
+    std::string keymasterName_;
+    std::string authorName_;
+};
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
new file mode 100644
index 0000000..86ef4f8
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
@@ -0,0 +1,156 @@
+/*
+ **
+ ** Copyright 2017, 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 HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
+#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
+
+#include "Keymaster.h"
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+using android::sp;
+using IKeymaster4Device = ::android::hardware::keymaster::V4_0::IKeymasterDevice;
+
+class Keymaster4 : public Keymaster {
+   public:
+    using WrappedIKeymasterDevice = IKeymaster4Device;
+    Keymaster4(sp<IKeymasterDevice> km4_dev) : haveVersion_(false), dev_(km4_dev) {}
+
+    uint8_t halMajorVersion() { return 4; }
+
+    VersionResult halVersion() override;
+
+    Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override {
+        return dev_->getHardwareInfo(_hidl_cb);
+    }
+
+    Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override {
+        return dev_->getHmacSharingParameters(_hidl_cb);
+    }
+
+    Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>& params,
+                                   computeSharedHmac_cb _hidl_cb) override {
+        return dev_->computeSharedHmac(params, _hidl_cb);
+    }
+
+    Return<void> verifyAuthorization(uint64_t operationHandle, const hidl_vec<KeyParameter>& params,
+                                     const HardwareAuthToken& authToken,
+                                     verifyAuthorization_cb _hidl_cb) override {
+        return dev_->verifyAuthorization(operationHandle, params, authToken, _hidl_cb);
+    }
+
+    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override {
+        return dev_->addRngEntropy(data);
+    }
+
+    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+                             generateKey_cb _hidl_cb) override {
+        return dev_->generateKey(keyParams, _hidl_cb);
+    }
+
+    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                       const hidl_vec<uint8_t>& clientId,
+                                       const hidl_vec<uint8_t>& appData,
+                                       getKeyCharacteristics_cb _hidl_cb) override {
+        return dev_->getKeyCharacteristics(keyBlob, clientId, appData, _hidl_cb);
+    }
+
+    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                           const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override {
+        return dev_->importKey(params, keyFormat, keyData, _hidl_cb);
+    }
+
+    Return<void> importWrappedKey(const hidl_vec<uint8_t>& wrappedKeyData,
+                                  const hidl_vec<uint8_t>& wrappingKeyBlob,
+                                  const hidl_vec<uint8_t>& maskingKey,
+                                  const hidl_vec<KeyParameter>& unwrappingParams,
+                                  uint64_t passwordSid, uint64_t biometricSid,
+                                  importWrappedKey_cb _hidl_cb) {
+        return dev_->importWrappedKey(wrappedKeyData, wrappingKeyBlob, maskingKey, unwrappingParams,
+                                      passwordSid, biometricSid, _hidl_cb);
+    }
+
+    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+                           exportKey_cb _hidl_cb) override {
+        return dev_->exportKey(exportFormat, keyBlob, clientId, appData, _hidl_cb);
+    }
+
+    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                           const hidl_vec<KeyParameter>& attestParams,
+                           attestKey_cb _hidl_cb) override {
+        return dev_->attestKey(keyToAttest, attestParams, _hidl_cb);
+    }
+
+    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                            const hidl_vec<KeyParameter>& upgradeParams,
+                            upgradeKey_cb _hidl_cb) override {
+        return dev_->upgradeKey(keyBlobToUpgrade, upgradeParams, _hidl_cb);
+    }
+
+    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override {
+        return dev_->deleteKey(keyBlob);
+    }
+
+    Return<ErrorCode> deleteAllKeys() override { return dev_->deleteAllKeys(); }
+
+    Return<ErrorCode> destroyAttestationIds() override { return dev_->destroyAttestationIds(); }
+
+    Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                       const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+                       begin_cb _hidl_cb) override {
+        return dev_->begin(purpose, key, inParams, authToken, _hidl_cb);
+    }
+
+    Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, update_cb _hidl_cb) override {
+        return dev_->update(operationHandle, inParams, input, authToken, verificationToken,
+                            _hidl_cb);
+    }
+
+    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                        const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, finish_cb _hidl_cb) override {
+        return dev_->finish(operationHandle, inParams, input, signature, authToken,
+                            verificationToken, _hidl_cb);
+    }
+
+    Return<ErrorCode> abort(uint64_t operationHandle) override {
+        return dev_->abort(operationHandle);
+    }
+
+   private:
+    void getVersionIfNeeded();
+
+    bool haveVersion_;
+    SecurityLevel securityLevel_;
+    sp<IKeymaster4Device> dev_;
+};
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
diff --git a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
index f67f192..09a06fe 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
@@ -258,6 +258,7 @@
     AuthorizationSetBuilder& EcdsaKey(uint32_t key_size);
     AuthorizationSetBuilder& EcdsaKey(EcCurve curve);
     AuthorizationSetBuilder& AesKey(uint32_t key_size);
+    AuthorizationSetBuilder& TripleDesKey(uint32_t key_size);
     AuthorizationSetBuilder& HmacKey(uint32_t key_size);
 
     AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent);
@@ -265,6 +266,7 @@
     AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size);
     AuthorizationSetBuilder& EcdsaSigningKey(EcCurve curve);
     AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size);
+    AuthorizationSetBuilder& TripleDesEncryptionKey(uint32_t key_size);
 
     AuthorizationSetBuilder& SigningKey();
     AuthorizationSetBuilder& EncryptionKey();
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index 2f9f88b..0dfc735 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -329,6 +329,94 @@
     return accessTagValue(ttag, param);
 }
 
+inline bool operator==(const KeyParameter& a, const KeyParameter& b) {
+    if (a.tag != b.tag) {
+        return false;
+    }
+
+    switch (a.tag) {
+        /* Boolean tags */
+        case Tag::INVALID:
+        case Tag::CALLER_NONCE:
+        case Tag::INCLUDE_UNIQUE_ID:
+        case Tag::BOOTLOADER_ONLY:
+        case Tag::NO_AUTH_REQUIRED:
+        case Tag::ALLOW_WHILE_ON_BODY:
+        case Tag::ROLLBACK_RESISTANCE:
+        case Tag::RESET_SINCE_ID_ROTATION:
+        case Tag::TRUSTED_USER_PRESENCE_REQUIRED:
+            return true;
+
+        /* Integer tags */
+        case Tag::KEY_SIZE:
+        case Tag::MIN_MAC_LENGTH:
+        case Tag::MIN_SECONDS_BETWEEN_OPS:
+        case Tag::MAX_USES_PER_BOOT:
+        case Tag::OS_VERSION:
+        case Tag::OS_PATCHLEVEL:
+        case Tag::MAC_LENGTH:
+        case Tag::AUTH_TIMEOUT:
+        case Tag::VENDOR_PATCHLEVEL:
+        case Tag::BOOT_PATCHLEVEL:
+            return a.f.integer == b.f.integer;
+
+        /* Long integer tags */
+        case Tag::RSA_PUBLIC_EXPONENT:
+        case Tag::USER_SECURE_ID:
+            return a.f.longInteger == b.f.longInteger;
+
+        /* Date-time tags */
+        case Tag::ACTIVE_DATETIME:
+        case Tag::ORIGINATION_EXPIRE_DATETIME:
+        case Tag::USAGE_EXPIRE_DATETIME:
+        case Tag::CREATION_DATETIME:
+            return a.f.dateTime == b.f.dateTime;
+
+        /* Bytes tags */
+        case Tag::APPLICATION_ID:
+        case Tag::APPLICATION_DATA:
+        case Tag::ROOT_OF_TRUST:
+        case Tag::UNIQUE_ID:
+        case Tag::ATTESTATION_CHALLENGE:
+        case Tag::ATTESTATION_APPLICATION_ID:
+        case Tag::ATTESTATION_ID_BRAND:
+        case Tag::ATTESTATION_ID_DEVICE:
+        case Tag::ATTESTATION_ID_PRODUCT:
+        case Tag::ATTESTATION_ID_SERIAL:
+        case Tag::ATTESTATION_ID_IMEI:
+        case Tag::ATTESTATION_ID_MEID:
+        case Tag::ATTESTATION_ID_MANUFACTURER:
+        case Tag::ATTESTATION_ID_MODEL:
+        case Tag::ASSOCIATED_DATA:
+        case Tag::NONCE:
+            return a.blob == b.blob;
+
+        /* Enum tags */
+        case Tag::PURPOSE:
+            return a.f.purpose == b.f.purpose;
+        case Tag::ALGORITHM:
+            return a.f.algorithm == b.f.algorithm;
+        case Tag::BLOCK_MODE:
+            return a.f.blockMode == b.f.blockMode;
+        case Tag::DIGEST:
+            return a.f.digest == b.f.digest;
+        case Tag::PADDING:
+            return a.f.paddingMode == b.f.paddingMode;
+        case Tag::EC_CURVE:
+            return a.f.ecCurve == b.f.ecCurve;
+        case Tag::BLOB_USAGE_REQUIREMENTS:
+            return a.f.keyBlobUsageRequirements == b.f.keyBlobUsageRequirements;
+        case Tag::USER_AUTH_TYPE:
+            return a.f.integer == b.f.integer;
+        case Tag::ORIGIN:
+            return a.f.origin == b.f.origin;
+        case Tag::HARDWARE_TYPE:
+            return a.f.hardwareType == b.f.hardwareType;
+    }
+
+    return false;
+}
+
 }  // namespace V4_0
 }  // namespace keymaster
 }  // namespace hardware
diff --git a/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h b/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h
index 2d3bcf1..cc71dd1 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h
@@ -14,6 +14,11 @@
  * limitations under the License.
  */
 
+#ifndef HARDWARE_INTERFACES_KEYMASTER_4_0_SUPPORT_OPENSSL_UTILS_H_
+#define HARDWARE_INTERFACES_KEYMASTER_4_0_SUPPORT_OPENSSL_UTILS_H_
+
+#include <android/hardware/keymaster/4.0/types.h>
+
 template <typename T, void (*F)(T*)>
 struct UniquePtrDeleter {
     void operator()(T* p) const { F(p); }
@@ -51,3 +56,5 @@
     }
     return nullptr;
 }
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_4_0_SUPPORT_OPENSSL_UTILS_H_
diff --git a/keymaster/4.0/types.hal b/keymaster/4.0/types.hal
index 0c890bd..5714c4d 100644
--- a/keymaster/4.0/types.hal
+++ b/keymaster/4.0/types.hal
@@ -136,6 +136,51 @@
                                                 * if device is still on-body (requires secure
                                                 * on-body sensor. */
 
+    /**
+     * TRUSTED_USER_PRESENCE_REQUIRED is an optional feature that specifies that this key must be
+     * unusable except when the user has provided proof of physical presence.  Proof of physical
+     * presence must be a signal that cannot be triggered by an attacker who doesn't have one of:
+     *
+     *    a) Physical control of the device or
+     *
+     *    b) Control of the secure environment that holds the key.
+     *
+     * For instance, proof of user identity may be considered proof of presence if it meets the
+     * requirements.  However, proof of identity established in one security domain (e.g. TEE) does
+     * not constitute proof of presence in another security domain (e.g. StrongBox), and no
+     * mechanism analogous to the authentication token is defined for communicating proof of
+     * presence across security domains.
+     *
+     * Some examples:
+     *
+     *     A hardware button hardwired to a pin on a StrongBox device in such a way that nothing
+     *     other than a button press can trigger the signal constitutes proof of physical presence
+     *     for StrongBox keys.
+     *
+     *     Fingerprint authentication provides proof of presence (and identity) for TEE keys if the
+     *     TEE has exclusive control of the fingerprint scanner and performs fingerprint matching.
+     *
+     *     Password authentication does not provide proof of presence to either TEE or StrongBox,
+     *     even if TEE or StrongBox does the password matching, because password input is handled by
+     *     the non-secure world, which means an attacker who has compromised Android can spoof
+     *     password authentication.
+     *
+     * Note that no mechanism is defined for delivering proof of presence to Keymaster,
+     * except perhaps as implied by an auth token.  This means that Keymaster must be able to check
+     * proof of presence some other way.  Further, the proof of presence must be performed between
+     * begin() and the first call to update() or finish().  If the first update() or the finish()
+     * call is made without proof of presence, the keymaster method must return
+     * ErrorCode::PROOF_OF_PRESENCE_REQUIRED and abort the operation.  The caller must delay the
+     * update() or finish() call until proof of presence has been provided, which means the caller
+     * must also have some mechanism for verifying that the proof has been provided.
+     *
+     * Only one operation requiring TUP may be in flight at a time.  If begin() has already been
+     * called on one key with TRUSTED_USER_PRESENCE_REQUIRED, and another begin() comes in for that
+     * key or another with TRUSTED_USER_PRESENCE_REQUIRED, Keymaster must return
+     * ErrorCode::CONCURRENT_PROOF_OF_PRESENCE_REQUESTED.
+     */
+    TRUSTED_USER_PRESENCE_REQUIRED = TagType:BOOL | 507,
+
     /* Application access control */
     APPLICATION_ID = TagType:BYTES | 601, /* Byte string identifying the authorized application. */
 
@@ -174,6 +219,30 @@
     ATTESTATION_ID_MODEL = TagType:BYTES | 717, /* Used to provide the device's model name to be
                                                  * included in attestation */
 
+    /**
+     * Patch level of vendor image.  The value is an integer of the form YYYYMM, where YYYY is the
+     * four-digit year when the vendor image was released and MM is the two-digit month.  During
+     * each boot, the bootloader must provide the patch level of the vendor image to keymaser
+     * (mechanism is implemntation-defined).  When keymaster keys are created or updated, the
+     * VENDOR_PATCHLEVEL tag must be cryptographically bound to the keys, with the current value as
+     * provided by the bootloader.  When keys are used, keymaster must verify that the
+     * VENDOR_PATCHLEVEL bound to the key matches the current value.  If they do not match,
+     * keymaster must return ErrorCode::KEY_REQUIRES_UPGRADE.  The client must then call upgradeKey.
+     */
+    VENDOR_PATCHLEVEL = TagType:UINT | 718,
+
+    /**
+     * Patch level of boot image.  The value is an integer of the form YYYYMM, where YYYY is the
+     * four-digit year when the boot image was released and MM is the two-digit month.  During each
+     * boot, the bootloader must provide the patch level of the boot image to keymaser (mechanism is
+     * implemntation-defined).  When keymaster keys are created or updated, the BOOT_PATCHLEVEL tag
+     * must be cryptographically bound to the keys, with the current value as provided by the
+     * bootloader.  When keys are used, keymaster must verify that the BOOT_PATCHLEVEL bound to the
+     * key matches the current value.  If they do not match, keymaster must return
+     * ErrorCode::KEY_REQUIRES_UPGRADE.  The client must then call upgradeKey.
+     */
+    BOOT_PATCHLEVEL = TagType:UINT | 719,
+
     /* Tags used only to provide data to or receive data from operations */
     ASSOCIATED_DATA = TagType:BYTES | 1000, /* Used to provide associated data for AEAD modes. */
     NONCE = TagType:BYTES | 1001,           /* Nonce or Initialization Vector */
@@ -195,6 +264,7 @@
 
     /** Block ciphers algorithms */
     AES = 32,
+    TRIPLE_DES = 33,
 
     /** MAC algorithms */
     HMAC = 128,
@@ -381,6 +451,8 @@
     CANNOT_ATTEST_IDS = -66,
     ROLLBACK_RESISTANCE_UNAVAILABLE = -67,
     HARDWARE_TYPE_UNAVAILABLE = -68,
+    PROOF_OF_PRESENCE_REQUIRED = -69,
+    CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70,
 
     UNIMPLEMENTED = -100,
     VERSION_MISMATCH = -101,
@@ -591,7 +663,7 @@
     SecurityLevel securityLevel;
 
     /**
-     * 32-byte HMAC of the above values, computed as:
+     * 32-byte HMAC-SHA256 of the above values, computed as:
      *
      *    HMAC(H,
      *         "Auth Verification" || challenge || timestamp || securityLevel || parametersVerified)
diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index 3c3063c..d74a16f 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -18,6 +18,9 @@
     name: "VtsHalKeymasterV4_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
+        "HmacKeySharingTest.cpp",
+        "KeymasterHidlTest.cpp",
+        "VerificationTokenTest.cpp",
         "keymaster_hidl_hal_test.cpp",
     ],
     static_libs: [
diff --git a/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp b/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
new file mode 100644
index 0000000..96c47a8
--- /dev/null
+++ b/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2017 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 "KeymasterHidlTest.h"
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace test {
+
+/**
+ * HmacKeySharingTest extends KeymasterHidlTest with some utilities that make writing HMAC sharing
+ * tests easier.
+ */
+class HmacKeySharingTest : public KeymasterHidlTest {
+   protected:
+    struct GetParamsResult {
+        ErrorCode error;
+        HmacSharingParameters params;
+        auto tie() { return std::tie(error, params); }
+    };
+
+    struct ComputeHmacResult {
+        ErrorCode error;
+        HidlBuf sharing_check;
+        auto tie() { return std::tie(error, sharing_check); }
+    };
+
+    using KeymasterVec = std::vector<sp<IKeymasterDevice>>;
+    using ByteString = std::basic_string<uint8_t>;
+    // using NonceVec = std::vector<HidlBuf>;
+
+    GetParamsResult getHmacSharingParameters(IKeymasterDevice& keymaster) {
+        GetParamsResult result;
+        EXPECT_TRUE(keymaster
+                        .getHmacSharingParameters([&](auto error, auto params) {
+                            result.tie() = std::tie(error, params);
+                        })
+                        .isOk());
+        return result;
+    }
+
+    hidl_vec<HmacSharingParameters> getHmacSharingParameters(const KeymasterVec& keymasters) {
+        std::vector<HmacSharingParameters> paramsVec;
+        for (auto& keymaster : keymasters) {
+            auto result = getHmacSharingParameters(*keymaster);
+            EXPECT_EQ(ErrorCode::OK, result.error);
+            if (result.error == ErrorCode::OK) paramsVec.push_back(std::move(result.params));
+        }
+        return paramsVec;
+    }
+
+    ComputeHmacResult computeSharedHmac(IKeymasterDevice& keymaster,
+                                        const hidl_vec<HmacSharingParameters>& params) {
+        ComputeHmacResult result;
+        EXPECT_TRUE(keymaster
+                        .computeSharedHmac(params,
+                                           [&](auto error, auto params) {
+                                               result.tie() = std::tie(error, params);
+                                           })
+                        .isOk());
+        return result;
+    }
+
+    std::vector<ComputeHmacResult> computeSharedHmac(
+        const KeymasterVec& keymasters, const hidl_vec<HmacSharingParameters>& paramsVec) {
+        std::vector<ComputeHmacResult> resultVec;
+        for (auto& keymaster : keymasters) {
+            resultVec.push_back(computeSharedHmac(*keymaster, paramsVec));
+        }
+        return resultVec;
+    }
+
+    std::vector<ByteString> copyNonces(const hidl_vec<HmacSharingParameters>& paramsVec) {
+        std::vector<ByteString> nonces;
+        for (auto& param : paramsVec) {
+            nonces.emplace_back(param.nonce.data(), param.nonce.size());
+        }
+        return nonces;
+    }
+
+    void verifyResponses(const HidlBuf& expected, const std::vector<ComputeHmacResult>& responses) {
+        for (auto& response : responses) {
+            EXPECT_EQ(ErrorCode::OK, response.error);
+            EXPECT_EQ(expected, response.sharing_check) << "Sharing check values should match.";
+        }
+    }
+};
+
+TEST_F(HmacKeySharingTest, GetParameters) {
+    auto result1 = getHmacSharingParameters(keymaster());
+    EXPECT_EQ(ErrorCode::OK, result1.error);
+
+    auto result2 = getHmacSharingParameters(keymaster());
+    EXPECT_EQ(ErrorCode::OK, result2.error);
+
+    ASSERT_EQ(result1.params.seed, result2.params.seed)
+        << "A given keymaster should always return the same seed.";
+    ASSERT_EQ(result1.params.nonce, result2.params.nonce)
+        << "A given keymaster should always return the same nonce until restart.";
+}
+
+TEST_F(HmacKeySharingTest, ComputeSharedHmac) {
+    auto params = getHmacSharingParameters(all_keymasters());
+    ASSERT_EQ(all_keymasters().size(), params.size())
+        << "One or more keymasters failed to provide parameters.";
+
+    auto nonces = copyNonces(params);
+    EXPECT_EQ(all_keymasters().size(), nonces.size());
+    std::sort(nonces.begin(), nonces.end());
+    std::unique(nonces.begin(), nonces.end());
+    EXPECT_EQ(all_keymasters().size(), nonces.size());
+
+    auto responses = computeSharedHmac(all_keymasters(), params);
+    ASSERT_GT(responses.size(), 0U);
+    verifyResponses(responses[0].sharing_check, responses);
+
+    // Do it a second time.  Should get the same answers.
+    params = getHmacSharingParameters(all_keymasters());
+    ASSERT_EQ(all_keymasters().size(), params.size())
+        << "One or more keymasters failed to provide parameters.";
+
+    responses = computeSharedHmac(all_keymasters(), params);
+    ASSERT_GT(responses.size(), 0U);
+    verifyResponses(responses[0].sharing_check, responses);
+}
+
+template <class F>
+class final_action {
+   public:
+    explicit final_action(F f) : f_(move(f)) {}
+    ~final_action() { f_(); }
+
+   private:
+    F f_;
+};
+
+template <class F>
+inline final_action<F> finally(const F& f) {
+    return final_action<F>(f);
+}
+
+TEST_F(HmacKeySharingTest, ComputeSharedHmacCorruptNonce) {
+    // Important: The execution of this test gets the keymaster implementations on the device out of
+    // sync with respect to the HMAC key.  Granted that VTS tests aren't run on in-use production
+    // devices, this still has the potential to cause confusion.  To mitigate that, we always
+    // (barring crashes :-/) re-run the unmodified agreement process on our way out.
+    auto fixup_hmac = finally(
+        [&]() { computeSharedHmac(all_keymasters(), getHmacSharingParameters(all_keymasters())); });
+
+    auto params = getHmacSharingParameters(all_keymasters());
+    ASSERT_EQ(all_keymasters().size(), params.size())
+        << "One or more keymasters failed to provide parameters.";
+
+    // All should be well in the normal case
+    auto responses = computeSharedHmac(all_keymasters(), params);
+
+    ASSERT_GT(responses.size(), 0U);
+    HidlBuf correct_response = responses[0].sharing_check;
+    verifyResponses(correct_response, responses);
+
+    // Pick a random param, a random byte within the param's nonce, and a random bit within
+    // the byte.  Flip that bit.
+    size_t param_to_tweak = rand() % params.size();
+    uint8_t byte_to_tweak = rand() % sizeof(params[param_to_tweak].nonce);
+    uint8_t bit_to_tweak = rand() % 8;
+    params[param_to_tweak].nonce[byte_to_tweak] ^= (1 << bit_to_tweak);
+
+    responses = computeSharedHmac(all_keymasters(), params);
+    for (size_t i = 0; i < responses.size(); ++i) {
+        if (i == param_to_tweak) {
+            EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
+                << "Keymaster that provided tweaked param should fail to compute HMAC key";
+        } else {
+            EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
+            EXPECT_NE(correct_response, responses[i].sharing_check)
+                << "Others should calculate a different HMAC key, due to the tweaked nonce.";
+        }
+    }
+}
+
+TEST_F(HmacKeySharingTest, ComputeSharedHmacCorruptSeed) {
+    // Important: The execution of this test gets the keymaster implementations on the device out of
+    // sync with respect to the HMAC key.  Granted that VTS tests aren't run on in-use production
+    // devices, this still has the potential to cause confusion.  To mitigate that, we always
+    // (barring crashes :-/) re-run the unmodified agreement process on our way out.
+    auto fixup_hmac = finally(
+        [&]() { computeSharedHmac(all_keymasters(), getHmacSharingParameters(all_keymasters())); });
+
+    auto params = getHmacSharingParameters(all_keymasters());
+    ASSERT_EQ(all_keymasters().size(), params.size())
+        << "One or more keymasters failed to provide parameters.";
+
+    // All should be well in the normal case
+    auto responses = computeSharedHmac(all_keymasters(), params);
+
+    ASSERT_GT(responses.size(), 0U);
+    HidlBuf correct_response = responses[0].sharing_check;
+    verifyResponses(correct_response, responses);
+
+    // Pick a random param and modify the seed.  We just increase the seed length by 1.  It doesn't
+    // matter what value is in the additional byte; it changes the seed regardless.
+    auto param_to_tweak = rand() % params.size();
+    auto& to_tweak = params[param_to_tweak].seed;
+    to_tweak.resize(to_tweak.size() + 1);
+
+    responses = computeSharedHmac(all_keymasters(), params);
+    for (size_t i = 0; i < responses.size(); ++i) {
+        if (i == param_to_tweak) {
+            EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
+                << "Keymaster that provided tweaked param should fail to compute HMAC key ";
+        } else {
+            EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
+            EXPECT_NE(correct_response, responses[i].sharing_check)
+                << "Others should calculate a different HMAC key, due to the tweaked nonce.";
+        }
+    }
+}
+
+}  // namespace test
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
new file mode 100644
index 0000000..37d8c42
--- /dev/null
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -0,0 +1,592 @@
+/*
+ * Copyright (C) 2017 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 "KeymasterHidlTest.h"
+
+#include <android/hidl/manager/1.0/IServiceManager.h>
+
+#include <keymasterV4_0/key_param_output.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+
+::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set) {
+    if (set.size() == 0)
+        os << "(Empty)" << ::std::endl;
+    else {
+        os << "\n";
+        for (size_t i = 0; i < set.size(); ++i) os << set[i] << ::std::endl;
+    }
+    return os;
+}
+
+namespace test {
+
+sp<IKeymasterDevice> KeymasterHidlTest::keymaster_;
+std::vector<sp<IKeymasterDevice>> KeymasterHidlTest::all_keymasters_;
+uint32_t KeymasterHidlTest::os_version_;
+uint32_t KeymasterHidlTest::os_patch_level_;
+SecurityLevel KeymasterHidlTest::securityLevel_;
+hidl_string KeymasterHidlTest::name_;
+hidl_string KeymasterHidlTest::author_;
+
+void KeymasterHidlTest::SetUpTestCase() {
+    string service_name = KeymasterHidlEnvironment::Instance()->getServiceName<IKeymasterDevice>();
+    keymaster_ = ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(service_name);
+    ASSERT_NE(keymaster_, nullptr);
+
+    ASSERT_TRUE(keymaster_
+                    ->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
+                                          const hidl_string& author) {
+                        securityLevel_ = securityLevel;
+                        name_ = name;
+                        author_ = author;
+                    })
+                    .isOk());
+
+    os_version_ = ::keymaster::GetOsVersion();
+    os_patch_level_ = ::keymaster::GetOsPatchlevel();
+
+    auto service_manager = android::hidl::manager::V1_0::IServiceManager::getService();
+    ASSERT_NE(nullptr, service_manager.get());
+
+    all_keymasters_.push_back(keymaster_);
+    service_manager->listByInterface(
+        IKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) {
+            for (auto& name : names) {
+                if (name == service_name) continue;
+                auto keymaster =
+                    ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(name);
+                ASSERT_NE(keymaster, nullptr);
+                all_keymasters_.push_back(keymaster);
+            }
+        });
+}
+
+ErrorCode KeymasterHidlTest::GenerateKey(const AuthorizationSet& key_desc, HidlBuf* key_blob,
+                                         KeyCharacteristics* key_characteristics) {
+    EXPECT_NE(key_blob, nullptr) << "Key blob pointer must not be null.  Test bug";
+    EXPECT_EQ(0U, key_blob->size()) << "Key blob not empty before generating key.  Test bug.";
+    EXPECT_NE(key_characteristics, nullptr)
+        << "Previous characteristics not deleted before generating key.  Test bug.";
+
+    ErrorCode error;
+    EXPECT_TRUE(keymaster_
+                    ->generateKey(key_desc.hidl_data(),
+                                  [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
+                                      const KeyCharacteristics& hidl_key_characteristics) {
+                                      error = hidl_error;
+                                      *key_blob = hidl_key_blob;
+                                      *key_characteristics = hidl_key_characteristics;
+                                  })
+                    .isOk());
+    // On error, blob & characteristics should be empty.
+    if (error != ErrorCode::OK) {
+        EXPECT_EQ(0U, key_blob->size());
+        EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
+                       key_characteristics->hardwareEnforced.size()));
+    }
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::GenerateKey(const AuthorizationSet& key_desc) {
+    return GenerateKey(key_desc, &key_blob_, &key_characteristics_);
+}
+
+ErrorCode KeymasterHidlTest::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+                                       const string& key_material, HidlBuf* key_blob,
+                                       KeyCharacteristics* key_characteristics) {
+    ErrorCode error;
+    EXPECT_TRUE(keymaster_
+                    ->importKey(key_desc.hidl_data(), format, HidlBuf(key_material),
+                                [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
+                                    const KeyCharacteristics& hidl_key_characteristics) {
+                                    error = hidl_error;
+                                    *key_blob = hidl_key_blob;
+                                    *key_characteristics = hidl_key_characteristics;
+                                })
+                    .isOk());
+    // On error, blob & characteristics should be empty.
+    if (error != ErrorCode::OK) {
+        EXPECT_EQ(0U, key_blob->size());
+        EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
+                       key_characteristics->hardwareEnforced.size()));
+    }
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+                                       const string& key_material) {
+    return ImportKey(key_desc, format, key_material, &key_blob_, &key_characteristics_);
+}
+
+ErrorCode KeymasterHidlTest::ImportWrappedKey(string wrapped_key, string wrapping_key,
+                                              const AuthorizationSet& wrapping_key_desc,
+                                              string masking_key,
+                                              const AuthorizationSet& unwrapping_params) {
+    ErrorCode error;
+    ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key);
+    EXPECT_TRUE(keymaster_
+                    ->importWrappedKey(HidlBuf(wrapped_key), key_blob_, HidlBuf(masking_key),
+                                       unwrapping_params.hidl_data(), 0 /* passwordSid */,
+                                       0 /* biometricSid */,
+                                       [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
+                                           const KeyCharacteristics& hidl_key_characteristics) {
+                                           error = hidl_error;
+                                           key_blob_ = hidl_key_blob;
+                                           key_characteristics_ = hidl_key_characteristics;
+                                       })
+                    .isOk());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::ExportKey(KeyFormat format, const HidlBuf& key_blob,
+                                       const HidlBuf& client_id, const HidlBuf& app_data,
+                                       HidlBuf* key_material) {
+    ErrorCode error;
+    EXPECT_TRUE(keymaster_
+                    ->exportKey(format, key_blob, client_id, app_data,
+                                [&](ErrorCode hidl_error_code, const HidlBuf& hidl_key_material) {
+                                    error = hidl_error_code;
+                                    *key_material = hidl_key_material;
+                                })
+                    .isOk());
+    // On error, blob should be empty.
+    if (error != ErrorCode::OK) {
+        EXPECT_EQ(0U, key_material->size());
+    }
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::ExportKey(KeyFormat format, HidlBuf* key_material) {
+    HidlBuf client_id, app_data;
+    return ExportKey(format, key_blob_, client_id, app_data, key_material);
+}
+
+ErrorCode KeymasterHidlTest::DeleteKey(HidlBuf* key_blob, bool keep_key_blob) {
+    auto rc = keymaster_->deleteKey(*key_blob);
+    if (!keep_key_blob) *key_blob = HidlBuf();
+    if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
+    return rc;
+}
+
+ErrorCode KeymasterHidlTest::DeleteKey(bool keep_key_blob) {
+    return DeleteKey(&key_blob_, keep_key_blob);
+}
+
+ErrorCode KeymasterHidlTest::DeleteAllKeys() {
+    ErrorCode error = keymaster_->deleteAllKeys();
+    return error;
+}
+
+void KeymasterHidlTest::CheckedDeleteKey(HidlBuf* key_blob, bool keep_key_blob) {
+    auto rc = DeleteKey(key_blob, keep_key_blob);
+    EXPECT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED);
+}
+
+void KeymasterHidlTest::CheckedDeleteKey() {
+    CheckedDeleteKey(&key_blob_);
+}
+
+ErrorCode KeymasterHidlTest::GetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id,
+                                                const HidlBuf& app_data,
+                                                KeyCharacteristics* key_characteristics) {
+    ErrorCode error = ErrorCode::UNKNOWN_ERROR;
+    EXPECT_TRUE(
+        keymaster_
+            ->getKeyCharacteristics(
+                key_blob, client_id, app_data,
+                [&](ErrorCode hidl_error, const KeyCharacteristics& hidl_key_characteristics) {
+                    error = hidl_error, *key_characteristics = hidl_key_characteristics;
+                })
+            .isOk());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::GetCharacteristics(const HidlBuf& key_blob,
+                                                KeyCharacteristics* key_characteristics) {
+    HidlBuf client_id, app_data;
+    return GetCharacteristics(key_blob, client_id, app_data, key_characteristics);
+}
+
+ErrorCode KeymasterHidlTest::Begin(KeyPurpose purpose, const HidlBuf& key_blob,
+                                   const AuthorizationSet& in_params, AuthorizationSet* out_params,
+                                   OperationHandle* op_handle) {
+    SCOPED_TRACE("Begin");
+    ErrorCode error;
+    OperationHandle saved_handle = *op_handle;
+    EXPECT_TRUE(keymaster_
+                    ->begin(purpose, key_blob, in_params.hidl_data(), HardwareAuthToken(),
+                            [&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
+                                uint64_t hidl_op_handle) {
+                                error = hidl_error;
+                                *out_params = hidl_out_params;
+                                *op_handle = hidl_op_handle;
+                            })
+                    .isOk());
+    if (error != ErrorCode::OK) {
+        // Some implementations may modify *op_handle on error.
+        *op_handle = saved_handle;
+    }
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
+                                   AuthorizationSet* out_params) {
+    SCOPED_TRACE("Begin");
+    EXPECT_EQ(kOpHandleSentinel, op_handle_);
+    return Begin(purpose, key_blob_, in_params, out_params, &op_handle_);
+}
+
+ErrorCode KeymasterHidlTest::Begin(KeyPurpose purpose, const AuthorizationSet& in_params) {
+    SCOPED_TRACE("Begin");
+    AuthorizationSet out_params;
+    ErrorCode error = Begin(purpose, in_params, &out_params);
+    EXPECT_TRUE(out_params.empty());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Update(OperationHandle op_handle, const AuthorizationSet& in_params,
+                                    const string& input, AuthorizationSet* out_params,
+                                    string* output, size_t* input_consumed) {
+    SCOPED_TRACE("Update");
+    ErrorCode error;
+    EXPECT_TRUE(keymaster_
+                    ->update(op_handle, in_params.hidl_data(), HidlBuf(input), HardwareAuthToken(),
+                             VerificationToken(),
+                             [&](ErrorCode hidl_error, uint32_t hidl_input_consumed,
+                                 const hidl_vec<KeyParameter>& hidl_out_params,
+                                 const HidlBuf& hidl_output) {
+                                 error = hidl_error;
+                                 out_params->push_back(AuthorizationSet(hidl_out_params));
+                                 output->append(hidl_output.to_string());
+                                 *input_consumed = hidl_input_consumed;
+                             })
+                    .isOk());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Update(const string& input, string* out, size_t* input_consumed) {
+    SCOPED_TRACE("Update");
+    AuthorizationSet out_params;
+    ErrorCode error = Update(op_handle_, AuthorizationSet() /* in_params */, input, &out_params,
+                             out, input_consumed);
+    EXPECT_TRUE(out_params.empty());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Finish(OperationHandle op_handle, const AuthorizationSet& in_params,
+                                    const string& input, const string& signature,
+                                    AuthorizationSet* out_params, string* output) {
+    SCOPED_TRACE("Finish");
+    ErrorCode error;
+    EXPECT_TRUE(
+        keymaster_
+            ->finish(op_handle, in_params.hidl_data(), HidlBuf(input), HidlBuf(signature),
+                     HardwareAuthToken(), VerificationToken(),
+                     [&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
+                         const HidlBuf& hidl_output) {
+                         error = hidl_error;
+                         *out_params = hidl_out_params;
+                         output->append(hidl_output.to_string());
+                     })
+            .isOk());
+    op_handle_ = kOpHandleSentinel;  // So dtor doesn't Abort().
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Finish(const string& message, string* output) {
+    SCOPED_TRACE("Finish");
+    AuthorizationSet out_params;
+    string finish_output;
+    ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message,
+                             "" /* signature */, &out_params, output);
+    if (error != ErrorCode::OK) {
+        return error;
+    }
+    EXPECT_EQ(0U, out_params.size());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Finish(const string& message, const string& signature,
+                                    string* output) {
+    SCOPED_TRACE("Finish");
+    AuthorizationSet out_params;
+    ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message, signature,
+                             &out_params, output);
+    op_handle_ = kOpHandleSentinel;  // So dtor doesn't Abort().
+    if (error != ErrorCode::OK) {
+        return error;
+    }
+    EXPECT_EQ(0U, out_params.size());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Abort(OperationHandle op_handle) {
+    SCOPED_TRACE("Abort");
+    auto retval = keymaster_->abort(op_handle);
+    EXPECT_TRUE(retval.isOk());
+    return retval;
+}
+
+void KeymasterHidlTest::AbortIfNeeded() {
+    SCOPED_TRACE("AbortIfNeeded");
+    if (op_handle_ != kOpHandleSentinel) {
+        EXPECT_EQ(ErrorCode::OK, Abort(op_handle_));
+        op_handle_ = kOpHandleSentinel;
+    }
+}
+
+ErrorCode KeymasterHidlTest::AttestKey(const HidlBuf& key_blob,
+                                       const AuthorizationSet& attest_params,
+                                       hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
+    SCOPED_TRACE("AttestKey");
+    ErrorCode error;
+    auto rc = keymaster_->attestKey(
+        key_blob, attest_params.hidl_data(),
+        [&](ErrorCode hidl_error, const hidl_vec<hidl_vec<uint8_t>>& hidl_cert_chain) {
+            error = hidl_error;
+            *cert_chain = hidl_cert_chain;
+        });
+
+    EXPECT_TRUE(rc.isOk()) << rc.description();
+    if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
+
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::AttestKey(const AuthorizationSet& attest_params,
+                                       hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
+    SCOPED_TRACE("AttestKey");
+    return AttestKey(key_blob_, attest_params, cert_chain);
+}
+
+string KeymasterHidlTest::ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation,
+                                         const string& message, const AuthorizationSet& in_params,
+                                         AuthorizationSet* out_params) {
+    SCOPED_TRACE("ProcessMessage");
+    AuthorizationSet begin_out_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(operation, key_blob, in_params, &begin_out_params, &op_handle_));
+
+    string unused;
+    AuthorizationSet finish_params;
+    AuthorizationSet finish_out_params;
+    string output;
+    EXPECT_EQ(ErrorCode::OK,
+              Finish(op_handle_, finish_params, message, unused, &finish_out_params, &output));
+    op_handle_ = kOpHandleSentinel;
+
+    out_params->push_back(begin_out_params);
+    out_params->push_back(finish_out_params);
+    return output;
+}
+
+string KeymasterHidlTest::SignMessage(const HidlBuf& key_blob, const string& message,
+                                      const AuthorizationSet& params) {
+    SCOPED_TRACE("SignMessage");
+    AuthorizationSet out_params;
+    string signature = ProcessMessage(key_blob, KeyPurpose::SIGN, message, params, &out_params);
+    EXPECT_TRUE(out_params.empty());
+    return signature;
+}
+
+string KeymasterHidlTest::SignMessage(const string& message, const AuthorizationSet& params) {
+    SCOPED_TRACE("SignMessage");
+    return SignMessage(key_blob_, message, params);
+}
+
+string KeymasterHidlTest::MacMessage(const string& message, Digest digest, size_t mac_length) {
+    SCOPED_TRACE("MacMessage");
+    return SignMessage(
+        key_blob_, message,
+        AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
+}
+
+void KeymasterHidlTest::CheckHmacTestVector(const string& key, const string& message, Digest digest,
+                                            const string& expected_mac) {
+    SCOPED_TRACE("CheckHmacTestVector");
+    ASSERT_EQ(ErrorCode::OK,
+              ImportKey(AuthorizationSetBuilder()
+                            .Authorization(TAG_NO_AUTH_REQUIRED)
+                            .HmacKey(key.size() * 8)
+                            .Authorization(TAG_MIN_MAC_LENGTH, expected_mac.size() * 8)
+                            .Digest(digest),
+                        KeyFormat::RAW, key));
+    string signature = MacMessage(message, digest, expected_mac.size() * 8);
+    EXPECT_EQ(expected_mac, signature)
+        << "Test vector didn't match for key of size " << key.size() << " message of size "
+        << message.size() << " and digest " << digest;
+    CheckedDeleteKey();
+}
+
+void KeymasterHidlTest::CheckAesCtrTestVector(const string& key, const string& nonce,
+                                              const string& message,
+                                              const string& expected_ciphertext) {
+    SCOPED_TRACE("CheckAesCtrTestVector");
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                                           .AesEncryptionKey(key.size() * 8)
+                                           .BlockMode(BlockMode::CTR)
+                                           .Authorization(TAG_CALLER_NONCE)
+                                           .Padding(PaddingMode::NONE),
+                                       KeyFormat::RAW, key));
+
+    auto params = AuthorizationSetBuilder()
+                      .Authorization(TAG_NONCE, nonce.data(), nonce.size())
+                      .BlockMode(BlockMode::CTR)
+                      .Padding(PaddingMode::NONE);
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(key_blob_, message, params, &out_params);
+    EXPECT_EQ(expected_ciphertext, ciphertext);
+}
+
+void KeymasterHidlTest::CheckTripleDesTestVector(KeyPurpose purpose, BlockMode block_mode,
+                                                 PaddingMode padding_mode, const string& key,
+                                                 const string& iv, const string& input,
+                                                 const string& expected_output) {
+    auto authset = AuthorizationSetBuilder()
+                       .TripleDesEncryptionKey(key.size() * 7)
+                       .BlockMode(block_mode)
+                       .Padding(padding_mode);
+    if (iv.size()) authset.Authorization(TAG_CALLER_NONCE);
+    ASSERT_EQ(ErrorCode::OK, ImportKey(authset, KeyFormat::RAW, key));
+    auto begin_params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding_mode);
+    if (iv.size()) begin_params.Authorization(TAG_NONCE, iv.data(), iv.size());
+    AuthorizationSet output_params;
+    string output = ProcessMessage(key_blob_, purpose, input, begin_params, &output_params);
+    EXPECT_EQ(expected_output, output);
+}
+
+void KeymasterHidlTest::VerifyMessage(const HidlBuf& key_blob, const string& message,
+                                      const string& signature, const AuthorizationSet& params) {
+    SCOPED_TRACE("VerifyMessage");
+    AuthorizationSet begin_out_params;
+    ASSERT_EQ(ErrorCode::OK,
+              Begin(KeyPurpose::VERIFY, key_blob, params, &begin_out_params, &op_handle_));
+
+    string unused;
+    AuthorizationSet finish_params;
+    AuthorizationSet finish_out_params;
+    string output;
+    EXPECT_EQ(ErrorCode::OK,
+              Finish(op_handle_, finish_params, message, signature, &finish_out_params, &output));
+    op_handle_ = kOpHandleSentinel;
+    EXPECT_TRUE(output.empty());
+}
+
+void KeymasterHidlTest::VerifyMessage(const string& message, const string& signature,
+                                      const AuthorizationSet& params) {
+    SCOPED_TRACE("VerifyMessage");
+    VerifyMessage(key_blob_, message, signature, params);
+}
+
+string KeymasterHidlTest::EncryptMessage(const HidlBuf& key_blob, const string& message,
+                                         const AuthorizationSet& in_params,
+                                         AuthorizationSet* out_params) {
+    SCOPED_TRACE("EncryptMessage");
+    return ProcessMessage(key_blob, KeyPurpose::ENCRYPT, message, in_params, out_params);
+}
+
+string KeymasterHidlTest::EncryptMessage(const string& message, const AuthorizationSet& params,
+                                         AuthorizationSet* out_params) {
+    SCOPED_TRACE("EncryptMessage");
+    return EncryptMessage(key_blob_, message, params, out_params);
+}
+
+string KeymasterHidlTest::EncryptMessage(const string& message, const AuthorizationSet& params) {
+    SCOPED_TRACE("EncryptMessage");
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(message, params, &out_params);
+    EXPECT_TRUE(out_params.empty()) << "Output params should be empty. Contained: " << out_params;
+    return ciphertext;
+}
+
+string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
+                                         PaddingMode padding) {
+    SCOPED_TRACE("EncryptMessage");
+    auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding);
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(message, params, &out_params);
+    EXPECT_TRUE(out_params.empty()) << "Output params should be empty. Contained: " << out_params;
+    return ciphertext;
+}
+
+string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
+                                         PaddingMode padding, HidlBuf* iv_out) {
+    SCOPED_TRACE("EncryptMessage");
+    auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding);
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(message, params, &out_params);
+    EXPECT_EQ(1U, out_params.size());
+    auto ivVal = out_params.GetTagValue(TAG_NONCE);
+    EXPECT_TRUE(ivVal.isOk());
+    *iv_out = ivVal.value();
+    return ciphertext;
+}
+
+string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
+                                         PaddingMode padding, const HidlBuf& iv_in) {
+    SCOPED_TRACE("EncryptMessage");
+    auto params = AuthorizationSetBuilder()
+                      .BlockMode(block_mode)
+                      .Padding(padding)
+                      .Authorization(TAG_NONCE, iv_in);
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(message, params, &out_params);
+    return ciphertext;
+}
+
+string KeymasterHidlTest::DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
+                                         const AuthorizationSet& params) {
+    SCOPED_TRACE("DecryptMessage");
+    AuthorizationSet out_params;
+    string plaintext =
+        ProcessMessage(key_blob, KeyPurpose::DECRYPT, ciphertext, params, &out_params);
+    EXPECT_TRUE(out_params.empty());
+    return plaintext;
+}
+
+string KeymasterHidlTest::DecryptMessage(const string& ciphertext, const AuthorizationSet& params) {
+    SCOPED_TRACE("DecryptMessage");
+    return DecryptMessage(key_blob_, ciphertext, params);
+}
+
+string KeymasterHidlTest::DecryptMessage(const string& ciphertext, BlockMode block_mode,
+                                         PaddingMode padding_mode, const HidlBuf& iv) {
+    SCOPED_TRACE("DecryptMessage");
+    auto params = AuthorizationSetBuilder()
+                      .BlockMode(block_mode)
+                      .Padding(padding_mode)
+                      .Authorization(TAG_NONCE, iv);
+    return DecryptMessage(key_blob_, ciphertext, params);
+}
+
+std::pair<ErrorCode, HidlBuf> KeymasterHidlTest::UpgradeKey(const HidlBuf& key_blob) {
+    std::pair<ErrorCode, HidlBuf> retval;
+    keymaster_->upgradeKey(key_blob, hidl_vec<KeyParameter>(),
+                           [&](ErrorCode error, const hidl_vec<uint8_t>& upgraded_blob) {
+                               retval = std::tie(error, upgraded_blob);
+                           });
+    return retval;
+}
+
+}  // namespace test
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
new file mode 100644
index 0000000..36d3fc2
--- /dev/null
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2017 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 HARDWARE_INTERFACES_KEYMASTER_40_VTS_FUNCTIONAL_KEYMASTER_HIDL_TEST_H_
+#define HARDWARE_INTERFACES_KEYMASTER_40_VTS_FUNCTIONAL_KEYMASTER_HIDL_TEST_H_
+
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <android/hardware/keymaster/4.0/types.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include <keymaster/keymaster_configuration.h>
+
+#include <keymasterV4_0/authorization_set.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+
+::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set);
+
+namespace test {
+
+using ::android::sp;
+using ::std::string;
+
+class HidlBuf : public hidl_vec<uint8_t> {
+    typedef hidl_vec<uint8_t> super;
+
+   public:
+    HidlBuf() {}
+    HidlBuf(const super& other) : super(other) {}
+    HidlBuf(super&& other) : super(std::move(other)) {}
+    explicit HidlBuf(const std::string& other) : HidlBuf() { *this = other; }
+
+    HidlBuf& operator=(const super& other) {
+        super::operator=(other);
+        return *this;
+    }
+
+    HidlBuf& operator=(super&& other) {
+        super::operator=(std::move(other));
+        return *this;
+    }
+
+    HidlBuf& operator=(const string& other) {
+        resize(other.size());
+        std::copy(other.begin(), other.end(), begin());
+        return *this;
+    }
+
+    string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); }
+};
+
+constexpr uint64_t kOpHandleSentinel = 0xFFFFFFFFFFFFFFFF;
+
+class KeymasterHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static KeymasterHidlEnvironment* Instance() {
+        static KeymasterHidlEnvironment* instance = new KeymasterHidlEnvironment;
+        return instance;
+    }
+
+    void registerTestServices() override { registerTestService<IKeymasterDevice>(); }
+
+   private:
+    KeymasterHidlEnvironment(){};
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(KeymasterHidlEnvironment);
+};
+
+class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    void TearDown() override {
+        if (key_blob_.size()) {
+            CheckedDeleteKey();
+        }
+        AbortIfNeeded();
+    }
+
+    // SetUpTestCase runs only once per test case, not once per test.
+    static void SetUpTestCase();
+    static void TearDownTestCase() {
+        keymaster_.clear();
+        all_keymasters_.clear();
+    }
+
+    static IKeymasterDevice& keymaster() { return *keymaster_; }
+    static const std::vector<sp<IKeymasterDevice>>& all_keymasters() { return all_keymasters_; }
+    static uint32_t os_version() { return os_version_; }
+    static uint32_t os_patch_level() { return os_patch_level_; }
+
+    ErrorCode GenerateKey(const AuthorizationSet& key_desc, HidlBuf* key_blob,
+                          KeyCharacteristics* key_characteristics);
+    ErrorCode GenerateKey(const AuthorizationSet& key_desc);
+
+    ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+                        const string& key_material, HidlBuf* key_blob,
+                        KeyCharacteristics* key_characteristics);
+    ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+                        const string& key_material);
+
+    ErrorCode ImportWrappedKey(string wrapped_key, string wrapping_key,
+                               const AuthorizationSet& wrapping_key_desc, string masking_key,
+                               const AuthorizationSet& unwrapping_params);
+
+    ErrorCode ExportKey(KeyFormat format, const HidlBuf& key_blob, const HidlBuf& client_id,
+                        const HidlBuf& app_data, HidlBuf* key_material);
+    ErrorCode ExportKey(KeyFormat format, HidlBuf* key_material);
+
+    ErrorCode DeleteKey(HidlBuf* key_blob, bool keep_key_blob = false);
+    ErrorCode DeleteKey(bool keep_key_blob = false);
+
+    ErrorCode DeleteAllKeys();
+
+    void CheckedDeleteKey(HidlBuf* key_blob, bool keep_key_blob = false);
+    void CheckedDeleteKey();
+
+    ErrorCode GetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id,
+                                 const HidlBuf& app_data, KeyCharacteristics* key_characteristics);
+    ErrorCode GetCharacteristics(const HidlBuf& key_blob, KeyCharacteristics* key_characteristics);
+
+    ErrorCode Begin(KeyPurpose purpose, const HidlBuf& key_blob, const AuthorizationSet& in_params,
+                    AuthorizationSet* out_params, OperationHandle* op_handle);
+    ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
+                    AuthorizationSet* out_params);
+    ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params);
+
+    ErrorCode Update(OperationHandle op_handle, const AuthorizationSet& in_params,
+                     const string& input, AuthorizationSet* out_params, string* output,
+                     size_t* input_consumed);
+    ErrorCode Update(const string& input, string* out, size_t* input_consumed);
+
+    ErrorCode Finish(OperationHandle op_handle, const AuthorizationSet& in_params,
+                     const string& input, const string& signature, AuthorizationSet* out_params,
+                     string* output);
+    ErrorCode Finish(const string& message, string* output);
+    ErrorCode Finish(const string& message, const string& signature, string* output);
+    ErrorCode Finish(string* output) { return Finish(string(), output); }
+
+    ErrorCode Abort(OperationHandle op_handle);
+
+    void AbortIfNeeded();
+
+    ErrorCode AttestKey(const HidlBuf& key_blob, const AuthorizationSet& attest_params,
+                        hidl_vec<hidl_vec<uint8_t>>* cert_chain);
+    ErrorCode AttestKey(const AuthorizationSet& attest_params,
+                        hidl_vec<hidl_vec<uint8_t>>* cert_chain);
+
+    string ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation, const string& message,
+                          const AuthorizationSet& in_params, AuthorizationSet* out_params);
+
+    string SignMessage(const HidlBuf& key_blob, const string& message,
+                       const AuthorizationSet& params);
+    string SignMessage(const string& message, const AuthorizationSet& params);
+
+    string MacMessage(const string& message, Digest digest, size_t mac_length);
+
+    void CheckHmacTestVector(const string& key, const string& message, Digest digest,
+                             const string& expected_mac);
+
+    void CheckAesCtrTestVector(const string& key, const string& nonce, const string& message,
+                               const string& expected_ciphertext);
+
+    void CheckTripleDesTestVector(KeyPurpose purpose, BlockMode block_mode,
+                                  PaddingMode padding_mode, const string& key, const string& iv,
+                                  const string& input, const string& expected_output);
+
+    void VerifyMessage(const HidlBuf& key_blob, const string& message, const string& signature,
+                       const AuthorizationSet& params);
+    void VerifyMessage(const string& message, const string& signature,
+                       const AuthorizationSet& params);
+
+    string EncryptMessage(const HidlBuf& key_blob, const string& message,
+                          const AuthorizationSet& in_params, AuthorizationSet* out_params);
+    string EncryptMessage(const string& message, const AuthorizationSet& params,
+                          AuthorizationSet* out_params);
+    string EncryptMessage(const string& message, const AuthorizationSet& params);
+    string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding);
+    string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
+                          HidlBuf* iv_out);
+    string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
+                          const HidlBuf& iv_in);
+
+    string DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
+                          const AuthorizationSet& params);
+    string DecryptMessage(const string& ciphertext, const AuthorizationSet& params);
+    string DecryptMessage(const string& ciphertext, BlockMode block_mode, PaddingMode padding_mode,
+                          const HidlBuf& iv);
+
+    std::pair<ErrorCode, HidlBuf> UpgradeKey(const HidlBuf& key_blob);
+
+    static bool IsSecure() { return securityLevel_ != SecurityLevel::SOFTWARE; }
+    static SecurityLevel SecLevel() { return securityLevel_; }
+
+    HidlBuf key_blob_;
+    KeyCharacteristics key_characteristics_;
+    OperationHandle op_handle_ = kOpHandleSentinel;
+
+   private:
+    static sp<IKeymasterDevice> keymaster_;
+    static std::vector<sp<IKeymasterDevice>> all_keymasters_;
+    static uint32_t os_version_;
+    static uint32_t os_patch_level_;
+
+    static SecurityLevel securityLevel_;
+    static hidl_string name_;
+    static hidl_string author_;
+};
+
+}  // namespace test
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_40_VTS_FUNCTIONAL_KEYMASTER_HIDL_TEST_H_
diff --git a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
new file mode 100644
index 0000000..6afba0c
--- /dev/null
+++ b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 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 "KeymasterHidlTest.h"
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace test {
+
+class VerificationTokenTest : public KeymasterHidlTest {
+   protected:
+    struct VerifyAuthorizationResult {
+        bool callSuccessful;
+        ErrorCode error;
+        VerificationToken token;
+    };
+
+    VerifyAuthorizationResult verifyAuthorization(uint64_t operationHandle,
+                                                  const AuthorizationSet& paramsToVerify,
+                                                  const HardwareAuthToken& authToken) {
+        VerifyAuthorizationResult result;
+        result.callSuccessful =
+            keymaster()
+                .verifyAuthorization(operationHandle, paramsToVerify.hidl_data(), authToken,
+                                     [&](auto error, auto token) {
+                                         result.error = error;
+                                         result.token = token;
+                                     })
+                .isOk();
+        return result;
+    }
+
+    uint64_t getTime() {
+        struct timespec timespec;
+        EXPECT_EQ(0, clock_gettime(CLOCK_BOOTTIME, &timespec));
+        return timespec.tv_sec * 1000 + timespec.tv_nsec / 1000000;
+    }
+
+    int sleep_ms(uint32_t milliseconds) {
+        struct timespec sleep_time = {static_cast<time_t>(milliseconds / 1000),
+                                      static_cast<long>(milliseconds % 1000) * 1000000};
+        while (sleep_time.tv_sec || sleep_time.tv_nsec) {
+            if (nanosleep(&sleep_time /* to wait */,
+                          &sleep_time /* remaining (on interrruption) */) == 0) {
+                sleep_time = {};
+            } else {
+                if (errno != EINTR) return errno;
+            }
+        }
+        return 0;
+    }
+
+};  // namespace test
+
+/*
+ * VerificationTokens exist to facilitate cross-Keymaster verification of requirements.  As
+ * such, the precise capabilities required will vary depending on the specific vendor
+ * implementations. Essentially, VerificationTokens are a "hook" to enable vendor
+ * implementations to communicate, so the precise usage is defined by those vendors.  The only
+ * thing we really can test is that tokens can be created by TEE keymasters, and that the
+ * timestamps increase as expected.
+ */
+TEST_F(VerificationTokenTest, TestCreation) {
+    auto result1 = verifyAuthorization(
+        1 /* operation handle */, AuthorizationSet() /* paramtersToVerify */, HardwareAuthToken());
+    ASSERT_TRUE(result1.callSuccessful);
+    auto result1_time = getTime();
+
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        // StrongBox should not implement verifyAuthorization.
+        EXPECT_EQ(ErrorCode::UNIMPLEMENTED, result1.error);
+        return;
+    }
+
+    EXPECT_EQ(ErrorCode::OK, result1.error);
+    EXPECT_EQ(1U, result1.token.challenge);
+    EXPECT_EQ(SecLevel(), result1.token.securityLevel);
+    EXPECT_EQ(0U, result1.token.parametersVerified.size())
+        << "We didn't supply any parameters to verify";
+    EXPECT_GT(result1.token.timestamp, 0U);
+
+    constexpr uint32_t time_to_sleep = 200;
+    sleep_ms(time_to_sleep);
+
+    auto result2 = verifyAuthorization(
+        2 /* operation handle */, AuthorizationSet() /* paramtersToVerify */, HardwareAuthToken());
+    ASSERT_TRUE(result2.callSuccessful);
+    auto result2_time = getTime();
+    EXPECT_EQ(ErrorCode::OK, result2.error);
+    EXPECT_EQ(2U, result2.token.challenge);
+    EXPECT_EQ(SecLevel(), result2.token.securityLevel);
+    EXPECT_EQ(0U, result2.token.parametersVerified.size())
+        << "We didn't supply any parameters to verify";
+
+    auto host_time_delta = result2_time - result1_time;
+
+    EXPECT_GE(host_time_delta, time_to_sleep)
+        << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
+    EXPECT_LE(host_time_delta, time_to_sleep + 10)
+        << "The verifyAuthorization call took more than 10 ms?  That's awful!";
+
+    auto km_time_delta = result2.token.timestamp - result1.token.timestamp;
+
+    // If not too much else is going on on the system, the time delta should be quite close.  Allow
+    // 2 ms of slop just to avoid test flakiness.
+    //
+    // TODO(swillden): see if we can output values so they can be gathered across many runs and
+    // report if times aren't nearly always <1ms apart.
+    EXPECT_LE(host_time_delta, km_time_delta + 2);
+    EXPECT_LE(km_time_delta, host_time_delta + 2);
+}
+
+}  // namespace test
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index c8858de..1d8dfdf 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -22,21 +22,13 @@
 #include <openssl/evp.h>
 #include <openssl/x509.h>
 
-#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
-#include <android/hardware/keymaster/4.0/types.h>
 #include <cutils/properties.h>
-#include <keymaster/keymaster_configuration.h>
-
-#include <VtsHalHidlTargetTestBase.h>
 
 #include <keymasterV4_0/attestation_record.h>
-#include <keymasterV4_0/authorization_set.h>
 #include <keymasterV4_0/key_param_output.h>
 #include <keymasterV4_0/openssl_utils.h>
 
-using ::android::sp;
-
-using ::std::string;
+#include "KeymasterHidlTest.h"
 
 static bool arm_deleteAllKeys = false;
 static bool dump_Attestations = false;
@@ -60,91 +52,6 @@
 namespace keymaster {
 namespace V4_0 {
 
-bool operator==(const KeyParameter& a, const KeyParameter& b) {
-    if (a.tag != b.tag) {
-        return false;
-    }
-
-    switch (a.tag) {
-        /* Boolean tags */
-        case Tag::INVALID:
-        case Tag::CALLER_NONCE:
-        case Tag::INCLUDE_UNIQUE_ID:
-        case Tag::BOOTLOADER_ONLY:
-        case Tag::NO_AUTH_REQUIRED:
-        case Tag::ALLOW_WHILE_ON_BODY:
-        case Tag::ROLLBACK_RESISTANCE:
-        case Tag::RESET_SINCE_ID_ROTATION:
-            return true;
-
-        /* Integer tags */
-        case Tag::KEY_SIZE:
-        case Tag::MIN_MAC_LENGTH:
-        case Tag::MIN_SECONDS_BETWEEN_OPS:
-        case Tag::MAX_USES_PER_BOOT:
-        case Tag::OS_VERSION:
-        case Tag::OS_PATCHLEVEL:
-        case Tag::MAC_LENGTH:
-        case Tag::AUTH_TIMEOUT:
-            return a.f.integer == b.f.integer;
-
-        /* Long integer tags */
-        case Tag::RSA_PUBLIC_EXPONENT:
-        case Tag::USER_SECURE_ID:
-            return a.f.longInteger == b.f.longInteger;
-
-        /* Date-time tags */
-        case Tag::ACTIVE_DATETIME:
-        case Tag::ORIGINATION_EXPIRE_DATETIME:
-        case Tag::USAGE_EXPIRE_DATETIME:
-        case Tag::CREATION_DATETIME:
-            return a.f.dateTime == b.f.dateTime;
-
-        /* Bytes tags */
-        case Tag::APPLICATION_ID:
-        case Tag::APPLICATION_DATA:
-        case Tag::ROOT_OF_TRUST:
-        case Tag::UNIQUE_ID:
-        case Tag::ATTESTATION_CHALLENGE:
-        case Tag::ATTESTATION_APPLICATION_ID:
-        case Tag::ATTESTATION_ID_BRAND:
-        case Tag::ATTESTATION_ID_DEVICE:
-        case Tag::ATTESTATION_ID_PRODUCT:
-        case Tag::ATTESTATION_ID_SERIAL:
-        case Tag::ATTESTATION_ID_IMEI:
-        case Tag::ATTESTATION_ID_MEID:
-        case Tag::ATTESTATION_ID_MANUFACTURER:
-        case Tag::ATTESTATION_ID_MODEL:
-        case Tag::ASSOCIATED_DATA:
-        case Tag::NONCE:
-            return a.blob == b.blob;
-
-        /* Enum tags */
-        case Tag::PURPOSE:
-            return a.f.purpose == b.f.purpose;
-        case Tag::ALGORITHM:
-            return a.f.algorithm == b.f.algorithm;
-        case Tag::BLOCK_MODE:
-            return a.f.blockMode == b.f.blockMode;
-        case Tag::DIGEST:
-            return a.f.digest == b.f.digest;
-        case Tag::PADDING:
-            return a.f.paddingMode == b.f.paddingMode;
-        case Tag::EC_CURVE:
-            return a.f.ecCurve == b.f.ecCurve;
-        case Tag::BLOB_USAGE_REQUIREMENTS:
-            return a.f.keyBlobUsageRequirements == b.f.keyBlobUsageRequirements;
-        case Tag::USER_AUTH_TYPE:
-            return a.f.integer == b.f.integer;
-        case Tag::ORIGIN:
-            return a.f.origin == b.f.origin;
-        case Tag::HARDWARE_TYPE:
-            return a.f.hardwareType == b.f.hardwareType;
-    }
-
-    return false;
-}
-
 bool operator==(const AuthorizationSet& a, const AuthorizationSet& b) {
     return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
 }
@@ -164,16 +71,6 @@
     return a_sw == b_sw && a_tee == b_tee;
 }
 
-::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set) {
-    if (set.size() == 0)
-        os << "(Empty)" << ::std::endl;
-    else {
-        os << "\n";
-        for (size_t i = 0; i < set.size(); ++i) os << set[i] << ::std::endl;
-    }
-    return os;
-}
-
 namespace test {
 namespace {
 
@@ -369,524 +266,8 @@
     return make_string(a, N);
 }
 
-class HidlBuf : public hidl_vec<uint8_t> {
-    typedef hidl_vec<uint8_t> super;
-
-   public:
-    HidlBuf() {}
-    HidlBuf(const super& other) : super(other) {}
-    HidlBuf(super&& other) : super(std::move(other)) {}
-    explicit HidlBuf(const std::string& other) : HidlBuf() { *this = other; }
-
-    HidlBuf& operator=(const super& other) {
-        super::operator=(other);
-        return *this;
-    }
-
-    HidlBuf& operator=(super&& other) {
-        super::operator=(std::move(other));
-        return *this;
-    }
-
-    HidlBuf& operator=(const string& other) {
-        resize(other.size());
-        for (size_t i = 0; i < other.size(); ++i) {
-            (*this)[i] = static_cast<uint8_t>(other[i]);
-        }
-        return *this;
-    }
-
-    string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); }
-};
-
-constexpr uint64_t kOpHandleSentinel = 0xFFFFFFFFFFFFFFFF;
-
 }  // namespace
 
-class KeymasterHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static KeymasterHidlEnvironment* Instance() {
-        static KeymasterHidlEnvironment* instance = new KeymasterHidlEnvironment;
-        return instance;
-    }
-
-    void registerTestServices() override { registerTestService<IKeymasterDevice>(); }
-
-   private:
-    KeymasterHidlEnvironment(){};
-
-    GTEST_DISALLOW_COPY_AND_ASSIGN_(KeymasterHidlEnvironment);
-};
-
-class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   public:
-    void TearDown() override {
-        if (key_blob_.size()) {
-            CheckedDeleteKey();
-        }
-        AbortIfNeeded();
-    }
-
-    // SetUpTestCase runs only once per test case, not once per test.
-    static void SetUpTestCase() {
-        string service_name =
-            KeymasterHidlEnvironment::Instance()->getServiceName<IKeymasterDevice>();
-        keymaster_ =
-            ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(service_name);
-        ASSERT_NE(keymaster_, nullptr);
-
-        ASSERT_TRUE(keymaster_
-                        ->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
-                                              const hidl_string& author) {
-                            securityLevel_ = securityLevel;
-                            name_ = name;
-                            author_ = author;
-                        })
-                        .isOk());
-
-        os_version_ = ::keymaster::GetOsVersion();
-        os_patch_level_ = ::keymaster::GetOsPatchlevel();
-    }
-
-    static void TearDownTestCase() { keymaster_.clear(); }
-
-    static IKeymasterDevice& keymaster() { return *keymaster_; }
-    static uint32_t os_version() { return os_version_; }
-    static uint32_t os_patch_level() { return os_patch_level_; }
-
-    ErrorCode GenerateKey(const AuthorizationSet& key_desc, HidlBuf* key_blob,
-                          KeyCharacteristics* key_characteristics) {
-        EXPECT_NE(key_blob, nullptr) << "Key blob pointer must not be null.  Test bug";
-        EXPECT_EQ(0U, key_blob->size()) << "Key blob not empty before generating key.  Test bug.";
-        EXPECT_NE(key_characteristics, nullptr)
-            << "Previous characteristics not deleted before generating key.  Test bug.";
-
-        ErrorCode error;
-        EXPECT_TRUE(keymaster_
-                        ->generateKey(key_desc.hidl_data(),
-                                      [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
-                                          const KeyCharacteristics& hidl_key_characteristics) {
-                                          error = hidl_error;
-                                          *key_blob = hidl_key_blob;
-                                          *key_characteristics = hidl_key_characteristics;
-                                      })
-                        .isOk());
-        // On error, blob & characteristics should be empty.
-        if (error != ErrorCode::OK) {
-            EXPECT_EQ(0U, key_blob->size());
-            EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
-                           key_characteristics->hardwareEnforced.size()));
-        }
-        return error;
-    }
-
-    ErrorCode GenerateKey(const AuthorizationSet& key_desc) {
-        return GenerateKey(key_desc, &key_blob_, &key_characteristics_);
-    }
-
-    ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
-                        const string& key_material, HidlBuf* key_blob,
-                        KeyCharacteristics* key_characteristics) {
-        ErrorCode error;
-        EXPECT_TRUE(keymaster_
-                        ->importKey(key_desc.hidl_data(), format, HidlBuf(key_material),
-                                    [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
-                                        const KeyCharacteristics& hidl_key_characteristics) {
-                                        error = hidl_error;
-                                        *key_blob = hidl_key_blob;
-                                        *key_characteristics = hidl_key_characteristics;
-                                    })
-                        .isOk());
-        // On error, blob & characteristics should be empty.
-        if (error != ErrorCode::OK) {
-            EXPECT_EQ(0U, key_blob->size());
-            EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
-                           key_characteristics->hardwareEnforced.size()));
-        }
-        return error;
-    }
-
-    ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
-                        const string& key_material) {
-        return ImportKey(key_desc, format, key_material, &key_blob_, &key_characteristics_);
-    }
-
-    ErrorCode ExportKey(KeyFormat format, const HidlBuf& key_blob, const HidlBuf& client_id,
-                        const HidlBuf& app_data, HidlBuf* key_material) {
-        ErrorCode error;
-        EXPECT_TRUE(
-            keymaster_
-                ->exportKey(format, key_blob, client_id, app_data,
-                            [&](ErrorCode hidl_error_code, const HidlBuf& hidl_key_material) {
-                                error = hidl_error_code;
-                                *key_material = hidl_key_material;
-                            })
-                .isOk());
-        // On error, blob should be empty.
-        if (error != ErrorCode::OK) {
-            EXPECT_EQ(0U, key_material->size());
-        }
-        return error;
-    }
-
-    ErrorCode ExportKey(KeyFormat format, HidlBuf* key_material) {
-        HidlBuf client_id, app_data;
-        return ExportKey(format, key_blob_, client_id, app_data, key_material);
-    }
-
-    ErrorCode DeleteKey(HidlBuf* key_blob, bool keep_key_blob = false) {
-        auto rc = keymaster_->deleteKey(*key_blob);
-        if (!keep_key_blob) *key_blob = HidlBuf();
-        if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
-        return rc;
-    }
-
-    ErrorCode DeleteKey(bool keep_key_blob = false) { return DeleteKey(&key_blob_, keep_key_blob); }
-
-    ErrorCode DeleteAllKeys() {
-        ErrorCode error = keymaster_->deleteAllKeys();
-        return error;
-    }
-
-    void CheckedDeleteKey(HidlBuf* key_blob, bool keep_key_blob = false) {
-        auto rc = DeleteKey(key_blob, keep_key_blob);
-        EXPECT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED);
-    }
-
-    void CheckedDeleteKey() { CheckedDeleteKey(&key_blob_); }
-
-    ErrorCode GetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id,
-                                 const HidlBuf& app_data, KeyCharacteristics* key_characteristics) {
-        ErrorCode error = ErrorCode::UNKNOWN_ERROR;
-        EXPECT_TRUE(
-            keymaster_
-                ->getKeyCharacteristics(
-                    key_blob, client_id, app_data,
-                    [&](ErrorCode hidl_error, const KeyCharacteristics& hidl_key_characteristics) {
-                        error = hidl_error, *key_characteristics = hidl_key_characteristics;
-                    })
-                .isOk());
-        return error;
-    }
-
-    ErrorCode GetCharacteristics(const HidlBuf& key_blob, KeyCharacteristics* key_characteristics) {
-        HidlBuf client_id, app_data;
-        return GetCharacteristics(key_blob, client_id, app_data, key_characteristics);
-    }
-
-    ErrorCode Begin(KeyPurpose purpose, const HidlBuf& key_blob, const AuthorizationSet& in_params,
-                    AuthorizationSet* out_params, OperationHandle* op_handle) {
-        SCOPED_TRACE("Begin");
-        ErrorCode error;
-        OperationHandle saved_handle = *op_handle;
-        EXPECT_TRUE(
-            keymaster_
-                ->begin(purpose, key_blob, in_params.hidl_data(), HardwareAuthToken(),
-                        [&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
-                            uint64_t hidl_op_handle) {
-                            error = hidl_error;
-                            *out_params = hidl_out_params;
-                            *op_handle = hidl_op_handle;
-                        })
-                .isOk());
-        if (error != ErrorCode::OK) {
-            // Some implementations may modify *op_handle on error.
-            *op_handle = saved_handle;
-        }
-        return error;
-    }
-
-    ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
-                    AuthorizationSet* out_params) {
-        SCOPED_TRACE("Begin");
-        EXPECT_EQ(kOpHandleSentinel, op_handle_);
-        return Begin(purpose, key_blob_, in_params, out_params, &op_handle_);
-    }
-
-    ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params) {
-        SCOPED_TRACE("Begin");
-        AuthorizationSet out_params;
-        ErrorCode error = Begin(purpose, in_params, &out_params);
-        EXPECT_TRUE(out_params.empty());
-        return error;
-    }
-
-    ErrorCode Update(OperationHandle op_handle, const AuthorizationSet& in_params,
-                     const string& input, AuthorizationSet* out_params, string* output,
-                     size_t* input_consumed) {
-        SCOPED_TRACE("Update");
-        ErrorCode error;
-        EXPECT_TRUE(keymaster_
-                        ->update(op_handle, in_params.hidl_data(), HidlBuf(input),
-                                 HardwareAuthToken(), VerificationToken(),
-                                 [&](ErrorCode hidl_error, uint32_t hidl_input_consumed,
-                                     const hidl_vec<KeyParameter>& hidl_out_params,
-                                     const HidlBuf& hidl_output) {
-                                     error = hidl_error;
-                                     out_params->push_back(AuthorizationSet(hidl_out_params));
-                                     output->append(hidl_output.to_string());
-                                     *input_consumed = hidl_input_consumed;
-                                 })
-                        .isOk());
-        return error;
-    }
-
-    ErrorCode Update(const string& input, string* out, size_t* input_consumed) {
-        SCOPED_TRACE("Update");
-        AuthorizationSet out_params;
-        ErrorCode error = Update(op_handle_, AuthorizationSet() /* in_params */, input, &out_params,
-                                 out, input_consumed);
-        EXPECT_TRUE(out_params.empty());
-        return error;
-    }
-
-    ErrorCode Finish(OperationHandle op_handle, const AuthorizationSet& in_params,
-                     const string& input, const string& signature, AuthorizationSet* out_params,
-                     string* output) {
-        SCOPED_TRACE("Finish");
-        ErrorCode error;
-        EXPECT_TRUE(
-            keymaster_
-                ->finish(op_handle, in_params.hidl_data(), HidlBuf(input), HidlBuf(signature),
-                         HardwareAuthToken(), VerificationToken(),
-                         [&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
-                             const HidlBuf& hidl_output) {
-                             error = hidl_error;
-                             *out_params = hidl_out_params;
-                             output->append(hidl_output.to_string());
-                         })
-                .isOk());
-        op_handle_ = kOpHandleSentinel;  // So dtor doesn't Abort().
-        return error;
-    }
-
-    ErrorCode Finish(const string& message, string* output) {
-        SCOPED_TRACE("Finish");
-        AuthorizationSet out_params;
-        string finish_output;
-        ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message,
-                                 "" /* signature */, &out_params, output);
-        if (error != ErrorCode::OK) {
-            return error;
-        }
-        EXPECT_EQ(0U, out_params.size());
-        return error;
-    }
-
-    ErrorCode Finish(const string& message, const string& signature, string* output) {
-        SCOPED_TRACE("Finish");
-        AuthorizationSet out_params;
-        ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message, signature,
-                                 &out_params, output);
-        op_handle_ = kOpHandleSentinel;  // So dtor doesn't Abort().
-        if (error != ErrorCode::OK) {
-            return error;
-        }
-        EXPECT_EQ(0U, out_params.size());
-        return error;
-    }
-
-    ErrorCode Abort(OperationHandle op_handle) {
-        SCOPED_TRACE("Abort");
-        auto retval = keymaster_->abort(op_handle);
-        EXPECT_TRUE(retval.isOk());
-        return retval;
-    }
-
-    void AbortIfNeeded() {
-        SCOPED_TRACE("AbortIfNeeded");
-        if (op_handle_ != kOpHandleSentinel) {
-            EXPECT_EQ(ErrorCode::OK, Abort(op_handle_));
-            op_handle_ = kOpHandleSentinel;
-        }
-    }
-
-    ErrorCode AttestKey(const HidlBuf& key_blob, const AuthorizationSet& attest_params,
-                        hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
-        SCOPED_TRACE("AttestKey");
-        ErrorCode error;
-        auto rc = keymaster_->attestKey(
-            key_blob, attest_params.hidl_data(),
-            [&](ErrorCode hidl_error, const hidl_vec<hidl_vec<uint8_t>>& hidl_cert_chain) {
-                error = hidl_error;
-                *cert_chain = hidl_cert_chain;
-            });
-
-        EXPECT_TRUE(rc.isOk()) << rc.description();
-        if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
-
-        return error;
-    }
-
-    ErrorCode AttestKey(const AuthorizationSet& attest_params,
-                        hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
-        SCOPED_TRACE("AttestKey");
-        return AttestKey(key_blob_, attest_params, cert_chain);
-    }
-
-    string ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation, const string& message,
-                          const AuthorizationSet& in_params, AuthorizationSet* out_params) {
-        SCOPED_TRACE("ProcessMessage");
-        AuthorizationSet begin_out_params;
-        EXPECT_EQ(ErrorCode::OK,
-                  Begin(operation, key_blob, in_params, &begin_out_params, &op_handle_));
-
-        string unused;
-        AuthorizationSet finish_params;
-        AuthorizationSet finish_out_params;
-        string output;
-        EXPECT_EQ(ErrorCode::OK,
-                  Finish(op_handle_, finish_params, message, unused, &finish_out_params, &output));
-        op_handle_ = kOpHandleSentinel;
-
-        out_params->push_back(begin_out_params);
-        out_params->push_back(finish_out_params);
-        return output;
-    }
-
-    string SignMessage(const HidlBuf& key_blob, const string& message,
-                       const AuthorizationSet& params) {
-        SCOPED_TRACE("SignMessage");
-        AuthorizationSet out_params;
-        string signature = ProcessMessage(key_blob, KeyPurpose::SIGN, message, params, &out_params);
-        EXPECT_TRUE(out_params.empty());
-        return signature;
-    }
-
-    string SignMessage(const string& message, const AuthorizationSet& params) {
-        SCOPED_TRACE("SignMessage");
-        return SignMessage(key_blob_, message, params);
-    }
-
-    string MacMessage(const string& message, Digest digest, size_t mac_length) {
-        SCOPED_TRACE("MacMessage");
-        return SignMessage(
-            key_blob_, message,
-            AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
-    }
-
-    void CheckHmacTestVector(const string& key, const string& message, Digest digest,
-                             const string& expected_mac) {
-        SCOPED_TRACE("CheckHmacTestVector");
-        ASSERT_EQ(ErrorCode::OK,
-                  ImportKey(AuthorizationSetBuilder()
-                                .Authorization(TAG_NO_AUTH_REQUIRED)
-                                .HmacKey(key.size() * 8)
-                                .Authorization(TAG_MIN_MAC_LENGTH, expected_mac.size() * 8)
-                                .Digest(digest),
-                            KeyFormat::RAW, key));
-        string signature = MacMessage(message, digest, expected_mac.size() * 8);
-        EXPECT_EQ(expected_mac, signature)
-            << "Test vector didn't match for key of size " << key.size() << " message of size "
-            << message.size() << " and digest " << digest;
-        CheckedDeleteKey();
-    }
-
-    void CheckAesCtrTestVector(const string& key, const string& nonce, const string& message,
-                               const string& expected_ciphertext) {
-        SCOPED_TRACE("CheckAesCtrTestVector");
-        ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
-                                               .Authorization(TAG_NO_AUTH_REQUIRED)
-                                               .AesEncryptionKey(key.size() * 8)
-                                               .BlockMode(BlockMode::CTR)
-                                               .Authorization(TAG_CALLER_NONCE)
-                                               .Padding(PaddingMode::NONE),
-                                           KeyFormat::RAW, key));
-
-        auto params = AuthorizationSetBuilder()
-                          .Authorization(TAG_NONCE, nonce.data(), nonce.size())
-                          .BlockMode(BlockMode::CTR)
-                          .Padding(PaddingMode::NONE);
-        AuthorizationSet out_params;
-        string ciphertext = EncryptMessage(key_blob_, message, params, &out_params);
-        EXPECT_EQ(expected_ciphertext, ciphertext);
-    }
-
-    void VerifyMessage(const HidlBuf& key_blob, const string& message, const string& signature,
-                       const AuthorizationSet& params) {
-        SCOPED_TRACE("VerifyMessage");
-        AuthorizationSet begin_out_params;
-        ASSERT_EQ(ErrorCode::OK,
-                  Begin(KeyPurpose::VERIFY, key_blob, params, &begin_out_params, &op_handle_));
-
-        string unused;
-        AuthorizationSet finish_params;
-        AuthorizationSet finish_out_params;
-        string output;
-        EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, message, signature,
-                                        &finish_out_params, &output));
-        op_handle_ = kOpHandleSentinel;
-        EXPECT_TRUE(output.empty());
-    }
-
-    void VerifyMessage(const string& message, const string& signature,
-                       const AuthorizationSet& params) {
-        SCOPED_TRACE("VerifyMessage");
-        VerifyMessage(key_blob_, message, signature, params);
-    }
-
-    string EncryptMessage(const HidlBuf& key_blob, const string& message,
-                          const AuthorizationSet& in_params, AuthorizationSet* out_params) {
-        SCOPED_TRACE("EncryptMessage");
-        return ProcessMessage(key_blob, KeyPurpose::ENCRYPT, message, in_params, out_params);
-    }
-
-    string EncryptMessage(const string& message, const AuthorizationSet& params,
-                          AuthorizationSet* out_params) {
-        SCOPED_TRACE("EncryptMessage");
-        return EncryptMessage(key_blob_, message, params, out_params);
-    }
-
-    string EncryptMessage(const string& message, const AuthorizationSet& params) {
-        SCOPED_TRACE("EncryptMessage");
-        AuthorizationSet out_params;
-        string ciphertext = EncryptMessage(message, params, &out_params);
-        EXPECT_TRUE(out_params.empty())
-            << "Output params should be empty. Contained: " << out_params;
-        return ciphertext;
-    }
-
-    string DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
-                          const AuthorizationSet& params) {
-        SCOPED_TRACE("DecryptMessage");
-        AuthorizationSet out_params;
-        string plaintext =
-            ProcessMessage(key_blob, KeyPurpose::DECRYPT, ciphertext, params, &out_params);
-        EXPECT_TRUE(out_params.empty());
-        return plaintext;
-    }
-
-    string DecryptMessage(const string& ciphertext, const AuthorizationSet& params) {
-        SCOPED_TRACE("DecryptMessage");
-        return DecryptMessage(key_blob_, ciphertext, params);
-    }
-
-    std::pair<ErrorCode, HidlBuf> UpgradeKey(const HidlBuf& key_blob) {
-        std::pair<ErrorCode, HidlBuf> retval;
-        keymaster_->upgradeKey(key_blob, hidl_vec<KeyParameter>(),
-                               [&](ErrorCode error, const hidl_vec<uint8_t>& upgraded_blob) {
-                                   retval = std::tie(error, upgraded_blob);
-                               });
-        return retval;
-    }
-
-    static bool IsSecure() { return securityLevel_ != SecurityLevel::SOFTWARE; }
-
-    HidlBuf key_blob_;
-    KeyCharacteristics key_characteristics_;
-    OperationHandle op_handle_ = kOpHandleSentinel;
-
-   private:
-    static sp<IKeymasterDevice> keymaster_;
-    static uint32_t os_version_;
-    static uint32_t os_patch_level_;
-
-    static SecurityLevel securityLevel_;
-    static hidl_string name_;
-    static hidl_string author_;
-};
-
 bool verify_attestation_record(const string& challenge, const string& app_id,
                                AuthorizationSet expected_sw_enforced,
                                AuthorizationSet expected_tee_enforced,
@@ -946,13 +327,6 @@
     return true;
 }
 
-sp<IKeymasterDevice> KeymasterHidlTest::keymaster_;
-uint32_t KeymasterHidlTest::os_version_;
-uint32_t KeymasterHidlTest::os_patch_level_;
-SecurityLevel KeymasterHidlTest::securityLevel_;
-hidl_string KeymasterHidlTest::name_;
-hidl_string KeymasterHidlTest::author_;
-
 class NewKeyGenerationTest : public KeymasterHidlTest {
    protected:
     void CheckBaseParams(const KeyCharacteristics& keyCharacteristics) {
@@ -2421,6 +1795,117 @@
     VerifyMessage(message, signature, AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
 }
 
+auto wrapped_key = hex2str(
+    "30820173020100048201006F5C273914D9E7EAB667FE62456A57DE64BED4A57DB3EFBB77E6907C82CC36B0BD12CB8A"
+    "85F3F8BC08A26C58186DB5C35636063388A04AE5579D3BDC057F9BB0EB6FDDA5E836DBB1F18A4546A64BA06E3D0132"
+    "AAA3306676638C786FAF0722E6E4145E0C91B009C422691F9F42F9F179DA93E16E7793DE5960E77A387433F0B43E49"
+    "3A7CF77ECA25BA724CC02F916D5792CAA76BC0756D3DB5D110D209B8B30285E9653D91FD89E953F351D82ACE1422CC"
+    "A146F8BD0C2F4CC32D1F81D894F4650043DB46109869696319A1A011BB003F2EBD8FA20B4A43F3226C1F182A39AE81"
+    "A35B9B7590A48B6A6874C9CC0EE0CD9528FB908688B4111932DF478CD7A92B50040CD796B02C370F1FA4CC0124F130"
+    "280201033023A1083106020100020101A203020120A30402020100A4053103020101A60531030201400420CCD54085"
+    "5F833A5E1480BFD2D36FAF3AEEE15DF5BEABE2691BC82DDE2A7AA91004107CB81BDDCD09E8F4DF575726279F3229");
+
+auto wrapped_key_masked = hex2str(
+    "30820173020100048201009059BB6E48F8036ABE1800D9C74F3DB5F20448F035C2C78AFBCC28AF26581061298CAC78"
+    "A8CA5B79721B60B74490555168488ED696C8930D00463C6FC81BF0B6E4E26C93E018D0E3DC8754C6B261E0A7C3A6DA"
+    "1A223EB59ACA8E13348F14B9E944AF3C224906C1ABFE21ADDEE81FC641D45E092C6B0A75A9BA56C05529AE47ECA0D5"
+    "CD3568501CF04D47391FC695EDE19A3022B347D1BDC6C792A08AA014F87DD4BBD44777B14D7D2273191DDCFE4E8512"
+    "EFA677A14E68E5D820C5513331D687C08B6317FA64D404231D05C74CDD9AEB89D253FBE07154B2080CF4ACA5E1EFCB"
+    "53EB193E8A01DD5F9634B65EF9B49899003E245FDA6A3B137FAC1263E55A6E1D040C6D9721D08589581AB49204A330"
+    "280201033023A1083106020100020101A203020120A30402020100A4053103020101A60531030201400420A61C6E24"
+    "7E25B3E6E69AA78EB03C2D4AC20D1F99A9A024A76F35C8E2CAB9B68D04101FF7A0E793B9EE4AECEBB9AC4C545254");
+
+auto wrapping_key = hex2str(
+    "308204be020100300d06092a864886f70d0101010500048204a8308204a40201000282010100aec367931d8900ce56"
+    "b0067f7d70e1fc653f3f34d194c1fed50018fb43db937b06e673a837313d56b1c725150a3fef86acbddc41bb759c28"
+    "54eae32d35841efb5c18d82bc90a1cb5c1d55adf245b02911f0b7cda88c421ff0ebafe7c0d23be312d7bd5921ffaea"
+    "1347c157406fef718f682643e4e5d33c6703d61c0cf7ac0bf4645c11f5c1374c3886427411c449796792e0bef75dec"
+    "858a2123c36753e02a95a96d7c454b504de385a642e0dfc3e60ac3a7ee4991d0d48b0172a95f9536f02ba13cecccb9"
+    "2b727db5c27e5b2f5cec09600b286af5cf14c42024c61ddfe71c2a8d7458f185234cb00e01d282f10f8fc6721d2aed"
+    "3f4833cca2bd8fa62821dd55020301000102820100431447b6251908112b1ee76f99f3711a52b6630960046c2de70d"
+    "e188d833f8b8b91e4d785caeeeaf4f0f74414e2cda40641f7fe24f14c67a88959bdb27766df9e710b630a03adc683b"
+    "5d2c43080e52bee71e9eaeb6de297a5fea1072070d181c822bccff087d63c940ba8a45f670feb29fb4484d1c95e6d2"
+    "579ba02aae0a00900c3ebf490e3d2cd7ee8d0e20c536e4dc5a5097272888cddd7e91f228b1c4d7474c55b8fcd618c4"
+    "a957bbddd5ad7407cc312d8d98a5caf7e08f4a0d6b45bb41c652659d5a5ba05b663737a8696281865ba20fbdd7f851"
+    "e6c56e8cbe0ddbbf24dc03b2d2cb4c3d540fb0af52e034a2d06698b128e5f101e3b51a34f8d8b4f8618102818100de"
+    "392e18d682c829266cc3454e1d6166242f32d9a1d10577753e904ea7d08bff841be5bac82a164c5970007047b8c517"
+    "db8f8f84e37bd5988561bdf503d4dc2bdb38f885434ae42c355f725c9a60f91f0788e1f1a97223b524b5357fdf72e2"
+    "f696bab7d78e32bf92ba8e1864eab1229e91346130748a6e3c124f9149d71c743502818100c95387c0f9d35f137b57"
+    "d0d65c397c5e21cc251e47008ed62a542409c8b6b6ac7f8967b3863ca645fcce49582a9aa17349db6c4a95affdae0d"
+    "ae612e1afac99ed39a2d934c880440aed8832f9843163a47f27f392199dc1202f9a0f9bd08308007cb1e4e7f583093"
+    "66a7de25f7c3c9b880677c068e1be936e81288815252a8a102818057ff8ca1895080b2cae486ef0adfd791fb0235c0"
+    "b8b36cd6c136e52e4085f4ea5a063212a4f105a3764743e53281988aba073f6e0027298e1c4378556e0efca0e14ece"
+    "1af76ad0b030f27af6f0ab35fb73a060d8b1a0e142fa2647e93b32e36d8282ae0a4de50ab7afe85500a16f43a64719"
+    "d6e2b9439823719cd08bcd03178102818100ba73b0bb28e3f81e9bd1c568713b101241acc607976c4ddccc90e65b65"
+    "56ca31516058f92b6e09f3b160ff0e374ec40d78ae4d4979fde6ac06a1a400c61dd31254186af30b22c10582a8a43e"
+    "34fe949c5f3b9755bae7baa7b7b7a6bd03b38cef55c86885fc6c1978b9cee7ef33da507c9df6b9277cff1e6aaa5d57"
+    "aca528466102818100c931617c77829dfb1270502be9195c8f2830885f57dba869536811e6864236d0c4736a0008a1"
+    "45af36b8357a7c3d139966d04c4e00934ea1aede3bb6b8ec841dc95e3f579751e2bfdfe27ae778983f959356210723"
+    "287b0affcc9f727044d48c373f1babde0724fa17a4fd4da0902c7c9b9bf27ba61be6ad02dfddda8f4e6822");
+
+string zero_masking_key =
+    hex2str("0000000000000000000000000000000000000000000000000000000000000000");
+string masking_key = hex2str("D796B02C370F1FA4CC0124F14EC8CBEBE987E825246265050F399A51FD477DFC");
+
+class ImportWrappedKeyTest : public KeymasterHidlTest {};
+
+TEST_F(ImportWrappedKeyTest, Success) {
+    auto wrapping_key_desc = AuthorizationSetBuilder()
+                                 .RsaEncryptionKey(2048, 65537)
+                                 .Digest(Digest::SHA1)
+                                 .Padding(PaddingMode::RSA_OAEP)
+                                 .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
+
+    ASSERT_EQ(ErrorCode::OK,
+              ImportWrappedKey(
+                  wrapped_key, wrapping_key, wrapping_key_desc, zero_masking_key,
+                  AuthorizationSetBuilder().Digest(Digest::SHA1).Padding(PaddingMode::RSA_OAEP)));
+
+    string message = "Hello World!";
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+    string ciphertext = EncryptMessage(message, params);
+    string plaintext = DecryptMessage(ciphertext, params);
+    EXPECT_EQ(message, plaintext);
+}
+
+TEST_F(ImportWrappedKeyTest, SuccessMasked) {
+    auto wrapping_key_desc = AuthorizationSetBuilder()
+                                 .RsaEncryptionKey(2048, 65537)
+                                 .Digest(Digest::SHA1)
+                                 .Padding(PaddingMode::RSA_OAEP)
+                                 .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
+
+    ASSERT_EQ(ErrorCode::OK,
+              ImportWrappedKey(
+                  wrapped_key_masked, wrapping_key, wrapping_key_desc, masking_key,
+                  AuthorizationSetBuilder().Digest(Digest::SHA1).Padding(PaddingMode::RSA_OAEP)));
+}
+
+TEST_F(ImportWrappedKeyTest, WrongMask) {
+    auto wrapping_key_desc = AuthorizationSetBuilder()
+                                 .RsaEncryptionKey(2048, 65537)
+                                 .Digest(Digest::SHA1)
+                                 .Padding(PaddingMode::RSA_OAEP)
+                                 .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
+
+    ASSERT_EQ(ErrorCode::VERIFICATION_FAILED,
+              ImportWrappedKey(
+                  wrapped_key_masked, wrapping_key, wrapping_key_desc, zero_masking_key,
+                  AuthorizationSetBuilder().Digest(Digest::SHA1).Padding(PaddingMode::RSA_OAEP)));
+}
+
+TEST_F(ImportWrappedKeyTest, WrongPurpose) {
+    auto wrapping_key_desc = AuthorizationSetBuilder()
+                                 .RsaEncryptionKey(2048, 65537)
+                                 .Digest(Digest::SHA1)
+                                 .Padding(PaddingMode::RSA_OAEP);
+
+    ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+              ImportWrappedKey(
+                  wrapped_key_masked, wrapping_key, wrapping_key_desc, zero_masking_key,
+                  AuthorizationSetBuilder().Digest(Digest::SHA1).Padding(PaddingMode::RSA_OAEP)));
+}
+
 typedef KeymasterHidlTest EncryptionOperationsTest;
 
 /*
@@ -3712,6 +3197,535 @@
     EXPECT_TRUE(finish_out_params.empty());
 }
 
+/*
+ * EncryptionOperationsTest.TripleDesEcbRoundTripSuccess
+ *
+ * Verifies that 3DES is basically functional.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesEcbRoundTripSuccess) {
+    std::cout << "Hello" << std::endl;
+
+    auto auths = AuthorizationSetBuilder()
+                     .TripleDesEncryptionKey(112)
+                     .BlockMode(BlockMode::ECB)
+                     .Padding(PaddingMode::NONE);
+
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(auths));
+    // Two-block message.
+    string message = "1234567890123456";
+    auto inParams = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
+    string ciphertext1 = EncryptMessage(message, inParams);
+    EXPECT_EQ(message.size(), ciphertext1.size());
+
+    string ciphertext2 = EncryptMessage(string(message), inParams);
+    EXPECT_EQ(message.size(), ciphertext2.size());
+
+    // ECB is deterministic.
+    EXPECT_EQ(ciphertext1, ciphertext2);
+
+    string plaintext = DecryptMessage(ciphertext1, inParams);
+    EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesEcbNotAuthorized
+ *
+ * Verifies that CBC keys reject ECB usage.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesEcbNotAuthorized) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::CBC)
+                                             .Padding(PaddingMode::NONE)));
+
+    auto inParams = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
+    EXPECT_EQ(ErrorCode::INCOMPATIBLE_BLOCK_MODE, Begin(KeyPurpose::ENCRYPT, inParams));
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesEcbPkcs7Padding
+ *
+ * Tests ECB mode with PKCS#7 padding, various message sizes.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesEcbPkcs7Padding) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::ECB)
+                                             .Padding(PaddingMode::PKCS7)));
+
+    for (size_t i = 0; i < 32; ++i) {
+        string message(i, 'a');
+        auto inParams =
+            AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+        string ciphertext = EncryptMessage(message, inParams);
+        EXPECT_EQ(i + 8 - (i % 8), ciphertext.size());
+        string plaintext = DecryptMessage(ciphertext, inParams);
+        EXPECT_EQ(message, plaintext);
+    }
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesEcbNoPaddingKeyWithPkcs7Padding
+ *
+ * Verifies that keys configured for no padding reject PKCS7 padding
+ */
+TEST_F(EncryptionOperationsTest, TripleDesEcbNoPaddingKeyWithPkcs7Padding) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::ECB)
+                                             .Padding(PaddingMode::NONE)));
+    for (size_t i = 0; i < 32; ++i) {
+        auto inParams =
+            AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+        EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, inParams));
+    }
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesEcbPkcs7PaddingCorrupted
+ *
+ * Verifies that corrupted padding is detected.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesEcbPkcs7PaddingCorrupted) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::ECB)
+                                             .Padding(PaddingMode::PKCS7)));
+
+    string message = "a";
+    string ciphertext = EncryptMessage(message, BlockMode::ECB, PaddingMode::PKCS7);
+    EXPECT_EQ(8U, ciphertext.size());
+    EXPECT_NE(ciphertext, message);
+    ++ciphertext[ciphertext.size() / 2];
+
+    AuthorizationSetBuilder begin_params;
+    begin_params.push_back(TAG_BLOCK_MODE, BlockMode::ECB);
+    begin_params.push_back(TAG_PADDING, PaddingMode::PKCS7);
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+    string plaintext;
+    size_t input_consumed;
+    EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
+    EXPECT_EQ(ciphertext.size(), input_consumed);
+    EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext));
+}
+
+struct TripleDesTestVector {
+    const char* name;
+    const KeyPurpose purpose;
+    const BlockMode block_mode;
+    const PaddingMode padding_mode;
+    const char* key;
+    const char* iv;
+    const char* input;
+    const char* output;
+};
+
+// These test vectors are from NIST CAVP, plus a few custom variants to test padding, since all of
+// the NIST vectors are multiples of the block size.
+static const TripleDesTestVector kTripleDesTestVectors[] = {
+    {
+        "TECBMMT2 Encrypt 0", KeyPurpose::ENCRYPT, BlockMode::ECB, PaddingMode::NONE,
+        "ad192fd064b5579e7a4fb3c8f794f22a",  // key
+        "",                                  // IV
+        "13bad542f3652d67",                  // input
+        "908e543cf2cb254f",                  // output
+    },
+    {
+        "TECBMMT2 Encrypt 0 PKCS7", KeyPurpose::ENCRYPT, BlockMode::ECB, PaddingMode::PKCS7,
+        "ad192fd064b5579e7a4fb3c8f794f22a",  // key
+        "",                                  // IV
+        "13bad542f3652d6700",                // input
+        "908e543cf2cb254fc40165289a89008c",  // output
+    },
+    {
+        "TECBMMT2 Encrypt 0 PKCS7 decrypted", KeyPurpose::DECRYPT, BlockMode::ECB,
+        PaddingMode::PKCS7,
+        "ad192fd064b5579e7a4fb3c8f794f22a",  // key
+        "",                                  // IV
+        "908e543cf2cb254fc40165289a89008c",  // input
+        "13bad542f3652d6700",                // output
+    },
+    {
+        "TECBMMT2 Encrypt 1", KeyPurpose::ENCRYPT, BlockMode::ECB, PaddingMode::NONE,
+        "259df16e7af804fe83b90e9bf7c7e557",  // key
+        "",                                  // IV
+        "a4619c433bbd6787c07c81728f9ac9fa",  // input
+        "9e06de155c483c6bcfd834dbc8bd5830",  // output
+    },
+    {
+        "TECBMMT2 Decrypt 0", KeyPurpose::DECRYPT, BlockMode::ECB, PaddingMode::NONE,
+        "b32ff42092024adf2076b9d3d9f19e6d",  // key
+        "",                                  // IV
+        "2f3f2a49bba807a5",                  // input
+        "2249973fa135fb52",                  // output
+    },
+    {
+        "TECBMMT2 Decrypt 1", KeyPurpose::DECRYPT, BlockMode::ECB, PaddingMode::NONE,
+        "023dfbe6621aa17cc219eae9cdecd923",  // key
+        "",                                  // IV
+        "54045dc71d8d565b227ec19f06fef912",  // input
+        "9b071622181e6412de6066429401410d",  // output
+    },
+    {
+        "TECBMMT3 Encrypt 0", KeyPurpose::ENCRYPT, BlockMode::ECB, PaddingMode::NONE,
+        "a2b5bc67da13dc92cd9d344aa238544a0e1fa79ef76810cd",  // key
+        "",                                                  // IV
+        "329d86bdf1bc5af4",                                  // input
+        "d946c2756d78633f",                                  // output
+    },
+    {
+        "TECBMMT3 Encrypt 1", KeyPurpose::ENCRYPT, BlockMode::ECB, PaddingMode::NONE,
+        "49e692290d2a5e46bace79b9648a4c5d491004c262dc9d49",  // key
+        "",                                                  // IV
+        "6b1540781b01ce1997adae102dbf3c5b",                  // input
+        "4d0dc182d6e481ac4a3dc6ab6976ccae",                  // output
+    },
+    {
+        "TECBMMT3 Decrypt 0", KeyPurpose::DECRYPT, BlockMode::ECB, PaddingMode::NONE,
+        "52daec2ac7dc1958377392682f37860b2cc1ea2304bab0e9",  // key
+        "",                                                  // IV
+        "6daad94ce08acfe7",                                  // input
+        "660e7d32dcc90e79",                                  // output
+    },
+    {
+        "TECBMMT3 Decrypt 1", KeyPurpose::DECRYPT, BlockMode::ECB, PaddingMode::NONE,
+        "7f8fe3d3f4a48394fb682c2919926d6ddfce8932529229ce",  // key
+        "",                                                  // IV
+        "e9653a0a1f05d31b9acd12d73aa9879d",                  // input
+        "9b2ae9d998efe62f1b592e7e1df8ff38",                  // output
+    },
+    {
+        "TCBCMMT2 Encrypt 0", KeyPurpose::ENCRYPT, BlockMode::CBC, PaddingMode::NONE,
+        "34a41a8c293176c1b30732ecfe38ae8a",  // key
+        "f55b4855228bd0b4",                  // IV
+        "7dd880d2a9ab411c",                  // input
+        "c91892948b6cadb4",                  // output
+    },
+    {
+        "TCBCMMT2 Encrypt 1", KeyPurpose::ENCRYPT, BlockMode::CBC, PaddingMode::NONE,
+        "70a88fa1dfb9942fa77f40157ffef2ad",  // key
+        "ece08ce2fdc6ce80",                  // IV
+        "bc225304d5a3a5c9918fc5006cbc40cc",  // input
+        "27f67dc87af7ddb4b68f63fa7c2d454a",  // output
+    },
+    {
+        "TCBCMMT2 Decrypt 0", KeyPurpose::DECRYPT, BlockMode::CBC, PaddingMode::NONE,
+        "4ff47fda89209bda8c85f7fe80192007",  // key
+        "d5bc4891dabe48b9",                  // IV
+        "7e154b28c353adef",                  // input
+        "712b961ea9a1d0af",                  // output
+    },
+    {
+        "TCBCMMT2 Decrypt 1", KeyPurpose::DECRYPT, BlockMode::CBC, PaddingMode::NONE,
+        "464092cdbf736d38fb1fe6a12a94ae0e",  // key
+        "5423455f00023b01",                  // IV
+        "3f6050b74ed64416bc23d53b0469ed7a",  // input
+        "9cbe7d1b5cdd1864c3095ba810575960",  // output
+    },
+    {
+        "TCBCMMT3 Encrypt 0", KeyPurpose::ENCRYPT, BlockMode::CBC, PaddingMode::NONE,
+        "b5cb1504802326c73df186e3e352a20de643b0d63ee30e37",  // key
+        "43f791134c5647ba",                                  // IV
+        "dcc153cef81d6f24",                                  // input
+        "92538bd8af18d3ba",                                  // output
+    },
+    {
+        "TCBCMMT3 Encrypt 1", KeyPurpose::ENCRYPT, BlockMode::CBC, PaddingMode::NONE,
+        "a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358",  // key
+        "c2e999cb6249023c",                                  // IV
+        "c689aee38a301bb316da75db36f110b5",                  // input
+        "e9afaba5ec75ea1bbe65506655bb4ecb",                  // output
+    },
+    {
+        "TCBCMMT3 Encrypt 1 PKCS7 variant", KeyPurpose::ENCRYPT, BlockMode::CBC, PaddingMode::PKCS7,
+        "a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358",  // key
+        "c2e999cb6249023c",                                  // IV
+        "c689aee38a301bb316da75db36f110b500",                // input
+        "e9afaba5ec75ea1bbe65506655bb4ecb825aa27ec0656156",  // output
+    },
+    {
+        "TCBCMMT3 Encrypt 1 PKCS7 decrypted", KeyPurpose::DECRYPT, BlockMode::CBC,
+        PaddingMode::PKCS7,
+        "a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358",  // key
+        "c2e999cb6249023c",                                  // IV
+        "e9afaba5ec75ea1bbe65506655bb4ecb825aa27ec0656156",  // input
+        "c689aee38a301bb316da75db36f110b500",                // output
+    },
+    {
+        "TCBCMMT3 Decrypt 0", KeyPurpose::DECRYPT, BlockMode::CBC, PaddingMode::NONE,
+        "5eb6040d46082c7aa7d06dfd08dfeac8c18364c1548c3ba1",  // key
+        "41746c7e442d3681",                                  // IV
+        "c53a7b0ec40600fe",                                  // input
+        "d4f00eb455de1034",                                  // output
+    },
+    {
+        "TCBCMMT3 Decrypt 1", KeyPurpose::DECRYPT, BlockMode::CBC, PaddingMode::NONE,
+        "5b1cce7c0dc1ec49130dfb4af45785ab9179e567f2c7d549",  // key
+        "3982bc02c3727d45",                                  // IV
+        "6006f10adef52991fcc777a1238bbb65",                  // input
+        "edae09288e9e3bc05746d872b48e3b29",                  // output
+    },
+};
+
+/*
+ * EncryptionOperationsTest.TripleDesTestVector
+ *
+ * Verifies that NIST (plus a few extra) test vectors produce the correct results.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesTestVector) {
+    constexpr size_t num_tests = sizeof(kTripleDesTestVectors) / sizeof(TripleDesTestVector);
+    for (auto* test = kTripleDesTestVectors; test < kTripleDesTestVectors + num_tests; ++test) {
+        SCOPED_TRACE(test->name);
+        CheckTripleDesTestVector(test->purpose, test->block_mode, test->padding_mode,
+                                 hex2str(test->key), hex2str(test->iv), hex2str(test->input),
+                                 hex2str(test->output));
+    }
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCbcRoundTripSuccess
+ *
+ * Validates CBC mode functionality.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesCbcRoundTripSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::CBC)
+                                             .Padding(PaddingMode::NONE)));
+    // Two-block message.
+    string message = "1234567890123456";
+    HidlBuf iv1;
+    string ciphertext1 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv1);
+    EXPECT_EQ(message.size(), ciphertext1.size());
+
+    HidlBuf iv2;
+    string ciphertext2 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv2);
+    EXPECT_EQ(message.size(), ciphertext2.size());
+
+    // IVs should be random, so ciphertexts should differ.
+    EXPECT_NE(iv1, iv2);
+    EXPECT_NE(ciphertext1, ciphertext2);
+
+    string plaintext = DecryptMessage(ciphertext1, BlockMode::CBC, PaddingMode::NONE, iv1);
+    EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCallerIv
+ *
+ * Validates that 3DES keys can allow caller-specified IVs, and use them correctly.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesCallerIv) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::CBC)
+                                             .Authorization(TAG_CALLER_NONCE)
+                                             .Padding(PaddingMode::NONE)));
+    string message = "1234567890123456";
+    HidlBuf iv;
+    // Don't specify IV, should get a random one.
+    string ciphertext1 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv);
+    EXPECT_EQ(message.size(), ciphertext1.size());
+    EXPECT_EQ(8U, iv.size());
+
+    string plaintext = DecryptMessage(ciphertext1, BlockMode::CBC, PaddingMode::NONE, iv);
+    EXPECT_EQ(message, plaintext);
+
+    // Now specify an IV, should also work.
+    iv = HidlBuf("abcdefgh");
+    string ciphertext2 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, iv);
+
+    // Decrypt with correct IV.
+    plaintext = DecryptMessage(ciphertext2, BlockMode::CBC, PaddingMode::NONE, iv);
+    EXPECT_EQ(message, plaintext);
+
+    // Now try with wrong IV.
+    plaintext = DecryptMessage(ciphertext2, BlockMode::CBC, PaddingMode::NONE, HidlBuf("aaaaaaaa"));
+    EXPECT_NE(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest, TripleDesCallerNonceProhibited.
+ *
+ * Verifies that 3DES keys without TAG_CALLER_NONCE do not allow caller-specified IVS.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesCallerNonceProhibited) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::CBC)
+                                             .Padding(PaddingMode::NONE)));
+
+    string message = "12345678901234567890123456789012";
+    HidlBuf iv;
+    // Don't specify nonce, should get a random one.
+    string ciphertext1 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv);
+    EXPECT_EQ(message.size(), ciphertext1.size());
+    EXPECT_EQ(8U, iv.size());
+
+    string plaintext = DecryptMessage(ciphertext1, BlockMode::CBC, PaddingMode::NONE, iv);
+    EXPECT_EQ(message, plaintext);
+
+    // Now specify a nonce, should fail.
+    auto input_params = AuthorizationSetBuilder()
+                            .Authorization(TAG_NONCE, HidlBuf("abcdefgh"))
+                            .BlockMode(BlockMode::CBC)
+                            .Padding(PaddingMode::NONE);
+    AuthorizationSet output_params;
+    EXPECT_EQ(ErrorCode::CALLER_NONCE_PROHIBITED,
+              Begin(KeyPurpose::ENCRYPT, input_params, &output_params));
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCbcNotAuthorized
+ *
+ * Verifies that 3DES ECB-only keys do not allow CBC usage.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesCbcNotAuthorized) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::ECB)
+                                             .Padding(PaddingMode::NONE)));
+    // Two-block message.
+    string message = "1234567890123456";
+    auto begin_params =
+        AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+    EXPECT_EQ(ErrorCode::INCOMPATIBLE_BLOCK_MODE, Begin(KeyPurpose::ENCRYPT, begin_params));
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCbcNoPaddingWrongInputSize
+ *
+ * Verifies that unpadded CBC operations reject inputs that are not a multiple of block size.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesCbcNoPaddingWrongInputSize) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::CBC)
+                                             .Padding(PaddingMode::NONE)));
+    // Message is slightly shorter than two blocks.
+    string message = "123456789012345";
+
+    auto begin_params =
+        AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+    AuthorizationSet output_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &output_params));
+    string ciphertext;
+    EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, "", &ciphertext));
+}
+
+/*
+ * EncryptionOperationsTest, TripleDesCbcPkcs7Padding.
+ *
+ * Verifies that PKCS7 padding works correctly in CBC mode.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesCbcPkcs7Padding) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::CBC)
+                                             .Padding(PaddingMode::PKCS7)));
+
+    // Try various message lengths; all should work.
+    for (size_t i = 0; i < 32; ++i) {
+        string message(i, 'a');
+        HidlBuf iv;
+        string ciphertext = EncryptMessage(message, BlockMode::CBC, PaddingMode::PKCS7, &iv);
+        EXPECT_EQ(i + 8 - (i % 8), ciphertext.size());
+        string plaintext = DecryptMessage(ciphertext, BlockMode::CBC, PaddingMode::PKCS7, iv);
+        EXPECT_EQ(message, plaintext);
+    }
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCbcNoPaddingKeyWithPkcs7Padding
+ *
+ * Verifies that a key that requires PKCS7 padding cannot be used in unpadded mode.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesCbcNoPaddingKeyWithPkcs7Padding) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::CBC)
+                                             .Padding(PaddingMode::NONE)));
+
+    // Try various message lengths; all should fail.
+    for (size_t i = 0; i < 32; ++i) {
+        auto begin_params =
+            AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::PKCS7);
+        EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, begin_params));
+    }
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCbcPkcs7PaddingCorrupted
+ *
+ * Verifies that corrupted PKCS7 padding is rejected during decryption.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesCbcPkcs7PaddingCorrupted) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::CBC)
+                                             .Padding(PaddingMode::PKCS7)));
+
+    string message = "a";
+    HidlBuf iv;
+    string ciphertext = EncryptMessage(message, BlockMode::CBC, PaddingMode::PKCS7, &iv);
+    EXPECT_EQ(8U, ciphertext.size());
+    EXPECT_NE(ciphertext, message);
+    ++ciphertext[ciphertext.size() / 2];
+
+    auto begin_params = AuthorizationSetBuilder()
+                            .BlockMode(BlockMode::CBC)
+                            .Padding(PaddingMode::PKCS7)
+                            .Authorization(TAG_NONCE, iv);
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+    string plaintext;
+    size_t input_consumed;
+    EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
+    EXPECT_EQ(ciphertext.size(), input_consumed);
+    EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext));
+}
+
+/*
+ * EncryptionOperationsTest, TripleDesCbcIncrementalNoPadding.
+ *
+ * Verifies that 3DES CBC works with many different input sizes.
+ */
+TEST_F(EncryptionOperationsTest, TripleDesCbcIncrementalNoPadding) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .TripleDesEncryptionKey(112)
+                                             .BlockMode(BlockMode::CBC)
+                                             .Padding(PaddingMode::NONE)));
+
+    int increment = 7;
+    string message(240, 'a');
+    AuthorizationSet input_params =
+        AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+    AuthorizationSet output_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, input_params, &output_params));
+
+    string ciphertext;
+    size_t input_consumed;
+    for (size_t i = 0; i < message.size(); i += increment)
+        EXPECT_EQ(ErrorCode::OK,
+                  Update(message.substr(i, increment), &ciphertext, &input_consumed));
+    EXPECT_EQ(ErrorCode::OK, Finish(&ciphertext));
+    EXPECT_EQ(message.size(), ciphertext.size());
+
+    // Move TAG_NONCE into input_params
+    input_params = output_params;
+    input_params.push_back(TAG_BLOCK_MODE, BlockMode::CBC);
+    input_params.push_back(TAG_PADDING, PaddingMode::NONE);
+    output_params.Clear();
+
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, input_params, &output_params));
+    string plaintext;
+    for (size_t i = 0; i < ciphertext.size(); i += increment)
+        EXPECT_EQ(ErrorCode::OK,
+                  Update(ciphertext.substr(i, increment), &plaintext, &input_consumed));
+    EXPECT_EQ(ErrorCode::OK, Finish(&plaintext));
+    EXPECT_EQ(ciphertext.size(), plaintext.size());
+    EXPECT_EQ(message, plaintext);
+}
+
 typedef KeymasterHidlTest MaxOperationsTest;
 
 /*
diff --git a/light/utils/Android.bp b/light/utils/Android.bp
new file mode 100644
index 0000000..ebcbfa2
--- /dev/null
+++ b/light/utils/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2017 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.
+//
+
+// Turns off the screen.
+// Canonical usage is for init (which can't talk to hals directly).
+cc_binary {
+    name: "blank_screen",
+    init_rc: ["blank_screen.rc"],
+    srcs: ["main.cpp"],
+    shared_libs: [
+        "android.hardware.light@2.0",
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+    ],
+}
diff --git a/light/utils/blank_screen.rc b/light/utils/blank_screen.rc
new file mode 100644
index 0000000..7b2a55e
--- /dev/null
+++ b/light/utils/blank_screen.rc
@@ -0,0 +1,5 @@
+service blank_screen /system/bin/blank_screen
+    user system
+    oneshot
+    group system
+    shutdown critical
diff --git a/light/utils/main.cpp b/light/utils/main.cpp
new file mode 100644
index 0000000..1f9cb9c
--- /dev/null
+++ b/light/utils/main.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 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 <iostream>
+#include <string>
+
+#include <android-base/logging.h>
+#include <android/hardware/light/2.0/ILight.h>
+
+void error(const std::string& msg) {
+    LOG(ERROR) << msg;
+    std::cerr << msg << std::endl;
+}
+
+int main() {
+    using ::android::hardware::light::V2_0::Brightness;
+    using ::android::hardware::light::V2_0::Flash;
+    using ::android::hardware::light::V2_0::ILight;
+    using ::android::hardware::light::V2_0::LightState;
+    using ::android::hardware::light::V2_0::Status;
+    using ::android::hardware::light::V2_0::Type;
+    using ::android::sp;
+
+    sp<ILight> service = ILight::getService();
+    if (service == nullptr) {
+        error("Could not retrieve light service.");
+        return -1;
+    }
+
+    const static LightState off = {
+        .color = 0u, .flashMode = Flash::NONE, .brightnessMode = Brightness::USER,
+    };
+
+    Status ret = service->setLight(Type::BACKLIGHT, off).withDefault(Status::UNKNOWN);
+    if (ret != Status::SUCCESS) {
+        error("Failed to shut off screen");
+    }
+    return 0;
+}
diff --git a/radio/1.2/Android.bp b/radio/1.2/Android.bp
index 3e678bb..f4ca1cf 100644
--- a/radio/1.2/Android.bp
+++ b/radio/1.2/Android.bp
@@ -20,6 +20,7 @@
     ],
     types: [
         "CardStatus",
+        "CellConnectionStatus",
         "CellIdentityCdma",
         "CellIdentityGsm",
         "CellIdentityLte",
@@ -31,13 +32,14 @@
         "CellInfoLte",
         "CellInfoWcdma",
         "IncrementalResultsPeriodicityRange",
+        "IndicationFilter",
+        "LinkCapacityEstimate",
         "MaxSearchTimeRange",
         "NetworkScanRequest",
         "NetworkScanResult",
+        "PhysicalChannelConfig",
         "RadioConst",
         "ScanIntervalRange",
-        "SimSlotStatus",
-        "SlotState",
     ],
     gen_java: true,
 }
diff --git a/radio/1.2/IRadio.hal b/radio/1.2/IRadio.hal
index 73f1024..babe86f 100644
--- a/radio/1.2/IRadio.hal
+++ b/radio/1.2/IRadio.hal
@@ -17,6 +17,7 @@
 package android.hardware.radio@1.2;
 
 import @1.1::IRadio;
+import @1.1::RadioAccessNetworks;
 
 /**
  * This interface is used by telephony and telecom to talk to cellular radio.
@@ -39,44 +40,70 @@
     oneway startNetworkScan_1_2(int32_t serial, NetworkScanRequest request);
 
     /**
-     * Get SIM Slot status.
+     * Sets the indication filter.
      *
-     * Request provides the slot status of all active and inactive SIM slots and whether card is
-     * present in the slots or not.
+     * Prevents the reporting of specified unsolicited indications from the radio. This is used
+     * for power saving in instances when those indications are not needed. If unset, defaults to
+     * @1.2::IndicationFilter:ALL.
      *
      * @param serial Serial number of request.
+     * @param indicationFilter 32-bit bitmap of IndicationFilter. Bits set to 1 indicate the
+     *        indications are enabled. See @1.2::IndicationFilter for the definition of each bit.
      *
-     * Response callback is IRadioResponse.getSimSlotsStatusResponse()
+     * Response callback is IRadioResponse.setIndicationFilterResponse()
      */
-    oneway getSimSlotsStatus(int32_t serial);
+    oneway setIndicationFilter_1_2(int32_t serial, bitfield<IndicationFilter> indicationFilter);
 
     /**
-     * Set SIM Slot mapping.
-
-     * Maps the logical slots to the physical slots. Logical slot is the slot that is seen by modem.
-     * Physical slot is the actual physical slot. Request maps the physical slot to logical slot.
-     * Logical slots that are already mapped to the requested physical slot are not impacted.
+     * Sets the signal strength reporting criteria.
      *
-     * Example no. of logical slots 1 and physical slots 2:
-     * The only logical slot (index 0) can be mapped to first physical slot (value 0) or second
-     * physical slot(value 1), while the other physical slot remains unmapped and inactive.
-     * slotMap[0] = 1 or slotMap[0] = 0
+     * The resulting reporting criteria are the AND of all the supplied criteria.
      *
-     * Example no. of logical slots 2 and physical slots 2:
-     * First logical slot (index 0) can be mapped to physical slot 1 or 2 and other logical slot
-     * can be mapped to other physical slot. Each logical slot must be mapped to a physical slot.
-     * slotMap[0] = 0 and slotMap[1] = 1 or slotMap[0] = 1 and slotMap[1] = 0
+     * Note: Reporting criteria must be individually set for each RAN. If unset, reporting criteria
+     * for that RAN are implementation-defined.
      *
-     * @param serial Serial number of request
-     * @param slotMap Logical to physical slot mapping, size == no. of radio instances. Index is
-     *        mapping to logical slot and value to physical slot, need to provide all the slots
-     *        mapping when sending request in case of multi slot device.
-     *        EX: uint32_t slotMap[logical slot] = physical slot
-     *        index 0 is the first logical_slot number of logical slots is equal to number of Radio
-     *        instances and number of physical slots is equal to size of slotStatus in
-     *        getSimSlotsStatusResponse
+     * Response callback is IRadioResponse.setSignalStrengthReportingCriteriaResponse().
      *
-     * Response callback is IRadioResponse.setSimSlotsMappingResponse()
+     * @param serial Serial number of request.
+     * @param hysteresisMs A hysteresis time in milliseconds to prevent flapping. A value of 0
+     *                     disables hysteresis.
+     * @param hysteresisDb An interval in dB defining the required magnitude change between reports.
+     *                     hysteresisDb must be smaller than the smallest threshold delta. An
+     *                     interval value of 0 disables hysteresis.
+     * @param thresholdsDbm A vector of trigger thresholds in dBm. A vector size of 0 disables the
+     *                      use of thresholds for reporting.
+     * @param ran The type of network for which to apply these thresholds.
      */
-    oneway setSimSlotsMapping(int32_t serial, vec<uint32_t> slotMap);
+    oneway setSignalStrengthReportingCriteria(int32_t serial, int32_t hysteresisMs,
+            int32_t hysteresisDb, vec<int32_t> thresholdsDbm, RadioAccessNetworks ran);
+
+    /**
+     * Sets the link capacity reporting criteria.
+     *
+     * The resulting reporting criteria are the AND of all the supplied criteria.
+     *
+     * Note: Reporting criteria must be individually set for each RAN. If unset, reporting criteria
+     * for that RAN are implementation-defined.
+     *
+     * Response callback is IRadioResponse.setLinkCapacityReportingCriteriaResponse().
+     *
+     * @param serial Serial number of request.
+     * @param hysteresisMs A hysteresis time in milliseconds to prevent flapping. A value of 0
+     *                     disables hysteresis.
+     * @param hysteresisDlKbps An interval in kbps defining the required magnitude change between DL
+     *                         reports. hysteresisDlKbps must be smaller than the smallest threshold
+     *                         delta. A value of 0 disables hysteresis.
+     * @param hysteresisUlKbps An interval in kbps defining the required magnitude change between UL
+     *                         reports. hysteresisUlKbps must be smaller than the smallest threshold
+     *                         delta. A value of 0 disables hysteresis.
+     * @param thresholdsDownlinkKbps A vector of trigger thresholds in kbps for downlink reports. A
+     *                               vector size of 0 disables the use of DL thresholds for
+     *                               reporting.
+     * @param thresholdsUplinkKbps A vector of trigger thresholds in kbps for uplink reports. A
+     *                             vector size of 0 disables the use of UL thresholds for reporting.
+     * @param ran The type of network for which to apply these thresholds.
+     */
+    oneway setLinkCapacityReportingCriteria(int32_t serial, int32_t hysteresisMs,
+            int32_t hysteresisDlKbps, int32_t hysteresisUlKbps, vec<int32_t> thresholdsDownlinkKbps,
+            vec<int32_t> thresholdsUplinkKbps, RadioAccessNetworks ran);
 };
diff --git a/radio/1.2/IRadioIndication.hal b/radio/1.2/IRadioIndication.hal
index 4aae74d..a124557 100644
--- a/radio/1.2/IRadioIndication.hal
+++ b/radio/1.2/IRadioIndication.hal
@@ -30,11 +30,36 @@
     oneway networkScanResult_1_2(RadioIndicationType type, NetworkScanResult result);
 
     /**
-     * Indicates SIM slot status change.
+     * Request all of the current cell information known to the radio.
+     * Same information as returned by getCellInfoList() in 1.0::IRadio.
      *
      * @param type Type of radio indication
-     * @param slotStatus new slot status info with size equals to the number of physical slots on
-     *        the device
+     * @param records Current cell information known to radio
      */
-    oneway simSlotsStatusChanged(RadioIndicationType type, vec<SimSlotStatus> slotStatus);
+     oneway cellInfoList_1_2(RadioIndicationType type, vec<CellInfo> records);
+
+    /**
+     * Indicates current link capacity estimate.
+     *
+     * This replaces @1.0::IRadioIndication.lceData(). The framework must be able to handle
+     * either this function or @1.0::IRadioIndication.lceData(). Implementations supporting
+     * v1.2 must call this function instead of lceData().
+     *
+     * This indication is sent whenever the reporting criteria, as set by
+     * @1.2::IRadio.setLinkCapacityReportingCriteria, are met and the indication is not
+     * suppressed by @1.2::IRadio.setIndicationFilter_1_2().
+     *
+     * @param type Type of radio indication
+     * @param lce LinkCapacityEstimate information as defined in types.hal
+     */
+    oneway currentLinkCapacityEstimate(RadioIndicationType type, LinkCapacityEstimate lce);
+
+    /**
+     * Indicates physical channel configurations.
+     *
+     * @param type Type of radio indication
+     * @param configs List of PhysicalChannelConfigs as defined in types.hal
+     */
+    oneway currentPhysicalChannelConfigs(RadioIndicationType type,
+            vec<PhysicalChannelConfig> configs);
 };
diff --git a/radio/1.2/IRadioResponse.hal b/radio/1.2/IRadioResponse.hal
index cf6bc00..c356954 100644
--- a/radio/1.2/IRadioResponse.hal
+++ b/radio/1.2/IRadioResponse.hal
@@ -53,30 +53,23 @@
 
     /**
      * @param info Response info struct containing response type, serial no. and error
-     * @param slotStatus Sim slot struct containing all the physical SIM slots info with size
-      *       equals to the number of physical slots on the device
      *
      * Valid errors returned:
      *   RadioError:NONE
-     *   RadioError:RADIO_NOT_AVAILABLE
-     *   RadioError:REQUEST_NOT_SUPPORTED
-     *   RadioError:NO_MEMORY
-     *   RadioError:INTERNAL_ERR
-     *   RadioError:MODEM_ERR
      *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
      */
-    oneway getSimSlotsStatusResponse(RadioResponseInfo info, vec<SimSlotStatus> slotStatus);
+    oneway setSignalStrengthReportingCriteriaResponse(RadioResponseInfo info);
 
     /**
      * @param info Response info struct containing response type, serial no. and error
      *
      * Valid errors returned:
      *   RadioError:NONE
+     *   RadioError:INVALID_ARGUMENTS
      *   RadioError:RADIO_NOT_AVAILABLE
-     *   RadioError:REQUEST_NOT_SUPPORTED
-     *   RadioError:NO_MEMORY
      *   RadioError:INTERNAL_ERR
-     *   RadioError:MODEM_ERR
      */
-    oneway setSimSlotsMappingResponse(RadioResponseInfo info);
+    oneway setLinkCapacityReportingCriteriaResponse(RadioResponseInfo info);
 };
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index 1e28d3b..4515237 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -64,6 +64,67 @@
     MAX = 10,
 };
 
+enum CellConnectionStatus : int32_t {
+    /**
+     * Cell is not a serving cell.
+     */
+    NONE = 0,
+    /**
+     * UE has connection to cell for signalling and possibly data (3GPP 36.331, 25.331).
+     */
+    PRIMARY_SERVING,
+    /**
+     * UE has connection to cell for data (3GPP 36.331, 25.331).
+     */
+    SECONDARY_SERVING,
+};
+
+/**
+ * Overwritten from @1.0::IndicationFilter in order to redefine ALL. In the future, this should
+ * be extended instead of overwritten.
+ */
+enum IndicationFilter : int32_t {
+    NONE = 0,
+    ALL = ~0,
+    /**
+     * When this bit is set, modem must send the signal strength update through
+     * IRadioIndication.currentSignalStrength() when all criteria specified by
+     * IRadio.setSignalStrengthReportingCriteria() are met.
+     */
+    SIGNAL_STRENGTH = 1 << 0,
+    /**
+     * When this bit is set, modem must invoke IRadioIndication.networkStateChanged() when any field
+     * in VoiceRegStateResult or DataRegStateResult changes. When this bit is not set, modem must
+     * suppress IRadioIndication.networkStateChanged() when there are only changes from
+     * insignificant fields. Modem must invoke IRadioIndication.networkStateChanged() when
+     * significant fields are updated regardless of whether this bit is set.
+     *
+     * The following fields are considered significant: VoiceRegStateResult.regState,
+     * VoiceRegStateResult.rat, DataRegStateResult.regState, DataRegStateResult.rat.
+     */
+    FULL_NETWORK_STATE = 1 << 1,
+    /**
+     * When this bit is set, modem must send IRadioIndication.dataCallListChanged() whenever any
+     * field in ITypes.SetupDataCallResult changes. When this bit is not set, modem must suppress
+     * the indication when the only changed field is 'active' (for data dormancy). For all other
+     * field changes, the modem must send IRadioIndication.dataCallListChanged() regardless of
+     * whether this bit is set.
+     */
+    DATA_CALL_DORMANCY_CHANGED = 1 << 2,
+    /**
+     * When this bit is set, modem must send the link capacity update through
+     * IRadioIndication.currentLinkCapacityEstimate() when all criteria specified by
+     * IRadio.setLinkCapacityReportingCriteria() are met.
+     */
+    LINK_CAPACITY_ESTIMATE = 1 << 3,
+    /**
+     * When this bit is set, the modem must send the physical channel configuration update through
+     * IRadioIndication.currentPhysicalChannelConfigs() when the configuration has changed. It is
+     * recommended that this be reported whenever link capacity or signal strength is reported.
+     */
+    PHYSICAL_CHANNEL_CONFIG = 1 << 4,
+};
+
 struct NetworkScanRequest {
     ScanType type;
 
@@ -156,6 +217,10 @@
 struct CellIdentityLte {
     @1.0::CellIdentityLte base;
     CellIdentityOperatorNames operatorNames;
+    /**
+     * Cell bandwidth, in kHz.
+     */
+    int32_t bandwidth;
 };
 
 struct CellIdentityWcdma {
@@ -222,17 +287,10 @@
      * Valid only if type = tdscdma and size = 1 else must be empty.
      */
     vec<CellInfoTdscdma> tdscdma;
-};
-
-enum SlotState : int32_t {
     /**
-     * Physical slot is inactive
+     * Connection status for the cell.
      */
-    INACTIVE  = 0x00,
-    /**
-     * Physical slot is active
-     */
-    ACTIVE    = 0x01,
+    CellConnectionStatus connectionStatus;
 };
 
 struct CardStatus {
@@ -256,30 +314,24 @@
     string iccid;
 };
 
-struct SimSlotStatus {
+struct LinkCapacityEstimate {
     /**
-     * Card state in the physical slot
+     * Estimated downlink capacity in kbps.
      */
-    CardState cardState;
+    uint32_t downlinkCapacityKbps;
     /**
-     * Slot state Active/Inactive
+     * Estimated uplink capacity in kbps.
      */
-    SlotState slotState;
+    uint32_t uplinkCapacityKbps;
+};
+
+struct PhysicalChannelConfig {
     /**
-     * An Answer To Reset (ATR) is a message output by a Smart Card conforming to ISO/IEC 7816
-     * standards, following electrical reset of the card's chip. The ATR conveys information about
-     * the communication parameters proposed by the card, and the card's nature and state.
-     *
-     * This data is applicable only when cardState is CardState:PRESENT.
+     * Connection status for cell. Valid values are PRIMARY_SERVING and SECONDARY_SERVING.
      */
-    string atr;
-    uint32_t logicalSlotId;
+    CellConnectionStatus status;
     /**
-     * Integrated Circuit Card IDentifier (ICCID) is Unique Identifier of the SIM CARD. File is
-     * located in the SIM card at EFiccid (0x2FE2) as per ETSI 102.221. The ICCID is defined by
-     * the ITU-T recommendation E.118 ISO/IEC 7816.
-     *
-     * This data is applicable only when cardState is CardState:PRESENT.
+     * Cell bandwidth, in kHz.
      */
-    string iccid;
+    int32_t cellBandwidthDownlink;
 };
diff --git a/radio/config/1.0/Android.bp b/radio/config/1.0/Android.bp
new file mode 100644
index 0000000..c50e71c
--- /dev/null
+++ b/radio/config/1.0/Android.bp
@@ -0,0 +1,25 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.radio.config@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IRadioConfig.hal",
+        "IRadioConfigIndication.hal",
+        "IRadioConfigResponse.hal",
+    ],
+    interfaces: [
+        "android.hardware.radio@1.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "SimSlotStatus",
+        "SlotState",
+    ],
+    gen_java: true,
+}
+
diff --git a/radio/config/1.0/IRadioConfig.hal b/radio/config/1.0/IRadioConfig.hal
new file mode 100644
index 0000000..9b5d4a8
--- /dev/null
+++ b/radio/config/1.0/IRadioConfig.hal
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 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.radio.config@1.0;
+
+import IRadioConfigResponse;
+import IRadioConfigIndication;
+
+/**
+ * This interface is used by telephony and telecom to talk to cellular radio for the purpose of
+ * radio configuration, and it is not associated with any specific modem or slot.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ */
+interface IRadioConfig {
+
+    /**
+     * Set response functions for radio config requests & radio config indications.
+     *
+     * @param radioConfigResponse Object containing radio config response functions
+     * @param radioConfigIndication Object containing radio config indications
+     */
+    setResponseFunctions(IRadioConfigResponse radioConfigResponse,
+            IRadioConfigIndication radioConfigIndication);
+
+    /**
+     * Get SIM Slot status.
+     *
+     * Request provides the slot status of all active and inactive SIM slots and whether card is
+     * present in the slots or not.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response callback is IRadioConfigResponse.getSimSlotsStatusResponse()
+     */
+    oneway getSimSlotsStatus(int32_t serial);
+
+    /**
+     * Set SIM Slot mapping.
+
+     * Maps the logical slots to the physical slots. Logical slot is the slot that is seen by modem.
+     * Physical slot is the actual physical slot. Request maps the physical slot to logical slot.
+     * Logical slots that are already mapped to the requested physical slot are not impacted.
+     *
+     * Example no. of logical slots 1 and physical slots 2:
+     * The only logical slot (index 0) can be mapped to first physical slot (value 0) or second
+     * physical slot(value 1), while the other physical slot remains unmapped and inactive.
+     * slotMap[0] = 1 or slotMap[0] = 0
+     *
+     * Example no. of logical slots 2 and physical slots 2:
+     * First logical slot (index 0) can be mapped to physical slot 1 or 2 and other logical slot
+     * can be mapped to other physical slot. Each logical slot must be mapped to a physical slot.
+     * slotMap[0] = 0 and slotMap[1] = 1 or slotMap[0] = 1 and slotMap[1] = 0
+     *
+     * @param serial Serial number of request
+     * @param slotMap Logical to physical slot mapping, size == no. of radio instances. Index is
+     *        mapping to logical slot and value to physical slot, need to provide all the slots
+     *        mapping when sending request in case of multi slot device.
+     *        EX: uint32_t slotMap[logical slot] = physical slot
+     *        index 0 is the first logical_slot number of logical slots is equal to number of Radio
+     *        instances and number of physical slots is equal to size of slotStatus in
+     *        getSimSlotsStatusResponse
+     *
+     * Response callback is IRadioConfigResponse.setSimSlotsMappingResponse()
+     */
+    oneway setSimSlotsMapping(int32_t serial, vec<uint32_t> slotMap);
+};
diff --git a/radio/config/1.0/IRadioConfigIndication.hal b/radio/config/1.0/IRadioConfigIndication.hal
new file mode 100644
index 0000000..1800c3c
--- /dev/null
+++ b/radio/config/1.0/IRadioConfigIndication.hal
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 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.radio.config@1.0;
+
+import android.hardware.radio@1.0::RadioIndicationType;
+
+/**
+ * Interface declaring unsolicited radio config indications.
+ */
+interface IRadioConfigIndication {
+
+    /**
+     * Indicates SIM slot status change.
+
+     * This indication must be sent by the modem whenever there is any slot status change, even the
+     * slot is inactive. For example, this indication must be triggered if a SIM card is inserted
+     * into an inactive slot.
+     *
+     * @param type Type of radio indication
+     * @param slotStatus new slot status info with size equals to the number of physical slots on
+     *        the device
+     */
+    oneway simSlotsStatusChanged(RadioIndicationType type, vec<SimSlotStatus> slotStatus);
+};
diff --git a/radio/config/1.0/IRadioConfigResponse.hal b/radio/config/1.0/IRadioConfigResponse.hal
new file mode 100644
index 0000000..917fda1
--- /dev/null
+++ b/radio/config/1.0/IRadioConfigResponse.hal
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 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.radio.config@1.0;
+
+import android.hardware.radio@1.0::RadioResponseInfo;
+
+/**
+ * Interface declaring response functions to solicited radio config requests.
+ */
+interface IRadioConfigResponse {
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param slotStatus Sim slot struct containing all the physical SIM slots info with size
+      *       equals to the number of physical slots on the device
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     */
+    oneway getSimSlotsStatusResponse(RadioResponseInfo info, vec<SimSlotStatus> slotStatus);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    oneway setSimSlotsMappingResponse(RadioResponseInfo info);
+};
diff --git a/radio/config/1.0/default/Android.bp b/radio/config/1.0/default/Android.bp
new file mode 100644
index 0000000..f52335e
--- /dev/null
+++ b/radio/config/1.0/default/Android.bp
@@ -0,0 +1,20 @@
+cc_binary {
+    name: "android.hardware.radio.config@1.0-service",
+    init_rc: ["android.hardware.radio.config@1.0-service.rc"],
+    relative_install_path: "hw",
+    vendor: true,
+    srcs: [
+        "RadioConfig.cpp",
+        "RadioConfigIndication.cpp",
+        "RadioConfigResponse.cpp",
+        "service.cpp",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.radio.config@1.0",
+        "android.hardware.radio@1.0",
+    ],
+}
diff --git a/radio/config/1.0/default/RadioConfig.cpp b/radio/config/1.0/default/RadioConfig.cpp
new file mode 100644
index 0000000..af4b77e
--- /dev/null
+++ b/radio/config/1.0/default/RadioConfig.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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 "RadioConfig.h"
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_0 {
+namespace implementation {
+
+using namespace ::android::hardware::radio::config::V1_0;
+
+// Methods from ::android::hardware::radio::config::V1_0::IRadioConfig follow.
+Return<void> RadioConfig::setResponseFunctions(
+    const sp<IRadioConfigResponse>& radioConfigResponse,
+    const sp<IRadioConfigIndication>& radioConfigIndication) {
+    mRadioConfigResponse = radioConfigResponse;
+    mRadioConfigIndication = radioConfigIndication;
+    return Void();
+}
+
+Return<void> RadioConfig::getSimSlotsStatus(int32_t /* serial */) {
+    hidl_vec<SimSlotStatus> slotStatus;
+    ::android::hardware::radio::V1_0::RadioResponseInfo info;
+    mRadioConfigResponse->getSimSlotsStatusResponse(info, slotStatus);
+    return Void();
+}
+
+Return<void> RadioConfig::setSimSlotsMapping(int32_t /* serial */,
+                                             const hidl_vec<uint32_t>& /* slotMap */) {
+    ::android::hardware::radio::V1_0::RadioResponseInfo info;
+    mRadioConfigResponse->setSimSlotsMappingResponse(info);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
diff --git a/radio/config/1.0/default/RadioConfig.h b/radio/config/1.0/default/RadioConfig.h
new file mode 100644
index 0000000..0f0ac75
--- /dev/null
+++ b/radio/config/1.0/default/RadioConfig.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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_RADIO_CONFIG_V1_0_RADIOCONFIG_H
+#define ANDROID_HARDWARE_RADIO_CONFIG_V1_0_RADIOCONFIG_H
+
+#include <android/hardware/radio/config/1.0/IRadioConfig.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct RadioConfig : public IRadioConfig {
+    sp<IRadioConfigResponse> mRadioConfigResponse;
+    sp<IRadioConfigIndication> mRadioConfigIndication;
+    // Methods from ::android::hardware::radio::config::V1_0::IRadioConfig follow.
+    Return<void> setResponseFunctions(
+        const sp<::android::hardware::radio::config::V1_0::IRadioConfigResponse>&
+            radioConfigResponse,
+        const sp<::android::hardware::radio::config::V1_0::IRadioConfigIndication>&
+            radioConfigIndication) override;
+    Return<void> getSimSlotsStatus(int32_t serial) override;
+    Return<void> setSimSlotsMapping(int32_t serial, const hidl_vec<uint32_t>& slotMap) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_RADIO_CONFIG_V1_0_RADIOCONFIG_H
diff --git a/radio/config/1.0/default/RadioConfigIndication.cpp b/radio/config/1.0/default/RadioConfigIndication.cpp
new file mode 100644
index 0000000..1005ca3
--- /dev/null
+++ b/radio/config/1.0/default/RadioConfigIndication.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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 "RadioConfigIndication.h"
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_0 {
+namespace implementation {
+
+using namespace ::android::hardware::radio::V1_0;
+
+// Methods from ::android::hardware::radio::config::V1_0::IRadioConfigIndication follow.
+Return<void> RadioConfigIndication::simSlotsStatusChanged(
+    RadioIndicationType /* type */, const hidl_vec<SimSlotStatus>& /* slotStatus */) {
+    // TODO implement
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
diff --git a/radio/config/1.0/default/RadioConfigIndication.h b/radio/config/1.0/default/RadioConfigIndication.h
new file mode 100644
index 0000000..cfab1e6
--- /dev/null
+++ b/radio/config/1.0/default/RadioConfigIndication.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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_RADIO_CONFIG_V1_0_RADIOCONFIGINDICATION_H
+#define ANDROID_HARDWARE_RADIO_CONFIG_V1_0_RADIOCONFIGINDICATION_H
+
+#include <android/hardware/radio/config/1.0/IRadioConfigIndication.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct RadioConfigIndication : public IRadioConfigIndication {
+    // Methods from ::android::hardware::radio::config::V1_0::IRadioConfigIndication follow.
+    Return<void> simSlotsStatusChanged(
+        ::android::hardware::radio::V1_0::RadioIndicationType type,
+        const hidl_vec<::android::hardware::radio::config::V1_0::SimSlotStatus>& slotStatus)
+        override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_RADIO_CONFIG_V1_0_RADIOCONFIGINDICATION_H
diff --git a/radio/config/1.0/default/RadioConfigResponse.cpp b/radio/config/1.0/default/RadioConfigResponse.cpp
new file mode 100644
index 0000000..029eab2
--- /dev/null
+++ b/radio/config/1.0/default/RadioConfigResponse.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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 "RadioConfigResponse.h"
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_0 {
+namespace implementation {
+
+using namespace ::android::hardware::radio::V1_0;
+using namespace ::android::hardware::radio::config::V1_0;
+
+// Methods from ::android::hardware::radio::config::V1_0::IRadioConfigResponse follow.
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
+    const RadioResponseInfo& /* info */, const hidl_vec<SimSlotStatus>& /* slotStatus */) {
+    // TODO implement
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) {
+    // TODO implement
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
diff --git a/radio/config/1.0/default/RadioConfigResponse.h b/radio/config/1.0/default/RadioConfigResponse.h
new file mode 100644
index 0000000..7d121fd
--- /dev/null
+++ b/radio/config/1.0/default/RadioConfigResponse.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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_RADIO_CONFIG_V1_0_RADIOCONFIGRESPONSE_H
+#define ANDROID_HARDWARE_RADIO_CONFIG_V1_0_RADIOCONFIGRESPONSE_H
+
+#include <android/hardware/radio/config/1.0/IRadioConfigResponse.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct RadioConfigResponse : public IRadioConfigResponse {
+    // Methods from ::android::hardware::radio::config::V1_0::IRadioConfigResponse follow.
+    Return<void> getSimSlotsStatusResponse(
+        const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+        const hidl_vec<::android::hardware::radio::config::V1_0::SimSlotStatus>& slotStatus)
+        override;
+    Return<void> setSimSlotsMappingResponse(
+        const ::android::hardware::radio::V1_0::RadioResponseInfo& info) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_RADIO_CONFIG_V1_0_RADIOCONFIGRESPONSE_H
diff --git a/radio/config/1.0/default/android.hardware.radio.config@1.0-service.rc b/radio/config/1.0/default/android.hardware.radio.config@1.0-service.rc
new file mode 100644
index 0000000..fad16b1
--- /dev/null
+++ b/radio/config/1.0/default/android.hardware.radio.config@1.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.radio-config-hal-1-0 /vendor/bin/hw/android.hardware.radio.config@1.0-service
+    class hal
+    user system
+    group system
diff --git a/radio/config/1.0/default/service.cpp b/radio/config/1.0/default/service.cpp
new file mode 100644
index 0000000..a06cc22
--- /dev/null
+++ b/radio/config/1.0/default/service.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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 "android.hardware.radio.config@1.0-service"
+
+#include <android/hardware/radio/config/1.0/IRadioConfig.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "RadioConfig.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::radio::config::V1_0::IRadioConfig;
+using android::hardware::radio::config::V1_0::implementation::RadioConfig;
+using android::sp;
+using android::status_t;
+using android::OK;
+
+int main() {
+    configureRpcThreadpool(1, true);
+
+    sp<IRadioConfig> radioConfig = new RadioConfig;
+    status_t status = radioConfig->registerAsService();
+    ALOGW_IF(status != OK, "Could not register IRadioConfig");
+    ALOGD("Default service is ready.");
+
+    joinRpcThreadpool();
+    return 0;
+}
\ No newline at end of file
diff --git a/radio/config/1.0/types.hal b/radio/config/1.0/types.hal
new file mode 100644
index 0000000..a493679
--- /dev/null
+++ b/radio/config/1.0/types.hal
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 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.radio.config@1.0;
+
+import android.hardware.radio@1.0::CardState;
+
+enum SlotState : int32_t {
+    /**
+     * Physical slot is inactive
+     */
+    INACTIVE  = 0x00,
+    /**
+     * Physical slot is active
+     */
+    ACTIVE    = 0x01,
+};
+
+struct SimSlotStatus {
+    /**
+     * Card state in the physical slot
+     */
+    CardState cardState;
+    /**
+     * Slot state Active/Inactive
+     */
+    SlotState slotState;
+    /**
+     * An Answer To Reset (ATR) is a message output by a Smart Card conforming to ISO/IEC 7816
+     * standards, following electrical reset of the card's chip. The ATR conveys information about
+     * the communication parameters proposed by the card, and the card's nature and state.
+     *
+     * This data is applicable only when cardState is CardState:PRESENT.
+     */
+    string atr;
+    uint32_t logicalSlotId;
+    /**
+     * Integrated Circuit Card IDentifier (ICCID) is Unique Identifier of the SIM CARD. File is
+     * located in the SIM card at EFiccid (0x2FE2) as per ETSI 102.221. The ICCID is defined by
+     * the ITU-T recommendation E.118 ISO/IEC 7816.
+     *
+     * This data is applicable only when cardState is CardState:PRESENT.
+     */
+    string iccid;
+};
diff --git a/radio/config/1.0/vts/functional/Android.bp b/radio/config/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..66bfd92
--- /dev/null
+++ b/radio/config/1.0/vts/functional/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2018 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: "VtsHalRadioConfigV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "radio_config_hidl_hal_api.cpp",
+        "radio_config_hidl_hal_test.cpp",
+        "radio_config_response.cpp",
+        "radio_config_indication.cpp",
+    ],
+    static_libs: [
+        "RadioVtsTestUtilBase",
+        "android.hardware.radio.config@1.0",
+    ],
+    header_libs: ["radio.util.header@1.0"],
+}
diff --git a/radio/config/1.0/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.0/vts/functional/radio_config_hidl_hal_api.cpp
new file mode 100644
index 0000000..6782314
--- /dev/null
+++ b/radio/config/1.0/vts/functional/radio_config_hidl_hal_api.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 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 <radio_config_hidl_hal_utils.h>
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+/*
+ * Test IRadioConfig.getSimSlotsStatus()
+ */
+TEST_F(RadioConfigHidlTest, getSimSlotsStatus) {
+    const int serial = GetRandomSerialNumber();
+    Return<void> res = radioConfig->getSimSlotsStatus(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    ALOGI("getIccSlotsStatus, rspInfo.error = %s\n",
+          toString(radioConfigRsp->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioConfig.setSimSlotsMapping()
+ */
+TEST_F(RadioConfigHidlTest, setSimSlotsMapping) {
+    const int serial = GetRandomSerialNumber();
+    android::hardware::hidl_vec<uint32_t> mapping = {0};
+    Return<void> res = radioConfig->setSimSlotsMapping(serial, mapping);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    ALOGI("setSimSlotsMapping, rspInfo.error = %s\n",
+          toString(radioConfigRsp->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
diff --git a/radio/config/1.0/vts/functional/radio_config_hidl_hal_test.cpp b/radio/config/1.0/vts/functional/radio_config_hidl_hal_test.cpp
new file mode 100644
index 0000000..8df6842
--- /dev/null
+++ b/radio/config/1.0/vts/functional/radio_config_hidl_hal_test.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2018 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 <radio_config_hidl_hal_utils.h>
+
+void RadioConfigHidlTest::SetUp() {
+    radioConfig = ::testing::VtsHalHidlTargetTestBase::getService<IRadioConfig>(
+        hidl_string(RADIO_SERVICE_NAME));
+    if (radioConfig == NULL) {
+        sleep(60);
+        radioConfig = ::testing::VtsHalHidlTargetTestBase::getService<IRadioConfig>(
+            hidl_string(RADIO_SERVICE_NAME));
+    }
+    ASSERT_NE(nullptr, radioConfig.get());
+
+    radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this);
+    ASSERT_NE(nullptr, radioConfigRsp.get());
+
+    count_ = 0;
+
+    radioConfigInd = new (std::nothrow) RadioConfigIndication(*this);
+    ASSERT_NE(nullptr, radioConfigInd.get());
+
+    radioConfig->setResponseFunctions(radioConfigRsp, radioConfigInd);
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioConfigHidlTest::notify() {
+    std::unique_lock<std::mutex> lock(mtx_);
+    count_++;
+    cv_.notify_one();
+}
+
+/*
+ * Wait till the response message is notified or till TIMEOUT_PERIOD.
+ */
+std::cv_status RadioConfigHidlTest::wait() {
+    std::unique_lock<std::mutex> lock(mtx_);
+
+    std::cv_status status = std::cv_status::no_timeout;
+    auto now = std::chrono::system_clock::now();
+    while (count_ == 0) {
+        status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+        if (status == std::cv_status::timeout) {
+            return status;
+        }
+    }
+    count_--;
+    return status;
+}
diff --git a/radio/config/1.0/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.0/vts/functional/radio_config_hidl_hal_utils.h
new file mode 100644
index 0000000..762cc98
--- /dev/null
+++ b/radio/config/1.0/vts/functional/radio_config_hidl_hal_utils.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2018 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 <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include <android/hardware/radio/config/1.0/IRadioConfig.h>
+#include <android/hardware/radio/config/1.0/IRadioConfigIndication.h>
+#include <android/hardware/radio/config/1.0/IRadioConfigResponse.h>
+#include <android/hardware/radio/config/1.0/types.h>
+
+#include "vts_test_util.h"
+
+using namespace ::android::hardware::radio::config::V1_0;
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::radio::V1_0::RadioIndicationType;
+using ::android::hardware::radio::V1_0::RadioResponseInfo;
+using ::android::hardware::radio::V1_0::RadioResponseType;
+using ::android::sp;
+
+#define TIMEOUT_PERIOD 75
+#define RADIO_SERVICE_NAME "slot1"
+
+class RadioConfigHidlTest;
+
+/* Callback class for radio config response */
+class RadioConfigResponse : public IRadioConfigResponse {
+   protected:
+    RadioConfigHidlTest& parent;
+
+   public:
+    RadioResponseInfo rspInfo;
+
+    RadioConfigResponse(RadioConfigHidlTest& parent);
+    virtual ~RadioConfigResponse() = default;
+
+    Return<void> getSimSlotsStatusResponse(
+        const RadioResponseInfo& info,
+        const ::android::hardware::hidl_vec<SimSlotStatus>& slotStatus);
+
+    Return<void> setSimSlotsMappingResponse(const RadioResponseInfo& info);
+};
+
+/* Callback class for radio config indication */
+class RadioConfigIndication : public IRadioConfigIndication {
+   protected:
+    RadioConfigHidlTest& parent;
+
+   public:
+    RadioConfigIndication(RadioConfigHidlTest& parent);
+    virtual ~RadioConfigIndication() = default;
+
+    Return<void> simSlotsStatusChanged(
+        RadioIndicationType type, const ::android::hardware::hidl_vec<SimSlotStatus>& slotStatus);
+};
+
+// The main test class for Radio config HIDL.
+class RadioConfigHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   protected:
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    int count_;
+
+   public:
+    virtual void SetUp() override;
+
+    /* Used as a mechanism to inform the test about data/event callback */
+    void notify();
+
+    /* Test code calls this function to wait for response */
+    std::cv_status wait();
+
+    /* radio config service handle */
+    sp<IRadioConfig> radioConfig;
+
+    /* radio config response handle */
+    sp<RadioConfigResponse> radioConfigRsp;
+
+    /* radio config indication handle */
+    sp<RadioConfigIndication> radioConfigInd;
+};
diff --git a/radio/config/1.0/vts/functional/radio_config_indication.cpp b/radio/config/1.0/vts/functional/radio_config_indication.cpp
new file mode 100644
index 0000000..b3a5843
--- /dev/null
+++ b/radio/config/1.0/vts/functional/radio_config_indication.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 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 <radio_config_hidl_hal_utils.h>
+
+RadioConfigIndication::RadioConfigIndication(RadioConfigHidlTest& parent) : parent(parent) {}
+
+Return<void> RadioConfigIndication::simSlotsStatusChanged(
+    RadioIndicationType /*type*/,
+    const ::android::hardware::hidl_vec<SimSlotStatus>& /*slotStatus*/) {
+    return Void();
+}
diff --git a/radio/config/1.0/vts/functional/radio_config_response.cpp b/radio/config/1.0/vts/functional/radio_config_response.cpp
new file mode 100644
index 0000000..97e8dca
--- /dev/null
+++ b/radio/config/1.0/vts/functional/radio_config_response.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 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 <radio_config_hidl_hal_utils.h>
+
+SimSlotStatus slotStatus;
+
+RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {}
+
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
+    const RadioResponseInfo& /* info */,
+    const ::android::hardware::hidl_vec<SimSlotStatus>& /* slotStatus */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) {
+    return Void();
+}
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index ca3d3e4..24b58a7 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -15,8 +15,8 @@
  */
 
 #define LOG_TAG "sensors_hidl_hal_test"
-#include "GrallocWrapper.h"
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/sensors/1.0/ISensors.h>
 #include <android/hardware/sensors/1.0/types.h>
@@ -24,6 +24,7 @@
 #include <hardware/sensors.h>  // for sensor type strings
 #include <log/log.h>
 #include <utils/SystemClock.h>
+#include "GrallocWrapper.h"
 
 #include <algorithm>
 #include <cinttypes>
@@ -46,63 +47,65 @@
 
 // Test environment for sensors
 class SensorsHidlTest;
-class SensorsHidlEnvironment : public ::testing::Environment {
- public:
-  // get the test environment singleton
-  static SensorsHidlEnvironment* Instance() {
-    static SensorsHidlEnvironment* instance = new SensorsHidlEnvironment;
-    return instance;
-  }
+class SensorsHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static SensorsHidlEnvironment* Instance() {
+        static SensorsHidlEnvironment* instance = new SensorsHidlEnvironment;
+        return instance;
+    }
 
-  virtual void SetUp();
-  virtual void TearDown();
+    virtual void HidlSetUp() override;
+    virtual void HidlTearDown() override;
 
-  // Get and clear all events collected so far (like "cat" shell command).
-  // If output is nullptr, it clears all collected events.
-  void catEvents(std::vector<Event>* output);
+    virtual void registerTestServices() override { registerTestService<ISensors>(); }
 
-  // set sensor event collection status
-  void setCollection(bool enable);
+    // Get and clear all events collected so far (like "cat" shell command).
+    // If output is nullptr, it clears all collected events.
+    void catEvents(std::vector<Event>* output);
 
- private:
-  friend SensorsHidlTest;
-  // sensors hidl service
-  sp<ISensors> sensors;
+    // set sensor event collection status
+    void setCollection(bool enable);
 
-  SensorsHidlEnvironment() {}
+   private:
+    friend SensorsHidlTest;
+    // sensors hidl service
+    sp<ISensors> sensors;
 
-  void addEvent(const Event& ev);
-  void startPollingThread();
-  void resetHal();
-  static void pollingThread(SensorsHidlEnvironment* env, std::shared_ptr<bool> stop);
+    SensorsHidlEnvironment() {}
 
-  bool collectionEnabled;
-  std::shared_ptr<bool> stopThread;
-  std::thread pollThread;
-  std::vector<Event> events;
-  std::mutex events_mutex;
+    void addEvent(const Event& ev);
+    void startPollingThread();
+    void resetHal();
+    static void pollingThread(SensorsHidlEnvironment* env, std::shared_ptr<bool> stop);
 
-  GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironment);
+    bool collectionEnabled;
+    std::shared_ptr<bool> stopThread;
+    std::thread pollThread;
+    std::vector<Event> events;
+    std::mutex events_mutex;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironment);
 };
 
-void SensorsHidlEnvironment::SetUp() {
-  resetHal();
+void SensorsHidlEnvironment::HidlSetUp() {
+    resetHal();
 
-  ASSERT_NE(sensors, nullptr) << "sensors is nullptr, cannot get hidl service";
+    ASSERT_NE(sensors, nullptr) << "sensors is nullptr, cannot get hidl service";
 
-  collectionEnabled = false;
-  startPollingThread();
+    collectionEnabled = false;
+    startPollingThread();
 
-  // In case framework just stopped for test and there is sensor events in the pipe,
-  // wait some time for those events to be cleared to avoid them messing up the test.
-  std::this_thread::sleep_for(std::chrono::seconds(3));
+    // In case framework just stopped for test and there is sensor events in the pipe,
+    // wait some time for those events to be cleared to avoid them messing up the test.
+    std::this_thread::sleep_for(std::chrono::seconds(3));
 }
 
-void SensorsHidlEnvironment::TearDown() {
-  if (stopThread) {
-    *stopThread = true;
-  }
-  pollThread.detach();
+void SensorsHidlEnvironment::HidlTearDown() {
+    if (stopThread) {
+        *stopThread = true;
+    }
+    pollThread.detach();
 }
 
 void SensorsHidlEnvironment::resetHal() {
@@ -115,7 +118,8 @@
     // this do ... while is for easy error handling
     do {
       step = "getService()";
-      sensors = ISensors::getService();
+      sensors = ISensors::getService(
+          SensorsHidlEnvironment::Instance()->getServiceName<ISensors>());
       if (sensors == nullptr) {
         break;
       }
@@ -1500,6 +1504,7 @@
 int main(int argc, char **argv) {
   ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironment::Instance());
   ::testing::InitGoogleTest(&argc, argv);
+  SensorsHidlEnvironment::Instance()->init(&argc, argv);
   int status = RUN_ALL_TESTS();
   ALOGI("Test result = %d", status);
   return status;
diff --git a/soundtrigger/2.0/default/Android.bp b/soundtrigger/2.0/default/Android.bp
new file mode 100644
index 0000000..cc20f91
--- /dev/null
+++ b/soundtrigger/2.0/default/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2018 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_library_shared {
+    name: "android.hardware.soundtrigger@2.0-core",
+    defaults: ["hidl_defaults"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "SoundTriggerHalImpl.cpp",
+    ],
+
+    export_include_dirs: ["."],
+
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "libhardware",
+        "android.hardware.soundtrigger@2.0",
+        "android.hardware.audio.common@2.0",
+    ],
+
+    header_libs: [
+        "libaudio_system_headers",
+        "libhardware_headers",
+    ],
+}
diff --git a/soundtrigger/2.0/default/Android.mk b/soundtrigger/2.0/default/Android.mk
index 9262858..835a020 100644
--- a/soundtrigger/2.0/default/Android.mk
+++ b/soundtrigger/2.0/default/Android.mk
@@ -18,23 +18,20 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.soundtrigger@2.0-impl
-LOCAL_PROPRIETARY_MODULE := true
+LOCAL_VENDOR_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_SRC_FILES := \
-    SoundTriggerHalImpl.cpp
+    FetchISoundTriggerHw.cpp
 
 LOCAL_CFLAGS := -Wall -Werror
 
 LOCAL_SHARED_LIBRARIES := \
-        libhidlbase \
-        libhidltransport \
-        liblog \
-        libutils \
         libhardware \
+        libutils \
         android.hardware.soundtrigger@2.0 \
-        android.hardware.audio.common@2.0
+        android.hardware.soundtrigger@2.0-core
 
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH)
 
 ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
 LOCAL_MULTILIB := 32
diff --git a/soundtrigger/2.0/default/FetchISoundTriggerHw.cpp b/soundtrigger/2.0/default/FetchISoundTriggerHw.cpp
new file mode 100644
index 0000000..bd99221
--- /dev/null
+++ b/soundtrigger/2.0/default/FetchISoundTriggerHw.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2018 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 "SoundTriggerHalImpl.h"
+
+extern "C" ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(
+    const char* /* name */) {
+    return (new ::android::hardware::soundtrigger::V2_0::implementation::SoundTriggerHalImpl())
+        ->getInterface();
+}
diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
index f963fb1..612772c 100644
--- a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
+++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
@@ -17,9 +17,8 @@
 #define LOG_TAG "SoundTriggerHalImpl"
 //#define LOG_NDEBUG 0
 
-#include <android/log.h>
 #include "SoundTriggerHalImpl.h"
-
+#include <android/log.h>
 
 namespace android {
 namespace hardware {
@@ -28,64 +27,45 @@
 namespace implementation {
 
 // static
-void SoundTriggerHalImpl::soundModelCallback(struct sound_trigger_model_event *halEvent,
-                                               void *cookie)
-{
+void SoundTriggerHalImpl::soundModelCallback(struct sound_trigger_model_event* halEvent,
+                                             void* cookie) {
     if (halEvent == NULL) {
         ALOGW("soundModelCallback called with NULL event");
         return;
     }
     sp<SoundModelClient> client =
-            wp<SoundModelClient>(static_cast<SoundModelClient *>(cookie)).promote();
+        wp<SoundModelClient>(static_cast<SoundModelClient*>(cookie)).promote();
     if (client == 0) {
         ALOGW("soundModelCallback called on stale client");
         return;
     }
-    if (halEvent->model != client->mHalHandle) {
+    if (halEvent->model != client->getHalHandle()) {
         ALOGW("soundModelCallback call with wrong handle %d on client with handle %d",
-              (int)halEvent->model, (int)client->mHalHandle);
+              (int)halEvent->model, (int)client->getHalHandle());
         return;
     }
 
-    ISoundTriggerHwCallback::ModelEvent event;
-    convertSoundModelEventFromHal(&event, halEvent);
-    event.model = client->mId;
-
-    client->mCallback->soundModelCallback(event, client->mCookie);
+    client->soundModelCallback(halEvent);
 }
 
 // static
-void SoundTriggerHalImpl::recognitionCallback(struct sound_trigger_recognition_event *halEvent,
-                                               void *cookie)
-{
+void SoundTriggerHalImpl::recognitionCallback(struct sound_trigger_recognition_event* halEvent,
+                                              void* cookie) {
     if (halEvent == NULL) {
         ALOGW("recognitionCallback call NULL event");
         return;
     }
     sp<SoundModelClient> client =
-            wp<SoundModelClient>(static_cast<SoundModelClient *>(cookie)).promote();
+        wp<SoundModelClient>(static_cast<SoundModelClient*>(cookie)).promote();
     if (client == 0) {
         ALOGW("soundModelCallback called on stale client");
         return;
     }
 
-    ISoundTriggerHwCallback::RecognitionEvent *event = convertRecognitionEventFromHal(halEvent);
-    event->model = client->mId;
-    if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
-        client->mCallback->phraseRecognitionCallback(
-                *(reinterpret_cast<ISoundTriggerHwCallback::PhraseRecognitionEvent *>(event)),
-                client->mCookie);
-    } else {
-        client->mCallback->recognitionCallback(*event, client->mCookie);
-    }
-    delete event;
+    client->recognitionCallback(halEvent);
 }
 
-
-
-// Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow.
-Return<void> SoundTriggerHalImpl::getProperties(getProperties_cb _hidl_cb)
-{
+Return<void> SoundTriggerHalImpl::getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb) {
     ALOGV("getProperties() mHwDevice %p", mHwDevice);
     int ret;
     struct sound_trigger_properties halProperties;
@@ -100,8 +80,8 @@
 
     convertPropertiesFromHal(&properties, &halProperties);
 
-    ALOGV("getProperties implementor %s recognitionModes %08x",
-          properties.implementor.c_str(), properties.recognitionModes);
+    ALOGV("getProperties implementor %s recognitionModes %08x", properties.implementor.c_str(),
+          properties.recognitionModes);
 
 exit:
     _hidl_cb(ret, properties);
@@ -109,14 +89,9 @@
 }
 
 int SoundTriggerHalImpl::doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
-                                                 const sp<ISoundTriggerHwCallback>& callback,
-                                                 ISoundTriggerHwCallback::CallbackCookie cookie,
-                                                 uint32_t *modelId)
-{
+                                          sp<SoundModelClient> client) {
     int32_t ret = 0;
-    struct sound_trigger_sound_model *halSoundModel;
-    *modelId = 0;
-    sp<SoundModelClient> client;
+    struct sound_trigger_sound_model* halSoundModel;
 
     ALOGV("doLoadSoundModel() data size %zu", soundModel.data.size());
 
@@ -131,19 +106,9 @@
         goto exit;
     }
 
-    {
-        AutoMutex lock(mLock);
-        do {
-            *modelId = nextUniqueId();
-        } while (mClients.valueFor(*modelId) != 0 && *modelId != 0);
-    }
-    LOG_ALWAYS_FATAL_IF(*modelId == 0,
-                        "wrap around in sound model IDs, num loaded models %zu", mClients.size());
-
-    client = new SoundModelClient(*modelId, callback, cookie);
-
-    ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback,
-                                          client.get(), &client->mHalHandle);
+    sound_model_handle_t halHandle;
+    ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback, client.get(),
+                                      &halHandle);
 
     free(halSoundModel);
 
@@ -151,9 +116,10 @@
         goto exit;
     }
 
+    client->setHalHandle(halHandle);
     {
         AutoMutex lock(mLock);
-        mClients.add(*modelId, client);
+        mClients.add(client->getId(), client);
     }
 
 exit:
@@ -163,31 +129,23 @@
 Return<void> SoundTriggerHalImpl::loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
                                                  const sp<ISoundTriggerHwCallback>& callback,
                                                  ISoundTriggerHwCallback::CallbackCookie cookie,
-                                                 loadSoundModel_cb _hidl_cb)
-{
-    uint32_t modelId = 0;
-    int32_t ret = doLoadSoundModel(soundModel, callback, cookie, &modelId);
-
-    _hidl_cb(ret, modelId);
+                                                 ISoundTriggerHw::loadSoundModel_cb _hidl_cb) {
+    sp<SoundModelClient> client = new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
+    _hidl_cb(doLoadSoundModel(soundModel, client), client->getId());
     return Void();
 }
 
 Return<void> SoundTriggerHalImpl::loadPhraseSoundModel(
-                                            const ISoundTriggerHw::PhraseSoundModel& soundModel,
-                                            const sp<ISoundTriggerHwCallback>& callback,
-                                            ISoundTriggerHwCallback::CallbackCookie cookie,
-                                            ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb)
-{
-    uint32_t modelId = 0;
-    int32_t ret = doLoadSoundModel((const ISoundTriggerHw::SoundModel&)soundModel,
-                                   callback, cookie, &modelId);
-
-    _hidl_cb(ret, modelId);
+    const ISoundTriggerHw::PhraseSoundModel& soundModel,
+    const sp<ISoundTriggerHwCallback>& callback, ISoundTriggerHwCallback::CallbackCookie cookie,
+    ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb) {
+    sp<SoundModelClient> client = new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
+    _hidl_cb(doLoadSoundModel((const ISoundTriggerHw::SoundModel&)soundModel, client),
+             client->getId());
     return Void();
 }
 
-Return<int32_t> SoundTriggerHalImpl::unloadSoundModel(SoundModelHandle modelHandle)
-{
+Return<int32_t> SoundTriggerHalImpl::unloadSoundModel(SoundModelHandle modelHandle) {
     int32_t ret;
     sp<SoundModelClient> client;
 
@@ -205,7 +163,7 @@
         }
     }
 
-    ret = mHwDevice->unload_sound_model(mHwDevice, client->mHalHandle);
+    ret = mHwDevice->unload_sound_model(mHwDevice, client->getHalHandle());
 
     mClients.removeItem(modelHandle);
 
@@ -213,14 +171,11 @@
     return ret;
 }
 
-Return<int32_t> SoundTriggerHalImpl::startRecognition(SoundModelHandle modelHandle,
-                                           const ISoundTriggerHw::RecognitionConfig& config,
-                                           const sp<ISoundTriggerHwCallback>& callback __unused,
-                                           ISoundTriggerHwCallback::CallbackCookie cookie __unused)
-{
+Return<int32_t> SoundTriggerHalImpl::startRecognition(
+    SoundModelHandle modelHandle, const ISoundTriggerHw::RecognitionConfig& config) {
     int32_t ret;
     sp<SoundModelClient> client;
-    struct sound_trigger_recognition_config *halConfig;
+    struct sound_trigger_recognition_config* halConfig;
 
     if (mHwDevice == NULL) {
         ret = -ENODEV;
@@ -236,15 +191,14 @@
         }
     }
 
-
     halConfig = convertRecognitionConfigToHal(&config);
 
     if (halConfig == NULL) {
         ret = -EINVAL;
         goto exit;
     }
-    ret = mHwDevice->start_recognition(mHwDevice, client->mHalHandle, halConfig,
-                                 recognitionCallback, client.get());
+    ret = mHwDevice->start_recognition(mHwDevice, client->getHalHandle(), halConfig,
+                                       recognitionCallback, client.get());
 
     free(halConfig);
 
@@ -252,8 +206,7 @@
     return ret;
 }
 
-Return<int32_t> SoundTriggerHalImpl::stopRecognition(SoundModelHandle modelHandle)
-{
+Return<int32_t> SoundTriggerHalImpl::stopRecognition(SoundModelHandle modelHandle) {
     int32_t ret;
     sp<SoundModelClient> client;
     if (mHwDevice == NULL) {
@@ -270,14 +223,13 @@
         }
     }
 
-    ret = mHwDevice->stop_recognition(mHwDevice, client->mHalHandle);
+    ret = mHwDevice->stop_recognition(mHwDevice, client->getHalHandle());
 
 exit:
     return ret;
 }
 
-Return<int32_t> SoundTriggerHalImpl::stopAllRecognitions()
-{
+Return<int32_t> SoundTriggerHalImpl::stopAllRecognitions() {
     int32_t ret;
     if (mHwDevice == NULL) {
         ret = -ENODEV;
@@ -285,7 +237,7 @@
     }
 
     if (mHwDevice->common.version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_1 &&
-            mHwDevice->stop_all_recognitions) {
+        mHwDevice->stop_all_recognitions) {
         ret = mHwDevice->stop_all_recognitions(mHwDevice);
     } else {
         ret = -ENOSYS;
@@ -295,19 +247,16 @@
 }
 
 SoundTriggerHalImpl::SoundTriggerHalImpl()
-    : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1)
-{
-}
+    : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {}
 
-void SoundTriggerHalImpl::onFirstRef()
-{
-    const hw_module_t *mod;
+void SoundTriggerHalImpl::onFirstRef() {
+    const hw_module_t* mod;
     int rc;
 
     rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod);
     if (rc != 0) {
-        ALOGE("couldn't load sound trigger module %s.%s (%s)",
-              SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc));
+        ALOGE("couldn't load sound trigger module %s.%s (%s)", SOUND_TRIGGER_HARDWARE_MODULE_ID,
+              mModuleName, strerror(-rc));
         return;
     }
     rc = sound_trigger_hw_device_open(mod, &mHwDevice);
@@ -318,7 +267,7 @@
         return;
     }
     if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_0 ||
-            mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
+        mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
         ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version);
         sound_trigger_hw_device_close(mHwDevice);
         mHwDevice = NULL;
@@ -328,22 +277,27 @@
     ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice);
 }
 
-SoundTriggerHalImpl::~SoundTriggerHalImpl()
-{
+SoundTriggerHalImpl::~SoundTriggerHalImpl() {
     if (mHwDevice != NULL) {
         sound_trigger_hw_device_close(mHwDevice);
     }
 }
 
-uint32_t SoundTriggerHalImpl::nextUniqueId()
-{
-    return (uint32_t) atomic_fetch_add_explicit(&mNextModelId,
-                (uint_fast32_t) 1, memory_order_acq_rel);
+uint32_t SoundTriggerHalImpl::nextUniqueModelId() {
+    uint32_t modelId = 0;
+    {
+        AutoMutex lock(mLock);
+        do {
+            modelId =
+                atomic_fetch_add_explicit(&mNextModelId, (uint_fast32_t)1, memory_order_acq_rel);
+        } while (mClients.valueFor(modelId) != 0 && modelId != 0);
+    }
+    LOG_ALWAYS_FATAL_IF(modelId == 0, "wrap around in sound model IDs, num loaded models %zu",
+                        mClients.size());
+    return modelId;
 }
 
-void SoundTriggerHalImpl::convertUuidFromHal(Uuid *uuid,
-                                             const sound_trigger_uuid_t *halUuid)
-{
+void SoundTriggerHalImpl::convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid) {
     uuid->timeLow = halUuid->timeLow;
     uuid->timeMid = halUuid->timeMid;
     uuid->versionAndTimeHigh = halUuid->timeHiAndVersion;
@@ -351,9 +305,7 @@
     memcpy(&uuid->node[0], &halUuid->node[0], 6);
 }
 
-void SoundTriggerHalImpl::convertUuidToHal(sound_trigger_uuid_t *halUuid,
-                                           const Uuid *uuid)
-{
+void SoundTriggerHalImpl::convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid) {
     halUuid->timeLow = uuid->timeLow;
     halUuid->timeMid = uuid->timeMid;
     halUuid->timeHiAndVersion = uuid->versionAndTimeHigh;
@@ -362,9 +314,7 @@
 }
 
 void SoundTriggerHalImpl::convertPropertiesFromHal(
-        ISoundTriggerHw::Properties *properties,
-        const struct sound_trigger_properties *halProperties)
-{
+    ISoundTriggerHw::Properties* properties, const struct sound_trigger_properties* halProperties) {
     properties->implementor = halProperties->implementor;
     properties->description = halProperties->description;
     properties->version = halProperties->version;
@@ -378,13 +328,10 @@
     properties->concurrentCapture = halProperties->concurrent_capture;
     properties->triggerInEvent = halProperties->trigger_in_event;
     properties->powerConsumptionMw = halProperties->power_consumption_mw;
-
 }
 
-void SoundTriggerHalImpl::convertTriggerPhraseToHal(
-        struct sound_trigger_phrase *halTriggerPhrase,
-        const ISoundTriggerHw::Phrase *triggerPhrase)
-{
+void SoundTriggerHalImpl::convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
+                                                    const ISoundTriggerHw::Phrase* triggerPhrase) {
     halTriggerPhrase->id = triggerPhrase->id;
     halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes;
     unsigned int i;
@@ -395,39 +342,35 @@
         halTriggerPhrase->users[i] = triggerPhrase->users[i];
     }
 
-    strlcpy(halTriggerPhrase->locale,
-            triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
-    strlcpy(halTriggerPhrase->text,
-            triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
+    strlcpy(halTriggerPhrase->locale, triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
+    strlcpy(halTriggerPhrase->text, triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
 }
 
-struct sound_trigger_sound_model *SoundTriggerHalImpl::convertSoundModelToHal(
-        const ISoundTriggerHw::SoundModel *soundModel)
-{
-    struct sound_trigger_sound_model *halModel = NULL;
+struct sound_trigger_sound_model* SoundTriggerHalImpl::convertSoundModelToHal(
+    const ISoundTriggerHw::SoundModel* soundModel) {
+    struct sound_trigger_sound_model* halModel = NULL;
     if (soundModel->type == SoundModelType::KEYPHRASE) {
         size_t allocSize =
-                sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
-        struct sound_trigger_phrase_sound_model *halKeyPhraseModel =
-                static_cast<struct sound_trigger_phrase_sound_model *>(malloc(allocSize));
+            sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
+        struct sound_trigger_phrase_sound_model* halKeyPhraseModel =
+            static_cast<struct sound_trigger_phrase_sound_model*>(malloc(allocSize));
         LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL,
-                        "malloc failed for size %zu in convertSoundModelToHal PHRASE", allocSize);
+                            "malloc failed for size %zu in convertSoundModelToHal PHRASE",
+                            allocSize);
 
-        const ISoundTriggerHw::PhraseSoundModel *keyPhraseModel =
-                reinterpret_cast<const ISoundTriggerHw::PhraseSoundModel *>(soundModel);
+        const ISoundTriggerHw::PhraseSoundModel* keyPhraseModel =
+            reinterpret_cast<const ISoundTriggerHw::PhraseSoundModel*>(soundModel);
 
         size_t i;
         for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
-            convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i],
-                                      &keyPhraseModel->phrases[i]);
+            convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i], &keyPhraseModel->phrases[i]);
         }
         halKeyPhraseModel->num_phrases = (unsigned int)i;
-        halModel = reinterpret_cast<struct sound_trigger_sound_model *>(halKeyPhraseModel);
+        halModel = reinterpret_cast<struct sound_trigger_sound_model*>(halKeyPhraseModel);
         halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model);
     } else {
-        size_t allocSize =
-                sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
-        halModel = static_cast<struct sound_trigger_sound_model *>(malloc(allocSize));
+        size_t allocSize = sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
+        halModel = static_cast<struct sound_trigger_sound_model*>(malloc(allocSize));
         LOG_ALWAYS_FATAL_IF(halModel == NULL,
                             "malloc failed for size %zu in convertSoundModelToHal GENERIC",
                             allocSize);
@@ -438,17 +381,15 @@
     convertUuidToHal(&halModel->uuid, &soundModel->uuid);
     convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid);
     halModel->data_size = soundModel->data.size();
-    uint8_t *dst = reinterpret_cast<uint8_t *>(halModel) + halModel->data_offset;
-    const uint8_t *src = reinterpret_cast<const uint8_t *>(&soundModel->data[0]);
+    uint8_t* dst = reinterpret_cast<uint8_t*>(halModel) + halModel->data_offset;
+    const uint8_t* src = reinterpret_cast<const uint8_t*>(&soundModel->data[0]);
     memcpy(dst, src, soundModel->data.size());
 
     return halModel;
 }
 
 void SoundTriggerHalImpl::convertPhraseRecognitionExtraToHal(
-        struct sound_trigger_phrase_recognition_extra *halExtra,
-        const PhraseRecognitionExtra *extra)
-{
+    struct sound_trigger_phrase_recognition_extra* halExtra, const PhraseRecognitionExtra* extra) {
     halExtra->id = extra->id;
     halExtra->recognition_modes = extra->recognitionModes;
     halExtra->confidence_level = extra->confidenceLevel;
@@ -461,16 +402,14 @@
     halExtra->num_levels = i;
 }
 
-struct sound_trigger_recognition_config *SoundTriggerHalImpl::convertRecognitionConfigToHal(
-        const ISoundTriggerHw::RecognitionConfig *config)
-{
+struct sound_trigger_recognition_config* SoundTriggerHalImpl::convertRecognitionConfigToHal(
+    const ISoundTriggerHw::RecognitionConfig* config) {
     size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size();
-    struct sound_trigger_recognition_config *halConfig =
-            static_cast<struct sound_trigger_recognition_config *>(malloc(allocSize));
+    struct sound_trigger_recognition_config* halConfig =
+        static_cast<struct sound_trigger_recognition_config*>(malloc(allocSize));
 
     LOG_ALWAYS_FATAL_IF(halConfig == NULL,
-                        "malloc failed for size %zu in convertRecognitionConfigToHal",
-                        allocSize);
+                        "malloc failed for size %zu in convertRecognitionConfigToHal", allocSize);
 
     halConfig->capture_handle = (audio_io_handle_t)config->captureHandle;
     halConfig->capture_device = (audio_devices_t)config->captureDevice;
@@ -478,57 +417,43 @@
 
     unsigned int i;
     for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
-        convertPhraseRecognitionExtraToHal(&halConfig->phrases[i],
-                                  &config->phrases[i]);
+        convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], &config->phrases[i]);
     }
     halConfig->num_phrases = i;
 
     halConfig->data_offset = sizeof(struct sound_trigger_recognition_config);
     halConfig->data_size = config->data.size();
-    uint8_t *dst = reinterpret_cast<uint8_t *>(halConfig) + halConfig->data_offset;
-    const uint8_t *src = reinterpret_cast<const uint8_t *>(&config->data[0]);
+    uint8_t* dst = reinterpret_cast<uint8_t*>(halConfig) + halConfig->data_offset;
+    const uint8_t* src = reinterpret_cast<const uint8_t*>(&config->data[0]);
     memcpy(dst, src, config->data.size());
     return halConfig;
 }
 
 // static
-void SoundTriggerHalImpl::convertSoundModelEventFromHal(ISoundTriggerHwCallback::ModelEvent *event,
-                                                const struct sound_trigger_model_event *halEvent)
-{
+void SoundTriggerHalImpl::convertSoundModelEventFromHal(
+    ISoundTriggerHwCallback::ModelEvent* event, const struct sound_trigger_model_event* halEvent) {
     event->status = (ISoundTriggerHwCallback::SoundModelStatus)halEvent->status;
     // event->model to be remapped by called
     event->data.setToExternal(
-            const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(halEvent)) + halEvent->data_offset,
-            halEvent->data_size);
+        const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
+        halEvent->data_size);
 }
 
 // static
-ISoundTriggerHwCallback::RecognitionEvent *SoundTriggerHalImpl::convertRecognitionEventFromHal(
-                                            const struct sound_trigger_recognition_event *halEvent)
-{
-    ISoundTriggerHwCallback::RecognitionEvent * event;
-
-    if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
-        const struct sound_trigger_phrase_recognition_event *halPhraseEvent =
-                reinterpret_cast<const struct sound_trigger_phrase_recognition_event *>(halEvent);
-        ISoundTriggerHwCallback::PhraseRecognitionEvent *phraseEvent =
-                new ISoundTriggerHwCallback::PhraseRecognitionEvent();
-
-        PhraseRecognitionExtra *phraseExtras =
-                new PhraseRecognitionExtra[halPhraseEvent->num_phrases];
-        for (unsigned int i = 0; i < halPhraseEvent->num_phrases; i++) {
-            convertPhraseRecognitionExtraFromHal(&phraseExtras[i],
-                                                 &halPhraseEvent->phrase_extras[i]);
-        }
-        phraseEvent->phraseExtras.setToExternal(phraseExtras, halPhraseEvent->num_phrases);
-        // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-        phraseEvent->phraseExtras.resize(halPhraseEvent->num_phrases);
-        delete[] phraseExtras;
-        event = reinterpret_cast<ISoundTriggerHwCallback::RecognitionEvent *>(phraseEvent);
-    } else {
-        event = new ISoundTriggerHwCallback::RecognitionEvent();
+void SoundTriggerHalImpl::convertPhaseRecognitionEventFromHal(
+    ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
+    const struct sound_trigger_phrase_recognition_event* halEvent) {
+    event->phraseExtras.resize(halEvent->num_phrases);
+    for (unsigned int i = 0; i < halEvent->num_phrases; i++) {
+        convertPhraseRecognitionExtraFromHal(&event->phraseExtras[i], &halEvent->phrase_extras[i]);
     }
+    convertRecognitionEventFromHal(&event->common, &halEvent->common);
+}
 
+// static
+void SoundTriggerHalImpl::convertRecognitionEventFromHal(
+    ISoundTriggerHwCallback::RecognitionEvent* event,
+    const struct sound_trigger_recognition_event* halEvent) {
     event->status = static_cast<ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status);
     event->type = static_cast<SoundModelType>(halEvent->type);
     // event->model to be remapped by called
@@ -539,45 +464,53 @@
     event->triggerInData = halEvent->trigger_in_data;
     event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate;
     event->audioConfig.channelMask =
-            (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
+        (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
     event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format;
     event->data.setToExternal(
-            const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(halEvent)) + halEvent->data_offset,
-            halEvent->data_size);
-
-    return event;
+        const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
+        halEvent->data_size);
 }
 
 // static
 void SoundTriggerHalImpl::convertPhraseRecognitionExtraFromHal(
-        PhraseRecognitionExtra *extra,
-        const struct sound_trigger_phrase_recognition_extra *halExtra)
-{
+    PhraseRecognitionExtra* extra, const struct sound_trigger_phrase_recognition_extra* halExtra) {
     extra->id = halExtra->id;
     extra->recognitionModes = halExtra->recognition_modes;
     extra->confidenceLevel = halExtra->confidence_level;
 
-    ConfidenceLevel *levels =
-            new ConfidenceLevel[halExtra->num_levels];
-    for (unsigned int i = 0; i < halExtra->num_levels; i++) {
-        levels[i].userId = halExtra->levels[i].user_id;
-        levels[i].levelPercent = halExtra->levels[i].level;
-    }
-    extra->levels.setToExternal(levels, halExtra->num_levels);
-    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
     extra->levels.resize(halExtra->num_levels);
-    delete[] levels;
+    for (unsigned int i = 0; i < halExtra->num_levels; i++) {
+        extra->levels[i].userId = halExtra->levels[i].user_id;
+        extra->levels[i].levelPercent = halExtra->levels[i].level;
+    }
 }
 
-ISoundTriggerHw *HIDL_FETCH_ISoundTriggerHw(const char* /* name */)
-{
-    return new SoundTriggerHalImpl();
+void SoundTriggerHalImpl::SoundModelClient_2_0::recognitionCallback(
+    struct sound_trigger_recognition_event* halEvent) {
+    if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+        ISoundTriggerHwCallback::PhraseRecognitionEvent event;
+        convertPhaseRecognitionEventFromHal(
+            &event, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
+        event.common.model = mId;
+        mCallback->phraseRecognitionCallback(event, mCookie);
+    } else {
+        ISoundTriggerHwCallback::RecognitionEvent event;
+        convertRecognitionEventFromHal(&event, halEvent);
+        event.model = mId;
+        mCallback->recognitionCallback(event, mCookie);
+    }
 }
-} // namespace implementation
+
+void SoundTriggerHalImpl::SoundModelClient_2_0::soundModelCallback(
+    struct sound_trigger_model_event* halEvent) {
+    ISoundTriggerHwCallback::ModelEvent event;
+    convertSoundModelEventFromHal(&event, halEvent);
+    event.model = mId;
+    mCallback->soundModelCallback(event, mCookie);
+}
+
+}  // namespace implementation
 }  // namespace V2_0
 }  // namespace soundtrigger
 }  // namespace hardware
 }  // namespace android
-
-
-
diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.h b/soundtrigger/2.0/default/SoundTriggerHalImpl.h
index 4769590..5a9f0e1 100644
--- a/soundtrigger/2.0/default/SoundTriggerHalImpl.h
+++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.h
@@ -19,12 +19,12 @@
 
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
+#include <hardware/sound_trigger.h>
 #include <hidl/Status.h>
 #include <stdatomic.h>
-#include <utils/threads.h>
-#include <utils/KeyedVector.h>
 #include <system/sound_trigger.h>
-#include <hardware/sound_trigger.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
 
 namespace android {
 namespace hardware {
@@ -35,96 +35,144 @@
 using ::android::hardware::audio::common::V2_0::Uuid;
 using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
 
+class SoundTriggerHalImpl : public RefBase {
+   public:
+    SoundTriggerHalImpl();
+    ISoundTriggerHw* getInterface() { return new TrampolineSoundTriggerHw_2_0(this); }
 
-class SoundTriggerHalImpl : public ISoundTriggerHw {
-public:
-        SoundTriggerHalImpl();
+   protected:
+    class SoundModelClient : public RefBase {
+       public:
+        SoundModelClient(uint32_t id, ISoundTriggerHwCallback::CallbackCookie cookie)
+            : mId(id), mCookie(cookie) {}
+        virtual ~SoundModelClient() {}
+
+        uint32_t getId() const { return mId; }
+        sound_model_handle_t getHalHandle() const { return mHalHandle; }
+        void setHalHandle(sound_model_handle_t handle) { mHalHandle = handle; }
+
+        virtual void recognitionCallback(struct sound_trigger_recognition_event* halEvent) = 0;
+        virtual void soundModelCallback(struct sound_trigger_model_event* halEvent) = 0;
+
+       protected:
+        const uint32_t mId;
+        sound_model_handle_t mHalHandle;
+        ISoundTriggerHwCallback::CallbackCookie mCookie;
+    };
+
+    static void convertPhaseRecognitionEventFromHal(
+        ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
+        const struct sound_trigger_phrase_recognition_event* halEvent);
+    static void convertRecognitionEventFromHal(
+        ISoundTriggerHwCallback::RecognitionEvent* event,
+        const struct sound_trigger_recognition_event* halEvent);
+    static void convertSoundModelEventFromHal(ISoundTriggerHwCallback::ModelEvent* event,
+                                              const struct sound_trigger_model_event* halEvent);
+
+    virtual ~SoundTriggerHalImpl();
+
+    Return<void> getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb);
+    Return<void> loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
+                                const sp<ISoundTriggerHwCallback>& callback,
+                                ISoundTriggerHwCallback::CallbackCookie cookie,
+                                ISoundTriggerHw::loadSoundModel_cb _hidl_cb);
+    Return<void> loadPhraseSoundModel(const ISoundTriggerHw::PhraseSoundModel& soundModel,
+                                      const sp<ISoundTriggerHwCallback>& callback,
+                                      ISoundTriggerHwCallback::CallbackCookie cookie,
+                                      ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb);
+    Return<int32_t> unloadSoundModel(SoundModelHandle modelHandle);
+    Return<int32_t> startRecognition(SoundModelHandle modelHandle,
+                                     const ISoundTriggerHw::RecognitionConfig& config);
+    Return<int32_t> stopRecognition(SoundModelHandle modelHandle);
+    Return<int32_t> stopAllRecognitions();
+
+    uint32_t nextUniqueModelId();
+    int doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
+                         sp<SoundModelClient> client);
+
+    // RefBase
+    void onFirstRef() override;
+
+   private:
+    struct TrampolineSoundTriggerHw_2_0 : public ISoundTriggerHw {
+        explicit TrampolineSoundTriggerHw_2_0(sp<SoundTriggerHalImpl> impl) : mImpl(impl) {}
 
         // Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow.
-        Return<void> getProperties(getProperties_cb _hidl_cb)  override;
+        Return<void> getProperties(getProperties_cb _hidl_cb) override {
+            return mImpl->getProperties(_hidl_cb);
+        }
         Return<void> loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
                                     const sp<ISoundTriggerHwCallback>& callback,
                                     ISoundTriggerHwCallback::CallbackCookie cookie,
-                                    loadSoundModel_cb _hidl_cb)  override;
+                                    loadSoundModel_cb _hidl_cb) override {
+            return mImpl->loadSoundModel(soundModel, callback, cookie, _hidl_cb);
+        }
         Return<void> loadPhraseSoundModel(const ISoundTriggerHw::PhraseSoundModel& soundModel,
-                                    const sp<ISoundTriggerHwCallback>& callback,
-                                    ISoundTriggerHwCallback::CallbackCookie cookie,
-                                    loadPhraseSoundModel_cb _hidl_cb)  override;
+                                          const sp<ISoundTriggerHwCallback>& callback,
+                                          ISoundTriggerHwCallback::CallbackCookie cookie,
+                                          loadPhraseSoundModel_cb _hidl_cb) override {
+            return mImpl->loadPhraseSoundModel(soundModel, callback, cookie, _hidl_cb);
+        }
+        Return<int32_t> unloadSoundModel(SoundModelHandle modelHandle) override {
+            return mImpl->unloadSoundModel(modelHandle);
+        }
+        Return<int32_t> startRecognition(
+            SoundModelHandle modelHandle, const ISoundTriggerHw::RecognitionConfig& config,
+            const sp<ISoundTriggerHwCallback>& /*callback*/,
+            ISoundTriggerHwCallback::CallbackCookie /*cookie*/) override {
+            return mImpl->startRecognition(modelHandle, config);
+        }
+        Return<int32_t> stopRecognition(SoundModelHandle modelHandle) override {
+            return mImpl->stopRecognition(modelHandle);
+        }
+        Return<int32_t> stopAllRecognitions() override { return mImpl->stopAllRecognitions(); }
 
-        Return<int32_t> unloadSoundModel(SoundModelHandle modelHandle)  override;
-        Return<int32_t> startRecognition(SoundModelHandle modelHandle,
-                                      const ISoundTriggerHw::RecognitionConfig& config,
-                                      const sp<ISoundTriggerHwCallback>& callback,
-                                      ISoundTriggerHwCallback::CallbackCookie cookie)  override;
-        Return<int32_t> stopRecognition(SoundModelHandle modelHandle)  override;
-        Return<int32_t> stopAllRecognitions()  override;
+       private:
+        sp<SoundTriggerHalImpl> mImpl;
+    };
 
-        // RefBase
-        virtual     void        onFirstRef();
+    class SoundModelClient_2_0 : public SoundModelClient {
+       public:
+        SoundModelClient_2_0(uint32_t id, ISoundTriggerHwCallback::CallbackCookie cookie,
+                             sp<ISoundTriggerHwCallback> callback)
+            : SoundModelClient(id, cookie), mCallback(callback) {}
 
-        static void soundModelCallback(struct sound_trigger_model_event *halEvent,
-                                       void *cookie);
-        static void recognitionCallback(struct sound_trigger_recognition_event *halEvent,
-                                        void *cookie);
+        void recognitionCallback(struct sound_trigger_recognition_event* halEvent) override;
+        void soundModelCallback(struct sound_trigger_model_event* halEvent) override;
 
-private:
+       private:
+        sp<ISoundTriggerHwCallback> mCallback;
+    };
 
-        class SoundModelClient : public RefBase {
-        public:
-            SoundModelClient(uint32_t id, sp<ISoundTriggerHwCallback> callback,
-                             ISoundTriggerHwCallback::CallbackCookie cookie)
-                : mId(id), mCallback(callback), mCookie(cookie) {}
-            virtual ~SoundModelClient() {}
+    void convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid);
+    void convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid);
+    void convertPropertiesFromHal(ISoundTriggerHw::Properties* properties,
+                                  const struct sound_trigger_properties* halProperties);
+    void convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
+                                   const ISoundTriggerHw::Phrase* triggerPhrase);
+    // returned HAL sound model must be freed by caller
+    struct sound_trigger_sound_model* convertSoundModelToHal(
+        const ISoundTriggerHw::SoundModel* soundModel);
+    void convertPhraseRecognitionExtraToHal(struct sound_trigger_phrase_recognition_extra* halExtra,
+                                            const PhraseRecognitionExtra* extra);
+    // returned recognition config must be freed by caller
+    struct sound_trigger_recognition_config* convertRecognitionConfigToHal(
+        const ISoundTriggerHw::RecognitionConfig* config);
 
-            uint32_t mId;
-            sound_model_handle_t mHalHandle;
-            sp<ISoundTriggerHwCallback> mCallback;
-            ISoundTriggerHwCallback::CallbackCookie mCookie;
-        };
+    static void convertPhraseRecognitionExtraFromHal(
+        PhraseRecognitionExtra* extra,
+        const struct sound_trigger_phrase_recognition_extra* halExtra);
 
-        uint32_t nextUniqueId();
-        void convertUuidFromHal(Uuid *uuid,
-                                const sound_trigger_uuid_t *halUuid);
-        void convertUuidToHal(sound_trigger_uuid_t *halUuid,
-                              const Uuid *uuid);
-        void convertPropertiesFromHal(ISoundTriggerHw::Properties *properties,
-                                      const struct sound_trigger_properties *halProperties);
-        void convertTriggerPhraseToHal(struct sound_trigger_phrase *halTriggerPhrase,
-                                       const ISoundTriggerHw::Phrase *triggerPhrase);
-        // returned HAL sound model must be freed by caller
-        struct sound_trigger_sound_model *convertSoundModelToHal(
-                    const ISoundTriggerHw::SoundModel *soundModel);
-        void convertPhraseRecognitionExtraToHal(
-                struct sound_trigger_phrase_recognition_extra *halExtra,
-                const PhraseRecognitionExtra *extra);
-        // returned recognition config must be freed by caller
-        struct sound_trigger_recognition_config *convertRecognitionConfigToHal(
-                const ISoundTriggerHw::RecognitionConfig *config);
+    static void soundModelCallback(struct sound_trigger_model_event* halEvent, void* cookie);
+    static void recognitionCallback(struct sound_trigger_recognition_event* halEvent, void* cookie);
 
-
-        static void convertSoundModelEventFromHal(ISoundTriggerHwCallback::ModelEvent *event,
-                                            const struct sound_trigger_model_event *halEvent);
-        static ISoundTriggerHwCallback::RecognitionEvent *convertRecognitionEventFromHal(
-                                            const struct sound_trigger_recognition_event *halEvent);
-        static void convertPhraseRecognitionExtraFromHal(PhraseRecognitionExtra *extra,
-                                    const struct sound_trigger_phrase_recognition_extra *halExtra);
-
-        int doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
-                             const sp<ISoundTriggerHwCallback>& callback,
-                             ISoundTriggerHwCallback::CallbackCookie cookie,
-                             uint32_t *modelId);
-
-        virtual             ~SoundTriggerHalImpl();
-
-        const char *                                        mModuleName;
-        struct sound_trigger_hw_device*                     mHwDevice;
-        volatile atomic_uint_fast32_t                       mNextModelId;
-        DefaultKeyedVector<int32_t, sp<SoundModelClient> >  mClients;
-        Mutex                                               mLock;
+    const char* mModuleName;
+    struct sound_trigger_hw_device* mHwDevice;
+    volatile atomic_uint_fast32_t mNextModelId;
+    DefaultKeyedVector<int32_t, sp<SoundModelClient> > mClients;
+    Mutex mLock;
 };
 
-extern "C" ISoundTriggerHw *HIDL_FETCH_ISoundTriggerHw(const char *name);
-
 }  // namespace implementation
 }  // namespace V2_0
 }  // namespace soundtrigger
@@ -132,4 +180,3 @@
 }  // namespace android
 
 #endif  // ANDROID_HARDWARE_SOUNDTRIGGER_V2_0_IMPLEMENTATION_H
-
diff --git a/soundtrigger/2.1/Android.bp b/soundtrigger/2.1/Android.bp
new file mode 100644
index 0000000..ed1ec3d
--- /dev/null
+++ b/soundtrigger/2.1/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.soundtrigger@2.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "ISoundTriggerHw.hal",
+        "ISoundTriggerHwCallback.hal",
+    ],
+    interfaces: [
+        "android.hardware.audio.common@2.0",
+        "android.hardware.soundtrigger@2.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: false,
+}
+
diff --git a/soundtrigger/2.1/ISoundTriggerHw.hal b/soundtrigger/2.1/ISoundTriggerHw.hal
new file mode 100644
index 0000000..a9796d8
--- /dev/null
+++ b/soundtrigger/2.1/ISoundTriggerHw.hal
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2017 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.soundtrigger@2.1;
+
+import @2.0::ISoundTriggerHw;
+import @2.0::ISoundTriggerHwCallback.CallbackCookie;
+import @2.0::SoundModelHandle;
+
+import ISoundTriggerHwCallback;
+
+/**
+ * SoundTrigger HAL interface. Used for hardware recognition of hotwords.
+ */
+interface ISoundTriggerHw extends @2.0::ISoundTriggerHw {
+
+    /**
+     * Base sound model descriptor. This struct is the header of a larger block
+     * passed to loadSoundModel_2_1() and contains the binary data of the
+     * sound model.
+     */
+    struct SoundModel {
+        /** Sound model header. Any data contained in the 'header.data' field
+         * is ignored */
+        @2.0::ISoundTriggerHw.SoundModel header;
+        /** Opaque data transparent to Android framework */
+        memory data;
+    };
+
+    /**
+     * Specialized sound model for key phrase detection.
+     * Proprietary representation of key phrases in binary data must match
+     * information indicated by phrases field.
+     */
+    struct PhraseSoundModel {
+        /** Common part of sound model descriptor */
+        SoundModel  common;
+        /** List of descriptors for key phrases supported by this sound model */
+        vec<Phrase> phrases;
+    };
+
+    /**
+     * Configuration for sound trigger capture session passed to
+     * startRecognition_2_1() method.
+     */
+    struct RecognitionConfig {
+        /** Configuration header. Any data contained in the 'header.data' field
+         * is ignored */
+        @2.0::ISoundTriggerHw.RecognitionConfig header;
+        /** Opaque capture configuration data transparent to the framework */
+        memory data;
+    };
+
+    /**
+     * Load a sound model. Once loaded, recognition of this model can be
+     * started and stopped. Only one active recognition per model at a time.
+     * The SoundTrigger service must handle concurrent recognition requests by
+     * different users/applications on the same model.
+     * The implementation returns a unique handle used by other functions
+     * (unloadSoundModel(), startRecognition*(), etc...
+     *
+     * Must have the exact same semantics as loadSoundModel from
+     * ISoundTriggerHw@2.0 except that the SoundModel uses shared memory
+     * instead of data.
+     *
+     * @param soundModel A SoundModel structure describing the sound model
+     *     to load.
+     * @param callback The callback interface on which the soundmodelCallback*()
+     *     method must be called upon completion.
+     * @param cookie The value of the cookie argument passed to the completion
+     *     callback. This unique context information is assigned and
+     *     used only by the framework.
+     * @return retval Operation completion status: 0 in case of success,
+     *     -EINVAL in case of invalid sound model (e.g 0 data size),
+     *     -ENOSYS in case of invalid operation (e.g max number of models
+     *             exceeded),
+     *     -ENOMEM in case of memory allocation failure,
+     *     -ENODEV in case of initialization error.
+     * @return modelHandle A unique handle assigned by the HAL for use by the
+     *     framework when controlling activity for this sound model.
+     */
+    @callflow(next={"startRecognition_2_1", "unloadSoundModel"})
+    loadSoundModel_2_1(SoundModel soundModel,
+                   ISoundTriggerHwCallback callback,
+                   CallbackCookie cookie)
+            generates (int32_t retval, SoundModelHandle modelHandle);
+
+    /**
+     * Load a key phrase sound model. Once loaded, recognition of this model can
+     * be started and stopped. Only one active recognition per model at a time.
+     * The SoundTrigger service must handle concurrent recognition requests by
+     * different users/applications on the same model.
+     * The implementation returns a unique handle used by other functions
+     * (unloadSoundModel(), startRecognition*(), etc...
+     *
+     * Must have the exact same semantics as loadPhraseSoundModel from
+     * ISoundTriggerHw@2.0 except that the PhraseSoundModel uses shared memory
+     * instead of data.
+     *
+     * @param soundModel A PhraseSoundModel structure describing the sound model
+     *     to load.
+     * @param callback The callback interface on which the soundmodelCallback*()
+     *     method must be called upon completion.
+     * @param cookie The value of the cookie argument passed to the completion
+     *     callback. This unique context information is assigned and
+     *     used only by the framework.
+     * @return retval Operation completion status: 0 in case of success,
+     *     -EINVAL in case of invalid sound model (e.g 0 data size),
+     *     -ENOSYS in case of invalid operation (e.g max number of models
+     *             exceeded),
+     *     -ENOMEM in case of memory allocation failure,
+     *     -ENODEV in case of initialization error.
+     * @return modelHandle A unique handle assigned by the HAL for use by the
+     *     framework when controlling activity for this sound model.
+     */
+    @callflow(next={"startRecognition_2_1", "unloadSoundModel"})
+    loadPhraseSoundModel_2_1(PhraseSoundModel soundModel,
+                   ISoundTriggerHwCallback callback,
+                   CallbackCookie cookie)
+            generates (int32_t retval, SoundModelHandle modelHandle);
+
+    /**
+     * Start recognition on a given model. Only one recognition active
+     * at a time per model. Once recognition succeeds of fails, the callback
+     * is called.
+     *
+     * Must have the exact same semantics as startRecognition from
+     * ISoundTriggerHw@2.0 except that the RecognitionConfig uses shared memory
+     * instead of data.
+     *
+     * @param modelHandle the handle of the sound model to use for recognition
+     * @param config A RecognitionConfig structure containing attributes of the
+     *     recognition to perform
+     * @param callback The callback interface on which the recognitionCallback()
+     *     method must be called upon recognition.
+     * @param cookie The value of the cookie argument passed to the recognition
+     *     callback. This unique context information is assigned and
+     *     used only by the framework.
+     * @return retval Operation completion status: 0 in case of success,
+     *     -EINVAL in case of invalid recognition attributes,
+     *     -ENOSYS in case of invalid model handle,
+     *     -ENOMEM in case of memory allocation failure,
+     *     -ENODEV in case of initialization error.
+     */
+    @callflow(next={"stopRecognition", "stopAllRecognitions"})
+    startRecognition_2_1(SoundModelHandle modelHandle,
+                     RecognitionConfig config,
+                     ISoundTriggerHwCallback callback,
+                     CallbackCookie cookie)
+            generates (int32_t retval);
+};
diff --git a/soundtrigger/2.1/ISoundTriggerHwCallback.hal b/soundtrigger/2.1/ISoundTriggerHwCallback.hal
new file mode 100644
index 0000000..42e851b
--- /dev/null
+++ b/soundtrigger/2.1/ISoundTriggerHwCallback.hal
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2017 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.soundtrigger@2.1;
+
+import @2.0::ISoundTriggerHwCallback;
+import @2.0::PhraseRecognitionExtra;
+
+/**
+ * SoundTrigger HAL Callback interface. Obtained during SoundTrigger setup.
+ */
+@hidl_callback
+interface ISoundTriggerHwCallback extends @2.0::ISoundTriggerHwCallback {
+
+    /**
+     * Generic recognition event sent via recognition callback.
+     */
+    struct RecognitionEvent {
+        /** Event header. Any data contained in the 'header.data' field
+         * is ignored */
+        @2.0::ISoundTriggerHwCallback.RecognitionEvent header;
+        /** Opaque event data */
+        memory data;
+    };
+
+    /**
+     * Specialized recognition event for key phrase recognitions.
+     */
+    struct PhraseRecognitionEvent {
+        /** Common part of the recognition event */
+        RecognitionEvent common;
+        /** List of descriptors for each recognized key phrase */
+        vec<PhraseRecognitionExtra> phraseExtras;
+    };
+
+    /**
+     * Event sent via load sound model callback.
+     */
+    struct ModelEvent {
+        /** Event header. Any data contained in the 'header.data' field
+         * is ignored */
+        @2.0::ISoundTriggerHwCallback.ModelEvent header;
+        /** Opaque event data, passed transparently by the framework */
+        memory data;
+    };
+
+    /**
+     * Callback method called by the HAL when the sound recognition triggers.
+     *
+     * @param event A RecognitionEvent structure containing detailed results
+     *     of the recognition triggered
+     * @param cookie The cookie passed by the framework when recognition was
+     *     started (see ISoundtriggerHw.startRecognition*())
+     */
+    recognitionCallback_2_1(RecognitionEvent event, CallbackCookie cookie);
+
+    /**
+     * Callback method called by the HAL when the sound recognition triggers
+     * for a key phrase sound model.
+     *
+     * @param event A RecognitionEvent structure containing detailed results
+     *     of the recognition triggered
+     * @param cookie The cookie passed by the framework when recognition was
+     *     started (see ISoundtriggerHw.startRecognition*())
+     */
+    phraseRecognitionCallback_2_1(PhraseRecognitionEvent event,
+                                  CallbackCookie cookie);
+
+    /**
+     * Callback method called by the HAL when the sound model loading completes.
+     *
+     * @param event A ModelEvent structure containing detailed results of the
+     *     model loading operation
+     * @param cookie The cookie passed by the framework when loading was
+     *     initiated (see ISoundtriggerHw.loadSoundModel*())
+     */
+    soundModelCallback_2_1(ModelEvent event, CallbackCookie cookie);
+};
diff --git a/soundtrigger/2.1/default/Android.mk b/soundtrigger/2.1/default/Android.mk
new file mode 100644
index 0000000..5851d63
--- /dev/null
+++ b/soundtrigger/2.1/default/Android.mk
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2018 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.soundtrigger@2.1-impl
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    SoundTriggerHw.cpp
+
+LOCAL_CFLAGS := -Wall -Werror
+
+LOCAL_SHARED_LIBRARIES := \
+        libhardware \
+        libhidlbase \
+        libhidlmemory \
+        libhidltransport \
+        liblog \
+        libutils \
+        android.hardware.soundtrigger@2.1 \
+        android.hardware.soundtrigger@2.0 \
+        android.hardware.soundtrigger@2.0-core \
+        android.hidl.allocator@1.0 \
+        android.hidl.memory@1.0
+
+LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH)
+
+ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
+LOCAL_MULTILIB := 32
+else
+LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/soundtrigger/2.1/default/SoundTriggerHw.cpp b/soundtrigger/2.1/default/SoundTriggerHw.cpp
new file mode 100644
index 0000000..246d2bc
--- /dev/null
+++ b/soundtrigger/2.1/default/SoundTriggerHw.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2018 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 "SoundTriggerHw"
+
+#include "SoundTriggerHw.h"
+
+#include <utility>
+
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/log.h>
+#include <hidlmemory/mapping.h>
+
+using android::hardware::hidl_memory;
+using android::hidl::allocator::V1_0::IAllocator;
+using android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+namespace hardware {
+namespace soundtrigger {
+namespace V2_1 {
+namespace implementation {
+
+namespace {
+
+// Backs up by the vector with the contents of shared memory.
+// It is assumed that the passed hidl_vector is empty, so it's
+// not cleared if the memory is a null object.
+// The caller needs to keep the returned sp<IMemory> as long as
+// the data is needed.
+std::pair<bool, sp<IMemory>> memoryAsVector(const hidl_memory& m, hidl_vec<uint8_t>* vec) {
+    sp<IMemory> memory;
+    if (m.size() == 0) {
+        return std::make_pair(true, memory);
+    }
+    memory = mapMemory(m);
+    if (memory != nullptr) {
+        memory->read();
+        vec->setToExternal(static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())),
+                           memory->getSize());
+        return std::make_pair(true, memory);
+    }
+    ALOGE("%s: Could not map HIDL memory to IMemory", __func__);
+    return std::make_pair(false, memory);
+}
+
+// Moves the data from the vector into allocated shared memory,
+// emptying the vector.
+// It is assumed that the passed hidl_memory is a null object, so it's
+// not reset if the vector is empty.
+// The caller needs to keep the returned sp<IMemory> as long as
+// the data is needed.
+std::pair<bool, sp<IMemory>> moveVectorToMemory(hidl_vec<uint8_t>* v, hidl_memory* mem) {
+    sp<IMemory> memory;
+    if (v->size() == 0) {
+        return std::make_pair(true, memory);
+    }
+    sp<IAllocator> ashmem = IAllocator::getService("ashmem");
+    if (ashmem == 0) {
+        ALOGE("Failed to retrieve ashmem allocator service");
+        return std::make_pair(false, memory);
+    }
+    bool success = false;
+    Return<void> r = ashmem->allocate(v->size(), [&](bool s, const hidl_memory& m) {
+        success = s;
+        if (success) *mem = m;
+    });
+    if (r.isOk() && success) {
+        memory = hardware::mapMemory(*mem);
+        if (memory != 0) {
+            memory->update();
+            memcpy(memory->getPointer(), v->data(), v->size());
+            memory->commit();
+            v->resize(0);
+            return std::make_pair(true, memory);
+        } else {
+            ALOGE("Failed to map allocated ashmem");
+        }
+    } else {
+        ALOGE("Failed to allocate %llu bytes from ashmem", (unsigned long long)v->size());
+    }
+    return std::make_pair(false, memory);
+}
+
+}  // namespace
+
+Return<void> SoundTriggerHw::loadSoundModel_2_1(
+    const V2_1::ISoundTriggerHw::SoundModel& soundModel,
+    const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
+    V2_1::ISoundTriggerHw::loadSoundModel_2_1_cb _hidl_cb) {
+    // It is assumed that legacy data vector is empty, thus making copy is cheap.
+    V2_0::ISoundTriggerHw::SoundModel soundModel_2_0(soundModel.header);
+    auto result = memoryAsVector(soundModel.data, &soundModel_2_0.data);
+    if (result.first) {
+        sp<SoundModelClient> client =
+            new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
+        _hidl_cb(doLoadSoundModel(soundModel_2_0, client), client->getId());
+        return Void();
+    }
+    _hidl_cb(-ENOMEM, 0);
+    return Void();
+}
+
+Return<void> SoundTriggerHw::loadPhraseSoundModel_2_1(
+    const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
+    const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
+    V2_1::ISoundTriggerHw::loadPhraseSoundModel_2_1_cb _hidl_cb) {
+    V2_0::ISoundTriggerHw::PhraseSoundModel soundModel_2_0;
+    // It is assumed that legacy data vector is empty, thus making copy is cheap.
+    soundModel_2_0.common = soundModel.common.header;
+    // Avoid copying phrases data.
+    soundModel_2_0.phrases.setToExternal(
+        const_cast<V2_0::ISoundTriggerHw::Phrase*>(soundModel.phrases.data()),
+        soundModel.phrases.size());
+    auto result = memoryAsVector(soundModel.common.data, &soundModel_2_0.common.data);
+    if (result.first) {
+        sp<SoundModelClient> client =
+            new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
+        _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel_2_0, client),
+                 client->getId());
+        return Void();
+    }
+    _hidl_cb(-ENOMEM, 0);
+    return Void();
+}
+
+Return<int32_t> SoundTriggerHw::startRecognition_2_1(
+    int32_t modelHandle, const V2_1::ISoundTriggerHw::RecognitionConfig& config) {
+    // It is assumed that legacy data vector is empty, thus making copy is cheap.
+    V2_0::ISoundTriggerHw::RecognitionConfig config_2_0(config.header);
+    auto result = memoryAsVector(config.data, &config_2_0.data);
+    return result.first ? startRecognition(modelHandle, config_2_0) : Return<int32_t>(-ENOMEM);
+}
+
+void SoundTriggerHw::SoundModelClient_2_1::recognitionCallback(
+    struct sound_trigger_recognition_event* halEvent) {
+    if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+        V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0;
+        convertPhaseRecognitionEventFromHal(
+            &event_2_0, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
+        event_2_0.common.model = mId;
+        V2_1::ISoundTriggerHwCallback::PhraseRecognitionEvent event;
+        event.phraseExtras.setToExternal(event_2_0.phraseExtras.data(),
+                                         event_2_0.phraseExtras.size());
+        auto result = moveVectorToMemory(&event_2_0.common.data, &event.common.data);
+        if (result.first) {
+            // The data vector is now empty, thus copying is cheap.
+            event.common.header = event_2_0.common;
+            mCallback->phraseRecognitionCallback_2_1(event, mCookie);
+        }
+    } else {
+        V2_1::ISoundTriggerHwCallback::RecognitionEvent event;
+        convertRecognitionEventFromHal(&event.header, halEvent);
+        event.header.model = mId;
+        auto result = moveVectorToMemory(&event.header.data, &event.data);
+        if (result.first) {
+            mCallback->recognitionCallback_2_1(event, mCookie);
+        }
+    }
+}
+
+void SoundTriggerHw::SoundModelClient_2_1::soundModelCallback(
+    struct sound_trigger_model_event* halEvent) {
+    V2_1::ISoundTriggerHwCallback::ModelEvent event;
+    convertSoundModelEventFromHal(&event.header, halEvent);
+    event.header.model = mId;
+    auto result = moveVectorToMemory(&event.header.data, &event.data);
+    if (result.first) {
+        mCallback->soundModelCallback_2_1(event, mCookie);
+    }
+}
+
+ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) {
+    return (new SoundTriggerHw())->getInterface();
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace soundtrigger
+}  // namespace hardware
+}  // namespace android
diff --git a/soundtrigger/2.1/default/SoundTriggerHw.h b/soundtrigger/2.1/default/SoundTriggerHw.h
new file mode 100644
index 0000000..a5515eb
--- /dev/null
+++ b/soundtrigger/2.1/default/SoundTriggerHw.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2018 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_SOUNDTRIGGER_V2_1_SOUNDTRIGGERHW_H
+#define ANDROID_HARDWARE_SOUNDTRIGGER_V2_1_SOUNDTRIGGERHW_H
+
+#include <SoundTriggerHalImpl.h>
+#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace soundtrigger {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct SoundTriggerHw : public V2_0::implementation::SoundTriggerHalImpl {
+    SoundTriggerHw() = default;
+    ISoundTriggerHw* getInterface() { return new TrampolineSoundTriggerHw_2_1(this); }
+
+   protected:
+    virtual ~SoundTriggerHw() = default;
+
+    Return<void> loadSoundModel_2_1(const V2_1::ISoundTriggerHw::SoundModel& soundModel,
+                                    const sp<V2_1::ISoundTriggerHwCallback>& callback,
+                                    int32_t cookie,
+                                    V2_1::ISoundTriggerHw::loadSoundModel_2_1_cb _hidl_cb);
+    Return<void> loadPhraseSoundModel_2_1(
+        const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
+        const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
+        V2_1::ISoundTriggerHw::loadPhraseSoundModel_2_1_cb _hidl_cb);
+    Return<int32_t> startRecognition_2_1(int32_t modelHandle,
+                                         const V2_1::ISoundTriggerHw::RecognitionConfig& config);
+
+   private:
+    struct TrampolineSoundTriggerHw_2_1 : public ISoundTriggerHw {
+        explicit TrampolineSoundTriggerHw_2_1(sp<SoundTriggerHw> impl) : mImpl(impl) {}
+
+        // Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow.
+        Return<void> getProperties(getProperties_cb _hidl_cb) override {
+            return mImpl->getProperties(_hidl_cb);
+        }
+        Return<void> loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
+                                    const sp<V2_0::ISoundTriggerHwCallback>& callback,
+                                    int32_t cookie, loadSoundModel_cb _hidl_cb) override {
+            return mImpl->loadSoundModel(soundModel, callback, cookie, _hidl_cb);
+        }
+        Return<void> loadPhraseSoundModel(const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel,
+                                          const sp<V2_0::ISoundTriggerHwCallback>& callback,
+                                          int32_t cookie,
+                                          loadPhraseSoundModel_cb _hidl_cb) override {
+            return mImpl->loadPhraseSoundModel(soundModel, callback, cookie, _hidl_cb);
+        }
+        Return<int32_t> unloadSoundModel(V2_0::SoundModelHandle modelHandle) override {
+            return mImpl->unloadSoundModel(modelHandle);
+        }
+        Return<int32_t> startRecognition(int32_t modelHandle,
+                                         const V2_0::ISoundTriggerHw::RecognitionConfig& config,
+                                         const sp<V2_0::ISoundTriggerHwCallback>& /*callback*/,
+                                         int32_t /*cookie*/) override {
+            return mImpl->startRecognition(modelHandle, config);
+        }
+        Return<int32_t> stopRecognition(V2_0::SoundModelHandle modelHandle) override {
+            return mImpl->stopRecognition(modelHandle);
+        }
+        Return<int32_t> stopAllRecognitions() override { return mImpl->stopAllRecognitions(); }
+
+        // Methods from V2_1::ISoundTriggerHw follow.
+        Return<void> loadSoundModel_2_1(const V2_1::ISoundTriggerHw::SoundModel& soundModel,
+                                        const sp<V2_1::ISoundTriggerHwCallback>& callback,
+                                        int32_t cookie, loadSoundModel_2_1_cb _hidl_cb) override {
+            return mImpl->loadSoundModel_2_1(soundModel, callback, cookie, _hidl_cb);
+        }
+        Return<void> loadPhraseSoundModel_2_1(
+            const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
+            const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
+            loadPhraseSoundModel_2_1_cb _hidl_cb) override {
+            return mImpl->loadPhraseSoundModel_2_1(soundModel, callback, cookie, _hidl_cb);
+        }
+        Return<int32_t> startRecognition_2_1(int32_t modelHandle,
+                                             const V2_1::ISoundTriggerHw::RecognitionConfig& config,
+                                             const sp<V2_1::ISoundTriggerHwCallback>& /*callback*/,
+                                             int32_t /*cookie*/) override {
+            return mImpl->startRecognition_2_1(modelHandle, config);
+        }
+
+       private:
+        sp<SoundTriggerHw> mImpl;
+    };
+
+    class SoundModelClient_2_1 : public SoundModelClient {
+       public:
+        SoundModelClient_2_1(uint32_t id, V2_1::ISoundTriggerHwCallback::CallbackCookie cookie,
+                             sp<V2_1::ISoundTriggerHwCallback> callback)
+            : SoundModelClient(id, cookie), mCallback(callback) {}
+
+        void recognitionCallback(struct sound_trigger_recognition_event* halEvent) override;
+        void soundModelCallback(struct sound_trigger_model_event* halEvent) override;
+
+       private:
+        sp<V2_1::ISoundTriggerHwCallback> mCallback;
+    };
+};
+
+extern "C" ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* name);
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace soundtrigger
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_SOUNDTRIGGER_V2_1_SOUNDTRIGGERHW_H
diff --git a/soundtrigger/2.1/vts/functional/Android.bp b/soundtrigger/2.1/vts/functional/Android.bp
new file mode 100644
index 0000000..925a17c
--- /dev/null
+++ b/soundtrigger/2.1/vts/functional/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2018 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: "VtsHalSoundtriggerV2_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalSoundtriggerV2_1TargetTest.cpp"],
+    static_libs: [
+                 "android.hidl.allocator@1.0",
+                 "android.hidl.memory@1.0",
+                 "android.hardware.soundtrigger@2.0",
+                 "android.hardware.soundtrigger@2.1",
+                 "libhidlmemory"
+                 ],
+}
diff --git a/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp b/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp
new file mode 100644
index 0000000..fdd5f0d
--- /dev/null
+++ b/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2018 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 "SoundTriggerHidlHalTest"
+#include <stdlib.h>
+#include <time.h>
+
+#include <condition_variable>
+#include <mutex>
+
+#include <android/log.h>
+#include <cutils/native_handle.h>
+#include <log/log.h>
+
+#include <android/hardware/audio/common/2.0/types.h>
+#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.0/types.h>
+#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <hidlmemory/mapping.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#define SHORT_TIMEOUT_PERIOD (1)
+
+using ::android::sp;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::soundtrigger::V2_0::PhraseRecognitionExtra;
+using ::android::hardware::soundtrigger::V2_0::RecognitionMode;
+using ::android::hardware::soundtrigger::V2_0::SoundModelHandle;
+using ::android::hardware::soundtrigger::V2_0::SoundModelType;
+using V2_0_ISoundTriggerHw = ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
+using V2_0_ISoundTriggerHwCallback =
+    ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
+using ::android::hardware::soundtrigger::V2_1::ISoundTriggerHw;
+using ::android::hardware::soundtrigger::V2_1::ISoundTriggerHwCallback;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+
+/**
+ * Test code uses this class to wait for notification from callback.
+ */
+class Monitor {
+   public:
+    Monitor() : mCount(0) {}
+
+    /**
+     * Adds 1 to the internal counter and unblocks one of the waiting threads.
+     */
+    void notify() {
+        std::unique_lock<std::mutex> lock(mMtx);
+        mCount++;
+        mCv.notify_one();
+    }
+
+    /**
+     * Blocks until the internal counter becomes greater than 0.
+     *
+     * If notified, this method decreases the counter by 1 and returns true.
+     * If timeout, returns false.
+     */
+    bool wait(int timeoutSeconds) {
+        auto deadline = std::chrono::system_clock::now() + std::chrono::seconds(timeoutSeconds);
+        std::unique_lock<std::mutex> lock(mMtx);
+        if (!mCv.wait_until(lock, deadline, [& count = mCount] { return count > 0; })) {
+            return false;
+        }
+        mCount--;
+        return true;
+    }
+
+   private:
+    std::mutex mMtx;
+    std::condition_variable mCv;
+    int mCount;
+};
+
+// The main test class for Sound Trigger HIDL HAL.
+class SoundTriggerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        mSoundTriggerHal = ::testing::VtsHalHidlTargetTestBase::getService<ISoundTriggerHw>();
+        ASSERT_NE(nullptr, mSoundTriggerHal.get());
+        mCallback = new SoundTriggerHwCallback(*this);
+        ASSERT_NE(nullptr, mCallback.get());
+    }
+
+    static void SetUpTestCase() { srand(1234); }
+
+    class SoundTriggerHwCallback : public ISoundTriggerHwCallback {
+       private:
+        SoundTriggerHidlTest& mParent;
+
+       public:
+        SoundTriggerHwCallback(SoundTriggerHidlTest& parent) : mParent(parent) {}
+
+        Return<void> recognitionCallback(const V2_0_ISoundTriggerHwCallback::RecognitionEvent& event
+                                             __unused,
+                                         int32_t cookie __unused) override {
+            ALOGI("%s", __FUNCTION__);
+            return Void();
+        };
+
+        Return<void> phraseRecognitionCallback(
+            const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent& event __unused,
+            int32_t cookie __unused) override {
+            ALOGI("%s", __FUNCTION__);
+            return Void();
+        };
+
+        Return<void> soundModelCallback(const V2_0_ISoundTriggerHwCallback::ModelEvent& event,
+                                        int32_t cookie __unused) override {
+            ALOGI("%s", __FUNCTION__);
+            mParent.lastModelEvent_2_0 = event;
+            mParent.monitor.notify();
+            return Void();
+        }
+
+        Return<void> recognitionCallback_2_1(const ISoundTriggerHwCallback::RecognitionEvent& event
+                                                 __unused,
+                                             int32_t cookie __unused) override {
+            ALOGI("%s", __FUNCTION__);
+            return Void();
+        }
+
+        Return<void> phraseRecognitionCallback_2_1(
+            const ISoundTriggerHwCallback::PhraseRecognitionEvent& event __unused,
+            int32_t cookie __unused) override {
+            ALOGI("%s", __FUNCTION__);
+            return Void();
+        }
+
+        Return<void> soundModelCallback_2_1(const ISoundTriggerHwCallback::ModelEvent& event,
+                                            int32_t cookie __unused) {
+            ALOGI("%s", __FUNCTION__);
+            mParent.lastModelEvent = event;
+            mParent.monitor.notify();
+            return Void();
+        }
+    };
+
+    virtual void TearDown() override {}
+
+    Monitor monitor;
+    // updated by soundModelCallback()
+    V2_0_ISoundTriggerHwCallback::ModelEvent lastModelEvent_2_0;
+    // updated by soundModelCallback_2_1()
+    ISoundTriggerHwCallback::ModelEvent lastModelEvent;
+
+   protected:
+    sp<ISoundTriggerHw> mSoundTriggerHal;
+    sp<SoundTriggerHwCallback> mCallback;
+};
+
+/**
+ * Test ISoundTriggerHw::getProperties() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the method returns 0 (no error)
+ *  - the implementation supports at least one sound model and one key phrase
+ *  - the implementation supports at least VOICE_TRIGGER recognition mode
+ */
+TEST_F(SoundTriggerHidlTest, GetProperties) {
+    ISoundTriggerHw::Properties halProperties;
+    Return<void> hidlReturn;
+    int ret = -ENODEV;
+
+    hidlReturn = mSoundTriggerHal->getProperties([&](int rc, auto res) {
+        ret = rc;
+        halProperties = res;
+    });
+
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_EQ(0, ret);
+    EXPECT_GT(halProperties.maxSoundModels, 0u);
+    EXPECT_GT(halProperties.maxKeyPhrases, 0u);
+    EXPECT_NE(0u, (halProperties.recognitionModes & (uint32_t)RecognitionMode::VOICE_TRIGGER));
+}
+
+/**
+ * Test ISoundTriggerHw::loadPhraseSoundModel() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the implementation returns an error when passed a malformed sound model
+ *
+ * There is no way to verify that implementation actually can load a sound model because each
+ * sound model is vendor specific.
+ */
+TEST_F(SoundTriggerHidlTest, LoadInvalidModelFail) {
+    Return<void> hidlReturn;
+    int ret = -ENODEV;
+    V2_0_ISoundTriggerHw::PhraseSoundModel model;
+    SoundModelHandle handle;
+
+    model.common.type = SoundModelType::UNKNOWN;
+
+    hidlReturn =
+        mSoundTriggerHal->loadPhraseSoundModel(model, mCallback, 0, [&](int32_t retval, auto res) {
+            ret = retval;
+            handle = res;
+        });
+
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_NE(0, ret);
+    EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::loadPhraseSoundModel_2_1() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the implementation returns an error when passed a malformed sound model
+ *
+ * There is no way to verify that implementation actually can load a sound model because each
+ * sound model is vendor specific.
+ */
+TEST_F(SoundTriggerHidlTest, LoadInvalidModelFail_2_1) {
+    Return<void> hidlReturn;
+    int ret = -ENODEV;
+    ISoundTriggerHw::PhraseSoundModel model;
+    SoundModelHandle handle;
+
+    model.common.header.type = SoundModelType::UNKNOWN;
+
+    hidlReturn = mSoundTriggerHal->loadPhraseSoundModel_2_1(model, mCallback, 0,
+                                                            [&](int32_t retval, auto res) {
+                                                                ret = retval;
+                                                                handle = res;
+                                                            });
+
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_NE(0, ret);
+    EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::loadSoundModel() method
+ *
+ * Verifies that:
+ *  - the implementation returns an error when passed an empty sound model
+ */
+TEST_F(SoundTriggerHidlTest, LoadEmptyGenericSoundModelFail) {
+    int ret = -ENODEV;
+    V2_0_ISoundTriggerHw::SoundModel model;
+    SoundModelHandle handle = 0;
+
+    model.type = SoundModelType::GENERIC;
+
+    Return<void> loadReturn =
+        mSoundTriggerHal->loadSoundModel(model, mCallback, 0, [&](int32_t retval, auto res) {
+            ret = retval;
+            handle = res;
+        });
+
+    EXPECT_TRUE(loadReturn.isOk());
+    EXPECT_NE(0, ret);
+    EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::loadSoundModel() method
+ *
+ * Verifies that:
+ *  - the implementation returns error when passed a sound model with random data.
+ */
+TEST_F(SoundTriggerHidlTest, LoadGenericSoundModelFail) {
+    int ret = -ENODEV;
+    V2_0_ISoundTriggerHw::SoundModel model;
+    SoundModelHandle handle = 0;
+
+    model.type = SoundModelType::GENERIC;
+    model.data.resize(100);
+    for (auto& d : model.data) {
+        d = rand();
+    }
+
+    Return<void> loadReturn =
+        mSoundTriggerHal->loadSoundModel(model, mCallback, 0, [&](int32_t retval, auto res) {
+            ret = retval;
+            handle = res;
+        });
+
+    EXPECT_TRUE(loadReturn.isOk());
+    EXPECT_NE(0, ret);
+    EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::loadSoundModel_2_1() method
+ *
+ * Verifies that:
+ *  - the implementation returns error when passed a sound model with random data.
+ */
+TEST_F(SoundTriggerHidlTest, LoadEmptyGenericSoundModelFail_2_1) {
+    int ret = -ENODEV;
+    ISoundTriggerHw::SoundModel model;
+    SoundModelHandle handle = 0;
+
+    model.header.type = SoundModelType::GENERIC;
+
+    Return<void> loadReturn =
+        mSoundTriggerHal->loadSoundModel_2_1(model, mCallback, 0, [&](int32_t retval, auto res) {
+            ret = retval;
+            handle = res;
+        });
+
+    EXPECT_TRUE(loadReturn.isOk());
+    EXPECT_NE(0, ret);
+    EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::loadSoundModel_2_1() method
+ *
+ * Verifies that:
+ *  - the implementation returns error when passed a sound model with random data.
+ */
+TEST_F(SoundTriggerHidlTest, LoadGenericSoundModelFail_2_1) {
+    int ret = -ENODEV;
+    ISoundTriggerHw::SoundModel model;
+    SoundModelHandle handle = 0;
+
+    model.header.type = SoundModelType::GENERIC;
+    sp<IAllocator> ashmem = IAllocator::getService("ashmem");
+    ASSERT_NE(nullptr, ashmem.get());
+    hidl_memory hmemory;
+    int size = 100;
+    Return<void> allocReturn = ashmem->allocate(size, [&](bool success, const hidl_memory& m) {
+        ASSERT_TRUE(success);
+        hmemory = m;
+    });
+    sp<IMemory> memory = ::android::hardware::mapMemory(hmemory);
+    ASSERT_NE(nullptr, memory.get());
+    memory->update();
+    for (uint8_t *p = static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())); size >= 0;
+         p++, size--) {
+        *p = rand();
+    }
+
+    Return<void> loadReturn =
+        mSoundTriggerHal->loadSoundModel_2_1(model, mCallback, 0, [&](int32_t retval, auto res) {
+            ret = retval;
+            handle = res;
+        });
+
+    EXPECT_TRUE(loadReturn.isOk());
+    EXPECT_NE(0, ret);
+    EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::unloadSoundModel() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the implementation returns an error when called without a valid loaded sound model
+ *
+ */
+TEST_F(SoundTriggerHidlTest, UnloadModelNoModelFail) {
+    Return<int32_t> hidlReturn(0);
+    SoundModelHandle halHandle = 0;
+
+    hidlReturn = mSoundTriggerHal->unloadSoundModel(halHandle);
+
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_NE(0, hidlReturn);
+}
+
+/**
+ * Test ISoundTriggerHw::startRecognition() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the implementation returns an error when called without a valid loaded sound model
+ *
+ * There is no way to verify that implementation actually starts recognition because no model can
+ * be loaded.
+ */
+TEST_F(SoundTriggerHidlTest, StartRecognitionNoModelFail) {
+    Return<int32_t> hidlReturn(0);
+    SoundModelHandle handle = 0;
+    PhraseRecognitionExtra phrase;
+    V2_0_ISoundTriggerHw::RecognitionConfig config;
+
+    config.captureHandle = 0;
+    config.captureDevice = AudioDevice::IN_BUILTIN_MIC;
+    phrase.id = 0;
+    phrase.recognitionModes = (uint32_t)RecognitionMode::VOICE_TRIGGER;
+    phrase.confidenceLevel = 0;
+
+    config.phrases.setToExternal(&phrase, 1);
+
+    hidlReturn = mSoundTriggerHal->startRecognition(handle, config, mCallback, 0);
+
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_NE(0, hidlReturn);
+}
+
+/**
+ * Test ISoundTriggerHw::startRecognition_2_1() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the implementation returns an error when called without a valid loaded sound model
+ *
+ * There is no way to verify that implementation actually starts recognition because no model can
+ * be loaded.
+ */
+TEST_F(SoundTriggerHidlTest, StartRecognitionNoModelFail_2_1) {
+    Return<int32_t> hidlReturn(0);
+    SoundModelHandle handle = 0;
+    PhraseRecognitionExtra phrase;
+    ISoundTriggerHw::RecognitionConfig config;
+
+    config.header.captureHandle = 0;
+    config.header.captureDevice = AudioDevice::IN_BUILTIN_MIC;
+    phrase.id = 0;
+    phrase.recognitionModes = (uint32_t)RecognitionMode::VOICE_TRIGGER;
+    phrase.confidenceLevel = 0;
+
+    config.header.phrases.setToExternal(&phrase, 1);
+
+    hidlReturn = mSoundTriggerHal->startRecognition_2_1(handle, config, mCallback, 0);
+
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_NE(0, hidlReturn);
+}
+
+/**
+ * Test ISoundTriggerHw::stopRecognition() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the implementation returns an error when called without an active recognition running
+ *
+ */
+TEST_F(SoundTriggerHidlTest, StopRecognitionNoAStartFail) {
+    Return<int32_t> hidlReturn(0);
+    SoundModelHandle handle = 0;
+
+    hidlReturn = mSoundTriggerHal->stopRecognition(handle);
+
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_NE(0, hidlReturn);
+}
+
+/**
+ * Test ISoundTriggerHw::stopAllRecognitions() method
+ *
+ * Verifies that:
+ *  - the implementation implements this optional method or indicates it is not supported by
+ *  returning -ENOSYS
+ */
+TEST_F(SoundTriggerHidlTest, stopAllRecognitions) {
+    Return<int32_t> hidlReturn(0);
+
+    hidlReturn = mSoundTriggerHal->stopAllRecognitions();
+
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_TRUE(hidlReturn == 0 || hidlReturn == -ENOSYS);
+}
diff --git a/update-base-files.sh b/update-base-files.sh
index bb99d22..75d2be5 100755
--- a/update-base-files.sh
+++ b/update-base-files.sh
@@ -31,8 +31,11 @@
 
 # system/core
 hidl-gen $options \
-         -o $ANDROID_BUILD_TOP/system/core/include/system/graphics-base.h \
+         -o $ANDROID_BUILD_TOP/system/core/include/system/graphics-base-v1.0.h \
          android.hardware.graphics.common@1.0
+hidl-gen $options \
+         -o $ANDROID_BUILD_TOP/system/core/include/system/graphics-base-v1.1.h \
+         android.hardware.graphics.common@1.1
 
 # system/media
 hidl-gen $options \
diff --git a/usb/gadget/1.0/Android.bp b/usb/gadget/1.0/Android.bp
new file mode 100644
index 0000000..f38002f
--- /dev/null
+++ b/usb/gadget/1.0/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.usb.gadget@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IUsbGadget.hal",
+        "IUsbGadgetCallback.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "GadgetFunction",
+        "Status",
+    ],
+    gen_java: true,
+}
+
diff --git a/usb/gadget/1.0/IUsbGadget.hal b/usb/gadget/1.0/IUsbGadget.hal
new file mode 100644
index 0000000..41be401
--- /dev/null
+++ b/usb/gadget/1.0/IUsbGadget.hal
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 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.usb.gadget@1.0;
+
+import IUsbGadgetCallback;
+
+interface IUsbGadget {
+    /**
+     * This function is used to set the current USB gadget configuration.
+     * Usb gadget needs to teared down if an USB configuration is already
+     * active.
+     *
+     * @param functions list of functions defined by GadgetFunction to be
+     *                  included in the gadget composition.
+     * @param callback IUsbGadgetCallback::setCurrentUsbFunctionsCb used to
+     *                 propagate back the status.
+     * @param timeout The maximum time (in milliseconds) within which the
+     *                IUsbGadgetCallback needs to be returned.
+     */
+    oneway setCurrentUsbFunctions(bitfield<GadgetFunction> functions,
+                                  IUsbGadgetCallback callback,
+                                  uint64_t timeout);
+
+    /**
+     * This function is used to query the USB functions included in the
+     * current USB configuration.
+     *
+     * @param callback IUsbGadgetCallback::getCurrentUsbFunctionsCb used to
+     *                 propagate the current functions list.
+     */
+    oneway getCurrentUsbFunctions(IUsbGadgetCallback callback);
+
+};
diff --git a/usb/gadget/1.0/IUsbGadgetCallback.hal b/usb/gadget/1.0/IUsbGadgetCallback.hal
new file mode 100644
index 0000000..8876abb
--- /dev/null
+++ b/usb/gadget/1.0/IUsbGadgetCallback.hal
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 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.usb.gadget@1.0;
+
+interface IUsbGadgetCallback {
+    /**
+     * Callback function used to propagate the status of configuration
+     * switch to the caller.
+     *
+     * @param functions list of functions defined by GadgetFunction
+     *                  included in the current USB gadget composition.
+     * @param status SUCCESS when the functions are applied.
+     *               FUNCTIONS_NOT_SUPPORTED when the configuration is
+     *                                       not supported.
+     *               ERROR otherwise.
+     */
+    oneway setCurrentUsbFunctionsCb(bitfield<GadgetFunction> functions,
+                                    Status status);
+
+    /**
+     * Callback function used to propagate the current USB gadget
+     * configuration.
+     * @param functions list of functions defined by GadgetFunction
+     *                  included in the current USB gadget composition.
+     * @param status FUNCTIONS_APPLIED when list of functions have been
+     *                                 applied.
+     *               FUNCTIONS_NOT_APPLIED when the functions have not
+     *                                     been applied.
+     *               ERROR otherwise.
+     */
+    oneway getCurrentUsbFunctionsCb(bitfield<GadgetFunction> functions,
+                                    Status status);
+};
diff --git a/usb/gadget/1.0/types.hal b/usb/gadget/1.0/types.hal
new file mode 100644
index 0000000..3793fe2
--- /dev/null
+++ b/usb/gadget/1.0/types.hal
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 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.usb.gadget@1.0;
+
+enum GadgetFunction : uint64_t {
+    /**
+     * Removes all the functions and pulls down the gadget.
+     */
+    NONE = 0,
+
+    /**
+     * Android Debug Bridge function.
+     */
+    ADB = 1 << 0,
+
+    /**
+     * Android open accessory protocol function.
+     */
+    ACCESSORY = 1 << 1,
+
+    /**
+     * Media Transfer protocol function.
+     */
+    MTP = 1 << 2,
+
+    /**
+     * Peripheral mode USB Midi function.
+     */
+    MIDI = 1 << 3,
+
+    /**
+     * Picture transfer protocol function.
+     */
+    PTP = 1 << 4,
+
+    /**
+     * Tethering function.
+     */
+    RNDIS = 1 << 5,
+
+    /**
+     * AOAv2.0 - Audio Source function.
+     */
+    AUDIO_SOURCE = 1 << 6,
+};
+
+enum Status : uint32_t {
+    SUCCESS = 0,
+
+    /**
+     * Error value when the HAL operation fails for reasons not listed here.
+     */
+    ERROR = 1,
+
+    /**
+     * USB configuration applied successfully.
+     */
+    FUNCTIONS_APPLIED = 2,
+
+    /**
+     * USB confgiuration failed to apply.
+     */
+    FUNCTIONS_NOT_APPLIED = 3,
+
+    /**
+     * USB configuration not supported.
+     */
+    CONFIGURATION_NOT_SUPPORTED = 4,
+};
diff --git a/wifi/1.0/types.hal b/wifi/1.0/types.hal
index b9fb0bd..4b8d68a 100644
--- a/wifi/1.0/types.hal
+++ b/wifi/1.0/types.hal
@@ -1411,7 +1411,8 @@
   vec<uint8_t> extendedServiceSpecificInfo;
   /**
    * The match filter from the discovery packet (publish or subscribe) which caused service
-   * discovery. Matches the peer's |NanDiscoveryCommonConfig.txMatchFilter|.
+   * discovery. Matches the |NanDiscoveryCommonConfig.txMatchFilter| of the peer's Unsolicited
+   * publish message or of the local device's Active subscribe message.
    * Max length: |NanCapabilities.maxMatchFilterLen|.
    * NAN Spec: Service Descriptor Attribute (SDA) / Matching Filter
    */
diff --git a/wifi/1.2/Android.bp b/wifi/1.2/Android.bp
index 49752a1..100b36b 100644
--- a/wifi/1.2/Android.bp
+++ b/wifi/1.2/Android.bp
@@ -7,14 +7,23 @@
         enabled: true,
     },
     srcs: [
+        "types.hal",
         "IWifi.hal",
         "IWifiChip.hal",
+        "IWifiNanIface.hal",
+        "IWifiNanIfaceEventCallback.hal",
     ],
     interfaces: [
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
         "android.hidl.base@1.0",
     ],
+    types: [
+        "NanConfigRequestSupplemental",
+        "NanDataPathChannelInfo",
+        "NanDataPathConfirmInd",
+        "NanDataPathScheduleUpdateInd",
+    ],
     gen_java: true,
 }
 
diff --git a/wifi/1.2/IWifiNanIface.hal b/wifi/1.2/IWifiNanIface.hal
new file mode 100644
index 0000000..0260162
--- /dev/null
+++ b/wifi/1.2/IWifiNanIface.hal
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2017 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.wifi@1.2;
+
+import @1.0::CommandIdShort;
+import @1.0::IWifiNanIface;
+import @1.0::NanConfigRequest;
+import @1.0::NanEnableRequest;
+import @1.0::WifiStatus;
+import IWifiNanIfaceEventCallback;
+
+/**
+ * Interface used to represent a single NAN (Neighbour Aware Network) iface.
+ *
+ * References to "NAN Spec" are to the Wi-Fi Alliance "Wi-Fi Neighbor Awareness
+ * Networking (NAN) Technical Specification".
+ */
+interface IWifiNanIface extends @1.0::IWifiNanIface {
+    /**
+     * Requests notifications of significant events on this iface. Multiple calls
+     * to this must register multiple callbacks each of which must receive all
+     * events.
+     *
+     * Note: supersedes the @1.0::IWifiNanIface.registerEventCallback() method which is deprecated
+     * as of HAL version 1.2.
+     *
+     * @param callback An instance of the |IWifiNanIfaceEventCallback| HIDL interface
+     *        object.
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|
+     */
+    registerEventCallback_1_2(IWifiNanIfaceEventCallback callback)
+        generates (WifiStatus status);
+
+    /**
+     * Enable NAN: configures and activates NAN clustering (does not start
+     * a discovery session or set up data-interfaces or data-paths). Use the
+     * |IWifiNanIface.configureRequest| method to change the configuration of an already enabled
+     * NAN interface.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyEnableResponse|.
+     *
+     * Note: supersedes the @1.0::IWifiNanIface.enableRequest() method which is deprecated as of
+     * HAL version 1.2.
+     *
+     * @param cmdId command Id to use for this invocation.
+     * @param msg1 Instance of |NanEnableRequest|.
+     * @param msg2 Instance of |NanConfigRequestSupplemental|.
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    enableRequest_1_2(CommandIdShort cmdId, NanEnableRequest msg1,
+                      NanConfigRequestSupplemental msg2)
+        generates (WifiStatus status);
+
+    /**
+     * Configure NAN: configures an existing NAN functionality (i.e. assumes
+     * |IWifiNanIface.enableRequest| already submitted and succeeded).
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyConfigResponse|.
+     *
+     * Note: supersedes the @1.0::IWifiNanIface.configRequest() method which is deprecated as of
+     * HAL version 1.2.
+     *
+     * @param cmdId command Id to use for this invocation.
+     * @param msg1 Instance of |NanConfigRequest|.
+     * @param msg1 Instance of |NanConfigRequestSupplemental|.
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    configRequest_1_2(CommandIdShort cmdId, NanConfigRequest msg1,
+                      NanConfigRequestSupplemental msg2)
+        generates (WifiStatus status);
+};
diff --git a/wifi/1.2/IWifiNanIfaceEventCallback.hal b/wifi/1.2/IWifiNanIfaceEventCallback.hal
new file mode 100644
index 0000000..efd5479
--- /dev/null
+++ b/wifi/1.2/IWifiNanIfaceEventCallback.hal
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 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.wifi@1.2;
+
+import @1.0::IWifiNanIfaceEventCallback;
+
+/**
+ * NAN Response and Asynchronous Event Callbacks.
+ *
+ * References to "NAN Spec" are to the Wi-Fi Alliance "Wi-Fi Neighbor Awareness
+ * Networking (NAN) Technical Specification".
+ */
+interface IWifiNanIfaceEventCallback extends @1.0::IWifiNanIfaceEventCallback {
+    /**
+     * Asynchronous callback indicating a data-path (NDP) setup has been completed: received by
+     * both Initiator and Responder.
+     *
+     * Note: supersedes the @1.0::IWifiNanIfaceEventCallback.eventDataPathConfirm() method which is
+     * deprecated as of HAL version 1.2.
+     *
+     * @param event: NanDataPathConfirmInd containing event details.
+     */
+    oneway eventDataPathConfirm_1_2(NanDataPathConfirmInd event);
+
+    /**
+     * Asynchronous callback indicating a data-path (NDP) schedule has been updated (e.g. channels
+     * have been changed).
+     *
+     * @param event: NanDataPathScheduleUpdateInd containing event details.
+     */
+    oneway eventDataPathScheduleUpdate(NanDataPathScheduleUpdateInd event);
+};
\ No newline at end of file
diff --git a/wifi/1.2/default/Android.mk b/wifi/1.2/default/Android.mk
index 95414bc..8d0262b 100644
--- a/wifi/1.2/default/Android.mk
+++ b/wifi/1.2/default/Android.mk
@@ -30,6 +30,7 @@
 LOCAL_SRC_FILES := \
     hidl_struct_util.cpp \
     hidl_sync_util.cpp \
+    ringbuffer.cpp \
     wifi.cpp \
     wifi_ap_iface.cpp \
     wifi_chip.cpp \
@@ -97,6 +98,7 @@
     tests/mock_wifi_feature_flags.cpp \
     tests/mock_wifi_legacy_hal.cpp \
     tests/mock_wifi_mode_controller.cpp \
+    tests/ringbuffer_unit_tests.cpp \
     tests/wifi_chip_unit_tests.cpp
 LOCAL_STATIC_LIBRARIES := \
     libgmock \
diff --git a/wifi/1.2/default/hidl_struct_util.cpp b/wifi/1.2/default/hidl_struct_util.cpp
index 5d48109..f87828c 100644
--- a/wifi/1.2/default/hidl_struct_util.cpp
+++ b/wifi/1.2/default/hidl_struct_util.cpp
@@ -1118,6 +1118,35 @@
     return true;
 }
 
+bool convertHidlNanEnableRequest_1_2ToLegacy(
+    const NanEnableRequest& hidl_request1,
+    const NanConfigRequestSupplemental& hidl_request2,
+    legacy_hal::NanEnableRequest* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR)
+            << "convertHidlNanEnableRequest_1_2ToLegacy: null legacy_request";
+        return false;
+    }
+
+    *legacy_request = {};
+    if (!convertHidlNanEnableRequestToLegacy(hidl_request1, legacy_request)) {
+        return false;
+    }
+
+    legacy_request->config_discovery_beacon_int = 1;
+    legacy_request->discovery_beacon_interval =
+        hidl_request2.discoveryBeaconIntervalMs;
+    legacy_request->config_nss = 1;
+    legacy_request->nss = hidl_request2.numberOfSpatialStreamsInDiscovery;
+    legacy_request->config_dw_early_termination = 1;
+    legacy_request->enable_dw_termination =
+        hidl_request2.enableDiscoveryWindowEarlyTermination;
+    legacy_request->config_enable_ranging = 1;
+    legacy_request->enable_ranging = hidl_request2.enableRanging;
+
+    return true;
+}
+
 bool convertHidlNanPublishRequestToLegacy(
     const NanPublishRequest& hidl_request,
     legacy_hal::NanPublishRequest* legacy_request) {
@@ -1600,6 +1629,35 @@
     return true;
 }
 
+bool convertHidlNanConfigRequest_1_2ToLegacy(
+    const NanConfigRequest& hidl_request1,
+    const NanConfigRequestSupplemental& hidl_request2,
+    legacy_hal::NanConfigRequest* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR) << "convertHidlNanConfigRequest_1_2ToLegacy: legacy_request "
+                      "is null";
+        return false;
+    }
+
+    *legacy_request = {};
+    if (!convertHidlNanConfigRequestToLegacy(hidl_request1, legacy_request)) {
+        return false;
+    }
+
+    legacy_request->config_discovery_beacon_int = 1;
+    legacy_request->discovery_beacon_interval =
+        hidl_request2.discoveryBeaconIntervalMs;
+    legacy_request->config_nss = 1;
+    legacy_request->nss = hidl_request2.numberOfSpatialStreamsInDiscovery;
+    legacy_request->config_dw_early_termination = 1;
+    legacy_request->enable_dw_termination =
+        hidl_request2.enableDiscoveryWindowEarlyTermination;
+    legacy_request->config_enable_ranging = 1;
+    legacy_request->enable_ranging = hidl_request2.enableRanging;
+
+    return true;
+}
+
 bool convertHidlNanDataPathInitiatorRequestToLegacy(
     const NanInitiateDataPathRequest& hidl_request,
     legacy_hal::NanDataPathInitiatorRequest* legacy_request) {
@@ -1902,6 +1960,22 @@
     return true;
 }
 
+bool convertLegacyNdpChannelInfoToHidl(
+    const legacy_hal::NanChannelInfo& legacy_struct,
+    NanDataPathChannelInfo* hidl_struct) {
+    if (!hidl_struct) {
+        LOG(ERROR) << "convertLegacyNdpChannelInfoToHidl: hidl_struct is null";
+        return false;
+    }
+    *hidl_struct = {};
+
+    hidl_struct->channelFreq = legacy_struct.channel;
+    hidl_struct->channelBandwidth = legacy_struct.bandwidth;
+    hidl_struct->numSpatialStreams = legacy_struct.nss;
+
+    return true;
+}
+
 bool convertLegacyNanDataPathConfirmIndToHidl(
     const legacy_hal::NanDataPathConfirmInd& legacy_ind,
     NanDataPathConfirmInd* hidl_ind) {
@@ -1912,18 +1986,60 @@
     }
     *hidl_ind = {};
 
-    hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id;
-    hidl_ind->dataPathSetupSuccess =
+    hidl_ind->V1_0.ndpInstanceId = legacy_ind.ndp_instance_id;
+    hidl_ind->V1_0.dataPathSetupSuccess =
         legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT;
-    hidl_ind->peerNdiMacAddr =
+    hidl_ind->V1_0.peerNdiMacAddr =
         hidl_array<uint8_t, 6>(legacy_ind.peer_ndi_mac_addr);
-    hidl_ind->appInfo =
+    hidl_ind->V1_0.appInfo =
         std::vector<uint8_t>(legacy_ind.app_info.ndp_app_info,
                              legacy_ind.app_info.ndp_app_info +
                                  legacy_ind.app_info.ndp_app_info_len);
-    hidl_ind->status.status =
+    hidl_ind->V1_0.status.status =
         convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code);
-    hidl_ind->status.description = "";  // TODO: b/34059183
+    hidl_ind->V1_0.status.description = "";  // TODO: b/34059183
+
+    std::vector<NanDataPathChannelInfo> channelInfo;
+    for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) {
+        NanDataPathChannelInfo hidl_struct;
+        if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i],
+                                               &hidl_struct)) {
+            return false;
+        }
+        channelInfo.push_back(hidl_struct);
+    }
+    hidl_ind->channelInfo = channelInfo;
+
+    return true;
+}
+
+bool convertLegacyNanDataPathScheduleUpdateIndToHidl(
+    const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
+    NanDataPathScheduleUpdateInd* hidl_ind) {
+    if (!hidl_ind) {
+        LOG(ERROR) << "convertLegacyNanDataPathScheduleUpdateIndToHidl: "
+                      "hidl_ind is null";
+        return false;
+    }
+    *hidl_ind = {};
+
+    hidl_ind->peerDiscoveryAddress =
+        hidl_array<uint8_t, 6>(legacy_ind.peer_mac_addr);
+    std::vector<NanDataPathChannelInfo> channelInfo;
+    for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) {
+        NanDataPathChannelInfo hidl_struct;
+        if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i],
+                                               &hidl_struct)) {
+            return false;
+        }
+        channelInfo.push_back(hidl_struct);
+    }
+    hidl_ind->channelInfo = channelInfo;
+    std::vector<uint32_t> ndpInstanceIds;
+    for (unsigned int i = 0; i < legacy_ind.num_ndp_instances; ++i) {
+        ndpInstanceIds.push_back(legacy_ind.ndp_instance_id[i]);
+    }
+    hidl_ind->ndpInstanceIds = ndpInstanceIds;
 
     return true;
 }
diff --git a/wifi/1.2/default/hidl_struct_util.h b/wifi/1.2/default/hidl_struct_util.h
index 6766b0f..1208afd 100644
--- a/wifi/1.2/default/hidl_struct_util.h
+++ b/wifi/1.2/default/hidl_struct_util.h
@@ -22,6 +22,7 @@
 #include <android/hardware/wifi/1.0/IWifiChip.h>
 #include <android/hardware/wifi/1.0/types.h>
 #include <android/hardware/wifi/1.1/IWifiChip.h>
+#include <android/hardware/wifi/1.2/types.h>
 
 #include "wifi_legacy_hal.h"
 
@@ -106,6 +107,14 @@
 bool convertHidlNanConfigRequestToLegacy(
     const NanConfigRequest& hidl_request,
     legacy_hal::NanConfigRequest* legacy_request);
+bool convertHidlNanEnableRequest_1_2ToLegacy(
+    const NanEnableRequest& hidl_request1,
+    const NanConfigRequestSupplemental& hidl_request2,
+    legacy_hal::NanEnableRequest* legacy_request);
+bool convertHidlNanConfigRequest_1_2ToLegacy(
+    const NanConfigRequest& hidl_request1,
+    const NanConfigRequestSupplemental& hidl_request2,
+    legacy_hal::NanConfigRequest* legacy_request);
 bool convertHidlNanPublishRequestToLegacy(
     const NanPublishRequest& hidl_request,
     legacy_hal::NanPublishRequest* legacy_request);
@@ -138,6 +147,9 @@
 bool convertLegacyNanDataPathConfirmIndToHidl(
     const legacy_hal::NanDataPathConfirmInd& legacy_ind,
     NanDataPathConfirmInd* hidl_ind);
+bool convertLegacyNanDataPathScheduleUpdateIndToHidl(
+    const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
+    NanDataPathScheduleUpdateInd* hidl_ind);
 
 // RTT controller conversion methods.
 bool convertHidlVectorOfRttConfigToLegacy(
diff --git a/wifi/1.2/default/ringbuffer.cpp b/wifi/1.2/default/ringbuffer.cpp
new file mode 100644
index 0000000..5511f2f
--- /dev/null
+++ b/wifi/1.2/default/ringbuffer.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 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 "ringbuffer.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+
+Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {}
+
+void Ringbuffer::append(const std::vector<uint8_t>& input) {
+    if (input.size() == 0) {
+        return;
+    }
+    data_.push_back(input);
+    size_ += input.size() * sizeof(input[0]);
+    while (size_ > maxSize_) {
+        size_ -= data_.front().size() * sizeof(data_.front()[0]);
+        data_.pop_front();
+    }
+}
+
+const std::list<std::vector<uint8_t>>& Ringbuffer::getData() const {
+    return data_;
+}
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.2/default/ringbuffer.h b/wifi/1.2/default/ringbuffer.h
new file mode 100644
index 0000000..4808e40
--- /dev/null
+++ b/wifi/1.2/default/ringbuffer.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 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 RINGBUFFER_H_
+#define RINGBUFFER_H_
+
+#include <list>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+
+/**
+ * Ringbuffer object used to store debug data.
+ */
+class Ringbuffer {
+   public:
+    explicit Ringbuffer(size_t maxSize);
+
+    // Appends the data buffer and deletes from the front until buffer is
+    // within |maxSize_|.
+    void append(const std::vector<uint8_t>& input);
+    const std::list<std::vector<uint8_t>>& getData() const;
+
+   private:
+    std::list<std::vector<uint8_t>> data_;
+    size_t size_;
+    size_t maxSize_;
+};
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // RINGBUFFER_H_
diff --git a/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp b/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
new file mode 100644
index 0000000..1b332f9
--- /dev/null
+++ b/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018, 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 <gmock/gmock.h>
+
+#include "ringbuffer.h"
+
+using testing::Return;
+using testing::Test;
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+
+class RingbufferTest : public Test {
+   public:
+    const uint32_t maxBufferSize_ = 10;
+    Ringbuffer buffer_{maxBufferSize_};
+};
+
+TEST_F(RingbufferTest, CreateEmptyBuffer) {
+    ASSERT_TRUE(buffer_.getData().empty());
+}
+
+TEST_F(RingbufferTest, CanUseFullBufferCapacity) {
+    const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
+    const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
+    buffer_.append(input);
+    buffer_.append(input2);
+    ASSERT_EQ(2u, buffer_.getData().size());
+    EXPECT_EQ(input, buffer_.getData().front());
+    EXPECT_EQ(input2, buffer_.getData().back());
+}
+
+TEST_F(RingbufferTest, OldDataIsRemovedOnOverflow) {
+    const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
+    const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
+    const std::vector<uint8_t> input3 = {'G'};
+    buffer_.append(input);
+    buffer_.append(input2);
+    buffer_.append(input3);
+    ASSERT_EQ(2u, buffer_.getData().size());
+    EXPECT_EQ(input2, buffer_.getData().front());
+    EXPECT_EQ(input3, buffer_.getData().back());
+}
+
+TEST_F(RingbufferTest, MultipleOldDataIsRemovedOnOverflow) {
+    const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
+    const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
+    const std::vector<uint8_t> input3(maxBufferSize_, '2');
+    buffer_.append(input);
+    buffer_.append(input2);
+    buffer_.append(input3);
+    ASSERT_EQ(1u, buffer_.getData().size());
+    EXPECT_EQ(input3, buffer_.getData().front());
+}
+
+TEST_F(RingbufferTest, AppendingEmptyBufferDoesNotAddGarbage) {
+    const std::vector<uint8_t> input = {};
+    buffer_.append(input);
+    ASSERT_TRUE(buffer_.getData().empty());
+}
+
+TEST_F(RingbufferTest, OversizedAppendIsDropped) {
+    const std::vector<uint8_t> input(maxBufferSize_ + 1, '0');
+    buffer_.append(input);
+    ASSERT_TRUE(buffer_.getData().empty());
+}
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
index f73869b..1b082d0 100644
--- a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
@@ -117,8 +117,10 @@
             });
         } else if (type == IfaceType::NAN) {
             chip_->createNanIface(
-                [&iface_name](const WifiStatus& status,
-                              const sp<IWifiNanIface>& iface) {
+                [&iface_name](
+                    const WifiStatus& status,
+                    const sp<android::hardware::wifi::V1_0::IWifiNanIface>&
+                        iface) {
                     if (WifiStatusCode::SUCCESS == status.code) {
                         ASSERT_NE(iface.get(), nullptr);
                         iface->getName([&iface_name](const WifiStatus& status,
diff --git a/wifi/1.2/default/wifi.cpp b/wifi/1.2/default/wifi.cpp
index 06f5058..d6106b4 100644
--- a/wifi/1.2/default/wifi.cpp
+++ b/wifi/1.2/default/wifi.cpp
@@ -77,6 +77,12 @@
                            &Wifi::getChipInternal, hidl_status_cb, chip_id);
 }
 
+Return<void> Wifi::debug(const hidl_handle& handle,
+                         const hidl_vec<hidl_string>&) {
+    LOG(INFO) << "-----------Debug is called----------------";
+    return chip_->debug(handle, {});
+}
+
 WifiStatus Wifi::registerEventCallbackInternal(
     const sp<IWifiEventCallback>& event_callback) {
     if (!event_cb_handler_.addCallback(event_callback)) {
diff --git a/wifi/1.2/default/wifi.h b/wifi/1.2/default/wifi.h
index 440c3c7..86919b1 100644
--- a/wifi/1.2/default/wifi.h
+++ b/wifi/1.2/default/wifi.h
@@ -56,6 +56,8 @@
     Return<void> stop(stop_cb hidl_status_cb) override;
     Return<void> getChipIds(getChipIds_cb hidl_status_cb) override;
     Return<void> getChip(ChipId chip_id, getChip_cb hidl_status_cb) override;
+    Return<void> debug(const hidl_handle& handle,
+                       const hidl_vec<hidl_string>& options) override;
 
    private:
     enum class RunState { STOPPED, STARTED, STOPPING };
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp
index adba054..bc3404a 100644
--- a/wifi/1.2/default/wifi_chip.cpp
+++ b/wifi/1.2/default/wifi_chip.cpp
@@ -14,8 +14,13 @@
  * limitations under the License.
  */
 
+#include <fcntl.h>
+
 #include <android-base/logging.h>
+#include <android-base/unique_fd.h>
 #include <cutils/properties.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
 
 #include "hidl_return_util.h"
 #include "hidl_struct_util.h"
@@ -23,6 +28,7 @@
 #include "wifi_status_util.h"
 
 namespace {
+using android::base::unique_fd;
 using android::hardware::hidl_string;
 using android::hardware::hidl_vec;
 using android::hardware::wifi::V1_0::ChipModeId;
@@ -39,6 +45,11 @@
 // Mode ID for V2
 constexpr ChipModeId kV2ChipModeId = 2;
 
+constexpr char kCpioMagic[] = "070701";
+constexpr size_t kMaxBufferSizeBytes = 1024 * 1024;
+constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60;
+constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
+
 template <typename Iface>
 void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
     iface->invalidate();
@@ -93,6 +104,165 @@
     return buffer.data();
 }
 
+// delete files older than a predefined time in the wifi tombstone dir
+bool removeOldFilesInternal() {
+    time_t now = time(0);
+    const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds;
+    DIR* dir_dump = opendir(kTombstoneFolderPath);
+    if (!dir_dump) {
+        LOG(ERROR) << "Failed to open directory: " << strerror(errno);
+        return false;
+    }
+    unique_fd dir_auto_closer(dirfd(dir_dump));
+    struct dirent* dp;
+    bool success = true;
+    while ((dp = readdir(dir_dump))) {
+        if (dp->d_type != DT_REG) {
+            continue;
+        }
+        std::string cur_file_name(dp->d_name);
+        struct stat cur_file_stat;
+        std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
+        if (stat(cur_file_path.c_str(), &cur_file_stat) != -1) {
+            if (cur_file_stat.st_mtime < delete_files_before) {
+                if (unlink(cur_file_path.c_str()) != 0) {
+                    LOG(ERROR) << "Error deleting file " << strerror(errno);
+                    success = false;
+                }
+            }
+        } else {
+            LOG(ERROR) << "Failed to get file stat for " << cur_file_path
+                       << ": " << strerror(errno);
+            success = false;
+        }
+    }
+    return success;
+}
+
+// Archives all files in |input_dir| and writes result into |out_fd|
+// Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive"
+// portion
+size_t cpioFilesInDir(int out_fd, const char* input_dir) {
+    struct dirent* dp;
+    size_t n_error = 0;
+    char read_buf[32 * 1024];
+    DIR* dir_dump = opendir(input_dir);
+    if (!dir_dump) {
+        LOG(ERROR) << "Failed to open directory: " << strerror(errno);
+        n_error++;
+        return n_error;
+    }
+    unique_fd dir_auto_closer(dirfd(dir_dump));
+    while ((dp = readdir(dir_dump))) {
+        if (dp->d_type != DT_REG) {
+            continue;
+        }
+        std::string cur_file_name(dp->d_name);
+        const size_t file_name_len =
+            cur_file_name.size() + 1;  // string.size() does not include the
+                                       // null terminator. The cpio FreeBSD file
+                                       // header expects the null character to
+                                       // be included in the length.
+        struct stat st;
+        ssize_t llen;
+        const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
+        if (stat(cur_file_path.c_str(), &st) != -1) {
+            const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
+            unique_fd file_auto_closer(fd_read);
+            if (fd_read == -1) {
+                LOG(ERROR) << "Failed to read file " << cur_file_path << " "
+                           << strerror(errno);
+                n_error++;
+                continue;
+            }
+            llen = sprintf(
+                read_buf,
+                "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
+                kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid,
+                st.st_gid, static_cast<int>(st.st_nlink),
+                static_cast<int>(st.st_mtime), static_cast<int>(st.st_size),
+                major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
+                minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
+            if (write(out_fd, read_buf, llen) == -1) {
+                LOG(ERROR) << "Error writing cpio header to file "
+                           << cur_file_path << " " << strerror(errno);
+                n_error++;
+                return n_error;
+            }
+            if (write(out_fd, cur_file_name.c_str(), file_name_len) == -1) {
+                LOG(ERROR) << "Error writing filename to file " << cur_file_path
+                           << " " << strerror(errno);
+                n_error++;
+                return n_error;
+            }
+
+            // NUL Pad header up to 4 multiple bytes.
+            llen = (llen + file_name_len) % 4;
+            if (llen != 0) {
+                const uint32_t zero = 0;
+                if (write(out_fd, &zero, 4 - llen) == -1) {
+                    LOG(ERROR) << "Error padding 0s to file " << cur_file_path
+                               << " " << strerror(errno);
+                    n_error++;
+                    return n_error;
+                }
+            }
+
+            // writing content of file
+            llen = st.st_size;
+            while (llen > 0) {
+                ssize_t bytes_read = read(fd_read, read_buf, sizeof(read_buf));
+                if (bytes_read == -1) {
+                    LOG(ERROR) << "Error reading file " << cur_file_path << " "
+                               << strerror(errno);
+                    n_error++;
+                    return n_error;
+                }
+                llen -= bytes_read;
+                if (write(out_fd, read_buf, bytes_read) == -1) {
+                    LOG(ERROR) << "Error writing data to file " << cur_file_path
+                               << " " << strerror(errno);
+                    n_error++;
+                    return n_error;
+                }
+                if (bytes_read ==
+                    0) {  // this should never happen, but just in case
+                          // to unstuck from while loop
+                    LOG(ERROR) << "Unexpected file size for " << cur_file_path
+                               << " " << strerror(errno);
+                    n_error++;
+                    break;
+                }
+            }
+            llen = st.st_size % 4;
+            if (llen != 0) {
+                const uint32_t zero = 0;
+                write(out_fd, &zero, 4 - llen);
+            }
+        } else {
+            LOG(ERROR) << "Failed to get file stat for " << cur_file_path
+                       << ": " << strerror(errno);
+            n_error++;
+        }
+    }
+    memset(read_buf, 0, sizeof(read_buf));
+    if (write(out_fd, read_buf,
+              sprintf(read_buf, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0) +
+                  4) == -1) {
+        LOG(ERROR) << "Error writing trailing bytes " << strerror(errno);
+        n_error++;
+    }
+    return n_error;
+}
+
+// Helper function to create a non-const char*.
+std::vector<char> makeCharVec(const std::string& str) {
+    std::vector<char> vec(str.size() + 1);
+    vec.assign(str.begin(), str.end());
+    vec.push_back('\0');
+    return vec;
+}
+
 }  // namespace
 
 namespace android {
@@ -350,6 +520,24 @@
                            hidl_status_cb);
 }
 
+Return<void> WifiChip::debug(const hidl_handle& handle,
+                             const hidl_vec<hidl_string>&) {
+    if (handle != nullptr && handle->numFds >= 1) {
+        int fd = handle->data[0];
+        if (!writeRingbufferFilesInternal()) {
+            LOG(ERROR) << "Error writing files to flash";
+        }
+        uint32_t n_error = cpioFilesInDir(fd, kTombstoneFolderPath);
+        if (n_error != 0) {
+            LOG(ERROR) << n_error << " errors occured in cpio function";
+        }
+        fsync(fd);
+    } else {
+        LOG(ERROR) << "File handle error";
+    }
+    return Void();
+}
+
 void WifiChip::invalidateAndRemoveAllIfaces() {
     invalidateAndClearAll(ap_ifaces_);
     invalidateAndClearAll(nan_ifaces_);
@@ -387,7 +575,8 @@
     std::tie(legacy_status, legacy_logger_feature_set) =
         legacy_hal_.lock()->getLoggerSupportedFeatureSet(getWlan0IfaceName());
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), 0};
+        // some devices don't support querying logger feature set
+        legacy_logger_feature_set = 0;
     }
     uint32_t hidl_caps;
     if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(
@@ -726,6 +915,8 @@
                 std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
                 verbose_level),
             max_interval_in_sec, min_data_size_in_bytes);
+    ringbuffer_map_.insert(std::pair<std::string, Ringbuffer>(
+        ring_name, Ringbuffer(kMaxBufferSizeBytes)));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -737,6 +928,7 @@
     }
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->getRingBufferData(getWlan0IfaceName(), ring_name);
+
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -848,7 +1040,7 @@
 
     android::wp<WifiChip> weak_ptr_this(this);
     const auto& on_ring_buffer_data_callback =
-        [weak_ptr_this](const std::string& /* name */,
+        [weak_ptr_this](const std::string& name,
                         const std::vector<uint8_t>& data,
                         const legacy_hal::wifi_ring_buffer_status& status) {
             const auto shared_ptr_this = weak_ptr_this.promote();
@@ -862,13 +1054,13 @@
                 LOG(ERROR) << "Error converting ring buffer status";
                 return;
             }
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->onDebugRingBufferDataAvailable(hidl_status, data)
-                         .isOk()) {
-                    LOG(ERROR)
-                        << "Failed to invoke onDebugRingBufferDataAvailable"
-                        << " callback on: " << toString(callback);
-                }
+            const auto& target = shared_ptr_this->ringbuffer_map_.find(name);
+            if (target != shared_ptr_this->ringbuffer_map_.end()) {
+                Ringbuffer& cur_buffer = target->second;
+                cur_buffer.append(data);
+            } else {
+                LOG(ERROR) << "Ringname " << name << " not found";
+                return;
             }
         };
     legacy_hal::wifi_error legacy_status =
@@ -1079,6 +1271,35 @@
     return {};
 }
 
+bool WifiChip::writeRingbufferFilesInternal() {
+    if (!removeOldFilesInternal()) {
+        LOG(ERROR) << "Error occurred while deleting old tombstone files";
+        return false;
+    }
+    // write ringbuffers to file
+    for (const auto& item : ringbuffer_map_) {
+        const Ringbuffer& cur_buffer = item.second;
+        if (cur_buffer.getData().empty()) {
+            continue;
+        }
+        const std::string file_path_raw =
+            kTombstoneFolderPath + item.first + "XXXXXXXXXX";
+        const int dump_fd = mkstemp(makeCharVec(file_path_raw).data());
+        if (dump_fd == -1) {
+            LOG(ERROR) << "create file failed: " << strerror(errno);
+            return false;
+        }
+        unique_fd file_auto_closer(dump_fd);
+        for (const auto& cur_block : cur_buffer.getData()) {
+            if (write(dump_fd, cur_block.data(),
+                      sizeof(cur_block[0]) * cur_block.size()) == -1) {
+                LOG(ERROR) << "Error writing to file " << strerror(errno);
+            }
+        }
+    }
+    return true;
+}
+
 }  // namespace implementation
 }  // namespace V1_2
 }  // namespace wifi
diff --git a/wifi/1.2/default/wifi_chip.h b/wifi/1.2/default/wifi_chip.h
index b5dcc8c..4ffa8da 100644
--- a/wifi/1.2/default/wifi_chip.h
+++ b/wifi/1.2/default/wifi_chip.h
@@ -17,12 +17,14 @@
 #ifndef WIFI_CHIP_H_
 #define WIFI_CHIP_H_
 
+#include <list>
 #include <map>
 
 #include <android-base/macros.h>
 #include <android/hardware/wifi/1.2/IWifiChip.h>
 
 #include "hidl_callback_util.h"
+#include "ringbuffer.h"
 #include "wifi_ap_iface.h"
 #include "wifi_feature_flags.h"
 #include "wifi_legacy_hal.h"
@@ -134,6 +136,8 @@
         selectTxPowerScenario_cb hidl_status_cb) override;
     Return<void> resetTxPowerScenario(
         resetTxPowerScenario_cb hidl_status_cb) override;
+    Return<void> debug(const hidl_handle& handle,
+                       const hidl_vec<hidl_string>& options) override;
 
    private:
     void invalidateAndRemoveAllIfaces();
@@ -204,6 +208,7 @@
     bool canCurrentModeSupportIfaceOfType(IfaceType type);
     bool isValidModeId(ChipModeId mode_id);
     std::string allocateApOrStaIfaceName();
+    bool writeRingbufferFilesInternal();
 
     ChipId chip_id_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
@@ -214,6 +219,7 @@
     std::vector<sp<WifiP2pIface>> p2p_ifaces_;
     std::vector<sp<WifiStaIface>> sta_ifaces_;
     std::vector<sp<WifiRttController>> rtt_controllers_;
+    std::map<std::string, Ringbuffer> ringbuffer_map_;
     bool is_valid_;
     // Members pertaining to chip configuration.
     uint32_t current_mode_id_;
diff --git a/wifi/1.2/default/wifi_nan_iface.cpp b/wifi/1.2/default/wifi_nan_iface.cpp
index 12e4d7b..535e3d3 100644
--- a/wifi/1.2/default/wifi_nan_iface.cpp
+++ b/wifi/1.2/default/wifi_nan_iface.cpp
@@ -428,7 +428,7 @@
             }
 
             for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->eventDataPathConfirm(hidl_struct).isOk()) {
+                if (!callback->eventDataPathConfirm_1_2(hidl_struct).isOk()) {
                     LOG(ERROR) << "Failed to invoke the callback";
                 }
             }
@@ -467,10 +467,28 @@
             LOG(ERROR) << "on_event_range_report - should not be called";
         };
 
-    callback_handlers.on_event_schedule_update =
-        [weak_ptr_this](const legacy_hal::NanDataPathScheduleUpdateInd& /* msg */) {
-            LOG(ERROR) << "on_event_schedule_update - should not be called";
-        };
+    callback_handlers
+        .on_event_schedule_update = [weak_ptr_this](
+                                        const legacy_hal::
+                                            NanDataPathScheduleUpdateInd& msg) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        NanDataPathScheduleUpdateInd hidl_struct;
+        if (!hidl_struct_util::convertLegacyNanDataPathScheduleUpdateIndToHidl(
+                msg, &hidl_struct)) {
+            LOG(ERROR) << "Failed to convert nan capabilities response";
+            return;
+        }
+
+        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+            if (!callback->eventDataPathScheduleUpdate(hidl_struct).isOk()) {
+                LOG(ERROR) << "Failed to invoke the callback";
+            }
+        }
+    };
 
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->nanRegisterCallbackHandlers(ifname_,
@@ -511,7 +529,7 @@
 }
 
 Return<void> WifiNanIface::registerEventCallback(
-    const sp<IWifiNanIfaceEventCallback>& callback,
+    const sp<V1_0::IWifiNanIfaceEventCallback>& callback,
     registerEventCallback_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
                            &WifiNanIface::registerEventCallbackInternal,
@@ -628,6 +646,32 @@
                            hidl_status_cb, cmd_id, ndpInstanceId);
 }
 
+Return<void> WifiNanIface::registerEventCallback_1_2(
+    const sp<IWifiNanIfaceEventCallback>& callback,
+    registerEventCallback_1_2_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::registerEventCallback_1_2Internal,
+                           hidl_status_cb, callback);
+}
+
+Return<void> WifiNanIface::enableRequest_1_2(
+    uint16_t cmd_id, const NanEnableRequest& msg1,
+    const NanConfigRequestSupplemental& msg2,
+    enableRequest_1_2_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::enableRequest_1_2Internal,
+                           hidl_status_cb, cmd_id, msg1, msg2);
+}
+
+Return<void> WifiNanIface::configRequest_1_2(
+    uint16_t cmd_id, const NanConfigRequest& msg1,
+    const NanConfigRequestSupplemental& msg2,
+    configRequest_1_2_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::configRequest_1_2Internal,
+                           hidl_status_cb, cmd_id, msg1, msg2);
+}
+
 std::pair<WifiStatus, std::string> WifiNanIface::getNameInternal() {
     return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
 }
@@ -637,11 +681,8 @@
 }
 
 WifiStatus WifiNanIface::registerEventCallbackInternal(
-    const sp<IWifiNanIfaceEventCallback>& callback) {
-    if (!event_cb_handler_.addCallback(callback)) {
-        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-    }
-    return createWifiStatus(WifiStatusCode::SUCCESS);
+    const sp<V1_0::IWifiNanIfaceEventCallback>& /*callback*/) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
 }
 
 WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t cmd_id) {
@@ -650,28 +691,14 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
-WifiStatus WifiNanIface::enableRequestInternal(uint16_t cmd_id,
-                                               const NanEnableRequest& msg) {
-    legacy_hal::NanEnableRequest legacy_msg;
-    if (!hidl_struct_util::convertHidlNanEnableRequestToLegacy(msg,
-                                                               &legacy_msg)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg);
-    return createWifiStatusFromLegacyError(legacy_status);
+WifiStatus WifiNanIface::enableRequestInternal(
+    uint16_t /* cmd_id */, const NanEnableRequest& /* msg */) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
 }
 
-WifiStatus WifiNanIface::configRequestInternal(uint16_t cmd_id,
-                                               const NanConfigRequest& msg) {
-    legacy_hal::NanConfigRequest legacy_msg;
-    if (!hidl_struct_util::convertHidlNanConfigRequestToLegacy(msg,
-                                                               &legacy_msg)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg);
-    return createWifiStatusFromLegacyError(legacy_status);
+WifiStatus WifiNanIface::configRequestInternal(
+    uint16_t /* cmd_id */, const NanConfigRequest& /* msg */) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
 }
 
 WifiStatus WifiNanIface::disableRequestInternal(uint16_t cmd_id) {
@@ -780,6 +807,40 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
+WifiStatus WifiNanIface::registerEventCallback_1_2Internal(
+    const sp<IWifiNanIfaceEventCallback>& callback) {
+    if (!event_cb_handler_.addCallback(callback)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+WifiStatus WifiNanIface::enableRequest_1_2Internal(
+    uint16_t cmd_id, const NanEnableRequest& msg1,
+    const NanConfigRequestSupplemental& msg2) {
+    legacy_hal::NanEnableRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanEnableRequest_1_2ToLegacy(
+            msg1, msg2, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::configRequest_1_2Internal(
+    uint16_t cmd_id, const NanConfigRequest& msg1,
+    const NanConfigRequestSupplemental& msg2) {
+    legacy_hal::NanConfigRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanConfigRequest_1_2ToLegacy(
+            msg1, msg2, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
 }  // namespace implementation
 }  // namespace V1_2
 }  // namespace wifi
diff --git a/wifi/1.2/default/wifi_nan_iface.h b/wifi/1.2/default/wifi_nan_iface.h
index 6fa7b0c..a2dcf3a 100644
--- a/wifi/1.2/default/wifi_nan_iface.h
+++ b/wifi/1.2/default/wifi_nan_iface.h
@@ -18,8 +18,8 @@
 #define WIFI_NAN_IFACE_H_
 
 #include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiNanIface.h>
 #include <android/hardware/wifi/1.0/IWifiNanIfaceEventCallback.h>
+#include <android/hardware/wifi/1.2/IWifiNanIface.h>
 
 #include "hidl_callback_util.h"
 #include "wifi_legacy_hal.h"
@@ -34,7 +34,7 @@
 /**
  * HIDL interface object used to control a NAN Iface instance.
  */
-class WifiNanIface : public V1_0::IWifiNanIface {
+class WifiNanIface : public V1_2::IWifiNanIface {
    public:
     WifiNanIface(const std::string& ifname,
                  const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
@@ -47,7 +47,7 @@
     Return<void> getName(getName_cb hidl_status_cb) override;
     Return<void> getType(getType_cb hidl_status_cb) override;
     Return<void> registerEventCallback(
-        const sp<IWifiNanIfaceEventCallback>& callback,
+        const sp<V1_0::IWifiNanIfaceEventCallback>& callback,
         registerEventCallback_cb hidl_status_cb) override;
     Return<void> getCapabilitiesRequest(
         uint16_t cmd_id, getCapabilitiesRequest_cb hidl_status_cb) override;
@@ -88,12 +88,24 @@
         uint16_t cmd_id, uint32_t ndpInstanceId,
         terminateDataPathRequest_cb hidl_status_cb) override;
 
+    Return<void> registerEventCallback_1_2(
+        const sp<IWifiNanIfaceEventCallback>& callback,
+        registerEventCallback_1_2_cb hidl_status_cb) override;
+    Return<void> enableRequest_1_2(
+        uint16_t cmd_id, const NanEnableRequest& msg1,
+        const NanConfigRequestSupplemental& msg2,
+        enableRequest_1_2_cb hidl_status_cb) override;
+    Return<void> configRequest_1_2(
+        uint16_t cmd_id, const NanConfigRequest& msg1,
+        const NanConfigRequestSupplemental& msg2,
+        configRequest_1_2_cb hidl_status_cb) override;
+
    private:
     // Corresponding worker functions for the HIDL methods.
     std::pair<WifiStatus, std::string> getNameInternal();
     std::pair<WifiStatus, IfaceType> getTypeInternal();
     WifiStatus registerEventCallbackInternal(
-        const sp<IWifiNanIfaceEventCallback>& callback);
+        const sp<V1_0::IWifiNanIfaceEventCallback>& callback);
     WifiStatus getCapabilitiesRequestInternal(uint16_t cmd_id);
     WifiStatus enableRequestInternal(uint16_t cmd_id,
                                      const NanEnableRequest& msg);
@@ -119,6 +131,15 @@
     WifiStatus terminateDataPathRequestInternal(uint16_t cmd_id,
                                                 uint32_t ndpInstanceId);
 
+    WifiStatus registerEventCallback_1_2Internal(
+        const sp<IWifiNanIfaceEventCallback>& callback);
+    WifiStatus enableRequest_1_2Internal(
+        uint16_t cmd_id, const NanEnableRequest& msg1,
+        const NanConfigRequestSupplemental& msg2);
+    WifiStatus configRequest_1_2Internal(
+        uint16_t cmd_id, const NanConfigRequest& msg,
+        const NanConfigRequestSupplemental& msg2);
+
     std::set<sp<IWifiNanIfaceEventCallback>> getEventCallbacks();
 
     std::string ifname_;
diff --git a/wifi/1.2/types.hal b/wifi/1.2/types.hal
new file mode 100644
index 0000000..1636ae8
--- /dev/null
+++ b/wifi/1.2/types.hal
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2017 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.wifi@1.2;
+
+import @1.0::MacAddress;
+import @1.0::NanDataPathConfirmInd;
+import @1.0::WifiChannelInMhz;
+
+/**
+ * NAN configuration request parameters added in the 1.2 HAL. These are supplemental to previous
+ * versions.
+ */
+struct NanConfigRequestSupplemental {
+    /**
+     * Specify the Discovery Beacon interval in ms. Specification only applicable if the device
+     * transmits Discovery Beacons (based on the Wi-Fi Aware protocol selection criteria). The value
+     * can be increased to reduce power consumption (on devices which would transmit Discovery
+     * Beacons), however - cluster synchronization time will likely increase.
+     * Values are:
+     *  - A value of 0 indicates that the HAL sets the interval to a default (implementation specific)
+     *  - A positive value
+     */
+    uint32_t discoveryBeaconIntervalMs;
+    /**
+     * The number of spatial streams to be used for transmitting NAN management frames (does NOT apply
+     * to data-path packets). A small value may reduce power consumption for small discovery packets.
+     * Values are:
+     *  - A value of 0 indicates that the HAL sets the number to a default (implementation specific)
+     *  - A positive value
+     */
+    uint32_t numberOfSpatialStreamsInDiscovery;
+    /**
+     * Controls whether the device may terminate listening on a Discovery Window (DW) earlier than the
+     * DW termination (16ms) if no information is received. Enabling the feature will result in
+     * lower power consumption, but may result in some missed messages and hence increased latency.
+     */
+    bool enableDiscoveryWindowEarlyTermination;
+    /**
+     * Controls whether NAN RTT (ranging) is permitted. Global flag on any NAN RTT operations are
+     * allowed. Controls ranging in the context of discovery as well as direct RTT.
+     */
+    bool enableRanging;
+};
+
+/**
+ * NAN data path channel information provided to the framework.
+ */
+struct NanDataPathChannelInfo {
+    /**
+     * Channel frequency in MHz.
+     */
+    WifiChannelInMhz channelFreq;
+    /**
+     * Channel bandwidth in MHz.
+     */
+    uint32_t channelBandwidth;
+    /**
+     * Number of spatial streams used in the channel.
+     */
+    uint32_t numSpatialStreams;
+};
+
+/**
+ * NAN Data path confirmation Indication structure.
+ * Event indication is received on both initiator and responder side when negotiation for a
+ * data-path finish: on success or failure.
+ */
+struct NanDataPathConfirmInd {
+    /**
+     * Baseline information as defined in HAL 1.0.
+     */
+    @1.0::NanDataPathConfirmInd V1_0;
+    /**
+     * The channel(s) on which the NDP is scheduled to operate.
+     * Updates to the operational channels are provided using the |eventDataPathScheduleUpdate|
+     * event.
+     */
+    vec<NanDataPathChannelInfo> channelInfo;
+};
+
+/**
+ * NAN data path channel information update indication structure.
+ * Event indication is received by all NDP owners whenever the channels on which the NDP operates
+ * are updated.
+ * Note: multiple NDPs may share the same schedule, the indication specifies all NDPs to which it
+ * applies.
+ */
+struct NanDataPathScheduleUpdateInd {
+    /**
+     * The discovery address (NMI) of the peer to which the NDP is connected.
+     */
+    MacAddress peerDiscoveryAddress;
+    /**
+     * The updated channel(s) information.
+     */
+    vec<NanDataPathChannelInfo> channelInfo;
+    /**
+     * The list of NDPs to which this update applies.
+     */
+    vec<uint32_t> ndpInstanceIds;
+};
diff --git a/wifi/hostapd/1.0/Android.bp b/wifi/hostapd/1.0/Android.bp
new file mode 100644
index 0000000..a17e153
--- /dev/null
+++ b/wifi/hostapd/1.0/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.wifi.hostapd@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IHostapd.hal",
+    ],
+    interfaces: [
+        "android.hardware.wifi.supplicant@1.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "HostapdStatus",
+        "HostapdStatusCode",
+    ],
+    gen_java: true,
+}
+
diff --git a/wifi/hostapd/1.0/IHostapd.hal b/wifi/hostapd/1.0/IHostapd.hal
new file mode 100644
index 0000000..4dc7bf8
--- /dev/null
+++ b/wifi/hostapd/1.0/IHostapd.hal
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2017 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.wifi.hostapd@1.0;
+
+import android.hardware.wifi.supplicant@1.0::Ssid;
+
+/**
+ * Top-level object for managing SoftAPs.
+ */
+interface IHostapd {
+    /**
+     * Size limits for some of the params used in this interface.
+     */
+    enum ParamSizeLimits : uint32_t {
+        /** Max length of SSID param. */
+        SSID_MAX_LEN_IN_BYTES = 32,
+
+        /** Min length of PSK passphrase param. */
+        WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES = 8,
+
+        /** Max length of PSK passphrase param. */
+        WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES = 63,
+    };
+
+    /** Possble Security types. */
+    enum EncryptionType : uint32_t {
+        NONE,
+        WPA,
+        WPA2
+    };
+
+    /**
+     * Band to use for the SoftAp operations.
+     * When using ACS, special value |BAND_ANY| can be
+     * used to indicate that any supported band can be used. This special
+     * case is currently supported only with drivers with which
+     * offloaded ACS is used.
+     */
+    enum Band : uint32_t {
+        BAND_2_4_GHZ,
+        BAND_5_GHZ,
+        BAND_ANY
+    };
+
+    /**
+     * Parameters to control the HW mode for the interface.
+     */
+    struct HwModeParams {
+        /**
+         * Whether IEEE 802.11n (HT) is enabled or not.
+         * Note: hwMode=G (2.4 GHz) and hwMode=A (5 GHz) is used to specify
+         * the band.
+         */
+        bool enable80211N;
+         /**
+          * Whether IEEE 802.11ac (VHT) is enabled or not.
+          * Note: hw_mode=a is used to specify that 5 GHz band is used with VHT.
+          */
+        bool enable80211AC;
+    };
+
+    /**
+     * Parameters to control the channel selection for the interface.
+     */
+    struct ChannelParams {
+        /**
+         * Whether to enable ACS (Automatic Channel Selection) or not.
+         * The channel can be selected automatically at run time by setting
+         * this flag, which must enable the ACS survey based algorithm.
+         */
+        bool enableAcs;
+        /**
+         * This option can be used to exclude all DFS channels from the ACS
+         * channel list in cases where the driver supports DFS channels.
+         **/
+        bool acsShouldExcludeDfs;
+        /**
+         * Channel number (IEEE 802.11) to use for the interface.
+         * If ACS is enabled, this field is ignored.
+         */
+        uint32_t channel;
+        /**
+         * Band to use for the SoftAp operations.
+         */
+        Band band;
+    };
+
+    /**
+     * Parameters to use for setting up the access point interface.
+     */
+    struct IfaceParams {
+        /** Name of the interface */
+        string ifaceName;
+        /** Hw mode params for the interface */
+        HwModeParams hwModeParams;
+        /** Chanel params for the interface */
+        ChannelParams channelParams;
+    };
+
+    /**
+     * Parameters to use for setting up the access point network.
+     */
+    struct NetworkParams {
+        /** SSID to set for the network */
+        Ssid ssid;
+        /** Whether the network needs to be hidden or not. */
+        bool isHidden;
+        /** Key management mask for the network. */
+        EncryptionType encryptionType;
+        /** Passphrase for WPA_PSK network. */
+        string pskPassphrase;
+    };
+
+    /**
+     * Adds a new access point for hostapd to control.
+     *
+     * This should trigger the setup of an access point with the specified
+     * interface and network params.
+     *
+     * @param ifaceParams AccessPoint Params for the access point.
+     * @param nwParams Network Params for the access point.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |HostapdStatusCode.SUCCESS|,
+     *         |HostapdStatusCode.FAILURE_ARGS_INVALID|,
+     *         |HostapdStatusCode.FAILURE_UNKNOWN|,
+     *         |HostapdStatusCode.FAILURE_IFACE_EXISTS|
+     */
+    addAccessPoint(IfaceParams ifaceParams, NetworkParams nwParams)
+        generates(HostapdStatus status);
+
+    /**
+     * Removes an existing access point from hostapd.
+     *
+     * This should bring down the access point previously setup on the
+     * interface.
+     *
+     * @param ifaceName Name of the interface.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |HostapdStatusCode.SUCCESS|,
+     *         |HostapdStatusCode.FAILURE_UNKNOWN|,
+     *         |HostapdStatusCode.FAILURE_IFACE_UNKNOWN|
+     */
+    removeAccessPoint(string ifaceName) generates(HostapdStatus status);
+};
diff --git a/wifi/hostapd/1.0/types.hal b/wifi/hostapd/1.0/types.hal
new file mode 100644
index 0000000..31bbc34
--- /dev/null
+++ b/wifi/hostapd/1.0/types.hal
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017 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.wifi.hostapd@1.0;
+/**
+ * Enum values indicating the status of any hostapd operation.
+ */
+enum HostapdStatusCode : uint32_t {
+  /** No errors. */
+  SUCCESS,
+  /** Unknown failure occured. */
+  FAILURE_UNKNOWN,
+  /** One or more of the incoming args is invalid. */
+  FAILURE_ARGS_INVALID,
+  /** Iface with the provided name does not exist. */
+  FAILURE_IFACE_UNKNOWN,
+  /** Iface with the provided name already exists. */
+  FAILURE_IFACE_EXISTS
+};
+
+/**
+ * Generic structure to return the status of any hostapd operation.
+ */
+struct HostapdStatus {
+  HostapdStatusCode code;
+  /**
+   * A vendor-specific error message to provide more information beyond the
+   * status code.
+   * This must be used for debugging purposes only.
+   */
+  string debugMessage;
+};
diff --git a/wifi/hostapd/1.0/vts/functional/Android.bp b/wifi/hostapd/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..7a920b4
--- /dev/null
+++ b/wifi/hostapd/1.0/vts/functional/Android.bp
@@ -0,0 +1,52 @@
+//
+// Copyright (C) 2018 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_library_static {
+    name: "VtsHalWifiHostapdV1_0TargetTestUtil",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["hostapd_hidl_test_utils.cpp"],
+    export_include_dirs: [
+        "."
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi.hostapd@1.0",
+        "android.hardware.wifi@1.0",
+        "libcrypto",
+        "libgmock",
+        "libwifi-system",
+        "libwifi-system-iface",
+    ],
+}
+
+cc_test {
+    name: "VtsHalWifiHostapdV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "VtsHalWifiHostapdV1_0TargetTest.cpp",
+        "hostapd_hidl_test.cpp",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "VtsHalWifiHostapdV1_0TargetTestUtil",
+        "android.hardware.wifi.hostapd@1.0",
+        "android.hardware.wifi@1.0",
+        "libcrypto",
+        "libgmock",
+        "libwifi-system",
+        "libwifi-system-iface",
+    ],
+}
diff --git a/wifi/hostapd/1.0/vts/functional/VtsHalWifiHostapdV1_0TargetTest.cpp b/wifi/hostapd/1.0/vts/functional/VtsHalWifiHostapdV1_0TargetTest.cpp
new file mode 100644
index 0000000..64e6fbe
--- /dev/null
+++ b/wifi/hostapd/1.0/vts/functional/VtsHalWifiHostapdV1_0TargetTest.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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 <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include "hostapd_hidl_test_utils.h"
+
+class HostapdHidlEnvironment : public ::testing::Environment {
+   public:
+    virtual void SetUp() override { stopHostapd(); }
+    virtual void TearDown() override { startHostapdAndWaitForHidlService(); }
+};
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(new HostapdHidlEnvironment);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h
new file mode 100644
index 0000000..2f71ccb
--- /dev/null
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+// This file is copied from
+// hardware/interfaces/wifi/1.0/vts/functional/wifi_hidl_call_util.h
+// Please make sure these two file are consistent.
+
+#pragma once
+
+#include <functional>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace {
+namespace detail {
+template <typename>
+struct functionArgSaver;
+
+// Provides a std::function that takes one argument, and a buffer
+// wherein the function will store its argument. The buffer has
+// the same type as the argument, but with const and reference
+// modifiers removed.
+template <typename ArgT>
+struct functionArgSaver<std::function<void(ArgT)>> final {
+    using StorageT = typename std::remove_const<
+        typename std::remove_reference<ArgT>::type>::type;
+
+    std::function<void(ArgT)> saveArgs = [this](ArgT arg) {
+        this->saved_values = arg;
+    };
+
+    StorageT saved_values;
+};
+
+// Provides a std::function that takes two arguments, and a buffer
+// wherein the function will store its arguments. The buffer is a
+// std::pair, whose elements have the same types as the arguments
+// (but with const and reference modifiers removed).
+template <typename Arg1T, typename Arg2T>
+struct functionArgSaver<std::function<void(Arg1T, Arg2T)>> final {
+    using StorageT =
+        std::pair<typename std::remove_const<
+                      typename std::remove_reference<Arg1T>::type>::type,
+                  typename std::remove_const<
+                      typename std::remove_reference<Arg2T>::type>::type>;
+
+    std::function<void(Arg1T, Arg2T)> saveArgs = [this](Arg1T arg1,
+                                                        Arg2T arg2) {
+        this->saved_values = {arg1, arg2};
+    };
+
+    StorageT saved_values;
+};
+
+// Provides a std::function that takes three or more arguments, and a
+// buffer wherein the function will store its arguments. The buffer is a
+// std::tuple whose elements have the same types as the arguments (but
+// with const and reference modifiers removed).
+template <typename... ArgT>
+struct functionArgSaver<std::function<void(ArgT...)>> final {
+    using StorageT = std::tuple<typename std::remove_const<
+        typename std::remove_reference<ArgT>::type>::type...>;
+
+    std::function<void(ArgT...)> saveArgs = [this](ArgT... arg) {
+        this->saved_values = {arg...};
+    };
+
+    StorageT saved_values;
+};
+
+// Invokes |method| on |object|, providing |method| a CallbackT as the
+// final argument. Returns a copy of the parameters that |method| provided
+// to CallbackT. (The parameters are returned by value.)
+template <typename CallbackT, typename MethodT, typename ObjectT,
+          typename... ArgT>
+typename functionArgSaver<CallbackT>::StorageT invokeMethod(
+    MethodT method, ObjectT object, ArgT&&... methodArg) {
+    functionArgSaver<CallbackT> result_buffer;
+    const auto& res = ((*object).*method)(std::forward<ArgT>(methodArg)...,
+                                          result_buffer.saveArgs);
+    EXPECT_TRUE(res.isOk());
+    return result_buffer.saved_values;
+}
+}  // namespace detail
+}  // namespace
+
+// Invokes |method| on |strong_pointer|, passing provided arguments through to
+// |method|.
+//
+// Returns either:
+// - A copy of the result callback parameter (for callbacks with a single
+//   parameter), OR
+// - A pair containing a copy of the result callback parameters (for callbacks
+//   with two parameters), OR
+// - A tuple containing a copy of the result callback paramters (for callbacks
+//   with three or more parameters).
+//
+// Example usage:
+//   EXPECT_EQ(HostapdStatusCode::SUCCESS,
+//       HIDL_INVOKE(strong_pointer, methodReturningHostapdStatus).code);
+//   EXPECT_EQ(HostapdStatusCode::SUCCESS,
+//       HIDL_INVOKE(strong_pointer, methodReturningHostapdStatusAndOneMore)
+//         .first.code);
+//   EXPECT_EQ(HostapdStatusCode::SUCCESS, std::get<0>(
+//       HIDL_INVOKE(strong_pointer, methodReturningHostapdStatusAndTwoMore))
+//         .code);
+#define HIDL_INVOKE(strong_pointer, method, ...)                              \
+    (detail::invokeMethod<                                                    \
+        std::remove_reference<decltype(*strong_pointer)>::type::method##_cb>( \
+        &std::remove_reference<decltype(*strong_pointer)>::type::method,      \
+        strong_pointer, ##__VA_ARGS__))
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
new file mode 100644
index 0000000..5f51cfb
--- /dev/null
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
@@ -0,0 +1,222 @@
+/*
+ * 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 <android-base/logging.h>
+#include <cutils/properties.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
+
+#include "hostapd_hidl_call_util.h"
+#include "hostapd_hidl_test_utils.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
+using ::android::hardware::wifi::hostapd::V1_0::HostapdStatus;
+using ::android::hardware::wifi::hostapd::V1_0::HostapdStatusCode;
+
+namespace {
+constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1',
+                                     '2', '3', '4', '5'};
+constexpr char kNwPassphrase[] = "test12345";
+constexpr int kIfaceChannel = 6;
+constexpr int kIfaceInvalidChannel = 567;
+}  // namespace
+
+class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        startHostapdAndWaitForHidlService();
+        hostapd_ = getHostapd();
+        ASSERT_NE(hostapd_.get(), nullptr);
+    }
+
+    virtual void TearDown() override { stopHostapd(); }
+
+   protected:
+    std::string getPrimaryWlanIfaceName() {
+        std::array<char, PROPERTY_VALUE_MAX> buffer;
+        property_get("wifi.interface", buffer.data(), "wlan0");
+        return buffer.data();
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithAcs() {
+        IHostapd::IfaceParams iface_params;
+        iface_params.ifaceName = getPrimaryWlanIfaceName();
+        iface_params.hwModeParams.enable80211N = true;
+        iface_params.hwModeParams.enable80211AC = false;
+        iface_params.channelParams.enableAcs = true;
+        iface_params.channelParams.acsShouldExcludeDfs = true;
+        iface_params.channelParams.channel = 0;
+        iface_params.channelParams.band = IHostapd::Band::BAND_ANY;
+        return iface_params;
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithoutAcs() {
+        IHostapd::IfaceParams iface_params;
+        iface_params.ifaceName = getPrimaryWlanIfaceName();
+        iface_params.hwModeParams.enable80211N = true;
+        iface_params.hwModeParams.enable80211AC = false;
+        iface_params.channelParams.enableAcs = false;
+        iface_params.channelParams.acsShouldExcludeDfs = false;
+        iface_params.channelParams.channel = kIfaceChannel;
+        iface_params.channelParams.band = IHostapd::Band::BAND_2_4_GHZ;
+        return iface_params;
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithInvalidChannel() {
+        IHostapd::IfaceParams iface_params;
+        iface_params.ifaceName = getPrimaryWlanIfaceName();
+        iface_params.hwModeParams.enable80211N = true;
+        iface_params.hwModeParams.enable80211AC = false;
+        iface_params.channelParams.enableAcs = false;
+        iface_params.channelParams.acsShouldExcludeDfs = false;
+        iface_params.channelParams.channel = kIfaceInvalidChannel;
+        iface_params.channelParams.band = IHostapd::Band::BAND_2_4_GHZ;
+        return iface_params;
+    }
+
+    IHostapd::NetworkParams getPskNwParams() {
+        IHostapd::NetworkParams nw_params;
+        nw_params.ssid =
+            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+        nw_params.isHidden = false;
+        nw_params.encryptionType = IHostapd::EncryptionType::WPA2;
+        nw_params.pskPassphrase = kNwPassphrase;
+        return nw_params;
+    }
+
+    IHostapd::NetworkParams getInvalidPskNwParams() {
+        IHostapd::NetworkParams nw_params;
+        nw_params.ssid =
+            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+        nw_params.isHidden = false;
+        nw_params.encryptionType = IHostapd::EncryptionType::WPA2;
+        return nw_params;
+    }
+
+    IHostapd::NetworkParams getOpenNwParams() {
+        IHostapd::NetworkParams nw_params;
+        nw_params.ssid =
+            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+        nw_params.isHidden = false;
+        nw_params.encryptionType = IHostapd::EncryptionType::NONE;
+        return nw_params;
+    }
+    // IHostapd object used for all tests in this fixture.
+    sp<IHostapd> hostapd_;
+};
+
+/*
+ * Create:
+ * Ensures that an instance of the IHostapd proxy object is
+ * successfully created.
+ */
+TEST(HostapdHidlTestNoFixture, Create) {
+    startHostapdAndWaitForHidlService();
+    EXPECT_NE(nullptr, getHostapd().get());
+    stopHostapd();
+}
+
+/**
+ * Adds an access point with PSK network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(),
+                              getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with Open network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddOpenAccessPointWithAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(),
+                              getOpenNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with PSK network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithoutAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint,
+                              getIfaceParamsWithoutAcs(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with Open network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddOpenAccessPointWithoutAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint,
+                              getIfaceParamsWithoutAcs(), getOpenNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS enabled.
+ * Access point creation & removal should pass.
+ */
+TEST_F(HostapdHidlTest, RemoveAccessPointWithAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(),
+                              getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+    status =
+        HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS disabled.
+ * Access point creation & removal should pass.
+ */
+TEST_F(HostapdHidlTest, RemoveAccessPointWithoutAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint,
+                              getIfaceParamsWithoutAcs(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+    status =
+        HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid channel.
+ * Access point creation should fail.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) {
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint,
+                    getIfaceParamsWithInvalidChannel(), getPskNwParams());
+    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid PSK network config.
+ * Access point creation should fail.
+ */
+TEST_F(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) {
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithoutAcs(),
+                    getInvalidPskNwParams());
+    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
new file mode 100644
index 0000000..0915150
--- /dev/null
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
@@ -0,0 +1,135 @@
+/*
+ * 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 <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/manager/1.0/IServiceNotification.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include <wifi_system/hostapd_manager.h>
+#include <wifi_system/interface_tool.h>
+
+#include "hostapd_hidl_test_utils.h"
+#include "wifi_hidl_test_utils.h"
+
+using ::android::sp;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::wifi::V1_0::ChipModeId;
+using ::android::hardware::wifi::V1_0::IWifiChip;
+using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
+using ::android::hardware::wifi::hostapd::V1_0::HostapdStatus;
+using ::android::hardware::wifi::hostapd::V1_0::HostapdStatusCode;
+using ::android::hidl::manager::V1_0::IServiceNotification;
+using ::android::wifi_system::HostapdManager;
+
+namespace {
+const char kHostapdServiceName[] = "default";
+
+// Helper function to initialize the driver and firmware to AP mode
+// using the vendor HAL HIDL interface.
+void initilializeDriverAndFirmware() {
+    sp<IWifiChip> wifi_chip = getWifiChip();
+    ChipModeId mode_id;
+    EXPECT_TRUE(configureChipToSupportIfaceType(
+        wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::AP, &mode_id));
+}
+
+// Helper function to deinitialize the driver and firmware
+// using the vendor HAL HIDL interface.
+void deInitilializeDriverAndFirmware() { stopWifi(); }
+}  // namespace
+
+// Utility class to wait for wpa_hostapd's HIDL service registration.
+class ServiceNotificationListener : public IServiceNotification {
+   public:
+    Return<void> onRegistration(const hidl_string& fully_qualified_name,
+                                const hidl_string& instance_name,
+                                bool pre_existing) override {
+        if (pre_existing) {
+            return Void();
+        }
+        std::unique_lock<std::mutex> lock(mutex_);
+        registered_.push_back(std::string(fully_qualified_name.c_str()) + "/" +
+                              instance_name.c_str());
+        lock.unlock();
+        condition_.notify_one();
+        return Void();
+    }
+
+    bool registerForHidlServiceNotifications(const std::string& instance_name) {
+        if (!IHostapd::registerForNotifications(instance_name, this)) {
+            return false;
+        }
+        configureRpcThreadpool(2, false);
+        return true;
+    }
+
+    bool waitForHidlService(uint32_t timeout_in_millis,
+                            const std::string& instance_name) {
+        std::unique_lock<std::mutex> lock(mutex_);
+        condition_.wait_for(lock, std::chrono::milliseconds(timeout_in_millis),
+                            [&]() { return registered_.size() >= 1; });
+        if (registered_.size() != 1) {
+            return false;
+        }
+        std::string expected_registered =
+            std::string(IHostapd::descriptor) + "/" + instance_name;
+        if (registered_[0] != expected_registered) {
+            LOG(ERROR) << "Expected: " << expected_registered
+                       << ", Got: " << registered_[0];
+            return false;
+        }
+        return true;
+    }
+
+   private:
+    std::vector<std::string> registered_{};
+    std::mutex mutex_;
+    std::condition_variable condition_;
+};
+
+void stopHostapd() {
+    HostapdManager hostapd_manager;
+
+    ASSERT_TRUE(hostapd_manager.StopHostapd());
+    deInitilializeDriverAndFirmware();
+}
+
+void startHostapdAndWaitForHidlService() {
+    initilializeDriverAndFirmware();
+
+    android::sp<ServiceNotificationListener> notification_listener =
+        new ServiceNotificationListener();
+    ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
+        kHostapdServiceName));
+
+    HostapdManager hostapd_manager;
+    ASSERT_TRUE(hostapd_manager.StartHostapd());
+
+    ASSERT_TRUE(
+        notification_listener->waitForHidlService(200, kHostapdServiceName));
+}
+
+sp<IHostapd> getHostapd() {
+    return ::testing::VtsHalHidlTargetTestBase::getService<IHostapd>();
+}
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
new file mode 100644
index 0000000..74ed284
--- /dev/null
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
@@ -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.
+ */
+
+#ifndef HOSTAPD_HIDL_TEST_UTILS_H
+#define HOSTAPD_HIDL_TEST_UTILS_H
+
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
+
+// Used to stop the android wifi framework before every test.
+void stopWifiFramework();
+void startWifiFramework();
+void stopHostapd();
+// Used to configure the chip, driver and start wpa_hostapd before every
+// test.
+void startHostapdAndWaitForHidlService();
+
+// Helper functions to obtain references to the various HIDL interface objects.
+// Note: We only have a single instance of each of these objects currently.
+// These helper functions should be modified to return vectors if we support
+// multiple instances.
+android::sp<android::hardware::wifi::hostapd::V1_0::IHostapd> getHostapd();
+
+#endif /* HOSTAPD_HIDL_TEST_UTILS_H */