Merge "Camera: use finer lock in external camera OutputThread" into pi-dev
diff --git a/audio/2.0/default/service.cpp b/audio/2.0/default/service.cpp
deleted file mode 100644
index d554481..0000000
--- a/audio/2.0/default/service.cpp
+++ /dev/null
@@ -1,56 +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.
- */
-
-#define LOG_TAG "audiohalservice"
-
-#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 <binder/ProcessState.h>
-#include <hidl/HidlTransportSupport.h>
-#include <hidl/LegacySupport.h>
-
-using android::hardware::configureRpcThreadpool;
-using android::hardware::joinRpcThreadpool;
-using android::hardware::registerPassthroughServiceImplementation;
-
-using android::hardware::audio::effect::V2_0::IEffectsFactory;
-using android::hardware::audio::V2_0::IDevicesFactory;
-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;
-
-int main(int /* argc */, char* /* argv */ []) {
-    android::ProcessState::initWithDriver("/dev/vndbinder");
-    // start a threadpool for vndbinder interactions
-    android::ProcessState::self()->startThreadPool();
-    configureRpcThreadpool(16, true /*callerWillJoin*/);
-    android::status_t status;
-    status = registerPassthroughServiceImplementation<IDevicesFactory>();
-    LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio service: %d", status);
-    status = registerPassthroughServiceImplementation<IEffectsFactory>();
-    LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio effects service: %d", status);
-    // Soundtrigger might be not present.
-    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/4.0/IDevice.hal b/audio/4.0/IDevice.hal
index 7eb03c8..1bb5aba 100644
--- a/audio/4.0/IDevice.hal
+++ b/audio/4.0/IDevice.hal
@@ -132,7 +132,6 @@
      * @param device device type and (if needed) address.
      * @param config stream configuration.
      * @param flags additional flags.
-     * @param source source specification.
      * @param sinkMetadata Description of the audio that is suggested by the client.
      *                     May be used by implementations to configure hardware effects.
      * @return retval operation completion status.
diff --git a/audio/4.0/IDevicesFactory.hal b/audio/4.0/IDevicesFactory.hal
index c552c6d..489294e 100644
--- a/audio/4.0/IDevicesFactory.hal
+++ b/audio/4.0/IDevicesFactory.hal
@@ -18,42 +18,53 @@
 
 import android.hardware.audio.common@4.0;
 import IDevice;
+import IPrimaryDevice;
 
+/** This factory allows a HAL implementation to be split in multiple independent
+ *  devices (called module in the pre-treble API).
+ *  Note that this division is arbitrary and implementation are free
+ *  to only have a Primary.
+ *  The framework will query the devices according to audio_policy_configuration.xml
+ *
+ *  Each device name is arbitrary, provided by the vendor's audio_policy_configuration.xml
+ *  and only used to identify a device in this factory.
+ *  The framework must not interpret the name, treating it as a vendor opaque data
+ *  with the following exception:
+ *  - the "r_submix" device that must be present to support policyMixes (Eg: Android projected).
+ *    Note that this Device is included by default in a build derived from AOSP.
+ *
+ *  Note that on AOSP Oreo (including MR1) the "a2dp" module is not using this API
+ *  but is loaded directly from the system partition using the legacy API
+ *  due to limitations with the Bluetooth framework.
+ */
 interface IDevicesFactory {
-    /** Allows a HAL implementation to be split in multiple independent
-     *  devices (called module in the pre-treble API).
-     *  Note that this division is arbitrary and implementation are free
-     *  to only have a Primary.
-     *  The framework will query the devices according to audio_policy_configuration.xml
-     *
-     *  Each Device value is interchangeable with any other and the framework
-     *  does not differentiate between values with the following exceptions:
-     *  - the Primary device must always be present
-     *  - the R_SUBMIX that is used to forward audio of REMOTE_SUBMIX DEVICES
-     */
-    enum Device : int32_t {
-        PRIMARY,
-        A2DP,
-        USB,
-        R_SUBMIX,
-        STUB,
-        CODEC_OFFLOAD,
-        SECONDARY,
-        AUXILIARY,
-        /** Multi Stream Decoder */
-        MSD
-    };
 
     /**
      * Opens an audio device. To close the device, it is necessary to release
      * references to the returned device object.
      *
-     * @param device device type.
+     * @param device device name.
      * @return retval operation completion status. Returns INVALID_ARGUMENTS
      *         if there is no corresponding hardware module found,
      *         NOT_INITIALIZED if an error occured while opening the hardware
      *         module.
      * @return result the interface for the created device.
      */
-    openDevice(Device device) generates (Result retval, IDevice result);
+    openDevice(string device) generates (Result retval, IDevice result);
+
+    /**
+     * Opens the Primary audio device that must be present.
+     * This function is not optional and must return successfully the primary device.
+     *
+     * This device must have the name "primary".
+     *
+     * The telephony stack uses this device to control the audio during a voice call.
+     *
+     * @return retval operation completion status. Must be SUCCESS.
+     *         For debuging, return INVALID_ARGUMENTS if there is no corresponding
+     *         hardware module found, NOT_INITIALIZED if an error occurred
+     *         while opening the hardware module.
+     * @return result the interface for the created device.
+     */
+    openPrimaryDevice() generates (Result retval, IPrimaryDevice result);
 };
diff --git a/audio/4.0/config/audio_policy_configuration.xsd b/audio/4.0/config/audio_policy_configuration.xsd
index 924fb47..34c2b11 100644
--- a/audio/4.0/config/audio_policy_configuration.xsd
+++ b/audio/4.0/config/audio_policy_configuration.xsd
@@ -66,35 +66,6 @@
     <xs:complexType name="globalConfiguration">
         <xs:attribute name="speaker_drc_enabled" type="xs:boolean" use="required"/>
     </xs:complexType>
-    <!-- Enum values of IDevicesFactory::Device
-         TODO: generate from hidl to avoid manual sync. -->
-    <xs:simpleType name="halName">
-        <xs:union>
-            <xs:simpleType>
-                <xs:restriction base="xs:string">
-                    <xs:enumeration value="primary"/>
-                    <xs:enumeration value="a2dp"/>
-                    <xs:enumeration value="usb"/>
-                    <xs:enumeration value="r_submix"/>
-                    <xs:enumeration value="codec_offload"/>
-                    <xs:enumeration value="stub"/>
-                </xs:restriction>
-            </xs:simpleType>
-            <xs:simpleType>
-                <xs:annotation>
-                    <xs:documentation xml:lang="en">
-                        Vendor eXtension names must be in the vx namespace.
-                        Vendor are encouraged to namespace their module names.
-                        Example for an hypothetical Google virtual reality HAL:
-                            <module name="vx_google_vr" halVersion="3.0"/>
-                    </xs:documentation>
-                </xs:annotation>
-                <xs:restriction base="xs:string">
-                    <xs:pattern value="vx_[_a-zA-Z0-9]+"/>
-                </xs:restriction>
-            </xs:simpleType>
-        </xs:union>
-    </xs:simpleType>
     <xs:complexType name="modules">
         <xs:annotation>
             <xs:documentation xml:lang="en">
@@ -133,7 +104,7 @@
                         <xs:element name="devicePorts" type="devicePorts" minOccurs="0"/>
                         <xs:element name="routes" type="routes" minOccurs="0"/>
                     </xs:sequence>
-                    <xs:attribute name="name" type="halName" use="required"/>
+                    <xs:attribute name="name" type="xs:string" use="required"/>
                     <xs:attribute name="halVersion" type="halVersion" use="required"/>
                 </xs:complexType>
                 <xs:unique name="mixPortNameUniqueness">
diff --git a/audio/common/2.0/default/VersionUtils.h b/audio/common/2.0/default/VersionUtils.h
new file mode 100644
index 0000000..60d1f9c
--- /dev/null
+++ b/audio/common/2.0/default/VersionUtils.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H
+
+#include <android/hardware/audio/common/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace common {
+namespace V2_0 {
+namespace implementation {
+
+typedef common::V2_0::AudioDevice AudioDeviceBitfield;
+typedef common::V2_0::AudioChannelMask AudioChannelBitfield;
+typedef common::V2_0::AudioOutputFlag AudioOutputFlagBitfield;
+typedef common::V2_0::AudioInputFlag AudioInputFlagBitfield;
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H
diff --git a/audio/common/4.0/default/Android.bp b/audio/common/4.0/default/Android.bp
new file mode 100644
index 0000000..57b2e01
--- /dev/null
+++ b/audio/common/4.0/default/Android.bp
@@ -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.
+
+cc_library_shared {
+    name: "android.hardware.audio.common@4.0-util",
+    defaults: ["hidl_defaults"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "HidlUtils.cpp",
+    ],
+
+    export_include_dirs: ["."],
+
+    static_libs: [
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libutils",
+        "libhidlbase",
+        "android.hardware.audio.common-util",
+        "android.hardware.audio.common@4.0",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.audio.common-util"
+    ],
+
+    header_libs: [
+        "libaudio_system_headers",
+        "libhardware_headers",
+    ],
+}
diff --git a/audio/common/4.0/default/HidlUtils.cpp b/audio/common/4.0/default/HidlUtils.cpp
new file mode 100644
index 0000000..b66eff9
--- /dev/null
+++ b/audio/common/4.0/default/HidlUtils.cpp
@@ -0,0 +1,21 @@
+/*
+ * 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 "HidlUtils.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <common/all-versions/default/HidlUtils.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/common/4.0/default/HidlUtils.h b/audio/common/4.0/default/HidlUtils.h
new file mode 100644
index 0000000..91e6a9e
--- /dev/null
+++ b/audio/common/4.0/default/HidlUtils.h
@@ -0,0 +1,26 @@
+/*
+ * 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_audio_V4_0_Hidl_Utils_H_
+#define android_hardware_audio_V4_0_Hidl_Utils_H_
+
+#include <android/hardware/audio/common/4.0/types.h>
+
+#define AUDIO_HAL_VERSION V4_0
+#include <common/all-versions/default/HidlUtils.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // android_hardware_audio_V4_0_Hidl_Utils_H_
diff --git a/audio/common/4.0/default/VersionUtils.h b/audio/common/4.0/default/VersionUtils.h
new file mode 100644
index 0000000..b7f2aec
--- /dev/null
+++ b/audio/common/4.0/default/VersionUtils.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H
+
+#include <android/hardware/audio/common/4.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace common {
+namespace V4_0 {
+namespace implementation {
+
+typedef hidl_bitfield<common::V4_0::AudioDevice> AudioDeviceBitfield;
+typedef hidl_bitfield<common::V4_0::AudioChannelMask> AudioChannelBitfield;
+typedef hidl_bitfield<common::V4_0::AudioOutputFlag> AudioOutputFlagBitfield;
+typedef hidl_bitfield<common::V4_0::AudioInputFlag> AudioInputFlagBitfield;
+
+}  // namespace implementation
+}  // namespace V4_0
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H
diff --git a/audio/common/4.0/types.hal b/audio/common/4.0/types.hal
index 4efdea3..e55491d 100644
--- a/audio/common/4.0/types.hal
+++ b/audio/common/4.0/types.hal
@@ -104,8 +104,6 @@
     TTS              = 9,  // Transmitted Through Speaker.  Plays over speaker
                            // only, silent on other devices
     ACCESSIBILITY    = 10, // For accessibility talk back prompts
-    REROUTING        = 11, // For dynamic policy output mixes
-    PATCH            = 12, // For internal audio flinger tracks.  Fixed volume
 };
 
 @export(name="audio_source_t", value_prefix="AUDIO_SOURCE_")
@@ -375,21 +373,21 @@
     OUT_TOP_BACK_LEFT         = 0x8000,
     OUT_TOP_BACK_CENTER       = 0x10000,
     OUT_TOP_BACK_RIGHT        = 0x20000,
-    OUT_TOP_CENTER_LEFT       = 0x40000,
-    OUT_TOP_CENTER_RIGHT      = 0x80000,
+    OUT_TOP_SIDE_LEFT         = 0x40000,
+    OUT_TOP_SIDE_RIGHT        = 0x80000,
 
     OUT_MONO     = OUT_FRONT_LEFT,
     OUT_STEREO   = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT),
     OUT_2POINT1  = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_LOW_FREQUENCY),
     OUT_2POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
-                         OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT),
+                         OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT),
     OUT_2POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
-                         OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT |
+                         OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT |
                          OUT_LOW_FREQUENCY),
     OUT_3POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT |
-                         OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT),
+                         OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT),
     OUT_3POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT |
-                        OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT |
+                        OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT |
                         OUT_LOW_FREQUENCY),
     OUT_QUAD     = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
             OUT_BACK_LEFT | OUT_BACK_RIGHT),
@@ -408,6 +406,10 @@
     OUT_5POINT1_SIDE = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
             OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
             OUT_SIDE_LEFT | OUT_SIDE_RIGHT),
+    OUT_5POINT1POINT2  = (OUT_5POINT1 | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT),
+    OUT_5POINT1POINT4  = (OUT_5POINT1 |
+            OUT_TOP_FRONT_LEFT | OUT_TOP_FRONT_RIGHT |
+            OUT_TOP_BACK_LEFT | OUT_TOP_BACK_RIGHT),
     OUT_6POINT1 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
             OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
             OUT_BACK_LEFT | OUT_BACK_RIGHT |
@@ -417,6 +419,10 @@
             OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
             OUT_BACK_LEFT | OUT_BACK_RIGHT |
             OUT_SIDE_LEFT | OUT_SIDE_RIGHT),
+    OUT_7POINT1POINT2  = (OUT_7POINT1 | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT),
+    OUT_7POINT1POINT4  = (OUT_7POINT1 |
+            OUT_TOP_FRONT_LEFT | OUT_TOP_FRONT_RIGHT |
+            OUT_TOP_BACK_LEFT | OUT_TOP_BACK_RIGHT),
     // Note that the 2.0 OUT_ALL* have been moved to helper functions
 
     /* These are bits only, not complete values */
@@ -450,6 +456,12 @@
     IN_6 = (IN_LEFT | IN_RIGHT |
             IN_FRONT | IN_BACK |
             IN_LEFT_PROCESSED | IN_RIGHT_PROCESSED),
+    IN_2POINT0POINT2 = (IN_LEFT | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT),
+    IN_2POINT1POINT2 = (IN_LEFT | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT |
+            IN_LOW_FREQUENCY),
+    IN_3POINT0POINT2 = (IN_LEFT | IN_CENTER | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT),
+    IN_3POINT1POINT2 = (IN_LEFT | IN_CENTER | IN_RIGHT |
+            IN_TOP_LEFT | IN_TOP_RIGHT | IN_LOW_FREQUENCY),
     IN_5POINT1 = (IN_LEFT | IN_CENTER | IN_RIGHT |
                   IN_BACK_LEFT | IN_BACK_RIGHT | IN_LOW_FREQUENCY),
     IN_VOICE_UPLINK_MONO = (IN_VOICE_UPLINK | IN_MONO),
@@ -657,6 +669,8 @@
 /** Type of audio generated by an application. */
 @export(name="audio_content_type_t", value_prefix="AUDIO_CONTENT_TYPE_")
 enum AudioContentType : uint32_t {
+    // Do not change these values without updating their counterparts
+    // in frameworks/base/media/java/android/media/AudioAttributes.java
     UNKNOWN      = 0,
     SPEECH       = 1,
     MUSIC        = 2,
diff --git a/audio/common/all-versions/default/Android.bp b/audio/common/all-versions/default/Android.bp
index 8f6b74c..4a27bb7 100644
--- a/audio/common/all-versions/default/Android.bp
+++ b/audio/common/all-versions/default/Android.bp
@@ -33,7 +33,11 @@
     ],
 
     header_libs: [
+        "android.hardware.audio.common.util@all-versions",
         "libaudio_system_headers",
         "libhardware_headers",
     ],
+    export_header_lib_headers: [
+        "android.hardware.audio.common.util@all-versions",
+    ]
 }
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
index 1654ac6..f9a5697 100644
--- 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
@@ -47,6 +47,8 @@
                                      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 AudioUsage audioUsageFromHal(const audio_usage_t halUsage);
+    static audio_usage_t audioUsageToHal(const AudioUsage usage);
     static void audioOffloadInfoFromHal(const audio_offload_info_t& halOffload,
                                         AudioOffloadInfo* offload);
     static void audioOffloadInfoToHal(const AudioOffloadInfo& offload,
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
index 935f307..8ab7350 100644
--- 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
@@ -18,6 +18,7 @@
 #error "AUDIO_HAL_VERSION must be set before including this file."
 #endif
 
+#include <common/all-versions/VersionUtils.h>
 #include <string.h>
 
 using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask;
@@ -32,6 +33,8 @@
 using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioStreamType;
 using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioUsage;
 
+using ::android::hardware::audio::common::utils::mkEnumConverter;
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -40,7 +43,7 @@
 
 void HidlUtils::audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config) {
     config->sampleRateHz = halConfig.sample_rate;
-    config->channelMask = AudioChannelMask(halConfig.channel_mask);
+    config->channelMask = mkEnumConverter<AudioChannelMask>(halConfig.channel_mask);
     config->format = AudioFormat(halConfig.format);
     audioOffloadInfoFromHal(halConfig.offload_info, &config->offloadInfo);
     config->frameCount = halConfig.frame_count;
@@ -58,8 +61,8 @@
 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);
+    config->mode = mkEnumConverter<AudioGainMode>(halConfig.mode);
+    config->channelMask = mkEnumConverter<AudioChannelMask>(halConfig.channel_mask);
     for (size_t i = 0; i < sizeof(audio_channel_mask_t) * 8; ++i) {
         config->values[i] = halConfig.values[i];
     }
@@ -79,8 +82,8 @@
 }
 
 void HidlUtils::audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain) {
-    gain->mode = AudioGainMode(halGain.mode);
-    gain->channelMask = AudioChannelMask(halGain.channel_mask);
+    gain->mode = mkEnumConverter<AudioGainMode>(halGain.mode);
+    gain->channelMask = mkEnumConverter<AudioChannelMask>(halGain.channel_mask);
     gain->minValue = halGain.min_value;
     gain->maxValue = halGain.max_value;
     gain->defaultValue = halGain.default_value;
@@ -100,10 +103,26 @@
     halGain->max_ramp_ms = gain.maxRampMs;
 }
 
+AudioUsage HidlUtils::audioUsageFromHal(const audio_usage_t halUsage) {
+    switch (halUsage) {
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+        case AUDIO_USAGE_NOTIFICATION_EVENT:
+            return AudioUsage::NOTIFICATION;
+        default:
+            return static_cast<AudioUsage>(halUsage);
+    }
+}
+
+audio_usage_t HidlUtils::audioUsageToHal(const AudioUsage usage) {
+    return static_cast<audio_usage_t>(usage);
+}
+
 void HidlUtils::audioOffloadInfoFromHal(const audio_offload_info_t& halOffload,
                                         AudioOffloadInfo* offload) {
     offload->sampleRateHz = halOffload.sample_rate;
-    offload->channelMask = AudioChannelMask(halOffload.channel_mask);
+    offload->channelMask = mkEnumConverter<AudioChannelMask>(halOffload.channel_mask);
     offload->format = AudioFormat(halOffload.format);
     offload->streamType = AudioStreamType(halOffload.stream_type);
     offload->bitRatePerSecond = halOffload.bit_rate;
@@ -112,7 +131,7 @@
     offload->isStreaming = halOffload.is_streaming;
     offload->bitWidth = halOffload.bit_width;
     offload->bufferSize = halOffload.offload_buffer_size;
-    offload->usage = static_cast<AudioUsage>(halOffload.usage);
+    offload->usage = audioUsageFromHal(halOffload.usage);
 }
 
 void HidlUtils::audioOffloadInfoToHal(const AudioOffloadInfo& offload,
@@ -128,7 +147,7 @@
     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);
+    halOffload->usage = audioUsageToHal(offload.usage);
 }
 
 void HidlUtils::audioPortConfigFromHal(const struct audio_port_config& halConfig,
@@ -136,9 +155,9 @@
     config->id = halConfig.id;
     config->role = AudioPortRole(halConfig.role);
     config->type = AudioPortType(halConfig.type);
-    config->configMask = AudioPortConfigMask(halConfig.config_mask);
+    config->configMask = mkEnumConverter<AudioPortConfigMask>(halConfig.config_mask);
     config->sampleRateHz = halConfig.sample_rate;
-    config->channelMask = AudioChannelMask(halConfig.channel_mask);
+    config->channelMask = mkEnumConverter<AudioChannelMask>(halConfig.channel_mask);
     config->format = AudioFormat(halConfig.format);
     audioGainConfigFromHal(halConfig.gain, &config->gain);
     switch (halConfig.type) {
@@ -238,7 +257,7 @@
     }
     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->channelMasks[i] = mkEnumConverter<AudioChannelMask>(halPort.channel_masks[i]);
     }
     port->formats.resize(halPort.num_formats);
     for (size_t i = 0; i < halPort.num_formats; ++i) {
@@ -277,8 +296,8 @@
     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)));
+    strncpy(halPort->name, port.name.c_str(), AUDIO_PORT_MAX_NAME_LEN);
+    halPort->name[AUDIO_PORT_MAX_NAME_LEN - 1] = '\0';
     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) {
diff --git a/audio/2.0/default/Android.mk b/audio/common/all-versions/default/service/Android.mk
similarity index 90%
rename from audio/2.0/default/Android.mk
rename to audio/common/all-versions/default/service/Android.mk
index edf1761..43d7fe1 100644
--- a/audio/2.0/default/Android.mk
+++ b/audio/common/all-versions/default/service/Android.mk
@@ -38,8 +38,12 @@
     libutils \
     libhardware \
     android.hardware.audio@2.0 \
+    android.hardware.audio@4.0 \
     android.hardware.audio.common@2.0 \
+    android.hardware.audio.common@4.0 \
     android.hardware.audio.effect@2.0 \
+    android.hardware.audio.effect@4.0 \
+    android.hardware.bluetooth.a2dp@1.0 \
     android.hardware.soundtrigger@2.0 \
     android.hardware.soundtrigger@2.1
 
diff --git a/audio/2.0/default/android.hardware.audio@2.0-service.rc b/audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc
similarity index 100%
rename from audio/2.0/default/android.hardware.audio@2.0-service.rc
rename to audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
new file mode 100644
index 0000000..c7ce638
--- /dev/null
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "audiohalservice"
+
+#include <android/hardware/audio/2.0/IDevicesFactory.h>
+#include <android/hardware/audio/4.0/IDevicesFactory.h>
+#include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
+#include <android/hardware/audio/effect/4.0/IEffectsFactory.h>
+#include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioOffload.h>
+#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
+#include <binder/ProcessState.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+
+using namespace android::hardware;
+using android::OK;
+
+int main(int /* argc */, char* /* argv */ []) {
+    android::ProcessState::initWithDriver("/dev/vndbinder");
+    // start a threadpool for vndbinder interactions
+    android::ProcessState::self()->startThreadPool();
+    configureRpcThreadpool(16, true /*callerWillJoin*/);
+
+    bool fail = registerPassthroughServiceImplementation<audio::V4_0::IDevicesFactory>() != OK &&
+                registerPassthroughServiceImplementation<audio::V2_0::IDevicesFactory>() != OK;
+    LOG_ALWAYS_FATAL_IF(fail, "Could not register audio core API 2.0 nor 4.0");
+
+    fail = registerPassthroughServiceImplementation<audio::effect::V4_0::IEffectsFactory>() != OK &&
+           registerPassthroughServiceImplementation<audio::effect::V2_0::IEffectsFactory>() != OK,
+    LOG_ALWAYS_FATAL_IF(fail, "Could not register audio effect API 2.0 nor 4.0");
+
+    fail = registerPassthroughServiceImplementation<soundtrigger::V2_1::ISoundTriggerHw>() != OK &&
+           registerPassthroughServiceImplementation<soundtrigger::V2_0::ISoundTriggerHw>() != OK,
+    ALOGW_IF(fail, "Could not register soundtrigger API 2.0 nor 2.1");
+
+    fail =
+        registerPassthroughServiceImplementation<bluetooth::a2dp::V1_0::IBluetoothAudioOffload>() !=
+        OK;
+    ALOGW_IF(fail, "Could not register Bluetooth audio offload 1.0");
+
+    joinRpcThreadpool();
+}
diff --git a/audio/common/all-versions/test/utility/include/utility/ReturnIn.h b/audio/common/all-versions/test/utility/include/utility/ReturnIn.h
index 2b92a21..7fd0d4a 100644
--- a/audio/common/all-versions/test/utility/include/utility/ReturnIn.h
+++ b/audio/common/all-versions/test/utility/include/utility/ReturnIn.h
@@ -45,7 +45,7 @@
     template <class Head, class... Tail>
     void set(Head&& head, Tail&&... tail) {
         std::get<sizeof...(ResultStore) - sizeof...(Tail) - 1>(results) = std::forward<Head>(head);
-        set(tail...);
+        set(std::forward<Tail>(tail)...);
     }
     // Trivial case
     void set() {}
@@ -56,7 +56,7 @@
 }  // namespace detail
 
 // Generate the HIDL synchronous callback with a copy policy
-// Input: the variables (lvalue reference) where to save the return values
+// Input: the variables (lvalue references) where to copy the return values
 // Output: the callback to provide to a HIDL call with a synchronous callback
 // The output parameters *will be copied* do not use this function if you have
 // a zero copy policy
diff --git a/audio/common/all-versions/util/include/common/all-versions/VersionUtils.h b/audio/common/all-versions/util/include/common/all-versions/VersionUtils.h
new file mode 100644
index 0000000..70c3d56
--- /dev/null
+++ b/audio/common/all-versions/util/include/common/all-versions/VersionUtils.h
@@ -0,0 +1,67 @@
+/*
+ * 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_audio_common_VersionUtils_H_
+#define android_hardware_audio_common_VersionUtils_H_
+
+#include <hidl/HidlSupport.h>
+#include <type_traits>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace common {
+namespace utils {
+
+/** Similar to static_cast but also casts to hidl_bitfield depending on
+ * return type inference (emulated through user-define conversion).
+ */
+template <class Source, class Destination = Source>
+class EnumConverter {
+   public:
+    static_assert(std::is_enum<Source>::value || std::is_enum<Destination>::value,
+                  "Source or destination should be an enum");
+
+    explicit EnumConverter(Source source) : mSource(source) {}
+
+    operator Destination() const { return static_cast<Destination>(mSource); }
+
+    template <class = std::enable_if_t<std::is_enum<Destination>::value>>
+    operator ::android::hardware::hidl_bitfield<Destination>() {
+        return static_cast<std::underlying_type_t<Destination>>(mSource);
+    }
+
+   private:
+    const Source mSource;
+};
+template <class Destination, class Source>
+auto mkEnumConverter(Source source) {
+    return EnumConverter<Source, Destination>{source};
+}
+
+/** Allows converting an enum to its bitfield or itself. */
+template <class Enum>
+EnumConverter<Enum> mkBitfield(Enum value) {
+    return EnumConverter<Enum>{value};
+}
+
+}  // namespace utils
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_audio_common_VersionUtils_H_
diff --git a/audio/core/2.0/default/Android.bp b/audio/core/2.0/default/Android.bp
index 9847886..625df74 100644
--- a/audio/core/2.0/default/Android.bp
+++ b/audio/core/2.0/default/Android.bp
@@ -14,6 +14,10 @@
         "StreamOut.cpp",
     ],
 
+    cflags: [
+        "-DAUDIO_HAL_VERSION_2_0",
+    ],
+
     defaults: ["hidl_defaults"],
 
     export_include_dirs: ["include"],
diff --git a/audio/core/4.0/default/Android.bp b/audio/core/4.0/default/Android.bp
new file mode 100644
index 0000000..8e41545
--- /dev/null
+++ b/audio/core/4.0/default/Android.bp
@@ -0,0 +1,53 @@
+cc_library_shared {
+    name: "android.hardware.audio@4.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",
+    ],
+
+    cflags: [
+        "-DAUDIO_HAL_VERSION_4_0",
+    ],
+
+    defaults: ["hidl_defaults"],
+
+    export_include_dirs: ["include"],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libfmq",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.audio@4.0",
+        "android.hardware.audio.common@4.0",
+        "android.hardware.audio.common@4.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/4.0/default/Conversions.cpp b/audio/core/4.0/default/Conversions.cpp
new file mode 100644
index 0000000..4f18744
--- /dev/null
+++ b/audio/core/4.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/4.0/default/Conversions.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/Conversions.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/4.0/default/Device.cpp b/audio/core/4.0/default/Device.cpp
new file mode 100644
index 0000000..26f9ab4
--- /dev/null
+++ b/audio/core/4.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/4.0/default/Device.h"
+#include <HidlUtils.h>
+#include "core/4.0/default/Conversions.h"
+#include "core/4.0/default/StreamIn.h"
+#include "core/4.0/default/StreamOut.h"
+#include "core/all-versions/default/Util.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/Device.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/4.0/default/DevicesFactory.cpp b/audio/core/4.0/default/DevicesFactory.cpp
new file mode 100644
index 0000000..cb8a3c3
--- /dev/null
+++ b/audio/core/4.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/4.0/default/DevicesFactory.h"
+#include "core/4.0/default/Device.h"
+#include "core/4.0/default/PrimaryDevice.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/DevicesFactory.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/4.0/default/ParametersUtil.cpp b/audio/core/4.0/default/ParametersUtil.cpp
new file mode 100644
index 0000000..5c1b1c4
--- /dev/null
+++ b/audio/core/4.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/4.0/default/ParametersUtil.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/ParametersUtil.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/4.0/default/PrimaryDevice.cpp b/audio/core/4.0/default/PrimaryDevice.cpp
new file mode 100644
index 0000000..0294b4d
--- /dev/null
+++ b/audio/core/4.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/4.0/default/PrimaryDevice.h"
+#include "core/all-versions/default/Util.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/PrimaryDevice.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/4.0/default/Stream.cpp b/audio/core/4.0/default/Stream.cpp
new file mode 100644
index 0000000..30b3454
--- /dev/null
+++ b/audio/core/4.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/4.0/default/Stream.h"
+#include "common/all-versions/default/EffectMap.h"
+#include "core/4.0/default/Conversions.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/Stream.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/4.0/default/StreamIn.cpp b/audio/core/4.0/default/StreamIn.cpp
new file mode 100644
index 0000000..18719b5
--- /dev/null
+++ b/audio/core/4.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/4.0/default/StreamIn.h"
+#include "core/all-versions/default/Util.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/StreamIn.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/4.0/default/StreamOut.cpp b/audio/core/4.0/default/StreamOut.cpp
new file mode 100644
index 0000000..11c8fde
--- /dev/null
+++ b/audio/core/4.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/4.0/default/StreamOut.h"
+#include "core/all-versions/default/Util.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/StreamOut.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/core/4.0/default/include/core/4.0/default/Conversions.h b/audio/core/4.0/default/include/core/4.0/default/Conversions.h
new file mode 100644
index 0000000..32c2f88
--- /dev/null
+++ b/audio/core/4.0/default/include/core/4.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_V4_0_CONVERSIONS_H_
+#define ANDROID_HARDWARE_AUDIO_V4_0_CONVERSIONS_H_
+
+#include <android/hardware/audio/4.0/types.h>
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/Conversions.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V4_0_CONVERSIONS_H_
diff --git a/audio/core/4.0/default/include/core/4.0/default/Device.h b/audio/core/4.0/default/include/core/4.0/default/Device.h
new file mode 100644
index 0000000..770d606
--- /dev/null
+++ b/audio/core/4.0/default/include/core/4.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_V4_0_DEVICE_H
+#define ANDROID_HARDWARE_AUDIO_V4_0_DEVICE_H
+
+#include <android/hardware/audio/4.0/IDevice.h>
+
+#include "ParametersUtil.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/Device.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V4_0_DEVICE_H
diff --git a/audio/core/4.0/default/include/core/4.0/default/DevicesFactory.h b/audio/core/4.0/default/include/core/4.0/default/DevicesFactory.h
new file mode 100644
index 0000000..200e59d
--- /dev/null
+++ b/audio/core/4.0/default/include/core/4.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_V4_0_DEVICESFACTORY_H
+#define ANDROID_HARDWARE_AUDIO_V4_0_DEVICESFACTORY_H
+
+#include <android/hardware/audio/4.0/IDevicesFactory.h>
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/DevicesFactory.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V4_0_DEVICESFACTORY_H
diff --git a/audio/core/4.0/default/include/core/4.0/default/ParametersUtil.h b/audio/core/4.0/default/include/core/4.0/default/ParametersUtil.h
new file mode 100644
index 0000000..fa31ee9
--- /dev/null
+++ b/audio/core/4.0/default/include/core/4.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_V4_0_PARAMETERS_UTIL_H_
+#define ANDROID_HARDWARE_AUDIO_V4_0_PARAMETERS_UTIL_H_
+
+#include <android/hardware/audio/4.0/types.h>
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/ParametersUtil.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V4_0_PARAMETERS_UTIL_H_
diff --git a/audio/core/4.0/default/include/core/4.0/default/PrimaryDevice.h b/audio/core/4.0/default/include/core/4.0/default/PrimaryDevice.h
new file mode 100644
index 0000000..e7f846b
--- /dev/null
+++ b/audio/core/4.0/default/include/core/4.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_V4_0_PRIMARYDEVICE_H
+#define ANDROID_HARDWARE_AUDIO_V4_0_PRIMARYDEVICE_H
+
+#include <android/hardware/audio/4.0/IPrimaryDevice.h>
+
+#include "Device.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/PrimaryDevice.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V4_0_PRIMARYDEVICE_H
diff --git a/audio/core/4.0/default/include/core/4.0/default/Stream.h b/audio/core/4.0/default/include/core/4.0/default/Stream.h
new file mode 100644
index 0000000..afad80f
--- /dev/null
+++ b/audio/core/4.0/default/include/core/4.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_V4_0_STREAM_H
+#define ANDROID_HARDWARE_AUDIO_V4_0_STREAM_H
+
+#include <android/hardware/audio/4.0/IStream.h>
+
+#include "ParametersUtil.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/Stream.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V4_0_STREAM_H
diff --git a/audio/core/4.0/default/include/core/4.0/default/StreamIn.h b/audio/core/4.0/default/include/core/4.0/default/StreamIn.h
new file mode 100644
index 0000000..151f03f
--- /dev/null
+++ b/audio/core/4.0/default/include/core/4.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_V4_0_STREAMIN_H
+#define ANDROID_HARDWARE_AUDIO_V4_0_STREAMIN_H
+
+#include <android/hardware/audio/4.0/IStreamIn.h>
+
+#include "Device.h"
+#include "Stream.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/StreamIn.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V4_0_STREAMIN_H
diff --git a/audio/core/4.0/default/include/core/4.0/default/StreamOut.h b/audio/core/4.0/default/include/core/4.0/default/StreamOut.h
new file mode 100644
index 0000000..dbf3bd1
--- /dev/null
+++ b/audio/core/4.0/default/include/core/4.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_V4_0_STREAMOUT_H
+#define ANDROID_HARDWARE_AUDIO_V4_0_STREAMOUT_H
+
+#include <android/hardware/audio/4.0/IStreamOut.h>
+
+#include "Device.h"
+#include "Stream.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <core/all-versions/default/StreamOut.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_V4_0_STREAMOUT_H
diff --git a/audio/core/4.0/vts/OWNERS b/audio/core/4.0/vts/OWNERS
new file mode 100644
index 0000000..8711a9f
--- /dev/null
+++ b/audio/core/4.0/vts/OWNERS
@@ -0,0 +1,5 @@
+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/core/4.0/vts/functional/Android.bp b/audio/core/4.0/vts/functional/Android.bp
new file mode 100644
index 0000000..dde3e7b
--- /dev/null
+++ b/audio/core/4.0/vts/functional/Android.bp
@@ -0,0 +1,36 @@
+//
+// 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_test {
+    name: "VtsHalAudioV4_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "AudioPrimaryHidlHalTest.cpp",
+        "ValidateAudioConfiguration.cpp"
+    ],
+    static_libs: [
+        "android.hardware.audio.common.test.utility",
+        "android.hardware.audio@4.0",
+        "android.hardware.audio.common@4.0",
+        "libxml2",
+    ],
+    shared_libs: [
+        "libicuuc",
+    ],
+    header_libs: [
+        "android.hardware.audio.common.util@all-versions",
+    ],
+}
diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
new file mode 100644
index 0000000..a568a3c
--- /dev/null
+++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -0,0 +1,1324 @@
+/*
+ * 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 "VtsHalAudioV4_0TargetTest"
+
+#include <algorithm>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <initializer_list>
+#include <limits>
+#include <string>
+#include <vector>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include <android-base/logging.h>
+
+#include <android/hardware/audio/4.0/IDevice.h>
+#include <android/hardware/audio/4.0/IDevicesFactory.h>
+#include <android/hardware/audio/4.0/IPrimaryDevice.h>
+#include <android/hardware/audio/4.0/types.h>
+#include <android/hardware/audio/common/4.0/types.h>
+
+#include <common/all-versions/VersionUtils.h>
+
+#include "utility/AssertOk.h"
+#include "utility/Documentation.h"
+#include "utility/EnvironmentTearDown.h"
+#define AUDIO_HAL_VERSION V4_0
+#include "utility/PrettyPrintAudioTypes.h"
+#include "utility/ReturnIn.h"
+
+using std::initializer_list;
+using std::string;
+using std::to_string;
+using std::vector;
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::hidl_bitfield;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::audio::V4_0::AudioDrain;
+using ::android::hardware::audio::V4_0::DeviceAddress;
+using ::android::hardware::audio::V4_0::IDevice;
+using ::android::hardware::audio::V4_0::IPrimaryDevice;
+using TtyMode = ::android::hardware::audio::V4_0::IPrimaryDevice::TtyMode;
+using ::android::hardware::audio::V4_0::IDevicesFactory;
+using ::android::hardware::audio::V4_0::IStream;
+using ::android::hardware::audio::V4_0::IStreamIn;
+using ::android::hardware::audio::V4_0::TimeSpec;
+using ReadParameters = ::android::hardware::audio::V4_0::IStreamIn::ReadParameters;
+using ReadStatus = ::android::hardware::audio::V4_0::IStreamIn::ReadStatus;
+using ::android::hardware::audio::V4_0::IStreamOut;
+using ::android::hardware::audio::V4_0::IStreamOutCallback;
+using ::android::hardware::audio::V4_0::MmapBufferInfo;
+using ::android::hardware::audio::V4_0::MmapPosition;
+using ::android::hardware::audio::V4_0::ParameterValue;
+using ::android::hardware::audio::V4_0::Result;
+using ::android::hardware::audio::V4_0::SourceMetadata;
+using ::android::hardware::audio::V4_0::SinkMetadata;
+using ::android::hardware::audio::common::V4_0::AudioChannelMask;
+using ::android::hardware::audio::common::V4_0::AudioConfig;
+using ::android::hardware::audio::common::V4_0::AudioDevice;
+using ::android::hardware::audio::common::V4_0::AudioFormat;
+using ::android::hardware::audio::common::V4_0::AudioHandleConsts;
+using ::android::hardware::audio::common::V4_0::AudioHwSync;
+using ::android::hardware::audio::common::V4_0::AudioInputFlag;
+using ::android::hardware::audio::common::V4_0::AudioIoHandle;
+using ::android::hardware::audio::common::V4_0::AudioMode;
+using ::android::hardware::audio::common::V4_0::AudioOffloadInfo;
+using ::android::hardware::audio::common::V4_0::AudioOutputFlag;
+using ::android::hardware::audio::common::V4_0::AudioSource;
+using ::android::hardware::audio::common::V4_0::ThreadInfo;
+using ::android::hardware::audio::common::utils::mkBitfield;
+
+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 AudioHidlTestEnvironment* environment;
+
+class HidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   protected:
+    // Convenient member to store results
+    Result res;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+////////////////////// getService audio_devices_factory //////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+// Test all audio devices
+class AudioHidlTest : public HidlTest {
+   public:
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp());  // setup base
+
+        if (devicesFactory == nullptr) {
+            environment->registerTearDown([] { devicesFactory.clear(); });
+            devicesFactory = ::testing::VtsHalHidlTargetTestBase::getService<IDevicesFactory>(
+                environment->getServiceName<IDevicesFactory>("default"));
+        }
+        ASSERT_TRUE(devicesFactory != nullptr);
+    }
+
+   protected:
+    // Cache the devicesFactory retrieval to speed up each test by ~0.5s
+    static sp<IDevicesFactory> devicesFactory;
+};
+sp<IDevicesFactory> AudioHidlTest::devicesFactory;
+
+TEST_F(AudioHidlTest, GetAudioDevicesFactoryService) {
+    doc::test("test the getService (called in SetUp)");
+}
+
+TEST_F(AudioHidlTest, OpenDeviceInvalidParameter) {
+    doc::test("test passing an invalid parameter to openDevice");
+    Result result;
+    sp<IDevice> device;
+    ASSERT_OK(devicesFactory->openDevice("Non existing device", returnIn(result, device)));
+    ASSERT_EQ(Result::INVALID_ARGUMENTS, result);
+    ASSERT_TRUE(device == nullptr);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+/////////////////////////////// openDevice primary ///////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+// Test the primary device
+class AudioPrimaryHidlTest : public AudioHidlTest {
+   public:
+    /** Primary HAL test are NOT thread safe. */
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUp());  // setup base
+
+        if (device == nullptr) {
+            Result result;
+            sp<IDevice> baseDevice;
+            ASSERT_OK(devicesFactory->openDevice("primary", returnIn(result, baseDevice)));
+            ASSERT_OK(result);
+            ASSERT_TRUE(baseDevice != nullptr);
+
+            environment->registerTearDown([] { device.clear(); });
+            device = IPrimaryDevice::castFrom(baseDevice);
+            ASSERT_TRUE(device != nullptr);
+        }
+    }
+
+   protected:
+    // Cache the device opening to speed up each test by ~0.5s
+    static sp<IPrimaryDevice> device;
+};
+sp<IPrimaryDevice> AudioPrimaryHidlTest::device;
+
+TEST_F(AudioPrimaryHidlTest, OpenPrimaryDevice) {
+    doc::test("Test the openDevice (called in SetUp)");
+}
+
+TEST_F(AudioPrimaryHidlTest, Init) {
+    doc::test("Test that the audio primary hal initialized correctly");
+    ASSERT_OK(device->initCheck());
+}
+
+//////////////////////////////////////////////////////////////////////////////
+///////////////////// {set,get}{Master,Mic}{Mute,Volume} /////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+template <class Property>
+class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest {
+   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 = {}) {
+        Property initialValue;  // Save initial value to restore it at the end
+                                // of the test
+        ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue)));
+        ASSERT_OK(res);
+
+        for (Property setValue : valuesToTest) {
+            SCOPED_TRACE("Test " + propertyName + " getter and setter for " +
+                         testing::PrintToString(setValue));
+            ASSERT_OK((device.get()->*setter)(setValue));
+            Property getValue;
+            // Make sure the getter returns the same value just set
+            ASSERT_OK((device.get()->*getter)(returnIn(res, getValue)));
+            ASSERT_OK(res);
+            EXPECT_EQ(setValue, getValue);
+        }
+
+        for (Property invalidValue : invalidValues) {
+            SCOPED_TRACE("Try to set " + propertyName + " with the invalid value " +
+                         testing::PrintToString(invalidValue));
+            EXPECT_RESULT(Result::INVALID_ARGUMENTS, (device.get()->*setter)(invalidValue));
+        }
+
+        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,
+                               Setter setter, Getter getter,
+                               const vector<Property>& invalidValues = {}) {
+        doc::test("Test the optional " + propertyName + " getters and setter");
+        {
+            SCOPED_TRACE("Test feature support by calling the getter");
+            Property initialValue;
+            ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue)));
+            if (res == Result::NOT_SUPPORTED) {
+                doc::partialTest(propertyName + " getter is not supported");
+                return;
+            }
+            ASSERT_OK(res);  // If it is supported it must succeed
+        }
+        // The feature is supported, test it
+        testAccessors(propertyName, valuesToTest, setter, getter, invalidValues);
+    }
+};
+
+using BoolAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<bool>;
+
+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);
+    // TODO: check that the mic is really muted (all sample are 0)
+}
+
+TEST_F(BoolAccessorPrimaryHidlTest, MasterMuteTest) {
+    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);
+    // 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()});
+    // TODO: check that the master volume is really changed
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////// AudioPatches ////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+class AudioPatchPrimaryHidlTest : public AudioPrimaryHidlTest {
+   protected:
+    bool areAudioPatchesSupported() {
+        auto result = device->supportsAudioPatches();
+        EXPECT_IS_OK(result);
+        return result;
+    }
+};
+
+TEST_F(AudioPatchPrimaryHidlTest, AudioPatches) {
+    doc::test("Test if audio patches are supported");
+    if (!areAudioPatchesSupported()) {
+        doc::partialTest("Audio patches are not supported");
+        return;
+    }
+    // TODO: test audio patches
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////// Required and recommended audio format support ///////////////
+// From:
+// https://source.android.com/compatibility/android-cdd.html#5_4_audio_recording
+// From:
+// https://source.android.com/compatibility/android-cdd.html#5_5_audio_playback
+/////////// TODO: move to the beginning of the file for easier update ////////
+//////////////////////////////////////////////////////////////////////////////
+
+class AudioConfigPrimaryTest : public AudioPatchPrimaryHidlTest {
+   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});
+    }
+
+    static const vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
+        return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
+                                  {24000, 48000}, {AudioFormat::PCM_16_BIT});
+    }
+
+    static const vector<AudioConfig> getSupportedPlaybackAudioConfig() {
+        // TODO: retrieve audio config supported by the platform
+        // as declared in the policy configuration
+        return {};
+    }
+
+    static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
+        return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100},
+                                  {AudioFormat::PCM_16_BIT});
+    }
+    static const vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
+        return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000},
+                                  {AudioFormat::PCM_16_BIT});
+    }
+    static const vector<AudioConfig> getSupportedCaptureAudioConfig() {
+        // TODO: retrieve audio config supported by the platform
+        // as declared in the policy configuration
+        return {};
+    }
+
+   private:
+    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) {
+                for (auto format : formats) {
+                    AudioConfig config{};
+                    // leave offloadInfo to 0
+                    config.channelMask = mkBitfield(channelMask);
+                    config.sampleRateHz = sampleRate;
+                    config.format = format;
+                    // FIXME: leave frameCount to 0 ?
+                    configs.push_back(config);
+                }
+            }
+        }
+        return configs;
+    }
+};
+
+/** Generate a test name based on an audio config.
+ *
+ * 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) {
+    const AudioConfig& config = info.param;
+    return to_string(info.index) + "__" + to_string(config.sampleRateHz) + "_" +
+           // "MONO" is more clear than "FRONT_LEFT"
+           ((config.channelMask == mkBitfield(AudioChannelMask::OUT_MONO) ||
+             config.channelMask == mkBitfield(AudioChannelMask::IN_MONO))
+                ? "MONO"
+                : ::testing::PrintToString(config.channelMask));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+///////////////////////////// getInputBufferSize /////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+// FIXME: execute input test only if platform declares
+// android.hardware.microphone
+//        how to get this value ? is it a property ???
+
+class AudioCaptureConfigPrimaryTest : public AudioConfigPrimaryTest,
+                                      public ::testing::WithParamInterface<AudioConfig> {
+   protected:
+    void inputBufferSizeTest(const AudioConfig& audioConfig, bool supportRequired) {
+        uint64_t bufferSize;
+        ASSERT_OK(device->getInputBufferSize(audioConfig, returnIn(res, bufferSize)));
+
+        switch (res) {
+            case Result::INVALID_ARGUMENTS:
+                EXPECT_FALSE(supportRequired);
+                break;
+            case Result::OK:
+                // Check that the buffer is of a sane size
+                // For now only that it is > 0
+                EXPECT_GT(bufferSize, uint64_t(0));
+                break;
+            default:
+                FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
+        }
+    }
+};
+
+// Test that the required capture config and those declared in the policy are
+// indeed supported
+class RequiredInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
+TEST_P(RequiredInputBufferSizeTest, RequiredInputBufferSizeTest) {
+    doc::test(
+        "Input buffer size must be retrievable for a format with required "
+        "support.");
+    inputBufferSizeTest(GetParam(), true);
+}
+INSTANTIATE_TEST_CASE_P(
+    RequiredInputBufferSize, RequiredInputBufferSizeTest,
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
+    &generateTestName);
+INSTANTIATE_TEST_CASE_P(
+    SupportedInputBufferSize, RequiredInputBufferSizeTest,
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
+    &generateTestName);
+
+// Test that the recommended capture config are supported or lead to a
+// INVALID_ARGUMENTS return
+class OptionalInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
+TEST_P(OptionalInputBufferSizeTest, OptionalInputBufferSizeTest) {
+    doc::test(
+        "Input buffer size should be retrievable for a format with recommended "
+        "support.");
+    inputBufferSizeTest(GetParam(), false);
+}
+INSTANTIATE_TEST_CASE_P(
+    RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
+    &generateTestName);
+
+//////////////////////////////////////////////////////////////////////////////
+/////////////////////////////// setScreenState ///////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+TEST_F(AudioPrimaryHidlTest, setScreenState) {
+    doc::test("Check that the hal can receive the screen state");
+    for (bool turnedOn : {false, true, true, false, false}) {
+        auto ret = device->setScreenState(turnedOn);
+        ASSERT_IS_OK(ret);
+        Result result = ret;
+        auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
+        ASSERT_RESULT(okOrNotSupported, result);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// {get,set}Parameters /////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+TEST_F(AudioPrimaryHidlTest, getParameters) {
+    doc::test("Check that the hal can set and get parameters");
+    hidl_vec<ParameterValue> context;
+    hidl_vec<hidl_string> keys;
+    hidl_vec<ParameterValue> values;
+    ASSERT_OK(device->getParameters(context, keys, returnIn(res, values)));
+    ASSERT_OK(device->setParameters(context, values));
+    values.resize(0);
+    ASSERT_OK(device->setParameters(context, values));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////// debugDebug //////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+template <class DebugDump>
+static void testDebugDump(DebugDump debugDump) {
+    // File descriptors to our pipe. fds[0] corresponds to the read end and
+    // fds[1] to the write end.
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    // Make sure that the pipe is at least 1 MB in size. The test process runs
+    // in su domain, so it should be safe to make this call.
+    fcntl(fds[0], F_SETPIPE_SZ, 1 << 20);
+
+    // Wrap the temporary file file descriptor in a native handle
+    auto* nativeHandle = native_handle_create(1, 0);
+    ASSERT_NE(nullptr, nativeHandle);
+    nativeHandle->data[0] = fds[1];
+
+    // Wrap this native handle in a hidl handle
+    hidl_handle handle;
+    handle.setTo(nativeHandle, false /*take ownership*/);
+
+    ASSERT_OK(debugDump(handle));
+
+    // Check that at least one bit was written by the hal
+    // TODO: debugDump does not return a Result.
+    // This mean that the hal can not report that it not implementing the
+    // function.
+    char buff;
+    if (read(fds[0], &buff, 1) != 1) {
+        doc::note("debugDump does not seem implemented");
+    }
+    EXPECT_EQ(0, close(fds[0])) << errno;
+    EXPECT_EQ(0, close(fds[1])) << errno;
+}
+
+TEST_F(AudioPrimaryHidlTest, DebugDump) {
+    doc::test("Check that the hal can dump its state without error");
+    testDebugDump([](const auto& handle) { return device->debug(handle, {/* options */}); });
+}
+
+TEST_F(AudioPrimaryHidlTest, DebugDumpInvalidArguments) {
+    doc::test("Check that the hal dump doesn't crash on invalid arguments");
+    ASSERT_OK(device->debug(hidl_handle(), {/* options */}));
+}
+
+TEST_F(AudioPrimaryHidlTest, SetConnectedState) {
+    doc::test("Check that the HAL can be notified of device connection and deconnection");
+    using AD = AudioDevice;
+    for (auto deviceType : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
+        SCOPED_TRACE("device=" + ::testing::PrintToString(deviceType));
+        for (bool state : {true, false}) {
+            SCOPED_TRACE("state=" + ::testing::PrintToString(state));
+            DeviceAddress address = {};
+            address.device = deviceType;
+            auto ret = device->setConnectedState(address, state);
+            ASSERT_TRUE(ret.isOk());
+            if (res == Result::NOT_SUPPORTED) {
+                doc::partialTest("setConnectedState is not supported");
+                return;
+            }
+            ASSERT_OK(res);
+        }
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+////////////////////////// open{Output,Input}Stream //////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+template <class Stream>
+class OpenStreamTest : public AudioConfigPrimaryTest,
+                       public ::testing::WithParamInterface<AudioConfig> {
+   protected:
+    template <class Open>
+    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;
+        AudioConfig suggestedConfig{};
+        ASSERT_OK(openStream(ioHandle, config, returnIn(res, stream, suggestedConfig)));
+
+        // TODO: only allow failure for RecommendedPlaybackAudioConfig
+        switch (res) {
+            case Result::OK:
+                ASSERT_TRUE(stream != nullptr);
+                audioConfig = config;
+                break;
+            case Result::INVALID_ARGUMENTS:
+                ASSERT_TRUE(stream == nullptr);
+                AudioConfig suggestedConfigRetry;
+                // Could not open stream with config, try again with the
+                // suggested one
+                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);
+        }
+        open = true;
+    }
+
+    Return<Result> closeStream() {
+        open = false;
+        return stream->close();
+    }
+
+   private:
+    void TearDown() override {
+        if (open) {
+            ASSERT_OK(stream->close());
+        }
+    }
+
+   protected:
+    AudioConfig audioConfig;
+    DeviceAddress address = {};
+    sp<Stream> stream;
+    bool open = false;
+};
+
+////////////////////////////// openOutputStream //////////////////////////////
+
+class OutputStreamTest : public OpenStreamTest<IStreamOut> {
+    virtual void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
+        address.device = AudioDevice::OUT_DEFAULT;
+        const AudioConfig& config = GetParam();
+        // TODO: test all flag combination
+        auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
+        SourceMetadata metadata = {{{}}};  // create on track metadata
+        testOpen(
+            [&](AudioIoHandle handle, AudioConfig config, auto cb) {
+                return device->openOutputStream(handle, address, config, flags, metadata, cb);
+            },
+            config);
+    }
+};
+TEST_P(OutputStreamTest, OpenOutputStreamTest) {
+    doc::test(
+        "Check that output streams can be open with the required and "
+        "recommended config");
+    // Open done in SetUp
+}
+INSTANTIATE_TEST_CASE_P(
+    RequiredOutputStreamConfigSupport, OutputStreamTest,
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportPlaybackAudioConfig()),
+    &generateTestName);
+INSTANTIATE_TEST_CASE_P(
+    SupportedOutputStreamConfig, OutputStreamTest,
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedPlaybackAudioConfig()),
+    &generateTestName);
+
+INSTANTIATE_TEST_CASE_P(
+    RecommendedOutputStreamConfigSupport, OutputStreamTest,
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportPlaybackAudioConfig()),
+    &generateTestName);
+
+////////////////////////////// openInputStream //////////////////////////////
+
+class InputStreamTest : public OpenStreamTest<IStreamIn> {
+    virtual void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
+        address.device = AudioDevice::IN_DEFAULT;
+        const AudioConfig& config = GetParam();
+        // TODO: test all supported flags and source
+        auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
+        SinkMetadata metadata = {{{AudioSource::DEFAULT, 1}}};
+        testOpen(
+            [&](AudioIoHandle handle, AudioConfig config, auto cb) {
+                return device->openInputStream(handle, address, config, flags, metadata, cb);
+            },
+            config);
+    }
+};
+
+TEST_P(InputStreamTest, OpenInputStreamTest) {
+    doc::test(
+        "Check that input streams can be open with the required and "
+        "recommended config");
+    // Open done in setup
+}
+INSTANTIATE_TEST_CASE_P(
+    RequiredInputStreamConfigSupport, InputStreamTest,
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
+    &generateTestName);
+INSTANTIATE_TEST_CASE_P(
+    SupportedInputStreamConfig, InputStreamTest,
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
+    &generateTestName);
+
+INSTANTIATE_TEST_CASE_P(
+    RecommendedInputStreamConfigSupport, InputStreamTest,
+    ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
+    &generateTestName);
+
+//////////////////////////////////////////////////////////////////////////////
+////////////////////////////// IStream getters ///////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/** Unpack the provided result.
+ * If the result is not OK, register a failure and return an undefined value. */
+template <class R>
+static R extract(Return<R> ret) {
+    if (!ret.isOk()) {
+        EXPECT_IS_OK(ret);
+        return R{};
+    }
+    return ret;
+}
+
+/* Could not find a way to write a test for two parametrized class fixure
+ * thus use this macro do duplicate tests for Input and Output stream */
+#define TEST_IO_STREAM(test_name, documentation, code) \
+    TEST_P(InputStreamTest, test_name) {               \
+        doc::test(documentation);                      \
+        code;                                          \
+    }                                                  \
+    TEST_P(OutputStreamTest, test_name) {              \
+        doc::test(documentation);                      \
+        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(GetSampleRate, "Check that the stream sample rate == the one it was opened with",
+               ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
+
+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",
+               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",
+               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())));
+
+template <class Property, class CapablityGetter>
+static void testCapabilityGetter(const string& name, IStream* stream,
+                                 CapablityGetter capablityGetter,
+                                 Return<Property> (IStream::*getter)(),
+                                 Return<Result> (IStream::*setter)(Property),
+                                 bool currentMustBeSupported = true) {
+    hidl_vec<Property> capabilities;
+    auto ret = capablityGetter(stream, capabilities);
+    if (ret == Result::NOT_SUPPORTED) {
+        doc::partialTest(name + " is not supported");
+        return;
+    };
+    ASSERT_OK(ret);
+
+    if (currentMustBeSupported) {
+        Property currentValue = extract((stream->*getter)());
+        EXPECT_NE(std::find(capabilities.begin(), capabilities.end(), currentValue),
+                  capabilities.end())
+            << "current " << name << " is not in the list of the supported ones "
+            << toString(capabilities);
+    }
+
+    // Check that all declared supported values are indeed supported
+    for (auto capability : capabilities) {
+        auto ret = (stream->*setter)(capability);
+        ASSERT_TRUE(ret.isOk());
+        if (ret == Result::NOT_SUPPORTED) {
+            doc::partialTest("Setter is not supported");
+            return;
+        }
+        ASSERT_OK(ret);
+        ASSERT_EQ(capability, extract((stream->*getter)()));
+    }
+}
+
+Result getSupportedSampleRates(IStream* stream, hidl_vec<uint32_t>& rates) {
+    Result res;
+    EXPECT_OK(stream->getSupportedSampleRates(extract(stream->getFormat()), returnIn(res, rates)));
+    return res;
+}
+
+Result getSupportedChannelMasks(IStream* stream,
+                                hidl_vec<hidl_bitfield<AudioChannelMask>>& channels) {
+    Result res;
+    EXPECT_OK(
+        stream->getSupportedSampleRates(extract(stream->getFormat()), returnIn(res, channels)));
+    return res;
+}
+
+Result getSupportedFormats(IStream* stream, hidl_vec<AudioFormat>& capabilities) {
+    EXPECT_OK(stream->getSupportedFormats(returnIn(capabilities)));
+    // TODO: this should be an optional function
+    return Result::OK;
+}
+
+TEST_IO_STREAM(SupportedSampleRate, "Check that the stream sample rate is declared as supported",
+               testCapabilityGetter("getSupportedSampleRate", stream.get(),
+                                    &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",
+               testCapabilityGetter("getSupportedChannelMask", stream.get(),
+                                    &getSupportedChannelMasks, &IStream::getChannelMask,
+                                    &IStream::setChannelMask))
+
+TEST_IO_STREAM(SupportedFormat, "Check that the stream format is declared as supported",
+               testCapabilityGetter("getSupportedFormat", stream.get(), &getSupportedFormats,
+                                    &IStream::getFormat, &IStream::setFormat))
+
+static void testGetDevice(IStream* stream, AudioDevice expectedDevice) {
+    hidl_vec<DeviceAddress> devices;
+    Result res;
+    ASSERT_OK(stream->getDevices(returnIn(res, devices)));
+    if (res == Result::NOT_SUPPORTED) {
+        return doc::partialTest("GetDevices is not supported");
+    }
+    // The stream was constructed with one device, thus getDevices must only return one
+    ASSERT_EQ(1U, devices.size());
+    AudioDevice device = devices[0].device;
+    ASSERT_TRUE(device == expectedDevice)
+        << "Expected: " << ::testing::PrintToString(expectedDevice)
+        << "\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))
+
+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;
+    EXPECT_OK(stream->setDevices({otherAddress}));
+
+    ASSERT_OK(stream->setDevices({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))
+
+static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
+    uint32_t sampleRateHz;
+    hidl_bitfield<AudioChannelMask> mask;
+    AudioFormat format;
+
+    stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
+
+    // FIXME: the qcom hal it does not currently negotiate the sampleRate &
+    // channel mask
+    EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz);
+    EXPECT_EQ(expectedConfig.channelMask, mask);
+    EXPECT_EQ(expectedConfig.format, format);
+}
+
+TEST_IO_STREAM(GetAudioProperties,
+               "Check that the stream audio properties == the ones it was opened with",
+               testGetAudioProperties(stream.get(), audioConfig))
+
+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)))
+
+static void checkGetHwAVSync(IDevice* device) {
+    Result res;
+    AudioHwSync sync;
+    ASSERT_OK(device->getHwAvSync(returnIn(res, sync)));
+    if (res == Result::NOT_SUPPORTED) {
+        return doc::partialTest("getHwAvSync is not supported");
+    }
+    ASSERT_OK(res);
+}
+TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail", checkGetHwAVSync(device.get()));
+
+static void checkGetNoParameter(IStream* stream, hidl_vec<hidl_string> keys,
+                                initializer_list<Result> expectedResults) {
+    hidl_vec<ParameterValue> context;
+    hidl_vec<ParameterValue> parameters;
+    Result res;
+    ASSERT_OK(stream->getParameters(context, keys, returnIn(res, parameters)));
+    ASSERT_RESULT(expectedResults, res);
+    if (res == Result::OK) {
+        for (auto& parameter : parameters) {
+            ASSERT_EQ(0U, parameter.value.size()) << toString(parameter);
+        }
+    }
+}
+
+/* Get/Set parameter is intended to be an opaque channel between vendors app and
+ * their HALs.
+ * Thus can not be meaningfully tested.
+ */
+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 */,
+                                   {Result::NOT_SUPPORTED}))
+
+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(DebugDump, "Check that a stream can dump its state without error",
+               testDebugDump([this](const auto& handle) { return stream->debug(handle, {}); }))
+
+TEST_IO_STREAM(DebugDumpInvalidArguments,
+               "Check that the stream dump doesn't crash on invalid arguments",
+               ASSERT_OK(stream->debug(hidl_handle(), {})))
+
+//////////////////////////////////////////////////////////////////////////////
+////////////////////////////// addRemoveEffect ///////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+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)))
+
+// TODO: positive tests
+
+//////////////////////////////////////////////////////////////////////////////
+/////////////////////////////// Control ////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+TEST_IO_STREAM(standby, "Make sure the stream can be put in stanby",
+               ASSERT_OK(stream->standby()))  // can not fail
+
+static constexpr auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUPPORTED};
+
+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",
+               ASSERT_RESULT(invalidStateOrNotSupported, stream->stop()))
+
+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());
+               ASSERT_RESULT(Result::INVALID_STATE, closeStream()))
+
+static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
+static void testCreateTooBigMmapBuffer(IStream* stream) {
+    MmapBufferInfo info;
+    Result res;
+    // Assume that int max is a value too big to be allocated
+    // This is true currently with a 32bit media server, but might not when it
+    // will run in 64 bit
+    auto minSizeFrames = std::numeric_limits<int32_t>::max();
+    ASSERT_OK(stream->createMmapBuffer(minSizeFrames, returnIn(res, info)));
+    ASSERT_RESULT(invalidArgsOrNotSupported, res);
+}
+
+TEST_IO_STREAM(CreateTooBigMmapBuffer, "Create mmap buffer too big should fail",
+               testCreateTooBigMmapBuffer(stream.get()))
+
+static void testGetMmapPositionOfNonMmapedStream(IStream* stream) {
+    Result res;
+    MmapPosition position;
+    ASSERT_OK(stream->getMmapPosition(returnIn(res, position)));
+    ASSERT_RESULT(invalidArgsOrNotSupported, res);
+}
+
+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");
+    AudioSource source;
+    ASSERT_OK(stream->getAudioSource(returnIn(res, source)));
+    if (res == Result::NOT_SUPPORTED) {
+        doc::partialTest("getAudioSource is not supported");
+        return;
+    }
+    ASSERT_OK(res);
+    ASSERT_EQ(AudioSource::DEFAULT, source);
+}
+
+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;
+    }
+    // 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*/}) {
+        EXPECT_OK(setGain(value)) << "value=" << value;
+    }
+}
+
+static void testOptionalUnitaryGain(std::function<Return<Result>(float)> setGain,
+                                    string debugName) {
+    auto result = setGain(1);
+    ASSERT_IS_OK(result);
+    if (result == Result::NOT_SUPPORTED) {
+        doc::partialTest(debugName + " is not supported");
+        return;
+    }
+    testUnitaryGain(setGain);
+}
+
+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");
+}
+
+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; }));
+    EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
+}
+
+TEST_P(InputStreamTest, PrepareForReadingWithZeroBuffer) {
+    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());
+}
+
+TEST_P(InputStreamTest, PrepareForReadingCheckOverflow) {
+    doc::test(
+        "Preparing a stream for reading with a overflowing sized buffer should "
+        "fail");
+    auto uintMax = std::numeric_limits<uint32_t>::max();
+    testPrepareForReading(stream.get(), uintMax, uintMax);
+}
+
+TEST_P(InputStreamTest, GetInputFramesLost) {
+    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};
+    ASSERT_EQ(0U, framesLost);
+}
+
+TEST_P(InputStreamTest, getCapturePosition) {
+    doc::test(
+        "The capture position of a non prepared stream should not be "
+        "retrievable");
+    uint64_t frames;
+    uint64_t time;
+    ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, time)));
+    ASSERT_RESULT(invalidStateOrNotSupported, res);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+///////////////////////////////// StreamIn ///////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+TEST_P(OutputStreamTest, getLatency) {
+    doc::test("Make sure latency is over 0");
+    auto result = stream->getLatency();
+    ASSERT_IS_OK(result);
+    ASSERT_GT(result, 0U);
+}
+
+TEST_P(OutputStreamTest, setVolume) {
+    doc::test("Try to set the output volume");
+    testOptionalUnitaryGain([this](float volume) { return stream->setVolume(volume, volume); },
+                            "setVolume");
+}
+
+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; }));
+    EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
+}
+
+TEST_P(OutputStreamTest, PrepareForWriteWithZeroBuffer) {
+    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());
+}
+
+TEST_P(OutputStreamTest, PrepareForWritingCheckOverflow) {
+    doc::test(
+        "Preparing a stream for writing with a overflowing sized buffer should "
+        "fail");
+    auto uintMax = std::numeric_limits<uint32_t>::max();
+    testPrepareForWriting(stream.get(), uintMax, uintMax);
+}
+
+struct Capability {
+    Capability(IStreamOut* stream) {
+        EXPECT_OK(stream->supportsPauseAndResume(returnIn(pause, resume)));
+        auto ret = stream->supportsDrain();
+        EXPECT_IS_OK(ret);
+        if (ret.isOk()) {
+            drain = ret;
+        }
+    }
+    bool pause = false;
+    bool resume = false;
+    bool drain = false;
+};
+
+TEST_P(OutputStreamTest, SupportsPauseAndResumeAndDrain) {
+    doc::test("Implementation must expose pause, resume and drain capabilities");
+    Capability(stream.get());
+}
+
+template <class Value>
+static void checkInvalidStateOr0(Result res, Value value) {
+    switch (res) {
+        case Result::INVALID_STATE:
+            break;
+        case Result::OK:
+            ASSERT_EQ(0U, value);
+            break;
+        default:
+            FAIL() << "Unexpected result " << toString(res);
+    }
+}
+
+TEST_P(OutputStreamTest, GetRenderPosition) {
+    doc::test("A new stream render position should be 0 or INVALID_STATE");
+    uint32_t dspFrames;
+    ASSERT_OK(stream->getRenderPosition(returnIn(res, dspFrames)));
+    if (res == Result::NOT_SUPPORTED) {
+        doc::partialTest("getRenderPosition is not supported");
+        return;
+    }
+    checkInvalidStateOr0(res, dspFrames);
+}
+
+TEST_P(OutputStreamTest, GetNextWriteTimestamp) {
+    doc::test("A new stream next write timestamp should be 0 or INVALID_STATE");
+    uint64_t timestampUs;
+    ASSERT_OK(stream->getNextWriteTimestamp(returnIn(res, timestampUs)));
+    if (res == Result::NOT_SUPPORTED) {
+        doc::partialTest("getNextWriteTimestamp is not supported");
+        return;
+    }
+    checkInvalidStateOr0(res, timestampUs);
+}
+
+/** Stub implementation of out stream callback. */
+class MockOutCallbacks : public IStreamOutCallback {
+    Return<void> onWriteReady() override { return {}; }
+    Return<void> onDrainReady() override { return {}; }
+    Return<void> onError() override { return {}; }
+};
+
+static bool isAsyncModeSupported(IStreamOut* stream) {
+    auto res = stream->setCallback(new MockOutCallbacks);
+    stream->clearCallback();  // try to restore the no callback state, ignore
+                              // any error
+    auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
+    EXPECT_RESULT(okOrNotSupported, res);
+    return res.isOk() ? res == Result::OK : false;
+}
+
+TEST_P(OutputStreamTest, SetCallback) {
+    doc::test(
+        "If supported, registering callback for async operation should never "
+        "fail");
+    if (!isAsyncModeSupported(stream.get())) {
+        doc::partialTest("The stream does not support async operations");
+        return;
+    }
+    ASSERT_OK(stream->setCallback(new MockOutCallbacks));
+    ASSERT_OK(stream->setCallback(new MockOutCallbacks));
+}
+
+TEST_P(OutputStreamTest, clearCallback) {
+    doc::test(
+        "If supported, clearing a callback to go back to sync operation should "
+        "not fail");
+    if (!isAsyncModeSupported(stream.get())) {
+        doc::partialTest("The stream does not support async operations");
+        return;
+    }
+    // TODO: Clarify if clearing a non existing callback should fail
+    ASSERT_OK(stream->setCallback(new MockOutCallbacks));
+    ASSERT_OK(stream->clearCallback());
+}
+
+TEST_P(OutputStreamTest, Resume) {
+    doc::test(
+        "If supported, a stream should fail to resume if not previously "
+        "paused");
+    if (!Capability(stream.get()).resume) {
+        doc::partialTest("The output stream does not support resume");
+        return;
+    }
+    ASSERT_RESULT(Result::INVALID_STATE, stream->resume());
+}
+
+TEST_P(OutputStreamTest, Pause) {
+    doc::test(
+        "If supported, a stream should fail to pause if not previously "
+        "started");
+    if (!Capability(stream.get()).pause) {
+        doc::partialTest("The output stream does not support pause");
+        return;
+    }
+    ASSERT_RESULT(Result::INVALID_STATE, stream->resume());
+}
+
+static void testDrain(IStreamOut* stream, AudioDrain type) {
+    if (!Capability(stream).drain) {
+        doc::partialTest("The output stream does not support drain");
+        return;
+    }
+    ASSERT_RESULT(Result::OK, stream->drain(type));
+}
+
+TEST_P(OutputStreamTest, DrainAll) {
+    doc::test("If supported, a stream should always succeed to drain");
+    testDrain(stream.get(), AudioDrain::ALL);
+}
+
+TEST_P(OutputStreamTest, DrainEarlyNotify) {
+    doc::test("If supported, a stream should always succeed to drain");
+    testDrain(stream.get(), AudioDrain::EARLY_NOTIFY);
+}
+
+TEST_P(OutputStreamTest, FlushStop) {
+    doc::test("If supported, a stream should always succeed to flush");
+    auto ret = stream->flush();
+    ASSERT_IS_OK(ret);
+    if (ret == Result::NOT_SUPPORTED) {
+        doc::partialTest("Flush is not supported");
+        return;
+    }
+    ASSERT_OK(ret);
+}
+
+TEST_P(OutputStreamTest, GetPresentationPositionStop) {
+    doc::test(
+        "If supported, a stream should always succeed to retrieve the "
+        "presentation position");
+    uint64_t frames;
+    TimeSpec mesureTS;
+    ASSERT_OK(stream->getPresentationPosition(returnIn(res, frames, mesureTS)));
+    if (res == Result::NOT_SUPPORTED) {
+        doc::partialTest("getpresentationPosition is not supported");
+        return;
+    }
+    ASSERT_EQ(0U, frames);
+
+    if (mesureTS.tvNSec == 0 && mesureTS.tvSec == 0) {
+        // As the stream has never written a frame yet,
+        // the timestamp does not really have a meaning, allow to return 0
+        return;
+    }
+
+    // Make sure the return measure is not more than 1s old.
+    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 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);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+/////////////////////////////// PrimaryDevice ////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+TEST_F(AudioPrimaryHidlTest, setVoiceVolume) {
+    doc::test("Make sure setVoiceVolume only succeed if volume is in [0,1]");
+    testUnitaryGain([](float volume) { return device->setVoiceVolume(volume); });
+}
+
+TEST_F(AudioPrimaryHidlTest, setMode) {
+    doc::test(
+        "Make sure setMode always succeeds if mode is valid "
+        "and fails otherwise");
+    // Test Invalid values
+    for (int mode : {-1, 0, int(AudioMode::IN_COMMUNICATION) + 1}) {
+        SCOPED_TRACE("mode=" + to_string(mode));
+        ASSERT_RESULT(Result::INVALID_ARGUMENTS, device->setMode(AudioMode(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 */}) {
+        SCOPED_TRACE("mode=" + toString(mode));
+        ASSERT_OK(device->setMode(mode));
+    }
+}
+
+TEST_F(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) {
+    doc::test("Query and set the BT SCO NR&EC state");
+    testOptionalAccessors("BtScoNrecEnabled", {true, false, true},
+                          &IPrimaryDevice::setBtScoNrecEnabled,
+                          &IPrimaryDevice::getBtScoNrecEnabled);
+}
+
+TEST_F(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) {
+    doc::test("Query and set the SCO whideband state");
+    testOptionalAccessors("BtScoWideband", {true, false, true},
+                          &IPrimaryDevice::setBtScoWidebandEnabled,
+                          &IPrimaryDevice::getBtScoWidebandEnabled);
+}
+
+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);
+}
+
+TEST_F(BoolAccessorPrimaryHidlTest, setGetHac) {
+    doc::test("Query and set the HAC state");
+    testOptionalAccessors("HAC", {true, false, true}, &IPrimaryDevice::setHacEnabled,
+                          &IPrimaryDevice::getHacEnabled);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////// Clean caches on global tear down ////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+int main(int argc, char** argv) {
+    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/core/4.0/vts/functional/ValidateAudioConfiguration.cpp b/audio/core/4.0/vts/functional/ValidateAudioConfiguration.cpp
new file mode 100644
index 0000000..a64513f
--- /dev/null
+++ b/audio/core/4.0/vts/functional/ValidateAudioConfiguration.cpp
@@ -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.
+ */
+
+#include <unistd.h>
+#include <string>
+
+#include "utility/ValidateXml.h"
+
+TEST(CheckConfig, audioPolicyConfigurationValidation) {
+    RecordProperty("description",
+                   "Verify that the audio policy configuration file "
+                   "is valid according to the schema");
+
+    std::vector<const char*> locations = {"/odm/etc", "/vendor/etc", "/system/etc"};
+    EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS("audio_policy_configuration.xml", locations,
+                                            "/data/local/tmp/audio_policy_configuration_V4_0.xsd");
+}
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index 214b8d5..bb02863 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -1,7 +1,6 @@
 cc_library_headers {
     name: "android.hardware.audio.core@all-versions-impl",
     relative_install_path: "hw",
-    proprietary: true,
     vendor: true,
 
     defaults: ["hidl_defaults"],
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
index fa05350..b38eca3 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
@@ -30,6 +30,11 @@
 
 std::string deviceAddressToHal(const DeviceAddress& address);
 
+#ifdef AUDIO_HAL_VERSION_4_0
+bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
+                                    const struct audio_microphone_characteristic_t& src);
+#endif
+
 }  // namespace implementation
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
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
index 3f3f936..004a99e 100644
--- 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
@@ -24,6 +24,8 @@
 namespace AUDIO_HAL_VERSION {
 namespace implementation {
 
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+
 std::string deviceAddressToHal(const DeviceAddress& address) {
     // HAL assumes that the address is NUL-terminated.
     char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
@@ -54,6 +56,132 @@
     return halAddress;
 }
 
+#ifdef AUDIO_HAL_VERSION_4_0
+status_t deviceAddressFromHal(audio_devices_t device, const char* halAddress,
+                              DeviceAddress* address) {
+    if (address == nullptr) {
+        return BAD_VALUE;
+    }
+    address->device = AudioDevice(device);
+    if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
+        return OK;
+    }
+
+    const bool isInput = (device & AUDIO_DEVICE_BIT_IN) != 0;
+    if (isInput) device &= ~AUDIO_DEVICE_BIT_IN;
+    if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) ||
+        (isInput && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+        int status =
+            sscanf(halAddress, "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &address->address.mac[0],
+                   &address->address.mac[1], &address->address.mac[2], &address->address.mac[3],
+                   &address->address.mac[4], &address->address.mac[5]);
+        return status == 6 ? OK : BAD_VALUE;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_IP) != 0) ||
+               (isInput && (device & AUDIO_DEVICE_IN_IP) != 0)) {
+        int status =
+            sscanf(halAddress, "%hhu.%hhu.%hhu.%hhu", &address->address.ipv4[0],
+                   &address->address.ipv4[1], &address->address.ipv4[2], &address->address.ipv4[3]);
+        return status == 4 ? OK : BAD_VALUE;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_USB)) != 0 ||
+               (isInput && (device & AUDIO_DEVICE_IN_ALL_USB)) != 0) {
+        int status = sscanf(halAddress, "card=%d;device=%d", &address->address.alsa.card,
+                            &address->address.alsa.device);
+        return status == 2 ? OK : BAD_VALUE;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_BUS) != 0) ||
+               (isInput && (device & AUDIO_DEVICE_IN_BUS) != 0)) {
+        address->busAddress = halAddress;
+        return OK;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0 ||
+               (isInput && (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
+        address->rSubmixAddress = halAddress;
+        return OK;
+    }
+    address->busAddress = halAddress;
+    return OK;
+}
+
+AudioMicrophoneChannelMapping halToChannelMapping(audio_microphone_channel_mapping_t mapping) {
+    switch (mapping) {
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED:
+            return AudioMicrophoneChannelMapping::UNUSED;
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT:
+            return AudioMicrophoneChannelMapping::DIRECT;
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED:
+            return AudioMicrophoneChannelMapping::PROCESSED;
+    }
+}
+
+AudioMicrophoneLocation halToLocation(audio_microphone_location_t location) {
+    switch (location) {
+        default:
+        case AUDIO_MICROPHONE_LOCATION_UNKNOWN:
+            return AudioMicrophoneLocation::UNKNOWN;
+        case AUDIO_MICROPHONE_LOCATION_MAINBODY:
+            return AudioMicrophoneLocation::MAINBODY;
+        case AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE:
+            return AudioMicrophoneLocation::MAINBODY_MOVABLE;
+        case AUDIO_MICROPHONE_LOCATION_PERIPHERAL:
+            return AudioMicrophoneLocation::PERIPHERAL;
+    }
+}
+
+AudioMicrophoneDirectionality halToDirectionality(audio_microphone_directionality_t dir) {
+    switch (dir) {
+        default:
+        case AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN:
+            return AudioMicrophoneDirectionality::UNKNOWN;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_OMNI:
+            return AudioMicrophoneDirectionality::OMNI;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL:
+            return AudioMicrophoneDirectionality::BI_DIRECTIONAL;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID:
+            return AudioMicrophoneDirectionality::CARDIOID;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID:
+            return AudioMicrophoneDirectionality::HYPER_CARDIOID;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID:
+            return AudioMicrophoneDirectionality::SUPER_CARDIOID;
+    }
+}
+
+bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
+                                    const struct audio_microphone_characteristic_t& src) {
+    bool status = false;
+    if (pDst != NULL) {
+        pDst->deviceId = src.device_id;
+
+        if (deviceAddressFromHal(src.device, src.address, &pDst->deviceAddress) != OK) {
+            return false;
+        }
+        pDst->channelMapping.resize(AUDIO_CHANNEL_COUNT_MAX);
+        for (size_t ch = 0; ch < pDst->channelMapping.size(); ch++) {
+            pDst->channelMapping[ch] = halToChannelMapping(src.channel_mapping[ch]);
+        }
+        pDst->location = halToLocation(src.location);
+        pDst->group = (AudioMicrophoneGroup)src.group;
+        pDst->indexInTheGroup = (uint32_t)src.index_in_the_group;
+        pDst->sensitivity = src.sensitivity;
+        pDst->maxSpl = src.max_spl;
+        pDst->minSpl = src.min_spl;
+        pDst->directionality = halToDirectionality(src.directionality);
+        pDst->frequencyResponse.resize(src.num_frequency_responses);
+        for (size_t k = 0; k < src.num_frequency_responses; k++) {
+            pDst->frequencyResponse[k].frequency = src.frequency_responses[0][k];
+            pDst->frequencyResponse[k].level = src.frequency_responses[1][k];
+        }
+        pDst->position.x = src.geometric_location.x;
+        pDst->position.y = src.geometric_location.y;
+        pDst->position.z = src.geometric_location.z;
+
+        pDst->orientation.x = src.orientation.x;
+        pDst->orientation.y = src.orientation.y;
+        pDst->orientation.z = src.orientation.z;
+
+        status = true;
+    }
+    return status;
+}
+#endif
+
 }  // namespace implementation
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
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
index 224823c..eb53b48 100644
--- 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
@@ -25,6 +25,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include <VersionUtils.h>
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -39,6 +41,9 @@
 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::common::AUDIO_HAL_VERSION::implementation::AudioInputFlagBitfield;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::implementation::
+    AudioOutputFlagBitfield;
 using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress;
 using ::android::hardware::audio::AUDIO_HAL_VERSION::IDevice;
 using ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamIn;
@@ -51,6 +56,11 @@
 using ::android::hardware::hidl_string;
 using ::android::sp;
 
+#ifdef AUDIO_HAL_VERSION_4_0
+using ::android::hardware::audio::AUDIO_HAL_VERSION::SourceMetadata;
+using ::android::hardware::audio::AUDIO_HAL_VERSION::SinkMetadata;
+#endif
+
 struct Device : public IDevice, public ParametersUtil {
     explicit Device(audio_hw_device_t* device);
 
@@ -64,12 +74,26 @@
     Return<void> getMasterMute(getMasterMute_cb _hidl_cb) override;
     Return<void> getInputBufferSize(const AudioConfig& config,
                                     getInputBufferSize_cb _hidl_cb) override;
+
+    // V2 openInputStream is called by V4 input stream thus present in both versions
+    Return<void> openInputStream(int32_t ioHandle, const DeviceAddress& device,
+                                 const AudioConfig& config, AudioInputFlagBitfield flags,
+                                 AudioSource source, openInputStream_cb _hidl_cb);
+#ifdef AUDIO_HAL_VERSION_2_0
     Return<void> openOutputStream(int32_t ioHandle, const DeviceAddress& device,
-                                  const AudioConfig& config, AudioOutputFlag flags,
+                                  const AudioConfig& config, AudioOutputFlagBitfield flags,
+                                  openOutputStream_cb _hidl_cb) override;
+#elif defined(AUDIO_HAL_VERSION_4_0)
+    Return<void> openOutputStream(int32_t ioHandle, const DeviceAddress& device,
+                                  const AudioConfig& config, AudioOutputFlagBitfield flags,
+                                  const SourceMetadata& sourceMetadata,
                                   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;
+                                 const AudioConfig& config, AudioInputFlagBitfield flags,
+                                 const SinkMetadata& sinkMetadata,
+                                 openInputStream_cb _hidl_cb) override;
+#endif
+
     Return<bool> supportsAudioPatches() override;
     Return<void> createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
                                   const hidl_vec<AudioPortConfig>& sinks,
@@ -77,12 +101,27 @@
     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;
+
+#ifdef AUDIO_HAL_VERSION_2_0
+    Return<AudioHwSync> getHwAvSync() 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;
+#elif defined(AUDIO_HAL_VERSION_4_0)
+    Return<void> getHwAvSync(getHwAvSync_cb _hidl_cb) override;
+    Return<void> getParameters(const hidl_vec<ParameterValue>& context,
+                               const hidl_vec<hidl_string>& keys,
+                               getParameters_cb _hidl_cb) override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& context,
+                                 const hidl_vec<ParameterValue>& parameters) override;
+    Return<void> getMicrophones(getMicrophones_cb _hidl_cb) override;
+    Return<Result> setConnectedState(const DeviceAddress& address, bool connected) override;
+#endif
+
+    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
 
     // Utility methods for extending interfaces.
     Result analyzeStatus(const char* funcName, int status);
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
index b295082..581e1dc 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
@@ -147,7 +147,10 @@
 }
 
 Return<void> Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
-                                      const AudioConfig& config, AudioOutputFlag flags,
+                                      const AudioConfig& config, AudioOutputFlagBitfield flags,
+#ifdef AUDIO_HAL_VERSION_4_0
+                                      const SourceMetadata& /* sourceMetadata */,
+#endif
                                       openOutputStream_cb _hidl_cb) {
     audio_config_t halConfig;
     HidlUtils::audioConfigToHal(config, &halConfig);
@@ -174,7 +177,7 @@
 }
 
 Return<void> Device::openInputStream(int32_t ioHandle, const DeviceAddress& device,
-                                     const AudioConfig& config, AudioInputFlag flags,
+                                     const AudioConfig& config, AudioInputFlagBitfield flags,
                                      AudioSource source, openInputStream_cb _hidl_cb) {
     audio_config_t halConfig;
     HidlUtils::audioConfigToHal(config, &halConfig);
@@ -201,6 +204,24 @@
     return Void();
 }
 
+#ifdef AUDIO_HAL_VERSION_4_0
+Return<void> Device::openInputStream(int32_t ioHandle, const DeviceAddress& device,
+                                     const AudioConfig& config, AudioInputFlagBitfield flags,
+                                     const SinkMetadata& sinkMetadata,
+                                     openInputStream_cb _hidl_cb) {
+    if (sinkMetadata.tracks.size() == 0) {
+        // This should never happen, the framework must not create as stream
+        // if there is no client
+        ALOGE("openInputStream called without tracks connected");
+        _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, AudioConfig());
+        return Void();
+    }
+    // Pick the first one as the main until the legacy API is update
+    AudioSource source = sinkMetadata.tracks[0].source;
+    return openInputStream(ioHandle, device, config, flags, source, _hidl_cb);
+}
+#endif
+
 Return<bool> Device::supportsAudioPatches() {
     return version() >= AUDIO_DEVICE_API_VERSION_3_0;
 }
@@ -256,32 +277,84 @@
     return Result::NOT_SUPPORTED;
 }
 
+#ifdef AUDIO_HAL_VERSION_2_0
 Return<AudioHwSync> Device::getHwAvSync() {
     int halHwAvSync;
     Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
     return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID;
 }
+#elif defined(AUDIO_HAL_VERSION_4_0)
+Return<void> Device::getHwAvSync(getHwAvSync_cb _hidl_cb) {
+    int halHwAvSync;
+    Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
+    _hidl_cb(retval, halHwAvSync);
+    return Void();
+}
+#endif
 
 Return<Result> Device::setScreenState(bool turnedOn) {
     return setParam(AudioParameter::keyScreenState, turnedOn);
 }
 
+#ifdef AUDIO_HAL_VERSION_2_0
 Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
-    getParametersImpl(keys, _hidl_cb);
+    getParametersImpl({}, keys, _hidl_cb);
     return Void();
 }
 
 Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& parameters) {
-    return setParametersImpl(parameters);
+    return setParametersImpl({} /* context */, parameters);
 }
+#elif defined(AUDIO_HAL_VERSION_4_0)
+Return<void> Device::getParameters(const hidl_vec<ParameterValue>& context,
+                                   const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
+    getParametersImpl(context, keys, _hidl_cb);
+    return Void();
+}
+Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& context,
+                                     const hidl_vec<ParameterValue>& parameters) {
+    return setParametersImpl(context, parameters);
+}
+#endif
 
+#ifdef AUDIO_HAL_VERSION_2_0
 Return<void> Device::debugDump(const hidl_handle& fd) {
+    return debug(fd, {});
+}
+#endif
+
+Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
     if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
         analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
     }
     return Void();
 }
 
+#ifdef AUDIO_HAL_VERSION_4_0
+Return<void> Device::getMicrophones(getMicrophones_cb _hidl_cb) {
+    Result retval = Result::NOT_SUPPORTED;
+    size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
+    audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
+
+    hidl_vec<MicrophoneInfo> microphones;
+    if (mDevice->get_microphones != NULL &&
+        mDevice->get_microphones(mDevice, &mic_array[0], &actual_mics) == 0) {
+        microphones.resize(actual_mics);
+        for (size_t i = 0; i < actual_mics; ++i) {
+            halToMicrophoneCharacteristics(&microphones[i], mic_array[i]);
+        }
+        retval = Result::OK;
+    }
+    _hidl_cb(retval, microphones);
+    return Void();
+}
+
+Return<Result> Device::setConnectedState(const DeviceAddress& address, bool connected) {
+    auto key = connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect;
+    return setParam(key, address);
+}
+#endif
+
 }  // namespace implementation
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.h b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.h
index 769adaa..1509ad1 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.h
@@ -37,11 +37,19 @@
 using ::android::sp;
 
 struct DevicesFactory : public IDevicesFactory {
-    // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IDevicesFactory follow.
+#ifdef AUDIO_HAL_VERSION_2_0
     Return<void> openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) override;
+#endif
+#ifdef AUDIO_HAL_VERSION_4_0
+    Return<void> openDevice(const hidl_string& device, openDevice_cb _hidl_cb) override;
+    Return<void> openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override;
+#endif
 
    private:
-    static const char* deviceToString(IDevicesFactory::Device device);
+    template <class DeviceShim, class Callback>
+    Return<void> openDevice(const char* moduleName, Callback _hidl_cb);
+    Return<void> openDevice(const char* moduleName, openDevice_cb _hidl_cb);
+
     static int loadAudioInterface(const char* if_name, audio_hw_device_t** dev);
 };
 
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
index 014b4d8..43e5d6e 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
@@ -26,21 +26,54 @@
 namespace AUDIO_HAL_VERSION {
 namespace implementation {
 
-// static
-const char* DevicesFactory::deviceToString(IDevicesFactory::Device device) {
+#ifdef AUDIO_HAL_VERSION_2_0
+Return<void> DevicesFactory::openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) {
     switch (device) {
         case IDevicesFactory::Device::PRIMARY:
-            return AUDIO_HARDWARE_MODULE_ID_PRIMARY;
+            return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
         case IDevicesFactory::Device::A2DP:
-            return AUDIO_HARDWARE_MODULE_ID_A2DP;
+            return openDevice(AUDIO_HARDWARE_MODULE_ID_A2DP, _hidl_cb);
         case IDevicesFactory::Device::USB:
-            return AUDIO_HARDWARE_MODULE_ID_USB;
+            return openDevice(AUDIO_HARDWARE_MODULE_ID_USB, _hidl_cb);
         case IDevicesFactory::Device::R_SUBMIX:
-            return AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX;
+            return openDevice(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, _hidl_cb);
         case IDevicesFactory::Device::STUB:
-            return AUDIO_HARDWARE_MODULE_ID_STUB;
+            return openDevice(AUDIO_HARDWARE_MODULE_ID_STUB, _hidl_cb);
     }
-    return nullptr;
+    _hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
+    return Void();
+}
+#endif
+#ifdef AUDIO_HAL_VERSION_4_0
+Return<void> DevicesFactory::openDevice(const hidl_string& moduleName, openDevice_cb _hidl_cb) {
+    if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
+        return openDevice<PrimaryDevice>(moduleName.c_str(), _hidl_cb);
+    }
+    return openDevice(moduleName.c_str(), _hidl_cb);
+}
+Return<void> DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) {
+    return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
+}
+#endif
+
+Return<void> DevicesFactory::openDevice(const char* moduleName, openDevice_cb _hidl_cb) {
+    return openDevice<implementation::Device>(moduleName, _hidl_cb);
+}
+
+template <class DeviceShim, class Callback>
+Return<void> DevicesFactory::openDevice(const char* moduleName, Callback _hidl_cb) {
+    audio_hw_device_t* halDevice;
+    Result retval(Result::INVALID_ARGUMENTS);
+    sp<DeviceShim> result;
+    int halStatus = loadAudioInterface(moduleName, &halDevice);
+    if (halStatus == OK) {
+        result = new DeviceShim(halDevice);
+        retval = Result::OK;
+    } else if (halStatus == -EINVAL) {
+        retval = Result::NOT_INITIALIZED;
+    }
+    _hidl_cb(retval, result);
+    return Void();
 }
 
 // static
@@ -73,30 +106,6 @@
     return rc;
 }
 
-// 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);
-    if (moduleName != nullptr) {
-        int halStatus = loadAudioInterface(moduleName, &halDevice);
-        if (halStatus == OK) {
-            if (device == IDevicesFactory::Device::PRIMARY) {
-                result = new PrimaryDevice(halDevice);
-            } else {
-                result = new ::android::hardware::audio::AUDIO_HAL_VERSION::implementation::Device(
-                    halDevice);
-            }
-            retval = Result::OK;
-        } else if (halStatus == -EINVAL) {
-            retval = Result::NOT_INITIALIZED;
-        }
-    }
-    _hidl_cb(retval, result);
-    return Void();
-}
-
 IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* /* name */) {
     return new DevicesFactory();
 }
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h
index df5adee..a27ac25 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h
@@ -28,6 +28,7 @@
 namespace AUDIO_HAL_VERSION {
 namespace implementation {
 
+using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress;
 using ::android::hardware::audio::AUDIO_HAL_VERSION::ParameterValue;
 using ::android::hardware::audio::AUDIO_HAL_VERSION::Result;
 using ::android::hardware::hidl_string;
@@ -37,16 +38,18 @@
    public:
     Result getParam(const char* name, bool* value);
     Result getParam(const char* name, int* value);
-    Result getParam(const char* name, String8* value);
+    Result getParam(const char* name, String8* value, AudioParameter context = {});
     void getParametersImpl(
-        const hidl_vec<hidl_string>& keys,
+        const hidl_vec<ParameterValue>& context, const hidl_vec<hidl_string>& keys,
         std::function<void(Result retval, const hidl_vec<ParameterValue>& parameters)> cb);
     std::unique_ptr<AudioParameter> getParams(const AudioParameter& keys);
     Result setParam(const char* name, bool value);
     Result setParam(const char* name, int value);
-    Result setParam(const char* name, const char* value);
-    Result setParametersImpl(const hidl_vec<ParameterValue>& parameters);
+    Result setParam(const char* name, float value);
+    Result setParametersImpl(const hidl_vec<ParameterValue>& context,
+                             const hidl_vec<ParameterValue>& parameters);
     Result setParams(const AudioParameter& param);
+    Result setParam(const char* name, const DeviceAddress& address);
 
    protected:
     virtual ~ParametersUtil() {}
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h
index a858a48..3907284 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h
@@ -15,6 +15,8 @@
  */
 
 #include <common/all-versions/IncludeGuard.h>
+#include <core/all-versions/default/Conversions.h>
+#include <system/audio.h>
 
 namespace android {
 namespace hardware {
@@ -62,18 +64,20 @@
     return getHalStatusToResult(params->getInt(halName, *value));
 }
 
-Result ParametersUtil::getParam(const char* name, String8* value) {
+Result ParametersUtil::getParam(const char* name, String8* value, AudioParameter context) {
     const String8 halName(name);
-    AudioParameter keys;
-    keys.addKey(halName);
-    std::unique_ptr<AudioParameter> params = getParams(keys);
+    context.addKey(halName);
+    std::unique_ptr<AudioParameter> params = getParams(context);
     return getHalStatusToResult(params->get(halName, *value));
 }
 
 void ParametersUtil::getParametersImpl(
-    const hidl_vec<hidl_string>& keys,
+    const hidl_vec<ParameterValue>& context, const hidl_vec<hidl_string>& keys,
     std::function<void(Result retval, const hidl_vec<ParameterValue>& parameters)> cb) {
     AudioParameter halKeys;
+    for (auto& pair : context) {
+        halKeys.add(String8(pair.key.c_str()), String8(pair.value.c_str()));
+    }
     for (size_t i = 0; i < keys.size(); ++i) {
         halKeys.addKey(String8(keys[i].c_str()));
     }
@@ -120,19 +124,28 @@
     return setParams(param);
 }
 
-Result ParametersUtil::setParam(const char* name, const char* value) {
+Result ParametersUtil::setParam(const char* name, float value) {
     AudioParameter param;
-    param.add(String8(name), String8(value));
+    param.addFloat(String8(name), value);
     return setParams(param);
 }
 
-Result ParametersUtil::setParametersImpl(const hidl_vec<ParameterValue>& parameters) {
+Result ParametersUtil::setParametersImpl(const hidl_vec<ParameterValue>& context,
+                                         const hidl_vec<ParameterValue>& parameters) {
     AudioParameter params;
+    for (auto& pair : context) {
+        params.add(String8(pair.key.c_str()), String8(pair.value.c_str()));
+    }
     for (size_t i = 0; i < parameters.size(); ++i) {
         params.add(String8(parameters[i].key.c_str()), String8(parameters[i].value.c_str()));
     }
     return setParams(params);
 }
+Result ParametersUtil::setParam(const char* name, const DeviceAddress& address) {
+    AudioParameter params(String8(deviceAddressToHal(address).c_str()));
+    params.addInt(String8(name), int(address.device));
+    return setParams(params);
+}
 
 Result ParametersUtil::setParams(const AudioParameter& param) {
     int halStatus = halSetParameters(param.toString().string());
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
index 240b221..42996d7 100644
--- 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
@@ -59,12 +59,24 @@
     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,
+                                  const AudioConfig& config, AudioOutputFlagBitfield flags,
+#ifdef AUDIO_HAL_VERSION_4_0
+                                  const SourceMetadata& sourceMetadata,
+#endif
                                   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;
+                                 const AudioConfig& config, AudioInputFlagBitfield flags,
+                                 AudioSource source, openInputStream_cb _hidl_cb);
+#ifdef AUDIO_HAL_VERSION_4_0
+    Return<void> openInputStream(int32_t ioHandle, const DeviceAddress& device,
+                                 const AudioConfig& config, AudioInputFlagBitfield flags,
+                                 const SinkMetadata& sinkMetadata,
+                                 openInputStream_cb _hidl_cb) override;
+#endif
+
     Return<bool> supportsAudioPatches() override;
     Return<void> createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
                                   const hidl_vec<AudioPortConfig>& sinks,
@@ -72,12 +84,27 @@
     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;
+
+#ifdef AUDIO_HAL_VERSION_2_0
+    Return<AudioHwSync> getHwAvSync() 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;
+#elif defined(AUDIO_HAL_VERSION_4_0)
+    Return<void> getHwAvSync(getHwAvSync_cb _hidl_cb) override;
+    Return<void> getParameters(const hidl_vec<ParameterValue>& context,
+                               const hidl_vec<hidl_string>& keys,
+                               getParameters_cb _hidl_cb) override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& context,
+                                 const hidl_vec<ParameterValue>& parameters) override;
+    Return<void> getMicrophones(getMicrophones_cb _hidl_cb) override;
+    Return<Result> setConnectedState(const DeviceAddress& address, bool connected) override;
+#endif
+
+    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
 
     // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IPrimaryDevice follow.
     Return<Result> setVoiceVolume(float volume) override;
@@ -91,6 +118,15 @@
     Return<void> getHacEnabled(getHacEnabled_cb _hidl_cb) override;
     Return<Result> setHacEnabled(bool enabled) override;
 
+#ifdef AUDIO_HAL_VERSION_4_0
+    Return<Result> setBtScoHeadsetDebugName(const hidl_string& name) override;
+    Return<void> getBtHfpEnabled(getBtHfpEnabled_cb _hidl_cb) override;
+    Return<Result> setBtHfpEnabled(bool enabled) override;
+    Return<Result> setBtHfpSampleRate(uint32_t sampleRateHz) override;
+    Return<Result> setBtHfpVolume(float volume) override;
+    Return<Result> updateRotation(IPrimaryDevice::Rotation rotation) override;
+#endif
+
    private:
     sp<Device> mDevice;
 
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h
index 3ce047a..f00cac4 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h
@@ -60,17 +60,35 @@
     return mDevice->getInputBufferSize(config, _hidl_cb);
 }
 
+#ifdef AUDIO_HAL_VERSION_2_0
 Return<void> PrimaryDevice::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
-                                             const AudioConfig& config, AudioOutputFlag flags,
+                                             const AudioConfig& config,
+                                             AudioOutputFlagBitfield 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,
+                                            const AudioConfig& config, AudioInputFlagBitfield flags,
                                             AudioSource source, openInputStream_cb _hidl_cb) {
     return mDevice->openInputStream(ioHandle, device, config, flags, source, _hidl_cb);
 }
+#elif defined(AUDIO_HAL_VERSION_4_0)
+Return<void> PrimaryDevice::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
+                                             const AudioConfig& config,
+                                             AudioOutputFlagBitfield flags,
+                                             const SourceMetadata& sourceMetadata,
+                                             openOutputStream_cb _hidl_cb) {
+    return mDevice->openOutputStream(ioHandle, device, config, flags, sourceMetadata, _hidl_cb);
+}
+
+Return<void> PrimaryDevice::openInputStream(int32_t ioHandle, const DeviceAddress& device,
+                                            const AudioConfig& config, AudioInputFlagBitfield flags,
+                                            const SinkMetadata& sinkMetadata,
+                                            openInputStream_cb _hidl_cb) {
+    return mDevice->openInputStream(ioHandle, device, config, flags, sinkMetadata, _hidl_cb);
+}
+#endif
 
 Return<bool> PrimaryDevice::supportsAudioPatches() {
     return mDevice->supportsAudioPatches();
@@ -94,14 +112,15 @@
     return mDevice->setAudioPortConfig(config);
 }
 
-Return<AudioHwSync> PrimaryDevice::getHwAvSync() {
-    return mDevice->getHwAvSync();
-}
-
 Return<Result> PrimaryDevice::setScreenState(bool turnedOn) {
     return mDevice->setScreenState(turnedOn);
 }
 
+#ifdef AUDIO_HAL_VERSION_2_0
+Return<AudioHwSync> PrimaryDevice::getHwAvSync() {
+    return mDevice->getHwAvSync();
+}
+
 Return<void> PrimaryDevice::getParameters(const hidl_vec<hidl_string>& keys,
                                           getParameters_cb _hidl_cb) {
     return mDevice->getParameters(keys, _hidl_cb);
@@ -114,6 +133,26 @@
 Return<void> PrimaryDevice::debugDump(const hidl_handle& fd) {
     return mDevice->debugDump(fd);
 }
+#elif defined(AUDIO_HAL_VERSION_4_0)
+Return<void> PrimaryDevice::getHwAvSync(getHwAvSync_cb _hidl_cb) {
+    return mDevice->getHwAvSync(_hidl_cb);
+}
+Return<void> PrimaryDevice::getParameters(const hidl_vec<ParameterValue>& context,
+                                          const hidl_vec<hidl_string>& keys,
+                                          getParameters_cb _hidl_cb) {
+    return mDevice->getParameters(context, keys, _hidl_cb);
+}
+Return<Result> PrimaryDevice::setParameters(const hidl_vec<ParameterValue>& context,
+                                            const hidl_vec<ParameterValue>& parameters) {
+    return mDevice->setParameters(context, parameters);
+}
+Return<void> PrimaryDevice::getMicrophones(getMicrophones_cb _hidl_cb) {
+    return mDevice->getMicrophones(_hidl_cb);
+}
+Return<Result> PrimaryDevice::setConnectedState(const DeviceAddress& address, bool connected) {
+    return mDevice->setConnectedState(address, connected);
+}
+#endif
 
 // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IPrimaryDevice follow.
 Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
@@ -188,6 +227,35 @@
     return mDevice->setParam(AUDIO_PARAMETER_KEY_HAC, enabled);
 }
 
+#ifdef AUDIO_HAL_VERSION_4_0
+Return<Result> PrimaryDevice::setBtScoHeadsetDebugName(const hidl_string& name) {
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_BT_SCO_HEADSET_NAME, name.c_str());
+}
+Return<void> PrimaryDevice::getBtHfpEnabled(getBtHfpEnabled_cb _hidl_cb) {
+    bool enabled;
+    Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_HFP_ENABLE, &enabled);
+    _hidl_cb(retval, enabled);
+    return Void();
+}
+Return<Result> PrimaryDevice::setBtHfpEnabled(bool enabled) {
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_ENABLE, enabled);
+}
+Return<Result> PrimaryDevice::setBtHfpSampleRate(uint32_t sampleRateHz) {
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_SET_SAMPLING_RATE, int(sampleRateHz));
+}
+Return<Result> PrimaryDevice::setBtHfpVolume(float volume) {
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_VOLUME, volume);
+}
+Return<Result> PrimaryDevice::updateRotation(IPrimaryDevice::Rotation rotation) {
+    // legacy API expects the rotation in degree
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_ROTATION, int(rotation) * 90);
+}
+#endif
+
+Return<void> PrimaryDevice::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+    return mDevice->debug(fd, options);
+}
+
 }  // namespace implementation
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Stream.h b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h
index 4196dec..6f79429 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Stream.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h
@@ -23,6 +23,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include <VersionUtils.h>
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -32,6 +34,7 @@
 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::implementation::AudioChannelBitfield;
 using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress;
 using ::android::hardware::audio::AUDIO_HAL_VERSION::IStream;
 using ::android::hardware::audio::AUDIO_HAL_VERSION::ParameterValue;
@@ -57,11 +60,15 @@
     Return<uint64_t> getFrameCount() override;
     Return<uint64_t> getBufferSize() override;
     Return<uint32_t> getSampleRate() override;
+#ifdef AUDIO_HAL_VERSION_2_0
     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;
+#endif
+    Return<void> getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb);
+    Return<void> getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb);
+    Return<Result> setSampleRate(uint32_t sampleRateHz) override;
+    Return<AudioChannelBitfield> getChannelMask() override;
+    Return<Result> setChannelMask(AudioChannelBitfield mask) override;
     Return<AudioFormat> getFormat() override;
     Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb) override;
     Return<Result> setFormat(AudioFormat format) override;
@@ -69,20 +76,34 @@
     Return<Result> addEffect(uint64_t effectId) override;
     Return<Result> removeEffect(uint64_t effectId) override;
     Return<Result> standby() override;
+#ifdef AUDIO_HAL_VERSION_2_0
     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> setConnectedState(const DeviceAddress& address, bool connected) override;
+#elif defined(AUDIO_HAL_VERSION_4_0)
+    Return<void> getDevices(getDevices_cb _hidl_cb) override;
+    Return<Result> setDevices(const hidl_vec<DeviceAddress>& devices) override;
+    Return<void> getParameters(const hidl_vec<ParameterValue>& context,
+                               const hidl_vec<hidl_string>& keys,
+                               getParameters_cb _hidl_cb) override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& context,
+                                 const hidl_vec<ParameterValue>& parameters) override;
+#endif
+    Return<Result> setHwAvSync(uint32_t hwAvSync) 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<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
+#ifdef AUDIO_HAL_VERSION_2_0
+    Return<void> debugDump(const hidl_handle& fd) override;
+#endif
+
     // Utility methods for extending interfaces.
     static Result analyzeStatus(const char* funcName, int status);
     static Result analyzeStatus(const char* funcName, int status,
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h
index 92cff72..fa0ef45 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h
@@ -100,9 +100,22 @@
     return mStream->get_sample_rate(mStream);
 }
 
+#ifdef AUDIO_HAL_VERSION_2_0
 Return<void> Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
+    return getSupportedSampleRates(getFormat(), _hidl_cb);
+}
+Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
+    return getSupportedChannelMasks(getFormat(), _hidl_cb);
+}
+#endif
+
+Return<void> Stream::getSupportedSampleRates(AudioFormat format,
+                                             getSupportedSampleRates_cb _hidl_cb) {
+    AudioParameter context;
+    context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
     String8 halListValue;
-    Result result = getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue);
+    Result result =
+        getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context);
     hidl_vec<uint32_t> sampleRates;
     SortedVector<uint32_t> halSampleRates;
     if (result == Result::OK) {
@@ -110,7 +123,36 @@
             samplingRatesFromString(halListValue.string(), AudioParameter::valueListSeparator);
         sampleRates.setToExternal(halSampleRates.editArray(), halSampleRates.size());
     }
+#ifdef AUDIO_HAL_VERSION_2_0
     _hidl_cb(sampleRates);
+#endif
+#ifdef AUDIO_HAL_VERSION_4_0
+    _hidl_cb(result, sampleRates);
+#endif
+    return Void();
+}
+
+Return<void> Stream::getSupportedChannelMasks(AudioFormat format,
+                                              getSupportedChannelMasks_cb _hidl_cb) {
+    AudioParameter context;
+    context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
+    String8 halListValue;
+    Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context);
+    hidl_vec<AudioChannelBitfield> channelMasks;
+    SortedVector<audio_channel_mask_t> halChannelMasks;
+    if (result == Result::OK) {
+        halChannelMasks =
+            channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator);
+        channelMasks.resize(halChannelMasks.size());
+        for (size_t i = 0; i < halChannelMasks.size(); ++i) {
+            channelMasks[i] = AudioChannelBitfield(halChannelMasks[i]);
+        }
+    }
+#ifdef AUDIO_HAL_VERSION_2_0
+    _hidl_cb(channelMasks);
+#elif defined(AUDIO_HAL_VERSION_4_0)
+    _hidl_cb(result, channelMasks);
+#endif
     return Void();
 }
 
@@ -118,28 +160,11 @@
     return setParam(AudioParameter::keySamplingRate, static_cast<int>(sampleRateHz));
 }
 
-Return<AudioChannelMask> Stream::getChannelMask() {
-    return AudioChannelMask(mStream->get_channels(mStream));
+Return<AudioChannelBitfield> Stream::getChannelMask() {
+    return AudioChannelBitfield(mStream->get_channels(mStream));
 }
 
-Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
-    String8 halListValue;
-    Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue);
-    hidl_vec<AudioChannelMask> channelMasks;
-    SortedVector<audio_channel_mask_t> halChannelMasks;
-    if (result == Result::OK) {
-        halChannelMasks =
-            channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator);
-        channelMasks.resize(halChannelMasks.size());
-        for (size_t i = 0; i < halChannelMasks.size(); ++i) {
-            channelMasks[i] = AudioChannelMask(halChannelMasks[i]);
-        }
-    }
-    _hidl_cb(channelMasks);
-    return Void();
-}
-
-Return<Result> Stream::setChannelMask(AudioChannelMask mask) {
+Return<Result> Stream::setChannelMask(AudioChannelBitfield mask) {
     return setParam(AudioParameter::keyChannels, static_cast<int>(mask));
 }
 
@@ -171,7 +196,7 @@
     uint32_t halSampleRate = mStream->get_sample_rate(mStream);
     audio_channel_mask_t halMask = mStream->get_channels(mStream);
     audio_format_t halFormat = mStream->get_format(mStream);
-    _hidl_cb(halSampleRate, AudioChannelMask(halMask), AudioFormat(halFormat));
+    _hidl_cb(halSampleRate, AudioChannelBitfield(halMask), AudioFormat(halFormat));
     return Void();
 }
 
@@ -200,48 +225,73 @@
     return analyzeStatus("standby", mStream->standby(mStream));
 }
 
+Return<Result> Stream::setHwAvSync(uint32_t hwAvSync) {
+    return setParam(AudioParameter::keyStreamHwAvSync, static_cast<int>(hwAvSync));
+}
+
+#ifdef AUDIO_HAL_VERSION_2_0
 Return<AudioDevice> Stream::getDevice() {
-    int device;
+    int device = 0;
     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());
-    AudioParameter params((String8(halDeviceAddress)));
-    free(halDeviceAddress);
-    params.addInt(String8(AudioParameter::keyRouting),
-                  static_cast<audio_devices_t>(address.device));
-    return setParams(params);
+    return setParam(AudioParameter::keyRouting, address);
+}
+
+Return<void> Stream::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
+    getParametersImpl({} /* context */, keys, _hidl_cb);
+    return Void();
+}
+
+Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters) {
+    return setParametersImpl({} /* context */, parameters);
 }
 
 Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected) {
     return setParam(
         connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect,
-        deviceAddressToHal(address).c_str());
+        address);
 }
-
-Return<Result> Stream::setHwAvSync(uint32_t hwAvSync) {
-    return setParam(AudioParameter::keyStreamHwAvSync, static_cast<int>(hwAvSync));
-}
-
-Return<void> Stream::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
-    getParametersImpl(keys, _hidl_cb);
-    return Void();
-}
-
-Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters) {
-    return setParametersImpl(parameters);
-}
-
-Return<void> Stream::debugDump(const hidl_handle& fd) {
-    if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
-        analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
+#elif defined(AUDIO_HAL_VERSION_4_0)
+Return<void> Stream::getDevices(getDevices_cb _hidl_cb) {
+    int device = 0;
+    Result retval = getParam(AudioParameter::keyRouting, &device);
+    hidl_vec<DeviceAddress> devices;
+    if (retval == Result::OK) {
+        devices.resize(1);
+        devices[0].device = static_cast<AudioDevice>(device);
     }
+    _hidl_cb(retval, devices);
     return Void();
 }
 
+Return<Result> Stream::setDevices(const hidl_vec<DeviceAddress>& devices) {
+    // FIXME: can the legacy API set multiple device with address ?
+    if (devices.size() > 1) {
+        return Result::NOT_SUPPORTED;
+    }
+    DeviceAddress address;
+    if (devices.size() == 1) {
+        address = devices[0];
+    } else {
+        address.device = AudioDevice::NONE;
+    }
+    return setParam(AudioParameter::keyRouting, address);
+}
+Return<void> Stream::getParameters(const hidl_vec<ParameterValue>& context,
+                                   const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
+    getParametersImpl(context, keys, _hidl_cb);
+    return Void();
+}
+
+Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& context,
+                                     const hidl_vec<ParameterValue>& parameters) {
+    return setParametersImpl(context, parameters);
+}
+#endif
+
 Return<Result> Stream::start() {
     return Result::NOT_SUPPORTED;
 }
@@ -269,6 +319,19 @@
     return Result::NOT_SUPPORTED;
 }
 
+Return<void> Stream::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
+    if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
+        analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
+    }
+    return Void();
+}
+
+#ifdef AUDIO_HAL_VERSION_2_0
+Return<void> Stream::debugDump(const hidl_handle& fd) {
+    return debug(fd, {} /* options */);
+}
+#endif
+
 }  // namespace implementation
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
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
index 7380dae..f226e63 100644
--- 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
@@ -58,11 +58,15 @@
     Return<uint64_t> getFrameCount() override;
     Return<uint64_t> getBufferSize() override;
     Return<uint32_t> getSampleRate() override;
+#ifdef AUDIO_HAL_VERSION_2_0
     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;
+#endif
+    Return<void> getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb);
+    Return<void> getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb);
+    Return<Result> setSampleRate(uint32_t sampleRateHz) override;
+    Return<AudioChannelBitfield> getChannelMask() override;
+    Return<Result> setChannelMask(AudioChannelBitfield mask) override;
     Return<AudioFormat> getFormat() override;
     Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb) override;
     Return<Result> setFormat(AudioFormat format) override;
@@ -70,16 +74,30 @@
     Return<Result> addEffect(uint64_t effectId) override;
     Return<Result> removeEffect(uint64_t effectId) override;
     Return<Result> standby() override;
+#ifdef AUDIO_HAL_VERSION_2_0
     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> setConnectedState(const DeviceAddress& address, bool connected) override;
+#elif defined(AUDIO_HAL_VERSION_4_0)
+    Return<void> getDevices(getDevices_cb _hidl_cb) override;
+    Return<Result> setDevices(const hidl_vec<DeviceAddress>& devices) override;
+    Return<void> getParameters(const hidl_vec<ParameterValue>& context,
+                               const hidl_vec<hidl_string>& keys,
+                               getParameters_cb _hidl_cb) override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& context,
+                                 const hidl_vec<ParameterValue>& parameters) override;
+#endif
+    Return<Result> setHwAvSync(uint32_t hwAvSync) override;
     Return<Result> close() override;
 
+    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
+#ifdef AUDIO_HAL_VERSION_2_0
+    Return<void> debugDump(const hidl_handle& fd) override;
+#endif
+
     // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamIn follow.
     Return<void> getAudioSource(getAudioSource_cb _hidl_cb) override;
     Return<Result> setGain(float gain) override;
@@ -91,6 +109,10 @@
     Return<Result> stop() override;
     Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
     Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
+#ifdef AUDIO_HAL_VERSION_4_0
+    Return<void> updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
+    Return<void> getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) override;
+#endif
 
     static Result getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames,
                                          uint64_t* time);
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
index abee225..8774be9 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
@@ -26,6 +26,8 @@
 
 using ::android::hardware::audio::AUDIO_HAL_VERSION::MessageQueueFlagBits;
 using ::android::hardware::audio::all_versions::implementation::isGainNormalized;
+#include "Conversions.h"
+#include "Util.h"
 
 namespace android {
 namespace hardware {
@@ -179,23 +181,33 @@
     return mStreamCommon->getSampleRate();
 }
 
+#ifdef AUDIO_HAL_VERSION_2_0
+Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
+    return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
+}
 Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
     return mStreamCommon->getSupportedSampleRates(_hidl_cb);
 }
+#endif
+
+Return<void> StreamIn::getSupportedChannelMasks(AudioFormat format,
+                                                getSupportedChannelMasks_cb _hidl_cb) {
+    return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb);
+}
+Return<void> StreamIn::getSupportedSampleRates(AudioFormat format,
+                                               getSupportedSampleRates_cb _hidl_cb) {
+    return mStreamCommon->getSupportedSampleRates(format, _hidl_cb);
+}
 
 Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz) {
     return mStreamCommon->setSampleRate(sampleRateHz);
 }
 
-Return<AudioChannelMask> StreamIn::getChannelMask() {
+Return<AudioChannelBitfield> StreamIn::getChannelMask() {
     return mStreamCommon->getChannelMask();
 }
 
-Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
-    return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
-}
-
-Return<Result> StreamIn::setChannelMask(AudioChannelMask mask) {
+Return<Result> StreamIn::setChannelMask(AudioChannelBitfield mask) {
     return mStreamCommon->setChannelMask(mask);
 }
 
@@ -227,6 +239,15 @@
     return mStreamCommon->standby();
 }
 
+Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) {
+    return mStreamCommon->setHwAvSync(hwAvSync);
+}
+
+#ifdef AUDIO_HAL_VERSION_2_0
+Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected) {
+    return mStreamCommon->setConnectedState(address, connected);
+}
+
 Return<AudioDevice> StreamIn::getDevice() {
     return mStreamCommon->getDevice();
 }
@@ -235,14 +256,6 @@
     return mStreamCommon->setDevice(address);
 }
 
-Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected) {
-    return mStreamCommon->setConnectedState(address, connected);
-}
-
-Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) {
-    return mStreamCommon->setHwAvSync(hwAvSync);
-}
-
 Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
     return mStreamCommon->getParameters(keys, _hidl_cb);
 }
@@ -254,6 +267,24 @@
 Return<void> StreamIn::debugDump(const hidl_handle& fd) {
     return mStreamCommon->debugDump(fd);
 }
+#elif defined(AUDIO_HAL_VERSION_4_0)
+Return<void> StreamIn::getDevices(getDevices_cb _hidl_cb) {
+    return mStreamCommon->getDevices(_hidl_cb);
+}
+
+Return<Result> StreamIn::setDevices(const hidl_vec<DeviceAddress>& devices) {
+    return mStreamCommon->setDevices(devices);
+}
+Return<void> StreamIn::getParameters(const hidl_vec<ParameterValue>& context,
+                                     const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
+    return mStreamCommon->getParameters(context, keys, _hidl_cb);
+}
+
+Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& context,
+                                       const hidl_vec<ParameterValue>& parameters) {
+    return mStreamCommon->setParameters(context, parameters);
+}
+#endif
 
 Return<Result> StreamIn::start() {
     return mStreamMmap->start();
@@ -415,6 +446,48 @@
     return Void();
 }
 
+Return<void> StreamIn::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+    return mStreamCommon->debug(fd, options);
+}
+
+#ifdef AUDIO_HAL_VERSION_4_0
+Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
+    if (mStream->update_sink_metadata == nullptr) {
+        return Void();  // not supported by the HAL
+    }
+    std::vector<record_track_metadata> halTracks;
+    halTracks.reserve(sinkMetadata.tracks.size());
+    for (auto& metadata : sinkMetadata.tracks) {
+        halTracks.push_back(
+            {.source = static_cast<audio_source_t>(metadata.source), .gain = metadata.gain});
+    }
+    const sink_metadata_t halMetadata = {
+        .track_count = halTracks.size(), .tracks = halTracks.data(),
+    };
+    mStream->update_sink_metadata(mStream, &halMetadata);
+    return Void();
+}
+
+Return<void> StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) {
+    Result retval = Result::NOT_SUPPORTED;
+    size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
+    audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
+
+    hidl_vec<MicrophoneInfo> microphones;
+    if (mStream->get_active_microphones != NULL &&
+        mStream->get_active_microphones(mStream, &mic_array[0], &actual_mics) == 0) {
+        microphones.resize(actual_mics);
+        for (size_t i = 0; i < actual_mics; ++i) {
+            halToMicrophoneCharacteristics(&microphones[i], mic_array[i]);
+        }
+        retval = Result::OK;
+    }
+
+    _hidl_cb(retval, microphones);
+    return Void();
+}
+#endif
+
 }  // namespace implementation
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
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
index 4cfe2e3..134d7b9 100644
--- 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
@@ -60,11 +60,15 @@
     Return<uint64_t> getFrameCount() override;
     Return<uint64_t> getBufferSize() override;
     Return<uint32_t> getSampleRate() override;
+#ifdef AUDIO_HAL_VERSION_2_0
     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;
+#endif
+    Return<void> getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb);
+    Return<void> getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb);
+    Return<Result> setSampleRate(uint32_t sampleRateHz) override;
+    Return<AudioChannelBitfield> getChannelMask() override;
+    Return<Result> setChannelMask(AudioChannelBitfield mask) override;
     Return<AudioFormat> getFormat() override;
     Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb) override;
     Return<Result> setFormat(AudioFormat format) override;
@@ -72,16 +76,30 @@
     Return<Result> addEffect(uint64_t effectId) override;
     Return<Result> removeEffect(uint64_t effectId) override;
     Return<Result> standby() override;
+#ifdef AUDIO_HAL_VERSION_2_0
     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> setConnectedState(const DeviceAddress& address, bool connected) override;
+#elif defined(AUDIO_HAL_VERSION_4_0)
+    Return<void> getDevices(getDevices_cb _hidl_cb) override;
+    Return<Result> setDevices(const hidl_vec<DeviceAddress>& devices) override;
+    Return<void> getParameters(const hidl_vec<ParameterValue>& context,
+                               const hidl_vec<hidl_string>& keys,
+                               getParameters_cb _hidl_cb) override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& context,
+                                 const hidl_vec<ParameterValue>& parameters) override;
+#endif
+    Return<Result> setHwAvSync(uint32_t hwAvSync) override;
     Return<Result> close() override;
 
+    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
+#ifdef AUDIO_HAL_VERSION_2_0
+    Return<void> debugDump(const hidl_handle& fd) override;
+#endif
+
     // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamOut follow.
     Return<uint32_t> getLatency() override;
     Return<Result> setVolume(float left, float right) override;
@@ -102,6 +120,10 @@
     Return<Result> stop() override;
     Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
     Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
+#ifdef AUDIO_HAL_VERSION_4_0
+    Return<void> updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
+    Return<Result> selectPresentation(int32_t presentationId, int32_t programId) override;
+#endif
 
     static Result getPresentationPositionImpl(audio_stream_out_t* stream, uint64_t* frames,
                                               TimeSpec* timeStamp);
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h
index bdbeb38..77098a8 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h
@@ -183,23 +183,33 @@
     return mStreamCommon->getSampleRate();
 }
 
+#ifdef AUDIO_HAL_VERSION_2_0
+Return<void> StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
+    return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
+}
 Return<void> StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
     return mStreamCommon->getSupportedSampleRates(_hidl_cb);
 }
+#endif
+
+Return<void> StreamOut::getSupportedChannelMasks(AudioFormat format,
+                                                 getSupportedChannelMasks_cb _hidl_cb) {
+    return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb);
+}
+Return<void> StreamOut::getSupportedSampleRates(AudioFormat format,
+                                                getSupportedSampleRates_cb _hidl_cb) {
+    return mStreamCommon->getSupportedSampleRates(format, _hidl_cb);
+}
 
 Return<Result> StreamOut::setSampleRate(uint32_t sampleRateHz) {
     return mStreamCommon->setSampleRate(sampleRateHz);
 }
 
-Return<AudioChannelMask> StreamOut::getChannelMask() {
+Return<AudioChannelBitfield> StreamOut::getChannelMask() {
     return mStreamCommon->getChannelMask();
 }
 
-Return<void> StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
-    return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
-}
-
-Return<Result> StreamOut::setChannelMask(AudioChannelMask mask) {
+Return<Result> StreamOut::setChannelMask(AudioChannelBitfield mask) {
     return mStreamCommon->setChannelMask(mask);
 }
 
@@ -231,6 +241,15 @@
     return mStreamCommon->standby();
 }
 
+Return<Result> StreamOut::setHwAvSync(uint32_t hwAvSync) {
+    return mStreamCommon->setHwAvSync(hwAvSync);
+}
+
+#ifdef AUDIO_HAL_VERSION_2_0
+Return<Result> StreamOut::setConnectedState(const DeviceAddress& address, bool connected) {
+    return mStreamCommon->setConnectedState(address, connected);
+}
+
 Return<AudioDevice> StreamOut::getDevice() {
     return mStreamCommon->getDevice();
 }
@@ -239,14 +258,6 @@
     return mStreamCommon->setDevice(address);
 }
 
-Return<Result> StreamOut::setConnectedState(const DeviceAddress& address, bool connected) {
-    return mStreamCommon->setConnectedState(address, connected);
-}
-
-Return<Result> StreamOut::setHwAvSync(uint32_t hwAvSync) {
-    return mStreamCommon->setHwAvSync(hwAvSync);
-}
-
 Return<void> StreamOut::getParameters(const hidl_vec<hidl_string>& keys,
                                       getParameters_cb _hidl_cb) {
     return mStreamCommon->getParameters(keys, _hidl_cb);
@@ -259,6 +270,25 @@
 Return<void> StreamOut::debugDump(const hidl_handle& fd) {
     return mStreamCommon->debugDump(fd);
 }
+#elif defined(AUDIO_HAL_VERSION_4_0)
+Return<void> StreamOut::getDevices(getDevices_cb _hidl_cb) {
+    return mStreamCommon->getDevices(_hidl_cb);
+}
+
+Return<Result> StreamOut::setDevices(const hidl_vec<DeviceAddress>& devices) {
+    return mStreamCommon->setDevices(devices);
+}
+Return<void> StreamOut::getParameters(const hidl_vec<ParameterValue>& context,
+                                      const hidl_vec<hidl_string>& keys,
+                                      getParameters_cb _hidl_cb) {
+    return mStreamCommon->getParameters(context, keys, _hidl_cb);
+}
+
+Return<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& context,
+                                        const hidl_vec<ParameterValue>& parameters) {
+    return mStreamCommon->setParameters(context, parameters);
+}
+#endif
 
 Return<Result> StreamOut::close() {
     if (mIsClosed) return Result::INVALID_STATE;
@@ -512,6 +542,35 @@
     return mStreamMmap->getMmapPosition(_hidl_cb);
 }
 
+Return<void> StreamOut::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+    return mStreamCommon->debug(fd, options);
+}
+
+#ifdef AUDIO_HAL_VERSION_4_0
+Return<void> StreamOut::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
+    if (mStream->update_source_metadata == nullptr) {
+        return Void();  // not supported by the HAL
+    }
+    std::vector<playback_track_metadata> halTracks;
+    halTracks.reserve(sourceMetadata.tracks.size());
+    for (auto& metadata : sourceMetadata.tracks) {
+        halTracks.push_back({
+            .usage = static_cast<audio_usage_t>(metadata.usage),
+            .content_type = static_cast<audio_content_type_t>(metadata.contentType),
+            .gain = metadata.gain,
+        });
+    }
+    const source_metadata_t halMetadata = {
+        .track_count = halTracks.size(), .tracks = halTracks.data(),
+    };
+    mStream->update_source_metadata(mStream, &halMetadata);
+    return Void();
+}
+Return<Result> StreamOut::selectPresentation(int32_t /*presentationId*/, int32_t /*programId*/) {
+    return Result::NOT_SUPPORTED;  // TODO: propagate to legacy
+}
+#endif
+
 }  // namespace implementation
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
diff --git a/audio/effect/4.0/default/AcousticEchoCancelerEffect.cpp b/audio/effect/4.0/default/AcousticEchoCancelerEffect.cpp
new file mode 100644
index 0000000..242740e
--- /dev/null
+++ b/audio/effect/4.0/default/AcousticEchoCancelerEffect.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.
+ */
+
+#define LOG_TAG "AEC_Effect_HAL"
+
+#include "AcousticEchoCancelerEffect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/AcousticEchoCancelerEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/AcousticEchoCancelerEffect.h b/audio/effect/4.0/default/AcousticEchoCancelerEffect.h
new file mode 100644
index 0000000..0ac0a1e
--- /dev/null
+++ b/audio/effect/4.0/default/AcousticEchoCancelerEffect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ACOUSTICECHOCANCELEREFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ACOUSTICECHOCANCELEREFFECT_H
+
+#include <android/hardware/audio/effect/4.0/IAcousticEchoCancelerEffect.h>
+
+#include "Effect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/AcousticEchoCancelerEffect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ACOUSTICECHOCANCELEREFFECT_H
diff --git a/audio/effect/4.0/default/Android.bp b/audio/effect/4.0/default/Android.bp
new file mode 100644
index 0000000..dcb2269
--- /dev/null
+++ b/audio/effect/4.0/default/Android.bp
@@ -0,0 +1,50 @@
+cc_library_shared {
+    name: "android.hardware.audio.effect@4.0-impl",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: [
+        "AcousticEchoCancelerEffect.cpp",
+        "AudioBufferManager.cpp",
+        "AutomaticGainControlEffect.cpp",
+        "BassBoostEffect.cpp",
+        "Conversions.cpp",
+        "DownmixEffect.cpp",
+        "Effect.cpp",
+        "EffectsFactory.cpp",
+        "EnvironmentalReverbEffect.cpp",
+        "EqualizerEffect.cpp",
+        "LoudnessEnhancerEffect.cpp",
+        "NoiseSuppressionEffect.cpp",
+        "PresetReverbEffect.cpp",
+        "VirtualizerEffect.cpp",
+        "VisualizerEffect.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libeffects",
+        "libfmq",
+        "libhidlbase",
+        "libhidlmemory",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.audio.common-util",
+        "android.hardware.audio.common@4.0",
+        "android.hardware.audio.common@4.0-util",
+        "android.hardware.audio.effect@4.0",
+        "android.hidl.memory@1.0",
+    ],
+
+    header_libs: [
+        "android.hardware.audio.common.util@all-versions",
+        "android.hardware.audio.effect@all-versions-impl",
+        "libaudio_system_headers",
+        "libaudioclient_headers",
+        "libeffects_headers",
+        "libhardware_headers",
+        "libmedia_headers",
+    ],
+}
diff --git a/audio/effect/4.0/default/AudioBufferManager.cpp b/audio/effect/4.0/default/AudioBufferManager.cpp
new file mode 100644
index 0000000..2d75f3f
--- /dev/null
+++ b/audio/effect/4.0/default/AudioBufferManager.cpp
@@ -0,0 +1,21 @@
+/*
+ * 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 "AudioBufferManager.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/AudioBufferManager.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/AudioBufferManager.h b/audio/effect/4.0/default/AudioBufferManager.h
new file mode 100644
index 0000000..1f151e6
--- /dev/null
+++ b/audio/effect/4.0/default/AudioBufferManager.h
@@ -0,0 +1,26 @@
+/*
+ * 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_AUDIO_EFFECT_V4_0_AUDIO_BUFFER_MANAGER_H_
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_AUDIO_BUFFER_MANAGER_H_
+
+#include <android/hardware/audio/effect/4.0/types.h>
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/AudioBufferManager.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_AUDIO_BUFFER_MANAGER_H_
diff --git a/audio/effect/4.0/default/AutomaticGainControlEffect.cpp b/audio/effect/4.0/default/AutomaticGainControlEffect.cpp
new file mode 100644
index 0000000..9d21c8a
--- /dev/null
+++ b/audio/effect/4.0/default/AutomaticGainControlEffect.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.
+ */
+
+#define LOG_TAG "AGC_Effect_HAL"
+
+#include "AutomaticGainControlEffect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/AutomaticGainControlEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/AutomaticGainControlEffect.h b/audio/effect/4.0/default/AutomaticGainControlEffect.h
new file mode 100644
index 0000000..7f12007
--- /dev/null
+++ b/audio/effect/4.0/default/AutomaticGainControlEffect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_AUTOMATICGAINCONTROLEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_AUTOMATICGAINCONTROLEFFECT_H
+
+#include <android/hardware/audio/effect/4.0/IAutomaticGainControlEffect.h>
+
+#include "Effect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/AutomaticGainControlEffect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_AUTOMATICGAINCONTROLEFFECT_H
diff --git a/audio/effect/4.0/default/BassBoostEffect.cpp b/audio/effect/4.0/default/BassBoostEffect.cpp
new file mode 100644
index 0000000..74a626b
--- /dev/null
+++ b/audio/effect/4.0/default/BassBoostEffect.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.
+ */
+
+#define LOG_TAG "BassBoost_HAL"
+
+#include "BassBoostEffect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/BassBoostEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/BassBoostEffect.h b/audio/effect/4.0/default/BassBoostEffect.h
new file mode 100644
index 0000000..206a75f
--- /dev/null
+++ b/audio/effect/4.0/default/BassBoostEffect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_BASSBOOSTEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_BASSBOOSTEFFECT_H
+
+#include <android/hardware/audio/effect/4.0/IBassBoostEffect.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/BassBoostEffect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_BASSBOOSTEFFECT_H
diff --git a/audio/effect/4.0/default/Conversions.cpp b/audio/effect/4.0/default/Conversions.cpp
new file mode 100644
index 0000000..91285ae
--- /dev/null
+++ b/audio/effect/4.0/default/Conversions.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 "Conversions.h"
+#include "HidlUtils.h"
+
+using ::android::hardware::audio::common::V4_0::HidlUtils;
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/Conversions.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/Conversions.h b/audio/effect/4.0/default/Conversions.h
new file mode 100644
index 0000000..50e380f
--- /dev/null
+++ b/audio/effect/4.0/default/Conversions.h
@@ -0,0 +1,26 @@
+/*
+ * 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_AUDIO_EFFECT_V4_0_CONVERSIONS_H_
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_CONVERSIONS_H_
+
+#include <android/hardware/audio/effect/4.0/types.h>
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/Conversions.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_CONVERSIONS_H_
diff --git a/audio/effect/4.0/default/DownmixEffect.cpp b/audio/effect/4.0/default/DownmixEffect.cpp
new file mode 100644
index 0000000..07fcab2
--- /dev/null
+++ b/audio/effect/4.0/default/DownmixEffect.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.
+ */
+
+#define LOG_TAG "Downmix_HAL"
+
+#include "DownmixEffect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/DownmixEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/DownmixEffect.h b/audio/effect/4.0/default/DownmixEffect.h
new file mode 100644
index 0000000..5ae820b
--- /dev/null
+++ b/audio/effect/4.0/default/DownmixEffect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_DOWNMIXEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_DOWNMIXEFFECT_H
+
+#include <android/hardware/audio/effect/4.0/IDownmixEffect.h>
+
+#include "Effect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/DownmixEffect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_DOWNMIXEFFECT_H
diff --git a/audio/effect/4.0/default/Effect.cpp b/audio/effect/4.0/default/Effect.cpp
new file mode 100644
index 0000000..707044b
--- /dev/null
+++ b/audio/effect/4.0/default/Effect.cpp
@@ -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.
+ */
+
+#include <memory.h>
+
+#define LOG_TAG "EffectHAL"
+#define ATRACE_TAG ATRACE_TAG_AUDIO
+
+#include "Conversions.h"
+#include "Effect.h"
+#include "common/all-versions/default/EffectMap.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/Effect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/Effect.h b/audio/effect/4.0/default/Effect.h
new file mode 100644
index 0000000..9ca79c4
--- /dev/null
+++ b/audio/effect/4.0/default/Effect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EFFECT_H
+
+#include <android/hardware/audio/effect/4.0/IEffect.h>
+
+#include "AudioBufferManager.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/Effect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EFFECT_H
diff --git a/audio/effect/4.0/default/EffectsFactory.cpp b/audio/effect/4.0/default/EffectsFactory.cpp
new file mode 100644
index 0000000..ee0413d
--- /dev/null
+++ b/audio/effect/4.0/default/EffectsFactory.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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 "EffectFactoryHAL"
+#include "EffectsFactory.h"
+#include "AcousticEchoCancelerEffect.h"
+#include "AutomaticGainControlEffect.h"
+#include "BassBoostEffect.h"
+#include "Conversions.h"
+#include "DownmixEffect.h"
+#include "Effect.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"
+
+using ::android::hardware::audio::common::V4_0::HidlUtils;
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/EffectsFactory.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/EffectsFactory.h b/audio/effect/4.0/default/EffectsFactory.h
new file mode 100644
index 0000000..48e4b4c
--- /dev/null
+++ b/audio/effect/4.0/default/EffectsFactory.h
@@ -0,0 +1,29 @@
+/*
+ * 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_AUDIO_EFFECT_V4_0_EFFECTSFACTORY_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EFFECTSFACTORY_H
+
+#include <system/audio_effect.h>
+
+#include <android/hardware/audio/effect/4.0/IEffectsFactory.h>
+
+#include <hidl/MQDescriptor.h>
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/EffectsFactory.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EFFECTSFACTORY_H
diff --git a/audio/effect/4.0/default/EnvironmentalReverbEffect.cpp b/audio/effect/4.0/default/EnvironmentalReverbEffect.cpp
new file mode 100644
index 0000000..cc3102d
--- /dev/null
+++ b/audio/effect/4.0/default/EnvironmentalReverbEffect.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.
+ */
+
+#define LOG_TAG "EnvReverb_HAL"
+#include <android/log.h>
+
+#include "EnvironmentalReverbEffect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/EnvironmentalReverbEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/EnvironmentalReverbEffect.h b/audio/effect/4.0/default/EnvironmentalReverbEffect.h
new file mode 100644
index 0000000..c0fb25c
--- /dev/null
+++ b/audio/effect/4.0/default/EnvironmentalReverbEffect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ENVIRONMENTALREVERBEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ENVIRONMENTALREVERBEFFECT_H
+
+#include <system/audio_effects/effect_environmentalreverb.h>
+
+#include <android/hardware/audio/effect/4.0/IEnvironmentalReverbEffect.h>
+
+#include "Effect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/EnvironmentalReverbEffect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ENVIRONMENTALREVERBEFFECT_H
diff --git a/audio/effect/4.0/default/EqualizerEffect.cpp b/audio/effect/4.0/default/EqualizerEffect.cpp
new file mode 100644
index 0000000..d0a40bc
--- /dev/null
+++ b/audio/effect/4.0/default/EqualizerEffect.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.
+ */
+
+#define LOG_TAG "Equalizer_HAL"
+
+#include "EqualizerEffect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/EqualizerEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/EqualizerEffect.h b/audio/effect/4.0/default/EqualizerEffect.h
new file mode 100644
index 0000000..7c9463b
--- /dev/null
+++ b/audio/effect/4.0/default/EqualizerEffect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EQUALIZEREFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EQUALIZEREFFECT_H
+
+#include <android/hardware/audio/effect/4.0/IEqualizerEffect.h>
+
+#include "Effect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/EqualizerEffect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EQUALIZEREFFECT_H
diff --git a/audio/effect/4.0/default/LoudnessEnhancerEffect.cpp b/audio/effect/4.0/default/LoudnessEnhancerEffect.cpp
new file mode 100644
index 0000000..e3c5184
--- /dev/null
+++ b/audio/effect/4.0/default/LoudnessEnhancerEffect.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.
+ */
+
+#define LOG_TAG "LoudnessEnhancer_HAL"
+
+#include "LoudnessEnhancerEffect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/LoudnessEnhancerEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/LoudnessEnhancerEffect.h b/audio/effect/4.0/default/LoudnessEnhancerEffect.h
new file mode 100644
index 0000000..64fa26a
--- /dev/null
+++ b/audio/effect/4.0/default/LoudnessEnhancerEffect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_LOUDNESSENHANCEREFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_LOUDNESSENHANCEREFFECT_H
+
+#include <android/hardware/audio/effect/4.0/ILoudnessEnhancerEffect.h>
+
+#include "Effect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/LoudnessEnhancerEffect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_LOUDNESSENHANCEREFFECT_H
diff --git a/audio/effect/4.0/default/NoiseSuppressionEffect.cpp b/audio/effect/4.0/default/NoiseSuppressionEffect.cpp
new file mode 100644
index 0000000..e83a8e3
--- /dev/null
+++ b/audio/effect/4.0/default/NoiseSuppressionEffect.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.
+ */
+
+#define LOG_TAG "NS_Effect_HAL"
+
+#include "NoiseSuppressionEffect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/NoiseSuppressionEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/NoiseSuppressionEffect.h b/audio/effect/4.0/default/NoiseSuppressionEffect.h
new file mode 100644
index 0000000..36d45af
--- /dev/null
+++ b/audio/effect/4.0/default/NoiseSuppressionEffect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_NOISESUPPRESSIONEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_NOISESUPPRESSIONEFFECT_H
+
+#include <android/hardware/audio/effect/4.0/INoiseSuppressionEffect.h>
+
+#include "Effect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/NoiseSuppressionEffect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_NOISESUPPRESSIONEFFECT_H
diff --git a/audio/effect/4.0/default/PresetReverbEffect.cpp b/audio/effect/4.0/default/PresetReverbEffect.cpp
new file mode 100644
index 0000000..0c23be7
--- /dev/null
+++ b/audio/effect/4.0/default/PresetReverbEffect.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.
+ */
+
+#define LOG_TAG "PresetReverb_HAL"
+
+#include "PresetReverbEffect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/PresetReverbEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/PresetReverbEffect.h b/audio/effect/4.0/default/PresetReverbEffect.h
new file mode 100644
index 0000000..3eeae0a
--- /dev/null
+++ b/audio/effect/4.0/default/PresetReverbEffect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_PRESETREVERBEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_PRESETREVERBEFFECT_H
+
+#include <android/hardware/audio/effect/4.0/IPresetReverbEffect.h>
+
+#include "Effect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/PresetReverbEffect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_PRESETREVERBEFFECT_H
diff --git a/audio/effect/4.0/default/VirtualizerEffect.cpp b/audio/effect/4.0/default/VirtualizerEffect.cpp
new file mode 100644
index 0000000..f50e8ad
--- /dev/null
+++ b/audio/effect/4.0/default/VirtualizerEffect.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.
+ */
+
+#define LOG_TAG "Virtualizer_HAL"
+
+#include "VirtualizerEffect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/VirtualizerEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/VirtualizerEffect.h b/audio/effect/4.0/default/VirtualizerEffect.h
new file mode 100644
index 0000000..8e7114e
--- /dev/null
+++ b/audio/effect/4.0/default/VirtualizerEffect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VIRTUALIZEREFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VIRTUALIZEREFFECT_H
+
+#include <android/hardware/audio/effect/4.0/IVirtualizerEffect.h>
+
+#include "Effect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/VirtualizerEffect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VIRTUALIZEREFFECT_H
diff --git a/audio/effect/4.0/default/VisualizerEffect.cpp b/audio/effect/4.0/default/VisualizerEffect.cpp
new file mode 100644
index 0000000..8d4f100
--- /dev/null
+++ b/audio/effect/4.0/default/VisualizerEffect.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.
+ */
+
+#define LOG_TAG "Visualizer_HAL"
+
+#include "VisualizerEffect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/VisualizerEffect.impl.h>
+#undef AUDIO_HAL_VERSION
diff --git a/audio/effect/4.0/default/VisualizerEffect.h b/audio/effect/4.0/default/VisualizerEffect.h
new file mode 100644
index 0000000..6b5ab9c
--- /dev/null
+++ b/audio/effect/4.0/default/VisualizerEffect.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VISUALIZEREFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VISUALIZEREFFECT_H
+
+#include <android/hardware/audio/effect/4.0/IVisualizerEffect.h>
+
+#include "Effect.h"
+
+#define AUDIO_HAL_VERSION V4_0
+#include <effect/all-versions/default/VisualizerEffect.h>
+#undef AUDIO_HAL_VERSION
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VISUALIZEREFFECT_H
diff --git a/audio/effect/4.0/vts/OWNERS b/audio/effect/4.0/vts/OWNERS
new file mode 100644
index 0000000..8711a9f
--- /dev/null
+++ b/audio/effect/4.0/vts/OWNERS
@@ -0,0 +1,5 @@
+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/effect/4.0/vts/functional/Android.bp b/audio/effect/4.0/vts/functional/Android.bp
new file mode 100644
index 0000000..92b5db7
--- /dev/null
+++ b/audio/effect/4.0/vts/functional/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_test {
+    name: "VtsHalAudioEffectV4_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "VtsHalAudioEffectV4_0TargetTest.cpp",
+        "ValidateAudioEffectsConfiguration.cpp"
+    ],
+    static_libs: [
+        "android.hardware.audio.common.test.utility",
+        "android.hardware.audio.common@4.0",
+        "android.hardware.audio.effect@4.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libxml2",
+    ],
+    shared_libs: [
+        "libeffectsconfig",
+        "libicuuc",
+    ],
+    header_libs: [
+        "android.hardware.audio.common.util@all-versions",
+    ],
+}
diff --git a/audio/effect/4.0/vts/functional/ValidateAudioEffectsConfiguration.cpp b/audio/effect/4.0/vts/functional/ValidateAudioEffectsConfiguration.cpp
new file mode 100644
index 0000000..6338563
--- /dev/null
+++ b/audio/effect/4.0/vts/functional/ValidateAudioEffectsConfiguration.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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 <iterator>
+
+#include <media/EffectsConfig.h>
+
+#include "utility/ValidateXml.h"
+
+TEST(CheckConfig, audioEffectsConfigurationValidation) {
+    RecordProperty("description",
+                   "Verify that the effects configuration file is valid according to the schema");
+    using namespace android::effectsConfig;
+
+    std::vector<const char*> locations(std::begin(DEFAULT_LOCATIONS), std::end(DEFAULT_LOCATIONS));
+    EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(DEFAULT_NAME, locations,
+                                            "/data/local/tmp/audio_effects_conf_V4_0.xsd");
+}
diff --git a/audio/effect/4.0/vts/functional/VtsHalAudioEffectV4_0TargetTest.cpp b/audio/effect/4.0/vts/functional/VtsHalAudioEffectV4_0TargetTest.cpp
new file mode 100644
index 0000000..ec783c4
--- /dev/null
+++ b/audio/effect/4.0/vts/functional/VtsHalAudioEffectV4_0TargetTest.cpp
@@ -0,0 +1,852 @@
+/*
+ * 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 "AudioEffectHidlHalTest"
+#include <android-base/logging.h>
+#include <system/audio.h>
+
+#include <android/hardware/audio/effect/4.0/IEffect.h>
+#include <android/hardware/audio/effect/4.0/IEffectsFactory.h>
+#include <android/hardware/audio/effect/4.0/IEqualizerEffect.h>
+#include <android/hardware/audio/effect/4.0/ILoudnessEnhancerEffect.h>
+#include <android/hardware/audio/effect/4.0/types.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+
+#include <common/all-versions/VersionUtils.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using android::hardware::audio::common::V4_0::AudioDevice;
+using android::hardware::audio::common::V4_0::AudioHandleConsts;
+using android::hardware::audio::common::V4_0::AudioMode;
+using android::hardware::audio::common::V4_0::AudioSource;
+using android::hardware::audio::common::V4_0::Uuid;
+using android::hardware::audio::common::utils::mkBitfield;
+using android::hardware::audio::effect::V4_0::AudioBuffer;
+using android::hardware::audio::effect::V4_0::EffectAuxChannelsConfig;
+using android::hardware::audio::effect::V4_0::EffectBufferConfig;
+using android::hardware::audio::effect::V4_0::EffectConfig;
+using android::hardware::audio::effect::V4_0::EffectDescriptor;
+using android::hardware::audio::effect::V4_0::EffectOffloadParameter;
+using android::hardware::audio::effect::V4_0::IEffect;
+using android::hardware::audio::effect::V4_0::IEffectsFactory;
+using android::hardware::audio::effect::V4_0::IEqualizerEffect;
+using android::hardware::audio::effect::V4_0::ILoudnessEnhancerEffect;
+using android::hardware::audio::effect::V4_0::Result;
+using android::hardware::MQDescriptorSync;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_memory;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hidl::allocator::V1_0::IAllocator;
+using android::hidl::memory::V1_0::IMemory;
+using android::sp;
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+#endif
+
+// Test environment for Audio Effects Factory HIDL HAL.
+class AudioEffectsFactoryHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static AudioEffectsFactoryHidlEnvironment* Instance() {
+        static AudioEffectsFactoryHidlEnvironment* instance =
+            new AudioEffectsFactoryHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IEffectsFactory>(); }
+};
+
+// The main test class for Audio Effects Factory HIDL HAL.
+class AudioEffectsFactoryHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+  void SetUp() override {
+      effectsFactory = ::testing::VtsHalHidlTargetTestBase::getService<IEffectsFactory>(
+          AudioEffectsFactoryHidlEnvironment::Instance()->getServiceName<IEffectsFactory>());
+      ASSERT_NE(effectsFactory, nullptr);
+  }
+
+  void TearDown() override { effectsFactory.clear(); }
+
+ protected:
+  static void description(const std::string& description) {
+    RecordProperty("description", description);
+  }
+
+  sp<IEffectsFactory> effectsFactory;
+};
+
+TEST_F(AudioEffectsFactoryHidlTest, EnumerateEffects) {
+  description("Verify that EnumerateEffects returns at least one effect");
+  Result retval = Result::NOT_INITIALIZED;
+  size_t effectCount = 0;
+  Return<void> ret = effectsFactory->getAllDescriptors(
+      [&](Result r, const hidl_vec<EffectDescriptor>& result) {
+        retval = r;
+        effectCount = result.size();
+      });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  EXPECT_GT(effectCount, 0u);
+}
+
+TEST_F(AudioEffectsFactoryHidlTest, CreateEffect) {
+  description("Verify that an effect can be created via CreateEffect");
+  bool gotEffect = false;
+  Uuid effectUuid;
+  Return<void> ret = effectsFactory->getAllDescriptors(
+      [&](Result r, const hidl_vec<EffectDescriptor>& result) {
+        if (r == Result::OK && result.size() > 0) {
+          gotEffect = true;
+          effectUuid = result[0].uuid;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(gotEffect);
+  Result retval = Result::NOT_INITIALIZED;
+  sp<IEffect> effect;
+  ret = effectsFactory->createEffect(
+      effectUuid, 1 /*session*/, 1 /*ioHandle*/,
+      [&](Result r, const sp<IEffect>& result, uint64_t /*effectId*/) {
+        retval = r;
+        if (r == Result::OK) {
+          effect = result;
+        }
+      });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  EXPECT_NE(nullptr, effect.get());
+}
+
+TEST_F(AudioEffectsFactoryHidlTest, GetDescriptor) {
+  description(
+      "Verify that effects factory can provide an effect descriptor via "
+      "GetDescriptor");
+  hidl_vec<EffectDescriptor> allDescriptors;
+  Return<void> ret = effectsFactory->getAllDescriptors(
+      [&](Result r, const hidl_vec<EffectDescriptor>& result) {
+        if (r == Result::OK) {
+          allDescriptors = result;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_GT(allDescriptors.size(), 0u);
+  for (size_t i = 0; i < allDescriptors.size(); ++i) {
+    ret = effectsFactory->getDescriptor(
+        allDescriptors[i].uuid, [&](Result r, const EffectDescriptor& result) {
+          EXPECT_EQ(r, Result::OK);
+          EXPECT_EQ(result, allDescriptors[i]);
+        });
+  }
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectsFactoryHidlTest, DebugDumpInvalidArgument) {
+    description("Verify that debugDump doesn't crash on invalid arguments");
+    Return<void> ret = effectsFactory->debug(hidl_handle(), {});
+    ASSERT_TRUE(ret.isOk());
+}
+
+// Equalizer effect is required by CDD, but only the type is fixed.
+// This is the same UUID as AudioEffect.EFFECT_TYPE_EQUALIZER in Java.
+static const Uuid EQUALIZER_EFFECT_TYPE = {
+    0x0bed4300, 0xddd6, 0x11db, 0x8f34,
+    std::array<uint8_t, 6>{{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}};
+// Loudness Enhancer effect is required by CDD, but only the type is fixed.
+// This is the same UUID as AudioEffect.EFFECT_TYPE_LOUDNESS_ENHANCER in Java.
+static const Uuid LOUDNESS_ENHANCER_EFFECT_TYPE = {
+    0xfe3199be, 0xaed0, 0x413f, 0x87bb,
+    std::array<uint8_t, 6>{{0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}}};
+
+// The main test class for Audio Effect HIDL HAL.
+class AudioEffectHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+  void SetUp() override {
+    effectsFactory =
+        ::testing::VtsHalHidlTargetTestBase::getService<IEffectsFactory>();
+    ASSERT_NE(nullptr, effectsFactory.get());
+
+    findAndCreateEffect(getEffectType());
+    ASSERT_NE(nullptr, effect.get());
+
+    Return<Result> ret = effect->init();
+    ASSERT_TRUE(ret.isOk());
+    ASSERT_EQ(Result::OK, ret);
+  }
+
+  void TearDown() override {
+    effect.clear();
+    effectsFactory.clear();
+  }
+
+ protected:
+  static void description(const std::string& description) {
+    RecordProperty("description", description);
+  }
+
+  virtual Uuid getEffectType() { return EQUALIZER_EFFECT_TYPE; }
+
+  void findAndCreateEffect(const Uuid& type);
+  void findEffectInstance(const Uuid& type, Uuid* uuid);
+  void getChannelCount(uint32_t* channelCount);
+
+  sp<IEffectsFactory> effectsFactory;
+  sp<IEffect> effect;
+};
+
+void AudioEffectHidlTest::findAndCreateEffect(const Uuid& type) {
+  Uuid effectUuid;
+  findEffectInstance(type, &effectUuid);
+  Return<void> ret = effectsFactory->createEffect(
+      effectUuid, 1 /*session*/, 1 /*ioHandle*/,
+      [&](Result r, const sp<IEffect>& result, uint64_t /*effectId*/) {
+        if (r == Result::OK) {
+          effect = result;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+}
+
+void AudioEffectHidlTest::findEffectInstance(const Uuid& type, Uuid* uuid) {
+  bool effectFound = false;
+  Return<void> ret = effectsFactory->getAllDescriptors(
+      [&](Result r, const hidl_vec<EffectDescriptor>& result) {
+        if (r == Result::OK) {
+          for (const auto& desc : result) {
+            if (desc.type == type) {
+              effectFound = true;
+              *uuid = desc.uuid;
+              break;
+            }
+          }
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(effectFound);
+}
+
+void AudioEffectHidlTest::getChannelCount(uint32_t* channelCount) {
+  Result retval;
+  EffectConfig currentConfig;
+  Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+    retval = r;
+    if (r == Result::OK) {
+      currentConfig = conf;
+    }
+  });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+  ASSERT_TRUE(audio_channel_mask_is_valid(
+      static_cast<audio_channel_mask_t>(currentConfig.outputCfg.channels)));
+  *channelCount = audio_channel_count_from_out_mask(
+      static_cast<audio_channel_mask_t>(currentConfig.outputCfg.channels));
+}
+
+TEST_F(AudioEffectHidlTest, Close) {
+  description("Verify that an effect can be closed");
+  Return<Result> ret = effect->close();
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+}
+
+TEST_F(AudioEffectHidlTest, GetDescriptor) {
+  description(
+      "Verify that an effect can return its own descriptor via GetDescriptor");
+  Result retval = Result::NOT_INITIALIZED;
+  Uuid actualType;
+  Return<void> ret =
+      effect->getDescriptor([&](Result r, const EffectDescriptor& desc) {
+        retval = r;
+        if (r == Result::OK) {
+          actualType = desc.type;
+        }
+      });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  EXPECT_EQ(getEffectType(), actualType);
+}
+
+TEST_F(AudioEffectHidlTest, GetSetConfig) {
+  description(
+      "Verify that it is possible to manipulate effect config via Get / "
+      "SetConfig");
+  Result retval = Result::NOT_INITIALIZED;
+  EffectConfig currentConfig;
+  Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+    retval = r;
+    if (r == Result::OK) {
+      currentConfig = conf;
+    }
+  });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  Return<Result> ret2 = effect->setConfig(currentConfig, nullptr, nullptr);
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, ret2);
+}
+
+TEST_F(AudioEffectHidlTest, GetConfigReverse) {
+  description("Verify that GetConfigReverse does not crash");
+  Return<void> ret =
+      effect->getConfigReverse([&](Result, const EffectConfig&) {});
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, GetSupportedAuxChannelsConfigs) {
+  description("Verify that GetSupportedAuxChannelsConfigs does not crash");
+  Return<void> ret = effect->getSupportedAuxChannelsConfigs(
+      0, [&](Result, const hidl_vec<EffectAuxChannelsConfig>&) {});
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, GetAuxChannelsConfig) {
+  description("Verify that GetAuxChannelsConfig does not crash");
+  Return<void> ret = effect->getAuxChannelsConfig(
+      [&](Result, const EffectAuxChannelsConfig&) {});
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, SetAuxChannelsConfig) {
+  description("Verify that SetAuxChannelsConfig does not crash");
+  Return<Result> ret = effect->setAuxChannelsConfig(EffectAuxChannelsConfig());
+  EXPECT_TRUE(ret.isOk());
+}
+
+// Not generated automatically because AudioBuffer contains
+// instances of hidl_memory which can't be compared properly
+// in general case due to presence of handles.
+//
+// However, in this particular case, handles must not present
+// thus comparison is possible.
+//
+// operator== must be defined in the same namespace as the structures.
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V4_0 {
+inline bool operator==(const AudioBuffer& lhs, const AudioBuffer& rhs) {
+  return lhs.id == rhs.id && lhs.frameCount == rhs.frameCount &&
+         lhs.data.handle() == nullptr && rhs.data.handle() == nullptr;
+}
+
+inline bool operator==(const EffectBufferConfig& lhs,
+                       const EffectBufferConfig& rhs) {
+  return lhs.buffer == rhs.buffer && lhs.samplingRateHz == rhs.samplingRateHz &&
+         lhs.channels == rhs.channels && lhs.format == rhs.format &&
+         lhs.accessMode == rhs.accessMode && lhs.mask == rhs.mask;
+}
+
+inline bool operator==(const EffectConfig& lhs, const EffectConfig& rhs) {
+  return lhs.inputCfg == rhs.inputCfg && lhs.outputCfg == rhs.outputCfg;
+}
+}  // namespace V4_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+TEST_F(AudioEffectHidlTest, Reset) {
+  description("Verify that Reset preserves effect configuration");
+  Result retval = Result::NOT_INITIALIZED;
+  EffectConfig originalConfig;
+  Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+    retval = r;
+    if (r == Result::OK) {
+      originalConfig = conf;
+    }
+  });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+  Return<Result> ret2 = effect->reset();
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, ret2);
+  EffectConfig configAfterReset;
+  ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+    retval = r;
+    if (r == Result::OK) {
+      configAfterReset = conf;
+    }
+  });
+  EXPECT_EQ(originalConfig, configAfterReset);
+}
+
+TEST_F(AudioEffectHidlTest, DisableEnableDisable) {
+  description("Verify Disable -> Enable -> Disable sequence for an effect");
+  Return<Result> ret = effect->disable();
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::INVALID_ARGUMENTS, ret);
+  ret = effect->enable();
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+  ret = effect->disable();
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+}
+
+TEST_F(AudioEffectHidlTest, SetDevice) {
+  description("Verify that SetDevice works for an output chain effect");
+  Return<Result> ret = effect->setDevice(mkBitfield(AudioDevice::OUT_SPEAKER));
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+}
+
+TEST_F(AudioEffectHidlTest, SetAndGetVolume) {
+  description("Verify that SetAndGetVolume method works for an effect");
+  uint32_t channelCount;
+  getChannelCount(&channelCount);
+  hidl_vec<uint32_t> volumes;
+  volumes.resize(channelCount);
+  for (uint32_t i = 0; i < channelCount; ++i) {
+    volumes[i] = 0;
+  }
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret = effect->setAndGetVolume(
+      volumes, [&](Result r, const hidl_vec<uint32_t>&) { retval = r; });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, retval);
+}
+
+TEST_F(AudioEffectHidlTest, VolumeChangeNotification) {
+  description("Verify that effect accepts VolumeChangeNotification");
+  uint32_t channelCount;
+  getChannelCount(&channelCount);
+  hidl_vec<uint32_t> volumes;
+  volumes.resize(channelCount);
+  for (uint32_t i = 0; i < channelCount; ++i) {
+    volumes[i] = 0;
+  }
+  Return<Result> ret = effect->volumeChangeNotification(volumes);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+}
+
+TEST_F(AudioEffectHidlTest, SetAudioMode) {
+  description("Verify that SetAudioMode works for an effect");
+  Return<Result> ret = effect->setAudioMode(AudioMode::NORMAL);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+}
+
+TEST_F(AudioEffectHidlTest, SetConfigReverse) {
+  description("Verify that SetConfigReverse does not crash");
+  Return<Result> ret =
+      effect->setConfigReverse(EffectConfig(), nullptr, nullptr);
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, SetInputDevice) {
+  description("Verify that SetInputDevice does not crash");
+  Return<Result> ret = effect->setInputDevice(mkBitfield(AudioDevice::IN_BUILTIN_MIC));
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, SetAudioSource) {
+  description("Verify that SetAudioSource does not crash");
+  Return<Result> ret = effect->setAudioSource(AudioSource::MIC);
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, Offload) {
+  description("Verify that calling Offload method does not crash");
+  EffectOffloadParameter offloadParam;
+  offloadParam.isOffload = false;
+  offloadParam.ioHandle =
+      static_cast<int>(AudioHandleConsts::AUDIO_IO_HANDLE_NONE);
+  Return<Result> ret = effect->offload(offloadParam);
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, PrepareForProcessing) {
+  description("Verify that PrepareForProcessing method works for an effect");
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret = effect->prepareForProcessing(
+      [&](Result r, const MQDescriptorSync<Result>&) { retval = r; });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, retval);
+}
+
+TEST_F(AudioEffectHidlTest, SetProcessBuffers) {
+  description("Verify that SetProcessBuffers works for an effect");
+  sp<IAllocator> ashmem = IAllocator::getService("ashmem");
+  ASSERT_NE(nullptr, ashmem.get());
+  bool success = false;
+  AudioBuffer buffer;
+  Return<void> ret =
+      ashmem->allocate(1024, [&](bool s, const hidl_memory& memory) {
+        success = s;
+        if (s) {
+          buffer.data = memory;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(success);
+  Return<Result> ret2 = effect->setProcessBuffers(buffer, buffer);
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, ret2);
+}
+
+TEST_F(AudioEffectHidlTest, Command) {
+  description("Verify that Command does not crash");
+  Return<void> ret = effect->command(0, hidl_vec<uint8_t>(), 0,
+                                     [&](int32_t, const hidl_vec<uint8_t>&) {});
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, SetParameter) {
+  description("Verify that SetParameter does not crash");
+  Return<Result> ret =
+      effect->setParameter(hidl_vec<uint8_t>(), hidl_vec<uint8_t>());
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, GetParameter) {
+  description("Verify that GetParameter does not crash");
+  Return<void> ret = effect->getParameter(
+      hidl_vec<uint8_t>(), 0, [&](Result, const hidl_vec<uint8_t>&) {});
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, GetSupportedConfigsForFeature) {
+  description("Verify that GetSupportedConfigsForFeature does not crash");
+  Return<void> ret = effect->getSupportedConfigsForFeature(
+      0, 0, 0, [&](Result, uint32_t, const hidl_vec<uint8_t>&) {});
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, GetCurrentConfigForFeature) {
+  description("Verify that GetCurrentConfigForFeature does not crash");
+  Return<void> ret = effect->getCurrentConfigForFeature(
+      0, 0, [&](Result, const hidl_vec<uint8_t>&) {});
+  EXPECT_TRUE(ret.isOk());
+}
+
+TEST_F(AudioEffectHidlTest, SetCurrentConfigForFeature) {
+  description("Verify that SetCurrentConfigForFeature does not crash");
+  Return<Result> ret =
+      effect->setCurrentConfigForFeature(0, hidl_vec<uint8_t>());
+  EXPECT_TRUE(ret.isOk());
+}
+
+
+// The main test class for Equalizer Audio Effect HIDL HAL.
+class EqualizerAudioEffectHidlTest : public AudioEffectHidlTest {
+ public:
+  void SetUp() override {
+    AudioEffectHidlTest::SetUp();
+    equalizer = IEqualizerEffect::castFrom(effect);
+    ASSERT_NE(nullptr, equalizer.get());
+  }
+
+ protected:
+  Uuid getEffectType() override { return EQUALIZER_EFFECT_TYPE; }
+  void getNumBands(uint16_t* numBands);
+  void getLevelRange(int16_t* minLevel, int16_t* maxLevel);
+  void getBandFrequencyRange(uint16_t band, uint32_t* minFreq,
+                             uint32_t* centerFreq, uint32_t* maxFreq);
+  void getPresetCount(size_t* count);
+
+  sp<IEqualizerEffect> equalizer;
+};
+
+void EqualizerAudioEffectHidlTest::getNumBands(uint16_t* numBands) {
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret = equalizer->getNumBands([&](Result r, uint16_t b) {
+    retval = r;
+    if (retval == Result::OK) {
+      *numBands = b;
+    }
+  });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+}
+
+void EqualizerAudioEffectHidlTest::getLevelRange(int16_t* minLevel,
+                                                 int16_t* maxLevel) {
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret =
+      equalizer->getLevelRange([&](Result r, int16_t min, int16_t max) {
+        retval = r;
+        if (retval == Result::OK) {
+          *minLevel = min;
+          *maxLevel = max;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+}
+
+void EqualizerAudioEffectHidlTest::getBandFrequencyRange(uint16_t band,
+                                                         uint32_t* minFreq,
+                                                         uint32_t* centerFreq,
+                                                         uint32_t* maxFreq) {
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret = equalizer->getBandFrequencyRange(
+      band, [&](Result r, uint32_t min, uint32_t max) {
+        retval = r;
+        if (retval == Result::OK) {
+          *minFreq = min;
+          *maxFreq = max;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+  ret = equalizer->getBandCenterFrequency(band, [&](Result r, uint32_t center) {
+    retval = r;
+    if (retval == Result::OK) {
+      *centerFreq = center;
+    }
+  });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+}
+
+void EqualizerAudioEffectHidlTest::getPresetCount(size_t* count) {
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret = equalizer->getPresetNames(
+      [&](Result r, const hidl_vec<hidl_string>& names) {
+        retval = r;
+        if (retval == Result::OK) {
+          *count = names.size();
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetNumBands) {
+  description("Verify that Equalizer effect reports at least one band");
+  uint16_t numBands = 0;
+  getNumBands(&numBands);
+  EXPECT_GT(numBands, 0);
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetLevelRange) {
+  description("Verify that Equalizer effect reports adequate band level range");
+  int16_t minLevel = 0x7fff, maxLevel = 0;
+  getLevelRange(&minLevel, &maxLevel);
+  EXPECT_GT(maxLevel, minLevel);
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetSetBandLevel) {
+  description(
+      "Verify that manipulating band levels works for Equalizer effect");
+  uint16_t numBands = 0;
+  getNumBands(&numBands);
+  ASSERT_GT(numBands, 0);
+  int16_t levels[3]{0x7fff, 0, 0};
+  getLevelRange(&levels[0], &levels[2]);
+  ASSERT_GT(levels[2], levels[0]);
+  levels[1] = (levels[2] + levels[0]) / 2;
+  for (uint16_t i = 0; i < numBands; ++i) {
+    for (size_t j = 0; j < ARRAY_SIZE(levels); ++j) {
+      Return<Result> ret = equalizer->setBandLevel(i, levels[j]);
+      EXPECT_TRUE(ret.isOk());
+      EXPECT_EQ(Result::OK, ret);
+      Result retval = Result::NOT_INITIALIZED;
+      int16_t actualLevel;
+      Return<void> ret2 = equalizer->getBandLevel(i, [&](Result r, int16_t l) {
+        retval = r;
+        if (retval == Result::OK) {
+          actualLevel = l;
+        }
+      });
+      EXPECT_TRUE(ret2.isOk());
+      EXPECT_EQ(Result::OK, retval);
+      EXPECT_EQ(levels[j], actualLevel);
+    }
+  }
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetBandCenterFrequencyAndRange) {
+  description(
+      "Verify that Equalizer effect reports adequate band frequency range");
+  uint16_t numBands = 0;
+  getNumBands(&numBands);
+  ASSERT_GT(numBands, 0);
+  for (uint16_t i = 0; i < numBands; ++i) {
+    uint32_t minFreq = 0xffffffff, centerFreq = 0xffffffff,
+             maxFreq = 0xffffffff;
+    getBandFrequencyRange(i, &minFreq, &centerFreq, &maxFreq);
+    // Note: NXP legacy implementation reports "1" as upper bound for last band,
+    // so this check fails.
+    EXPECT_GE(maxFreq, centerFreq);
+    EXPECT_GE(centerFreq, minFreq);
+  }
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetBandForFrequency) {
+  description(
+      "Verify that Equalizer effect supports GetBandForFrequency correctly");
+  uint16_t numBands = 0;
+  getNumBands(&numBands);
+  ASSERT_GT(numBands, 0);
+  for (uint16_t i = 0; i < numBands; ++i) {
+    uint32_t freqs[3]{0, 0, 0};
+    getBandFrequencyRange(i, &freqs[0], &freqs[1], &freqs[2]);
+    // NXP legacy implementation reports "1" as upper bound for last band, some
+    // of the checks fail.
+    for (size_t j = 0; j < ARRAY_SIZE(freqs); ++j) {
+      if (j == 0) {
+        freqs[j]++;
+      }  // Min frequency is an open interval.
+      Result retval = Result::NOT_INITIALIZED;
+      uint16_t actualBand = numBands + 1;
+      Return<void> ret =
+          equalizer->getBandForFrequency(freqs[j], [&](Result r, uint16_t b) {
+            retval = r;
+            if (retval == Result::OK) {
+              actualBand = b;
+            }
+          });
+      EXPECT_TRUE(ret.isOk());
+      EXPECT_EQ(Result::OK, retval);
+      EXPECT_EQ(i, actualBand) << "Frequency: " << freqs[j];
+    }
+  }
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetPresetNames) {
+  description("Verify that Equalizer effect reports at least one preset");
+  size_t presetCount;
+  getPresetCount(&presetCount);
+  EXPECT_GT(presetCount, 0u);
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetSetCurrentPreset) {
+  description(
+      "Verify that manipulating the current preset for Equalizer effect");
+  size_t presetCount;
+  getPresetCount(&presetCount);
+  ASSERT_GT(presetCount, 0u);
+  for (uint16_t i = 0; i < presetCount; ++i) {
+    Return<Result> ret = equalizer->setCurrentPreset(i);
+    EXPECT_TRUE(ret.isOk());
+    EXPECT_EQ(Result::OK, ret);
+    Result retval = Result::NOT_INITIALIZED;
+    uint16_t actualPreset = 0xffff;
+    Return<void> ret2 = equalizer->getCurrentPreset([&](Result r, uint16_t p) {
+      retval = r;
+      if (retval == Result::OK) {
+        actualPreset = p;
+      }
+    });
+    EXPECT_TRUE(ret2.isOk());
+    EXPECT_EQ(Result::OK, retval);
+    EXPECT_EQ(i, actualPreset);
+  }
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetSetAllProperties) {
+  description(
+      "Verify that setting band levels and presets works via Get / "
+      "SetAllProperties for Equalizer effect");
+  using AllProperties =
+      android::hardware::audio::effect::V4_0::IEqualizerEffect::AllProperties;
+  uint16_t numBands = 0;
+  getNumBands(&numBands);
+  ASSERT_GT(numBands, 0);
+  AllProperties props;
+  props.bandLevels.resize(numBands);
+  for (size_t i = 0; i < numBands; ++i) {
+    props.bandLevels[i] = 0;
+  }
+
+  AllProperties actualProps;
+  Result retval = Result::NOT_INITIALIZED;
+
+  // Verify setting of the band levels via properties.
+  props.curPreset = -1;
+  Return<Result> ret = equalizer->setAllProperties(props);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+  Return<void> ret2 =
+      equalizer->getAllProperties([&](Result r, AllProperties p) {
+        retval = r;
+        if (retval == Result::OK) {
+          actualProps = p;
+        }
+      });
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  EXPECT_EQ(props.bandLevels, actualProps.bandLevels);
+
+  // Verify setting of the current preset via properties.
+  props.curPreset = 0;  // Assuming there is at least one preset.
+  ret = equalizer->setAllProperties(props);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+  ret2 = equalizer->getAllProperties([&](Result r, AllProperties p) {
+    retval = r;
+    if (retval == Result::OK) {
+      actualProps = p;
+    }
+  });
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  EXPECT_EQ(props.curPreset, actualProps.curPreset);
+}
+
+// The main test class for Equalizer Audio Effect HIDL HAL.
+class LoudnessEnhancerAudioEffectHidlTest : public AudioEffectHidlTest {
+ public:
+  void SetUp() override {
+    AudioEffectHidlTest::SetUp();
+    enhancer = ILoudnessEnhancerEffect::castFrom(effect);
+    ASSERT_NE(nullptr, enhancer.get());
+  }
+
+ protected:
+  Uuid getEffectType() override { return LOUDNESS_ENHANCER_EFFECT_TYPE; }
+
+  sp<ILoudnessEnhancerEffect> enhancer;
+};
+
+TEST_F(LoudnessEnhancerAudioEffectHidlTest, GetSetTargetGain) {
+  description(
+      "Verify that manipulating the target gain works for Loudness Enhancer "
+      "effect");
+  const int32_t gain = 100;
+  Return<Result> ret = enhancer->setTargetGain(gain);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+  int32_t actualGain = 0;
+  Result retval;
+  Return<void> ret2 = enhancer->getTargetGain([&](Result r, int32_t g) {
+    retval = r;
+    if (retval == Result::OK) {
+      actualGain = g;
+    }
+  });
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  EXPECT_EQ(gain, actualGain);
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(AudioEffectsFactoryHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    AudioEffectsFactoryHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/audio/effect/4.0/xml/audio_effects_conf_V4_0.xsd b/audio/effect/4.0/xml/audio_effects_conf_V4_0.xsd
new file mode 120000
index 0000000..82d569a
--- /dev/null
+++ b/audio/effect/4.0/xml/audio_effects_conf_V4_0.xsd
@@ -0,0 +1 @@
+../../2.0/xml/audio_effects_conf_V2_0.xsd
\ No newline at end of file
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
index b63f2fb..852cb3f 100644
--- 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
@@ -20,6 +20,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -46,7 +48,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -54,7 +56,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
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
index bee3607..8ad80a2 100644
--- 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
@@ -19,6 +19,8 @@
 #include <android/log.h>
 #include <system/audio_effects/effect_aec.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -54,7 +56,7 @@
     return mEffect->disable();
 }
 
-Return<Result> AcousticEchoCancelerEffect::setDevice(AudioDevice device) {
+Return<Result> AcousticEchoCancelerEffect::setDevice(AudioDeviceBitfield device) {
     return mEffect->setDevice(device);
 }
 
@@ -78,7 +80,7 @@
     return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> AcousticEchoCancelerEffect::setInputDevice(AudioDevice device) {
+Return<Result> AcousticEchoCancelerEffect::setInputDevice(AudioDeviceBitfield device) {
     return mEffect->setInputDevice(device);
 }
 
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
index 941f45d..5ac43eb 100644
--- 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
@@ -22,6 +22,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -48,7 +50,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -56,7 +58,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
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
index af05d9b..e2e751e 100644
--- 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
@@ -18,6 +18,8 @@
 
 #include <android/log.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -67,7 +69,7 @@
     return mEffect->disable();
 }
 
-Return<Result> AutomaticGainControlEffect::setDevice(AudioDevice device) {
+Return<Result> AutomaticGainControlEffect::setDevice(AudioDeviceBitfield device) {
     return mEffect->setDevice(device);
 }
 
@@ -91,7 +93,7 @@
     return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> AutomaticGainControlEffect::setInputDevice(AudioDevice device) {
+Return<Result> AutomaticGainControlEffect::setInputDevice(AudioDeviceBitfield device) {
     return mEffect->setInputDevice(device);
 }
 
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
index 0092621..29173dd 100644
--- 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
@@ -20,6 +20,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -46,7 +48,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -54,7 +56,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
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
index 1fc8d1b..7bcb4a3 100644
--- 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
@@ -19,6 +19,8 @@
 #include <android/log.h>
 #include <system/audio_effects/effect_bassboost.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -53,7 +55,7 @@
     return mEffect->disable();
 }
 
-Return<Result> BassBoostEffect::setDevice(AudioDevice device) {
+Return<Result> BassBoostEffect::setDevice(AudioDeviceBitfield device) {
     return mEffect->setDevice(device);
 }
 
@@ -76,7 +78,7 @@
     return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> BassBoostEffect::setInputDevice(AudioDevice device) {
+Return<Result> BassBoostEffect::setInputDevice(AudioDeviceBitfield device) {
     return mEffect->setInputDevice(device);
 }
 
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
index e461ca8..3e3aa78 100644
--- 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
@@ -20,6 +20,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -46,7 +48,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -54,7 +56,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
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
index 98710f8..abef10e 100644
--- 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
@@ -19,6 +19,8 @@
 #include <android/log.h>
 #include <system/audio_effects/effect_downmix.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -53,7 +55,7 @@
     return mEffect->disable();
 }
 
-Return<Result> DownmixEffect::setDevice(AudioDevice device) {
+Return<Result> DownmixEffect::setDevice(AudioDeviceBitfield device) {
     return mEffect->setDevice(device);
 }
 
@@ -76,7 +78,7 @@
     return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> DownmixEffect::setInputDevice(AudioDevice device) {
+Return<Result> DownmixEffect::setInputDevice(AudioDeviceBitfield device) {
     return mEffect->setInputDevice(device);
 }
 
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
index 81b0b24..b546e0e 100644
--- 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
@@ -28,6 +28,8 @@
 
 #include <hardware/audio_effect.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -39,6 +41,7 @@
 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::common::AUDIO_HAL_VERSION::implementation::AudioDeviceBitfield;
 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;
@@ -69,7 +72,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -77,7 +80,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
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
index d376146..61c9805 100644
--- 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
@@ -24,6 +24,8 @@
 #include <media/EffectsFactoryApi.h>
 #include <utils/Trace.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -33,6 +35,7 @@
 
 using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask;
 using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioFormat;
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::implementation::AudioChannelBitfield;
 using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::MessageQueueFlagBits;
 
 namespace {
@@ -174,8 +177,8 @@
 // static
 void Effect::effectAuxChannelsConfigFromHal(const channel_config_t& halConfig,
                                             EffectAuxChannelsConfig* config) {
-    config->mainChannels = AudioChannelMask(halConfig.main_channels);
-    config->auxChannels = AudioChannelMask(halConfig.aux_channels);
+    config->mainChannels = AudioChannelBitfield(halConfig.main_channels);
+    config->auxChannels = AudioChannelBitfield(halConfig.aux_channels);
 }
 
 // static
@@ -191,10 +194,10 @@
     config->buffer.id = 0;
     config->buffer.frameCount = 0;
     config->samplingRateHz = halConfig.samplingRate;
-    config->channels = AudioChannelMask(halConfig.channels);
+    config->channels = AudioChannelBitfield(halConfig.channels);
     config->format = AudioFormat(halConfig.format);
     config->accessMode = EffectBufferAccess(halConfig.accessMode);
-    config->mask = EffectConfigParameters(halConfig.mask);
+    config->mask = static_cast<decltype(config->mask)>(halConfig.mask);
 }
 
 // static
@@ -500,7 +503,7 @@
     return sendCommandReturningStatus(EFFECT_CMD_DISABLE, "DISABLE");
 }
 
-Return<Result> Effect::setDevice(AudioDevice device) {
+Return<Result> Effect::setDevice(AudioDeviceBitfield device) {
     uint32_t halDevice = static_cast<uint32_t>(device);
     return sendCommand(EFFECT_CMD_SET_DEVICE, "SET_DEVICE", sizeof(uint32_t), &halDevice);
 }
@@ -539,7 +542,7 @@
                          inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> Effect::setInputDevice(AudioDevice device) {
+Return<Result> Effect::setInputDevice(AudioDeviceBitfield device) {
     uint32_t halDevice = static_cast<uint32_t>(device);
     return sendCommand(EFFECT_CMD_SET_INPUT_DEVICE, "SET_INPUT_DEVICE", sizeof(uint32_t),
                        &halDevice);
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
index e586abb..313c8c2 100644
--- 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
@@ -46,7 +46,7 @@
     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;
+    Return<void> debugDump(const hidl_handle& fd);
 
    private:
     static sp<IEffect> dispatchEffectInstanceCreation(const effect_descriptor_t& halDescriptor,
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
index 8351e55..d2f8cc3 100644
--- 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
@@ -22,6 +22,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -58,7 +60,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -66,7 +68,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
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
index 9090b8a..39a4092 100644
--- 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
@@ -18,6 +18,8 @@
 
 #include <android/log.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -81,7 +83,7 @@
     return mEffect->disable();
 }
 
-Return<Result> EnvironmentalReverbEffect::setDevice(AudioDevice device) {
+Return<Result> EnvironmentalReverbEffect::setDevice(AudioDeviceBitfield device) {
     return mEffect->setDevice(device);
 }
 
@@ -105,7 +107,7 @@
     return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> EnvironmentalReverbEffect::setInputDevice(AudioDevice device) {
+Return<Result> EnvironmentalReverbEffect::setInputDevice(AudioDeviceBitfield device) {
     return mEffect->setInputDevice(device);
 }
 
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
index c2b8ef8..de52052 100644
--- 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
@@ -24,6 +24,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -60,7 +62,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -68,7 +70,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
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
index 78485e4..db6bed8 100644
--- 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
@@ -20,6 +20,8 @@
 
 #include <android/log.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -76,7 +78,7 @@
     return mEffect->disable();
 }
 
-Return<Result> EqualizerEffect::setDevice(AudioDevice device) {
+Return<Result> EqualizerEffect::setDevice(AudioDeviceBitfield device) {
     return mEffect->setDevice(device);
 }
 
@@ -99,7 +101,7 @@
     return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> EqualizerEffect::setInputDevice(AudioDevice device) {
+Return<Result> EqualizerEffect::setInputDevice(AudioDeviceBitfield device) {
     return mEffect->setInputDevice(device);
 }
 
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
index e4f1bd5..b59b077 100644
--- 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
@@ -20,6 +20,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -56,7 +58,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -64,7 +66,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
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
index 3f4f379..88210e9 100644
--- 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
@@ -21,6 +21,8 @@
 #include <android/log.h>
 #include <system/audio_effects/effect_aec.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -56,7 +58,7 @@
     return mEffect->disable();
 }
 
-Return<Result> LoudnessEnhancerEffect::setDevice(AudioDevice device) {
+Return<Result> LoudnessEnhancerEffect::setDevice(AudioDeviceBitfield device) {
     return mEffect->setDevice(device);
 }
 
@@ -79,7 +81,7 @@
     return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> LoudnessEnhancerEffect::setInputDevice(AudioDevice device) {
+Return<Result> LoudnessEnhancerEffect::setInputDevice(AudioDeviceBitfield device) {
     return mEffect->setInputDevice(device);
 }
 
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
index 7b64ba0..af1635b 100644
--- 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
@@ -22,6 +22,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -58,7 +60,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -66,7 +68,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
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
index e5fc454..f32399c 100644
--- 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
@@ -18,6 +18,8 @@
 
 #include <android/log.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -65,7 +67,7 @@
     return mEffect->disable();
 }
 
-Return<Result> NoiseSuppressionEffect::setDevice(AudioDevice device) {
+Return<Result> NoiseSuppressionEffect::setDevice(AudioDeviceBitfield device) {
     return mEffect->setDevice(device);
 }
 
@@ -88,7 +90,7 @@
     return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> NoiseSuppressionEffect::setInputDevice(AudioDevice device) {
+Return<Result> NoiseSuppressionEffect::setInputDevice(AudioDeviceBitfield device) {
     return mEffect->setInputDevice(device);
 }
 
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
index 3114acd..1a91ab4 100644
--- 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
@@ -20,6 +20,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -56,7 +58,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -64,7 +66,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
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
index 32198d5..eab68fb 100644
--- 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
@@ -19,6 +19,8 @@
 #include <android/log.h>
 #include <system/audio_effects/effect_presetreverb.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -53,7 +55,7 @@
     return mEffect->disable();
 }
 
-Return<Result> PresetReverbEffect::setDevice(AudioDevice device) {
+Return<Result> PresetReverbEffect::setDevice(AudioDeviceBitfield device) {
     return mEffect->setDevice(device);
 }
 
@@ -76,7 +78,7 @@
     return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> PresetReverbEffect::setInputDevice(AudioDevice device) {
+Return<Result> PresetReverbEffect::setInputDevice(AudioDeviceBitfield device) {
     return mEffect->setInputDevice(device);
 }
 
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
index 3715894..c0d5a00 100644
--- 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
@@ -20,6 +20,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -31,6 +33,7 @@
 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::implementation::AudioChannelBitfield;
 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;
@@ -57,7 +60,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -65,7 +68,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
@@ -98,7 +101,7 @@
     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,
+    Return<void> getVirtualSpeakerAngles(AudioChannelBitfield mask, AudioDevice device,
                                          getVirtualSpeakerAngles_cb _hidl_cb) override;
     Return<Result> forceVirtualizationMode(AudioDevice device) override;
     Return<void> getVirtualizationMode(getVirtualizationMode_cb _hidl_cb) override;
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
index 6fb8005..23b09a89 100644
--- 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
@@ -21,6 +21,8 @@
 #include <android/log.h>
 #include <system/audio_effects/effect_virtualizer.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -36,7 +38,7 @@
                                              hidl_vec<SpeakerAngle>& speakerAngles) {
     speakerAngles.resize(channelCount);
     for (uint32_t i = 0; i < channelCount; ++i) {
-        speakerAngles[i].mask = AudioChannelMask(*halAngles++);
+        speakerAngles[i].mask = AudioChannelBitfield(*halAngles++);
         speakerAngles[i].azimuth = *halAngles++;
         speakerAngles[i].elevation = *halAngles++;
     }
@@ -65,7 +67,7 @@
     return mEffect->disable();
 }
 
-Return<Result> VirtualizerEffect::setDevice(AudioDevice device) {
+Return<Result> VirtualizerEffect::setDevice(AudioDeviceBitfield device) {
     return mEffect->setDevice(device);
 }
 
@@ -88,7 +90,7 @@
     return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> VirtualizerEffect::setInputDevice(AudioDevice device) {
+Return<Result> VirtualizerEffect::setInputDevice(AudioDeviceBitfield device) {
     return mEffect->setInputDevice(device);
 }
 
@@ -184,7 +186,8 @@
     return mEffect->getIntegerParam(VIRTUALIZER_PARAM_STRENGTH, _hidl_cb);
 }
 
-Return<void> VirtualizerEffect::getVirtualSpeakerAngles(AudioChannelMask mask, AudioDevice device,
+Return<void> VirtualizerEffect::getVirtualSpeakerAngles(AudioChannelBitfield mask,
+                                                        AudioDevice device,
                                                         getVirtualSpeakerAngles_cb _hidl_cb) {
     uint32_t channelCount =
         audio_channel_count_from_out_mask(static_cast<audio_channel_mask_t>(mask));
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
index 8050221..114d3b7 100644
--- 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
@@ -20,6 +20,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -56,7 +58,7 @@
     Return<Result> reset() override;
     Return<Result> enable() override;
     Return<Result> disable() override;
-    Return<Result> setDevice(AudioDevice device) override;
+    Return<Result> setDevice(AudioDeviceBitfield 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;
@@ -64,7 +66,7 @@
     Return<Result> setConfigReverse(
         const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
         const sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
-    Return<Result> setInputDevice(AudioDevice device) override;
+    Return<Result> setInputDevice(AudioDeviceBitfield device) override;
     Return<void> getConfig(getConfig_cb _hidl_cb) override;
     Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
     Return<void> getSupportedAuxChannelsConfigs(
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
index 0351453..9f2195b 100644
--- 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
@@ -19,6 +19,8 @@
 #include <android/log.h>
 #include <system/audio_effects/effect_visualizer.h>
 
+#include "VersionUtils.h"
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -54,7 +56,7 @@
     return mEffect->disable();
 }
 
-Return<Result> VisualizerEffect::setDevice(AudioDevice device) {
+Return<Result> VisualizerEffect::setDevice(AudioDeviceBitfield device) {
     return mEffect->setDevice(device);
 }
 
@@ -77,7 +79,7 @@
     return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
 }
 
-Return<Result> VisualizerEffect::setInputDevice(AudioDevice device) {
+Return<Result> VisualizerEffect::setInputDevice(AudioDeviceBitfield device) {
     return mEffect->setInputDevice(device);
 }
 
diff --git a/automotive/audiocontrol/1.0/IAudioControl.hal b/automotive/audiocontrol/1.0/IAudioControl.hal
index c029499..3c8b086 100644
--- a/automotive/audiocontrol/1.0/IAudioControl.hal
+++ b/automotive/audiocontrol/1.0/IAudioControl.hal
@@ -29,10 +29,8 @@
      *
      * 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)
+    getBusForContext(ContextNumber contextNumber)
         generates (int32_t busNumber);
 
 
diff --git a/automotive/audiocontrol/1.0/default/AudioControl.cpp b/automotive/audiocontrol/1.0/default/AudioControl.cpp
index b40f2ae..c96580e 100644
--- a/automotive/audiocontrol/1.0/default/AudioControl.cpp
+++ b/automotive/audiocontrol/1.0/default/AudioControl.cpp
@@ -36,7 +36,8 @@
 };
 
 
-Return<int32_t> AudioControl::getBusForContext(uint32_t contextNumber) {
+Return<int32_t> AudioControl::getBusForContext(ContextNumber ctxt) {
+    unsigned contextNumber = static_cast<unsigned>(ctxt);
     if (contextNumber > sContextNumberMax) {
         ALOGE("Unexpected context number %d (max expected is %d)", contextNumber, sContextCount);
         return -1;
diff --git a/automotive/audiocontrol/1.0/default/AudioControl.h b/automotive/audiocontrol/1.0/default/AudioControl.h
index 89e41f9..37f43c6 100644
--- a/automotive/audiocontrol/1.0/default/AudioControl.h
+++ b/automotive/audiocontrol/1.0/default/AudioControl.h
@@ -23,7 +23,7 @@
 struct AudioControl : public IAudioControl {
 public:
     // Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControl follow.
-    Return<int32_t> getBusForContext(uint32_t contextNumber) override;
+    Return<int32_t> getBusForContext(ContextNumber contextNumber) override;
     Return<void> setBalanceTowardRight(float value) override;
     Return<void> setFadeTowardFront(float value) override;
 
diff --git a/automotive/audiocontrol/1.0/vts/functional/Android.bp b/automotive/audiocontrol/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..c6e0d8e
--- /dev/null
+++ b/automotive/audiocontrol/1.0/vts/functional/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalAudioControlV1_0TargetTest",
+
+    srcs: [
+        "VtsHalAudioControlV1_0TargetTest.cpp",
+    ],
+
+    defaults: [
+        "VtsHalTargetTestDefaults",
+    ],
+
+    static_libs: [
+        "android.hardware.automotive.audiocontrol@1.0",
+    ],
+}
diff --git a/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp b/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp
new file mode 100644
index 0000000..68ed778
--- /dev/null
+++ b/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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 "VtsHalAudioControlTest"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <hwbinder/ProcessState.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+#include <android/hardware/automotive/audiocontrol/1.0/types.h>
+#include <android/hardware/automotive/audiocontrol/1.0/IAudioControl.h>
+#include <android/log.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+using namespace ::android::hardware::automotive::audiocontrol::V1_0;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_enum_iterator;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::sp;
+
+
+// Boiler plate for test harness
+class CarAudioControlHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static CarAudioControlHidlEnvironment* Instance() {
+        static CarAudioControlHidlEnvironment* instance = new CarAudioControlHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IAudioControl>(); }
+   private:
+    CarAudioControlHidlEnvironment() {}
+};
+
+
+// The main test class for the automotive AudioControl HAL
+class CarAudioControlHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+public:
+    virtual void SetUp() override {
+        // Make sure we can connect to the driver
+        pAudioControl = ::testing::VtsHalHidlTargetTestBase::getService<IAudioControl>(
+                                    CarAudioControlHidlEnvironment::Instance()->
+                                    getServiceName<IAudioControl>());
+        ASSERT_NE(pAudioControl.get(), nullptr);
+    }
+
+    virtual void TearDown() override {}
+
+   protected:
+    sp<IAudioControl> pAudioControl;  // Every test needs access to the service
+};
+
+//
+// Tests start here...
+//
+
+/*
+ * Fader exercise test.  Note that only a subjective observer could determine if the
+ * fader actually works.  The only thing we can do is exercise the HAL and if the HAL crashes,
+ * we _might_ get a test failure if that breaks the connection to the driver.
+ */
+TEST_F(CarAudioControlHidlTest, FaderExercise) {
+    ALOGI("Fader exercise test (silent)");
+
+    // Set the fader all the way to the back
+    pAudioControl->setFadeTowardFront(-1.0f);
+
+    // Set the fader all the way to the front
+    pAudioControl->setFadeTowardFront(1.0f);
+
+    // Set the fader part way toward the back
+    pAudioControl->setFadeTowardFront(-0.333f);
+
+    // Set the fader to a out of bounds value (driver should clamp)
+    pAudioControl->setFadeTowardFront(99999.9f);
+
+    // Set the fader back to the middle
+    pAudioControl->setFadeTowardFront(0.0f);
+}
+
+/*
+ * Balance exercise test.
+ */
+TEST_F(CarAudioControlHidlTest, BalanceExercise) {
+    ALOGI("Balance exercise test (silent)");
+
+    // Set the balance all the way to the left
+    pAudioControl->setBalanceTowardRight(-1.0f);
+
+    // Set the balance all the way to the right
+    pAudioControl->setBalanceTowardRight(1.0f);
+
+    // Set the balance part way toward the left
+    pAudioControl->setBalanceTowardRight(-0.333f);
+
+    // Set the balance to a out of bounds value (driver should clamp)
+    pAudioControl->setBalanceTowardRight(99999.9f);
+
+    // Set the balance back to the middle
+    pAudioControl->setBalanceTowardRight(0.0f);
+}
+
+/*
+ * Context mapping test.
+ */
+TEST_F(CarAudioControlHidlTest, ContextMapping) {
+    ALOGI("Context mapping test");
+
+    int bus = -1;
+
+    // For each defined context, query the driver for the BUS on which it should be delivered
+    for (const auto& ctxt : hidl_enum_iterator<ContextNumber>()) {
+         bus = pAudioControl->getBusForContext(ctxt);
+
+         if (ctxt == ContextNumber::INVALID) {
+             // Invalid context should never be mapped to a bus
+             EXPECT_EQ(bus, -1);
+         } else {
+             EXPECT_GE(bus, 0);
+             // TODO:  Consider enumerating the devices on the actual audio hal to validate the
+             // bus IDs.  This would introduce an dependency on the audio HAL, however.  Would that
+             // even work while Android is up and running?
+         }
+    }
+
+    // Try asking about an invalid context one beyond the last defined to see that it gets back a -1
+    int contextRange = std::distance(hidl_enum_iterator<ContextNumber>().begin(),
+                                     hidl_enum_iterator<ContextNumber>().end());
+    bus = pAudioControl->getBusForContext((ContextNumber)contextRange);
+    EXPECT_EQ(bus, -1);
+
+    // Try asking about an invalid context WAY out of range to see that it gets back a -1
+    bus = pAudioControl->getBusForContext((ContextNumber)~0);
+    EXPECT_EQ(bus, -1);
+}
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index bdc44ef..4b93008 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -26,14 +26,15 @@
         "Obd2IgnitionMonitorKind",
         "Obd2SecondaryAirStatus",
         "Obd2SparkIgnitionMonitors",
+        "PortLocationType",
         "StatusCode",
         "SubscribeFlags",
         "SubscribeOptions",
         "VehicleApPowerBootupReason",
-        "VehicleApPowerSetState",
-        "VehicleApPowerState",
         "VehicleApPowerStateConfigFlag",
-        "VehicleApPowerStateIndex",
+        "VehicleApPowerStateReq",
+        "VehicleApPowerStateReqIndex",
+        "VehicleApPowerStateReport",
         "VehicleApPowerStateShutdownParam",
         "VehicleArea",
         "VehicleAreaConfig",
@@ -41,23 +42,22 @@
         "VehicleAreaMirror",
         "VehicleAreaSeat",
         "VehicleAreaWindow",
-        "VehicleAreaZone",
         "VehicleDisplay",
-        "VehicleDrivingStatus",
         "VehicleGear",
         "VehicleHvacFanDirection",
         "VehicleHwKeyInputAction",
         "VehicleIgnitionState",
+        "VehicleLightState",
+        "VehicleLightSwitch",
+        "VehicleOilLevel",
         "VehiclePropConfig",
         "VehiclePropValue",
         "VehicleProperty",
         "VehiclePropertyAccess",
         "VehiclePropertyChangeMode",
         "VehiclePropertyGroup",
-        "VehiclePropertyOperation",
         "VehiclePropertyStatus",
         "VehiclePropertyType",
-        "VehicleRadioConstants",
         "VehicleTurnSignal",
         "VehicleUnit",
         "VmsAvailabilityStateIntegerValuesIndex",
diff --git a/automotive/vehicle/2.0/IVehicleCallback.hal b/automotive/vehicle/2.0/IVehicleCallback.hal
index 7060418..c4a756a 100644
--- a/automotive/vehicle/2.0/IVehicleCallback.hal
+++ b/automotive/vehicle/2.0/IVehicleCallback.hal
@@ -33,7 +33,7 @@
 
     /**
      * This method gets called if the client was subscribed to a property using
-     * SubscribeFlags::SET_CALL flag and IVehicle#set(...) method was called.
+     * SubscribeFlags::EVENTS_FROM_ANDROID flag and IVehicle#set(...) method was called.
      *
      * These events must be delivered to subscriber immediately without any
      * batching.
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
index 359bb6d..946e74d 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
@@ -152,7 +152,7 @@
  *   VehiclePropValuePool pool;
  *   auto v = pool.obtain(VehiclePropertyType::INT32);
  *   v->propId = VehicleProperty::HVAC_FAN_SPEED;
- *   v->areaId = VehicleAreaZone::ROW_1_LEFT;
+ *   v->areaId = VehicleAreaSeat::ROW_1_LEFT;
  *   v->timestamp = elapsedRealtimeNano();
  *   v->value->int32Values[0] = 42;
  *
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
index eda94b7..0a243fe 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
@@ -67,7 +67,7 @@
 
     /* Stores provided value. Returns true if value was written returns false if config for
      * example wasn't registered. */
-    bool writeValue(const VehiclePropValue& propValue);
+    bool writeValue(const VehiclePropValue& propValue, bool updateStatus);
 
     void removeValue(const VehiclePropValue& propValue);
     void removeValuesForProperty(int32_t propId);
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
index ce0b163..f97dfa1 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
@@ -33,10 +33,9 @@
 constexpr int32_t kAllSupportedAreas = 0;
 
 /** Returns underlying (integer) value for given enum. */
-template<typename ENUM>
-inline constexpr typename std::underlying_type<ENUM>::type toInt(
-        ENUM const value) {
-    return static_cast<typename std::underlying_type<ENUM>::type>(value);
+template<typename ENUM, typename U = typename std::underlying_type<ENUM>::type>
+inline constexpr U toInt(ENUM const value) {
+    return static_cast<U>(value);
 }
 
 inline constexpr VehiclePropertyType getPropType(int32_t prop) {
diff --git a/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp b/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp
index a7d5f50..97aeca6 100644
--- a/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp
@@ -106,7 +106,7 @@
 
         addClientToPropMapLocked(opts.propId, client);
 
-        if (SubscribeFlags::HAL_EVENT & opts.flags) {
+        if (SubscribeFlags::EVENTS_FROM_CAR & opts.flags) {
             SubscribeOptions updated;
             if (updateHalEventSubscriptionLocked(opts, &updated)) {
                 outUpdatedSubscriptions->push_back(updated);
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index 1918421..b5de262 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -216,7 +216,7 @@
                                               int32_t property,
                                               int32_t areaId) {
     const auto& clients =
-        mSubscriptionManager.getSubscribedClients(property, SubscribeFlags::HAL_EVENT);
+        mSubscriptionManager.getSubscribedClients(property, SubscribeFlags::EVENTS_FROM_CAR);
 
     for (auto client : clients) {
         client->getCallback()->onPropertySetError(errorCode, property, areaId);
@@ -224,8 +224,8 @@
 }
 
 void VehicleHalManager::onBatchHalEvent(const std::vector<VehiclePropValuePtr>& values) {
-    const auto& clientValues = mSubscriptionManager.distributeValuesToClients(
-            values, SubscribeFlags::HAL_EVENT);
+    const auto& clientValues =
+        mSubscriptionManager.distributeValuesToClients(values, SubscribeFlags::EVENTS_FROM_CAR);
 
     for (const HalClientValues& cv : clientValues) {
         auto vecSize = cv.values.size();
@@ -250,8 +250,7 @@
 }
 
 bool VehicleHalManager::isSampleRateFixed(VehiclePropertyChangeMode mode) {
-    return (mode & VehiclePropertyChangeMode::ON_SET)
-           || (mode & VehiclePropertyChangeMode::ON_CHANGE);
+    return (mode & VehiclePropertyChangeMode::ON_CHANGE);
 }
 
 float VehicleHalManager::checkSampleRate(const VehiclePropConfig &config,
@@ -281,7 +280,7 @@
                                        SubscribeFlags flags) {
     bool isReadable = config.access & VehiclePropertyAccess::READ;
 
-    if (!isReadable && (SubscribeFlags::HAL_EVENT & flags)) {
+    if (!isReadable && (SubscribeFlags::EVENTS_FROM_CAR & flags)) {
         ALOGW("Cannot subscribe, property 0x%x is not readable", config.prop);
         return false;
     }
@@ -289,12 +288,6 @@
         ALOGW("Cannot subscribe, property 0x%x is static", config.prop);
         return false;
     }
-
-    //TODO: extend to support event notification for set from android
-    if (config.changeMode == VehiclePropertyChangeMode::POLL) {
-        ALOGW("Cannot subscribe, property 0x%x is poll only", config.prop);
-        return false;
-    }
     return true;
 }
 
@@ -317,7 +310,8 @@
 }
 
 void VehicleHalManager::handlePropertySetEvent(const VehiclePropValue& value) {
-    auto clients = mSubscriptionManager.getSubscribedClients(value.prop, SubscribeFlags::SET_CALL);
+    auto clients =
+        mSubscriptionManager.getSubscribedClients(value.prop, SubscribeFlags::EVENTS_FROM_ANDROID);
     for (auto client : clients) {
         client->getCallback()->onPropertySet(value);
     }
diff --git a/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
index 2c3ebfc..94ace45 100644
--- a/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
@@ -41,7 +41,8 @@
     mConfigs.insert({ config.prop, RecordConfig { config, tokenFunc } });
 }
 
-bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue) {
+bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue,
+                                        bool updateStatus) {
     MuxGuard g(mLock);
     if (!mConfigs.count(propValue.prop)) return false;
 
@@ -52,6 +53,9 @@
     } else {
         valueToUpdate->timestamp = propValue.timestamp;
         valueToUpdate->value = propValue.value;
+        if (updateStatus) {
+            valueToUpdate->status = propValue.status;
+        }
     }
     return true;
 }
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index c1c511f..56813ce 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -30,7 +30,8 @@
 //
 // Some handy constants to avoid conversions from enum to int.
 constexpr int ABS_ACTIVE = (int)VehicleProperty::ABS_ACTIVE;
-constexpr int AP_POWER_STATE = (int)VehicleProperty::AP_POWER_STATE;
+constexpr int AP_POWER_STATE_REQ = (int)VehicleProperty::AP_POWER_STATE_REQ;
+constexpr int AP_POWER_STATE_REPORT = (int)VehicleProperty::AP_POWER_STATE_REPORT;
 constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME;
 constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME;
 constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO;
@@ -46,18 +47,35 @@
  *
  * It has the following format:
  *
- * int32Values[0] - command (1 - start fake data generation, 0 - stop)
+ * int32Values[0] - command (see FakeDataCommand below for possible values)
  * int32Values[1] - VehicleProperty to which command applies
- *
- * For start command, additional data should be provided:
- *   int64Values[0] - periodic interval in nanoseconds
- *   floatValues[0] - initial value
- *   floatValues[1] - dispersion defines min and max range relative to initial value
- *   floatValues[2] - increment, with every timer tick the value will be incremented by this amount
  */
 const int32_t kGenerateFakeDataControllingProperty =
     0x0666 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
 
+enum class FakeDataCommand : int32_t {
+    /** Stops generating of fake data that was triggered by Start command */
+    Stop = 0,
+
+    /**
+     * Starts fake data generation.  Caller must provide additional data:
+     *     int64Values[0] - periodic interval in nanoseconds
+     *     floatValues[0] - initial value
+     *     floatValues[1] - dispersion defines min and max range relative to initial value
+     *     floatValues[2] - increment, with every timer tick the value will be incremented by this
+     * amount
+     */
+    Start = 1,
+
+    /**
+     * Injects key press event (HAL incorporates UP/DOWN acction and triggers 2 HAL events for every
+     * key-press). Caller must provide the following data: int32Values[2] - Android key code
+     *     int32Values[3] - target display (0 - for main display, 1 - for instrument cluster, see
+     * VehicleDisplay)
+     */
+    KeyPress = 2,
+};
+
 const int32_t kHvacPowerProperties[] = {
     toInt(VehicleProperty::HVAC_FAN_SPEED),
     toInt(VehicleProperty::HVAC_FAN_DIRECTION),
@@ -132,14 +150,6 @@
          },
      .initialValue = {.floatValues = {0.0f}}},
 
-    {.config =
-         {
-             .prop = toInt(VehicleProperty::ENGINE_ON),
-             .access = VehiclePropertyAccess::READ,
-             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-         },
-     .initialValue = {.int32Values = {0}}},
-
     {
         .config =
             {
@@ -238,7 +248,7 @@
              .access = VehiclePropertyAccess::READ_WRITE,
              .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
              .areaConfigs = {VehicleAreaConfig{
-                 .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}},
+                 .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}},
              // TODO(bryaneyler): Ideally, this is generated dynamically from
              // kHvacPowerProperties.
              .configString = "0x12400500,0x12400501"  // HVAC_FAN_SPEED,HVAC_FAN_DIRECTION
@@ -259,28 +269,28 @@
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
+                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
      .initialValue = {.int32Values = {1}}},
 
     {.config = {.prop = toInt(VehicleProperty::HVAC_AC_ON),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
+                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
      .initialValue = {.int32Values = {1}}},
 
     {.config = {.prop = toInt(VehicleProperty::HVAC_AUTO_ON),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
+                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
      .initialValue = {.int32Values = {1}}},
 
     {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT),
+                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT),
                     .minInt32Value = 1,
                     .maxInt32Value = 7}}},
      .initialValue = {.int32Values = {3}}},
@@ -289,24 +299,24 @@
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
+                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
      .initialValue = {.int32Values = {toInt(VehicleHvacFanDirection::FACE)}}},
 
     {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                                    .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
+                                    .areaId = toInt(VehicleAreaSeat::ROW_1_LEFT),
                                     .minFloatValue = 16,
                                     .maxFloatValue = 32,
                                 },
                                 VehicleAreaConfig{
-                                    .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
+                                    .areaId = toInt(VehicleAreaSeat::ROW_1_RIGHT),
                                     .minFloatValue = 16,
                                     .maxFloatValue = 32,
                                 }}},
-     .initialAreaValues = {{toInt(VehicleAreaZone::ROW_1_LEFT), {.floatValues = {16}}},
-                           {toInt(VehicleAreaZone::ROW_1_RIGHT), {.floatValues = {20}}}}},
+     .initialAreaValues = {{toInt(VehicleAreaSeat::ROW_1_LEFT), {.floatValues = {16}}},
+                           {toInt(VehicleAreaSeat::ROW_1_RIGHT), {.floatValues = {20}}}}},
 
     {.config =
          {
@@ -329,14 +339,6 @@
 
     {.config =
          {
-             .prop = toInt(VehicleProperty::DRIVING_STATUS),
-             .access = VehiclePropertyAccess::READ,
-             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-         },
-     .initialValue = {.int32Values = {toInt(VehicleDrivingStatus::UNRESTRICTED)}}},
-
-    {.config =
-         {
              .prop = toInt(VehicleProperty::GEAR_SELECTION),
              .access = VehiclePropertyAccess::READ,
              .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -415,11 +417,17 @@
             },
     },
 
-    {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE),
-                .access = VehiclePropertyAccess::READ_WRITE,
+    {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+                .access = VehiclePropertyAccess::READ,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .configArray = {3}},
-     .initialValue = {.int32Values = {toInt(VehicleApPowerState::ON_FULL), 0}}},
+     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReq::ON_FULL), 0}}},
+
+    {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                .access = VehiclePropertyAccess::WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .configArray = {3}},
+     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::BOOT_COMPLETE), 0}}},
 
     {.config = {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
                 .access = VehiclePropertyAccess::READ_WRITE,
@@ -429,7 +437,7 @@
 
     {.config = {.prop = toInt(VehicleProperty::AP_POWER_BOOTUP_REASON),
                 .access = VehiclePropertyAccess::READ,
-                .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+                .changeMode = VehiclePropertyChangeMode::STATIC},
      .initialValue = {.int32Values = {toInt(VehicleApPowerBootupReason::USER_POWER_ON)}}},
 
     {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 764bebd..2eb905d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -85,11 +85,6 @@
     return sensorStore;
 }
 
-enum class FakeDataCommand : int32_t {
-    Stop = 0,
-    Start = 1,
-};
-
 EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
     : mPropStore(propStore),
       mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
@@ -132,15 +127,18 @@
 }
 
 StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
+    static constexpr bool shouldUpdateStatus = false;
+
     if (propValue.prop == kGenerateFakeDataControllingProperty) {
         StatusCode status = handleGenerateFakeDataRequest(propValue);
         if (status != StatusCode::OK) {
             return status;
         }
     } else if (mHvacPowerProps.count(propValue.prop)) {
+        // TODO(75328113): this should be handled by property status
         auto hvacPowerOn = mPropStore->readValueOrNull(
             toInt(VehicleProperty::HVAC_POWER_ON),
-            (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT));
+            (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT));
 
         if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
                 && hvacPowerOn->value.int32Values[0] == 0) {
@@ -155,7 +153,7 @@
                 // Placeholder for future implementation of VMS property in the default hal. For
                 // now, just returns OK; otherwise, hal clients crash with property not supported.
                 return StatusCode::OK;
-            case AP_POWER_STATE:
+            case AP_POWER_STATE_REPORT:
                 // This property has different behavior between get/set.  When it is set, the value
                 //  goes to the vehicle but is NOT updated in the property store back to Android.
                 // Commented out for now, because it may mess up automated testing that use the
@@ -165,7 +163,23 @@
         }
     }
 
-    if (!mPropStore->writeValue(propValue)) {
+    if (propValue.status != VehiclePropertyStatus::AVAILABLE) {
+        // Android side cannot set property status - this value is the
+        // purview of the HAL implementation to reflect the state of
+        // its underlying hardware
+        return StatusCode::INVALID_ARG;
+    }
+    auto currentPropValue = mPropStore->readValueOrNull(propValue);
+
+    if (currentPropValue == nullptr) {
+        return StatusCode::INVALID_ARG;
+    }
+    if (currentPropValue->status != VehiclePropertyStatus::AVAILABLE) {
+        // do not allow Android side to set() a disabled/error property
+        return StatusCode::NOT_AVAILABLE;
+    }
+
+    if (!mPropStore->writeValue(propValue, shouldUpdateStatus)) {
         return StatusCode::INVALID_ARG;
     }
 
@@ -187,6 +201,8 @@
 
 // Parse supported properties list and generate vector of property values to hold current values.
 void EmulatedVehicleHal::onCreate() {
+    static constexpr bool shouldUpdateStatus = true;
+
     for (auto& it : kVehicleProperties) {
         VehiclePropConfig cfg = it.config;
         int32_t numAreas = cfg.areaConfigs.size();
@@ -228,7 +244,7 @@
             } else {
                 prop.value = it.initialValue;
             }
-            mPropStore->writeValue(prop);
+            mPropStore->writeValue(prop, shouldUpdateStatus);
         }
     }
     initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
@@ -288,6 +304,8 @@
 }
 
 bool EmulatedVehicleHal::setPropertyFromVehicle(const VehiclePropValue& propValue) {
+    static constexpr bool shouldUpdateStatus = true;
+
     if (propValue.prop == kGenerateFakeDataControllingProperty) {
         StatusCode status = handleGenerateFakeDataRequest(propValue);
         if (status != StatusCode::OK) {
@@ -295,7 +313,7 @@
         }
     }
 
-    if (mPropStore->writeValue(propValue)) {
+    if (mPropStore->writeValue(propValue, shouldUpdateStatus)) {
         doHalEvent(getValuePool()->obtain(propValue));
         return true;
     } else {
@@ -343,10 +361,20 @@
             break;
         }
         case FakeDataCommand::Stop: {
-            ALOGI("%s, FakeDataCommandStop", __func__);
+            ALOGI("%s, FakeDataCommand::Stop", __func__);
             mFakeValueGenerator.stopGeneratingHalEvents(propId);
             break;
         }
+        case FakeDataCommand::KeyPress: {
+            ALOGI("%s, FakeDataCommand::KeyPress", __func__);
+            int32_t keyCode = request.value.int32Values[2];
+            int32_t display = request.value.int32Values[3];
+            doHalEvent(
+                createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display));
+            doHalEvent(createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display));
+            break;
+        }
+
         default: {
             ALOGE("%s: unexpected command: %d", __func__, command);
             return StatusCode::INVALID_ARG;
@@ -355,7 +383,22 @@
     return StatusCode::OK;
 }
 
+VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::createHwInputKeyProp(
+    VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
+    auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
+    keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
+    keyEvent->areaId = 0;
+    keyEvent->timestamp = elapsedRealtimeNano();
+    keyEvent->status = VehiclePropertyStatus::AVAILABLE;
+    keyEvent->value.int32Values[0] = toInt(action);
+    keyEvent->value.int32Values[1] = keyCode;
+    keyEvent->value.int32Values[2] = targetDisplay;
+    return keyEvent;
+}
+
 void EmulatedVehicleHal::onFakeValueGenerated(int32_t propId, float value) {
+    static constexpr bool shouldUpdateStatus = false;
+
     VehiclePropValuePtr updatedPropValue {};
     switch (getPropType(propId)) {
         case VehiclePropertyType::FLOAT:
@@ -375,7 +418,7 @@
         updatedPropValue->areaId = 0;  // Add area support if necessary.
         updatedPropValue->timestamp = elapsedRealtimeNano();
         updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
-        mPropStore->writeValue(*updatedPropValue);
+        mPropStore->writeValue(*updatedPropValue, shouldUpdateStatus);
         auto changeMode = mPropStore->getConfigOrDie(propId)->changeMode;
         if (VehiclePropertyChangeMode::ON_CHANGE == changeMode) {
             doHalEvent(move(updatedPropValue));
@@ -404,16 +447,20 @@
 }
 
 void EmulatedVehicleHal::initObd2LiveFrame(const VehiclePropConfig& propConfig) {
+    static constexpr bool shouldUpdateStatus = true;
+
     auto liveObd2Frame = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
     auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
                                             static_cast<size_t>(propConfig.configArray[1]));
     sensorStore->fillPropValue("", liveObd2Frame.get());
     liveObd2Frame->prop = OBD2_LIVE_FRAME;
 
-    mPropStore->writeValue(*liveObd2Frame);
+    mPropStore->writeValue(*liveObd2Frame, shouldUpdateStatus);
 }
 
 void EmulatedVehicleHal::initObd2FreezeFrame(const VehiclePropConfig& propConfig) {
+    static constexpr bool shouldUpdateStatus = true;
+
     auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
                                             static_cast<size_t>(propConfig.configArray[1]));
 
@@ -425,7 +472,7 @@
         sensorStore->fillPropValue(dtc, freezeFrame.get());
         freezeFrame->prop = OBD2_FREEZE_FRAME;
 
-        mPropStore->writeValue(*freezeFrame);
+        mPropStore->writeValue(*freezeFrame, shouldUpdateStatus);
     }
 }
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index 62fc126..d291dba 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -67,6 +67,8 @@
 
     StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
     void onFakeValueGenerated(int32_t propId, float value);
+    VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
+                                             int32_t targetDisplay);
 
     void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
     bool isContinuousProperty(int32_t propId) const;
diff --git a/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp b/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
index 4865e9e..ab2013d 100644
--- a/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
@@ -51,19 +51,16 @@
     }
 
     hidl_vec<SubscribeOptions> subscrToProp1 = {
-        SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::HAL_EVENT},
+        SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::EVENTS_FROM_CAR},
     };
 
     hidl_vec<SubscribeOptions> subscrToProp2 = {
-        SubscribeOptions {
-            .propId = PROP2,
-            .flags = SubscribeFlags::HAL_EVENT
-        },
+        SubscribeOptions{.propId = PROP2, .flags = SubscribeFlags::EVENTS_FROM_CAR},
     };
 
     hidl_vec<SubscribeOptions> subscrToProp1and2 = {
-        SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::HAL_EVENT},
-        SubscribeOptions{.propId = PROP2, .flags = SubscribeFlags::HAL_EVENT},
+        SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::EVENTS_FROM_CAR},
+        SubscribeOptions{.propId = PROP2, .flags = SubscribeFlags::EVENTS_FROM_CAR},
     };
 
     static std::list<sp<IVehicleCallback>> extractCallbacks(
@@ -76,11 +73,11 @@
     }
 
     std::list<sp<HalClient>> clientsToProp1() {
-        return manager.getSubscribedClients(PROP1, SubscribeFlags::DEFAULT);
+        return manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
     }
 
     std::list<sp<HalClient>> clientsToProp2() {
-        return manager.getSubscribedClients(PROP2, SubscribeFlags::DEFAULT);
+        return manager.getSubscribedClients(PROP2, SubscribeFlags::EVENTS_FROM_CAR);
     }
 
     void onPropertyUnsubscribed(int propertyId) {
@@ -110,9 +107,7 @@
     ASSERT_EQ(StatusCode::OK,
               manager.addOrUpdateSubscription(2, cb2, subscrToProp1, &updatedOptions));
 
-    auto clients = manager.getSubscribedClients(
-            PROP1,
-            SubscribeFlags::HAL_EVENT);
+    auto clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
 
     ASSERT_ALL_EXISTS({cb1, cb2}, extractCallbacks(clients));
 }
@@ -124,13 +119,11 @@
 
     // Wrong prop
     auto clients = manager.getSubscribedClients(toInt(VehicleProperty::AP_POWER_BOOTUP_REASON),
-                                                SubscribeFlags::HAL_EVENT);
+                                                SubscribeFlags::EVENTS_FROM_CAR);
     ASSERT_TRUE(clients.empty());
 
     // Wrong flag
-    clients = manager.getSubscribedClients(
-            PROP1,
-            SubscribeFlags::SET_CALL);
+    clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_ANDROID);
     ASSERT_TRUE(clients.empty());
 }
 
@@ -139,27 +132,22 @@
     ASSERT_EQ(StatusCode::OK, manager.addOrUpdateSubscription(1, cb1, subscrToProp1,
                                                               &updatedOptions));
 
-    auto clients = manager.getSubscribedClients(
-            PROP1,
-            SubscribeFlags::DEFAULT);
+    auto clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
     ASSERT_EQ((size_t) 1, clients.size());
     ASSERT_EQ(cb1, clients.front()->getCallback());
 
     // Same property, but different zone, to make sure we didn't unsubscribe
     // from previous zone.
-    ASSERT_EQ(StatusCode::OK, manager.addOrUpdateSubscription(1, cb1, {
-        SubscribeOptions {
-                .propId = PROP1,
-                .flags = SubscribeFlags::DEFAULT
-            }
-        }, &updatedOptions));
+    ASSERT_EQ(
+        StatusCode::OK,
+        manager.addOrUpdateSubscription(
+            1, cb1, {SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::EVENTS_FROM_CAR}},
+            &updatedOptions));
 
-    clients = manager.getSubscribedClients(PROP1,
-                                           SubscribeFlags::DEFAULT);
+    clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
     ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
 
-    clients = manager.getSubscribedClients(PROP1,
-                                           SubscribeFlags::DEFAULT);
+    clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
     ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
 }
 
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index 5b195db..f64eab5 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -241,10 +241,7 @@
     sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
 
     hidl_vec<SubscribeOptions> options = {
-        SubscribeOptions {
-            .propId = PROP,
-            .flags = SubscribeFlags::DEFAULT
-        },
+        SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR},
     };
 
     StatusCode res = manager->subscribe(cb, options);
@@ -259,11 +256,7 @@
     sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
 
     hidl_vec<SubscribeOptions> options = {
-        SubscribeOptions {
-            .propId = PROP,
-            .flags = SubscribeFlags::DEFAULT
-        }
-    };
+        SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
 
     StatusCode res = manager->subscribe(cb, options);
     ASSERT_EQ(StatusCode::OK, res);
@@ -301,18 +294,14 @@
     sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
 
     hidl_vec<SubscribeOptions> options = {
-        SubscribeOptions {
-            .propId = PROP,
-            .flags = SubscribeFlags::HAL_EVENT
-        },
+        SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR},
     };
 
     StatusCode res = manager->subscribe(cb, options);
     // Unable to subscribe on Hal Events for write-only properties.
     ASSERT_EQ(StatusCode::INVALID_ARG, res);
 
-
-    options[0].flags = SubscribeFlags::SET_CALL;
+    options[0].flags = SubscribeFlags::EVENTS_FROM_ANDROID;
 
     res = manager->subscribe(cb, options);
     // OK to subscribe on SET method call for write-only properties.
@@ -396,8 +385,8 @@
     const auto PROP = toInt(VehicleProperty::HVAC_FAN_SPEED);
     const auto VAL1 = 1;
     const auto VAL2 = 2;
-    const auto AREA1 = toInt(VehicleAreaZone::ROW_1_LEFT);
-    const auto AREA2 = toInt(VehicleAreaZone::ROW_1_RIGHT);
+    const auto AREA1 = toInt(VehicleAreaSeat::ROW_1_LEFT);
+    const auto AREA2 = toInt(VehicleAreaSeat::ROW_1_RIGHT);
 
     {
         auto expectedValue1 = hal->getValuePool()->obtainInt32(VAL1);
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h b/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
index 3cabcf2..108e32f 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
@@ -40,64 +40,38 @@
         .configString = "Some=config,options=if,you=have_any",
     },
 
-    {
-        .prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .areaConfigs = {
-            VehicleAreaConfig {
-                .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
-                .minInt32Value = 1,
-                .maxInt32Value = 7},
-            VehicleAreaConfig {
-                .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
-                .minInt32Value = 1,
-                .maxInt32Value = 5,
-            }
-        }
-    },
+    {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+     .access = VehiclePropertyAccess::READ_WRITE,
+     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+     .areaConfigs =
+         {VehicleAreaConfig{
+              .areaId = toInt(VehicleAreaSeat::ROW_1_LEFT), .minInt32Value = 1, .maxInt32Value = 7},
+          VehicleAreaConfig{
+              .areaId = toInt(VehicleAreaSeat::ROW_1_RIGHT), .minInt32Value = 1, .maxInt32Value = 5,
+          }}},
 
     // Write-only property
-    {
-        .prop = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE),
-        .access = VehiclePropertyAccess::WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_SET,
-        .areaConfigs = {
-            VehicleAreaConfig {
-                .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
-                .minInt32Value = 64,
-                .maxInt32Value = 80},
-            VehicleAreaConfig {
-                .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
-                .minInt32Value = 64,
-                .maxInt32Value = 80,
-            }
-        }
-    },
+    {.prop = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE),
+     .access = VehiclePropertyAccess::WRITE,
+     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+     .areaConfigs = {VehicleAreaConfig{.areaId = toInt(VehicleAreaSeat::ROW_1_LEFT),
+                                       .minInt32Value = 64,
+                                       .maxInt32Value = 80},
+                     VehicleAreaConfig{
+                         .areaId = toInt(VehicleAreaSeat::ROW_1_RIGHT),
+                         .minInt32Value = 64,
+                         .maxInt32Value = 80,
+                     }}},
 
-    {
-        .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .areaConfigs = {
-            VehicleAreaConfig {
-                .minFloatValue = 0,
-                .maxFloatValue = 1.0
-            }
-        }
-    },
+    {.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+     .access = VehiclePropertyAccess::READ,
+     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+     .areaConfigs = {VehicleAreaConfig{.minFloatValue = 0, .maxFloatValue = 1.0}}},
 
-    {
-        .prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .areaConfigs = {
-            VehicleAreaConfig {
-                .minInt32Value = 0,
-                .maxInt32Value = 10
-            }
-        }
-    },
+    {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
+     .access = VehiclePropertyAccess::READ_WRITE,
+     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+     .areaConfigs = {VehicleAreaConfig{.minInt32Value = 0, .maxInt32Value = 10}}},
 
     {
         .prop = toInt(VehicleProperty::MIRROR_FOLD),
@@ -107,12 +81,9 @@
     },
 
     // Complex data type.
-    {
-        .prop = kCustomComplexProperty,
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE
-    }
-};
+    {.prop = kCustomComplexProperty,
+     .access = VehiclePropertyAccess::READ_WRITE,
+     .changeMode = VehiclePropertyChangeMode::ON_CHANGE}};
 
 constexpr auto kTimeout = std::chrono::milliseconds(500);
 
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 3001213..15ba494 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -17,28 +17,28 @@
 package android.hardware.automotive.vehicle@2.0;
 
 /**
- * Enumerates supported data types for VehicleProperty.
+ * Enumerates supported data type for VehicleProperty.
  *
- * This is a bitwise flag that supposed to be used in VehicleProperty enum.
+ * Used to create property ID in VehicleProperty enum.
  */
 enum VehiclePropertyType : int32_t {
-    STRING         = 0x00100000,
-    BOOLEAN        = 0x00200000,
-    INT32          = 0x00400000,
-    INT32_VEC      = 0x00410000,
-    INT64          = 0x00500000,
-    INT64_VEC      = 0x00510000,
-    FLOAT          = 0x00600000,
-    FLOAT_VEC      = 0x00610000,
-    BYTES          = 0x00700000,
+    STRING          = 0x00100000,
+    BOOLEAN         = 0x00200000,
+    INT32           = 0x00400000,
+    INT32_VEC       = 0x00410000,
+    INT64           = 0x00500000,
+    INT64_VEC       = 0x00510000,
+    FLOAT           = 0x00600000,
+    FLOAT_VEC       = 0x00610000,
+    BYTES           = 0x00700000,
 
     /**
      * Any combination of scalar or vector types. The exact format must be
      * provided in the description of the property.
      */
-    MIXED          = 0x00e00000,
+    MIXED           = 0x00e00000,
 
-    MASK           = 0x00ff0000
+    MASK            = 0x00ff0000
 };
 
 /**
@@ -50,51 +50,60 @@
  * Other properties may not be associated with particular vehicle area,
  * these kind of properties must have VehicleArea:GLOBAL flag.
  *
- * This is a bitwise flag that supposed to be used in VehicleProperty enum.
+ * Used to create property ID in VehicleProperty enum.
  */
 enum VehicleArea : int32_t {
-      GLOBAL       = 0x01000000,
-      ZONE         = 0x02000000,
-      WINDOW       = 0x03000000,
-      MIRROR       = 0x04000000,
-      SEAT         = 0x05000000,
-      DOOR         = 0x06000000,
+    GLOBAL      = 0x01000000,
+    /** WINDOW maps to enum VehicleAreaWindow */
+    WINDOW      = 0x03000000,
+    /** MIRROR maps to enum VehicleAreaMirror */
+    MIRROR      = 0x04000000,
+    /** SEAT maps to enum VehicleAreaSeat */
+    SEAT        = 0x05000000,
+    /** DOOR maps to enum VehicleAreaDoor */
+    DOOR        = 0x06000000,
+    /** WHEEL maps to enum Wheel */
+    WHEEL       = 0x07000000,
 
-      MASK         = 0x0f000000,
+    MASK        = 0x0f000000,
 };
 
 /**
  * Enumerates property groups.
  *
- * This is a bitwise flag that supposed to be used in VehicleProperty enum.
+ * Used to create property ID in VehicleProperty enum.
  */
 enum VehiclePropertyGroup : int32_t {
     /**
-     * Properties declared in AOSP must have this flag.
+     * Properties declared in AOSP must use this flag.
      */
-    SYSTEM         = 0x10000000,
+    SYSTEM      = 0x10000000,
 
     /**
-     * Properties declared by vendors must have this flag.
+     * Properties declared by vendors must use this flag.
      */
-    VENDOR         = 0x20000000,
+    VENDOR      = 0x20000000,
 
-    MASK           = 0xf0000000,
+    MASK        = 0xf0000000,
 };
 
 /**
  * Declares all vehicle properties. VehicleProperty has a bitwise structure.
  * Each property must have:
- *   - an unique id from range 0x0100 - 0xffff
- *   - associated data type using VehiclePropertyType
- *   - property group (VehiclePropertyGroup)
- *   - vehicle area (VehicleArea)
+ *  - a unique id from range 0x0100 - 0xffff
+ *  - associated data type using VehiclePropertyType
+ *  - property group (VehiclePropertyGroup)
+ *  - vehicle area (VehicleArea)
  *
  * Vendors are allowed to extend this enum with their own properties. In this
  * case they must use VehiclePropertyGroup:VENDOR flag when property is
  * declared.
+ *
+ * When a property's status field is not set to AVAILABLE:
+ *  - IVehicle#set may return StatusCode::NOT_AVAILABLE.
+ *  - IVehicle#get is not guaranteed to work.
  */
-enum VehicleProperty: int32_t {
+enum VehicleProperty : int32_t {
 
     /** Undefined property. */
     INVALID = 0x00000000,
@@ -105,14 +114,14 @@
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
      */
-    INFO_VIN= (
+    INFO_VIN = (
         0x0100
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:STRING
         | VehicleArea:GLOBAL),
 
     /**
-     * Maker name of vehicle
+     * Manufacturer of vehicle
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
@@ -162,11 +171,11 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * List of fuels the vehicle may use.  Uses enum FuelType
+     * List of fuels the vehicle may use
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
-     * @unit VehicleUnit:MILLILITERS
+     * @data_enum FuelType
      */
     INFO_FUEL_TYPE = (
         0x0105
@@ -189,9 +198,10 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * List of connectors this EV may use.  Uses enum EvConnectorType
+     * List of connectors this EV may use
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
+     * @data_enum EvConnectorType
      * @access VehiclePropertyAccess:READ
      */
     INFO_EV_CONNECTOR_TYPE = (
@@ -201,9 +211,49 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Fuel door location
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @data_enum FuelDoorLocationType
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_FUEL_DOOR_LOCATION = (
+        0x0108
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * EV port location
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @data_enum PortLocationType
+     */
+    INFO_EV_PORT_LOCATION = (
+        0x0109
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Driver's seat location
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @data_enum VehicleAreaSeat
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_DRIVER_SEAT = (
+        0x010A
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+
+    /**
      * Current odometer value of the vehicle
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE | VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:KILOMETER
      */
@@ -216,7 +266,7 @@
     /**
      * Speed of the vehicle
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:METER_PER_SEC
      */
@@ -227,22 +277,9 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Engine on
-     *
-     * @change_mode VehiclePropertyChangeMode:STATIC
-     * @access VehiclePropertyAccess:READ
-     */
-    ENGINE_ON = (
-        0x0300
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:BOOLEAN
-        | VehicleArea:GLOBAL),
-
-
-    /**
      * Temperature of engine coolant
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:CELSIUS
      */
@@ -268,7 +305,7 @@
     /**
      * Temperature of engine oil
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:CELSIUS
      */
@@ -281,7 +318,7 @@
     /**
      * Engine rpm
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:RPM
      */
@@ -310,7 +347,7 @@
      *  int64Values[3] = rear right ticks
      *  int64Values[4] = rear left ticks
      *
-     * configArray is used to indicate the micrometers-per-wheel-tick value as well as
+     * configArray is used to indicate the micrometers-per-wheel-tick value and
      * which wheels are supported.  configArray is set as follows:
      *
      *  configArray[0], bits [0:3] = supported wheels.  Uses enum Wheel.
@@ -327,10 +364,10 @@
      * @access VehiclePropertyAccess:READ
      */
     WHEEL_TICK = (
-      0x0306
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:MIXED
-      | VehicleArea:GLOBAL),
+        0x0306
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT64_VEC
+        | VehicleArea:GLOBAL),
 
 
     /**
@@ -338,7 +375,7 @@
      *
      * Value may not exceed INFO_FUEL_CAPACITY
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:MILLILITER
      */
@@ -351,8 +388,8 @@
     /**
      * Fuel door open
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
-     * @access VehiclePropertyAccess:READ
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
      */
     FUEL_DOOR_OPEN = (
         0x0308
@@ -365,7 +402,7 @@
      *
      * Value may not exceed INFO_EV_BATTERY_CAPACITY
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:WH
      */
@@ -378,8 +415,8 @@
     /**
      * EV charge port open
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
-     * @access VehiclePropertyAccess:READ
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
      */
     EV_CHARGE_PORT_OPEN = (
         0x030A
@@ -390,7 +427,7 @@
     /**
      * EV charge port connected
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      */
     EV_CHARGE_PORT_CONNECTED = (
@@ -405,7 +442,7 @@
      * Positive value indicates battery is being charged.
      * Negative value indicates battery being discharged.
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:MW
      */
@@ -416,8 +453,42 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Range remaining
+     *
+     * Meters remaining of fuel and charge.  Range remaining shall account for
+     * all energy sources in a vehicle.  For example, a hybrid car's range will
+     * be the sum of the ranges based on fuel and battery.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @unit VehicleUnit:METER
+     */
+    RANGE_REMAINING = (
+        0x0308
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Tire pressure
+     *
+     * The min/max range is used to indicate the recommended tire pressure.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:KILOPASCAL
+     */
+    TIRE_PRESSURE = (
+        0x0309
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:WHEEL),
+
+    /**
      * Currently selected gear
      *
+     * This is the gear selected by the user.
+     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      * @data_enum VehicleGear
@@ -467,21 +538,12 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Driving status policy.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ
-     * @data_enum VehicleDrivingStatus
-     */
-    DRIVING_STATUS = (
-        0x0404
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
-        | VehicleArea:GLOBAL),
-
-    /**
      * Warning for fuel low level.
      *
+     * This property corresponds to the low fuel warning on the dashboard.
+     * Once FUEL_LEVEL_LOW is set, it should not be cleared until more fuel is
+     * added to the vehicle.
+     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      */
@@ -492,7 +554,9 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Night mode or not.
+     * Night mode
+     *
+     * True indicates that night mode is currently enabled.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
@@ -506,10 +570,9 @@
     /**
      * State of the vehicles turn signals
      *
-     * Values from VehicleTurnSignal
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleTurnSignal
      */
     TURN_SIGNAL_STATE = (
         0x0408
@@ -522,15 +585,20 @@
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleIgnitionState
      */
     IGNITION_STATE = (
         0x0409
-            | VehiclePropertyGroup:SYSTEM
-            | VehiclePropertyType:INT32
-            | VehicleArea:GLOBAL),
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
 
     /**
-     * ABS is active.  Set to true whenever ABS is activated.  Reset to false when ABS is off.
+     * ABS is active
+     *
+     * Set to true when ABS is active.  Reset to false when ABS is off.  This
+     * property may be intermittently set (pulsing) based on the real-time
+     * state of the ABS system.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
@@ -542,7 +610,11 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Traction Control is active.
+     * Traction Control is active
+     *
+     * Set to true when traction control (TC) is active.  Reset to false when
+     * TC is off.  This property may be intermittently set (pulsing) based on
+     * the real-time state of the TC system.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
@@ -556,10 +628,6 @@
     /**
      * Fan speed setting
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -567,15 +635,11 @@
         0x0500
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * Fan direction setting
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      * @data_enum VehicleHvacFanDirection
@@ -584,15 +648,11 @@
         0x0501
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * HVAC current temperature.
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -600,15 +660,11 @@
         0x0502
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:FLOAT
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * HVAC, target temperature set.
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -616,14 +672,10 @@
         0x0503
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:FLOAT
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
-     * On/off defrost
-     *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * On/off defrost for designated window
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -635,28 +687,25 @@
         | VehicleArea:WINDOW),
 
     /**
-     * On/off AC
-     *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * On/off AC for designated areaId
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
-     * @config_flags Supported zones
+     * @config_flags Supported areaIds
      */
     HVAC_AC_ON = (
         0x0505
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * On/off max AC
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * When MAX AC is on, the ECU may adjust the vent position, fan speed,
+     * temperature, etc as necessary to cool the vehicle as quickly as possible.
+     * Any parameters modified as a side effect of turning on/off the MAX AC
+     * parameter shall generate onPropertyEvent() callbacks to the VHAL.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -665,14 +714,16 @@
         0x0506
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * On/off max defrost
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * When MAX DEFROST is on, the ECU may adjust the vent position, fan speed,
+     * temperature, etc as necessary to defrost the windows as quickly as
+     * possible.  Any parameters modified as a side effect of turning on/off
+     * the MAX DEFROST parameter shall generate onPropertyEvent() callbacks to
+     * the VHAL.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -681,14 +732,15 @@
         0x0507
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
-     * On/off re-circulation
+     * Recirculation on/off
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * Controls the supply of exterior air to the cabin.  Recirc “on” means the
+     * majority of the airflow into the cabin is originating in the cabin.
+     * Recirc “off” means the majority of the airflow into the cabin is coming
+     * from outside the car.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -697,14 +749,25 @@
         0x0508
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
-     * On/off dual. This must be defined per each row.
+     * Enable temperature coupling between zones.
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * The areaId for this property must include the zones that are coupled
+     * together.  Typically, the front two zones (ROW_1_LEFT and ROW_1_RIGHT)
+     * are coupled together when this property is enabled.  Thus, the areaId
+     * shall be (ROW_1_LEFT | ROW_1_RIGHT).  When the property is enabled, the
+     * ECU may synchronize the temperature for the affected zones.  Any
+     * parameters modified as a side effect of turning on/off the DUAL_ON
+     * parameter shall generate onPropertyEvent() callbacks to the VHAL.  In
+     * addition, if setting a temperature (i.e. driver's temp) changes another
+     * temperature (i.e. front passenger's temp), then the appropriate
+     * onPropertyEvent() callbacks must be generated.  If a user changes a
+     * temperature that breaks the coupling (e.g. setting the passenger
+     * temperature independently) then the VHAL must send the appropriate
+     * onPropertyEvent() callbacks (i.e. HVAC_DUAL_ON = false,
+     * HVAC_TEMPERATURE_SET[zone] = xxx, etc).
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -713,15 +776,11 @@
         0x0509
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * On/off automatic mode
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -729,7 +788,7 @@
         0x050A
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * Seat temperature
@@ -742,10 +801,6 @@
      * min/max range defines the allowable range and number of steps in each
      * direction.
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -758,12 +813,9 @@
     /**
      * Side Mirror Heat
      *
-     * Increase values denote higher heating levels for side mirrors.
-     * 0 indicates heating is turned off.
-     *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * Increasing values denote higher heating levels for side mirrors.
+     * The Max value in the config data represents the highest heating level.
+     * The Min value in the config data MUST be zero and indicates no heating.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -775,51 +827,42 @@
         | VehicleArea:MIRROR),
 
     /**
-     * Steering Wheel Temperature
+     * Steering Wheel Heating/Cooling
      *
-     * Sets the temperature for the steering wheel
+     * Sets the amount of heating/cooling for the steering wheel
+     * config data Min and Max MUST be set appropriately.
      * Positive value indicates heating.
      * Negative value indicates cooling.
      * 0 indicates temperature control is off.
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
-    HVAC_STEERING_WHEEL_TEMP = (
+    HVAC_STEERING_WHEEL_HEAT = (
         0x050D
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32
         | VehicleArea:GLOBAL),
 
     /**
-     * Temperature units
+     * Temperature units for display
      *
      * Indicates whether the temperature is in Celsius, Fahrenheit, or a
-     * different unit from VehicleUnit enum.
-     * This parameter affects all HVAC temperatures in the system.
-     *
-     * IVehicle#get is not guaranteed to work if HVAC unit is off.  See
-     * HVAC_POWER_ON property for details.
+     * different unit from VehicleUnit enum.  This parameter MAY be used for
+     * displaying any HVAC temperature in the system.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ
+     * @access VehiclePropertyAccess:READ_WRITE
      */
-    HVAC_TEMPERATURE_UNITS = (
+    HVAC_TEMPERATURE_DISPLAY_UNITS = (
         0x050E
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32
-        | VehicleArea:ZONE),
+        | VehicleArea:GLOBAL),
 
     /**
      * Actual fan speed
      *
-     * IVehicle#get is not guaranteed to work if HVAC unit is off.  See
-     * HVAC_POWER_ON property for details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      */
@@ -827,37 +870,38 @@
         0x050F
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
-     * Represents power state for HVAC. Some HVAC properties must require
-     * matching power to be turned on to get out of OFF state. For non-zoned
-     * HVAC properties, VEHICLE_ALL_ZONE corresponds to global power state.
+     * Represents global power state for HVAC.  Setting this property to false
+     * MAY mark some properties that control individual HVAC features/subsystems
+     * to UNAVAILABLE state. Setting this property to true MAY mark some
+     * properties that control individual HVAC features/subsystems to AVAILABLE
+     * state (unless any/all of them are UNAVAILABLE on their own individual
+     * merits).  The list of properties affected by HVAC_POWER_ON must be set
+     * in the VehiclePropConfig.configArray.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
-     * @config_string list of HVAC properties whose power is controlled by this
-     *                property. Format is hexa-decimal number (0x...) separated
-     *                by comma like "0x500,0x503". All zones defined in these
-     *                affected properties must be available in the property.
      */
     HVAC_POWER_ON = (
         0x0510
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * Fan Positions Available
      *
-     * This is a bit mask of fan positions available for the zone.  Each available fan direction is
-     * denoted by a separate entry in the vector.  A fan direction may have multiple bits from
-     * vehicle_hvac_fan_direction set.  For instance, a typical car may have the following setting:
-     *   - [0] = FAN_DIRECTION_FACE (0x1)
-     *   - [1] = FAN_DIRECTION_FLOOR (0x2)
-     *   - [2] = FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR (0x3)
-     *   - [3] = FAN_DIRECTION_DEFROST (0x4)
-     *   - [4] = FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST (0x6)
+     * This is a bit mask of fan positions available for the zone.  Each
+     * available fan direction is denoted by a separate entry in the vector.  A
+     * fan direction may have multiple bits from vehicle_hvac_fan_direction set.
+     * For instance, a typical car may have the following fan positions:
+     *   - FAN_DIRECTION_FACE (0x1)
+     *   - FAN_DIRECTION_FLOOR (0x2)
+     *   - FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR (0x3)
+     *   - FAN_DIRECTION_DEFROST (0x4)
+     *   - FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST (0x6)
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
@@ -866,13 +910,14 @@
         0x0511
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32_VEC
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
-     * Automatic re-circulation on/off
+     * Automatic recirculation on/off
      *
-     * IVehicle#set and IVehicle#get must return StatusCode::NOT_AVAILABLE when HVAC unit is off.
-     * See HVAC_POWER_ON property for details.
+     * When automatic recirculation is ON, the HVAC system may automatically
+     * switch to recirculation mode if the vehicle detects poor incoming air
+     * quality.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -881,12 +926,32 @@
         0x0512
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
+
+    /**
+     * Seat ventilation
+     *
+     * 0 indicates off.
+     * Positive values indicates ventilation level.
+     *
+     * Used by HVAC apps and Assistant to enable, change, or read state of seat
+     * ventilation.  This is different than seating cooling. It can be on at the
+     * same time as cooling, or not.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_SEAT_VENTILATION = (
+        0x0513
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
 
     /**
      * Outside temperature
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:CELSIUS
      */
@@ -899,7 +964,7 @@
     /**
      * Cabin temperature
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:CELSIUS
      */
@@ -907,31 +972,7 @@
         0x0704
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:FLOAT
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Radio presets stored on the Car radio module. The data type used is int32
-     * array with the following fields:
-     * <ul>
-     *    <li> int32Values[0]: Preset number </li>
-     *    <li> int32Values[1]: Band type (see #RADIO_BAND_FM in
-     *    system/core/include/system/radio.h).
-     *    <li> int32Values[2]: Channel number </li>
-     *    <li> int32Values[3]: Sub channel number </li>
-     * </ul>
-     *
-     * NOTE: When getting a current preset config ONLY set preset number (i.e.
-     * int32Values[0]). For setting a preset other fields are required.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @config_flags Number of presets supported
-     */
-    RADIO_PRESET = (
-        0x0801
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
+        | VehicleArea:SEAT),
 
     /**
      * Property to control power state of application processor
@@ -942,40 +983,36 @@
      * For configuration information, VehiclePropConfig.configFlags can
      * have bit flag combining values in VehicleApPowerStateConfigFlag.
      *
-     * Value format for IVehicle#get / IVehicle#subscribe:
-     *   int32Values[0] : vehicle_ap_power_state_type
+     *   int32Values[0] : VehicleApPowerStateReq enum value
      *   int32Values[1] : additional parameter relevant for each state,
      *                    0 if not used.
-     * Value format for IVehicle#set:
-     *   int32Values[0] : vehicle_ap_power_state_set_type
-     *   int32Values[1] : additional parameter relevant for each request. should be 0 if not used.
      *
-     * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
-     * @access VEHICLE_PROP_ACCESS_READ_WRITE
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VEHICLE_PROP_ACCESS_READ
      */
-    AP_POWER_STATE = (
+    AP_POWER_STATE_REQ = (
         0x0A00
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32_VEC
         | VehicleArea:GLOBAL),
 
     /**
-     * Property to represent brightness of the display. Some cars have single
-     * control for the brightness of all displays and this property is to share
-     * change in that control.
+     * Property to report power state of application processor
      *
-     * If this is writable, android side can set this value when user changes
-     * display brightness from Settings. If this is read only, user may still
-     * change display brightness from Settings, but that will not be reflected
-     * to other displays.
+     * It is assumed that AP's power state is controller by separate power
+     * controller.
+     *
+     *   int32Values[0] : VehicleApPowerStateReport enum value
+     *   int32Values[1] : Time in ms to wake up, if necessary.  Otherwise 0.
+
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
+     * @access VEHICLE_PROP_ACCESS_WRITE
      */
-    DISPLAY_BRIGHTNESS = (
+    AP_POWER_STATE_REPORT = (
         0x0A01
         | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
+        | VehiclePropertyType:INT32_VEC
         | VehicleArea:GLOBAL),
 
     /**
@@ -997,6 +1034,25 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Property to represent brightness of the display. Some cars have single
+     * control for the brightness of all displays and this property is to share
+     * change in that control.
+     *
+     * If this is writable, android side can set this value when user changes
+     * display brightness from Settings. If this is read only, user may still
+     * change display brightness from Settings, but that must not be reflected
+     * to other displays.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    DISPLAY_BRIGHTNESS = (
+        0x0A03
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
      * Property to feed H/W input events to android
      *
      * int32Values[0] : action defined by VehicleHwKeyInputAction
@@ -1004,6 +1060,7 @@
      * int32Values[2] : target display defined in VehicleDisplay. Events not
      *                  tied to specific display must be sent to
      *                  VehicleDisplay#MAIN.
+     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      * @config_flags
@@ -1014,36 +1071,23 @@
         | VehiclePropertyType:INT32_VEC
         | VehicleArea:GLOBAL),
 
-    /**
-     * Current date and time, encoded as Unix time.
-     * This value denotes the number of seconds that have elapsed since
-     * 1/1/1970.
+    /***************************************************************************
+     * Most Car Cabin properties have both a POSition and MOVE parameter.  These
+     * are used to control the various movements for seats, doors, and windows
+     * in a vehicle.
      *
-     * @change_mode VehiclePropertyChangeMode:ON_SET
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @unit VehicleUnit:SECS
-     */
-    UNIX_TIME = (
-        0x0A30
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT64
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Current time only.
-     * Some vehicles may not keep track of date.  This property only affects
-     * the current time, in seconds during the day.  Thus, the max value for
-     * this parameter is 86,400 (24 * 60 * 60)
+     * A POS parameter allows the user to set the absolution position.  For
+     * instance, for a door, 0 indicates fully closed and max value indicates
+     * fully open.  Thus, a value halfway between min and max must indicate
+     * the door is halfway open.
      *
-     * @change_mode VehiclePropertyChangeMode:ON_SET
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @unit VehicleUnit:SECS
-     */
-    CURRENT_TIME_IN_SECONDS = (
-        0x0A31
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
-        | VehicleArea:GLOBAL),
+     * A MOVE parameter moves the device in a particular direction.  The sign
+     * indicates direction, and the magnitude indicates speed (if multiple
+     * speeds are available).  For a door, a move of -1 will close the door, and
+     * a move of +1 will open it.  Once a door reaches the limit of open/close,
+     * the door should automatically stop moving.  The user must NOT need to
+     * send a MOVE(0) command to stop the door at the end of its range.
+     **************************************************************************/
 
     /**
      * Door position
@@ -1198,7 +1242,7 @@
      *
      * This setting allows the user to save the current seat position settings
      * into the selected preset slot.  The maxValue for each seat position
-     * shall match the maxValue for SEAT_MEMORY_SELECT.
+     * must match the maxValue for SEAT_MEMORY_SELECT.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:WRITE
@@ -1588,6 +1632,14 @@
      * Max = window up / closed
      * Min = window down / open
      *
+     * For a window that may open out of plane (i.e. vent mode of sunroof) this
+     * parameter will work with negative values as follows:
+     *  Max = sunroof completely open
+     *  0 = sunroof closed.
+     *  Min = sunroof vent completely open
+     *
+     *  Note that in this mode, 0 indicates the window is closed.
+     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -1605,6 +1657,21 @@
      * Magnitude denotes relative speed.  I.e. +2 is faster than +1 in raising
      * the window.
      *
+     * For a window that may open out of plane (i.e. vent mode of sunroof) this
+     * parameter will work as follows:
+     *
+     *  If sunroof is open:
+     *    Max = open the sunroof further, automatically stop when fully open.
+     *    Min = close the sunroof, automatically stop when sunroof is closed.
+     *
+     * If vent is open:
+     *  Max = close the vent, automatically stop when vent is closed.
+     *  Min = open the vent further, automatically stop when vent is fully open.
+     *
+     * If window is in the closed position:
+     *  Max = open the sunroof, automatically stop when sunroof is fully open.
+     *  Min = open the vent, automatically stop when vent is fully open.
+     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -1615,40 +1682,6 @@
         | VehicleArea:WINDOW),
 
     /**
-     * Window Vent Position
-     *
-     * This feature is used to control the vent feature on a sunroof.
-     *
-     * Max = vent open
-     * Min = vent closed
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    WINDOW_VENT_POS = (
-        0x0BC2
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
-        | VehicleArea:WINDOW),
-
-    /**
-     * Window Vent Move
-     *
-     * This feature is used to control the vent feature on a sunroof.
-     *
-     * Max = vent open
-     * Min = vent closed
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    WINDOW_VENT_MOVE = (
-        0x0BC3
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
-        | VehicleArea:WINDOW),
-
-    /**
      * Window Lock
      *
      * True indicates windows are locked and can't be moved.
@@ -1727,10 +1760,10 @@
      * @access VehiclePropertyAccess:READ
      */
     OBD2_LIVE_FRAME = (
-      0x0D00
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:MIXED
-      | VehicleArea:GLOBAL),
+        0x0D00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:GLOBAL),
 
     /**
      * OBD2 Freeze Frame Sensor Data
@@ -1757,10 +1790,10 @@
      * @access VehiclePropertyAccess:READ
      */
     OBD2_FREEZE_FRAME = (
-      0x0D01
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:MIXED
-      | VehicleArea:GLOBAL),
+        0x0D01
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:GLOBAL),
 
     /**
      * OBD2 Freeze Frame Information
@@ -1778,10 +1811,10 @@
      * @access VehiclePropertyAccess:READ
      */
     OBD2_FREEZE_FRAME_INFO = (
-      0x0D02
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:MIXED
-      | VehicleArea:GLOBAL),
+        0x0D02
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:GLOBAL),
 
     /**
      * OBD2 Freeze Frame Clear
@@ -1804,10 +1837,164 @@
      * @access VehiclePropertyAccess:WRITE
      */
     OBD2_FREEZE_FRAME_CLEAR = (
-      0x0D03
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:MIXED
-      | VehicleArea:GLOBAL),
+        0x0D03
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Headlights State
+     *
+     * Return the current state of headlights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    HEADLIGHTS_STATE = (
+        0x0E00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * High beam lights state
+     *
+     * Return the current state of high beam lights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    HIGH_BEAM_LIGHTS_STATE = (
+        0x0E01
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Fog light state
+     *
+     * Return the current state of fog lights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    FOG_LIGHTS_STATE = (
+        0x0E02
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Hazard light status
+     *
+     * Return the current status of hazard lights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    HAZARD_LIGHTS_STATE = (
+        0x0E03
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Headlight switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    HEADLIGHTS_SWITCH = (
+        0x0E10
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * High beam light switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    HIGH_BEAM_LIGHTS_SWITCH = (
+        0x0E11
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Fog light switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    FOG_LIGHTS_SWITCH = (
+        0x0E12
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Hazard light switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    HAZARD_LIGHTS_SWITCH = (
+        0x0E13
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+};
+
+/**
+ * Used by lights state properties to enumerate the current state of the lights.
+ *
+ * Most XXX_LIGHTS_STATE properties will only report ON and OFF states.  Only
+ * the HEADLIGHTS_STATE property will report DAYTIME_RUNNING.
+ */
+enum  VehicleLightState : int32_t {
+
+    OFF = 0,
+    ON = 1,
+    DAYTIME_RUNNING = 2
+};
+
+/**
+ * Used by lights switch properties to enumerate user selected switch setting.
+ *
+ * XXX_LIGHTS_SWITCH properties report the switch settings that the user
+ * selects.  The switch setting may be decoupled from the state reported if the
+ * user selects AUTOMATIC.
+ */
+enum VehicleLightSwitch : int32_t {
+    OFF = 0,
+    ON = 1,
+    /**
+     * Daytime running lights mode.  Most cars automatically use DRL but some
+     * cars allow the user to activate them manually.
+     */
+    DAYTIME_RUNNING = 2,
+    /**
+     * Allows the vehicle ECU to set the lights automatically
+     */
+    AUTOMATIC = 0x100,
 };
 
 /**
@@ -1839,6 +2026,24 @@
 };
 
 /**
+ * Used by INFO_FUEL_DOOR_LOCATION/INFO_CHARGE_PORT_LOCATION to enumerate fuel door or
+ * ev port location.
+ */
+enum PortLocationType : int32_t {
+    /**
+     * Default type if the vehicle does not know or report the Fuel door
+     * and ev port location.
+     */
+    UNKNOWN = 0,
+    FRONT_LEFT = 1,
+    FRONT_RIGHT = 2,
+    REAR_RIGHT = 3,
+    REAR_LEFT = 4,
+    FRONT = 5,
+    REAR = 6,
+};
+
+/**
  * Used by INFO_FUEL_TYPE to enumerate the type of fuels this vehicle uses.
  * Consistent with projection protocol.
  */
@@ -1897,14 +2102,6 @@
     ERROR = 4,
 };
 
-/**
- * Constants relevant to radio.
- */
-enum VehicleRadioConstants : int32_t {
-    /** Minimum value for the radio preset */
-    VEHICLE_RADIO_PRESET_MIN_VALUE = 1,
-};
-
 enum VehicleApPowerStateConfigFlag : int32_t /* NOTE: type is guessed */ {
     /**
      * AP can enter deep sleep state. If not set, AP will always shutdown from
@@ -1919,7 +2116,7 @@
     CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2,
 };
 
-enum VehicleApPowerState : int32_t /* NOTE: type is guessed */ {
+enum VehicleApPowerStateReq : int32_t {
     /** vehicle HAL will never publish this state to AP */
     OFF = 0,
 
@@ -1944,6 +2141,16 @@
     SHUTDOWN_PREPARE = 4,
 };
 
+/**
+ * Index in int32Values for VehicleProperty#AP_POWER_STATE_REQ property.
+ */
+enum VehicleApPowerStateReqIndex : int32_t {
+    STATE = 0,
+    ADDITIONAL = 1,
+};
+
+
+
 enum VehicleApPowerStateShutdownParam : int32_t {
     /** AP must shutdown immediately. Postponing is not allowed. */
     SHUTDOWN_IMMEDIATELY = 1,
@@ -1955,7 +2162,7 @@
     SHUTDOWN_ONLY = 3,
 };
 
-enum VehicleApPowerSetState : int32_t /* NOTE: type is guessed */ {
+enum VehicleApPowerStateReport : int32_t {
     /**
      * AP has finished boot up, and can start shutdown if requested by power
      * controller.
@@ -2020,14 +2227,6 @@
 };
 
 /**
- * Index in int32Values for VehicleProperty#AP_POWER_STATE property.
- */
-enum VehicleApPowerStateIndex : int32_t {
-    STATE = 0,
-    ADDITIONAL = 1,
-};
-
-/**
  * Enum to represent bootup reason.
  */
 enum VehicleApPowerBootupReason : int32_t {
@@ -2061,7 +2260,7 @@
 };
 
 enum VehicleDisplay : int32_t {
-    /** center console */
+    /** The primary Android display (for example, center console) */
     MAIN = 0,
 
     INSTRUMENT_CLUSTER = 1,
@@ -2087,6 +2286,7 @@
     NANO_SECS      = 0x50,
     SECS           = 0x53,
     YEAR           = 0x59,
+    KILOPASCAL     = 0x70,
 
     // Electrical Units
     WATT_HOUR      = 0x60,
@@ -2095,46 +2295,33 @@
     MILLIWATTS     = 0x63,
 };
 
-  /**
-   * This describes how value of property can change.
-   */
+/**
+ * This describes how value of property can change.
+ */
 enum VehiclePropertyChangeMode : int32_t {
-  /**
-   * Property of this type must never be changed. Subscription is not supported
-   * for these properties.
-   */
-  STATIC = 0x00,
+    /**
+     * Property of this type must never be changed. Subscription is not supported
+     * for these properties.
+     */
+    STATIC = 0x00,
 
-  /**
-   * Property of this type must be reported when there is a change.
-   * IVehicle#get call must return the current value.
-   * Set operation for this property is assumed to be asynchronous. When the
-   * property is read (using IVehicle#get) after IVehicle#set, it may still
-   * return old value until underlying H/W backing this property has actually
-   * changed the state. Once state is changed, the property must dispatch
-   * changed value as event.
-   */
-  ON_CHANGE = 0x01,
+    /**
+     * Properties of this type must report when there is a change.
+     * IVehicle#get call must return the current value.
+     * Set operation for this property is assumed to be asynchronous. When the
+     * property is read (using IVehicle#get) after IVehicle#set, it may still
+     * return old value until underlying H/W backing this property has actually
+     * changed the state. Once state is changed, the property must dispatch
+     * changed value as event.
+     */
+    ON_CHANGE = 0x01,
 
-  /**
-   * Property of this type change continuously and requires fixed rate of
-   * sampling to retrieve the data.
-   */
-  CONTINUOUS = 0x02,
-
-  /**
-   * Property of this type may be polled to get the current value.
-   */
-  POLL = 0x03,
-
-  /**
-   * This is for property where change event must be sent only when the
-   * value is set from external component. Normal value change must not trigger
-   * event. For example, clock property can send change event only when it is
-   * set, outside android, for case like user setting time or time getting
-   * update. There is no need to send it per every value change.
-   */
-  ON_SET = 0x04,
+    /**
+     * Properties of this type change continuously and require a fixed rate of
+     * sampling to retrieve the data.  Implementers may choose to send extra
+     * notifications on significant value changes.
+     */
+    CONTINUOUS = 0x02,
 };
 
 /**
@@ -2158,8 +2345,15 @@
     /** Property is available and behaving normally */
     AVAILABLE   = 0x00,
     /**
-     * Property is not available, for read and/or write.  This is a transient state, as the
-     *  property is expected to be available at a later time.
+     * A property in this state is not available for reading and writing.  This
+     * is a transient state that depends on the availability of the underlying
+     * implementation (e.g. hardware or driver). It MUST NOT be used to
+     * represent features that this vehicle is always incapable of.  A get() of
+     * a property in this state MAY return an undefined value, but MUST
+     * correctly describe its status as UNAVAILABLE A set() of a property in
+     * this state MAY return NOT_AVAILABLE. The HAL implementation MUST ignore
+     * the value of the status field when writing a property value coming from
+     * Android.
      */
     UNAVAILABLE = 0x01,
     /** There is an error with this property. */
@@ -2167,28 +2361,13 @@
 };
 
 /**
- * Car states.
- *
- * The driving states determine what features of the UI will be accessible.
- */
-enum VehicleDrivingStatus : int32_t {
-    UNRESTRICTED = 0x00,
-    NO_VIDEO = 0x01,
-    NO_KEYBOARD_INPUT = 0x02,
-    NO_VOICE_INPUT = 0x04,
-    NO_CONFIG = 0x08,
-    LIMIT_MESSAGE_LEN = 0x10,
-};
-
-/**
  * Various gears which can be selected by user and chosen in system.
  */
-enum VehicleGear: int32_t {
+enum VehicleGear : int32_t {
     GEAR_NEUTRAL = 0x0001,
     GEAR_REVERSE = 0x0002,
     GEAR_PARK = 0x0004,
     GEAR_DRIVE = 0x0008,
-    GEAR_LOW = 0x0010,
     GEAR_1 = 0x0010,
     GEAR_2 = 0x0020,
     GEAR_3 = 0x0040,
@@ -2201,27 +2380,6 @@
 };
 
 /**
- * Various zones in the car.
- *
- * Zones are used for Air Conditioning purposes and divide the car into physical
- * area zones.
- */
-enum VehicleAreaZone : int32_t {
-  ROW_1_LEFT = 0x00000001,
-  ROW_1_CENTER = 0x00000002,
-  ROW_1_RIGHT = 0x00000004,
-  ROW_2_LEFT = 0x00000010,
-  ROW_2_CENTER = 0x00000020,
-  ROW_2_RIGHT = 0x00000040,
-  ROW_3_LEFT = 0x00000100,
-  ROW_3_CENTER = 0x00000200,
-  ROW_3_RIGHT = 0x00000400,
-  ROW_4_LEFT = 0x00001000,
-  ROW_4_CENTER = 0x00002000,
-  ROW_4_RIGHT = 0x00004000,
-};
-
-/**
  * Various Seats in the car.
  */
 enum VehicleAreaSeat : int32_t {
@@ -2240,15 +2398,18 @@
  * Various windshields/windows in the car.
  */
 enum VehicleAreaWindow : int32_t {
-    FRONT_WINDSHIELD = 0x0001,
-    REAR_WINDSHIELD = 0x0002,
-    ROOF_TOP = 0x0004,
-    ROW_1_LEFT = 0x0010,
-    ROW_1_RIGHT = 0x0020,
-    ROW_2_LEFT = 0x0100,
-    ROW_2_RIGHT = 0x0200,
-    ROW_3_LEFT = 0x1000,
-    ROW_3_RIGHT = 0x2000,
+    FRONT_WINDSHIELD  = 0x00000001,
+    REAR_WINDSHIELD   = 0x00000002,
+    ROW_1_LEFT        = 0x00000010,
+    ROW_1_RIGHT       = 0x00000040,
+    ROW_2_LEFT        = 0x00000100,
+    ROW_2_RIGHT       = 0x00000400,
+    ROW_3_LEFT        = 0x00001000,
+    ROW_3_RIGHT       = 0x00004000,
+
+    ROOF_TOP_1        = 0x00010000,
+    ROOF_TOP_2        = 0x00020000,
+
 };
 
 enum VehicleAreaDoor : int32_t {
@@ -2272,7 +2433,6 @@
     NONE = 0x00,
     RIGHT = 0x01,
     LEFT = 0x02,
-    EMERGENCY = 0x04,
 };
 
 struct VehicleAreaConfig {
@@ -2346,9 +2506,6 @@
  * events.
  */
 struct VehiclePropValue {
-    /** Property identifier */
-    int32_t prop;
-
     /** Time is elapsed nanoseconds since boot */
     int64_t timestamp;
 
@@ -2358,6 +2515,9 @@
      */
     int32_t areaId;
 
+    /** Property identifier */
+    int32_t prop;
+
     /** Status of the property */
     VehiclePropertyStatus status;
 
@@ -2397,11 +2557,11 @@
     /** Steering wheel is locked */
     LOCK = 1,
 
-     /**
-      * Steering wheel is not locked, engine and all accessories are OFF. If
-      * car can be in LOCK and OFF state at the same time than HAL must report
-      * LOCK state.
-      */
+    /**
+     * Steering wheel is not locked, engine and all accessories are OFF. If
+     * car can be in LOCK and OFF state at the same time than HAL must report
+     * LOCK state.
+     */
     OFF,
 
     /**
@@ -2420,33 +2580,6 @@
     START
 };
 
-
-/**
- * Represent the operation where the current error has happened.
- */
-enum VehiclePropertyOperation : int32_t {
-    /**
-     * Generic error to this property which is not tied to any operation.
-     */
-    GENERIC = 0,
-
-    /**
-     * Error happened while handling property set.
-     */
-    SET = 1,
-
-    /**
-     * Error happened while handling property get.
-     */
-    GET = 2,
-
-    /**
-     * Error happened while handling property subscription.
-     */
-    SUBSCRIBE = 3,
-};
-
-
 enum SubscribeFlags : int32_t {
     UNDEFINED = 0x0,
 
@@ -2454,15 +2587,13 @@
      * Subscribe to event that was originated in vehicle HAL
      * (most likely this event came from the vehicle itself).
      */
-    HAL_EVENT = 0x1,
+    EVENTS_FROM_CAR = 0x1,
 
     /**
      * Use this flag to subscribe on events when IVehicle#set(...) was called by
      * vehicle HAL's client (e.g. Car Service).
      */
-    SET_CALL = 0x2,
-
-    DEFAULT = HAL_EVENT,
+    EVENTS_FROM_ANDROID = 0x2,
 };
 
 /**
@@ -2483,7 +2614,7 @@
      */
     float sampleRate;
 
-    /** Flags that indicate what kind of events listen to. */
+    /** Flags that indicate to which event sources to listen. */
     SubscribeFlags flags;
 };
 
@@ -2773,11 +2904,11 @@
     ACCELERATOR_PEDAL_POSITION_E = 54, /* PID 0x4A */
     ACCELERATOR_PEDAL_POSITION_F = 55, /* PID 0x4B */
     COMMANDED_THROTTLE_ACTUATOR = 56, /* PID 0x4C */
-    ETHANOL_FUEL_PERCENTAGE = 57,/* PID 0x52 */
+    ETHANOL_FUEL_PERCENTAGE = 57, /* PID 0x52 */
     ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58, /* PID 0x53 */
     SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59, /* PID 0x55 */
     SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60, /* PID 0x57 */
-    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,/* PID 0x55 */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61, /* PID 0x55 */
     SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62, /* PID 0x57 */
     LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63, /* PID 0x56 */
     LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64, /* PID 0x58 */
@@ -3003,7 +3134,7 @@
  * - Layer version
  * - Number of publisher IDs (N)
  * - N x publisher ID
-*/
+ */
 enum VmsAvailabilityStateIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
     SEQUENCE_NUMBER = 1,
     NUMBER_OF_ASSOCIATED_LAYERS = 2,
diff --git a/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
index 123d339..9bfd3ba 100644
--- a/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
+++ b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
@@ -5,3 +5,4 @@
     class late_start
     user system
     group system input
+    writepid /dev/cpuset/system-background/tasks
\ No newline at end of file
diff --git a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
index e1f5faa..a634441 100644
--- a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
+++ b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
@@ -1,5 +1,6 @@
 service vendor.bluetooth-1-0 /vendor/bin/hw/android.hardware.bluetooth@1.0-service
     class hal
+    capabilities BLOCK_SUSPEND NET_ADMIN SYS_NICE
     user bluetooth
     group bluetooth
     writepid /dev/stune/foreground/tasks
diff --git a/bluetooth/a2dp/1.0/Android.bp b/bluetooth/a2dp/1.0/Android.bp
new file mode 100644
index 0000000..5e85290
--- /dev/null
+++ b/bluetooth/a2dp/1.0/Android.bp
@@ -0,0 +1,27 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.bluetooth.a2dp@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IBluetoothAudioHost.hal",
+        "IBluetoothAudioOffload.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "BitsPerSample",
+        "ChannelMode",
+        "CodecConfiguration",
+        "CodecType",
+        "SampleRate",
+        "Status",
+    ],
+    gen_java: false,
+}
+
diff --git a/bluetooth/a2dp/1.0/IBluetoothAudioHost.hal b/bluetooth/a2dp/1.0/IBluetoothAudioHost.hal
new file mode 100644
index 0000000..666419d
--- /dev/null
+++ b/bluetooth/a2dp/1.0/IBluetoothAudioHost.hal
@@ -0,0 +1,61 @@
+/*
+ * 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.bluetooth.a2dp@1.0;
+
+/**
+ * HAL interface for Bluetooth A2DP Offload functionality where
+ * the encoding of the A2DP data packets is offloaded to platform
+ * specific encoders. The A2DP control path is maintained in the
+ * Bluetooth stack.
+ *
+ * This interface is from HAL server to HAL client.
+ *
+ * The HAL server must call into the IBluetoothAudioHost to initiate
+ * the start, suspend and stop of the streaming operation. These
+ * calls return immediately and the results, if any, are send over
+ * the IBluetoothAudioOffload interface.
+ */
+
+interface IBluetoothAudioHost {
+    /**
+     * Invoked when the start stream is requested from HAL server
+     * to HAL client. This indicates that the HAL server
+     * has initialized the platform for streaming use case, and the
+     * HAL client can proceed with the streaming procedure. The
+     * result of the operation must be provided by the HAL
+     * client using the IBluetoothAudioOffload interface.
+     */
+    oneway startStream();
+
+    /**
+     * Invoked when the suspend stream is requested from HAL server
+     * to HAL client. This indicates that the HAL server
+     * wants to suspend the streaming procedure. The result of the
+     * operation must be provided by the HAL client using the
+     * IBluetoothAudioOffload interface.
+     */
+    oneway suspendStream();
+
+    /**
+     * Invoked when the stop stream is requested from HAL server
+     * to HAL client. This indicates that the HAL server wants to
+     * stop and reset the streaming procedure. There is no result
+     * provided by the HAL client for this call.
+     */
+    oneway stopStream();
+
+};
diff --git a/bluetooth/a2dp/1.0/IBluetoothAudioOffload.hal b/bluetooth/a2dp/1.0/IBluetoothAudioOffload.hal
new file mode 100644
index 0000000..52a580f
--- /dev/null
+++ b/bluetooth/a2dp/1.0/IBluetoothAudioOffload.hal
@@ -0,0 +1,85 @@
+/*
+ * 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.bluetooth.a2dp@1.0;
+
+import IBluetoothAudioHost;
+
+/**
+ * HAL interface for Bluetooth A2DP Offload functionality where
+ * the encoding of the A2DP data packets is offloaded to platform
+ * specific encoders. The A2DP control path is maintained in the
+ * Bluetooth stack.
+ *
+ * This interface is from HAL client to HAL server.
+ *
+ * The HAL client must provide the handle of IBluetoothAudioHost as well
+ * as codec configuration to the HAL server, when its connected to an
+ * active A2DP Sink device. HAL Server, based on the feedback from the Audio
+ * framework must call into the commands provided by the IBluetoothAudioHost.
+ * HAL client must call into IBluetoothAudioOffload to provide the status of
+ * these commands. Once the device becomes inactive, the HAL client must
+ * call the endSession to terminate the session with the HAL server.
+ */
+interface IBluetoothAudioOffload {
+
+    /**
+     * Indicates that the HAL client is connected to an A2DP Sink device
+     * and is ready to stream audio. This function is also used to register
+     * the BluetoothAudioHost interface and the provide the current negotiated
+     * codec.
+     *
+     * |endSession| must be called to unregister the interface.
+     *
+     * @param hostIf interface used to request stream control
+     * @param codecConfig Codec configuration as negotiated with the A2DP Sink
+     *    device
+     * @return status one of the following
+     *    SUCCESS if HAL server successfully initializes the platform with the
+     *        given codec configuration
+     *    UNSUPPORTED_CODEC_CONFIGURATION if HAL server cannot initialize the
+     *        platform with the given codec configuration
+     *    FAILURE if HAL server cannot initialize the platform for any other
+     *        reason
+     */
+    startSession(IBluetoothAudioHost hostIf, CodecConfiguration codecConfig) generates (Status status);
+
+    /**
+     * Updates status for start stream request. The HAL client may need
+     * to communicate to Bluetooth Controller and remote Sink device, in which
+     * case it must update with PENDING status. Once the operation is
+     * completed, it must return with either SUCCESS or FAILURE.
+     *
+     * @param status SUCCESS, FAILURE or PENDING
+     */
+    oneway streamStarted(Status status);
+
+    /**
+     * Updates status for suspend stream request. The HAL client may need
+     * to communicate to Bluetooth Controller and remote device, in which case
+     * it must update with PENDING status. Once the operation is completed, it
+     * must return with either SUCCESS or FAILURE.
+     *
+     * @param status SUCCESS, FAILURE or PENDING
+     */
+    oneway streamSuspended(Status status);
+
+    /**
+     * Ends the current A2DP offload session and unregisters the
+     * BluetoothAudioHost interface.
+     */
+    oneway endSession();
+};
diff --git a/bluetooth/a2dp/1.0/default/Android.bp b/bluetooth/a2dp/1.0/default/Android.bp
new file mode 100644
index 0000000..8e6f32d
--- /dev/null
+++ b/bluetooth/a2dp/1.0/default/Android.bp
@@ -0,0 +1,14 @@
+cc_library_shared {
+    name: "android.hardware.bluetooth.a2dp@1.0-impl",
+    relative_install_path: "hw",
+    vendor: true,
+    srcs: [
+        "BluetoothAudioOffload.cpp",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.hardware.bluetooth.a2dp@1.0",
+    ],
+}
diff --git a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp
new file mode 100644
index 0000000..2a66abe
--- /dev/null
+++ b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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 "BluetoothAudioOffload.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace a2dp {
+namespace V1_0 {
+namespace implementation {
+
+IBluetoothAudioOffload* HIDL_FETCH_IBluetoothAudioOffload(const char* /* name */) {
+    return new BluetoothAudioOffload();
+}
+
+// Methods from ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload follow.
+Return<::android::hardware::bluetooth::a2dp::V1_0::Status> BluetoothAudioOffload::startSession(
+    const sp<::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost>& hostIf __unused,
+    const ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration& codecConfig __unused) {
+    /**
+     * Initialize the audio platform if codecConfiguration is supported.
+     * Save the the IBluetoothAudioHost interface, so that it can be used
+     * later to send stream control commands to the HAL client, based on
+     * interaction with Audio framework.
+     */
+    return ::android::hardware::bluetooth::a2dp::V1_0::Status::FAILURE;
+}
+
+Return<void> BluetoothAudioOffload::streamStarted(
+    ::android::hardware::bluetooth::a2dp::V1_0::Status status __unused) {
+    /**
+     * Streaming on control path has started,
+     * HAL server should start the streaming on data path.
+     */
+    return Void();
+}
+
+Return<void> BluetoothAudioOffload::streamSuspended(
+    ::android::hardware::bluetooth::a2dp::V1_0::Status status __unused) {
+    /**
+     * Streaming on control path has suspend,
+     * HAL server should suspend the streaming on data path.
+     */
+    return Void();
+}
+
+Return<void> BluetoothAudioOffload::endSession() {
+    /**
+     * Cleanup the audio platform as remote A2DP Sink device is no
+     * longer active
+     */
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace a2dp
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h
new file mode 100644
index 0000000..5d07b5b
--- /dev/null
+++ b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h
@@ -0,0 +1,60 @@
+/*
+ * 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_BLUETOOTH_A2DP_V1_0_BLUETOOTHAUDIOOFFLOAD_H
+#define ANDROID_HARDWARE_BLUETOOTH_A2DP_V1_0_BLUETOOTHAUDIOOFFLOAD_H
+
+#include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioOffload.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace a2dp {
+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 BluetoothAudioOffload : public IBluetoothAudioOffload {
+    BluetoothAudioOffload() {}
+    // Methods from ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload follow.
+    Return<::android::hardware::bluetooth::a2dp::V1_0::Status> startSession(
+        const sp<::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost>& hostIf,
+        const ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration& codecConfig) override;
+    Return<void> streamStarted(::android::hardware::bluetooth::a2dp::V1_0::Status status) override;
+    Return<void> streamSuspended(
+        ::android::hardware::bluetooth::a2dp::V1_0::Status status) override;
+    Return<void> endSession() override;
+};
+
+extern "C" IBluetoothAudioOffload* HIDL_FETCH_IBluetoothAudioOffload(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace a2dp
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BLUETOOTH_A2DP_V1_0_BLUETOOTHAUDIOOFFLOAD_H
diff --git a/bluetooth/a2dp/1.0/types.hal b/bluetooth/a2dp/1.0/types.hal
new file mode 100644
index 0000000..6a430f0
--- /dev/null
+++ b/bluetooth/a2dp/1.0/types.hal
@@ -0,0 +1,99 @@
+/*
+ * 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.bluetooth.a2dp@1.0;
+
+enum Status : uint8_t {
+    SUCCESS,
+    FAILURE,
+    /** codec configuration not supported by the audio platform */
+    UNSUPPORTED_CODEC_CONFIGURATION ,
+    /** operation is pending */
+    PENDING,
+};
+
+enum CodecType : uint32_t {
+    UNKNOWN = 0x00,
+    SBC = 0x01,
+    AAC = 0x02,
+    APTX = 0x04,
+    APTX_HD = 0x08,
+    LDAC = 0x10,
+};
+enum SampleRate : uint32_t {
+    RATE_UNKNOWN = 0x00,
+    RATE_44100 = 0x01,
+    RATE_48000 = 0x02,
+    RATE_88200 = 0x04,
+    RATE_96000 = 0x08,
+    RATE_176400 = 0x10,
+    RATE_192000 = 0x20,
+};
+enum BitsPerSample : uint8_t {
+    BITS_UNKNOWN = 0x00,
+    BITS_16 = 0x01,
+    BITS_24 = 0x02,
+    BITS_32 = 0x04,
+};
+enum ChannelMode : uint8_t {
+    UNKNOWN = 0x00,
+    MONO = 0x01,
+    STEREO = 0x02,
+};
+struct CodecConfiguration {
+    /** Bluetooth A2DP codec */
+    CodecType codecType;
+    /** Sampling rate for encoder */
+    SampleRate sampleRate;
+    /** Bits per sample for encoder */
+    BitsPerSample bitsPerSample;
+    /** Channel mode for encoder */
+    ChannelMode channelMode;
+    /**
+     * The encoded audio bitrate in bits / second.
+     * 0x00000000 - The audio bitrate is not specified / unused
+     * 0x00000001 - 0x00FFFFFF - Encoded audio bitrate in bits/second
+     * 0x01000000 - 0xFFFFFFFF - Reserved
+     */
+    uint32_t encodedAudioBitrate;
+    /** Peer MTU (in octets) */
+    uint16_t peerMtu;
+    union CodecSpecific {
+        /**
+         * SBC Codec specific information
+         * Refer to SBC Codec specific information elements in A2DP v1.3
+         * Profile Specification.
+         */
+        struct SbcData {
+            /** Block length: 4 bits | Subbands: 2 bits | Allocation Method: 2 bits */
+            uint8_t codecParameters;
+            /** Minimum bitpool value */
+            uint8_t minBitpool;
+            /** Maximum bitpool value */
+            uint8_t maxBitpool;
+        } sbcData;
+        struct LdacData {
+            /**
+             * LDAC bitrate index value:
+             * 0x00 - High
+             * 0x01 - Mid
+             * 0x02 - Low
+             * 0x7F - ABR (Adaptive Bit Rate)
+             */
+            uint8_t bitrateIndex;
+        } ldacData;
+    } codecSpecific;
+};
diff --git a/broadcastradio/1.1/default/BroadcastRadio.cpp b/broadcastradio/1.1/default/BroadcastRadio.cpp
index 2933aa7..e01812e 100644
--- a/broadcastradio/1.1/default/BroadcastRadio.cpp
+++ b/broadcastradio/1.1/default/BroadcastRadio.cpp
@@ -122,28 +122,7 @@
         {"com.google.dummy", "dummy"},
     });
 
-    prop10.bands.resize(mConfig.amFmBands.size());
-    for (size_t i = 0; i < mConfig.amFmBands.size(); i++) {
-        auto& src = mConfig.amFmBands[i];
-        auto& dst = prop10.bands[i];
-
-        dst.type = src.type;
-        dst.antennaConnected = true;
-        dst.lowerLimit = src.lowerLimit;
-        dst.upperLimit = src.upperLimit;
-        dst.spacings = src.spacings;
-
-        if (utils::isAm(src.type)) {
-            dst.ext.am.stereo = true;
-        } else if (utils::isFm(src.type)) {
-            dst.ext.fm.deemphasis = static_cast<Deemphasis>(Deemphasis::D50 | Deemphasis::D75);
-            dst.ext.fm.stereo = true;
-            dst.ext.fm.rds = static_cast<Rds>(Rds::WORLD | Rds::US);
-            dst.ext.fm.ta = true;
-            dst.ext.fm.af = true;
-            dst.ext.fm.ea = true;
-        }
-    }
+    prop10.bands = getAmFmBands();
 
     _hidl_cb(prop11);
     return Void();
@@ -162,7 +141,7 @@
         mTuner = nullptr;
     }
 
-    sp<Tuner> newTuner = new Tuner(mClassId, callback);
+    sp<Tuner> newTuner = new Tuner(this, mClassId, callback);
     mTuner = newTuner;
     if (mClassId == Class::AM_FM) {
         auto ret = newTuner->setConfiguration(config);
@@ -189,6 +168,33 @@
     return Void();
 }
 
+std::vector<V1_0::BandConfig> BroadcastRadio::getAmFmBands() const {
+    std::vector<V1_0::BandConfig> out;
+    for (auto&& src : mConfig.amFmBands) {
+        V1_0::BandConfig dst;
+
+        dst.type = src.type;
+        dst.antennaConnected = true;
+        dst.lowerLimit = src.lowerLimit;
+        dst.upperLimit = src.upperLimit;
+        dst.spacings = src.spacings;
+
+        if (utils::isAm(src.type)) {
+            dst.ext.am.stereo = true;
+        } else if (utils::isFm(src.type)) {
+            dst.ext.fm.deemphasis = static_cast<Deemphasis>(Deemphasis::D50 | Deemphasis::D75);
+            dst.ext.fm.stereo = true;
+            dst.ext.fm.rds = static_cast<Rds>(Rds::WORLD | Rds::US);
+            dst.ext.fm.ta = true;
+            dst.ext.fm.af = true;
+            dst.ext.fm.ea = true;
+        }
+
+        out.push_back(dst);
+    }
+    return out;
+}
+
 }  // namespace implementation
 }  // namespace V1_1
 }  // namespace broadcastradio
diff --git a/broadcastradio/1.1/default/BroadcastRadio.h b/broadcastradio/1.1/default/BroadcastRadio.h
index bdf3b87..d0a73d9 100644
--- a/broadcastradio/1.1/default/BroadcastRadio.h
+++ b/broadcastradio/1.1/default/BroadcastRadio.h
@@ -65,6 +65,8 @@
                            openTuner_cb _hidl_cb) override;
     Return<void> getImage(int32_t id, getImage_cb _hidl_cb);
 
+    std::vector<V1_0::BandConfig> getAmFmBands() const;
+
    private:
     std::mutex mMut;
     V1_0::Class mClassId;
diff --git a/broadcastradio/1.1/default/Tuner.cpp b/broadcastradio/1.1/default/Tuner.cpp
index 2be070d..4b49b59 100644
--- a/broadcastradio/1.1/default/Tuner.cpp
+++ b/broadcastradio/1.1/default/Tuner.cpp
@@ -58,8 +58,10 @@
     milliseconds tune = 150ms;
 } gDefaultDelay;
 
-Tuner::Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback)
-    : mClassId(classId),
+Tuner::Tuner(const sp<BroadcastRadio> module, V1_0::Class classId,
+             const sp<V1_0::ITunerCallback>& callback)
+    : mModule(module),
+      mClassId(classId),
       mCallback(callback),
       mCallback1_1(V1_1::ITunerCallback::castFrom(callback).withDefault(nullptr)),
       mVirtualRadio(getRadio(classId)),
@@ -71,6 +73,34 @@
     mThread.cancelAll();
 }
 
+void Tuner::setConfigurationInternalLocked(const BandConfig& config) {
+    mAmfmConfig = config;
+    mAmfmConfig.antennaConnected = true;
+    mCurrentProgram = utils::make_selector(mAmfmConfig.type, mAmfmConfig.lowerLimit);
+
+    if (utils::isFm(mAmfmConfig.type)) {
+        mVirtualRadio = std::ref(getFmRadio());
+    } else {
+        mVirtualRadio = std::ref(getAmRadio());
+    }
+
+    mIsAmfmConfigSet = true;
+    mCallback->configChange(Result::OK, mAmfmConfig);
+    if (mCallback1_1 != nullptr) mCallback1_1->programListChanged();
+}
+
+bool Tuner::autoConfigureLocked(uint64_t frequency) {
+    for (auto&& config : mModule->getAmFmBands()) {
+        // The check here is rather poor, but it's enough for default implementation.
+        if (config.lowerLimit <= frequency && config.upperLimit >= frequency) {
+            ALOGI("Auto-switching band to %s", toString(config).c_str());
+            setConfigurationInternalLocked(config);
+            return true;
+        }
+    }
+    return false;
+}
+
 Return<Result> Tuner::setConfiguration(const BandConfig& config) {
     ALOGV("%s", __func__);
     lock_guard<mutex> lk(mMut);
@@ -85,19 +115,7 @@
     auto task = [this, config]() {
         ALOGI("Setting AM/FM config");
         lock_guard<mutex> lk(mMut);
-
-        mAmfmConfig = move(config);
-        mAmfmConfig.antennaConnected = true;
-        mCurrentProgram = utils::make_selector(mAmfmConfig.type, mAmfmConfig.lowerLimit);
-
-        if (utils::isFm(mAmfmConfig.type)) {
-            mVirtualRadio = std::ref(getFmRadio());
-        } else {
-            mVirtualRadio = std::ref(getAmRadio());
-        }
-
-        mIsAmfmConfigSet = true;
-        mCallback->configChange(Result::OK, mAmfmConfig);
+        setConfigurationInternalLocked(config);
     };
     mThread.schedule(task, gDefaultDelay.config);
 
@@ -276,7 +294,7 @@
 
         auto freq = utils::getId(sel, IdentifierType::AMFM_FREQUENCY);
         if (freq < mAmfmConfig.lowerLimit || freq > mAmfmConfig.upperLimit) {
-            return Result::INVALID_ARGUMENTS;
+            if (!autoConfigureLocked(freq)) return Result::INVALID_ARGUMENTS;
         }
     } else if (programType == ProgramType::DAB) {
         if (!utils::hasId(sel, IdentifierType::DAB_SIDECC)) return Result::INVALID_ARGUMENTS;
diff --git a/broadcastradio/1.1/default/Tuner.h b/broadcastradio/1.1/default/Tuner.h
index 764d5b3..e2668d8 100644
--- a/broadcastradio/1.1/default/Tuner.h
+++ b/broadcastradio/1.1/default/Tuner.h
@@ -28,8 +28,11 @@
 namespace V1_1 {
 namespace implementation {
 
+struct BroadcastRadio;
+
 struct Tuner : public ITuner {
-    Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback);
+    Tuner(const sp<BroadcastRadio> module, V1_0::Class classId,
+          const sp<V1_0::ITunerCallback>& callback);
 
     void forceClose();
 
@@ -55,6 +58,7 @@
     WorkerThread mThread;
     bool mIsClosed = false;
 
+    const sp<BroadcastRadio> mModule;
     V1_0::Class mClassId;
     const sp<V1_0::ITunerCallback> mCallback;
     const sp<V1_1::ITunerCallback> mCallback1_1;
@@ -68,7 +72,9 @@
     std::atomic<bool> mIsAnalogForced;
 
     utils::HalRevision getHalRev() const;
+    void setConfigurationInternalLocked(const V1_0::BandConfig& config);
     void tuneInternalLocked(const V1_1::ProgramSelector& sel);
+    bool autoConfigureLocked(uint64_t frequency);
 };
 
 }  // namespace implementation
diff --git a/broadcastradio/2.0/ITunerCallback.hal b/broadcastradio/2.0/ITunerCallback.hal
index ede8350..b20a0b2 100644
--- a/broadcastradio/2.0/ITunerCallback.hal
+++ b/broadcastradio/2.0/ITunerCallback.hal
@@ -17,12 +17,14 @@
 
 interface ITunerCallback {
     /**
-     * Method called by the HAL when a tuning operation fails
+     * Method called by the HAL when a tuning operation fails asynchronously
      * following a step(), scan() or tune() command.
      *
-     * @param result OK if tune succeeded;
-     *               TIMEOUT in case of time out.
-     * @param selector A ProgramSelector structure passed from tune(),
+     * This callback is only called when the step(), scan() or tune() command
+     * returned OK at first.
+     *
+     * @param result TIMEOUT in case of time out.
+     * @param selector A ProgramSelector structure passed from tune() call;
      *                 empty for step() and scan().
      */
     oneway onTuneFailed(Result result, ProgramSelector selector);
diff --git a/broadcastradio/2.0/types.hal b/broadcastradio/2.0/types.hal
index a9b9600..1ce61df 100644
--- a/broadcastradio/2.0/types.hal
+++ b/broadcastradio/2.0/types.hal
@@ -351,10 +351,16 @@
      * related content (i.e. DAB soft-links). This field is a list of pointers
      * to other programs on the program list.
      *
-     * Please note, that these identifiers does not have to exist on the program
+     * This is not a list of programs that carry the same content (i.e.
+     * DAB hard-links, RDS AF). Switching to programs from this list usually
+     * require user action.
+     *
+     * Please note, that these identifiers do not have to exist on the program
      * list - i.e. DAB tuner may provide information on FM RDS alternatives
      * despite not supporting FM RDS. If the system has multiple tuners, another
      * one may have it on its list.
+     *
+     * This field is optional (can be empty).
      */
     vec<ProgramIdentifier> relatedContent;
 
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 975fb01..5f89cde 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -1198,7 +1198,7 @@
     return Void();
 }
 
-void CameraDeviceSession::constructCaptureResult(CaptureResult& result,
+status_t CameraDeviceSession::constructCaptureResult(CaptureResult& result,
                                                  const camera3_capture_result *hal_result) {
     uint32_t frameNumber = hal_result->frame_number;
     bool hasInputBuf = (hal_result->input_buffer != nullptr);
@@ -1213,7 +1213,7 @@
             if (mInflightBuffers.count(key) != 1) {
                 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
                         __FUNCTION__, streamId, frameNumber);
-                return;
+                return -EINVAL;
             }
         }
 
@@ -1224,7 +1224,7 @@
             if (mInflightBuffers.count(key) != 1) {
                 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
                         __FUNCTION__, streamId, frameNumber);
-                return;
+                return -EINVAL;
             }
         }
     }
@@ -1344,7 +1344,7 @@
             ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
         }
     }
-
+    return OK;
 }
 
 /**
@@ -1356,10 +1356,11 @@
     CameraDeviceSession *d =
             const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
 
-    CaptureResult result;
-    d->constructCaptureResult(result, hal_result);
-
-    d->mResultBatcher.processCaptureResult(result);
+    CaptureResult result = {};
+    status_t ret = d->constructCaptureResult(result, hal_result);
+    if (ret == OK) {
+        d->mResultBatcher.processCaptureResult(result);
+    }
 }
 
 void CameraDeviceSession::sNotify(
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index 61db671..269cc06 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -327,7 +327,7 @@
     static callbacks_process_capture_result_t sProcessCaptureResult;
     static callbacks_notify_t sNotify;
 
-    void constructCaptureResult(CaptureResult& result,
+    status_t constructCaptureResult(CaptureResult& result,
                                 const camera3_capture_result *hal_result);
 private:
 
diff --git a/camera/device/3.4/Android.bp b/camera/device/3.4/Android.bp
index 87acd25..2c649ba 100644
--- a/camera/device/3.4/Android.bp
+++ b/camera/device/3.4/Android.bp
@@ -25,7 +25,6 @@
         "HalStreamConfiguration",
         "PhysicalCameraMetadata",
         "PhysicalCameraSetting",
-        "RequestTemplate",
         "Stream",
         "StreamConfiguration",
     ],
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index b032357..550d65a 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -51,6 +51,32 @@
             }
         }
     }
+
+    camera_metadata_entry_t capabilities =
+            mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+    bool isLogicalMultiCamera = false;
+    for (size_t i = 0; i < capabilities.count; i++) {
+        if (capabilities.data.u8[i] ==
+                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+            isLogicalMultiCamera = true;
+            break;
+        }
+    }
+    if (isLogicalMultiCamera) {
+        camera_metadata_entry entry =
+                mDeviceInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
+        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) {
+                    const char* physicalId = reinterpret_cast<const char*>(ids+start);
+                    mPhysicalCameraIds.emplace(physicalId);
+                }
+                start = i + 1;
+            }
+        }
+    }
 }
 
 CameraDeviceSession::~CameraDeviceSession() {
@@ -450,11 +476,25 @@
     CameraDeviceSession *d =
             const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
 
-    CaptureResult result;
-    d->constructCaptureResult(result.v3_2, hal_result);
+    CaptureResult result = {};
+    status_t ret = d->constructCaptureResult(result.v3_2, hal_result);
+    if (ret != OK) {
+        return;
+    }
+
+    if (hal_result->num_physcam_metadata > d->mPhysicalCameraIds.size()) {
+        ALOGE("%s: Fatal: Invalid num_physcam_metadata %u", __FUNCTION__,
+                hal_result->num_physcam_metadata);
+        return;
+    }
     result.physicalCameraMetadata.resize(hal_result->num_physcam_metadata);
     for (uint32_t i = 0; i < hal_result->num_physcam_metadata; i++) {
         std::string physicalId = hal_result->physcam_ids[i];
+        if (d->mPhysicalCameraIds.find(physicalId) == d->mPhysicalCameraIds.end()) {
+            ALOGE("%s: Fatal: Invalid physcam_ids[%u]: %s", __FUNCTION__,
+                  i, hal_result->physcam_ids[i]);
+            return;
+        }
         V3_2::CameraMetadata physicalMetadata;
         V3_2::implementation::convertToHidl(hal_result->physcam_metadata[i], &physicalMetadata);
         PhysicalCameraMetadata physicalCameraMetadata = {
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 0ede889..bb11d7c 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -2180,6 +2180,13 @@
     }
     uint32_t bufferSize = fmt.fmt.pix.sizeimage;
     ALOGI("%s: V4L2 buffer size is %d", __FUNCTION__, bufferSize);
+    uint32_t expectedMaxBufferSize = kMaxBytesPerPixel * fmt.fmt.pix.width * fmt.fmt.pix.height;
+    if ((bufferSize == 0) || (bufferSize > expectedMaxBufferSize)) {
+        ALOGE("%s: V4L2 buffer size: %u looks invalid. Expected maximum size: %u", __FUNCTION__,
+                bufferSize, expectedMaxBufferSize);
+        return -EINVAL;
+    }
+    mMaxV4L2BufferSize = bufferSize;
 
     const double kDefaultFps = 30.0;
     double fps = 1000.0;
@@ -2329,6 +2336,12 @@
         // TODO: try to dequeue again
     }
 
+    if (buffer.bytesused > mMaxV4L2BufferSize) {
+        ALOGE("%s: v4l2 buffer bytes used: %u maximum %u", __FUNCTION__, buffer.bytesused,
+                mMaxV4L2BufferSize);
+        return ret;
+    }
+
     if (buffer.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
         // Ideally we should also check for V4L2_BUF_FLAG_TSTAMP_SRC_SOE, but
         // even V4L2_BUF_FLAG_TSTAMP_SRC_EOF is better than capture a timestamp now
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 6e90ed4..5d6a112 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
@@ -27,6 +27,7 @@
 #include <hidl/Status.h>
 #include <deque>
 #include <map>
+#include <unordered_set>
 #include <unordered_map>
 #include "CameraMetadata.h"
 #include "HandleImporter.h"
@@ -110,6 +111,10 @@
 
     // Whether this camera device session is created with version 3.4 callback.
     bool mHasCallback_3_4;
+
+    // Physical camera ids for the logical multi-camera. Empty if this
+    // is not a logical multi-camera.
+    std::unordered_set<std::string> mPhysicalCameraIds;
 private:
 
     struct TrampolineSessionInterface_3_4 : public ICameraDeviceSession {
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
index 9843a50..14e5c9a 100644
--- 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
@@ -108,6 +108,7 @@
 
     static const int kMaxProcessedStream = 2;
     static const int kMaxStallStream = 1;
+    static const uint32_t kMaxBytesPerPixel = 2;
 
 protected:
 
@@ -322,6 +323,7 @@
     std::mutex mV4l2BufferLock; // protect the buffer count and condition below
     std::condition_variable mV4L2BufferReturned;
     size_t mNumDequeuedV4l2Buffers = 0;
+    uint32_t mMaxV4L2BufferSize = 0;
 
     // Not protected by mLock (but might be used when mLock is locked)
     sp<OutputThread> mOutputThread;
diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal
index ba9eead..04edfe9 100644
--- a/camera/metadata/3.3/types.hal
+++ b/camera/metadata/3.3/types.hal
@@ -33,6 +33,8 @@
     ANDROID_LOGICAL_MULTI_CAMERA =
         android.hardware.camera.metadata@3.2::CameraMetadataSection:ANDROID_SECTION_COUNT,
 
+    ANDROID_DISTORTION_CORRECTION,
+
     ANDROID_SECTION_COUNT_3_3,
 
     VENDOR_SECTION_3_3 = 0x8000,
@@ -46,6 +48,8 @@
 enum CameraMetadataSectionStart : android.hardware.camera.metadata@3.2::CameraMetadataSectionStart {
     ANDROID_LOGICAL_MULTI_CAMERA_START = CameraMetadataSection:ANDROID_LOGICAL_MULTI_CAMERA << 16,
 
+    ANDROID_DISTORTION_CORRECTION_START = CameraMetadataSection:ANDROID_DISTORTION_CORRECTION << 16,
+
     VENDOR_SECTION_START_3_3 = CameraMetadataSection:VENDOR_SECTION_3_3 << 16,
 
 };
@@ -74,6 +78,17 @@
      */
     ANDROID_LENS_POSE_REFERENCE = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_LENS_END,
 
+    /** android.lens.distortion [dynamic, float[], public]
+     *
+     * <p>The correction coefficients to correct for this camera device's
+     * radial and tangential lens distortion.</p>
+     * <p>Replaces the deprecated ANDROID_LENS_RADIAL_DISTORTION field, which was
+     * inconsistently defined.</p>
+     *
+     * @see ANDROID_LENS_RADIAL_DISTORTION
+     */
+    ANDROID_LENS_DISTORTION,
+
     ANDROID_LENS_END_3_3,
 
     /** android.request.availableSessionKeys [static, int32[], ndk_public]
@@ -153,6 +168,23 @@
 
     ANDROID_LOGICAL_MULTI_CAMERA_END_3_3,
 
+    /** android.distortionCorrection.mode [dynamic, enum, public]
+     *
+     * <p>Mode of operation for the lens distortion correction block.</p>
+     */
+    ANDROID_DISTORTION_CORRECTION_MODE = CameraMetadataSectionStart:ANDROID_DISTORTION_CORRECTION_START,
+
+    /** android.distortionCorrection.availableModes [static, byte[], public]
+     *
+     * <p>List of distortion correction modes for ANDROID_DISTORTION_CORRECTION_MODE that are
+     * supported by this camera device.</p>
+     *
+     * @see ANDROID_DISTORTION_CORRECTION_MODE
+     */
+    ANDROID_DISTORTION_CORRECTION_AVAILABLE_MODES,
+
+    ANDROID_DISTORTION_CORRECTION_END_3_3,
+
 };
 
 /*
@@ -198,6 +230,7 @@
         @3.2::CameraMetadataEnumAndroidRequestAvailableCapabilities {
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING,
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME,
 };
 
 /** android.statistics.oisDataMode enumeration values
@@ -223,3 +256,12 @@
     ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE,
     ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED,
 };
+
+/** android.distortionCorrection.mode enumeration values
+ * @see ANDROID_DISTORTION_CORRECTION_MODE
+ */
+enum CameraMetadataEnumAndroidDistortionCorrectionMode : uint32_t {
+    ANDROID_DISTORTION_CORRECTION_MODE_OFF,
+    ANDROID_DISTORTION_CORRECTION_MODE_FAST,
+    ANDROID_DISTORTION_CORRECTION_MODE_HIGH_QUALITY,
+};
diff --git a/camera/provider/2.4/ICameraProvider.hal b/camera/provider/2.4/ICameraProvider.hal
index abb6366..8773bc0 100644
--- a/camera/provider/2.4/ICameraProvider.hal
+++ b/camera/provider/2.4/ICameraProvider.hal
@@ -35,7 +35,8 @@
  * where
  *   - <major>/<minor> is the provider HAL HIDL version,
  *   - <type> is the type of devices this provider knows about, such as
- *     "internal", "legacy", "external", or "remote"
+ *     "internal", "legacy", "external", "remote" etc. The camera framework
+ *     must not differentiate or chage its behavior based on the specific type.
  *   - <instance> is a non-negative integer starting from 0 to disambiguate
  *     between multiple HALs of the same type.
  *
diff --git a/camera/provider/2.4/default/ExternalCameraProvider.cpp b/camera/provider/2.4/default/ExternalCameraProvider.cpp
index faa4e3a..285e96b 100644
--- a/camera/provider/2.4/default/ExternalCameraProvider.cpp
+++ b/camera/provider/2.4/default/ExternalCameraProvider.cpp
@@ -75,6 +75,9 @@
         Mutex::Autolock _l(mLock);
         mCallbacks = callback;
     }
+    if (mCallbacks == nullptr) {
+        return Status::OK;
+    }
     // Send a callback for all devices to initialize
     {
         for (const auto& pair : mCameraStatusMap) {
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index abd875a..5feec87 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "camera_hidl_hal_test"
 
+#include <algorithm>
 #include <chrono>
 #include <mutex>
 #include <regex>
@@ -65,6 +66,7 @@
 using ::android::BufferItemConsumer;
 using ::android::Surface;
 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::camera::common::V1_0::Status;
 using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
@@ -1084,7 +1086,7 @@
 }
 
 hidl_vec<hidl_string> CameraHidlTest::getCameraDeviceNames(sp<ICameraProvider> provider) {
-    hidl_vec<hidl_string> cameraDeviceNames;
+    std::vector<std::string> cameraDeviceNames;
     Return<void> ret;
     ret = provider->getCameraIdList(
         [&](auto status, const auto& idList) {
@@ -1093,12 +1095,50 @@
                 ALOGI("Camera Id[%zu] is %s", i, idList[i].c_str());
             }
             ASSERT_EQ(Status::OK, status);
-            cameraDeviceNames = idList;
+            for (const auto& id : idList) {
+                cameraDeviceNames.push_back(id);
+            }
         });
     if (!ret.isOk()) {
         ADD_FAILURE();
     }
-    return cameraDeviceNames;
+
+    // External camera devices are reported through cameraDeviceStatusChange
+    struct ProviderCb : public ICameraProviderCallback {
+        virtual Return<void> cameraDeviceStatusChange(
+                const hidl_string& devName,
+                CameraDeviceStatus newStatus) override {
+            ALOGI("camera device status callback name %s, status %d",
+                    devName.c_str(), (int) newStatus);
+            if (newStatus == CameraDeviceStatus::PRESENT) {
+                externalCameraDeviceNames.push_back(devName);
+
+            }
+            return Void();
+        }
+
+        virtual Return<void> torchModeStatusChange(
+                const hidl_string&, TorchModeStatus) override {
+            return Void();
+        }
+
+        std::vector<std::string> externalCameraDeviceNames;
+    };
+    sp<ProviderCb> cb = new ProviderCb;
+    auto status = mProvider->setCallback(cb);
+
+    for (const auto& devName : cb->externalCameraDeviceNames) {
+        if (cameraDeviceNames.end() == std::find(
+                cameraDeviceNames.begin(), cameraDeviceNames.end(), devName)) {
+            cameraDeviceNames.push_back(devName);
+        }
+    }
+
+    hidl_vec<hidl_string> retList(cameraDeviceNames.size());
+    for (size_t i = 0; i < cameraDeviceNames.size(); i++) {
+        retList[i] = cameraDeviceNames[i];
+    }
+    return retList;
 }
 
 // Test devices with first_api_level >= P does not advertise device@1.0
@@ -2010,7 +2050,8 @@
                         ASSERT_TRUE(
                                 hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED ||
                                 hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL ||
-                                hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3);
+                                hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3 ||
+                                hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL);
                     } else {
                         ADD_FAILURE() << "Get camera hardware level failed!";
                     }
@@ -2440,13 +2481,14 @@
         int32_t streamId = 0;
         for (auto& it : outputStreams) {
             V3_2::Stream stream3_2;
+            bool isJpeg = static_cast<PixelFormat>(it.format) == PixelFormat::BLOB;
             stream3_2 = {streamId,
                              StreamType::OUTPUT,
                              static_cast<uint32_t>(it.width),
                              static_cast<uint32_t>(it.height),
                              static_cast<PixelFormat>(it.format),
                              GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
-                             0,
+                             (isJpeg) ? static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF) : 0,
                              StreamRotation::ROTATION_0};
             ::android::hardware::hidl_vec<V3_2::Stream> streams3_2 = {stream3_2};
             ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
@@ -2897,7 +2939,7 @@
                                      static_cast<uint32_t>(blobIter.height),
                                      static_cast<PixelFormat>(blobIter.format),
                                      GRALLOC1_CONSUMER_USAGE_CPU_READ,
-                                     0,
+                                     static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF),
                                      StreamRotation::ROTATION_0};
                 ::android::hardware::hidl_vec<V3_2::Stream> streams = {previewStream,
                                                                  blobStream};
@@ -3162,7 +3204,7 @@
                                      static_cast<uint32_t>(blobIter.height),
                                      static_cast<PixelFormat>(blobIter.format),
                                      GRALLOC1_CONSUMER_USAGE_CPU_READ,
-                                     0,
+                                     static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF),
                                      StreamRotation::ROTATION_0};
                 ::android::hardware::hidl_vec<V3_2::Stream> streams = {videoStream, blobStream};
                 ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
@@ -3603,8 +3645,9 @@
 
         camera_metadata_entry_t hwLevel = staticMeta.find(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
         ASSERT_TRUE(0 < hwLevel.count);
-        if (ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED == hwLevel.data.u8[0]) {
-            //Limited devices can skip this test
+        if (ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED == hwLevel.data.u8[0] ||
+                ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL == hwLevel.data.u8[0]) {
+            //Limited/External devices can skip this test
             ret = session->close();
             ASSERT_TRUE(ret.isOk());
             continue;
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 71253da..948b4fe 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -21,6 +21,8 @@
 # Clear potential input variables to BUILD_FRAMEWORK_COMPATIBILITY_MATRIX
 LOCAL_ADD_VBMETA_VERSION :=
 LOCAL_ASSEMBLE_VINTF_ENV_VARS :=
+LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE :=
+LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE :=
 LOCAL_ASSEMBLE_VINTF_FLAGS :=
 LOCAL_KERNEL_VERSIONS :=
 LOCAL_GEN_FILE_DEPENDENCIES :=
@@ -29,18 +31,21 @@
 
 
 include $(CLEAR_VARS)
+LOCAL_MODULE := framework_compatibility_matrix.legacy.xml
 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 := framework_compatibility_matrix.1.xml
 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 := framework_compatibility_matrix.2.xml
 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
@@ -49,7 +54,8 @@
 # TODO(b/72409164): STOPSHIP: update kernel version requirements
 
 include $(CLEAR_VARS)
-LOCAL_MODULE_STEM := compatibility_matrix.current.xml
+LOCAL_MODULE := framework_compatibility_matrix.3.xml
+LOCAL_MODULE_STEM := compatibility_matrix.3.xml
 LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
 LOCAL_KERNEL_VERSIONS := 4.4.0 4.9.0
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
@@ -57,14 +63,47 @@
 # 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_MODULE := framework_compatibility_matrix.device.xml
+LOCAL_MODULE_STEM := compatibility_matrix.device.xml
+# define LOCAL_MODULE_CLASS for local-generated-sources-dir.
+LOCAL_MODULE_CLASS := ETC
+
+ifndef DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
+LOCAL_SRC_FILES := compatibility_matrix.empty.xml
+else
+
+# DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE specify an absolute path
+LOCAL_GENERATED_SOURCES := $(DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE)
+
+# Enforce that DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE does not specify required HALs
+# by checking it against an empty manifest. But the empty manifest needs to contain
+# BOARD_SEPOLICY_VERS to be compatible with DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE.
+my_manifest_src_file := $(LOCAL_PATH)/manifest.empty.xml
+my_gen_check_manifest := $(local-generated-sources-dir)/manifest.check.xml
+$(my_gen_check_manifest): PRIVATE_SRC_FILE := $(my_manifest_src_file)
+$(my_gen_check_manifest): $(my_manifest_src_file) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+	BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) \
+	VINTF_IGNORE_TARGET_FCM_VERSION=true \
+		$(HOST_OUT_EXECUTABLES)/assemble_vintf -i $(PRIVATE_SRC_FILE) -o $@
+
+LOCAL_GEN_FILE_DEPENDENCIES += $(my_gen_check_manifest)
+LOCAL_ASSEMBLE_VINTF_FLAGS += -c "$(my_gen_check_manifest)"
+
+my_gen_check_manifest :=
+my_manifest_src_file :=
+
+endif # DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
+
 LOCAL_ADD_VBMETA_VERSION := true
 LOCAL_ASSEMBLE_VINTF_ENV_VARS := \
     POLICYVERS \
     PLATFORM_SEPOLICY_VERSION \
     PLATFORM_SEPOLICY_COMPAT_VERSIONS
 
+LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE := PRODUCT_ENFORCE_VINTF_MANIFEST=true
+LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE := \
+    "Error: DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX cannot contain required HALs."
+
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
 
 # Framework Compatibility Matrix
@@ -77,8 +116,8 @@
     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
+    framework_compatibility_matrix.3.xml \
+    framework_compatibility_matrix.device.xml
 LOCAL_GENERATED_SOURCES := $(call module-installed-files,$(LOCAL_REQUIRED_MODULES))
 
 ifdef BUILT_VENDOR_MANIFEST
@@ -88,6 +127,14 @@
 
 LOCAL_ASSEMBLE_VINTF_ENV_VARS := PRODUCT_ENFORCE_VINTF_MANIFEST
 
+# TODO(b/65028233): Enforce no "unused HALs" for devices that does not define
+# DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE as well
+ifeq (true,$(strip $(PRODUCT_ENFORCE_VINTF_MANIFEST)))
+ifdef DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
+LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE := VINTF_ENFORCE_NO_UNUSED_HALS=true
+endif
+endif
+
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
 BUILT_SYSTEM_COMPATIBILITY_MATRIX := $(LOCAL_BUILT_MODULE)
 
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.3.xml
similarity index 80%
rename from compatibility_matrices/compatibility_matrix.current.xml
rename to compatibility_matrices/compatibility_matrix.3.xml
index 464b4a3..6aa5fc5 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.3.xml
@@ -1,7 +1,7 @@
 <compatibility-matrix version="1.0" type="framework" level="3">
     <hal format="hidl" optional="false">
         <name>android.hardware.audio</name>
-        <version>2.0</version>
+        <version>4.0</version>
         <interface>
             <name>IDevicesFactory</name>
             <instance>default</instance>
@@ -9,7 +9,7 @@
     </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.audio.effect</name>
-        <version>2.0</version>
+        <version>4.0</version>
         <interface>
             <name>IEffectsFactory</name>
             <instance>default</instance>
@@ -24,6 +24,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.audiocontrol</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAudioControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.automotive.evs</name>
         <version>1.0</version>
         <interface>
@@ -56,6 +64,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth.a2dp</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBluetoothAudioOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.boot</name>
         <version>1.0</version>
         <interface>
@@ -76,7 +92,7 @@
         <version>2.4</version>
         <interface>
             <name>ICameraProvider</name>
-            <instance>legacy/0</instance>
+            <regex-instance>[^/]+/[0-9]+</regex-instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
@@ -96,6 +112,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.confirmationui</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfirmationUI</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.contexthub</name>
         <version>1.0</version>
         <interface>
@@ -103,16 +127,28 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <hal format="hidl" optional="true">
         <name>android.hardware.drm</name>
         <version>1.0</version>
         <interface>
             <name>ICryptoFactory</name>
-            <instance>default</instance>
+            <regex-instance>.*</regex-instance>
         </interface>
         <interface>
             <name>IDrmFactory</name>
-            <instance>default</instance>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.drm</name>
+        <version>1.1</version>
+        <interface>
+            <name>ICryptoFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+        <interface>
+            <name>IDrmFactory</name>
+            <regex-instance>.*</regex-instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
@@ -133,7 +169,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.gnss</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IGnss</name>
             <instance>default</instance>
@@ -182,7 +218,14 @@
         <interface>
             <name>IKeymasterDevice</name>
             <instance>default</instance>
-	    <!-- TODO: strongbox here? -->
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.keymaster</name>
+        <version>4.0</version>
+        <interface>
+            <name>IKeymasterDevice</name>
+            <instance>strongbox</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
@@ -214,9 +257,17 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.nfc</name>
+        <name>android.hardware.neuralnetworks</name>
         <version>1.0</version>
         <interface>
+            <name>IDevice</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.nfc</name>
+        <version>1.0-1</version>
+        <interface>
             <name>INfc</name>
             <instance>default</instance>
         </interface>
@@ -239,10 +290,12 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0-1</version>
+        <version>1.0-2</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
         </interface>
         <interface>
             <name>ISap</name>
@@ -250,6 +303,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.radio.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IRadioConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.renderscript</name>
         <version>1.0</version>
         <interface>
@@ -262,7 +323,8 @@
         <version>1.0</version>
         <interface>
             <name>ISecureElement</name>
-            <instance>eSE1</instance>
+            <regex-instance>eSE[1-9][0-9]*</regex-instance>
+            <regex-instance>SIM[1-9][0-9]*</regex-instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
@@ -275,7 +337,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.soundtrigger</name>
-        <version>2.0</version>
+        <version>2.0-1</version>
         <interface>
             <name>ISoundTriggerHw</name>
             <instance>default</instance>
@@ -330,8 +392,16 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.usb.gadget</name>
+        <version>1.0</version>
+        <interface>
+            <name>IUsbGadget</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0-1</version>
+        <version>1.0-2</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
@@ -355,13 +425,21 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi</name>
-        <version>1.0-1</version>
+        <version>1.0-2</version>
         <interface>
             <name>IWifi</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.hostapd</name>
+        <version>1.0</version>
+        <interface>
+            <name>IHostapd</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.wifi.offload</name>
         <version>1.0</version>
         <interface>
@@ -371,7 +449,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>ISupplicant</name>
             <instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.mk b/compatibility_matrices/compatibility_matrix.mk
index 96815b8..6dc2b4f 100644
--- a/compatibility_matrices/compatibility_matrix.mk
+++ b/compatibility_matrices/compatibility_matrix.mk
@@ -25,12 +25,38 @@
 
 # $(warning $(call remove-minor-revision,3.18.0))
 
-ifndef LOCAL_MODULE_STEM
-$(error LOCAL_MODULE_STEM must be defined.)
+##### Input Variables:
+# LOCAL_MODULE: required. Module name for the build system.
+# LOCAL_MODULE_CLASS: optional. Default is ETC.
+# LOCAL_MODULE_PATH: optional. Path of output file. Default is $(TARGET_OUT)/etc/vintf.
+# LOCAL_MODULE_STEM: optional. Name of output file. Default is $(LOCAL_MODULE).
+# LOCAL_SRC_FILES: required. Local source files provided to assemble_vintf
+#       (command line argument -i).
+# LOCAL_GENERATED_SOURCES: optional. Global source files provided to assemble_vintf
+#       (command line argument -i).
+#
+# LOCAL_ADD_VBMETA_VERSION: Use AVBTOOL to add avb version to the output matrix
+#       (corresponds to <avb><vbmeta-version> tag)
+# LOCAL_ASSEMBLE_VINTF_ENV_VARS: Add a list of environment variable names from global variables in
+#       the build system that is lazily evaluated (e.g. PRODUCT_ENFORCE_VINTF_MANIFEST).
+# LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE: Add a list of environment variables that is local to
+#       assemble_vintf invocation. Format is "VINTF_ENFORCE_NO_UNUSED_HALS=true".
+# LOCAL_ASSEMBLE_VINTF_FLAGS: Add additional command line arguments to assemble_vintf invocation.
+# LOCAL_KERNEL_VERSIONS: Parse kernel configurations and add to the output matrix
+#       (corresponds to <kernel> tags.)
+# LOCAL_GEN_FILE_DEPENDENCIES: A list of additional dependencies for the generated file.
+
+ifndef LOCAL_MODULE
+$(error LOCAL_MODULE must be defined.)
 endif
 
-LOCAL_MODULE := framework_$(LOCAL_MODULE_STEM)
+ifndef LOCAL_MODULE_STEM
+LOCAL_MODULE_STEM := $(LOCAL_MODULE)
+endif
+
+ifndef LOCAL_MODULE_CLASS
 LOCAL_MODULE_CLASS := ETC
+endif
 
 ifndef LOCAL_MODULE_PATH
 LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf
@@ -76,13 +102,23 @@
 	$(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES)) \
 	$(LOCAL_GENERATED_SOURCES)
 
+$(GEN): PRIVATE_ADDITIONAL_ENV_VARS := $(LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE)
+
+ifneq (,$(strip $(LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE)))
+$(GEN): PRIVATE_COMMAND_TAIL := || (echo $(strip $(LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE)) && false)
+endif
+
 $(GEN): PRIVATE_SRC_FILES := $(my_matrix_src_files)
 $(GEN): $(my_matrix_src_files) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+	$(foreach varname,$(PRIVATE_ENV_VARS),\
+		$(if $(findstring $(varname),$(PRIVATE_ADDITIONAL_ENV_VARS)),\
+			$(error $(varname) should not be overridden by LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE.)))
 	$(foreach varname,$(PRIVATE_ENV_VARS),$(varname)="$($(varname))") \
+		$(PRIVATE_ADDITIONAL_ENV_VARS) \
 		$(HOST_OUT_EXECUTABLES)/assemble_vintf \
 		-i $(call normalize-path-list,$(PRIVATE_SRC_FILES)) \
 		-o $@ \
-		$(PRIVATE_FLAGS)
+		$(PRIVATE_FLAGS) $(PRIVATE_COMMAND_TAIL)
 
 LOCAL_PREBUILT_MODULE_FILE := $(GEN)
 LOCAL_SRC_FILES :=
@@ -90,6 +126,8 @@
 
 LOCAL_ADD_VBMETA_VERSION :=
 LOCAL_ASSEMBLE_VINTF_ENV_VARS :=
+LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE :=
+LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE :=
 LOCAL_ASSEMBLE_VINTF_FLAGS :=
 LOCAL_KERNEL_VERSIONS :=
 LOCAL_GEN_FILE_DEPENDENCIES :=
diff --git a/compatibility_matrices/manifest.empty.xml b/compatibility_matrices/manifest.empty.xml
new file mode 100644
index 0000000..e50e0e5
--- /dev/null
+++ b/compatibility_matrices/manifest.empty.xml
@@ -0,0 +1 @@
+<manifest version="1.0" type="device" />
diff --git a/confirmationui/1.0/default/ConfirmationUI.cpp b/confirmationui/1.0/default/ConfirmationUI.cpp
index f241a76..41e03ce 100644
--- a/confirmationui/1.0/default/ConfirmationUI.cpp
+++ b/confirmationui/1.0/default/ConfirmationUI.cpp
@@ -43,7 +43,12 @@
     const hidl_vec<uint8_t>& extraData, const hidl_string& locale,
     const hidl_vec<UIOption>& uiOptions) {
     auto& operation = MyOperation::get();
-    return operation.init(resultCB, promptText, extraData, locale, uiOptions);
+    auto result = operation.init(resultCB, promptText, extraData, locale, uiOptions);
+    if (result == ResponseCode::OK) {
+        // This is where implementation start the UI and then call setPending on success.
+        operation.setPending();
+    }
+    return result;
 }
 
 Return<ResponseCode> ConfirmationUI::deliverSecureInputEvent(
diff --git a/confirmationui/1.0/default/PlatformSpecifics.h b/confirmationui/1.0/default/PlatformSpecifics.h
index 18b88c8..488da6d 100644
--- a/confirmationui/1.0/default/PlatformSpecifics.h
+++ b/confirmationui/1.0/default/PlatformSpecifics.h
@@ -52,8 +52,14 @@
         const uint8_t key[32], std::initializer_list<support::ByteBufferProxy> buffers);
 };
 
-using MyOperation = generic::Operation<sp<IConfirmationResultCallback>, MonotonicClockTimeStamper,
-                                       HMacImplementation>;
+class MyOperation : public generic::Operation<sp<IConfirmationResultCallback>,
+                                              MonotonicClockTimeStamper, HMacImplementation> {
+   public:
+    static MyOperation& get() {
+        static MyOperation op;
+        return op;
+    }
+};
 
 }  // namespace implementation
 }  // namespace V1_0
diff --git a/confirmationui/1.0/default/android.hardware.confirmationui@1.0-service.rc b/confirmationui/1.0/default/android.hardware.confirmationui@1.0-service.rc
index a278028..c04e55e 100644
--- a/confirmationui/1.0/default/android.hardware.confirmationui@1.0-service.rc
+++ b/confirmationui/1.0/default/android.hardware.confirmationui@1.0-service.rc
@@ -1,4 +1,4 @@
 service vendor.confirmationui-1-0 /vendor/bin/hw/android.hardware.confirmationui@1.0-service
     class hal
-    user system
-    group system drmrpc
+    user nobody
+    group drmrpc
diff --git a/confirmationui/support/include/android/hardware/confirmationui/1.0/generic/GenericOperation.h b/confirmationui/support/include/android/hardware/confirmationui/1.0/generic/GenericOperation.h
index a88cd40..b480942 100644
--- a/confirmationui/support/include/android/hardware/confirmationui/1.0/generic/GenericOperation.h
+++ b/confirmationui/support/include/android/hardware/confirmationui/1.0/generic/GenericOperation.h
@@ -55,10 +55,27 @@
         (void)uiOptions;
         resultCB_ = resultCB;
         if (error_ != ResponseCode::Ignored) return ResponseCode::OperationPending;
-        // TODO make copy of promptText before using it may reside in shared buffer
-        auto state = write(
-            WriteState(formattedMessageBuffer_),
-            map(pair(text("prompt"), text(promptText)), pair(text("extra"), bytes(extraData))));
+
+        // We need to access the prompt text multiple times. Once for formatting the CBOR message
+        // and again for rendering the dialog. It is vital that the prompt does not change
+        // in the meantime. As of this point the prompt text is in a shared buffer and therefore
+        // susceptible to TOCTOU attacks. Note that promptText.size() resides on the stack and
+        // is safe to access multiple times. So now we copy the prompt string into the
+        // scratchpad promptStringBuffer_ from where we can format the CBOR message and then
+        // pass it to the renderer.
+        if (promptText.size() >= uint32_t(MessageSize::MAX))
+            return ResponseCode::UIErrorMessageTooLong;
+        auto pos = std::copy(promptText.c_str(), promptText.c_str() + promptText.size(),
+                             promptStringBuffer_);
+        *pos = 0;  // null-terminate the prompt for the renderer.
+
+        // Note the extra data is accessed only once for formating the CBOR message. So it is safe
+        // to read it from the shared buffer directly. Anyway we don't trust or interpret the
+        // extra data in any way so all we do is take a snapshot and we don't care if it is
+        // modified concurrently.
+        auto state = write(WriteState(formattedMessageBuffer_),
+                           map(pair(text("prompt"), text(promptStringBuffer_, promptText.size())),
+                               pair(text("extra"), bytes(extraData))));
         switch (state.error_) {
             case Error::OK:
                 break;
@@ -71,20 +88,20 @@
                 return ResponseCode::Unexpected;
         }
         formattedMessageLength_ = state.data_ - formattedMessageBuffer_;
-        // setup TUI and diagnose more UI errors here.
+
         // on success record the start time
         startTime_ = TimeStamper::now();
         if (!startTime_.isOk()) {
             return ResponseCode::SystemError;
         }
-        error_ = ResponseCode::OK;
         return ResponseCode::OK;
     }
 
+    void setPending() { error_ = ResponseCode::OK; }
+
     void setHmacKey(const uint8_t (&key)[32]) { hmacKey_ = {key}; }
 
     void abort() {
-        // tear down TUI here
         if (isPending()) {
             resultCB_->result(ResponseCode::Aborted, {}, {});
             error_ = ResponseCode::Ignored;
@@ -92,7 +109,6 @@
     }
 
     void userCancel() {
-        // tear down TUI here
         if (isPending()) error_ = ResponseCode::Canceled;
     }
 
@@ -104,10 +120,10 @@
     }
 
     bool isPending() const { return error_ != ResponseCode::Ignored; }
-
-    static Operation& get() {
-        static Operation operation;
-        return operation;
+    const hidl_string getPrompt() const {
+        hidl_string s;
+        s.setToExternal(promptStringBuffer_, strlen(promptStringBuffer_));
+        return s;
     }
 
     ResponseCode deliverSecureInputEvent(const HardwareAuthToken& secureInputToken) {
@@ -156,7 +172,6 @@
         return result;
     }
     hidl_vec<uint8_t> userConfirm(const uint8_t key[32]) {
-        // tear down TUI here
         if (error_ != ResponseCode::OK) return {};
         confirmationTokenScratchpad_ = HMacer::hmac256(key, "confirmation token", getMessage());
         if (!confirmationTokenScratchpad_.isOk()) {
@@ -169,9 +184,10 @@
         return result;
     }
 
-    ResponseCode error_;
+    ResponseCode error_ = ResponseCode::Ignored;
     uint8_t formattedMessageBuffer_[uint32_t(MessageSize::MAX)];
-    size_t formattedMessageLength_;
+    char promptStringBuffer_[uint32_t(MessageSize::MAX)];
+    size_t formattedMessageLength_ = 0;
     NullOr<array<uint8_t, 32>> confirmationTokenScratchpad_;
     Callback resultCB_;
     typename TimeStamper::TimeStamp startTime_;
diff --git a/confirmationui/support/include/android/hardware/confirmationui/support/msg_formatting.h b/confirmationui/support/include/android/hardware/confirmationui/support/msg_formatting.h
index 0d03591..6558799 100644
--- a/confirmationui/support/include/android/hardware/confirmationui/support/msg_formatting.h
+++ b/confirmationui/support/include/android/hardware/confirmationui/support/msg_formatting.h
@@ -105,6 +105,7 @@
     PromptUserConfirmation,
     DeliverSecureInputEvent,
     Abort,
+    Vendor,
 };
 
 template <Command cmd>
@@ -115,6 +116,7 @@
 DECLARE_COMMAND(PromptUserConfirmation);
 DECLARE_COMMAND(DeliverSecureInputEvent);
 DECLARE_COMMAND(Abort);
+DECLARE_COMMAND(Vendor);
 
 using PromptUserConfirmationMsg = Message<PromptUserConfirmation_t, hidl_string, hidl_vec<uint8_t>,
                                           hidl_string, hidl_vec<UIOption>>;
@@ -166,7 +168,7 @@
 }
 inline void zero(const volatile uint8_t*, const volatile uint8_t*) {}
 // This odd alignment function aligns the stream position to a 4byte and never 8byte boundary
-// It is to accommodate the 4 byte size field which is then followed by 8byte alligned data.
+// It is to accommodate the 4 byte size field which is then followed by 8byte aligned data.
 template <typename T>
 StreamState<T> unalign(StreamState<T> s) {
     uint8_t unalignment = uintptr_t(s.pos_) & 0x3;
diff --git a/current.txt b/current.txt
index 24321cc..5aa6259 100644
--- a/current.txt
+++ b/current.txt
@@ -250,11 +250,128 @@
 c8bc853546dd55584611def2a9fa1d99f657e3366c976d2f60fe6b8aa6d2cb87 android.hardware.thermal@1.1::IThermalCallback
 
 # ABI preserving changes to HALs during Android P
+eaeb3e4f3237430a7fdc206bffdf844713f5682990b2d49ea24392e15b5d343f android.hardware.broadcastradio@2.0::ITunerCallback
+2804120c1f8522ad15feb7695fe5eece527d399b406c671ea99618194118c316 android.hardware.broadcastradio@2.0::types
 cf72ff5a52bfa4d08e9e1000cf3ab5952a2d280c7f13cdad5ab7905c08050766 android.hardware.camera.metadata@3.2::types
-7b4723305354193b889a24153e1292fec62d5a5127bdfba08a5a27440f092de9 android.hardware.camera.provider@2.4::ICameraProvider
+3902efc42097cba55f0655aa389e052ea70164e99ced1a6d1ef53dafc13f7650 android.hardware.camera.provider@2.4::ICameraProvider
 6fa9804a17a8bb7923a56bd10493a5483c20007e4c9026fd04287bee7c945a8c android.hardware.gnss@1.0::IGnssCallback
 fb92e2b40f8e9d494e8fd3b4ac18499a3216342e7cff160714c3bbf3660b6e79 android.hardware.gnss@1.0::IGnssConfiguration
 251594ea9b27447bfa005ebd806e58fb0ae4aad84a69938129c9800ec0c64eda android.hardware.gnss@1.0::IGnssMeasurementCallback
 4e7169919d24fbe5573e5bcd683d0bd7abf553a4e6c34c41f9dfc1e12050db07 android.hardware.gnss@1.0::IGnssNavigationMessageCallback
+08ae9fc24f21f809e9b8501dfbc803662fcd6a8d8e1fb71d9dd7c0c4c6f5d556 android.hardware.neuralnetworks@1.0::types
 d4840db8efabdf1e4b344fc981cd36e5fe81a39aff6e199f6d06c1c8da413efd android.hardware.radio@1.0::types
 b280c4704dfcc548a9bf127b59b7c3578f460c50cce70a06b66fe0df8b27cff0 android.hardware.wifi@1.0::types
+
+# HALs released in Android P
+5860cf040a3d5d771967ecf648b00d06876a7120da985ee2b3e95d01f634dd20 android.hardware.audio@4.0::IDevice
+cf82a0249e918fdc657e189895e92d60af0491868477e82cdc30f6cab0ca2c65 android.hardware.audio@4.0::IDevicesFactory
+be3dc9baed45a0d330152eca3ca24fa419b375b20a41644c88d4fb46b72784d2 android.hardware.audio@4.0::IPrimaryDevice
+3e3acb70c4e6c7d578f511f4a44ee764ab9126f887a3bf65d523c42e40012bf6 android.hardware.audio@4.0::IStream
+d5de64e66b95f135dd42492250a309134b8227203ef3524440798c66b6f5a392 android.hardware.audio@4.0::IStreamIn
+888ac906461327fa0bd93854d5109be8c292a33afdb467164826970a8bd5b789 android.hardware.audio@4.0::IStreamOut
+15f6ae78e73344c8e7d68847ef03caec64fcd9f951bbcf59957d1712c247fcff android.hardware.audio@4.0::IStreamOutCallback
+e8abfc73b7f3c2095ea4fad83b5f42bced4315de2abcc3199376af880dac451b android.hardware.audio@4.0::types
+5d47a2ad2c136b8aba067dd45bb10d0ad390dd76340764154f580658f98f4fe6 android.hardware.audio.common@4.0::types
+b04b6b364938b80008e61fa2e318bc299622433e57c2e1f6cfba332a3f6e3f15 android.hardware.audio.effect@4.0::IAcousticEchoCancelerEffect
+1c17d4ece5c8ba3f7a646a305ee0dd109b0d51372e1bd585812e513cd40e1852 android.hardware.audio.effect@4.0::IAutomaticGainControlEffect
+34174259fe6fbb1bb14e7103e097f2f25529271a676687845b2f55d6d0d9d617 android.hardware.audio.effect@4.0::IBassBoostEffect
+7a18e9bd0163f3784448f6e24be0db75f877e2f0f9bd0d7ec427f1c34b382c0b android.hardware.audio.effect@4.0::IDownmixEffect
+bac81bffbe2661d5b6839087d2dd3a27eded66e60c6c76d35c68d54014cd5c06 android.hardware.audio.effect@4.0::IEffect
+65f0bcf9e498b26f3266ad10cf513a6c2b5906cc49f9db4bc5c7d3ba11a72e05 android.hardware.audio.effect@4.0::IEffectBufferProviderCallback
+5a746e81175489eb2371b88864c36c9bb63bc64ef799fae74cd96003b013c0d1 android.hardware.audio.effect@4.0::IEffectsFactory
+839980c7c5be79da6b95fdb9354a62b04407b4b084749b7a21d2c340773d7638 android.hardware.audio.effect@4.0::IEnvironmentalReverbEffect
+2805fbdac7cff050a1c095b9276bb41ac02a3b7b354336817487eb9a4b6bb462 android.hardware.audio.effect@4.0::IEqualizerEffect
+a91b547f5922f39fe4231d97fac1c3825c1c1b0c8ef7a5136689ceed37e8bfe9 android.hardware.audio.effect@4.0::ILoudnessEnhancerEffect
+1145f5b921ddec184fda5bdc87487b46f2a89cd9f42cc882bbb3a54f4ac80466 android.hardware.audio.effect@4.0::INoiseSuppressionEffect
+3661fa0623056922fdc4235ac5a9c91a2d066ab6f1ab4297e3b240fe302ba500 android.hardware.audio.effect@4.0::IPresetReverbEffect
+e88e520f8c98a62fccd8d5316c6687808f775de145d1405a7a9a66587ee6a001 android.hardware.audio.effect@4.0::IVirtualizerEffect
+fe28829dab10d171783b79ac9cc45412739f8ff275e90228d7c6370ef189b859 android.hardware.audio.effect@4.0::IVisualizerEffect
+5d92f6fd58d40c56611bb12f03be6af9bcf2bb73dfb35b77a99bbf2c3ea5439b android.hardware.audio.effect@4.0::types
+42a06dc288f61b0690580f3d37b30b663c31d74d50bb58d0772386b550d5faab android.hardware.authsecret@1.0::IAuthSecret
+a0f93c768c353cecee6237fe479bce47404eb10b629fafe07e32a054fd67f2af android.hardware.automotive.audiocontrol@1.0::IAudioControl
+ca515ff4b63c80cf5ad7b3395c997c57d6c56157361f6c367d1c96f23cc4860a android.hardware.automotive.audiocontrol@1.0::types
+f2904a4c108ad1b93eb2fa4e43b82bd01ce1ff26156316e49d1d9fc80dfecaad android.hardware.automotive.evs@1.0::IEvsCamera
+94cba6ad04c83aa840de2ed52b74ba2126a26dd960225e61ac36703315279a80 android.hardware.automotive.evs@1.0::IEvsCameraStream
+5ea36fb043d9e3b413219de3dfd7b046b48af4fda39f167f3528652e986cb76d android.hardware.automotive.evs@1.0::IEvsDisplay
+14ef8e993a4a7c899b19bb5e39b5b0cafd28312ea2b127e35b3be8f08e23fe8e android.hardware.automotive.evs@1.0::IEvsEnumerator
+3b17c1fdfc389e0abe626c37054954b07201127d890c2bc05d47613ec1f4de4f android.hardware.automotive.evs@1.0::types
+b3caf524c46a47d67e6453a34419e1881942d059e146cda740502670e9a752c3 android.hardware.automotive.vehicle@2.0::IVehicle
+7ce8728b27600e840cacf0a832f6942819fe535f9d3797ae052d5eef5065921c android.hardware.automotive.vehicle@2.0::IVehicleCallback
+848fb32d5ca79dd527d966e67c0af5874b6d7b361246b491e315cf7dea7888ab android.hardware.automotive.vehicle@2.0::types
+32cc50cc2a7658ec613c0c2dd2accbf6a05113b749852879e818b8b7b438db19 android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioHost
+ff4be64d7992f8bec97dff37f35450e79b3430c61f85f54322ce45bef229dc3b android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload
+27f22d2e873e6201f9620cf4d8e2facb25bd0dd30a2b911e441b4600d560fa62 android.hardware.bluetooth.a2dp@1.0::types
+3d8ed67d807e9f15d0708390a416bee00920f6a22196c104cc9e443c8d217df8 android.hardware.broadcastradio@2.0::IAnnouncementListener
+44017c42e6f4d8cb30f07eb1da04540a98736a336ac28c7e0ed2e69e1589f8d1 android.hardware.broadcastradio@2.0::IBroadcastRadio
+e5f4960290b4f3089163dd43251e1a032c81e9bdb796e75a87fc7c5810c262b3 android.hardware.broadcastradio@2.0::ICloseHandle
+7357516e8f4585e211b9b6f271af6fb82d6e9cc208df01851e63118404621e6d android.hardware.broadcastradio@2.0::ITunerCallback
+eacf4e7491fc52c4db90898faddf25ec7bc72501b07ae8737434c47cb845128c android.hardware.broadcastradio@2.0::ITunerSession
+34fe4601072aa5051eb8e41d776a9f6d43f716687de3f5c0031a12e7912ff3d6 android.hardware.broadcastradio@2.0::types
+4fb0725c36ed4f77a42b42e3f18d8b5f7919cb62b90098b23143a555aa7dd96d android.hardware.camera.device@3.4::ICameraDeviceCallback
+812fa66aa10ba0cba27cfddc2fd7f0ee27a8ab65a1f15aa79fdad97d403e6a14 android.hardware.camera.device@3.4::ICameraDeviceSession
+cc288f1f78d1e643eb3d3dbc16e1401d44033d8e6856761f5156814a29986ec7 android.hardware.camera.device@3.4::types
+f9278c8beb9d42d96e26d73ecabe1dff1d7e2fb301ab7f737d93e5ffae8d3312 android.hardware.camera.metadata@3.3::types
+1a46aeae45b7a0e47f79b7207300532986f9d9cd7060779afc7a529f54d712ab android.hardware.confirmationui@1.0::IConfirmationResultCallback
+6d8347ff3cd7de471065ac3e8e68385073630cdeebe9f8fa58cb91cf44436c95 android.hardware.confirmationui@1.0::IConfirmationUI
+a3ff916784dce87a56c757ab5c86433f0cdf562280999a5f978a6e8a0f3f19e7 android.hardware.confirmationui@1.0::types
+1fbf2d7e383632216aaaa1d972a21a618f55659263d2e6f0b309e3cb323b4b63 android.hardware.drm@1.1::ICryptoFactory
+7877ff8e4c1e48b825e6e5e66d050288e5656ed535c61cc7830a92ed4a9e1990 android.hardware.drm@1.1::IDrmFactory
+fef2f0ebde7704548fb203df46673ceb342272fc4fa9d0af25a980d2584a36e7 android.hardware.drm@1.1::IDrmPlugin
+5047a346ecce239404b9020959f60dd467318e9c17b290a6386bc3894df62c3c android.hardware.drm@1.1::types
+a830336ac8627d6432cfafb1b884343ad9f885dee0a5323e380e6d3c519156b8 android.hardware.gnss@1.1::IGnss
+8ad55bc35bb3a83e65c018bdfde7ae5ebc749ff2bf6b79412ded0bc6c89b97d8 android.hardware.gnss@1.1::IGnssCallback
+3c5183d7506010be57e0f748e3640fc2ded1ba955784b6256ba427f4c399591c android.hardware.gnss@1.1::IGnssConfiguration
+1a07d1383e847c3deb696ec7a2c9e33b9683772945660448a010b18063da67a4 android.hardware.gnss@1.1::IGnssMeasurement
+83e7a10ff3702147bd7ffa04567b20d407a3b16bbb7705644af44d919afe9103 android.hardware.gnss@1.1::IGnssMeasurementCallback
+0b96e0254e2168cfecb30c1ed5fb42681652cc00faa68c6e07568fafe64d1d50 android.hardware.graphics.common@1.1::types
+d9b40a5b09962a5a0780b10fe33a4e607e69e2e088fc83de88a584115b7cb1c0 android.hardware.graphics.composer@2.2::IComposer
+c3cd2a3e245ffefae859c9a3d31382a9421be95cfa6bc1231571eb3533049b54 android.hardware.graphics.composer@2.2::IComposerClient
+dd83be076b6b3f10ed62ab34d8c8b95f2415961fb785200eb842e7bfb2b0ee92 android.hardware.graphics.mapper@2.1::IMapper
+675682dd3007805c985eaaec91612abc88f4c25b3431fb84070b7584a1a741fb android.hardware.health@2.0::IHealth
+434c4c32c00b0e54bb05e40c79503208b40f786a318029a2a4f66e34f10f2a76 android.hardware.health@2.0::IHealthInfoCallback
+c9e498f1ade5e26f00d290b4763a9671ec6720f915e7d592844b62e8cb1f9b5c android.hardware.health@2.0::types
+a6cf986593c6ad15fe2ae3a1995d2cae233500bc32c055912a42723bdc076868 android.hardware.keymaster@4.0::IKeymasterDevice
+e15ebdf1e0a326ff5b8a59668d4d8cd3852bd88388eae91de13f5f7e1af50ed1 android.hardware.keymaster@4.0::types
+6d5c646a83538f0f9d8438c259932509f4353410c6c76e56db0d6ca98b69c3bb android.hardware.media.bufferpool@1.0::IAccessor
+b8c7ed58aa8740361e63d0ce9e7c94227572a629f356958840b34809d2393a7c android.hardware.media.bufferpool@1.0::IClientManager
+4a2c0dc82780e6c90731725a103feab8ab6ecf85a64e049b9cbd2b2c61620fe1 android.hardware.media.bufferpool@1.0::IConnection
+6aef1218e5949f867b0104752ac536c1b707222a403341720de90141df129e3e android.hardware.media.bufferpool@1.0::types
+1529409ed76ae87facab152b770495e9e62544fcc5215daabf146c28d588bab9 android.hardware.neuralnetworks@1.1::IDevice
+e808a6f61cd7b47887c599d8843e67a2dcbf4ec5aadd5d22fdce93020070ef1b android.hardware.neuralnetworks@1.1::types
+8d3d86da0bfa4bf070970d8303c659f67f35d670c287d45a3f542e4fedadd578 android.hardware.nfc@1.1::INfc
+e85f566698d2a2c28100e264fcf2c691a066756ddf8dd341d009ff50cfe10614 android.hardware.nfc@1.1::INfcClientCallback
+5e278fcaa3287d397d8eebe1c22aaa28150f5caae1cf9381cd6dc32cb37899c5 android.hardware.nfc@1.1::types
+163e115e833fc1d77cdd4a8cf0c833bb8b8d74fe35c880fe693101d17774926f android.hardware.power@1.2::IPower
+7899b9305587b2d5cd74a3cc87e9090f58bf4ae74256ce3ee36e7ec011822840 android.hardware.power@1.2::types
+ab132c990a62f0aca35871c092c22fb9c85d478e22124ef6a4d0a2302da76a9f android.hardware.radio@1.2::IRadio
+cda752aeabaabc20486a82ac57a3dd107785c006094a349bc5e224e8aa22a17c android.hardware.radio@1.2::IRadioIndication
+da8c6ae991c6a4b284cc6e445332e064e28ee8a09482ed5afff9d159ec6694b7 android.hardware.radio@1.2::IRadioResponse
+b65332996eb39ba63300a1011404141fa59ce5c252bc17afae637be6eeca5f55 android.hardware.radio@1.2::ISap
+a9361522cc97ef66209d39ba324095b2f08344054bb4d3481e803eee0480623a android.hardware.radio@1.2::types
+87385469cf4409f0f33b01508e7a477cf71f2a11e466dd7e3ab5971a1baaa72b android.hardware.radio.config@1.0::IRadioConfig
+228b2ee3c8c276c9f0afad2dc313ca3d6bbd9e482ddf313c7204c60ad9b636ab android.hardware.radio.config@1.0::IRadioConfigIndication
+a2e9b7aa09f79426f765838174e04b6f9a3e6c8b76b923fc1705632207bad44b android.hardware.radio.config@1.0::IRadioConfigResponse
+4307696b64ded9bd8de06887f9dfc533e875c4e0d83b8008df4d705164bde0b1 android.hardware.radio.config@1.0::types
+bd7699f07ba5392310fefd33ea964e01f4f4a66015146845c85055004823cc81 android.hardware.secure_element@1.0::ISecureElement
+a65aa82bbe48d81a9ae9e86247bb1b89fd2d3138d4053d7a5b716c71149b7dee android.hardware.secure_element@1.0::ISecureElementHalCallback
+2984c069f48ba35cd1bf49b0e17daad0d418fef52cb7a4a84dba0043114063d4 android.hardware.secure_element@1.0::types
+b4f507b4dc9b5cd5f0e4445926acb7d94525ae60dc307b3951142283632207b6 android.hardware.soundtrigger@2.1::ISoundTriggerHw
+92c2cc0f06ef744c5bda21f1d660258f7937203109b493eee22c3f3e2dbb0d3e android.hardware.soundtrigger@2.1::ISoundTriggerHwCallback
+8ddfa7542772cc7bca19972b2d856264efa31914bfd098aeb7c2079d950194cb android.hardware.usb.gadget@1.0::IUsbGadget
+ad0a620cda08f01b151c30cb7afa23b0637cc84340cf8dec00ac8e32cf54a8db android.hardware.usb.gadget@1.0::IUsbGadgetCallback
+51fc20f223561ac3a32ace3217837ef3860265bd91c8b7ae3859532caef9bc39 android.hardware.usb.gadget@1.0::types
+1bfc9fd9536ed09f04bcaf222a332bc919f1565d4d08bddccdebe1bfca8f01b5 android.hardware.vibrator@1.2::IVibrator
+a0aefa29881235c21e4761d15c55edc35ef85c2e0d9e01d0966176d1dbf5f811 android.hardware.vibrator@1.2::types
+8bc75a0dfac15c6f87ffec950b76c7d7de30d516b54e8e0b1f3c0ff9c7c6873b android.hardware.wifi@1.2::IWifi
+780c16fdeda13b779d993953a67f7ca578c938a172a9424c1c715ae81bc40fd7 android.hardware.wifi@1.2::IWifiChip
+167af870fdb87e1cbbaa0fa62ef35e1031caad20dd1ba695983dedb1e9993486 android.hardware.wifi@1.2::IWifiChipEventCallback
+8c7ef32fc78d5ec6e6956de3784cc2c6f42614b5272d2e461f6d60534ba38ec2 android.hardware.wifi@1.2::IWifiNanIface
+1e6074efad9da333803fb7c1acdb719d51c30b2e1e92087b0420341631c30b60 android.hardware.wifi@1.2::IWifiNanIfaceEventCallback
+f5682dbf19f712bef9cc3faa5fe3dc670b6ffbcb62a147a1d86b9d43574cd83f android.hardware.wifi@1.2::IWifiStaIface
+6db2e7d274be2dca9bf3087afd1f774a68c99d2b4dc7eeaf41690e5cebcbef7a android.hardware.wifi@1.2::types
+ee08280de21cb41e3ec26d6ed636c701b7f70516e71fb22f4fe60a13e603f406 android.hardware.wifi.hostapd@1.0::IHostapd
+b2479cd7a417a1cf4f3a22db4e4579e21bac38fdcaf381e2bf10176d05397e01 android.hardware.wifi.hostapd@1.0::types
+e362203b941f18bd4cba29a62adfa02453ed00d6be5b72cdb6c4d7e0bf394a40 android.hardware.wifi.supplicant@1.1::ISupplicant
+21757d0e5dd4b7e4bd981a4a20531bca3c32271ad9777b17b74eb5a1ea508384 android.hardware.wifi.supplicant@1.1::ISupplicantStaIface
+cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardware.wifi.supplicant@1.1::ISupplicantStaIfaceCallback
+10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork
diff --git a/drm/1.1/Android.bp b/drm/1.1/Android.bp
index ed8196e..dba3e42 100644
--- a/drm/1.1/Android.bp
+++ b/drm/1.1/Android.bp
@@ -17,8 +17,10 @@
         "android.hidl.base@1.0",
     ],
     types: [
+        "DrmMetricGroup",
         "HdcpLevel",
         "KeyRequestType",
+        "SecureStopRelease",
         "SecurityLevel",
     ],
     gen_java: false,
diff --git a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
index 061f2cd..1246616 100644
--- a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
@@ -43,7 +43,6 @@
 using ::android::hardware::drm::V1_0::ICryptoPlugin;
 using ::android::hardware::drm::V1_0::KeyedVector;
 using ::android::hardware::drm::V1_0::KeyValue;
-using ::android::hardware::drm::V1_0::KeyRequestType;
 using ::android::hardware::drm::V1_0::KeyType;
 using ::android::hardware::drm::V1_0::Mode;
 using ::android::hardware::drm::V1_0::Pattern;
@@ -60,6 +59,8 @@
 using ::android::hardware::drm::V1_1::ICryptoFactory;
 using ::android::hardware::drm::V1_1::IDrmFactory;
 using ::android::hardware::drm::V1_1::IDrmPlugin;
+using ::android::hardware::drm::V1_1::KeyRequestType;
+using ::android::hardware::drm::V1_1::SecureStopRelease;
 using ::android::hardware::drm::V1_1::SecurityLevel;
 using ::android::hardware::drm::V1_1::SecurityLevel;
 
@@ -167,7 +168,6 @@
     SessionId openSession(SecurityLevel level);
     void closeSession(const SessionId& sessionId);
     hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
-    sp<IMemory> getDecryptMemory(size_t size, size_t index);
 
   private:
     sp<IDrmPlugin> createDrmPlugin(sp<IDrmFactory> drmFactory) {
@@ -308,6 +308,125 @@
 }
 
 /**
+ * Helper method to load keys for subsequent decrypt tests.
+ * These tests use predetermined key request/response to
+ * avoid requiring a round trip to a license server.
+ */
+hidl_vec<uint8_t> DrmHalClearkeyTest::loadKeys(
+    const SessionId& sessionId, const KeyType& type = KeyType::STREAMING) {
+    hidl_vec<uint8_t> initData = {
+        // BMFF box header (4 bytes size + 'pssh')
+        0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
+        // full box header (version = 1 flags = 0)
+        0x01, 0x00, 0x00, 0x00,
+        // system id
+        0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c,
+        0x1e, 0x52, 0xe2, 0xfb, 0x4b,
+        // number of key ids
+        0x00, 0x00, 0x00, 0x01,
+        // key id
+        0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0,
+        0x0d, 0x1e, 0xd0, 0x0d, 0x1e,
+        // size of data, must be zero
+        0x00, 0x00, 0x00, 0x00};
+
+    hidl_vec<uint8_t> expectedKeyRequest = {
+        0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, 0x41, 0x59, 0x65,
+        0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74,
+        0x41, 0x4e, 0x48, 0x67, 0x22, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a,
+        0x22, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d};
+
+    hidl_vec<uint8_t> knownKeyResponse = {
+        0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6b, 0x74, 0x79, 0x22,
+        0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59,
+        0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e,
+        0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x47, 0x6f,
+        0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65,
+        0x36, 0x34, 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
+
+    hidl_string mimeType = "video/mp4";
+    KeyedVector optionalParameters;
+    auto res = drmPlugin->getKeyRequest_1_1(
+        sessionId, initData, mimeType, type, optionalParameters,
+        [&](Status status, const hidl_vec<uint8_t>& request,
+            KeyRequestType requestType, const hidl_string&) {
+            EXPECT_EQ(Status::OK, status);
+            EXPECT_EQ(KeyRequestType::INITIAL, requestType);
+            EXPECT_EQ(request, expectedKeyRequest);
+        });
+    EXPECT_OK(res);
+
+    hidl_vec<uint8_t> keySetId;
+    res = drmPlugin->provideKeyResponse(
+        sessionId, knownKeyResponse,
+        [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
+            EXPECT_EQ(Status::OK, status);
+            EXPECT_EQ(0u, myKeySetId.size());
+            keySetId = myKeySetId;
+        });
+    EXPECT_OK(res);
+    return keySetId;
+}
+
+/**
+ * Test openSession negative case: security level higher than supported
+ */
+TEST_F(DrmHalClearkeyTest, OpenSessionBadLevel) {
+    auto res = drmPlugin->openSession_1_1(SecurityLevel::HW_SECURE_ALL,
+            [&](Status status, const SessionId& /* id */) {
+                EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Test getKeyRequest_1_1 via loadKeys
+ */
+TEST_F(DrmHalClearkeyTest, GetKeyRequest) {
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+}
+
+/**
+ * A get key request should fail if no sessionId is provided
+ */
+TEST_F(DrmHalClearkeyTest, GetKeyRequestNoSession) {
+    SessionId invalidSessionId;
+    hidl_vec<uint8_t> initData;
+    hidl_string mimeType = "video/mp4";
+    KeyedVector optionalParameters;
+    auto res = drmPlugin->getKeyRequest_1_1(
+            invalidSessionId, initData, mimeType, KeyType::STREAMING,
+            optionalParameters,
+            [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
+                const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); });
+    EXPECT_OK(res);
+}
+
+/**
+ * The clearkey plugin doesn't support offline key requests.
+ * Test that the plugin returns the expected error code in
+ * this case.
+ */
+TEST_F(DrmHalClearkeyTest, GetKeyRequestOfflineKeyTypeNotSupported) {
+    auto sessionId = openSession();
+    hidl_vec<uint8_t> initData;
+    hidl_string mimeType = "video/mp4";
+    KeyedVector optionalParameters;
+
+    auto res = drmPlugin->getKeyRequest_1_1(
+            sessionId, initData, mimeType, KeyType::OFFLINE, optionalParameters,
+            [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
+                const hidl_string&) {
+                // Clearkey plugin doesn't support offline key type
+                EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
+            });
+    EXPECT_OK(res);
+    closeSession(sessionId);
+}
+
+/**
  * Test that the plugin returns valid connected and max HDCP levels
  */
 TEST_F(DrmHalClearkeyTest, GetHdcpLevels) {
@@ -322,6 +441,11 @@
 }
 
 /**
+ * Since getHdcpLevels only queries information there are no
+ * negative cases.
+ */
+
+/**
  * Test that the plugin returns default open and max session counts
  */
 TEST_F(DrmHalClearkeyTest, GetDefaultSessionCounts) {
@@ -373,6 +497,11 @@
 }
 
 /**
+ * Since getNumberOfSessions only queries information there are no
+ * negative cases.
+ */
+
+/**
  * Test that the plugin returns the same security level
  * by default as when it is requested explicitly
  */
@@ -428,7 +557,7 @@
 /**
  * Test metrics are set appropriately for open and close operations.
  */
-TEST_F(DrmHalClearkeyTest, GetMetricsSuccess) {
+TEST_F(DrmHalClearkeyTest, GetMetricsOpenClose) {
     SessionId sessionId = openSession();
     // The first close should be successful.
     closeSession(sessionId);
@@ -449,8 +578,292 @@
                                                     (int64_t)Status::ERROR_DRM_SESSION_NOT_OPENED,
                                                     "count", (int64_t)1));
     });
+    EXPECT_OK(res);
 }
 
+/**
+ * Since getMetrics only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that there are no secure stop ids after clearing them
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopIdsCleared) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    bool ok = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, ids.size());
+            }).isOk();
+    EXPECT_TRUE(ok);
+}
+
+/**
+ * Test that there are secure stop ids after loading keys once
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopIdsOnce) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+
+    auto res = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, ids.size());
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    res = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, ids.size());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Since getSecureStopIds only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that the clearkey plugin reports no secure stops when
+ * there are none.
+ */
+TEST_F(DrmHalClearkeyTest, GetNoSecureStops) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, stops.size());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Test get/remove of one secure stop
+ */
+TEST_F(DrmHalClearkeyTest, GetOneSecureStopAndRemoveIt) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+
+    auto res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, stops.size());
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, stops.size());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Since getSecureStops only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that there are no secure stops after clearing them
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopsCleared) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, stops.size());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Test that there are secure stops after loading keys once
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopsOnce) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+
+    auto res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, stops.size());
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, stops.size());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Since getSecureStops only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that releasing a secure stop with empty
+ * release message fails with the documented error
+ */
+TEST_F(DrmHalClearkeyTest, ReleaseEmptySecureStop) {
+    SecureStopRelease emptyRelease = {.opaqueData = hidl_vec<uint8_t>()};
+    Status status = drmPlugin->releaseSecureStops(emptyRelease);
+    EXPECT_EQ(Status::BAD_VALUE, status);
+}
+
+/**
+ * Helper function to create a secure release message for
+ * a secure stop. The clearkey secure stop release format
+ * is just a count followed by the secure stop opaque data.
+ */
+SecureStopRelease makeSecureRelease(const SecureStop &stop) {
+    std::vector<uint8_t> stopData = stop.opaqueData;
+    std::vector<uint8_t> buffer;
+    std::string count = "0001";
+
+    auto it = buffer.insert(buffer.begin(), count.begin(), count.end());
+    buffer.insert(it + count.size(), stopData.begin(), stopData.end());
+    SecureStopRelease release = { .opaqueData = hidl_vec<uint8_t>(buffer) };
+    return release;
+}
+
+/**
+ * Test that releasing one secure stop works
+ */
+TEST_F(DrmHalClearkeyTest, ReleaseOneSecureStop) {
+
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+
+    SecureStopRelease release;
+    auto res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, stops.size());
+                release = makeSecureRelease(stops[0]);
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->releaseSecureStops(release);
+    EXPECT_OK(stat);
+
+    res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, stops.size());
+            });
+    EXPECT_OK(res);
+}
+
+
+/**
+ * Test that removing a secure stop with an empty ID returns
+ * documented error
+ */
+TEST_F(DrmHalClearkeyTest, RemoveEmptySecureStopId) {
+    hidl_vec<uint8_t> emptyId;
+    auto stat = drmPlugin->removeSecureStop(emptyId);
+    EXPECT_OK(stat);
+    EXPECT_EQ(Status::BAD_VALUE, stat);
+}
+
+/**
+ * Test that removing a secure stop after it has already
+ * been removed fails with the documented error code.
+ */
+TEST_F(DrmHalClearkeyTest, RemoveRemovedSecureStopId) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+    SecureStopId ssid;
+
+    auto res = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, ids.size());
+                ssid = ids[0];
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    Status status = drmPlugin->removeSecureStop(ssid);
+    EXPECT_EQ(Status::BAD_VALUE, status);
+}
+
+/**
+ * Test that removing a secure stop by id works
+ */
+TEST_F(DrmHalClearkeyTest, RemoveSecureStopById) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+    SecureStopId ssid;
+
+    auto res = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, ids.size());
+                ssid = ids[0];
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->removeSecureStop(ssid);
+    EXPECT_OK(stat);
+
+    res = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, ids.size());
+            });
+    EXPECT_OK(res);
+}
+
+
 int main(int argc, char** argv) {
     ::testing::AddGlobalTestEnvironment(DrmHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
diff --git a/gnss/1.1/IGnss.hal b/gnss/1.1/IGnss.hal
index 096f251..672f742 100644
--- a/gnss/1.1/IGnss.hal
+++ b/gnss/1.1/IGnss.hal
@@ -46,15 +46,17 @@
      * @param minIntervalMs Represents the time between fixes in milliseconds.
      * @param preferredAccuracyMeters Represents the requested fix accuracy in meters.
      * @param preferredTimeMs Represents the requested time to first fix in milliseconds.
-     * @param lowPowerMode When true, HAL must make strong tradeoffs to substantially restrict power
-     *     use. Specifically, in the case of a several second long minIntervalMs, the GNSS chipset
-     *     must not, on average, run power hungry operations like RF and signal searches for more
-     *     than one second per interval, and must make exactly one call to gnssSvStatusCb(), and
-     *     either zero or one call to GnssLocationCb() at each interval. When false, HAL must
-     *     operate in the nominal mode (similar to V1.0 where this flag wasn't present) and is
-     *     expected to make power and performance tradoffs such as duty-cycling when signal
-     *     conditions are good and more active searches to reacquire GNSS signals when no signals
-     *     are present.
+     * @param lowPowerMode When true, and IGnss.hal is the only client to the GNSS hardware, the
+     *     GNSS hardware must make strong tradeoffs to substantially restrict power use.
+     *     Specifically, in the case of a several second long minIntervalMs, the GNSS hardware must
+     *     not, on average, run power hungry operations like RF and signal searches for more than
+     *     one second per interval, and must make exactly one call to gnssSvStatusCb(), and either
+     *     zero or one call to GnssLocationCb() at each interval. When false, HAL must operate in
+     *     the nominal mode (similar to V1.0 where this flag wasn't present) and is expected to make
+     *     power and performance tradoffs such as duty-cycling when signal conditions are good and
+     *     more active searches to reacquire GNSS signals when no signals are present.
+     *     When there are additional clients using the GNSS hardware other than IGnss.hal, the GNSS
+     *     hardware may operate in a higher power mode, on behalf of those clients.
      *
      * @return success Returns true if successful.
      */
diff --git a/gnss/1.1/IGnssCallback.hal b/gnss/1.1/IGnssCallback.hal
index fdd2ebe..7313340 100644
--- a/gnss/1.1/IGnssCallback.hal
+++ b/gnss/1.1/IGnssCallback.hal
@@ -30,6 +30,9 @@
      * This is a user-visible string that identifies the model and version of the GNSS HAL.
      * For example "ABC Co., Baseband Part 1234, RF Part 567, Software version 3.14.159"
      *
+     * For privacy reasons, this string must not contain any device-specific serial number or other
+     * identifier that uniquely identifies an individual device.
+     *
      * This must be called in response to IGnss::setCallback
      *
      * @param name String providing the name of the GNSS HAL implementation
diff --git a/gnss/1.1/IGnssMeasurement.hal b/gnss/1.1/IGnssMeasurement.hal
index cd83ae3..6ed8e53 100644
--- a/gnss/1.1/IGnssMeasurement.hal
+++ b/gnss/1.1/IGnssMeasurement.hal
@@ -33,10 +33,11 @@
      * @param callback Handle to GnssMeasurement callback interface.
      * @param enableFullTracking If true, GNSS chipset must switch off duty cycling. In such mode
      *     no clock discontinuities are expected and, when supported, carrier phase should be
-     *     continuous in good signal conditions. All constellations and frequency bands that the
-     *     chipset supports must be reported in this mode. The GNSS chipset is allowed to consume
-     *     more power in this mode. If false, API must behave as in HAL V1_0, optimizing power via
-     *     duty cycling, constellations and frequency limits, etc.
+     *     continuous in good signal conditions. All non-blacklisted, healthy constellations,
+     *     satellites and frequency bands that the chipset supports must be reported in this mode.
+     *     The GNSS chipset is allowed to consume more power in this mode. If false, API must behave
+     *     as in HAL V1_0, optimizing power via duty cycling, constellations and frequency limits,
+     *     etc.
      *
      * @return initRet Returns SUCCESS if successful. Returns ERROR_ALREADY_INIT if a callback has
      *     already been registered without a corresponding call to 'close'. Returns ERROR_GENERIC
diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp
index 977a22f..44aed2b 100644
--- a/gnss/1.1/default/Android.bp
+++ b/gnss/1.1/default/Android.bp
@@ -5,6 +5,7 @@
     vendor: true,
     srcs: [
         "Gnss.cpp",
+        "GnssDebug.cpp",
         "GnssConfiguration.cpp",
         "GnssMeasurement.cpp",
         "service.cpp",
diff --git a/gnss/1.1/default/Gnss.cpp b/gnss/1.1/default/Gnss.cpp
index 308ba70..bbc4940 100644
--- a/gnss/1.1/default/Gnss.cpp
+++ b/gnss/1.1/default/Gnss.cpp
@@ -1,8 +1,11 @@
 #define LOG_TAG "Gnss"
 
-#include "Gnss.h"
+#include <android/hardware/gnss/1.0/types.h>
 #include <log/log.h>
-#include "GnssConfiguration.h"
+
+#include "Gnss.h"
+#include "GnssConstants.h"
+#include "GnssDebug.h"
 #include "GnssMeasurement.h"
 
 namespace android {
@@ -11,20 +14,51 @@
 namespace V1_1 {
 namespace implementation {
 
+using GnssSvFlags = IGnssCallback::GnssSvFlags;
+
+const uint32_t MIN_INTERVAL_MILLIS = 100;
+sp<::android::hardware::gnss::V1_1::IGnssCallback> Gnss::sGnssCallback = nullptr;
+
+Gnss::Gnss() : mMinIntervalMs(1000), mGnssConfiguration{new GnssConfiguration()} {}
+
+Gnss::~Gnss() {
+    stop();
+}
+
 // Methods from ::android::hardware::gnss::V1_0::IGnss follow.
 Return<bool> Gnss::setCallback(const sp<::android::hardware::gnss::V1_0::IGnssCallback>&) {
-    // TODO implement
-    return bool{};
+    // Mock handles only new callback (see setCallback1_1) coming from Android P+
+    return false;
 }
 
 Return<bool> Gnss::start() {
-    // TODO implement
-    return bool{};
+    if (mIsActive) {
+        ALOGW("Gnss has started. Restarting...");
+        stop();
+    }
+
+    mIsActive = true;
+    mThread = std::thread([this]() {
+        while (mIsActive == true) {
+            auto svStatus = this->getMockSvStatus();
+            this->reportSvStatus(svStatus);
+
+            auto location = this->getMockLocation();
+            this->reportLocation(location);
+
+            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
+        }
+    });
+
+    return true;
 }
 
 Return<bool> Gnss::stop() {
-    // TODO implement
-    return bool{};
+    mIsActive = false;
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+    return true;
 }
 
 Return<void> Gnss::cleanup() {
@@ -43,7 +77,6 @@
 }
 
 Return<void> Gnss::deleteAidingData(::android::hardware::gnss::V1_0::IGnss::GnssAidingData) {
-    // TODO implement
     return Void();
 }
 
@@ -97,8 +130,7 @@
 }
 
 Return<sp<::android::hardware::gnss::V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
-    // TODO implement
-    return ::android::sp<::android::hardware::gnss::V1_0::IGnssDebug>{};
+    return new GnssDebug();
 }
 
 Return<sp<::android::hardware::gnss::V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
@@ -107,24 +139,48 @@
 }
 
 // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
-Return<bool> Gnss::setCallback_1_1(const sp<::android::hardware::gnss::V1_1::IGnssCallback>&) {
-    ALOGI("Gnss::setCallback_1_1");
-    // TODO implement
-    return bool{};
+Return<bool> Gnss::setCallback_1_1(
+    const sp<::android::hardware::gnss::V1_1::IGnssCallback>& callback) {
+    if (callback == nullptr) {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    sGnssCallback = callback;
+
+    uint32_t capabilities = 0x0;
+    auto ret = sGnssCallback->gnssSetCapabilitesCb(capabilities);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018};
+
+    ret = sGnssCallback->gnssSetSystemInfoCb(gnssInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    auto gnssName = "Google Mock GNSS Implementation v1.1";
+    ret = sGnssCallback->gnssNameCb(gnssName);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    return true;
 }
 
 Return<bool> Gnss::setPositionMode_1_1(
     ::android::hardware::gnss::V1_0::IGnss::GnssPositionMode,
-    ::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t, uint32_t,
-    bool) {
-    // TODO implement
-    return bool{};
+    ::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence, uint32_t minIntervalMs,
+    uint32_t, uint32_t, bool) {
+    mMinIntervalMs = (minIntervalMs < MIN_INTERVAL_MILLIS) ? MIN_INTERVAL_MILLIS : minIntervalMs;
+    return true;
 }
 
 Return<sp<::android::hardware::gnss::V1_1::IGnssConfiguration>>
 Gnss::getExtensionGnssConfiguration_1_1() {
-    // TODO implement
-    return new GnssConfiguration();
+    return mGnssConfiguration;
 }
 
 Return<sp<::android::hardware::gnss::V1_1::IGnssMeasurement>>
@@ -133,12 +189,84 @@
     return new GnssMeasurement();
 }
 
-Return<bool> Gnss::injectBestLocation(const ::android::hardware::gnss::V1_0::GnssLocation&) {
-    // TODO implement
-    return bool{};
+Return<bool> Gnss::injectBestLocation(const GnssLocation&) {
+    return true;
 }
 
-// Methods from ::android::hidl::base::V1_0::IBase follow.
+Return<GnssLocation> Gnss::getMockLocation() const {
+    GnssLocation location = {.gnssLocationFlags = 0xFF,
+                             .latitudeDegrees = kMockLatitudeDegrees,
+                             .longitudeDegrees = kMockLongitudeDegrees,
+                             .altitudeMeters = kMockAltitudeMeters,
+                             .speedMetersPerSec = kMockSpeedMetersPerSec,
+                             .bearingDegrees = kMockBearingDegrees,
+                             .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters,
+                             .verticalAccuracyMeters = kMockVerticalAccuracyMeters,
+                             .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
+                             .bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
+                             .timestamp = kMockTimestamp};
+    return location;
+}
+
+Return<GnssSvInfo> Gnss::getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz,
+                                   float elevationDegrees, float azimuthDegrees) const {
+    GnssSvInfo svInfo = {.svid = svid,
+                         .constellation = type,
+                         .cN0Dbhz = cN0DbHz,
+                         .elevationDegrees = elevationDegrees,
+                         .azimuthDegrees = azimuthDegrees,
+                         .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA |
+                                   GnssSvFlags::HAS_ALMANAC_DATA};
+    return svInfo;
+}
+
+Return<GnssSvStatus> Gnss::getMockSvStatus() const {
+    std::unique_lock<std::recursive_mutex> lock(mGnssConfiguration->getMutex());
+    GnssSvInfo mockGnssSvInfoList[] = {
+        getSvInfo(3, GnssConstellationType::GPS, 32.5, 59.1, 166.5),
+        getSvInfo(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5),
+        getSvInfo(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0),
+        getSvInfo(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0),
+        getSvInfo(30, GnssConstellationType::GPS, 20.5, 11.5, 116.0),
+        getSvInfo(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0)};
+
+    GnssSvStatus svStatus = {.numSvs = sizeof(mockGnssSvInfoList) / sizeof(GnssSvInfo)};
+    for (uint32_t i = 0; i < svStatus.numSvs; i++) {
+        if (mGnssConfiguration->isBlacklisted(mockGnssSvInfoList[i])) {
+            /**
+             * Note well, this is a simple, mock emulation of not using a satellite by changing the
+             * used bit.  Simply blanking the used bit, as is done here, is *not* an acceptable
+             * actual device implementation - actual devices *must not* use the satellite in the
+             * position calculation, as specified in IGnssConfiguration.hal.
+             */
+            mockGnssSvInfoList[i].svFlag &=
+                ~static_cast<uint8_t>(IGnssCallback::GnssSvFlags::USED_IN_FIX);
+        }
+        svStatus.gnssSvList[i] = mockGnssSvInfoList[i];
+    }
+
+    return svStatus;
+}
+
+Return<void> Gnss::reportLocation(const GnssLocation& location) const {
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (sGnssCallback == nullptr) {
+        ALOGE("%s: sGnssCallback is null.", __func__);
+        return Void();
+    }
+    sGnssCallback->gnssLocationCb(location);
+    return Void();
+}
+
+Return<void> Gnss::reportSvStatus(const GnssSvStatus& svStatus) const {
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (sGnssCallback == nullptr) {
+        ALOGE("%s: sGnssCallback is null.", __func__);
+        return Void();
+    }
+    sGnssCallback->gnssSvStatusCb(svStatus);
+    return Void();
+}
 
 }  // namespace implementation
 }  // namespace V1_1
diff --git a/gnss/1.1/default/Gnss.h b/gnss/1.1/default/Gnss.h
index e9ad34b..99af34c 100644
--- a/gnss/1.1/default/Gnss.h
+++ b/gnss/1.1/default/Gnss.h
@@ -4,6 +4,10 @@
 #include <android/hardware/gnss/1.1/IGnss.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
+#include <atomic>
+#include <mutex>
+#include <thread>
+#include "GnssConfiguration.h"
 
 namespace android {
 namespace hardware {
@@ -19,7 +23,18 @@
 using ::android::hardware::Void;
 using ::android::sp;
 
+using GnssConstellationType = V1_0::GnssConstellationType;
+using GnssLocation = V1_0::GnssLocation;
+using GnssSvInfo = V1_0::IGnssCallback::GnssSvInfo;
+using GnssSvStatus = V1_0::IGnssCallback::GnssSvStatus;
+
+/**
+ * Unlike the gnss/1.0/default implementation, which is a shim layer to the legacy gps.h, this
+ * default implementation serves as a mock implementation for emulators
+ */
 struct Gnss : public IGnss {
+    Gnss();
+    ~Gnss();
     // Methods from ::android::hardware::gnss::V1_0::IGnss follow.
     Return<bool> setCallback(
         const sp<::android::hardware::gnss::V1_0::IGnssCallback>& callback) override;
@@ -68,6 +83,20 @@
         const ::android::hardware::gnss::V1_0::GnssLocation& location) override;
 
     // Methods from ::android::hidl::base::V1_0::IBase follow.
+   private:
+    Return<GnssLocation> getMockLocation() const;
+    Return<GnssSvStatus> getMockSvStatus() const;
+    Return<GnssSvInfo> getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz,
+                                 float elevationDegress, float azimuthDegress) const;
+    Return<void> reportLocation(const GnssLocation&) const;
+    Return<void> reportSvStatus(const GnssSvStatus&) const;
+
+    static sp<IGnssCallback> sGnssCallback;
+    std::atomic<long> mMinIntervalMs;
+    sp<GnssConfiguration> mGnssConfiguration;
+    std::atomic<bool> mIsActive;
+    std::thread mThread;
+    mutable std::mutex mMutex;
 };
 
 }  // namespace implementation
diff --git a/gnss/1.1/default/GnssConfiguration.cpp b/gnss/1.1/default/GnssConfiguration.cpp
index d05f317..2717571 100644
--- a/gnss/1.1/default/GnssConfiguration.cpp
+++ b/gnss/1.1/default/GnssConfiguration.cpp
@@ -1,4 +1,7 @@
+#define LOG_TAG "GnssConfiguration"
+
 #include "GnssConfiguration.h"
+#include <log/log.h>
 
 namespace android {
 namespace hardware {
@@ -43,10 +46,33 @@
 }
 
 // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
-Return<bool> GnssConfiguration::setBlacklist(
-    const hidl_vec<::android::hardware::gnss::V1_1::IGnssConfiguration::BlacklistedSource>&) {
-    // TODO implement
-    return bool{};
+Return<bool> GnssConfiguration::setBlacklist(const hidl_vec<BlacklistedSource>& sourceList) {
+    std::unique_lock<std::recursive_mutex> lock(mMutex);
+    mBlacklistedConstellationSet.clear();
+    mBlacklistedSourceSet.clear();
+    for (auto source : sourceList) {
+        if (source.svid == 0) {
+            // Wildcard blacklist, i.e., blacklist entire constellation.
+            mBlacklistedConstellationSet.insert(source.constellation);
+        } else {
+            mBlacklistedSourceSet.insert(source);
+        }
+    }
+    return true;
+}
+
+Return<bool> GnssConfiguration::isBlacklisted(const GnssSvInfo& gnssSvInfo) const {
+    std::unique_lock<std::recursive_mutex> lock(mMutex);
+    if (mBlacklistedConstellationSet.find(gnssSvInfo.constellation) !=
+        mBlacklistedConstellationSet.end()) {
+        return true;
+    }
+    BlacklistedSource source = {.constellation = gnssSvInfo.constellation, .svid = gnssSvInfo.svid};
+    return (mBlacklistedSourceSet.find(source) != mBlacklistedSourceSet.end());
+}
+
+std::recursive_mutex& GnssConfiguration::getMutex() const {
+    return mMutex;
 }
 
 // Methods from ::android::hidl::base::V1_0::IBase follow.
diff --git a/gnss/1.1/default/GnssConfiguration.h b/gnss/1.1/default/GnssConfiguration.h
index 4f7ed2b..9b2699b 100644
--- a/gnss/1.1/default/GnssConfiguration.h
+++ b/gnss/1.1/default/GnssConfiguration.h
@@ -1,9 +1,12 @@
 #ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSCONFIGURATION_H
 #define ANDROID_HARDWARE_GNSS_V1_1_GNSSCONFIGURATION_H
 
+#include <android/hardware/gnss/1.1/IGnssCallback.h>
 #include <android/hardware/gnss/1.1/IGnssConfiguration.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
+#include <mutex>
+#include <unordered_set>
 
 namespace android {
 namespace hardware {
@@ -19,6 +22,26 @@
 using ::android::hardware::Void;
 using ::android::sp;
 
+using BlacklistedSource = ::android::hardware::gnss::V1_1::IGnssConfiguration::BlacklistedSource;
+using GnssConstellationType = V1_0::GnssConstellationType;
+using GnssSvInfo = V1_0::IGnssCallback::GnssSvInfo;
+
+struct BlacklistedSourceHash {
+    inline int operator()(const BlacklistedSource& source) const {
+        return int(source.constellation) * 1000 + int(source.svid);
+    }
+};
+
+struct BlacklistedSourceEqual {
+    inline bool operator()(const BlacklistedSource& s1, const BlacklistedSource& s2) const {
+        return (s1.constellation == s2.constellation) && (s1.svid == s2.svid);
+    }
+};
+
+using BlacklistedSourceSet =
+    std::unordered_set<BlacklistedSource, BlacklistedSourceHash, BlacklistedSourceEqual>;
+using BlacklistedConstellationSet = std::unordered_set<GnssConstellationType>;
+
 struct GnssConfiguration : public IGnssConfiguration {
     // Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
     Return<bool> setSuplEs(bool enabled) override;
@@ -30,11 +53,15 @@
     Return<bool> setEmergencySuplPdn(bool enable) override;
 
     // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
-    Return<bool> setBlacklist(
-        const hidl_vec<::android::hardware::gnss::V1_1::IGnssConfiguration::BlacklistedSource>&
-            blacklist) override;
+    Return<bool> setBlacklist(const hidl_vec<BlacklistedSource>& blacklist) override;
 
-    // Methods from ::android::hidl::base::V1_0::IBase follow.
+    Return<bool> isBlacklisted(const GnssSvInfo& gnssSvInfo) const;
+    std::recursive_mutex& getMutex() const;
+
+   private:
+    BlacklistedSourceSet mBlacklistedSourceSet;
+    BlacklistedConstellationSet mBlacklistedConstellationSet;
+    mutable std::recursive_mutex mMutex;
 };
 
 }  // namespace implementation
diff --git a/gnss/1.1/default/GnssConstants.h b/gnss/1.1/default/GnssConstants.h
new file mode 100644
index 0000000..9ce1a12
--- /dev/null
+++ b/gnss/1.1/default/GnssConstants.h
@@ -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.
+ */
+
+#ifndef android_hardware_gnss_V1_1_GnssConstants_H_
+#define android_hardware_gnss_V1_1_GnssConstants_H_
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+const float kMockLatitudeDegrees = 37.4219999;
+const float kMockLongitudeDegrees = -122.0840575;
+const float kMockAltitudeMeters = 1.60062531;
+const float kMockSpeedMetersPerSec = 0;
+const float kMockBearingDegrees = 0;
+const float kMockHorizontalAccuracyMeters = 5;
+const float kMockVerticalAccuracyMeters = 5;
+const float kMockSpeedAccuracyMetersPerSecond = 1;
+const float kMockBearingAccuracyDegrees = 90;
+const int64_t kMockTimestamp = 1519930775453L;
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_1_GnssConstants_H_
diff --git a/gnss/1.1/default/GnssDebug.cpp b/gnss/1.1/default/GnssDebug.cpp
new file mode 100644
index 0000000..62870e4
--- /dev/null
+++ b/gnss/1.1/default/GnssDebug.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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 "GnssDebug"
+
+#include <log/log.h>
+
+#include "GnssConstants.h"
+#include "GnssDebug.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+Return<void> GnssDebug::getDebugData(V1_0::IGnssDebug::getDebugData_cb _hidl_cb) {
+    PositionDebug positionDebug = {
+        .valid = true,
+        .latitudeDegrees = kMockLatitudeDegrees,
+        .longitudeDegrees = kMockLongitudeDegrees,
+        .altitudeMeters = kMockAltitudeMeters,
+        .speedMetersPerSec = kMockSpeedMetersPerSec,
+        .bearingDegrees = kMockBearingDegrees,
+        .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters,
+        .verticalAccuracyMeters = kMockVerticalAccuracyMeters,
+        .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
+        .bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
+        .ageSeconds = 0.99};
+
+    TimeDebug timeDebug = {.timeEstimate = kMockTimestamp,
+                           .timeUncertaintyNs = 1000,
+                           .frequencyUncertaintyNsPerSec = 5.0e4};
+
+    DebugData data = {.position = positionDebug, .time = timeDebug};
+
+    _hidl_cb(data);
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.1/default/GnssDebug.h b/gnss/1.1/default/GnssDebug.h
new file mode 100644
index 0000000..969d337
--- /dev/null
+++ b/gnss/1.1/default/GnssDebug.h
@@ -0,0 +1,51 @@
+/*
+ * 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_gnss_V1_1_GnssDebug_H_
+#define android_hardware_gnss_V1_1_GnssDebug_H_
+
+#include <android/hardware/gnss/1.0/IGnssDebug.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using V1_0::IGnssDebug;
+
+/* Interface for GNSS Debug support. */
+struct GnssDebug : public IGnssDebug {
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+     * These declarations were generated from IGnssDebug.hal.
+     */
+    Return<void> getDebugData(V1_0::IGnssDebug::getDebugData_cb _hidl_cb) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_1_GnssDebug_H_
diff --git a/gnss/1.1/default/OWNERS b/gnss/1.1/default/OWNERS
new file mode 100644
index 0000000..a3d8577
--- /dev/null
+++ b/gnss/1.1/default/OWNERS
@@ -0,0 +1,4 @@
+wyattriley@google.com
+gomo@google.com
+smalkos@google.com
+yuhany@google.com
diff --git a/gnss/1.1/vts/OWNERS b/gnss/1.1/vts/OWNERS
index 56648ad..3ed36da 100644
--- a/gnss/1.1/vts/OWNERS
+++ b/gnss/1.1/vts/OWNERS
@@ -1,6 +1,7 @@
 wyattriley@google.com
 gomo@google.com
 smalkos@google.com
+yuhany@google.com
 
 # VTS team
 yim@google.com
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp
index 23b7317..8928a5a 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "GnssHalTest"
+
 #include <gnss_hal_test.h>
 
 #include <chrono>
@@ -31,6 +33,8 @@
         GnssHidlEnvironment::Instance()->getServiceName<IGnss>());
     list_gnss_sv_status_.clear();
     ASSERT_NE(gnss_hal_, nullptr);
+
+    SetUpGnssCallback();
 }
 
 void GnssHalTest::TearDown() {
@@ -42,6 +46,30 @@
     }
 }
 
+void GnssHalTest::SetUpGnssCallback() {
+    gnss_cb_ = new GnssCallback(*this);
+    ASSERT_NE(gnss_cb_, nullptr);
+
+    auto result = gnss_hal_->setCallback_1_1(gnss_cb_);
+    if (!result.isOk()) {
+        ALOGE("result of failed setCallback %s", result.description().c_str());
+    }
+
+    ASSERT_TRUE(result.isOk());
+    ASSERT_TRUE(result);
+
+    /*
+     * All capabilities, name and systemInfo callbacks should trigger
+     */
+    EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
+    EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
+    EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
+
+    EXPECT_EQ(capabilities_called_count_, 1);
+    EXPECT_EQ(info_called_count_, 1);
+    EXPECT_EQ(name_called_count_, 1);
+}
+
 void GnssHalTest::StopAndClearLocations() {
     auto result = gnss_hal_->stop();
 
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.h b/gnss/1.1/vts/functional/gnss_hal_test.h
index 6d5bb4c..269366a 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.h
+++ b/gnss/1.1/vts/functional/gnss_hal_test.h
@@ -101,6 +101,12 @@
     };
 
     /*
+     * SetUpGnssCallback:
+     *   Set GnssCallback and verify the result.
+     */
+    void SetUpGnssCallback();
+
+    /*
      * StartAndGetSingleLocation:
      * Helper function to get one Location and check fields
      *
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
index a0a1c73..8f4691e 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "GnssHalTestCases"
+
 #include <gnss_hal_test.h>
 
 #include <VtsHalHidlTargetTestBase.h>
@@ -37,34 +39,6 @@
 TEST_F(GnssHalTest, SetupTeardownCreateCleanup) {}
 
 /*
- * SetCallbackResponses:
- * Sets up the callback, awaits the capability, info & name
- */
-TEST_F(GnssHalTest, SetCallbackResponses) {
-    gnss_cb_ = new GnssCallback(*this);
-    ASSERT_NE(gnss_cb_, nullptr);
-
-    auto result = gnss_hal_->setCallback_1_1(gnss_cb_);
-    if (!result.isOk()) {
-        ALOGE("result of failed setCallback %s", result.description().c_str());
-    }
-
-    ASSERT_TRUE(result.isOk());
-    ASSERT_TRUE(result);
-
-    /*
-     * All capabilities, name and systemInfo callbacks should trigger
-     */
-    EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
-    EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
-    EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
-
-    EXPECT_EQ(capabilities_called_count_, 1);
-    EXPECT_EQ(info_called_count_, 1);
-    EXPECT_EQ(name_called_count_, 1);
-}
-
-/*
  * TestGnssMeasurementCallback:
  * Gets the GnssMeasurementExtension and verify that it returns an actual extension.
  */
@@ -281,6 +255,7 @@
         if (strongest_sv_is_reobserved) break;
     }
     EXPECT_TRUE(strongest_sv_is_reobserved);
+    StopAndClearLocations();
 }
 
 /*
diff --git a/graphics/common/1.1/Android.bp b/graphics/common/1.1/Android.bp
index c319d80..8bc68f5 100644
--- a/graphics/common/1.1/Android.bp
+++ b/graphics/common/1.1/Android.bp
@@ -15,8 +15,10 @@
     ],
     types: [
         "BufferUsage",
+        "ColorMode",
         "Dataspace",
         "PixelFormat",
+        "RenderIntent",
     ],
     gen_java: true,
     gen_java_constants: true,
diff --git a/graphics/common/1.1/types.hal b/graphics/common/1.1/types.hal
index b917d5e..5dca482 100644
--- a/graphics/common/1.1/types.hal
+++ b/graphics/common/1.1/types.hal
@@ -16,9 +16,10 @@
 
 package android.hardware.graphics.common@1.1;
 
-import @1.0::PixelFormat;
 import @1.0::BufferUsage;
+import @1.0::ColorMode;
 import @1.0::Dataspace;
+import @1.0::PixelFormat;
 
 /**
  * Pixel formats for graphics buffers.
@@ -129,15 +130,165 @@
 @export(name="android_dataspace_v1_1_t", value_prefix="HAL_DATASPACE_",
         export_parent="false")
 enum Dataspace : @1.0::Dataspace {
+    /*
+     * @1.0::Dataspace defines six legacy dataspaces
+     *
+     *   SRGB_LINEAR = 0x200, // deprecated, use V0_SRGB_LINEAR
+     *   SRGB = 0x201, // deprecated, use V0_SRGB
+     *   JFIF = 0x101, // deprecated, use V0_JFIF
+     *   BT601_625 = 0x102, // deprecated, use V0_BT601_625
+     *   BT601_525 = 0x103, // deprecated, use V0_BT601_525
+     *   BT709 = 0x104, // deprecated, use V0_BT709
+     *
+     * The difference between the legacy dataspaces and their modern
+     * counterparts is that, with legacy dataspaces, the pixel values may have
+     * been desaturated by the content creator in an unspecified way.
+     *
+     * When colorimetric mapping is required, the legacy dataspaces must be
+     * treated as their modern counterparts (e.g., SRGB must be treated as
+     * V0_SRGB) and no re-saturation is allowed. When non-colorimetric mapping
+     * is allowed, the pixel values can be interpreted freely by
+     * implementations for the purpose of re-saturation, and the re-saturated
+     * pixel values are in the respective modern dataspaces.
+     *
+     * This is also true when UNKNOWN is treated as a legacy 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
+     * Use limited range, BT.709 transfer and BT2020 standard
      */
     BT2020_ITU = STANDARD_BT2020 | TRANSFER_SMPTE_170M | RANGE_LIMITED,
 
+    /**
+     * ITU-R Recommendation 2100 (BT.2100)
+     *
+     * High dynamic range television
+     *
+     * Use limited/full range, PQ/HLG transfer, and BT2020 standard
+     * limited range is the preferred / normative definition for BT.2100
+     */
     BT2020_ITU_PQ = STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_LIMITED,
+    BT2020_ITU_HLG = STANDARD_BT2020 | TRANSFER_HLG | RANGE_LIMITED,
+    BT2020_HLG = STANDARD_BT2020 | TRANSFER_HLG | RANGE_FULL,
+};
+
+@export(name="android_color_mode_v1_1_t", value_prefix="HAL_COLOR_MODE_",
+        export_parent="false")
+enum ColorMode : @1.0::ColorMode {
+    /**
+     * BT2020 corresponds with display settings that implement the ITU-R
+     * Recommendation BT.2020 / Rec. 2020 for UHDTV.
+     *
+     * Primaries:
+     *                  x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * Inverse Gamma Correction (IGC): V represents normalized (with [0 to 1]
+     * range) value of R, G, or B.
+     *
+     *  if Vnonlinear < b * 4.5
+     *    Vlinear = Vnonlinear / 4.5
+     *  else
+     *    Vlinear = ((Vnonlinear + (a - 1)) / a) ^ (1/0.45)
+     *
+     * Gamma Correction (GC):
+     *
+     *  if Vlinear < b
+     *    Vnonlinear = 4.5 * Vlinear
+     *  else
+     *    Vnonlinear = a * Vlinear ^ 0.45 - (a - 1)
+     *
+     * where
+     *
+     *   a = 1.09929682680944, b = 0.018053968510807
+     *
+     * For practical purposes, these a/b values can be used instead
+     *
+     *   a = 1.099, b = 0.018 for 10-bit display systems
+     *   a = 1.0993, b = 0.0181 for 12-bit display systems
+     */
+    BT2020 = 10,
+
+    /**
+     * BT2100_PQ and BT2100_HLG correspond with display settings that
+     * implement the ITU-R Recommendation BT.2100 / Rec. 2100 for HDR TV.
+     *
+     * Primaries:
+     *                  x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * For BT2100_PQ, the transfer function is Perceptual Quantizer (PQ). For
+     * BT2100_HLG, the transfer function is Hybrid Log-Gamma (HLG).
+     */
+    BT2100_PQ = 11,
+    BT2100_HLG = 12,
+};
+
+/**
+ * RenderIntent defines the mapping from color mode colors to display colors.
+ *
+ * A render intent must not change how it maps colors when the color mode
+ * changes. That is to say that when a render intent maps color C to color C',
+ * the fact that color C can have different pixel values in different color
+ * modes should not affect the mapping.
+ *
+ * RenderIntent overrides the render intents defined for individual color
+ * modes. It is ignored when the color mode is ColorMode::NATIVE, because
+ * ColorMode::NATIVE colors are already display colors.
+ */
+@export(name="android_render_intent_v1_1_t", value_prefix="HAL_RENDER_INTENT_",
+        export_parent="false")
+enum RenderIntent : int32_t {
+    /**
+     * Colors in the display gamut are unchanged. Colors out of the display
+     * gamut are hard-clipped.
+     *
+     * This implies that the display must have been calibrated unless
+     * ColorMode::NATIVE is the only supported color mode.
+     */
+    COLORIMETRIC = 0,
+
+    /**
+     * Enhance colors that are in the display gamut. Colors out of the display
+     * gamut are hard-clipped.
+     *
+     * The enhancement typically picks the biggest standard color space (e.g.
+     * DCI-P3) that is narrower than the display gamut and stretches it to the
+     * display gamut. The stretching is recommended to preserve skin tones.
+     */
+    ENHANCE = 1,
+
+    /**
+     * Tone map high-dynamic-range colors to the display's dynamic range. The
+     * dynamic range of the colors are communicated separately. After tone
+     * mapping, the mapping to the display gamut is as defined in
+     * COLORIMETRIC.
+     */
+    TONE_MAP_COLORIMETRIC = 2,
+
+    /**
+     * Tone map high-dynamic-range colors to the display's dynamic range. The
+     * dynamic range of the colors are communicated separately. After tone
+     * mapping, the mapping to the display gamut is as defined in ENHANCE.
+     *
+     * The tone mapping step and the enhancing step must match
+     * TONE_MAP_COLORIMETRIC and ENHANCE respectively when they are also
+     * supported.
+     */
+    TONE_MAP_ENHANCE = 3,
+
+    /*
+     * Vendors are recommended to use 0x100 - 0x1FF for their own values, and
+     * that must be done with subtypes defined by vendor extensions.
+     */
 };
diff --git a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
index 3b6710b..a2a12c1 100644
--- a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
+++ b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
@@ -3,4 +3,9 @@
     user system
     group graphics drmrpc
     capabilities SYS_NICE
-    onrestart restart surfaceflinger
+    writepid /dev/cpuset/system-background/tasks
+
+# Restart HWC when SurfaceFlinger stops. This turns off the display and prpares
+# a new HWC instance for when SurfaceFlinger gets started again
+on property:init.svc.surfaceflinger=stopped
+    restart vendor.hwcomposer-2-1
diff --git a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
index df529ec..2742207 100644
--- a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
+++ b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
@@ -247,21 +247,8 @@
 
     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);
-
-        beginCommand(IComposerClient::Command::SET_CLIENT_TARGET, length);
-        write(slot);
-        writeHandle(target, true);
-        writeFence(acquireFence);
-        writeSigned(static_cast<int32_t>(dataspace));
-        // When there are too many rectangles in the damage region and doWrite
-        // is false, we write no rectangle at all which means the entire
-        // client target is damaged.
-        if (doWrite) {
-            writeRegion(damage);
-        }
-        endCommand();
+        setClientTargetInternal(slot, target, acquireFence, static_cast<int32_t>(dataspace),
+                                damage);
     }
 
     static constexpr uint16_t kSetOutputBufferLength = 3;
@@ -354,9 +341,7 @@
 
     static constexpr uint16_t kSetLayerDataspaceLength = 1;
     void setLayerDataspace(Dataspace dataspace) {
-        beginCommand(IComposerClient::Command::SET_LAYER_DATASPACE, kSetLayerDataspaceLength);
-        writeSigned(static_cast<int32_t>(dataspace));
-        endCommand();
+        setLayerDataspaceInternal(static_cast<int32_t>(dataspace));
     }
 
     static constexpr uint16_t kSetLayerDisplayFrameLength = 4;
@@ -418,6 +403,32 @@
     }
 
    protected:
+    void setClientTargetInternal(uint32_t slot, const native_handle_t* target, int acquireFence,
+                                 int32_t dataspace,
+                                 const std::vector<IComposerClient::Rect>& damage) {
+        bool doWrite = (damage.size() <= (kMaxLength - 4) / 4);
+        size_t length = 4 + ((doWrite) ? damage.size() * 4 : 0);
+
+        beginCommand(IComposerClient::Command::SET_CLIENT_TARGET, length);
+        write(slot);
+        writeHandle(target, true);
+        writeFence(acquireFence);
+        writeSigned(dataspace);
+        // When there are too many rectangles in the damage region and doWrite
+        // is false, we write no rectangle at all which means the entire
+        // client target is damaged.
+        if (doWrite) {
+            writeRegion(damage);
+        }
+        endCommand();
+    }
+
+    void setLayerDataspaceInternal(int32_t dataspace) {
+        beginCommand(IComposerClient::Command::SET_LAYER_DATASPACE, kSetLayerDataspaceLength);
+        writeSigned(dataspace);
+        endCommand();
+    }
+
     void beginCommand(IComposerClient::Command command, uint16_t length) {
         if (mCommandEnd) {
             LOG_FATAL("endCommand was not called before command 0x%x", command);
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
index 0d883e4..8d5493e 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
@@ -104,9 +104,7 @@
 
     void execute(TestCommandReader* reader, CommandWriterBase* writer);
 
-   private:
-    sp<IComposerClient> mClient;
-
+   protected:
     // Keep track of all virtual displays and layers.  When a test fails with
     // ASSERT_*, the destructor will clean up the resources for the test.
     struct DisplayResource {
@@ -116,6 +114,9 @@
         std::unordered_set<Layer> layers;
     };
     std::unordered_map<Display, DisplayResource> mDisplayResources;
+
+   private:
+    sp<IComposerClient> mClient;
 };
 
 }  // namespace vts
diff --git a/graphics/composer/2.2/Android.bp b/graphics/composer/2.2/Android.bp
index 633a208..fe71e9e 100644
--- a/graphics/composer/2.2/Android.bp
+++ b/graphics/composer/2.2/Android.bp
@@ -12,6 +12,7 @@
     ],
     interfaces: [
         "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.composer@2.1",
         "android.hidl.base@1.0",
     ],
diff --git a/graphics/composer/2.2/IComposerClient.hal b/graphics/composer/2.2/IComposerClient.hal
index dcd9c8d..b7ba6a6 100644
--- a/graphics/composer/2.2/IComposerClient.hal
+++ b/graphics/composer/2.2/IComposerClient.hal
@@ -16,11 +16,14 @@
 
 package android.hardware.graphics.composer@2.2;
 
-import android.hardware.graphics.common@1.0::PixelFormat;
-import android.hardware.graphics.common@1.0::Dataspace;
+import android.hardware.graphics.common@1.1::ColorMode;
+import android.hardware.graphics.common@1.1::Dataspace;
+import android.hardware.graphics.common@1.1::PixelFormat;
+import android.hardware.graphics.common@1.1::RenderIntent;
 import @2.1::IComposerClient;
 import @2.1::Display;
 import @2.1::Error;
+import @2.1::IComposerClient;
 
 interface IComposerClient extends @2.1::IComposerClient {
 
@@ -90,16 +93,20 @@
 
     enum Command : @2.1::IComposerClient.Command {
         /**
-         * setPerFrameMetadata(Display display, vec<PerFrameMetadata> data)
+         * SET_LAYER_PER_FRAME_METADATA has this pseudo prototype
+         *
+         *   setLayerPerFrameMetadata(Display display, Layer layer,
+         *                            vec<PerFrameMetadata> data);
+         *
          * Sets the PerFrameMetadata for the display. This metadata must be used
          * by the implementation to better tone map content to that display.
          *
          * This is a method that may be called every frame. Thus it's
          * implemented using buffered transport.
-         * SET_PER_FRAME_METADATA is the command used by the buffered transport
+         * SET_LAYER_PER_FRAME_METADATA is the command used by the buffered transport
          * mechanism.
          */
-        SET_PER_FRAME_METADATA = 0x207 << @2.1::IComposerClient.Command:OPCODE_SHIFT,
+        SET_LAYER_PER_FRAME_METADATA = 0x303 << @2.1::IComposerClient.Command:OPCODE_SHIFT,
 
         /**
          * SET_LAYER_COLOR has this pseudo prototype
@@ -242,6 +249,65 @@
     setReadbackBuffer(Display display, handle buffer, handle releaseFence) generates (Error error);
 
     /**
+     * createVirtualDisplay_2_2
+     * Creates a new virtual display with the given width and height. The
+     * format passed into this function is the default format requested by the
+     * consumer of the virtual display output buffers.
+     *
+     * The display must be assumed to be on from the time the first frame is
+     * presented until the display is destroyed.
+     *
+     * @param width is the width in pixels.
+     * @param height is the height in pixels.
+     * @param formatHint is the default output buffer format selected by
+     *        the consumer.
+     * @param outputBufferSlotCount is the number of output buffer slots to be
+     *        reserved.
+     * @return error is NONE upon success. Otherwise,
+     *         UNSUPPORTED when the width or height is too large for the
+     *                     device to be able to create a virtual display.
+     *         NO_RESOURCES when the device is unable to create a new virtual
+     *                      display at this time.
+     * @return display is the newly-created virtual display.
+     * @return format is the format of the buffer the device will produce.
+     */
+    @callflow(next="*")
+    createVirtualDisplay_2_2(uint32_t width,
+                             uint32_t height,
+                             PixelFormat formatHint,
+                             uint32_t outputBufferSlotCount)
+                  generates (Error error,
+                             Display display,
+                             PixelFormat format);
+
+    /**
+     * getClientTargetSupport_2_2
+     * Returns whether a client target with the given properties can be
+     * handled by the device.
+     *
+     * This function must return true for a client target with width and
+     * height equal to the active display configuration dimensions,
+     * PixelFormat::RGBA_8888, and Dataspace::UNKNOWN. It is not required to
+     * return true for any other configuration.
+     *
+     * @param display is the display to query.
+     * @param width is the client target width in pixels.
+     * @param height is the client target height in pixels.
+     * @param format is the client target format.
+     * @param dataspace is the client target dataspace, as described in
+     *        setLayerDataspace.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         UNSUPPORTED when the given configuration is not supported.
+     */
+    @callflow(next="*")
+    getClientTargetSupport_2_2(Display display,
+                               uint32_t width,
+                               uint32_t height,
+                               PixelFormat format,
+                               Dataspace dataspace)
+                    generates (Error error);
+    /**
      * setPowerMode_2_2
      * Sets the power mode of the given display. The transition must be
      * complete when this function returns. It is valid to call this function
@@ -260,4 +326,118 @@
      */
     setPowerMode_2_2(Display display, PowerMode mode) generates (Error error);
 
+    /**
+     * Returns the color modes supported on this display.
+     *
+     * All devices must support at least ColorMode::NATIVE.
+     *
+     * @param display is the display to query.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     * @return modes is an array of color modes.
+     */
+    getColorModes_2_2(Display display)
+           generates (Error error,
+                      vec<ColorMode> modes);
+
+    /**
+     * Returns the render intents supported by the specified display and color
+     * mode.
+     *
+     * RenderIntent::COLORIMETRIC is always supported.
+     *
+     * @param display is the display to query.
+     * @param mode is the color mode to query.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_PARAMETER when an invalid color mode was passed in.
+     * @return intents is an array of render intents.
+     */
+    getRenderIntents(Display display, ColorMode mode)
+          generates (Error error,
+                     vec<RenderIntent> intents);
+
+    /**
+     * Sets the color mode and render intent of the given display.
+     *
+     * The color mode and render intent change must take effect on next
+     * presentDisplay.
+     *
+     * All devices must support at least ColorMode::NATIVE and
+     * RenderIntent::COLORIMETRIC, and displays are assumed to be in this mode
+     * upon hotplug.
+     *
+     * @param display is the display to which the color mode is set.
+     * @param mode is the color mode to set to.
+     * @param intent is the render intent to set to.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_PARAMETER when mode or intent is invalid
+     *         UNSUPPORTED when mode or intent is not supported on this
+     *                     display.
+     */
+    setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent)
+          generates (Error error);
+
+    /*
+     * By default, layer dataspaces are mapped to the current color mode
+     * colorimetrically with a few exceptions.
+     *
+     * When the layer dataspace is a legacy sRGB dataspace
+     * (Dataspace::SRGB_LINEAR, Dataspace::SRGB, or Dataspace::UNKNOWN when
+     * treated as such) and the display render intent is
+     * RenderIntent::ENHANCE, the pixel values can go through an
+     * implementation-defined saturation transform before being mapped to the
+     * current color mode colorimetrically.
+     *
+     * Colors that are out of the gamut of the current color mode are
+     * hard-clipped.
+     */
+
+    /**
+     * Returns the saturation matrix of the specified legacy dataspace.
+     *
+     * The saturation matrix can be used to approximate the legacy dataspace
+     * saturation transform. It is to be applied on linear pixel values like
+     * this:
+     *
+     *   (in GLSL)
+     *   linearSrgb = clamp(saturationMatrix * linearSrgb, 0.0, 1.0);
+     *
+     * @param dataspace must be Dataspace::SRGB_LINEAR.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_PARAMETER when an invalid dataspace was passed in.
+     * @return matrix is the 4x4 column-major matrix used to approximate the
+     *         legacy dataspace saturation operation. The last row must be
+     *         [0.0, 0.0, 0.0, 1.0].
+     */
+    getDataspaceSaturationMatrix(Dataspace dataspace)
+                      generates (Error error,
+                                 float[4][4] matrix);
+
+    /**
+     * Executes commands from the input command message queue. Return values
+     * generated by the input commands are written to the output command
+     * message queue in the form of value commands.
+     *
+     * @param inLength is the length of input commands.
+     * @param inHandles is an array of handles referenced by the input
+     *        commands.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_PARAMETER when inLength is not equal to the length of
+     *                       commands in the input command message queue.
+     *         NO_RESOURCES when the output command message queue was not
+     *                      properly drained.
+     * @param outQueueChanged indicates whether the output command message
+     *        queue has changed.
+     * @param outLength is the length of output commands.
+     * @param outHandles is an array of handles referenced by the output
+     *        commands.
+     */
+    executeCommands_2_2(uint32_t inLength,
+                        vec<handle> inHandles)
+             generates (Error error,
+                        bool outQueueChanged,
+                        uint32_t outLength,
+                        vec<handle> outHandles);
 };
diff --git a/graphics/composer/2.2/default/Android.bp b/graphics/composer/2.2/default/Android.bp
deleted file mode 100644
index 906479e..0000000
--- a/graphics/composer/2.2/default/Android.bp
+++ /dev/null
@@ -1,31 +0,0 @@
-cc_binary {
-    name: "android.hardware.graphics.composer@2.2-service",
-    defaults: ["hidl_defaults"],
-    vendor: true,
-    relative_install_path: "hw",
-    srcs: ["service.cpp"],
-    init_rc: ["android.hardware.graphics.composer@2.2-service.rc"],
-    header_libs: [
-        "android.hardware.graphics.composer@2.2-passthrough",
-    ],
-    shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.composer@2.2",
-        "android.hardware.graphics.mapper@2.0",
-        "libbase",
-        "libbinder",
-        "libcutils",
-        "libfmq",
-        "libhardware",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwc2on1adapter",
-        "libhwc2onfbadapter",
-        "liblog",
-        "libsync",
-        "libutils",
-    ],
-    cflags: [
-        "-DLOG_TAG=\"ComposerHal\""
-    ],
-}
diff --git a/graphics/composer/2.2/default/Android.mk b/graphics/composer/2.2/default/Android.mk
new file mode 100644
index 0000000..2f80f0c
--- /dev/null
+++ b/graphics/composer/2.2/default/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.graphics.composer@2.2-service
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_CFLAGS := -Wall -Werror -DLOG_TAG=\"ComposerHal\"
+LOCAL_SRC_FILES := service.cpp
+LOCAL_INIT_RC := android.hardware.graphics.composer@2.2-service.rc
+LOCAL_HEADER_LIBRARIES := android.hardware.graphics.composer@2.2-passthrough
+LOCAL_SHARED_LIBRARIES := \
+        android.hardware.graphics.composer@2.1 \
+        android.hardware.graphics.composer@2.2 \
+        android.hardware.graphics.mapper@2.0 \
+        libbase \
+        libbinder \
+        libcutils \
+        libfmq \
+        libhardware \
+        libhidlbase \
+        libhidltransport \
+        libhwc2on1adapter \
+        libhwc2onfbadapter \
+        liblog \
+        libsync \
+        libutils
+
+ifdef TARGET_USES_DISPLAY_RENDER_INTENTS
+LOCAL_CFLAGS += -DUSES_DISPLAY_RENDER_INTENTS
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
index c803d3c..138d700 100644
--- a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
+++ b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
@@ -47,8 +47,8 @@
 
 using android::hardware::MessageQueue;
 using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Dataspace;
 using android::hardware::graphics::common::V1_0::Transform;
+using android::hardware::graphics::common::V1_1::Dataspace;
 using android::hardware::graphics::composer::V2_1::Config;
 using android::hardware::graphics::composer::V2_1::Display;
 using android::hardware::graphics::composer::V2_1::Error;
@@ -64,6 +64,16 @@
    public:
     CommandWriterBase(uint32_t initialMaxSize) : V2_1::CommandWriterBase(initialMaxSize) {}
 
+    void setClientTarget(uint32_t slot, const native_handle_t* target, int acquireFence,
+                         Dataspace dataspace, const std::vector<IComposerClient::Rect>& damage) {
+        setClientTargetInternal(slot, target, acquireFence, static_cast<int32_t>(dataspace),
+                                damage);
+    }
+
+    void setLayerDataspace(Dataspace dataspace) {
+        setLayerDataspaceInternal(static_cast<int32_t>(dataspace));
+    }
+
     static constexpr uint16_t kSetLayerFloatColorLength = 4;
     void setLayerFloatColor(IComposerClient::FloatColor color) {
         beginCommand_2_2(IComposerClient::Command::SET_LAYER_FLOAT_COLOR,
@@ -72,8 +82,9 @@
         endCommand();
     }
 
-    void setPerFrameMetadata(const hidl_vec<IComposerClient::PerFrameMetadata>& metadataVec) {
-        beginCommand_2_2(IComposerClient::Command::SET_PER_FRAME_METADATA, metadataVec.size() * 2);
+    void setLayerPerFrameMetadata(const hidl_vec<IComposerClient::PerFrameMetadata>& metadataVec) {
+        beginCommand_2_2(IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA,
+                         metadataVec.size() * 2);
         for (const auto& metadata : metadataVec) {
             writeSigned(static_cast<int32_t>(metadata.key));
             writeFloat(metadata.value);
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
index d550f83..a6871fb 100644
--- a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
@@ -99,10 +99,87 @@
         return mHal->setReadbackBuffer(display, readbackBuffer, std::move(fenceFd));
     }
 
+    Return<void> createVirtualDisplay_2_2(
+        uint32_t width, uint32_t height, PixelFormat formatHint, uint32_t outputBufferSlotCount,
+        IComposerClient::createVirtualDisplay_2_2_cb hidl_cb) override {
+        Display display = 0;
+        Error err = mHal->createVirtualDisplay_2_2(width, height, &formatHint, &display);
+        if (err == Error::NONE) {
+            mResources->addVirtualDisplay(display, outputBufferSlotCount);
+        }
+
+        hidl_cb(err, display, formatHint);
+        return Void();
+    }
+
+    Return<Error> getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+                                             PixelFormat format, Dataspace dataspace) override {
+        Error err = mHal->getClientTargetSupport_2_2(display, width, height, format, dataspace);
+        return err;
+    }
+
     Return<Error> setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override {
         return mHal->setPowerMode_2_2(display, mode);
     }
 
+    Return<void> getColorModes_2_2(Display display,
+                                   IComposerClient::getColorModes_2_2_cb hidl_cb) override {
+        hidl_vec<ColorMode> modes;
+        Error err = mHal->getColorModes_2_2(display, &modes);
+        hidl_cb(err, modes);
+        return Void();
+    }
+
+    Return<void> getRenderIntents(Display display, ColorMode mode,
+                                  IComposerClient::getRenderIntents_cb hidl_cb) override {
+#ifdef USES_DISPLAY_RENDER_INTENTS
+        std::vector<RenderIntent> intents;
+        Error err = mHal->getRenderIntents(display, mode, &intents);
+        hidl_cb(err, intents);
+#else
+        (void)display;
+        (void)mode;
+        hidl_cb(Error::NONE, hidl_vec<RenderIntent>({RenderIntent::COLORIMETRIC}));
+#endif
+        return Void();
+    }
+
+    Return<Error> setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override {
+#ifndef USES_DISPLAY_RENDER_INTENTS
+        if (intent != RenderIntent::COLORIMETRIC) {
+            return Error::BAD_PARAMETER;
+        }
+#endif
+        return mHal->setColorMode_2_2(display, mode, intent);
+    }
+
+    Return<void> getDataspaceSaturationMatrix(
+        Dataspace dataspace, IComposerClient::getDataspaceSaturationMatrix_cb hidl_cb) override {
+        if (dataspace != Dataspace::SRGB_LINEAR) {
+            hidl_cb(Error::BAD_PARAMETER, std::array<float, 16>{0.0f}.data());
+            return Void();
+        }
+
+        hidl_cb(Error::NONE, mHal->getDataspaceSaturationMatrix(dataspace).data());
+        return Void();
+    }
+
+    Return<void> executeCommands_2_2(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
+                                     IComposerClient::executeCommands_2_2_cb hidl_cb) override {
+        std::lock_guard<std::mutex> lock(mCommandEngineMutex);
+        bool outChanged = false;
+        uint32_t outLength = 0;
+        hidl_vec<hidl_handle> outHandles;
+        Error error =
+            mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles);
+
+        hidl_cb(error, outChanged, outLength, outHandles);
+
+        mCommandEngine->reset();
+
+        return Void();
+    }
+
    protected:
     std::unique_ptr<V2_1::hal::ComposerResources> createResources() override {
         return ComposerResources::create();
@@ -146,6 +223,8 @@
 
    private:
     using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>;
+    using BaseType2_1::mCommandEngine;
+    using BaseType2_1::mCommandEngineMutex;
     using BaseType2_1::mHal;
     using BaseType2_1::mResources;
 };
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
index adcac46..97e3a9e 100644
--- a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
@@ -40,8 +40,8 @@
    protected:
     bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override {
         switch (static_cast<IComposerClient::Command>(command)) {
-            case IComposerClient::Command::SET_PER_FRAME_METADATA:
-                return executeSetPerFrameMetadata(length);
+            case IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA:
+                return executeSetLayerPerFrameMetadata(length);
             case IComposerClient::Command::SET_LAYER_FLOAT_COLOR:
                 return executeSetLayerFloatColor(length);
             default:
@@ -49,7 +49,7 @@
         }
     }
 
-    bool executeSetPerFrameMetadata(uint16_t length) {
+    bool executeSetLayerPerFrameMetadata(uint16_t length) {
         // (key, value) pairs
         if (length % 2 != 0) {
             return false;
@@ -63,7 +63,7 @@
             length -= 2;
         }
 
-        auto err = mHal->setPerFrameMetadata(mCurrentDisplay, metadata);
+        auto err = mHal->setLayerPerFrameMetadata(mCurrentDisplay, mCurrentLayer, metadata);
         if (err != Error::NONE) {
             mWriter.setError(getCommandLoc(), err);
         }
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
index 30b3643..335dc24 100644
--- a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
@@ -28,34 +28,68 @@
 namespace V2_2 {
 namespace hal {
 
-using common::V1_0::Dataspace;
-using common::V1_0::PixelFormat;
+using common::V1_1::ColorMode;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
 using V2_1::Display;
 using V2_1::Error;
 using V2_1::Layer;
 
 class ComposerHal : public V2_1::hal::ComposerHal {
    public:
+    Error createVirtualDisplay(uint32_t width, uint32_t height, common::V1_0::PixelFormat* format,
+                               Display* outDisplay) override {
+        return createVirtualDisplay_2_2(width, height, reinterpret_cast<PixelFormat*>(format),
+                                        outDisplay);
+    }
+    Error getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                 common::V1_0::PixelFormat format,
+                                 common::V1_0::Dataspace dataspace) override {
+        return getClientTargetSupport_2_2(display, width, height, static_cast<PixelFormat>(format),
+                                          static_cast<Dataspace>(dataspace));
+    }
     // superceded by setPowerMode_2_2
     Error setPowerMode(Display display, V2_1::IComposerClient::PowerMode mode) override {
         return setPowerMode_2_2(display, static_cast<IComposerClient::PowerMode>(mode));
     }
 
+    // superceded by getColorModes_2_2
+    Error getColorModes(Display display, hidl_vec<common::V1_0::ColorMode>* outModes) override {
+        return getColorModes_2_2(display, reinterpret_cast<hidl_vec<ColorMode>*>(outModes));
+    }
+
+    // superceded by setColorMode_2_2
+    Error setColorMode(Display display, common::V1_0::ColorMode mode) override {
+        return setColorMode_2_2(display, static_cast<ColorMode>(mode), RenderIntent::COLORIMETRIC);
+    }
+
     virtual Error getPerFrameMetadataKeys(
         Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) = 0;
-    virtual Error setPerFrameMetadata(
-        Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) = 0;
+    virtual Error setLayerPerFrameMetadata(
+        Display display, Layer layer,
+        const std::vector<IComposerClient::PerFrameMetadata>& metadata) = 0;
 
     virtual Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat,
                                               Dataspace* outDataspace) = 0;
     virtual Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle,
                                     base::unique_fd fenceFd) = 0;
     virtual Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) = 0;
-
+    virtual Error createVirtualDisplay_2_2(uint32_t width, uint32_t height, PixelFormat* format,
+                                           Display* outDisplay) = 0;
+    virtual Error getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+                                             PixelFormat format, Dataspace dataspace) = 0;
     virtual Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) = 0;
 
     virtual Error setLayerFloatColor(Display display, Layer layer,
                                      IComposerClient::FloatColor color) = 0;
+
+    virtual Error getColorModes_2_2(Display display, hidl_vec<ColorMode>* outModes) = 0;
+    virtual Error getRenderIntents(Display display, ColorMode mode,
+                                   std::vector<RenderIntent>* outIntents) = 0;
+    virtual Error setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) = 0;
+
+    virtual std::array<float, 16> getDataspaceSaturationMatrix(Dataspace dataspace) = 0;
 };
 
 }  // namespace hal
diff --git a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
index b251351..93da0a5 100644
--- a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
+++ b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
@@ -34,8 +34,10 @@
 
 namespace detail {
 
-using common::V1_0::Dataspace;
-using common::V1_0::PixelFormat;
+using common::V1_1::ColorMode;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
 using V2_1::Display;
 using V2_1::Error;
 using V2_1::Layer;
@@ -72,9 +74,10 @@
         return Error::NONE;
     }
 
-    Error setPerFrameMetadata(
-        Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) override {
-        if (!mDispatch.setPerFrameMetadata) {
+    Error setLayerPerFrameMetadata(
+        Display display, Layer layer,
+        const std::vector<IComposerClient::PerFrameMetadata>& metadata) override {
+        if (!mDispatch.setLayerPerFrameMetadata) {
             return Error::UNSUPPORTED;
         }
 
@@ -87,8 +90,8 @@
             values.push_back(m.value);
         }
 
-        int32_t error = mDispatch.setPerFrameMetadata(mDevice, display, metadata.size(),
-                                                      keys.data(), values.data());
+        int32_t error = mDispatch.setLayerPerFrameMetadata(mDevice, display, layer, metadata.size(),
+                                                           keys.data(), values.data());
         return static_cast<Error>(error);
     }
 
@@ -131,6 +134,19 @@
         return static_cast<Error>(error);
     }
 
+    Error createVirtualDisplay_2_2(uint32_t width, uint32_t height, PixelFormat* format,
+                                   Display* outDisplay) override {
+        return createVirtualDisplay(
+            width, height, reinterpret_cast<common::V1_0::PixelFormat*>(format), outDisplay);
+    }
+
+    Error getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+                                     PixelFormat format, Dataspace dataspace) override {
+        return getClientTargetSupport(display, width, height,
+                                      static_cast<common::V1_0::PixelFormat>(format),
+                                      static_cast<common::V1_0::Dataspace>(dataspace));
+    }
+
     Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override {
         if (mode == IComposerClient::PowerMode::ON_SUSPEND) {
             return Error::UNSUPPORTED;
@@ -149,6 +165,69 @@
         return static_cast<Error>(error);
     }
 
+    Error getColorModes_2_2(Display display, hidl_vec<ColorMode>* outModes) override {
+        return getColorModes(display,
+                             reinterpret_cast<hidl_vec<common::V1_0::ColorMode>*>(outModes));
+    }
+
+    Error getRenderIntents(Display display, ColorMode mode,
+                           std::vector<RenderIntent>* outIntents) override {
+        if (!mDispatch.getRenderIntents) {
+            *outIntents = std::vector<RenderIntent>({RenderIntent::COLORIMETRIC});
+            return Error::NONE;
+        }
+
+        uint32_t count = 0;
+        int32_t error =
+            mDispatch.getRenderIntents(mDevice, display, int32_t(mode), &count, nullptr);
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+
+        std::vector<RenderIntent> intents(count);
+        error = mDispatch.getRenderIntents(
+            mDevice, display, int32_t(mode), &count,
+            reinterpret_cast<std::underlying_type<RenderIntent>::type*>(intents.data()));
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+        intents.resize(count);
+
+        *outIntents = std::move(intents);
+        return Error::NONE;
+    }
+
+    Error setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override {
+        if (!mDispatch.setColorModeWithRenderIntent) {
+            if (intent != RenderIntent::COLORIMETRIC) {
+                return Error::UNSUPPORTED;
+            }
+            return setColorMode(display, static_cast<common::V1_0::ColorMode>(mode));
+        }
+
+        int32_t err = mDispatch.setColorModeWithRenderIntent(
+            mDevice, display, static_cast<int32_t>(mode), static_cast<int32_t>(intent));
+        return static_cast<Error>(err);
+    }
+
+    std::array<float, 16> getDataspaceSaturationMatrix(Dataspace dataspace) override {
+        std::array<float, 16> matrix;
+
+        int32_t error = HWC2_ERROR_UNSUPPORTED;
+        if (mDispatch.getDataspaceSaturationMatrix) {
+            error = mDispatch.getDataspaceSaturationMatrix(mDevice, static_cast<int32_t>(dataspace),
+                                                           matrix.data());
+        }
+        if (error != HWC2_ERROR_NONE) {
+            return std::array<float, 16>{
+                1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+                0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+            };
+        }
+
+        return matrix;
+    }
+
    protected:
     template <typename T>
     bool initOptionalDispatch(hwc2_function_descriptor_t desc, T* outPfn) {
@@ -168,7 +247,8 @@
 
         initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_FLOAT_COLOR, &mDispatch.setLayerFloatColor);
 
-        initOptionalDispatch(HWC2_FUNCTION_SET_PER_FRAME_METADATA, &mDispatch.setPerFrameMetadata);
+        initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA,
+                             &mDispatch.setLayerPerFrameMetadata);
         initOptionalDispatch(HWC2_FUNCTION_GET_PER_FRAME_METADATA_KEYS,
                              &mDispatch.getPerFrameMetadataKeys);
 
@@ -178,21 +258,34 @@
         initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_FENCE,
                              &mDispatch.getReadbackBufferFence);
 
+        initOptionalDispatch(HWC2_FUNCTION_GET_RENDER_INTENTS, &mDispatch.getRenderIntents);
+        initOptionalDispatch(HWC2_FUNCTION_SET_COLOR_MODE_WITH_RENDER_INTENT,
+                             &mDispatch.setColorModeWithRenderIntent);
+        initOptionalDispatch(HWC2_FUNCTION_GET_DATASPACE_SATURATION_MATRIX,
+                             &mDispatch.getDataspaceSaturationMatrix);
+
         return true;
     }
 
     struct {
         HWC2_PFN_SET_LAYER_FLOAT_COLOR setLayerFloatColor;
-        HWC2_PFN_SET_PER_FRAME_METADATA setPerFrameMetadata;
+        HWC2_PFN_SET_LAYER_PER_FRAME_METADATA setLayerPerFrameMetadata;
         HWC2_PFN_GET_PER_FRAME_METADATA_KEYS getPerFrameMetadataKeys;
         HWC2_PFN_SET_READBACK_BUFFER setReadbackBuffer;
         HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES getReadbackBufferAttributes;
         HWC2_PFN_GET_READBACK_BUFFER_FENCE getReadbackBufferFence;
+        HWC2_PFN_GET_RENDER_INTENTS getRenderIntents;
+        HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT setColorModeWithRenderIntent;
+        HWC2_PFN_GET_DATASPACE_SATURATION_MATRIX getDataspaceSaturationMatrix;
     } mDispatch = {};
 
    private:
     using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
+    using BaseType2_1::getColorModes;
     using BaseType2_1::mDevice;
+    using BaseType2_1::setColorMode;
+    using BaseType2_1::createVirtualDisplay;
+    using BaseType2_1::getClientTargetSupport;
     using BaseType2_1::setPowerMode;
 };
 
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
index 641fdcb..c6b524d 100644
--- a/graphics/composer/2.2/utils/vts/Android.bp
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -26,10 +26,17 @@
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
     ],
+    export_static_lib_headers: [
+        "android.hardware.graphics.composer@2.1-vts",
+    ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
         "android.hardware.graphics.composer@2.2-command-buffer",
     ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+        "android.hardware.graphics.composer@2.2-command-buffer",
+    ],
     cflags: [
         "-O0",
         "-g",
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index b536f67..357c772 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -87,6 +87,33 @@
                                   });
 }
 
+Display ComposerClient_v2_2::createVirtualDisplay_2_2(uint32_t width, uint32_t height,
+                                                      PixelFormat formatHint,
+                                                      uint32_t outputBufferSlotCount,
+                                                      PixelFormat* outFormat) {
+    Display display = 0;
+    mClient_v2_2->createVirtualDisplay_2_2(
+        width, height, formatHint, outputBufferSlotCount,
+        [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
+            display = tmpDisplay;
+            *outFormat = tmpFormat;
+
+            ASSERT_TRUE(mDisplayResources.insert({display, DisplayResource(true)}).second)
+                << "duplicated virtual display id " << display;
+        });
+
+    return display;
+}
+
+bool ComposerClient_v2_2::getClientTargetSupport_2_2(Display display, uint32_t width,
+                                                     uint32_t height, PixelFormat format,
+                                                     Dataspace dataspace) {
+    Error error =
+        mClient_v2_2->getClientTargetSupport_2_2(display, width, height, format, dataspace);
+    return error == Error::NONE;
+}
+
 void ComposerClient_v2_2::setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode) {
     Error error = mClient_v2_2->setPowerMode_2_2(display, mode);
     ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set power mode";
@@ -119,6 +146,41 @@
     *outFence = 0;
 }
 
+std::vector<ColorMode> ComposerClient_v2_2::getColorModes(Display display) {
+    std::vector<ColorMode> modes;
+    mClient_v2_2->getColorModes_2_2(display, [&](const auto& tmpError, const auto& tmpModes) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get color modes";
+        modes = tmpModes;
+    });
+    return modes;
+}
+
+std::vector<RenderIntent> ComposerClient_v2_2::getRenderIntents(Display display, ColorMode mode) {
+    std::vector<RenderIntent> intents;
+    mClient_v2_2->getRenderIntents(
+        display, mode, [&](const auto& tmpError, const auto& tmpIntents) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to get render intents";
+            intents = tmpIntents;
+        });
+    return intents;
+}
+
+void ComposerClient_v2_2::setColorMode(Display display, ColorMode mode, RenderIntent intent) {
+    Error error = mClient_v2_2->setColorMode_2_2(display, mode, intent);
+    ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set color mode";
+}
+
+std::array<float, 16> ComposerClient_v2_2::getDataspaceSaturationMatrix(Dataspace dataspace) {
+    std::array<float, 16> matrix;
+    mClient_v2_2->getDataspaceSaturationMatrix(
+        dataspace, [&](const auto& tmpError, const auto& tmpMatrix) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to get datasapce saturation matrix";
+            std::copy_n(tmpMatrix.data(), matrix.size(), matrix.begin());
+        });
+
+    return matrix;
+}
+
 }  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index eced69f..62ab83f 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -36,10 +36,11 @@
 namespace V2_2 {
 namespace vts {
 
-using android::hardware::graphics::common::V1_0::ColorMode;
-using android::hardware::graphics::common::V1_0::Dataspace;
 using android::hardware::graphics::common::V1_0::Hdr;
-using android::hardware::graphics::common::V1_0::PixelFormat;
+using android::hardware::graphics::common::V1_1::ColorMode;
+using android::hardware::graphics::common::V1_1::Dataspace;
+using android::hardware::graphics::common::V1_1::PixelFormat;
+using android::hardware::graphics::common::V1_1::RenderIntent;
 using android::hardware::graphics::composer::V2_2::IComposer;
 using android::hardware::graphics::composer::V2_2::IComposerClient;
 
@@ -66,12 +67,22 @@
 
     std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display);
 
+    Display createVirtualDisplay_2_2(uint32_t width, uint32_t height, PixelFormat formatHint,
+                                     uint32_t outputBufferSlotCount, PixelFormat* outFormat);
+    bool getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+                                    PixelFormat format, Dataspace dataspace);
     void setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode);
     void setReadbackBuffer(Display display, const native_handle_t* buffer, int32_t releaseFence);
     void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
                                      Dataspace* outDataspace);
     void getReadbackBufferFence(Display display, int32_t* outFence);
 
+    std::vector<ColorMode> getColorModes(Display display);
+    std::vector<RenderIntent> getRenderIntents(Display display, ColorMode mode);
+    void setColorMode(Display display, ColorMode mode, RenderIntent intent);
+
+    std::array<float, 16> getDataspaceSaturationMatrix(Dataspace dataspace);
+
    private:
     sp<V2_2::IComposerClient> mClient_v2_2;
 };
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 7747900..669fbae 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -27,6 +27,7 @@
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
@@ -34,6 +35,7 @@
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
         "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@2.1-vts",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index c494329..4e41333 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -22,7 +22,7 @@
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
 #include <composer-vts/2.1/TestCommandReader.h>
 #include <composer-vts/2.2/ComposerVts.h>
-#include <mapper-vts/2.0/MapperVts.h>
+#include <mapper-vts/2.1/MapperVts.h>
 
 namespace android {
 namespace hardware {
@@ -33,14 +33,15 @@
 namespace {
 
 using android::hardware::graphics::common::V1_0::BufferUsage;
-using android::hardware::graphics::common::V1_0::ColorMode;
 using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Dataspace;
-using android::hardware::graphics::common::V1_0::PixelFormat;
 using android::hardware::graphics::common::V1_0::Transform;
+using android::hardware::graphics::common::V1_1::ColorMode;
+using android::hardware::graphics::common::V1_1::Dataspace;
+using android::hardware::graphics::common::V1_1::PixelFormat;
+using android::hardware::graphics::common::V1_1::RenderIntent;
 using android::hardware::graphics::composer::V2_2::IComposerClient;
-using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::vts::Gralloc;
+using android::hardware::graphics::mapper::V2_1::IMapper;
+using android::hardware::graphics::mapper::V2_1::vts::Gralloc;
 using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
 
 // Test environment for graphics.composer
@@ -146,9 +147,9 @@
 };
 
 /**
- * Test IComposerClient::Command::SET_PER_FRAME_METADATA.
+ * Test IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA.
  */
-TEST_F(GraphicsComposerHidlCommandTest, SET_PER_FRAME_METADATA) {
+TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PER_FRAME_METADATA) {
     Layer layer;
     ASSERT_NO_FATAL_FAILURE(layer =
                                 mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
@@ -182,7 +183,7 @@
     hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, 78.0});
     hidlMetadata.push_back(
         {IComposerClient::PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, 62.0});
-    mWriter->setPerFrameMetadata(hidlMetadata);
+    mWriter->setLayerPerFrameMetadata(hidlMetadata);
     execute();
 }
 
@@ -192,6 +193,55 @@
 TEST_F(GraphicsComposerHidlTest, GetPerFrameMetadataKeys) {
     mComposerClient->getPerFrameMetadataKeys(mPrimaryDisplay);
 }
+
+/**
+ * Test IComposerClient::createVirtualDisplay_2_2 and
+ * IComposerClient::destroyVirtualDisplay.
+ *
+ * Test that virtual displays can be created and has the correct display type.
+ */
+TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay_2_2) {
+    if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
+        GTEST_SUCCEED() << "no virtual display support";
+        return;
+    }
+
+    Display display;
+    PixelFormat format;
+    ASSERT_NO_FATAL_FAILURE(
+        display = mComposerClient->createVirtualDisplay_2_2(
+            64, 64, PixelFormat::IMPLEMENTATION_DEFINED, kBufferSlotCount, &format));
+
+    // test display type
+    IComposerClient::DisplayType type = mComposerClient->getDisplayType(display);
+    EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type);
+
+    mComposerClient->destroyVirtualDisplay(display);
+}
+
+/**
+ * Test IComposerClient::getClientTargetSupport_2_2.
+ *
+ * Test that IComposerClient::getClientTargetSupport returns true for the
+ * required client targets.
+ */
+TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_2) {
+    std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+    for (auto config : configs) {
+        int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                             IComposerClient::Attribute::WIDTH);
+        int32_t height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                              IComposerClient::Attribute::HEIGHT);
+        ASSERT_LT(0, width);
+        ASSERT_LT(0, height);
+
+        mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+
+        ASSERT_TRUE(mComposerClient->getClientTargetSupport_2_2(
+            mPrimaryDisplay, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN));
+    }
+}
+
 /**
  * Test IComposerClient::setPowerMode_2_2.
  */
@@ -235,6 +285,56 @@
     mWriter->setLayerFloatColor(IComposerClient::FloatColor{0.0, 0.0, 0.0, 0.0});
 }
 
+/**
+ * Test IComposerClient::getDataspaceSaturationMatrix.
+ */
+TEST_F(GraphicsComposerHidlTest, getDataspaceSaturationMatrix) {
+    auto matrix = mComposerClient->getDataspaceSaturationMatrix(Dataspace::SRGB_LINEAR);
+    // the last row is known
+    ASSERT_EQ(0.0f, matrix[12]);
+    ASSERT_EQ(0.0f, matrix[13]);
+    ASSERT_EQ(0.0f, matrix[14]);
+    ASSERT_EQ(1.0f, matrix[15]);
+}
+
+/**
+ * Test IComposerClient::getColorMode_2_2.
+ */
+TEST_F(GraphicsComposerHidlTest, GetColorMode_2_2) {
+    std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+
+    auto nativeMode = std::find(modes.cbegin(), modes.cend(), ColorMode::NATIVE);
+    EXPECT_NE(modes.cend(), nativeMode);
+}
+
+/**
+ * Test IComposerClient::getRenderIntent.
+ */
+TEST_F(GraphicsComposerHidlTest, GetRenderIntent) {
+    std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+    for (auto mode : modes) {
+        std::vector<RenderIntent> intents =
+            mComposerClient->getRenderIntents(mPrimaryDisplay, mode);
+        auto colorimetricIntent =
+            std::find(intents.cbegin(), intents.cend(), RenderIntent::COLORIMETRIC);
+        EXPECT_NE(intents.cend(), colorimetricIntent);
+    }
+}
+
+/**
+ * Test IComposerClient::setColorMode_2_2.
+ */
+TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2) {
+    std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+    for (auto mode : modes) {
+        std::vector<RenderIntent> intents =
+            mComposerClient->getRenderIntents(mPrimaryDisplay, mode);
+        for (auto intent : intents) {
+            mComposerClient->setColorMode(mPrimaryDisplay, mode, intent);
+        }
+    }
+}
+
 }  // namespace
 }  // namespace vts
 }  // namespace V2_2
diff --git a/graphics/mapper/2.1/Android.bp b/graphics/mapper/2.1/Android.bp
index d917e59..8527d3d 100644
--- a/graphics/mapper/2.1/Android.bp
+++ b/graphics/mapper/2.1/Android.bp
@@ -11,6 +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/utils/vts/MapperVts.cpp b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
index 0aaa926..078068e 100644
--- a/graphics/mapper/2.1/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
@@ -43,6 +43,13 @@
                       offsetof(IMapper::BufferDescriptorInfo, usage),
               "");
 
+Gralloc::Gralloc() : V2_0::vts::Gralloc() {
+    if (::testing::Test::HasFatalFailure()) {
+        return;
+    }
+    init();
+}
+
 Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName)
     : V2_0::vts::Gralloc(allocatorServiceName, mapperServiceName) {
     if (::testing::Test::HasFatalFailure()) {
diff --git a/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
index b7fa751..423d4b3 100644
--- a/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
+++ b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
@@ -32,6 +32,7 @@
 // A wrapper to IAllocator and IMapper.
 class Gralloc : public V2_0::vts::Gralloc {
    public:
+    Gralloc();
     Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName);
 
     sp<IMapper> getMapper() const;
diff --git a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
index 3a181a9..fbe5237 100644
--- a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -2918,6 +2918,28 @@
 }
 
 /*
+ * EncryptionOperationsTest.AesEcbWithUserId
+ *
+ * Verifies that AES ECB mode works when Tag::USER_ID is specified.
+ */
+TEST_F(EncryptionOperationsTest, AesEcbWithUserId) {
+    string key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                                           .Authorization(TAG_USER_ID, 0)
+                                           .AesEncryptionKey(key.size() * 8)
+                                           .EcbMode()
+                                           .Padding(PaddingMode::PKCS7),
+                                       KeyFormat::RAW, key));
+
+    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);
+}
+
+/*
  * EncryptionOperationsTest.AesEcbRoundTripSuccess
  *
  * Verifies that AES encryption fails in the correct way when an unauthorized mode is specified.
diff --git a/keymaster/4.0/support/Keymaster.cpp b/keymaster/4.0/support/Keymaster.cpp
index bf52c47..fac0017 100644
--- a/keymaster/4.0/support/Keymaster.cpp
+++ b/keymaster/4.0/support/Keymaster.cpp
@@ -40,7 +40,7 @@
     serviceManager->listByInterface(descriptor, [&](const hidl_vec<hidl_string>& names) {
         for (auto& name : names) {
             if (name == "default") foundDefault = true;
-            auto device = Wrapper::WrappedIKeymasterDevice::getService();
+            auto device = Wrapper::WrappedIKeymasterDevice::getService(name);
             CHECK(device) << "Failed to get service for " << descriptor << " with interface name "
                           << name;
             result.push_back(std::unique_ptr<Keymaster>(new Wrapper(device, name)));
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 9d6501b..ce213bc 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -142,24 +142,28 @@
 DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
 DECLARE_TYPED_TAG(TRUSTED_CONFIRMATION_REQUIRED);
 DECLARE_TYPED_TAG(UNIQUE_ID);
+DECLARE_TYPED_TAG(UNLOCKED_DEVICE_REQUIRED);
 DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
 DECLARE_TYPED_TAG(USER_AUTH_TYPE);
+DECLARE_TYPED_TAG(USER_ID);
 DECLARE_TYPED_TAG(USER_SECURE_ID);
 
 template <typename... Elems>
 struct MetaList {};
 
-using all_tags_t = MetaList<
-    TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
-    TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, TAG_ACTIVE_DATETIME_t,
-    TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t, TAG_MIN_SECONDS_BETWEEN_OPS_t,
-    TAG_MAX_USES_PER_BOOT_t, TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t,
-    TAG_ALLOW_WHILE_ON_BODY_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t,
-    TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t,
-    TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
-    TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t,
-    TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t,
-    TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t>;
+using all_tags_t =
+    MetaList<TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t,
+             TAG_MIN_MAC_LENGTH_t, TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t,
+             TAG_ACTIVE_DATETIME_t, TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
+             TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USER_ID_t,
+             TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t,
+             TAG_ALLOW_WHILE_ON_BODY_t, TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t,
+             TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t,
+             TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t,
+             TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, TAG_ATTESTATION_CHALLENGE_t,
+             TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t,
+             TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t,
+             TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t>;
 
 template <typename TypedTagType>
 struct TypedTag2ValueType;
@@ -343,6 +347,7 @@
         case Tag::BOOTLOADER_ONLY:
         case Tag::NO_AUTH_REQUIRED:
         case Tag::ALLOW_WHILE_ON_BODY:
+        case Tag::UNLOCKED_DEVICE_REQUIRED:
         case Tag::ROLLBACK_RESISTANCE:
         case Tag::RESET_SINCE_ID_ROTATION:
         case Tag::TRUSTED_CONFIRMATION_REQUIRED:
@@ -357,6 +362,7 @@
         case Tag::OS_VERSION:
         case Tag::OS_PATCHLEVEL:
         case Tag::MAC_LENGTH:
+        case Tag::USER_ID:
         case Tag::AUTH_TIMEOUT:
         case Tag::VENDOR_PATCHLEVEL:
         case Tag::BOOT_PATCHLEVEL:
diff --git a/keymaster/4.0/types.hal b/keymaster/4.0/types.hal
index 91ec9bf..47fd1ed 100644
--- a/keymaster/4.0/types.hal
+++ b/keymaster/4.0/types.hal
@@ -118,7 +118,8 @@
                                                        * boot. */
 
     /* User authentication */
-    // 500-501 reserved
+    // 500 reserved
+    USER_ID = TagType:UINT | 501,             /* Android ID of authorized user or authenticator(s), */
     USER_SECURE_ID = TagType:ULONG_REP | 502, /* Secure ID of authorized user or authenticator(s).
                                                * Disallowed if NO_AUTH_REQUIRED is present. */
     NO_AUTH_REQUIRED = TagType:BOOL | 503,    /* If key is usable without authentication. */
@@ -191,6 +192,9 @@
      * match the data described in the token, keymaster must return NO_USER_CONFIRMATION. */
     TRUSTED_CONFIRMATION_REQUIRED = TagType:BOOL | 508,
 
+    UNLOCKED_DEVICE_REQUIRED = TagType:BOOL | 509, /* Require the device screen to be unlocked if
+                                                    * the key is used. */
+
     /* Application access control */
     APPLICATION_ID = TagType:BYTES | 601, /* Byte string identifying the authorized application. */
 
@@ -471,6 +475,7 @@
     PROOF_OF_PRESENCE_REQUIRED = -69,
     CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70,
     NO_USER_CONFIRMATION = -71,
+    DEVICE_LOCKED = -72,
 
     UNIMPLEMENTED = -100,
     VERSION_MISMATCH = -101,
diff --git a/light/2.0/default/android.hardware.light@2.0-service.rc b/light/2.0/default/android.hardware.light@2.0-service.rc
index 68f74c4..b54ca95 100644
--- a/light/2.0/default/android.hardware.light@2.0-service.rc
+++ b/light/2.0/default/android.hardware.light@2.0-service.rc
@@ -3,3 +3,5 @@
     class hal
     user system
     group system
+    # shutting off lights while powering-off
+    shutdown critical
diff --git a/light/utils/main.cpp b/light/utils/main.cpp
index 1f9cb9c..d07e799 100644
--- a/light/utils/main.cpp
+++ b/light/utils/main.cpp
@@ -26,6 +26,7 @@
 }
 
 int main() {
+    using ::android::hardware::hidl_vec;
     using ::android::hardware::light::V2_0::Brightness;
     using ::android::hardware::light::V2_0::Flash;
     using ::android::hardware::light::V2_0::ILight;
@@ -44,9 +45,15 @@
         .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");
-    }
+    service->getSupportedTypes([&](const hidl_vec<Type>& types) {
+        for (Type type : types) {
+            Status ret = service->setLight(type, off);
+            if (ret != Status::SUCCESS) {
+                error("Failed to shut off screen for type " +
+                      std::to_string(static_cast<int>(type)));
+            }
+        }
+    });
+
     return 0;
 }
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
index 8779723..c97a00b 100644
--- a/neuralnetworks/1.0/types.hal
+++ b/neuralnetworks/1.0/types.hal
@@ -84,6 +84,7 @@
      *     output.dimension = {5, 4, 3, 2}
      *
      * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
      * Supported tensor rank: up to 4
      *
      * Inputs:
@@ -645,6 +646,7 @@
      * input operands. It starts with the trailing dimensions, and works its way forward.
      *
      * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
      * Supported tensor rank: up to 4
      *
      * Inputs:
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 54dd14a..e28113b 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -18,7 +18,6 @@
     name: "VtsHalNeuralnetworksTest_utils",
     srcs: [
         "Callbacks.cpp",
-        "Models.cpp",
         "GeneratedTestHarness.cpp",
     ],
     defaults: ["VtsHalTargetTestDefaults"],
@@ -41,14 +40,17 @@
 cc_test {
     name: "VtsHalNeuralnetworksV1_0TargetTest",
     srcs: [
-        "VtsHalNeuralnetworksV1_0.cpp",
-        "VtsHalNeuralnetworksV1_0BasicTest.cpp",
-        "VtsHalNeuralnetworksV1_0GeneratedTest.cpp",
+        "BasicTests.cpp",
+        "GeneratedTests.cpp",
+        "ValidateModel.cpp",
+        "ValidateRequest.cpp",
+        "ValidationTests.cpp",
+        "VtsHalNeuralnetworks.cpp",
     ],
     defaults: ["VtsHalTargetTestDefaults"],
     static_libs: [
-        "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
+        "android.hardware.neuralnetworks@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "libhidlmemory",
diff --git a/neuralnetworks/1.0/vts/functional/BasicTests.cpp b/neuralnetworks/1.0/vts/functional/BasicTests.cpp
new file mode 100644
index 0000000..945c406
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/BasicTests.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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 "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+// create device test
+TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
+
+// status test
+TEST_F(NeuralnetworksHidlTest, StatusTest) {
+    Return<DeviceStatus> status = device->getStatus();
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
+}
+
+// initialization
+TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
+    Return<void> ret =
+        device->getCapabilities([](ErrorStatus status, const Capabilities& capabilities) {
+            EXPECT_EQ(ErrorStatus::NONE, status);
+            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.h b/neuralnetworks/1.0/vts/functional/Callbacks.h
index 0e2ffb3..2ac6130 100644
--- a/neuralnetworks/1.0/vts/functional/Callbacks.h
+++ b/neuralnetworks/1.0/vts/functional/Callbacks.h
@@ -17,14 +17,6 @@
 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;
-
 /**
  * The CallbackBase class is used internally by the NeuralNetworks runtime to
  * synchronize between different threads. An asynchronous task is launched
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index 8646a4c..4f9d528 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -179,7 +179,7 @@
     }
 }
 
-void Execute(sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
+void Execute(const sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
              std::function<bool(int)> is_ignored,
              const std::vector<MixedTypedExampleType>& examples) {
     V1_0::Model model = create_model();
@@ -223,7 +223,7 @@
     EvaluatePreparedModel(preparedModel, is_ignored, examples);
 }
 
-void Execute(sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
+void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
              std::function<bool(int)> is_ignored,
              const std::vector<MixedTypedExampleType>& examples) {
     V1_1::Model model = create_model();
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0GeneratedTest.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
similarity index 61%
rename from neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0GeneratedTest.cpp
rename to neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
index b99aef7..2107333 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0GeneratedTest.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
@@ -16,47 +16,33 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworksV1_0.h"
+#include "VtsHalNeuralnetworks.h"
 
 #include "Callbacks.h"
 #include "TestHarness.h"
+#include "Utils.h"
 
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
-using ::android::hardware::neuralnetworks::V1_0::IDevice;
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::Capabilities;
-using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
-using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
-using ::android::hardware::neuralnetworks::V1_0::Model;
-using ::android::hardware::neuralnetworks::V1_0::OperationType;
-using ::android::hardware::neuralnetworks::V1_0::PerformanceInfo;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
 
 namespace generated_tests {
 using ::generated_tests::MixedTypedExampleType;
-extern void Execute(sp<IDevice>&, std::function<Model(void)>, std::function<bool(int)>,
-                    const std::vector<MixedTypedExampleType>&);
+extern void Execute(const sp<V1_0::IDevice>&, std::function<V1_0::Model(void)>,
+                    std::function<bool(int)>, const std::vector<MixedTypedExampleType>&);
 }  // namespace generated_tests
 
 namespace V1_0 {
 namespace vts {
 namespace functional {
+
 using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
 using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::nn::allocateSharedMemory;
 
 // Mixed-typed examples
 typedef generated_tests::MixedTypedExampleType MixedTypedExample;
diff --git a/neuralnetworks/1.0/vts/functional/Models.cpp b/neuralnetworks/1.0/vts/functional/Models.cpp
deleted file mode 100644
index 180286a..0000000
--- a/neuralnetworks/1.0/vts/functional/Models.cpp
+++ /dev/null
@@ -1,202 +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.
- */
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "Models.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-#include <android/hidl/allocator/1.0/IAllocator.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-#include <vector>
-
-using ::android::sp;
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-
-// create a valid model
-V1_1::Model createValidTestModel_1_1() {
-    const std::vector<float> operand2Data = {5.0f, 6.0f, 7.0f, 8.0f};
-    const uint32_t size = operand2Data.size() * sizeof(float);
-
-    const uint32_t operand1 = 0;
-    const uint32_t operand2 = 1;
-    const uint32_t operand3 = 2;
-    const uint32_t operand4 = 3;
-
-    const std::vector<Operand> operands = {
-        {
-            .type = OperandType::TENSOR_FLOAT32,
-            .dimensions = {1, 2, 2, 1},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::MODEL_INPUT,
-            .location = {.poolIndex = 0, .offset = 0, .length = 0},
-        },
-        {
-            .type = OperandType::TENSOR_FLOAT32,
-            .dimensions = {1, 2, 2, 1},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 0, .length = size},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = size, .length = sizeof(int32_t)},
-        },
-        {
-            .type = OperandType::TENSOR_FLOAT32,
-            .dimensions = {1, 2, 2, 1},
-            .numberOfConsumers = 0,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::MODEL_OUTPUT,
-            .location = {.poolIndex = 0, .offset = 0, .length = 0},
-        },
-    };
-
-    const std::vector<Operation> operations = {{
-        .type = OperationType::ADD, .inputs = {operand1, operand2, operand3}, .outputs = {operand4},
-    }};
-
-    const std::vector<uint32_t> inputIndexes = {operand1};
-    const std::vector<uint32_t> outputIndexes = {operand4};
-    std::vector<uint8_t> operandValues(
-        reinterpret_cast<const uint8_t*>(operand2Data.data()),
-        reinterpret_cast<const uint8_t*>(operand2Data.data()) + size);
-    int32_t activation[1] = {static_cast<int32_t>(FusedActivationFunc::NONE)};
-    operandValues.insert(operandValues.end(), reinterpret_cast<const uint8_t*>(&activation[0]),
-                         reinterpret_cast<const uint8_t*>(&activation[1]));
-
-    const std::vector<hidl_memory> pools = {};
-
-    return {
-        .operands = operands,
-        .operations = operations,
-        .inputIndexes = inputIndexes,
-        .outputIndexes = outputIndexes,
-        .operandValues = operandValues,
-        .pools = pools,
-    };
-}
-
-// create first invalid model
-V1_1::Model createInvalidTestModel1_1_1() {
-    Model model = createValidTestModel_1_1();
-    model.operations[0].type = static_cast<OperationType>(0xDEADBEEF); /* INVALID */
-    return model;
-}
-
-// create second invalid model
-V1_1::Model createInvalidTestModel2_1_1() {
-    Model model = createValidTestModel_1_1();
-    const uint32_t operand1 = 0;
-    const uint32_t operand5 = 4;  // INVALID OPERAND
-    model.inputIndexes = std::vector<uint32_t>({operand1, operand5 /* INVALID OPERAND */});
-    return model;
-}
-
-V1_0::Model createValidTestModel_1_0() {
-    V1_1::Model model = createValidTestModel_1_1();
-    return nn::convertToV1_0(model);
-}
-
-V1_0::Model createInvalidTestModel1_1_0() {
-    V1_1::Model model = createInvalidTestModel1_1_1();
-    return nn::convertToV1_0(model);
-}
-
-V1_0::Model createInvalidTestModel2_1_0() {
-    V1_1::Model model = createInvalidTestModel2_1_1();
-    return nn::convertToV1_0(model);
-}
-
-// create a valid request
-Request createValidTestRequest() {
-    std::vector<float> inputData = {1.0f, 2.0f, 3.0f, 4.0f};
-    std::vector<float> outputData = {-1.0f, -1.0f, -1.0f, -1.0f};
-    const uint32_t INPUT = 0;
-    const uint32_t OUTPUT = 1;
-
-    // prepare inputs
-    uint32_t inputSize = static_cast<uint32_t>(inputData.size() * sizeof(float));
-    uint32_t outputSize = static_cast<uint32_t>(outputData.size() * sizeof(float));
-    std::vector<RequestArgument> inputs = {{
-        .location = {.poolIndex = INPUT, .offset = 0, .length = inputSize}, .dimensions = {},
-    }};
-    std::vector<RequestArgument> outputs = {{
-        .location = {.poolIndex = OUTPUT, .offset = 0, .length = outputSize}, .dimensions = {},
-    }};
-    std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
-                                      nn::allocateSharedMemory(outputSize)};
-    if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
-        return {};
-    }
-
-    // load data
-    sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
-    sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
-    if (inputMemory.get() == nullptr || outputMemory.get() == nullptr) {
-        return {};
-    }
-    float* inputPtr = reinterpret_cast<float*>(static_cast<void*>(inputMemory->getPointer()));
-    float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer()));
-    if (inputPtr == nullptr || outputPtr == nullptr) {
-        return {};
-    }
-    inputMemory->update();
-    outputMemory->update();
-    std::copy(inputData.begin(), inputData.end(), inputPtr);
-    std::copy(outputData.begin(), outputData.end(), outputPtr);
-    inputMemory->commit();
-    outputMemory->commit();
-
-    return {.inputs = inputs, .outputs = outputs, .pools = pools};
-}
-
-// create first invalid request
-Request createInvalidTestRequest1() {
-    Request request = createValidTestRequest();
-    const uint32_t INVALID = 2;
-    std::vector<float> inputData = {1.0f, 2.0f, 3.0f, 4.0f};
-    uint32_t inputSize = static_cast<uint32_t>(inputData.size() * sizeof(float));
-    request.inputs[0].location = {
-        .poolIndex = INVALID /* INVALID */, .offset = 0, .length = inputSize};
-    return request;
-}
-
-// create second invalid request
-Request createInvalidTestRequest2() {
-    Request request = createValidTestRequest();
-    request.inputs[0].dimensions = std::vector<uint32_t>({1, 2, 3, 4, 5, 6, 7, 8} /* INVALID */);
-    return request;
-}
-
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Models.h b/neuralnetworks/1.0/vts/functional/Models.h
index 9398235..a1fbe92 100644
--- a/neuralnetworks/1.0/vts/functional/Models.h
+++ b/neuralnetworks/1.0/vts/functional/Models.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,29 +14,187 @@
  * limitations under the License.
  */
 
+#ifndef VTS_HAL_NEURALNETWORKS_V1_0_VTS_FUNCTIONAL_MODELS_H
+#define VTS_HAL_NEURALNETWORKS_V1_0_VTS_FUNCTIONAL_MODELS_H
+
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include <android/hardware/neuralnetworks/1.1/types.h>
+#include "TestHarness.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
 
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
 
-// create V1_1 model
-V1_1::Model createValidTestModel_1_1();
-V1_1::Model createInvalidTestModel1_1_1();
-V1_1::Model createInvalidTestModel2_1_1();
+using MixedTypedExample = generated_tests::MixedTypedExampleType;
 
-// create V1_0 model
-V1_0::Model createValidTestModel_1_0();
-V1_0::Model createInvalidTestModel1_1_0();
-V1_0::Model createInvalidTestModel2_1_0();
+#define FOR_EACH_TEST_MODEL(FN)                          \
+    FN(add_broadcast_quant8)                             \
+    FN(add)                                              \
+    FN(add_quant8)                                       \
+    FN(avg_pool_float_1)                                 \
+    FN(avg_pool_float_2)                                 \
+    FN(avg_pool_float_3)                                 \
+    FN(avg_pool_float_4)                                 \
+    FN(avg_pool_float_5)                                 \
+    FN(avg_pool_quant8_1)                                \
+    FN(avg_pool_quant8_2)                                \
+    FN(avg_pool_quant8_3)                                \
+    FN(avg_pool_quant8_4)                                \
+    FN(avg_pool_quant8_5)                                \
+    FN(concat_float_1)                                   \
+    FN(concat_float_2)                                   \
+    FN(concat_float_3)                                   \
+    FN(concat_quant8_1)                                  \
+    FN(concat_quant8_2)                                  \
+    FN(concat_quant8_3)                                  \
+    FN(conv_1_h3_w2_SAME)                                \
+    FN(conv_1_h3_w2_VALID)                               \
+    FN(conv_3_h3_w2_SAME)                                \
+    FN(conv_3_h3_w2_VALID)                               \
+    FN(conv_float_2)                                     \
+    FN(conv_float_channels)                              \
+    FN(conv_float_channels_weights_as_inputs)            \
+    FN(conv_float_large)                                 \
+    FN(conv_float_large_weights_as_inputs)               \
+    FN(conv_float)                                       \
+    FN(conv_float_weights_as_inputs)                     \
+    FN(conv_quant8_2)                                    \
+    FN(conv_quant8_channels)                             \
+    FN(conv_quant8_channels_weights_as_inputs)           \
+    FN(conv_quant8_large)                                \
+    FN(conv_quant8_large_weights_as_inputs)              \
+    FN(conv_quant8)                                      \
+    FN(conv_quant8_overflow)                             \
+    FN(conv_quant8_overflow_weights_as_inputs)           \
+    FN(conv_quant8_weights_as_inputs)                    \
+    FN(depth_to_space_float_1)                           \
+    FN(depth_to_space_float_2)                           \
+    FN(depth_to_space_float_3)                           \
+    FN(depth_to_space_quant8_1)                          \
+    FN(depth_to_space_quant8_2)                          \
+    FN(depthwise_conv2d_float_2)                         \
+    FN(depthwise_conv2d_float_large_2)                   \
+    FN(depthwise_conv2d_float_large_2_weights_as_inputs) \
+    FN(depthwise_conv2d_float_large)                     \
+    FN(depthwise_conv2d_float_large_weights_as_inputs)   \
+    FN(depthwise_conv2d_float)                           \
+    FN(depthwise_conv2d_float_weights_as_inputs)         \
+    FN(depthwise_conv2d_quant8_2)                        \
+    FN(depthwise_conv2d_quant8_large)                    \
+    FN(depthwise_conv2d_quant8_large_weights_as_inputs)  \
+    FN(depthwise_conv2d_quant8)                          \
+    FN(depthwise_conv2d_quant8_weights_as_inputs)        \
+    FN(depthwise_conv)                                   \
+    FN(dequantize)                                       \
+    FN(embedding_lookup)                                 \
+    FN(floor)                                            \
+    FN(fully_connected_float_2)                          \
+    FN(fully_connected_float_large)                      \
+    FN(fully_connected_float_large_weights_as_inputs)    \
+    FN(fully_connected_float)                            \
+    FN(fully_connected_float_weights_as_inputs)          \
+    FN(fully_connected_quant8_2)                         \
+    FN(fully_connected_quant8_large)                     \
+    FN(fully_connected_quant8_large_weights_as_inputs)   \
+    FN(fully_connected_quant8)                           \
+    FN(fully_connected_quant8_weights_as_inputs)         \
+    FN(hashtable_lookup_float)                           \
+    FN(hashtable_lookup_quant8)                          \
+    FN(l2_normalization_2)                               \
+    FN(l2_normalization_large)                           \
+    FN(l2_normalization)                                 \
+    FN(l2_pool_float_2)                                  \
+    FN(l2_pool_float_large)                              \
+    FN(l2_pool_float)                                    \
+    FN(local_response_norm_float_1)                      \
+    FN(local_response_norm_float_2)                      \
+    FN(local_response_norm_float_3)                      \
+    FN(local_response_norm_float_4)                      \
+    FN(logistic_float_1)                                 \
+    FN(logistic_float_2)                                 \
+    FN(logistic_quant8_1)                                \
+    FN(logistic_quant8_2)                                \
+    FN(lsh_projection_2)                                 \
+    FN(lsh_projection)                                   \
+    FN(lsh_projection_weights_as_inputs)                 \
+    FN(lstm2)                                            \
+    FN(lstm2_state2)                                     \
+    FN(lstm2_state)                                      \
+    FN(lstm3)                                            \
+    FN(lstm3_state2)                                     \
+    FN(lstm3_state3)                                     \
+    FN(lstm3_state)                                      \
+    FN(lstm)                                             \
+    FN(lstm_state2)                                      \
+    FN(lstm_state)                                       \
+    FN(max_pool_float_1)                                 \
+    FN(max_pool_float_2)                                 \
+    FN(max_pool_float_3)                                 \
+    FN(max_pool_float_4)                                 \
+    FN(max_pool_quant8_1)                                \
+    FN(max_pool_quant8_2)                                \
+    FN(max_pool_quant8_3)                                \
+    FN(max_pool_quant8_4)                                \
+    FN(mobilenet_224_gender_basic_fixed)                 \
+    FN(mobilenet_quantized)                              \
+    FN(mul_broadcast_quant8)                             \
+    FN(mul)                                              \
+    FN(mul_quant8)                                       \
+    FN(mul_relu)                                         \
+    FN(relu1_float_1)                                    \
+    FN(relu1_float_2)                                    \
+    FN(relu1_quant8_1)                                   \
+    FN(relu1_quant8_2)                                   \
+    FN(relu6_float_1)                                    \
+    FN(relu6_float_2)                                    \
+    FN(relu6_quant8_1)                                   \
+    FN(relu6_quant8_2)                                   \
+    FN(relu_float_1)                                     \
+    FN(relu_float_2)                                     \
+    FN(relu_quant8_1)                                    \
+    FN(relu_quant8_2)                                    \
+    FN(reshape)                                          \
+    FN(reshape_quant8)                                   \
+    FN(reshape_quant8_weights_as_inputs)                 \
+    FN(reshape_weights_as_inputs)                        \
+    FN(resize_bilinear_2)                                \
+    FN(resize_bilinear)                                  \
+    FN(rnn)                                              \
+    FN(rnn_state)                                        \
+    FN(softmax_float_1)                                  \
+    FN(softmax_float_2)                                  \
+    FN(softmax_quant8_1)                                 \
+    FN(softmax_quant8_2)                                 \
+    FN(space_to_depth_float_1)                           \
+    FN(space_to_depth_float_2)                           \
+    FN(space_to_depth_float_3)                           \
+    FN(space_to_depth_quant8_1)                          \
+    FN(space_to_depth_quant8_2)                          \
+    FN(svdf2)                                            \
+    FN(svdf)                                             \
+    FN(svdf_state)                                       \
+    FN(tanh)
 
-// create the request
-V1_0::Request createValidTestRequest();
-V1_0::Request createInvalidTestRequest1();
-V1_0::Request createInvalidTestRequest2();
+#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \
+    namespace function {                            \
+    extern std::vector<MixedTypedExample> examples; \
+    Model createTestModel();                        \
+    }
 
+FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS)
+
+#undef FORWARD_DECLARE_GENERATED_OBJECTS
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
+
+#endif  // VTS_HAL_NEURALNETWORKS_V1_0_VTS_FUNCTIONAL_MODELS_H
diff --git a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
new file mode 100644
index 0000000..4f0697e
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
@@ -0,0 +1,506 @@
+/*
+ * 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 "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+
+///////////////////////// UTILITY FUNCTIONS /////////////////////////
+
+static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
+                                           const V1_0::Model& model) {
+    SCOPED_TRACE(message + " [getSupportedOperations]");
+
+    Return<void> ret =
+        device->getSupportedOperations(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
+            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+static void validatePrepareModel(const sp<IDevice>& device, const std::string& message,
+                                 const V1_0::Model& model) {
+    SCOPED_TRACE(message + " [prepareModel]");
+
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    ASSERT_EQ(nullptr, preparedModel.get());
+}
+
+// Primary validation function. This function will take a valid model, apply a
+// mutation to it to invalidate the model, then pass it to interface calls that
+// use the model. Note that the model here is passed by value, and any mutation
+// to the model does not leave this function.
+static void validate(const sp<IDevice>& device, const std::string& message, V1_0::Model model,
+                     const std::function<void(Model*)>& mutation) {
+    mutation(&model);
+    validateGetSupportedOperations(device, message, model);
+    validatePrepareModel(device, message, model);
+}
+
+// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
+// so this is efficiently accomplished by moving the element to the end and
+// resizing the hidl_vec to one less.
+template <typename Type>
+static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
+    if (vec) {
+        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
+        vec->resize(vec->size() - 1);
+    }
+}
+
+template <typename Type>
+static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
+    // assume vec is valid
+    const uint32_t index = vec->size();
+    vec->resize(index + 1);
+    (*vec)[index] = value;
+    return index;
+}
+
+static uint32_t addOperand(Model* model) {
+    return hidl_vec_push_back(&model->operands,
+                              {
+                                  .type = OperandType::INT32,
+                                  .dimensions = {},
+                                  .numberOfConsumers = 0,
+                                  .scale = 0.0f,
+                                  .zeroPoint = 0,
+                                  .lifetime = OperandLifeTime::MODEL_INPUT,
+                                  .location = {.poolIndex = 0, .offset = 0, .length = 0},
+                              });
+}
+
+static uint32_t addOperand(Model* model, OperandLifeTime lifetime) {
+    uint32_t index = addOperand(model);
+    model->operands[index].numberOfConsumers = 1;
+    model->operands[index].lifetime = lifetime;
+    return index;
+}
+
+///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
+
+static const int32_t invalidOperandTypes[] = {
+    static_cast<int32_t>(OperandType::FLOAT32) - 1,              // lower bound fundamental
+    static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1,  // upper bound fundamental
+    static_cast<int32_t>(OperandType::OEM) - 1,                  // lower bound OEM
+    static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,      // upper bound OEM
+};
+
+static void mutateOperandTypeTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        for (int32_t invalidOperandType : invalidOperandTypes) {
+            const std::string message = "mutateOperandTypeTest: operand " +
+                                        std::to_string(operand) + " set to value " +
+                                        std::to_string(invalidOperandType);
+            validate(device, message, model, [operand, invalidOperandType](Model* model) {
+                model->operands[operand].type = static_cast<OperandType>(invalidOperandType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE OPERAND RANK /////////////////////////
+
+static uint32_t getInvalidRank(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+            return 1;
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return 0;
+        default:
+            return 0;
+    }
+}
+
+static void mutateOperandRankTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const uint32_t invalidRank = getInvalidRank(model.operands[operand].type);
+        const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
+                                    " has rank of " + std::to_string(invalidRank);
+        validate(device, message, model, [operand, invalidRank](Model* model) {
+            model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
+        });
+    }
+}
+
+///////////////////////// VALIDATE OPERAND SCALE /////////////////////////
+
+static float getInvalidScale(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+        case OperandType::TENSOR_FLOAT32:
+            return 1.0f;
+        case OperandType::TENSOR_INT32:
+            return -1.0f;
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return 0.0f;
+        default:
+            return 0.0f;
+    }
+}
+
+static void mutateOperandScaleTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const float invalidScale = getInvalidScale(model.operands[operand].type);
+        const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
+                                    " has scale of " + std::to_string(invalidScale);
+        validate(device, message, model, [operand, invalidScale](Model* model) {
+            model->operands[operand].scale = invalidScale;
+        });
+    }
+}
+
+///////////////////////// VALIDATE OPERAND ZERO POINT /////////////////////////
+
+static std::vector<int32_t> getInvalidZeroPoints(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+            return {1};
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return {-1, 256};
+        default:
+            return {};
+    }
+}
+
+static void mutateOperandZeroPointTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const std::vector<int32_t> invalidZeroPoints =
+            getInvalidZeroPoints(model.operands[operand].type);
+        for (int32_t invalidZeroPoint : invalidZeroPoints) {
+            const std::string message = "mutateOperandZeroPointTest: operand " +
+                                        std::to_string(operand) + " has zero point of " +
+                                        std::to_string(invalidZeroPoint);
+            validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
+                model->operands[operand].zeroPoint = invalidZeroPoint;
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE EXTRA ??? /////////////////////////
+
+// TODO: Operand::lifetime
+// TODO: Operand::location
+
+///////////////////////// VALIDATE OPERATION OPERAND TYPE /////////////////////////
+
+static void mutateOperand(Operand* operand, OperandType type) {
+    Operand newOperand = *operand;
+    newOperand.type = type;
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+            newOperand.dimensions = hidl_vec<uint32_t>();
+            newOperand.scale = 0.0f;
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_FLOAT32:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.scale = 0.0f;
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_INT32:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
+            break;
+        case OperandType::OEM:
+        case OperandType::TENSOR_OEM_BYTE:
+        default:
+            break;
+    }
+    *operand = newOperand;
+}
+
+static bool mutateOperationOperandTypeSkip(size_t operand, const V1_0::Model& model) {
+    // LSH_PROJECTION's second argument is allowed to have any type. This is the
+    // only operation that currently has a type that can be anything independent
+    // from any other type. Changing the operand type to any other type will
+    // result in a valid model for LSH_PROJECTION. If this is the case, skip the
+    // test.
+    for (const Operation& operation : model.operations) {
+        if (operation.type == OperationType::LSH_PROJECTION && operand == operation.inputs[1]) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static void mutateOperationOperandTypeTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        if (mutateOperationOperandTypeSkip(operand, model)) {
+            continue;
+        }
+        for (OperandType invalidOperandType : hidl_enum_iterator<OperandType>{}) {
+            // Do not test OEM types
+            if (invalidOperandType == model.operands[operand].type ||
+                invalidOperandType == OperandType::OEM ||
+                invalidOperandType == OperandType::TENSOR_OEM_BYTE) {
+                continue;
+            }
+            const std::string message = "mutateOperationOperandTypeTest: operand " +
+                                        std::to_string(operand) + " set to type " +
+                                        toString(invalidOperandType);
+            validate(device, message, model, [operand, invalidOperandType](Model* model) {
+                mutateOperand(&model->operands[operand], invalidOperandType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION TYPE /////////////////////////
+
+static const int32_t invalidOperationTypes[] = {
+    static_cast<int32_t>(OperationType::ADD) - 1,            // lower bound fundamental
+    static_cast<int32_t>(OperationType::TANH) + 1,           // upper bound fundamental
+    static_cast<int32_t>(OperationType::OEM_OPERATION) - 1,  // lower bound OEM
+    static_cast<int32_t>(OperationType::OEM_OPERATION) + 1,  // upper bound OEM
+};
+
+static void mutateOperationTypeTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (int32_t invalidOperationType : invalidOperationTypes) {
+            const std::string message = "mutateOperationTypeTest: operation " +
+                                        std::to_string(operation) + " set to value " +
+                                        std::to_string(invalidOperationType);
+            validate(device, message, model, [operation, invalidOperationType](Model* model) {
+                model->operations[operation].type =
+                    static_cast<OperationType>(invalidOperationType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION INPUT OPERAND INDEX /////////////////////////
+
+static void mutateOperationInputOperandIndexTest(const sp<IDevice>& device,
+                                                 const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const uint32_t invalidOperand = model.operands.size();
+        for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
+            const std::string message = "mutateOperationInputOperandIndexTest: operation " +
+                                        std::to_string(operation) + " input " +
+                                        std::to_string(input);
+            validate(device, message, model, [operation, input, invalidOperand](Model* model) {
+                model->operations[operation].inputs[input] = invalidOperand;
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION OUTPUT OPERAND INDEX /////////////////////////
+
+static void mutateOperationOutputOperandIndexTest(const sp<IDevice>& device,
+                                                  const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const uint32_t invalidOperand = model.operands.size();
+        for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
+            const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
+                                        std::to_string(operation) + " output " +
+                                        std::to_string(output);
+            validate(device, message, model, [operation, output, invalidOperand](Model* model) {
+                model->operations[operation].outputs[output] = invalidOperand;
+            });
+        }
+    }
+}
+
+///////////////////////// REMOVE OPERAND FROM EVERYTHING /////////////////////////
+
+static void removeValueAndDecrementGreaterValues(hidl_vec<uint32_t>* vec, uint32_t value) {
+    if (vec) {
+        // remove elements matching "value"
+        auto last = std::remove(vec->begin(), vec->end(), value);
+        vec->resize(std::distance(vec->begin(), last));
+
+        // decrement elements exceeding "value"
+        std::transform(vec->begin(), vec->end(), vec->begin(),
+                       [value](uint32_t v) { return v > value ? v-- : v; });
+    }
+}
+
+static void removeOperand(Model* model, uint32_t index) {
+    hidl_vec_removeAt(&model->operands, index);
+    for (Operation& operation : model->operations) {
+        removeValueAndDecrementGreaterValues(&operation.inputs, index);
+        removeValueAndDecrementGreaterValues(&operation.outputs, index);
+    }
+    removeValueAndDecrementGreaterValues(&model->inputIndexes, index);
+    removeValueAndDecrementGreaterValues(&model->outputIndexes, index);
+}
+
+static void removeOperandTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const std::string message = "removeOperandTest: operand " + std::to_string(operand);
+        validate(device, message, model,
+                 [operand](Model* model) { removeOperand(model, operand); });
+    }
+}
+
+///////////////////////// REMOVE OPERATION /////////////////////////
+
+static void removeOperation(Model* model, uint32_t index) {
+    for (uint32_t operand : model->operations[index].inputs) {
+        model->operands[operand].numberOfConsumers--;
+    }
+    hidl_vec_removeAt(&model->operations, index);
+}
+
+static void removeOperationTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message = "removeOperationTest: operation " + std::to_string(operation);
+        validate(device, message, model,
+                 [operation](Model* model) { removeOperation(model, operation); });
+    }
+}
+
+///////////////////////// REMOVE OPERATION INPUT /////////////////////////
+
+static void removeOperationInputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
+            const V1_0::Operation& op = model.operations[operation];
+            // CONCATENATION has at least 2 inputs, with the last element being
+            // INT32. Skip this test if removing one of CONCATENATION's
+            // inputs still produces a valid model.
+            if (op.type == V1_0::OperationType::CONCATENATION && op.inputs.size() > 2 &&
+                input != op.inputs.size() - 1) {
+                continue;
+            }
+            const std::string message = "removeOperationInputTest: operation " +
+                                        std::to_string(operation) + ", input " +
+                                        std::to_string(input);
+            validate(device, message, model, [operation, input](Model* model) {
+                uint32_t operand = model->operations[operation].inputs[input];
+                model->operands[operand].numberOfConsumers--;
+                hidl_vec_removeAt(&model->operations[operation].inputs, input);
+            });
+        }
+    }
+}
+
+///////////////////////// REMOVE OPERATION OUTPUT /////////////////////////
+
+static void removeOperationOutputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
+            const std::string message = "removeOperationOutputTest: operation " +
+                                        std::to_string(operation) + ", output " +
+                                        std::to_string(output);
+            validate(device, message, model, [operation, output](Model* model) {
+                hidl_vec_removeAt(&model->operations[operation].outputs, output);
+            });
+        }
+    }
+}
+
+///////////////////////// MODEL VALIDATION /////////////////////////
+
+// TODO: remove model input
+// TODO: remove model output
+// TODO: add unused operation
+
+///////////////////////// ADD OPERATION INPUT /////////////////////////
+
+static void addOperationInputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
+        validate(device, message, model, [operation](Model* model) {
+            uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT);
+            hidl_vec_push_back(&model->operations[operation].inputs, index);
+            hidl_vec_push_back(&model->inputIndexes, index);
+        });
+    }
+}
+
+///////////////////////// ADD OPERATION OUTPUT /////////////////////////
+
+static void addOperationOutputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message =
+            "addOperationOutputTest: operation " + std::to_string(operation);
+        validate(device, message, model, [operation](Model* model) {
+            uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
+            hidl_vec_push_back(&model->operations[operation].outputs, index);
+            hidl_vec_push_back(&model->outputIndexes, index);
+        });
+    }
+}
+
+////////////////////////// ENTRY POINT //////////////////////////////
+
+void ValidationTest::validateModel(const V1_0::Model& model) {
+    mutateOperandTypeTest(device, model);
+    mutateOperandRankTest(device, model);
+    mutateOperandScaleTest(device, model);
+    mutateOperandZeroPointTest(device, model);
+    mutateOperationOperandTypeTest(device, model);
+    mutateOperationTypeTest(device, model);
+    mutateOperationInputOperandIndexTest(device, model);
+    mutateOperationOutputOperandIndexTest(device, model);
+    removeOperandTest(device, model);
+    removeOperationTest(device, model);
+    removeOperationInputTest(device, model);
+    removeOperationOutputTest(device, model);
+    addOperationInputTest(device, model);
+    addOperationOutputTest(device, model);
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
new file mode 100644
index 0000000..08f2613
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
@@ -0,0 +1,261 @@
+/*
+ * 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 "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+#include "TestHarness.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hidl::memory::V1_0::IMemory;
+using generated_tests::MixedTyped;
+using generated_tests::MixedTypedExampleType;
+using generated_tests::for_all;
+
+///////////////////////// UTILITY FUNCTIONS /////////////////////////
+
+static void createPreparedModel(const sp<IDevice>& device, const V1_0::Model& model,
+                                sp<IPreparedModel>* preparedModel) {
+    ASSERT_NE(nullptr, preparedModel);
+
+    // see if service can handle model
+    bool fullySupportsModel = false;
+    Return<void> supportedOpsLaunchStatus = device->getSupportedOperations(
+        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
+            ASSERT_EQ(ErrorStatus::NONE, status);
+            ASSERT_NE(0ul, supported.size());
+            fullySupportsModel =
+                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
+        });
+    ASSERT_TRUE(supportedOpsLaunchStatus.isOk());
+
+    // launch prepare model
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    // retrieve prepared model
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    *preparedModel = preparedModelCallback->getPreparedModel();
+
+    // The getSupportedOperations call returns a list of operations that are
+    // guaranteed not to fail if prepareModel is called, and
+    // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed.
+    // If a driver has any doubt that it can prepare an operation, it must
+    // return false. So here, if a driver isn't sure if it can support an
+    // operation, but reports that it successfully prepared the model, the test
+    // can continue.
+    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
+        ASSERT_EQ(nullptr, preparedModel->get());
+        LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot "
+                     "prepare model that it does not support.";
+        std::cout << "[          ]   Unable to test Request validation because vendor service "
+                     "cannot prepare model that it does not support."
+                  << std::endl;
+        return;
+    }
+    ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+    ASSERT_NE(nullptr, preparedModel->get());
+}
+
+// Primary validation function. This function will take a valid request, apply a
+// mutation to it to invalidate the request, then pass it to interface calls
+// that use the request. Note that the request here is passed by value, and any
+// mutation to the request does not leave this function.
+static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
+                     Request request, const std::function<void(Request*)>& mutation) {
+    mutation(&request);
+    SCOPED_TRACE(message + " [execute]");
+
+    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+    ASSERT_NE(nullptr, executionCallback.get());
+    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
+    ASSERT_TRUE(executeLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
+
+    executionCallback->wait();
+    ErrorStatus executionReturnStatus = executionCallback->getStatus();
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
+}
+
+// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
+// so this is efficiently accomplished by moving the element to the end and
+// resizing the hidl_vec to one less.
+template <typename Type>
+static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
+    if (vec) {
+        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
+        vec->resize(vec->size() - 1);
+    }
+}
+
+template <typename Type>
+static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
+    // assume vec is valid
+    const uint32_t index = vec->size();
+    vec->resize(index + 1);
+    (*vec)[index] = value;
+    return index;
+}
+
+///////////////////////// REMOVE INPUT ////////////////////////////////////
+
+static void removeInputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    for (size_t input = 0; input < request.inputs.size(); ++input) {
+        const std::string message = "removeInput: removed input " + std::to_string(input);
+        validate(preparedModel, message, request,
+                 [input](Request* request) { hidl_vec_removeAt(&request->inputs, input); });
+    }
+}
+
+///////////////////////// REMOVE OUTPUT ////////////////////////////////////
+
+static void removeOutputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    for (size_t output = 0; output < request.outputs.size(); ++output) {
+        const std::string message = "removeOutput: removed Output " + std::to_string(output);
+        validate(preparedModel, message, request,
+                 [output](Request* request) { hidl_vec_removeAt(&request->outputs, output); });
+    }
+}
+
+///////////////////////////// ENTRY POINT //////////////////////////////////
+
+std::vector<Request> createRequests(const std::vector<MixedTypedExampleType>& examples) {
+    const uint32_t INPUT = 0;
+    const uint32_t OUTPUT = 1;
+
+    std::vector<Request> requests;
+
+    for (auto& example : examples) {
+        const MixedTyped& inputs = example.first;
+        const MixedTyped& outputs = example.second;
+
+        std::vector<RequestArgument> inputs_info, outputs_info;
+        uint32_t inputSize = 0, outputSize = 0;
+
+        // This function only partially specifies the metadata (vector of RequestArguments).
+        // The contents are copied over below.
+        for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
+            if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
+                .dimensions = {},
+            };
+            RequestArgument arg_empty = {
+                .hasNoValue = true,
+            };
+            inputs_info[index] = s ? arg : arg_empty;
+            inputSize += s;
+        });
+        // Compute offset for inputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : inputs_info) {
+                if (!i.hasNoValue) i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+
+        // Go through all outputs, initialize RequestArgument descriptors
+        for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
+            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
+                .dimensions = {},
+            };
+            outputs_info[index] = arg;
+            outputSize += s;
+        });
+        // Compute offset for outputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : outputs_info) {
+                i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+        std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
+                                          nn::allocateSharedMemory(outputSize)};
+        if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
+            return {};
+        }
+
+        // map pool
+        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
+        if (inputMemory == nullptr) {
+            return {};
+        }
+        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
+        if (inputPtr == nullptr) {
+            return {};
+        }
+
+        // initialize pool
+        inputMemory->update();
+        for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
+            char* begin = (char*)p;
+            char* end = begin + s;
+            // TODO: handle more than one input
+            std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
+        });
+        inputMemory->commit();
+
+        requests.push_back({.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
+    }
+
+    return requests;
+}
+
+void ValidationTest::validateRequests(const V1_0::Model& model,
+                                      const std::vector<Request>& requests) {
+    // create IPreparedModel
+    sp<IPreparedModel> preparedModel;
+    ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel));
+    if (preparedModel == nullptr) {
+        return;
+    }
+
+    // validate each request
+    for (const Request& request : requests) {
+        removeInputTest(preparedModel, request);
+        removeOutputTest(preparedModel, request);
+    }
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/ValidationTests.cpp b/neuralnetworks/1.0/vts/functional/ValidationTests.cpp
new file mode 100644
index 0000000..98fc1c5
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/ValidationTests.cpp
@@ -0,0 +1,50 @@
+/*
+ * 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 "neuralnetworks_hidl_hal_test"
+
+#include "Models.h"
+#include "VtsHalNeuralnetworks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+// forward declarations
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+
+// generate validation tests
+#define VTS_CURRENT_TEST_CASE(TestName)                                           \
+    TEST_F(ValidationTest, TestName) {                                            \
+        const Model model = TestName::createTestModel();                          \
+        const std::vector<Request> requests = createRequests(TestName::examples); \
+        validateModel(model);                                                     \
+        validateRequests(model, requests);                                        \
+    }
+
+FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE)
+
+#undef VTS_CURRENT_TEST_CASE
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
similarity index 64%
rename from neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.cpp
rename to neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
index b14fb2c..1ff3b66 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.cpp
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
@@ -16,15 +16,7 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworksV1_0.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-
-using ::android::hardware::hidl_memory;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
+#include "VtsHalNeuralnetworks.h"
 
 namespace android {
 namespace hardware {
@@ -33,11 +25,6 @@
 namespace vts {
 namespace functional {
 
-// allocator helper
-hidl_memory allocateSharedMemory(int64_t size) {
-    return nn::allocateSharedMemory(size);
-}
-
 // A class for test environment setup
 NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
 
@@ -51,23 +38,49 @@
 }
 
 void NeuralnetworksHidlEnvironment::registerTestServices() {
-    registerTestService<V1_0::IDevice>();
+    registerTestService<IDevice>();
 }
 
 // The main test class for NEURALNETWORK HIDL HAL.
+NeuralnetworksHidlTest::NeuralnetworksHidlTest() {}
+
 NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
 
 void NeuralnetworksHidlTest::SetUp() {
-    device = ::testing::VtsHalHidlTargetTestBase::getService<V1_0::IDevice>(
+    ::testing::VtsHalHidlTargetTestBase::SetUp();
+    device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
         NeuralnetworksHidlEnvironment::getInstance());
     ASSERT_NE(nullptr, device.get());
 }
 
-void NeuralnetworksHidlTest::TearDown() {}
+void NeuralnetworksHidlTest::TearDown() {
+    device = nullptr;
+    ::testing::VtsHalHidlTargetTestBase::TearDown();
+}
 
 }  // namespace functional
 }  // namespace vts
+
+::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) {
+    return os << toString(errorStatus);
+}
+
+::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus) {
+    return os << toString(deviceStatus);
+}
+
 }  // namespace V1_0
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
+
+using android::hardware::neuralnetworks::V1_0::vts::functional::NeuralnetworksHidlEnvironment;
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
+    ::testing::InitGoogleTest(&argc, argv);
+    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
+
+    int status = RUN_ALL_TESTS();
+    return status;
+}
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
similarity index 60%
rename from neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.h
rename to neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
index fbb1607..e79129b 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.h
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
@@ -18,16 +18,15 @@
 #define VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
 
 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
 #include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hidl/allocator/1.0/IAllocator.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
+
+#include <android-base/macros.h>
 #include <gtest/gtest.h>
-#include <string>
+#include <iostream>
+#include <vector>
 
 namespace android {
 namespace hardware {
@@ -36,47 +35,47 @@
 namespace vts {
 namespace functional {
 
-hidl_memory allocateSharedMemory(int64_t size);
-
 // A class for test environment setup
 class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlEnvironment);
     NeuralnetworksHidlEnvironment();
-    NeuralnetworksHidlEnvironment(const NeuralnetworksHidlEnvironment&) = delete;
-    NeuralnetworksHidlEnvironment(NeuralnetworksHidlEnvironment&&) = delete;
-    NeuralnetworksHidlEnvironment& operator=(const NeuralnetworksHidlEnvironment&) = delete;
-    NeuralnetworksHidlEnvironment& operator=(NeuralnetworksHidlEnvironment&&) = delete;
+    ~NeuralnetworksHidlEnvironment() override;
 
    public:
-    ~NeuralnetworksHidlEnvironment() override;
     static NeuralnetworksHidlEnvironment* getInstance();
     void registerTestServices() override;
 };
 
 // The main test class for NEURALNETWORKS HIDL HAL.
 class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest);
+
    public:
+    NeuralnetworksHidlTest();
     ~NeuralnetworksHidlTest() override;
     void SetUp() override;
     void TearDown() override;
 
-    sp<V1_0::IDevice> device;
+   protected:
+    sp<IDevice> device;
 };
+
+// Tag for the validation tests
+class ValidationTest : public NeuralnetworksHidlTest {
+   protected:
+    void validateModel(const Model& model);
+    void validateRequests(const Model& model, const std::vector<Request>& request);
+};
+
+// Tag for the generated tests
+class GeneratedTest : public NeuralnetworksHidlTest {};
+
 }  // namespace functional
 }  // namespace vts
 
 // pretty-print values for error messages
-
-template <typename CharT, typename Traits>
-::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                V1_0::ErrorStatus errorStatus) {
-    return os << toString(errorStatus);
-}
-
-template <typename CharT, typename Traits>
-::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                V1_0::DeviceStatus deviceStatus) {
-    return os << toString(deviceStatus);
-}
+::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus);
+::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus);
 
 }  // namespace V1_0
 }  // namespace neuralnetworks
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0BasicTest.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0BasicTest.cpp
deleted file mode 100644
index 59e5b80..0000000
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0BasicTest.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * 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 "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworksV1_0.h"
-
-#include "Callbacks.h"
-#include "Models.h"
-#include "TestHarness.h"
-
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-using ::android::hardware::neuralnetworks::V1_0::IDevice;
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::Capabilities;
-using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
-using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
-using ::android::hardware::neuralnetworks::V1_0::Model;
-using ::android::hardware::neuralnetworks::V1_0::OperationType;
-using ::android::hardware::neuralnetworks::V1_0::PerformanceInfo;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-
-static void doPrepareModelShortcut(const sp<IDevice>& device, sp<IPreparedModel>* preparedModel) {
-    ASSERT_NE(nullptr, preparedModel);
-    Model model = createValidTestModel_1_0();
-
-    // see if service can handle model
-    bool fullySupportsModel = false;
-    Return<void> supportedOpsLaunchStatus = device->getSupportedOperations(
-        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
-            ASSERT_EQ(ErrorStatus::NONE, status);
-            ASSERT_NE(0ul, supported.size());
-            fullySupportsModel =
-                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
-        });
-    ASSERT_TRUE(supportedOpsLaunchStatus.isOk());
-
-    // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    // retrieve prepared model
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    *preparedModel = preparedModelCallback->getPreparedModel();
-
-    // The getSupportedOperations call returns a list of operations that are
-    // guaranteed not to fail if prepareModel is called, and
-    // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed.
-    // If a driver has any doubt that it can prepare an operation, it must
-    // return false. So here, if a driver isn't sure if it can support an
-    // operation, but reports that it successfully prepared the model, the test
-    // can continue.
-    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
-        ASSERT_EQ(nullptr, preparedModel->get());
-        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Early termination of test because vendor service cannot "
-                     "prepare model that it does not support."
-                  << std::endl;
-        return;
-    }
-    ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
-    ASSERT_NE(nullptr, preparedModel->get());
-}
-
-// create device test
-TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
-
-// status test
-TEST_F(NeuralnetworksHidlTest, StatusTest) {
-    Return<DeviceStatus> status = device->getStatus();
-    ASSERT_TRUE(status.isOk());
-    EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
-}
-
-// initialization
-TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
-    Return<void> ret =
-        device->getCapabilities([](ErrorStatus status, const Capabilities& capabilities) {
-            EXPECT_EQ(ErrorStatus::NONE, status);
-            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations positive test
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsPositiveTest) {
-    Model model = createValidTestModel_1_0();
-    Return<void> ret = device->getSupportedOperations(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::NONE, status);
-            EXPECT_EQ(model.operations.size(), supported.size());
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations negative test 1
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest1) {
-    Model model = createInvalidTestModel1_1_0();
-    Return<void> ret = device->getSupportedOperations(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-            (void)supported;
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations negative test 2
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest2) {
-    Model model = createInvalidTestModel2_1_0();
-    Return<void> ret = device->getSupportedOperations(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-            (void)supported;
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// prepare simple model positive test
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelPositiveTest) {
-    sp<IPreparedModel> preparedModel;
-    doPrepareModelShortcut(device, &preparedModel);
-}
-
-// prepare simple model negative test 1
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest1) {
-    Model model = createInvalidTestModel1_1_0();
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
-    EXPECT_EQ(nullptr, preparedModel.get());
-}
-
-// prepare simple model negative test 2
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest2) {
-    Model model = createInvalidTestModel2_1_0();
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
-    EXPECT_EQ(nullptr, preparedModel.get());
-}
-
-// execute simple graph positive test
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphPositiveTest) {
-    std::vector<float> outputData = {-1.0f, -1.0f, -1.0f, -1.0f};
-    std::vector<float> expectedData = {6.0f, 8.0f, 10.0f, 12.0f};
-    const uint32_t OUTPUT = 1;
-
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createValidTestRequest();
-
-    auto postWork = [&] {
-        sp<IMemory> outputMemory = mapMemory(request.pools[OUTPUT]);
-        if (outputMemory == nullptr) {
-            return false;
-        }
-        float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer()));
-        if (outputPtr == nullptr) {
-            return false;
-        }
-        outputMemory->read();
-        std::copy(outputPtr, outputPtr + outputData.size(), outputData.begin());
-        outputMemory->commit();
-        return true;
-    };
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    executionCallback->on_finish(postWork);
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::NONE, executionReturnStatus);
-    EXPECT_EQ(expectedData, outputData);
-}
-
-// execute simple graph negative test 1
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest1) {
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createInvalidTestRequest1();
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
-}
-
-// execute simple graph negative test 2
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest2) {
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createInvalidTestRequest2();
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
-}
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_0
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
-
-using android::hardware::neuralnetworks::V1_0::vts::functional::NeuralnetworksHidlEnvironment;
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
-    ::testing::InitGoogleTest(&argc, argv);
-    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
-
-    int status = RUN_ALL_TESTS();
-    return status;
-}
diff --git a/neuralnetworks/1.1/Android.bp b/neuralnetworks/1.1/Android.bp
index 9365d4e..81bcef3 100644
--- a/neuralnetworks/1.1/Android.bp
+++ b/neuralnetworks/1.1/Android.bp
@@ -15,6 +15,7 @@
         "android.hidl.base@1.0",
     ],
     types: [
+        "Capabilities",
         "Model",
         "Operation",
         "OperationType",
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 623b441..f755c20 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -17,9 +17,12 @@
 cc_test {
     name: "VtsHalNeuralnetworksV1_1TargetTest",
     srcs: [
-        "VtsHalNeuralnetworksV1_1.cpp",
-        "VtsHalNeuralnetworksV1_1BasicTest.cpp",
-        "VtsHalNeuralnetworksV1_1GeneratedTest.cpp",
+        "BasicTests.cpp",
+        "GeneratedTests.cpp",
+        "ValidateModel.cpp",
+        "ValidateRequest.cpp",
+        "ValidationTests.cpp",
+        "VtsHalNeuralnetworks.cpp",
     ],
     defaults: ["VtsHalTargetTestDefaults"],
     static_libs: [
@@ -36,4 +39,13 @@
         "libneuralnetworks_generated_test_harness_headers",
         "libneuralnetworks_generated_tests",
     ],
+    // Bug: http://b/74200014 - Disable arm32 asan since it triggers internal
+    // error in ld.gold.
+    arch: {
+        arm: {
+            sanitize: {
+                never: true,
+            },
+        },
+    },
 }
diff --git a/neuralnetworks/1.1/vts/functional/BasicTests.cpp b/neuralnetworks/1.1/vts/functional/BasicTests.cpp
new file mode 100644
index 0000000..ed59a2d
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/BasicTests.cpp
@@ -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.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_1 {
+namespace vts {
+namespace functional {
+
+// create device test
+TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
+
+// status test
+TEST_F(NeuralnetworksHidlTest, StatusTest) {
+    Return<DeviceStatus> status = device->getStatus();
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
+}
+
+// initialization
+TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
+    Return<void> ret =
+        device->getCapabilities_1_1([](ErrorStatus status, const Capabilities& capabilities) {
+            EXPECT_EQ(ErrorStatus::NONE, status);
+            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
+            EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.powerUsage);
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
new file mode 100644
index 0000000..1f1cc7a
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTests.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 "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+#include "TestHarness.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+
+namespace generated_tests {
+using ::generated_tests::MixedTypedExampleType;
+extern void Execute(const sp<V1_1::IDevice>&, std::function<V1_1::Model(void)>,
+                    std::function<bool(int)>, const std::vector<MixedTypedExampleType>&);
+}  // namespace generated_tests
+
+namespace V1_1 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::nn::allocateSharedMemory;
+
+// Mixed-typed examples
+typedef generated_tests::MixedTypedExampleType MixedTypedExample;
+
+// in frameworks/ml/nn/runtime/tests/generated/
+#include "all_generated_V1_0_vts_tests.cpp"
+#include "all_generated_V1_1_vts_tests.cpp"
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/Models.h b/neuralnetworks/1.1/vts/functional/Models.h
new file mode 100644
index 0000000..c3cadb5
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/Models.h
@@ -0,0 +1,323 @@
+/*
+ * 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 VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_H
+#define VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_H
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "TestHarness.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_1 {
+namespace vts {
+namespace functional {
+
+using MixedTypedExample = generated_tests::MixedTypedExampleType;
+
+#define FOR_EACH_TEST_MODEL(FN)                                \
+    FN(add)                                                    \
+    FN(add_broadcast_quant8)                                   \
+    FN(add_quant8)                                             \
+    FN(add_relaxed)                                            \
+    FN(avg_pool_float_1)                                       \
+    FN(avg_pool_float_1_relaxed)                               \
+    FN(avg_pool_float_2)                                       \
+    FN(avg_pool_float_2_relaxed)                               \
+    FN(avg_pool_float_3)                                       \
+    FN(avg_pool_float_3_relaxed)                               \
+    FN(avg_pool_float_4)                                       \
+    FN(avg_pool_float_4_relaxed)                               \
+    FN(avg_pool_float_5)                                       \
+    FN(avg_pool_quant8_1)                                      \
+    FN(avg_pool_quant8_2)                                      \
+    FN(avg_pool_quant8_3)                                      \
+    FN(avg_pool_quant8_4)                                      \
+    FN(avg_pool_quant8_5)                                      \
+    FN(batch_to_space)                                         \
+    FN(batch_to_space_float_1)                                 \
+    FN(batch_to_space_quant8_1)                                \
+    FN(concat_float_1)                                         \
+    FN(concat_float_1_relaxed)                                 \
+    FN(concat_float_2)                                         \
+    FN(concat_float_2_relaxed)                                 \
+    FN(concat_float_3)                                         \
+    FN(concat_float_3_relaxed)                                 \
+    FN(concat_quant8_1)                                        \
+    FN(concat_quant8_2)                                        \
+    FN(concat_quant8_3)                                        \
+    FN(conv_1_h3_w2_SAME)                                      \
+    FN(conv_1_h3_w2_SAME_relaxed)                              \
+    FN(conv_1_h3_w2_VALID)                                     \
+    FN(conv_1_h3_w2_VALID_relaxed)                             \
+    FN(conv_3_h3_w2_SAME)                                      \
+    FN(conv_3_h3_w2_SAME_relaxed)                              \
+    FN(conv_3_h3_w2_VALID)                                     \
+    FN(conv_3_h3_w2_VALID_relaxed)                             \
+    FN(conv_float)                                             \
+    FN(conv_float_2)                                           \
+    FN(conv_float_channels)                                    \
+    FN(conv_float_channels_relaxed)                            \
+    FN(conv_float_channels_weights_as_inputs)                  \
+    FN(conv_float_channels_weights_as_inputs_relaxed)          \
+    FN(conv_float_large)                                       \
+    FN(conv_float_large_relaxed)                               \
+    FN(conv_float_large_weights_as_inputs)                     \
+    FN(conv_float_large_weights_as_inputs_relaxed)             \
+    FN(conv_float_relaxed)                                     \
+    FN(conv_float_weights_as_inputs)                           \
+    FN(conv_float_weights_as_inputs_relaxed)                   \
+    FN(conv_quant8)                                            \
+    FN(conv_quant8_2)                                          \
+    FN(conv_quant8_channels)                                   \
+    FN(conv_quant8_channels_weights_as_inputs)                 \
+    FN(conv_quant8_large)                                      \
+    FN(conv_quant8_large_weights_as_inputs)                    \
+    FN(conv_quant8_overflow)                                   \
+    FN(conv_quant8_overflow_weights_as_inputs)                 \
+    FN(conv_quant8_weights_as_inputs)                          \
+    FN(depth_to_space_float_1)                                 \
+    FN(depth_to_space_float_1_relaxed)                         \
+    FN(depth_to_space_float_2)                                 \
+    FN(depth_to_space_float_2_relaxed)                         \
+    FN(depth_to_space_float_3)                                 \
+    FN(depth_to_space_float_3_relaxed)                         \
+    FN(depth_to_space_quant8_1)                                \
+    FN(depth_to_space_quant8_2)                                \
+    FN(depthwise_conv)                                         \
+    FN(depthwise_conv2d_float)                                 \
+    FN(depthwise_conv2d_float_2)                               \
+    FN(depthwise_conv2d_float_large)                           \
+    FN(depthwise_conv2d_float_large_2)                         \
+    FN(depthwise_conv2d_float_large_2_weights_as_inputs)       \
+    FN(depthwise_conv2d_float_large_relaxed)                   \
+    FN(depthwise_conv2d_float_large_weights_as_inputs)         \
+    FN(depthwise_conv2d_float_large_weights_as_inputs_relaxed) \
+    FN(depthwise_conv2d_float_weights_as_inputs)               \
+    FN(depthwise_conv2d_quant8)                                \
+    FN(depthwise_conv2d_quant8_2)                              \
+    FN(depthwise_conv2d_quant8_large)                          \
+    FN(depthwise_conv2d_quant8_large_weights_as_inputs)        \
+    FN(depthwise_conv2d_quant8_weights_as_inputs)              \
+    FN(depthwise_conv_relaxed)                                 \
+    FN(dequantize)                                             \
+    FN(div)                                                    \
+    FN(embedding_lookup)                                       \
+    FN(embedding_lookup_relaxed)                               \
+    FN(floor)                                                  \
+    FN(floor_relaxed)                                          \
+    FN(fully_connected_float)                                  \
+    FN(fully_connected_float_2)                                \
+    FN(fully_connected_float_large)                            \
+    FN(fully_connected_float_large_weights_as_inputs)          \
+    FN(fully_connected_float_relaxed)                          \
+    FN(fully_connected_float_weights_as_inputs)                \
+    FN(fully_connected_float_weights_as_inputs_relaxed)        \
+    FN(fully_connected_quant8)                                 \
+    FN(fully_connected_quant8_2)                               \
+    FN(fully_connected_quant8_large)                           \
+    FN(fully_connected_quant8_large_weights_as_inputs)         \
+    FN(fully_connected_quant8_weights_as_inputs)               \
+    FN(hashtable_lookup_float)                                 \
+    FN(hashtable_lookup_float_relaxed)                         \
+    FN(hashtable_lookup_quant8)                                \
+    FN(l2_normalization)                                       \
+    FN(l2_normalization_2)                                     \
+    FN(l2_normalization_large)                                 \
+    FN(l2_normalization_large_relaxed)                         \
+    FN(l2_normalization_relaxed)                               \
+    FN(l2_pool_float)                                          \
+    FN(l2_pool_float_2)                                        \
+    FN(l2_pool_float_large)                                    \
+    FN(l2_pool_float_relaxed)                                  \
+    FN(local_response_norm_float_1)                            \
+    FN(local_response_norm_float_1_relaxed)                    \
+    FN(local_response_norm_float_2)                            \
+    FN(local_response_norm_float_2_relaxed)                    \
+    FN(local_response_norm_float_3)                            \
+    FN(local_response_norm_float_3_relaxed)                    \
+    FN(local_response_norm_float_4)                            \
+    FN(local_response_norm_float_4_relaxed)                    \
+    FN(logistic_float_1)                                       \
+    FN(logistic_float_1_relaxed)                               \
+    FN(logistic_float_2)                                       \
+    FN(logistic_float_2_relaxed)                               \
+    FN(logistic_quant8_1)                                      \
+    FN(logistic_quant8_2)                                      \
+    FN(lsh_projection)                                         \
+    FN(lsh_projection_2)                                       \
+    FN(lsh_projection_2_relaxed)                               \
+    FN(lsh_projection_relaxed)                                 \
+    FN(lsh_projection_weights_as_inputs)                       \
+    FN(lsh_projection_weights_as_inputs_relaxed)               \
+    FN(lstm)                                                   \
+    FN(lstm2)                                                  \
+    FN(lstm2_relaxed)                                          \
+    FN(lstm2_state)                                            \
+    FN(lstm2_state2)                                           \
+    FN(lstm2_state2_relaxed)                                   \
+    FN(lstm2_state_relaxed)                                    \
+    FN(lstm3)                                                  \
+    FN(lstm3_relaxed)                                          \
+    FN(lstm3_state)                                            \
+    FN(lstm3_state2)                                           \
+    FN(lstm3_state2_relaxed)                                   \
+    FN(lstm3_state3)                                           \
+    FN(lstm3_state3_relaxed)                                   \
+    FN(lstm3_state_relaxed)                                    \
+    FN(lstm_relaxed)                                           \
+    FN(lstm_state)                                             \
+    FN(lstm_state2)                                            \
+    FN(lstm_state2_relaxed)                                    \
+    FN(lstm_state_relaxed)                                     \
+    FN(max_pool_float_1)                                       \
+    FN(max_pool_float_1_relaxed)                               \
+    FN(max_pool_float_2)                                       \
+    FN(max_pool_float_2_relaxed)                               \
+    FN(max_pool_float_3)                                       \
+    FN(max_pool_float_3_relaxed)                               \
+    FN(max_pool_float_4)                                       \
+    FN(max_pool_quant8_1)                                      \
+    FN(max_pool_quant8_2)                                      \
+    FN(max_pool_quant8_3)                                      \
+    FN(max_pool_quant8_4)                                      \
+    FN(mean)                                                   \
+    FN(mean_float_1)                                           \
+    FN(mean_float_2)                                           \
+    FN(mean_quant8_1)                                          \
+    FN(mean_quant8_2)                                          \
+    FN(mobilenet_224_gender_basic_fixed)                       \
+    FN(mobilenet_224_gender_basic_fixed_relaxed)               \
+    FN(mobilenet_quantized)                                    \
+    FN(mul)                                                    \
+    FN(mul_broadcast_quant8)                                   \
+    FN(mul_quant8)                                             \
+    FN(mul_relaxed)                                            \
+    FN(mul_relu)                                               \
+    FN(mul_relu_relaxed)                                       \
+    FN(pad)                                                    \
+    FN(pad_float_1)                                            \
+    FN(relu1_float_1)                                          \
+    FN(relu1_float_1_relaxed)                                  \
+    FN(relu1_float_2)                                          \
+    FN(relu1_float_2_relaxed)                                  \
+    FN(relu1_quant8_1)                                         \
+    FN(relu1_quant8_2)                                         \
+    FN(relu6_float_1)                                          \
+    FN(relu6_float_1_relaxed)                                  \
+    FN(relu6_float_2)                                          \
+    FN(relu6_float_2_relaxed)                                  \
+    FN(relu6_quant8_1)                                         \
+    FN(relu6_quant8_2)                                         \
+    FN(relu_float_1)                                           \
+    FN(relu_float_1_relaxed)                                   \
+    FN(relu_float_2)                                           \
+    FN(relu_quant8_1)                                          \
+    FN(relu_quant8_2)                                          \
+    FN(reshape)                                                \
+    FN(reshape_quant8)                                         \
+    FN(reshape_quant8_weights_as_inputs)                       \
+    FN(reshape_relaxed)                                        \
+    FN(reshape_weights_as_inputs)                              \
+    FN(reshape_weights_as_inputs_relaxed)                      \
+    FN(resize_bilinear)                                        \
+    FN(resize_bilinear_2)                                      \
+    FN(resize_bilinear_relaxed)                                \
+    FN(rnn)                                                    \
+    FN(rnn_relaxed)                                            \
+    FN(rnn_state)                                              \
+    FN(rnn_state_relaxed)                                      \
+    FN(softmax_float_1)                                        \
+    FN(softmax_float_1_relaxed)                                \
+    FN(softmax_float_2)                                        \
+    FN(softmax_float_2_relaxed)                                \
+    FN(softmax_quant8_1)                                       \
+    FN(softmax_quant8_2)                                       \
+    FN(space_to_batch)                                         \
+    FN(space_to_batch_float_1)                                 \
+    FN(space_to_batch_float_2)                                 \
+    FN(space_to_batch_float_3)                                 \
+    FN(space_to_batch_quant8_1)                                \
+    FN(space_to_batch_quant8_2)                                \
+    FN(space_to_batch_quant8_3)                                \
+    FN(space_to_depth_float_1)                                 \
+    FN(space_to_depth_float_1_relaxed)                         \
+    FN(space_to_depth_float_2)                                 \
+    FN(space_to_depth_float_2_relaxed)                         \
+    FN(space_to_depth_float_3)                                 \
+    FN(space_to_depth_float_3_relaxed)                         \
+    FN(space_to_depth_quant8_1)                                \
+    FN(space_to_depth_quant8_2)                                \
+    FN(squeeze)                                                \
+    FN(squeeze_float_1)                                        \
+    FN(squeeze_quant8_1)                                       \
+    FN(strided_slice)                                          \
+    FN(strided_slice_float_1)                                  \
+    FN(strided_slice_float_10)                                 \
+    FN(strided_slice_float_2)                                  \
+    FN(strided_slice_float_3)                                  \
+    FN(strided_slice_float_4)                                  \
+    FN(strided_slice_float_5)                                  \
+    FN(strided_slice_float_6)                                  \
+    FN(strided_slice_float_7)                                  \
+    FN(strided_slice_float_8)                                  \
+    FN(strided_slice_float_9)                                  \
+    FN(strided_slice_qaunt8_10)                                \
+    FN(strided_slice_quant8_1)                                 \
+    FN(strided_slice_quant8_2)                                 \
+    FN(strided_slice_quant8_3)                                 \
+    FN(strided_slice_quant8_4)                                 \
+    FN(strided_slice_quant8_5)                                 \
+    FN(strided_slice_quant8_6)                                 \
+    FN(strided_slice_quant8_7)                                 \
+    FN(strided_slice_quant8_8)                                 \
+    FN(strided_slice_quant8_9)                                 \
+    FN(sub)                                                    \
+    FN(svdf)                                                   \
+    FN(svdf2)                                                  \
+    FN(svdf2_relaxed)                                          \
+    FN(svdf_relaxed)                                           \
+    FN(svdf_state)                                             \
+    FN(svdf_state_relaxed)                                     \
+    FN(tanh)                                                   \
+    FN(tanh_relaxed)                                           \
+    FN(transpose)                                              \
+    FN(transpose_float_1)                                      \
+    FN(transpose_quant8_1)
+
+#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \
+    namespace function {                            \
+    extern std::vector<MixedTypedExample> examples; \
+    Model createTestModel();                        \
+    }
+
+FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS)
+
+#undef FORWARD_DECLARE_GENERATED_OBJECTS
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_H
diff --git a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
new file mode 100644
index 0000000..7a20e26
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
@@ -0,0 +1,513 @@
+/*
+ * 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 "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_1 {
+
+using V1_0::IPreparedModel;
+using V1_0::Operand;
+using V1_0::OperandLifeTime;
+using V1_0::OperandType;
+
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+
+///////////////////////// UTILITY FUNCTIONS /////////////////////////
+
+static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
+                                           const V1_1::Model& model) {
+    SCOPED_TRACE(message + " [getSupportedOperations_1_1]");
+
+    Return<void> ret =
+        device->getSupportedOperations_1_1(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
+            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+static void validatePrepareModel(const sp<IDevice>& device, const std::string& message,
+                                 const V1_1::Model& model) {
+    SCOPED_TRACE(message + " [prepareModel_1_1]");
+
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus =
+        device->prepareModel_1_1(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    ASSERT_EQ(nullptr, preparedModel.get());
+}
+
+// Primary validation function. This function will take a valid model, apply a
+// mutation to it to invalidate the model, then pass it to interface calls that
+// use the model. Note that the model here is passed by value, and any mutation
+// to the model does not leave this function.
+static void validate(const sp<IDevice>& device, const std::string& message, V1_1::Model model,
+                     const std::function<void(Model*)>& mutation) {
+    mutation(&model);
+    validateGetSupportedOperations(device, message, model);
+    validatePrepareModel(device, message, model);
+}
+
+// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
+// so this is efficiently accomplished by moving the element to the end and
+// resizing the hidl_vec to one less.
+template <typename Type>
+static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
+    if (vec) {
+        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
+        vec->resize(vec->size() - 1);
+    }
+}
+
+template <typename Type>
+static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
+    // assume vec is valid
+    const uint32_t index = vec->size();
+    vec->resize(index + 1);
+    (*vec)[index] = value;
+    return index;
+}
+
+static uint32_t addOperand(Model* model) {
+    return hidl_vec_push_back(&model->operands,
+                              {
+                                  .type = OperandType::INT32,
+                                  .dimensions = {},
+                                  .numberOfConsumers = 0,
+                                  .scale = 0.0f,
+                                  .zeroPoint = 0,
+                                  .lifetime = OperandLifeTime::MODEL_INPUT,
+                                  .location = {.poolIndex = 0, .offset = 0, .length = 0},
+                              });
+}
+
+static uint32_t addOperand(Model* model, OperandLifeTime lifetime) {
+    uint32_t index = addOperand(model);
+    model->operands[index].numberOfConsumers = 1;
+    model->operands[index].lifetime = lifetime;
+    return index;
+}
+
+///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
+
+static const int32_t invalidOperandTypes[] = {
+    static_cast<int32_t>(OperandType::FLOAT32) - 1,              // lower bound fundamental
+    static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1,  // upper bound fundamental
+    static_cast<int32_t>(OperandType::OEM) - 1,                  // lower bound OEM
+    static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,      // upper bound OEM
+};
+
+static void mutateOperandTypeTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        for (int32_t invalidOperandType : invalidOperandTypes) {
+            const std::string message = "mutateOperandTypeTest: operand " +
+                                        std::to_string(operand) + " set to value " +
+                                        std::to_string(invalidOperandType);
+            validate(device, message, model, [operand, invalidOperandType](Model* model) {
+                model->operands[operand].type = static_cast<OperandType>(invalidOperandType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE OPERAND RANK /////////////////////////
+
+static uint32_t getInvalidRank(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+            return 1;
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return 0;
+        default:
+            return 0;
+    }
+}
+
+static void mutateOperandRankTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const uint32_t invalidRank = getInvalidRank(model.operands[operand].type);
+        const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
+                                    " has rank of " + std::to_string(invalidRank);
+        validate(device, message, model, [operand, invalidRank](Model* model) {
+            model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
+        });
+    }
+}
+
+///////////////////////// VALIDATE OPERAND SCALE /////////////////////////
+
+static float getInvalidScale(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+        case OperandType::TENSOR_FLOAT32:
+            return 1.0f;
+        case OperandType::TENSOR_INT32:
+            return -1.0f;
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return 0.0f;
+        default:
+            return 0.0f;
+    }
+}
+
+static void mutateOperandScaleTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const float invalidScale = getInvalidScale(model.operands[operand].type);
+        const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
+                                    " has scale of " + std::to_string(invalidScale);
+        validate(device, message, model, [operand, invalidScale](Model* model) {
+            model->operands[operand].scale = invalidScale;
+        });
+    }
+}
+
+///////////////////////// VALIDATE OPERAND ZERO POINT /////////////////////////
+
+static std::vector<int32_t> getInvalidZeroPoints(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+            return {1};
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return {-1, 256};
+        default:
+            return {};
+    }
+}
+
+static void mutateOperandZeroPointTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const std::vector<int32_t> invalidZeroPoints =
+            getInvalidZeroPoints(model.operands[operand].type);
+        for (int32_t invalidZeroPoint : invalidZeroPoints) {
+            const std::string message = "mutateOperandZeroPointTest: operand " +
+                                        std::to_string(operand) + " has zero point of " +
+                                        std::to_string(invalidZeroPoint);
+            validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
+                model->operands[operand].zeroPoint = invalidZeroPoint;
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE EXTRA ??? /////////////////////////
+
+// TODO: Operand::lifetime
+// TODO: Operand::location
+
+///////////////////////// VALIDATE OPERATION OPERAND TYPE /////////////////////////
+
+static void mutateOperand(Operand* operand, OperandType type) {
+    Operand newOperand = *operand;
+    newOperand.type = type;
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+            newOperand.dimensions = hidl_vec<uint32_t>();
+            newOperand.scale = 0.0f;
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_FLOAT32:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.scale = 0.0f;
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_INT32:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
+            break;
+        case OperandType::OEM:
+        case OperandType::TENSOR_OEM_BYTE:
+        default:
+            break;
+    }
+    *operand = newOperand;
+}
+
+static bool mutateOperationOperandTypeSkip(size_t operand, const V1_1::Model& model) {
+    // LSH_PROJECTION's second argument is allowed to have any type. This is the
+    // only operation that currently has a type that can be anything independent
+    // from any other type. Changing the operand type to any other type will
+    // result in a valid model for LSH_PROJECTION. If this is the case, skip the
+    // test.
+    for (const Operation& operation : model.operations) {
+        if (operation.type == OperationType::LSH_PROJECTION && operand == operation.inputs[1]) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static void mutateOperationOperandTypeTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        if (mutateOperationOperandTypeSkip(operand, model)) {
+            continue;
+        }
+        for (OperandType invalidOperandType : hidl_enum_iterator<OperandType>{}) {
+            // Do not test OEM types
+            if (invalidOperandType == model.operands[operand].type ||
+                invalidOperandType == OperandType::OEM ||
+                invalidOperandType == OperandType::TENSOR_OEM_BYTE) {
+                continue;
+            }
+            const std::string message = "mutateOperationOperandTypeTest: operand " +
+                                        std::to_string(operand) + " set to type " +
+                                        toString(invalidOperandType);
+            validate(device, message, model, [operand, invalidOperandType](Model* model) {
+                mutateOperand(&model->operands[operand], invalidOperandType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION TYPE /////////////////////////
+
+static const int32_t invalidOperationTypes[] = {
+    static_cast<int32_t>(OperationType::ADD) - 1,            // lower bound fundamental
+    static_cast<int32_t>(OperationType::TRANSPOSE) + 1,      // upper bound fundamental
+    static_cast<int32_t>(OperationType::OEM_OPERATION) - 1,  // lower bound OEM
+    static_cast<int32_t>(OperationType::OEM_OPERATION) + 1,  // upper bound OEM
+};
+
+static void mutateOperationTypeTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (int32_t invalidOperationType : invalidOperationTypes) {
+            const std::string message = "mutateOperationTypeTest: operation " +
+                                        std::to_string(operation) + " set to value " +
+                                        std::to_string(invalidOperationType);
+            validate(device, message, model, [operation, invalidOperationType](Model* model) {
+                model->operations[operation].type =
+                    static_cast<OperationType>(invalidOperationType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION INPUT OPERAND INDEX /////////////////////////
+
+static void mutateOperationInputOperandIndexTest(const sp<IDevice>& device,
+                                                 const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const uint32_t invalidOperand = model.operands.size();
+        for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
+            const std::string message = "mutateOperationInputOperandIndexTest: operation " +
+                                        std::to_string(operation) + " input " +
+                                        std::to_string(input);
+            validate(device, message, model, [operation, input, invalidOperand](Model* model) {
+                model->operations[operation].inputs[input] = invalidOperand;
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION OUTPUT OPERAND INDEX /////////////////////////
+
+static void mutateOperationOutputOperandIndexTest(const sp<IDevice>& device,
+                                                  const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const uint32_t invalidOperand = model.operands.size();
+        for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
+            const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
+                                        std::to_string(operation) + " output " +
+                                        std::to_string(output);
+            validate(device, message, model, [operation, output, invalidOperand](Model* model) {
+                model->operations[operation].outputs[output] = invalidOperand;
+            });
+        }
+    }
+}
+
+///////////////////////// REMOVE OPERAND FROM EVERYTHING /////////////////////////
+
+static void removeValueAndDecrementGreaterValues(hidl_vec<uint32_t>* vec, uint32_t value) {
+    if (vec) {
+        // remove elements matching "value"
+        auto last = std::remove(vec->begin(), vec->end(), value);
+        vec->resize(std::distance(vec->begin(), last));
+
+        // decrement elements exceeding "value"
+        std::transform(vec->begin(), vec->end(), vec->begin(),
+                       [value](uint32_t v) { return v > value ? v-- : v; });
+    }
+}
+
+static void removeOperand(Model* model, uint32_t index) {
+    hidl_vec_removeAt(&model->operands, index);
+    for (Operation& operation : model->operations) {
+        removeValueAndDecrementGreaterValues(&operation.inputs, index);
+        removeValueAndDecrementGreaterValues(&operation.outputs, index);
+    }
+    removeValueAndDecrementGreaterValues(&model->inputIndexes, index);
+    removeValueAndDecrementGreaterValues(&model->outputIndexes, index);
+}
+
+static void removeOperandTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const std::string message = "removeOperandTest: operand " + std::to_string(operand);
+        validate(device, message, model,
+                 [operand](Model* model) { removeOperand(model, operand); });
+    }
+}
+
+///////////////////////// REMOVE OPERATION /////////////////////////
+
+static void removeOperation(Model* model, uint32_t index) {
+    for (uint32_t operand : model->operations[index].inputs) {
+        model->operands[operand].numberOfConsumers--;
+    }
+    hidl_vec_removeAt(&model->operations, index);
+}
+
+static void removeOperationTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message = "removeOperationTest: operation " + std::to_string(operation);
+        validate(device, message, model,
+                 [operation](Model* model) { removeOperation(model, operation); });
+    }
+}
+
+///////////////////////// REMOVE OPERATION INPUT /////////////////////////
+
+static void removeOperationInputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
+            const V1_1::Operation& op = model.operations[operation];
+            // CONCATENATION has at least 2 inputs, with the last element being
+            // INT32. Skip this test if removing one of CONCATENATION's
+            // inputs still produces a valid model.
+            if (op.type == V1_1::OperationType::CONCATENATION && op.inputs.size() > 2 &&
+                input != op.inputs.size() - 1) {
+                continue;
+            }
+            const std::string message = "removeOperationInputTest: operation " +
+                                        std::to_string(operation) + ", input " +
+                                        std::to_string(input);
+            validate(device, message, model, [operation, input](Model* model) {
+                uint32_t operand = model->operations[operation].inputs[input];
+                model->operands[operand].numberOfConsumers--;
+                hidl_vec_removeAt(&model->operations[operation].inputs, input);
+            });
+        }
+    }
+}
+
+///////////////////////// REMOVE OPERATION OUTPUT /////////////////////////
+
+static void removeOperationOutputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
+            const std::string message = "removeOperationOutputTest: operation " +
+                                        std::to_string(operation) + ", output " +
+                                        std::to_string(output);
+            validate(device, message, model, [operation, output](Model* model) {
+                hidl_vec_removeAt(&model->operations[operation].outputs, output);
+            });
+        }
+    }
+}
+
+///////////////////////// MODEL VALIDATION /////////////////////////
+
+// TODO: remove model input
+// TODO: remove model output
+// TODO: add unused operation
+
+///////////////////////// ADD OPERATION INPUT /////////////////////////
+
+static void addOperationInputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
+        validate(device, message, model, [operation](Model* model) {
+            uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT);
+            hidl_vec_push_back(&model->operations[operation].inputs, index);
+            hidl_vec_push_back(&model->inputIndexes, index);
+        });
+    }
+}
+
+///////////////////////// ADD OPERATION OUTPUT /////////////////////////
+
+static void addOperationOutputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message =
+            "addOperationOutputTest: operation " + std::to_string(operation);
+        validate(device, message, model, [operation](Model* model) {
+            uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
+            hidl_vec_push_back(&model->operations[operation].outputs, index);
+            hidl_vec_push_back(&model->outputIndexes, index);
+        });
+    }
+}
+
+////////////////////////// ENTRY POINT //////////////////////////////
+
+void ValidationTest::validateModel(const V1_1::Model& model) {
+    mutateOperandTypeTest(device, model);
+    mutateOperandRankTest(device, model);
+    mutateOperandScaleTest(device, model);
+    mutateOperandZeroPointTest(device, model);
+    mutateOperationOperandTypeTest(device, model);
+    mutateOperationTypeTest(device, model);
+    mutateOperationInputOperandIndexTest(device, model);
+    mutateOperationOutputOperandIndexTest(device, model);
+    removeOperandTest(device, model);
+    removeOperationTest(device, model);
+    removeOperationInputTest(device, model);
+    removeOperationOutputTest(device, model);
+    addOperationInputTest(device, model);
+    addOperationOutputTest(device, model);
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
new file mode 100644
index 0000000..bd96614
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
@@ -0,0 +1,262 @@
+/*
+ * 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 "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+#include "TestHarness.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_1 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hidl::memory::V1_0::IMemory;
+using generated_tests::MixedTyped;
+using generated_tests::MixedTypedExampleType;
+using generated_tests::for_all;
+
+///////////////////////// UTILITY FUNCTIONS /////////////////////////
+
+static void createPreparedModel(const sp<IDevice>& device, const V1_1::Model& model,
+                                sp<IPreparedModel>* preparedModel) {
+    ASSERT_NE(nullptr, preparedModel);
+
+    // see if service can handle model
+    bool fullySupportsModel = false;
+    Return<void> supportedOpsLaunchStatus = device->getSupportedOperations_1_1(
+        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
+            ASSERT_EQ(ErrorStatus::NONE, status);
+            ASSERT_NE(0ul, supported.size());
+            fullySupportsModel =
+                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
+        });
+    ASSERT_TRUE(supportedOpsLaunchStatus.isOk());
+
+    // launch prepare model
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus =
+        device->prepareModel_1_1(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    // retrieve prepared model
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    *preparedModel = preparedModelCallback->getPreparedModel();
+
+    // The getSupportedOperations_1_1 call returns a list of operations that are
+    // guaranteed not to fail if prepareModel_1_1 is called, and
+    // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed.
+    // If a driver has any doubt that it can prepare an operation, it must
+    // return false. So here, if a driver isn't sure if it can support an
+    // operation, but reports that it successfully prepared the model, the test
+    // can continue.
+    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
+        ASSERT_EQ(nullptr, preparedModel->get());
+        LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot "
+                     "prepare model that it does not support.";
+        std::cout << "[          ]   Unable to test Request validation because vendor service "
+                     "cannot prepare model that it does not support."
+                  << std::endl;
+        return;
+    }
+    ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+    ASSERT_NE(nullptr, preparedModel->get());
+}
+
+// Primary validation function. This function will take a valid request, apply a
+// mutation to it to invalidate the request, then pass it to interface calls
+// that use the request. Note that the request here is passed by value, and any
+// mutation to the request does not leave this function.
+static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
+                     Request request, const std::function<void(Request*)>& mutation) {
+    mutation(&request);
+    SCOPED_TRACE(message + " [execute]");
+
+    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+    ASSERT_NE(nullptr, executionCallback.get());
+    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
+    ASSERT_TRUE(executeLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
+
+    executionCallback->wait();
+    ErrorStatus executionReturnStatus = executionCallback->getStatus();
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
+}
+
+// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
+// so this is efficiently accomplished by moving the element to the end and
+// resizing the hidl_vec to one less.
+template <typename Type>
+static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
+    if (vec) {
+        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
+        vec->resize(vec->size() - 1);
+    }
+}
+
+template <typename Type>
+static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
+    // assume vec is valid
+    const uint32_t index = vec->size();
+    vec->resize(index + 1);
+    (*vec)[index] = value;
+    return index;
+}
+
+///////////////////////// REMOVE INPUT ////////////////////////////////////
+
+static void removeInputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    for (size_t input = 0; input < request.inputs.size(); ++input) {
+        const std::string message = "removeInput: removed input " + std::to_string(input);
+        validate(preparedModel, message, request,
+                 [input](Request* request) { hidl_vec_removeAt(&request->inputs, input); });
+    }
+}
+
+///////////////////////// REMOVE OUTPUT ////////////////////////////////////
+
+static void removeOutputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    for (size_t output = 0; output < request.outputs.size(); ++output) {
+        const std::string message = "removeOutput: removed Output " + std::to_string(output);
+        validate(preparedModel, message, request,
+                 [output](Request* request) { hidl_vec_removeAt(&request->outputs, output); });
+    }
+}
+
+///////////////////////////// ENTRY POINT //////////////////////////////////
+
+std::vector<Request> createRequests(const std::vector<MixedTypedExampleType>& examples) {
+    const uint32_t INPUT = 0;
+    const uint32_t OUTPUT = 1;
+
+    std::vector<Request> requests;
+
+    for (auto& example : examples) {
+        const MixedTyped& inputs = example.first;
+        const MixedTyped& outputs = example.second;
+
+        std::vector<RequestArgument> inputs_info, outputs_info;
+        uint32_t inputSize = 0, outputSize = 0;
+
+        // This function only partially specifies the metadata (vector of RequestArguments).
+        // The contents are copied over below.
+        for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
+            if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
+                .dimensions = {},
+            };
+            RequestArgument arg_empty = {
+                .hasNoValue = true,
+            };
+            inputs_info[index] = s ? arg : arg_empty;
+            inputSize += s;
+        });
+        // Compute offset for inputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : inputs_info) {
+                if (!i.hasNoValue) i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+
+        // Go through all outputs, initialize RequestArgument descriptors
+        for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
+            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
+                .dimensions = {},
+            };
+            outputs_info[index] = arg;
+            outputSize += s;
+        });
+        // Compute offset for outputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : outputs_info) {
+                i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+        std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
+                                          nn::allocateSharedMemory(outputSize)};
+        if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
+            return {};
+        }
+
+        // map pool
+        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
+        if (inputMemory == nullptr) {
+            return {};
+        }
+        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
+        if (inputPtr == nullptr) {
+            return {};
+        }
+
+        // initialize pool
+        inputMemory->update();
+        for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
+            char* begin = (char*)p;
+            char* end = begin + s;
+            // TODO: handle more than one input
+            std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
+        });
+        inputMemory->commit();
+
+        requests.push_back({.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
+    }
+
+    return requests;
+}
+
+void ValidationTest::validateRequests(const V1_1::Model& model,
+                                      const std::vector<Request>& requests) {
+    // create IPreparedModel
+    sp<IPreparedModel> preparedModel;
+    ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel));
+    if (preparedModel == nullptr) {
+        return;
+    }
+
+    // validate each request
+    for (const Request& request : requests) {
+        removeInputTest(preparedModel, request);
+        removeOutputTest(preparedModel, request);
+    }
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/ValidationTests.cpp b/neuralnetworks/1.1/vts/functional/ValidationTests.cpp
new file mode 100644
index 0000000..1c35ba8
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/ValidationTests.cpp
@@ -0,0 +1,50 @@
+/*
+ * 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 "neuralnetworks_hidl_hal_test"
+
+#include "Models.h"
+#include "VtsHalNeuralnetworks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_1 {
+namespace vts {
+namespace functional {
+
+// forward declarations
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+
+// generate validation tests
+#define VTS_CURRENT_TEST_CASE(TestName)                                           \
+    TEST_F(ValidationTest, TestName) {                                            \
+        const Model model = TestName::createTestModel();                          \
+        const std::vector<Request> requests = createRequests(TestName::examples); \
+        validateModel(model);                                                     \
+        validateRequests(model, requests);                                        \
+    }
+
+FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE)
+
+#undef VTS_CURRENT_TEST_CASE
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
similarity index 64%
rename from neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.cpp
rename to neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
index b1d3be7..62381e6 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.cpp
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
@@ -16,16 +16,7 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworksV1_1.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-#include <hidlmemory/mapping.h>
-
-using ::android::hardware::hidl_memory;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
+#include "VtsHalNeuralnetworks.h"
 
 namespace android {
 namespace hardware {
@@ -34,11 +25,6 @@
 namespace vts {
 namespace functional {
 
-// allocator helper
-hidl_memory allocateSharedMemory(int64_t size) {
-    return nn::allocateSharedMemory(size);
-}
-
 // A class for test environment setup
 NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
 
@@ -52,23 +38,49 @@
 }
 
 void NeuralnetworksHidlEnvironment::registerTestServices() {
-    registerTestService<V1_1::IDevice>();
+    registerTestService<IDevice>();
 }
 
 // The main test class for NEURALNETWORK HIDL HAL.
+NeuralnetworksHidlTest::NeuralnetworksHidlTest() {}
+
 NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
 
 void NeuralnetworksHidlTest::SetUp() {
-    device = ::testing::VtsHalHidlTargetTestBase::getService<V1_1::IDevice>(
+    ::testing::VtsHalHidlTargetTestBase::SetUp();
+    device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
         NeuralnetworksHidlEnvironment::getInstance());
     ASSERT_NE(nullptr, device.get());
 }
 
-void NeuralnetworksHidlTest::TearDown() {}
+void NeuralnetworksHidlTest::TearDown() {
+    device = nullptr;
+    ::testing::VtsHalHidlTargetTestBase::TearDown();
+}
 
 }  // namespace functional
 }  // namespace vts
+
+::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) {
+    return os << toString(errorStatus);
+}
+
+::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus) {
+    return os << toString(deviceStatus);
+}
+
 }  // namespace V1_1
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
+
+using android::hardware::neuralnetworks::V1_1::vts::functional::NeuralnetworksHidlEnvironment;
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
+    ::testing::InitGoogleTest(&argc, argv);
+    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
+
+    int status = RUN_ALL_TESTS();
+    return status;
+}
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
similarity index 60%
rename from neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.h
rename to neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
index 426246c..0050e52 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.h
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
@@ -17,65 +17,71 @@
 #ifndef VTS_HAL_NEURALNETWORKS_V1_1_H
 #define VTS_HAL_NEURALNETWORKS_V1_1_H
 
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
 #include <android/hardware/neuralnetworks/1.1/IDevice.h>
 #include <android/hardware/neuralnetworks/1.1/types.h>
-#include <android/hidl/allocator/1.0/IAllocator.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
+
+#include <android-base/macros.h>
 #include <gtest/gtest.h>
-#include <string>
+#include <iostream>
+#include <vector>
 
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
 namespace V1_1 {
+
+using V1_0::Request;
+using V1_0::DeviceStatus;
+using V1_0::ErrorStatus;
+
 namespace vts {
 namespace functional {
-hidl_memory allocateSharedMemory(int64_t size);
 
 // A class for test environment setup
 class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlEnvironment);
     NeuralnetworksHidlEnvironment();
-    NeuralnetworksHidlEnvironment(const NeuralnetworksHidlEnvironment&) = delete;
-    NeuralnetworksHidlEnvironment(NeuralnetworksHidlEnvironment&&) = delete;
-    NeuralnetworksHidlEnvironment& operator=(const NeuralnetworksHidlEnvironment&) = delete;
-    NeuralnetworksHidlEnvironment& operator=(NeuralnetworksHidlEnvironment&&) = delete;
+    ~NeuralnetworksHidlEnvironment() override;
 
    public:
-    ~NeuralnetworksHidlEnvironment() override;
     static NeuralnetworksHidlEnvironment* getInstance();
     void registerTestServices() override;
 };
 
 // The main test class for NEURALNETWORKS HIDL HAL.
 class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest);
+
    public:
+    NeuralnetworksHidlTest();
     ~NeuralnetworksHidlTest() override;
     void SetUp() override;
     void TearDown() override;
 
-    sp<V1_1::IDevice> device;
+   protected:
+    sp<IDevice> device;
 };
+
+// Tag for the validation tests
+class ValidationTest : public NeuralnetworksHidlTest {
+   protected:
+    void validateModel(const Model& model);
+    void validateRequests(const Model& model, const std::vector<Request>& request);
+};
+
+// Tag for the generated tests
+class GeneratedTest : public NeuralnetworksHidlTest {};
+
 }  // namespace functional
 }  // namespace vts
 
 // pretty-print values for error messages
-
-template <typename CharT, typename Traits>
-::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                V1_0::ErrorStatus errorStatus) {
-    return os << toString(errorStatus);
-}
-
-template <typename CharT, typename Traits>
-::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                V1_0::DeviceStatus deviceStatus) {
-    return os << toString(deviceStatus);
-}
+::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus);
+::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus);
 
 }  // namespace V1_1
 }  // namespace neuralnetworks
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp
deleted file mode 100644
index 17f6744..0000000
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * 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 "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworksV1_1.h"
-
-#include "Callbacks.h"
-#include "Models.h"
-#include "TestHarness.h"
-
-#include <android-base/logging.h>
-#include <android/hardware/neuralnetworks/1.1/IDevice.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
-using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
-using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
-using ::android::hardware::neuralnetworks::V1_0::Operand;
-using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
-using ::android::hardware::neuralnetworks::V1_0::OperandType;
-using ::android::hardware::neuralnetworks::V1_0::Request;
-using ::android::hardware::neuralnetworks::V1_1::Capabilities;
-using ::android::hardware::neuralnetworks::V1_1::IDevice;
-using ::android::hardware::neuralnetworks::V1_1::Model;
-using ::android::hardware::neuralnetworks::V1_1::Operation;
-using ::android::hardware::neuralnetworks::V1_1::OperationType;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-
-static void doPrepareModelShortcut(const sp<IDevice>& device, sp<IPreparedModel>* preparedModel) {
-    ASSERT_NE(nullptr, preparedModel);
-    Model model = createValidTestModel_1_1();
-
-    // see if service can handle model
-    bool fullySupportsModel = false;
-    Return<void> supportedOpsLaunchStatus = device->getSupportedOperations_1_1(
-        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
-            ASSERT_EQ(ErrorStatus::NONE, status);
-            ASSERT_NE(0ul, supported.size());
-            fullySupportsModel =
-                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
-        });
-    ASSERT_TRUE(supportedOpsLaunchStatus.isOk());
-
-    // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus =
-        device->prepareModel_1_1(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    // retrieve prepared model
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    *preparedModel = preparedModelCallback->getPreparedModel();
-
-    // The getSupportedOperations call returns a list of operations that are
-    // guaranteed not to fail if prepareModel is called, and
-    // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed.
-    // If a driver has any doubt that it can prepare an operation, it must
-    // return false. So here, if a driver isn't sure if it can support an
-    // operation, but reports that it successfully prepared the model, the test
-    // can continue.
-    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
-        ASSERT_EQ(nullptr, preparedModel->get());
-        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Early termination of test because vendor service cannot "
-                     "prepare model that it does not support."
-                  << std::endl;
-        return;
-    }
-    ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
-    ASSERT_NE(nullptr, preparedModel->get());
-}
-
-// create device test
-TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
-
-// status test
-TEST_F(NeuralnetworksHidlTest, StatusTest) {
-    Return<DeviceStatus> status = device->getStatus();
-    ASSERT_TRUE(status.isOk());
-    EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
-}
-
-// initialization
-TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
-    Return<void> ret =
-        device->getCapabilities_1_1([](ErrorStatus status, const Capabilities& capabilities) {
-            EXPECT_EQ(ErrorStatus::NONE, status);
-            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
-            EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.powerUsage);
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations positive test
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsPositiveTest) {
-    Model model = createValidTestModel_1_1();
-    Return<void> ret = device->getSupportedOperations_1_1(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::NONE, status);
-            EXPECT_EQ(model.operations.size(), supported.size());
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations negative test 1
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest1) {
-    Model model = createInvalidTestModel1_1_1();
-    Return<void> ret = device->getSupportedOperations_1_1(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-            (void)supported;
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations negative test 2
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest2) {
-    Model model = createInvalidTestModel2_1_1();
-    Return<void> ret = device->getSupportedOperations_1_1(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-            (void)supported;
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// prepare simple model positive test
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelPositiveTest) {
-    sp<IPreparedModel> preparedModel;
-    doPrepareModelShortcut(device, &preparedModel);
-}
-
-// prepare simple model negative test 1
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest1) {
-    Model model = createInvalidTestModel1_1_1();
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus =
-        device->prepareModel_1_1(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
-    EXPECT_EQ(nullptr, preparedModel.get());
-}
-
-// prepare simple model negative test 2
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest2) {
-    Model model = createInvalidTestModel2_1_1();
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus =
-        device->prepareModel_1_1(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
-    EXPECT_EQ(nullptr, preparedModel.get());
-}
-
-// execute simple graph positive test
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphPositiveTest) {
-    std::vector<float> outputData = {-1.0f, -1.0f, -1.0f, -1.0f};
-    std::vector<float> expectedData = {6.0f, 8.0f, 10.0f, 12.0f};
-    const uint32_t OUTPUT = 1;
-
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createValidTestRequest();
-
-    auto postWork = [&] {
-        sp<IMemory> outputMemory = mapMemory(request.pools[OUTPUT]);
-        if (outputMemory == nullptr) {
-            return false;
-        }
-        float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer()));
-        if (outputPtr == nullptr) {
-            return false;
-        }
-        outputMemory->read();
-        std::copy(outputPtr, outputPtr + outputData.size(), outputData.begin());
-        outputMemory->commit();
-        return true;
-    };
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    executionCallback->on_finish(postWork);
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::NONE, executionReturnStatus);
-    EXPECT_EQ(expectedData, outputData);
-}
-
-// execute simple graph negative test 1
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest1) {
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createInvalidTestRequest1();
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
-}
-
-// execute simple graph negative test 2
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest2) {
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createInvalidTestRequest2();
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
-}
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_1
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
-
-using android::hardware::neuralnetworks::V1_1::vts::functional::NeuralnetworksHidlEnvironment;
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
-    ::testing::InitGoogleTest(&argc, argv);
-    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
-
-    int status = RUN_ALL_TESTS();
-    return status;
-}
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1GeneratedTest.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1GeneratedTest.cpp
deleted file mode 100644
index 025d9fe..0000000
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1GeneratedTest.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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 "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworksV1_1.h"
-
-#include "Callbacks.h"
-#include "TestHarness.h"
-
-#include <android-base/logging.h>
-#include <android/hardware/neuralnetworks/1.1/IDevice.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::Capabilities;
-using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
-using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
-using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
-using ::android::hardware::neuralnetworks::V1_0::Operand;
-using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
-using ::android::hardware::neuralnetworks::V1_0::OperandType;
-using ::android::hardware::neuralnetworks::V1_0::Request;
-using ::android::hardware::neuralnetworks::V1_1::IDevice;
-using ::android::hardware::neuralnetworks::V1_1::Model;
-using ::android::hardware::neuralnetworks::V1_1::Operation;
-using ::android::hardware::neuralnetworks::V1_1::OperationType;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-
-namespace generated_tests {
-using ::generated_tests::MixedTypedExampleType;
-extern void Execute(sp<V1_1::IDevice>&, std::function<Model(void)>, std::function<bool(int)>,
-                    const std::vector<MixedTypedExampleType>&);
-}  // namespace generated_tests
-
-namespace V1_1 {
-namespace vts {
-namespace functional {
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-
-// Mixed-typed examples
-typedef generated_tests::MixedTypedExampleType MixedTypedExample;
-
-// in frameworks/ml/nn/runtime/tests/generated/
-#include "all_generated_V1_0_vts_tests.cpp"
-#include "all_generated_V1_1_vts_tests.cpp"
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_1
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
diff --git a/nfc/1.1/Android.bp b/nfc/1.1/Android.bp
index 73dc70a..9a1392e 100644
--- a/nfc/1.1/Android.bp
+++ b/nfc/1.1/Android.bp
@@ -16,7 +16,11 @@
         "android.hidl.base@1.0",
     ],
     types: [
+        "Constant",
+        "NfcConfig",
         "NfcEvent",
+        "PresenceCheckAlgorithm",
+        "ProtocolDiscoveryConfig",
     ],
     gen_java: true,
 }
diff --git a/nfc/1.1/INfc.hal b/nfc/1.1/INfc.hal
index ea6a571..b629d8c 100644
--- a/nfc/1.1/INfc.hal
+++ b/nfc/1.1/INfc.hal
@@ -49,4 +49,11 @@
      *                NfcStatus::SUCCESS otherwise.
      */
     open_1_1(INfcClientCallback clientCallback) generates (NfcStatus status);
+
+    /**
+     * Fetches vendor specific configurations.
+     * @return config indicates support for certain features and
+     *     populates the vendor specific configs
+     */
+    getConfig() generates (NfcConfig config);
 };
diff --git a/nfc/1.1/types.hal b/nfc/1.1/types.hal
index 2f5ec7f..e9ffd16 100644
--- a/nfc/1.1/types.hal
+++ b/nfc/1.1/types.hal
@@ -21,3 +21,81 @@
     /** In case of an error, HCI network needs to be re-initialized */
     HCI_NETWORK_RESET = 7
 };
+
+enum Constant : uint8_t {
+    UNSUPPORTED_CONFIG = 0xFF,
+};
+
+/**
+ * Vendor Specific Proprietary Protocol & Discovery Configuration.
+ * Set to UNSUPPORTED_CONFIG if not supported.
+ * discovery* fields map to "RF Technology and Mode" in NCI Spec
+ * protocol* fields map to "RF protocols" in NCI Spec
+ */
+struct ProtocolDiscoveryConfig {
+    uint8_t protocol18092Active;
+    uint8_t protocolBPrime;
+    uint8_t protocolDual;
+    uint8_t protocol15693;
+    uint8_t protocolKovio;
+    uint8_t protocolMifare;
+    uint8_t discoveryPollKovio;
+    uint8_t discoveryPollBPrime;
+    uint8_t discoveryListenBPrime;
+};
+
+/* Presence Check Algorithm as per ISO/IEC 14443-4 */
+enum PresenceCheckAlgorithm : uint8_t {
+    /** Lets the stack select an algorithm */
+    DEFAULT = 0,
+    /** ISO-DEP protocol's empty I-block */
+    I_BLOCK = 1,
+    /**
+     * Type - 4 tag protocol iso-dep nak presence check command is sent waiting for
+     * response and notification.
+     */
+    ISO_DEP_NAK = 2
+};
+
+struct NfcConfig {
+    /** If true, NFCC is using bail out mode for either Type A or Type B poll. */
+    bool nfaPollBailOutMode;
+
+    PresenceCheckAlgorithm presenceCheckAlgorithm;
+
+    ProtocolDiscoveryConfig nfaProprietaryCfg;
+
+    /** Default off-host route. 0x00 if there aren't any. Refer to NCI spec. */
+    uint8_t defaultOffHostRoute;
+
+    /**
+     * Default off-host route for Felica. 0x00 if there aren't any. Refer to
+     * NCI spec.
+     */
+    uint8_t defaultOffHostRouteFelica;
+
+    /** Default system code route. 0x00 if there aren't any. Refer NCI spec */
+    uint8_t defaultSystemCodeRoute;
+
+    /** Default power state for system code route. 0x00 if there aren't any. Refer NCI spec */
+    uint8_t defaultSystemCodePowerState;
+
+    /**
+     * Default route for all remaining protocols and technology which haven't
+     * been configured.
+     * Device Host(0x00) is the default. Refer to NCI spec.
+     * */
+    uint8_t defaultRoute;
+
+    /** Pipe ID for eSE. 0x00 if there aren't any. */
+    uint8_t offHostESEPipeId;
+
+    /** Pipe ID for UICC. 0x00 if there aren't any. */
+    uint8_t offHostSIMPipeId;
+
+    /** Extended APDU length for ISO_DEP. If not supported default length is 261 */
+    uint32_t maxIsoDepTransceiveLength;
+
+    /** list of white listed host ids, as per ETSI TS 102 622 */
+    vec<uint8_t> hostWhitelist;
+};
diff --git a/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp b/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
index bef412b..0b7c88b 100644
--- a/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
+++ b/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
@@ -30,6 +30,7 @@
 using ::android::hardware::nfc::V1_1::INfc;
 using ::android::hardware::nfc::V1_1::INfcClientCallback;
 using ::android::hardware::nfc::V1_1::NfcEvent;
+using ::android::hardware::nfc::V1_1::NfcConfig;
 using ::android::hardware::nfc::V1_0::NfcStatus;
 using ::android::hardware::nfc::V1_0::NfcData;
 using ::android::hardware::Return;
@@ -37,6 +38,9 @@
 using ::android::hardware::hidl_vec;
 using ::android::sp;
 
+// 261 bytes is the default and minimum transceive length
+constexpr unsigned int MIN_ISO_DEP_TRANSCEIVE_LENGTH = 261;
+
 constexpr char kCallbackNameSendEvent[] = "sendEvent";
 constexpr char kCallbackNameSendData[] = "sendData";
 
@@ -209,6 +213,17 @@
     EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 }
 
+/*
+ * getConfig:
+ * Calls getConfig()
+ * checks if fields in NfcConfig are populated correctly
+ */
+TEST_F(NfcHidlTest, GetConfig) {
+    nfc_->getConfig([](NfcConfig config) {
+        EXPECT_GE(config.maxIsoDepTransceiveLength, MIN_ISO_DEP_TRANSCEIVE_LENGTH);
+    });
+}
+
 int main(int argc, char** argv) {
     ::testing::AddGlobalTestEnvironment(NfcHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
diff --git a/radio/1.2/Android.bp b/radio/1.2/Android.bp
index a9c80b7..c90a03c 100644
--- a/radio/1.2/Android.bp
+++ b/radio/1.2/Android.bp
@@ -24,6 +24,7 @@
         "Call",
         "CardStatus",
         "CellConnectionStatus",
+        "CellIdentity",
         "CellIdentityCdma",
         "CellIdentityGsm",
         "CellIdentityLte",
@@ -36,6 +37,7 @@
         "CellInfoLte",
         "CellInfoTdscdma",
         "CellInfoWcdma",
+        "DataRegStateResult",
         "DataRequestReason",
         "IncrementalResultsPeriodicityRange",
         "IndicationFilter",
@@ -48,6 +50,7 @@
         "ScanIntervalRange",
         "SignalStrength",
         "TdscdmaSignalStrength",
+        "VoiceRegStateResult",
         "WcdmaSignalStrength",
     ],
     gen_java: true,
diff --git a/radio/1.2/IRadioResponse.hal b/radio/1.2/IRadioResponse.hal
index f26c9ec..300aa37 100644
--- a/radio/1.2/IRadioResponse.hal
+++ b/radio/1.2/IRadioResponse.hal
@@ -98,4 +98,31 @@
      *   RadioError:INTERNAL_ERR
      */
     oneway getSignalStrengthResponse_1_2(RadioResponseInfo info, SignalStrength signalStrength);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param voiceRegResponse Current Voice registration response as defined by VoiceRegStateResult
+     *        in types.hal
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    oneway getVoiceRegistrationStateResponse_1_2(RadioResponseInfo info,
+            VoiceRegStateResult voiceRegResponse);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param dataRegResponse Current Data registration response as defined by DataRegStateResult in
+     *        types.hal
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NOT_PROVISIONED
+     */
+    oneway getDataRegistrationStateResponse_1_2(RadioResponseInfo info,
+            DataRegStateResult dataRegResponse);
 };
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index 5e72b3b..4715fac 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -32,6 +32,7 @@
 import @1.0::LteSignalStrength;
 import @1.0::RadioConst;
 import @1.0::RadioError;
+import @1.0::RegState;
 import @1.0::SignalStrength;
 import @1.0::TdScdmaSignalStrength;
 import @1.0::TimeStampType;
@@ -462,3 +463,129 @@
     TdScdmaSignalStrength tdScdma;
     WcdmaSignalStrength wcdma;
 };
+
+struct CellIdentity {
+    /**
+     * Cell type for selecting from union CellInfo.
+     * Only one of the below vectors must be of size 1 based on a
+     * valid CellInfoType and others must be of size 0.
+     * If cell info type is NONE, then all the vectors must be of size 0.
+     */
+    CellInfoType cellInfoType;
+    vec<CellIdentityGsm> cellIdentityGsm;
+    vec<CellIdentityWcdma> cellIdentityWcdma;
+    vec<CellIdentityCdma> cellIdentityCdma;
+    vec<CellIdentityLte> cellIdentityLte;
+    vec<CellIdentityTdscdma> cellIdentityTdscdma;
+};
+
+struct VoiceRegStateResult {
+    /**
+     * Valid reg states are NOT_REG_MT_NOT_SEARCHING_OP,
+     * REG_HOME, NOT_REG_MT_SEARCHING_OP, REG_DENIED,
+     * UNKNOWN, REG_ROAMING defined in RegState
+     */
+    RegState regState;
+    /**
+     * Indicates the available voice radio technology, valid values as
+     * defined by RadioTechnology.
+     */
+    int32_t rat;
+    /**
+     * concurrent services support indicator. if registered on a CDMA system.
+     * false - Concurrent services not supported,
+     * true - Concurrent services supported
+     */
+    bool cssSupported;
+    /**
+     * TSB-58 Roaming Indicator if registered on a CDMA or EVDO system or -1 if not.
+     * Valid values are 0-255.
+     */
+    int32_t roamingIndicator;
+    /**
+     * Indicates whether the current system is in the PRL if registered on a CDMA or EVDO system
+     * or -1 if not. 0=not in the PRL, 1=in the PRL
+     */
+    int32_t systemIsInPrl;
+    /**
+     * Default Roaming Indicator from the PRL if registered on a CDMA or EVDO system or -1 if not.
+     * Valid values are 0-255.
+     */
+    int32_t defaultRoamingIndicator;
+    /**
+     * reasonForDenial if registration state is 3
+     * (Registration denied) this is an enumerated reason why
+     * registration was denied. See 3GPP TS 24.008,
+     * 10.5.3.6 and Annex G.
+     * 0 - General
+     * 1 - Authentication Failure
+     * 2 - IMSI unknown in HLR
+     * 3 - Illegal MS
+     * 4 - Illegal ME
+     * 5 - PLMN not allowed
+     * 6 - Location area not allowed
+     * 7 - Roaming not allowed
+     * 8 - No Suitable Cells in this Location Area
+     * 9 - Network failure
+     * 10 - Persistent location update reject
+     * 11 - PLMN not allowed
+     * 12 - Location area not allowed
+     * 13 - Roaming not allowed in this Location Area
+     * 15 - No Suitable Cells in this Location Area
+     * 17 - Network Failure
+     * 20 - MAC Failure
+     * 21 - Sync Failure
+     * 22 - Congestion
+     * 23 - GSM Authentication unacceptable
+     * 25 - Not Authorized for this CSG
+     * 32 - Service option not supported
+     * 33 - Requested service option not subscribed
+     * 34 - Service option temporarily out of order
+     * 38 - Call cannot be identified
+     * 48-63 - Retry upon entry into a new cell
+     * 95 - Semantically incorrect message
+     * 96 - Invalid mandatory information
+     * 97 - Message type non-existent or not implemented
+     * 98 - Message type not compatible with protocol state
+     * 99 - Information element non-existent or not implemented
+     * 100 - Conditional IE error
+     * 101 - Message not compatible with protocol state
+     * 111 - Protocol error, unspecified
+     */
+    int32_t reasonForDenial;
+
+    CellIdentity cellIdentity;
+};
+
+struct DataRegStateResult {
+    /**
+     * Valid reg states are NOT_REG_MT_NOT_SEARCHING_OP,
+     * REG_HOME, NOT_REG_MT_SEARCHING_OP, REG_DENIED,
+     * UNKNOWN, REG_ROAMING defined in RegState
+     */
+    RegState regState;
+    /**
+     * Indicates the available data radio technology,
+     * valid values as defined by RadioTechnology.
+     */
+    int32_t rat;
+    /**
+     * If registration state is 3 (Registration
+     * denied) this is an enumerated reason why
+     * registration was denied. See 3GPP TS 24.008,
+     * Annex G.6 "Additional cause codes for GMM".
+     * 7 == GPRS services not allowed
+     * 8 == GPRS services and non-GPRS services not allowed
+     * 9 == MS identity cannot be derived by the network
+     * 10 == Implicitly detached
+     * 14 == GPRS services not allowed in this PLMN
+     * 16 == MSC temporarily not reachable
+     * 40 == No PDP context activated
+     */
+    int32_t reasonDataDenied;
+    /**
+     * The maximum number of simultaneous Data Calls must be established using setupDataCall().
+     */
+    int32_t maxDataCalls;
+    CellIdentity cellIdentity;
+};
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
index 34a87e1..ee130f8 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -673,3 +673,40 @@
     ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
                                  {RadioError::NONE, RadioError::NO_NETWORK_FOUND}));
 }
+
+/*
+ * Test IRadio.getVoiceRegistrationState() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_2, getVoiceRegistrationState) {
+    int serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_2->getVoiceRegistrationState(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_2->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_2->rspInfo.serial);
+
+    ALOGI("getVoiceRegistrationStateResponse_1_2, rspInfo.error = %s\n",
+          toString(radioRsp_v1_2->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                 {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+}
+
+/*
+ * Test IRadio.getDataRegistrationState() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_2, getDataRegistrationState) {
+    int serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_2->getDataRegistrationState(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_2->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_2->rspInfo.serial);
+
+    ALOGI("getVoiceRegistrationStateResponse_1_2, rspInfo.error = %s\n",
+          toString(radioRsp_v1_2->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(
+        radioRsp_v1_2->rspInfo.error,
+        {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::NOT_PROVISIONED}));
+}
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
index 66d8ca4..c61913c 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
+++ b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
@@ -417,6 +417,12 @@
 
     Return<void> getCellInfoListResponse_1_2(
         const RadioResponseInfo& info, const ::android::hardware::hidl_vec<CellInfo>& cellInfo);
+
+    Return<void> getVoiceRegistrationStateResponse_1_2(
+        const RadioResponseInfo& info, const V1_2::VoiceRegStateResult& voiceRegResponse);
+
+    Return<void> getDataRegistrationStateResponse_1_2(
+        const RadioResponseInfo& info, const V1_2::DataRegStateResult& dataRegResponse);
 };
 
 /* Callback class for radio indication */
diff --git a/radio/1.2/vts/functional/radio_response.cpp b/radio/1.2/vts/functional/radio_response.cpp
index d96f76b..9195689 100644
--- a/radio/1.2/vts/functional/radio_response.cpp
+++ b/radio/1.2/vts/functional/radio_response.cpp
@@ -731,4 +731,14 @@
     rspInfo = info;
     parent_v1_2.notify();
     return Void();
-}
\ No newline at end of file
+}
+
+Return<void> RadioResponse_v1_2::getVoiceRegistrationStateResponse_1_2(
+    const RadioResponseInfo& /*info*/, const V1_2::VoiceRegStateResult& /*voiceRegResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_2::getDataRegistrationStateResponse_1_2(
+    const RadioResponseInfo& /*info*/, const V1_2::DataRegStateResult& /*dataRegResponse*/) {
+    return Void();
+}
diff --git a/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp b/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
index 59c354f..dab81e2 100644
--- a/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
+++ b/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
@@ -34,14 +34,13 @@
 using ::android::sp;
 using ::testing::VtsHalHidlTargetTestEnvBase;
 
-#define SELECT_ISD \
-    { 0x00, 0xA4, 0x04, 0x00, 0x00 }
-#define SEQUENCE_COUNTER \
-    { 0x80, 0xCA, 0x00, 0xC1, 0x00 }
-#define MANAGE_SELECT \
-    { 0x00, 0xA4, 0x04, 0x00, 0x00 }
-#define CRS_AID \
-    { 0xA0, 0x00, 0x00, 0x01, 0x51, 0x43, 0x52, 0x53, 0x00 }
+#define DATA_APDU \
+    { 0x00, 0x08, 0x00, 0x00, 0x00 }
+#define ANDROID_TEST_AID                                                                          \
+    {                                                                                             \
+        0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, \
+            0x31                                                                                  \
+    }
 
 constexpr char kCallbackNameOnStateChange[] = "onStateChange";
 
@@ -115,7 +114,7 @@
  * Check status word in the response
  */
 TEST_F(SecureElementHidlTest, transmit) {
-    std::vector<uint8_t> aid = CRS_AID;
+    std::vector<uint8_t> aid = ANDROID_TEST_AID;
     SecureElementStatus statusReturned;
     LogicalChannelResponse response;
     se_->openLogicalChannel(
@@ -132,9 +131,9 @@
             }
         });
     EXPECT_EQ(SecureElementStatus::SUCCESS, statusReturned);
-    EXPECT_LE((unsigned int)3, response.selectResponse.size());
+    EXPECT_LE((unsigned int)2, response.selectResponse.size());
     EXPECT_LE(1, response.channelNumber);
-    std::vector<uint8_t> command = SELECT_ISD;
+    std::vector<uint8_t> command = DATA_APDU;
     std::vector<uint8_t> transmitResponse;
     se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
         transmitResponse.resize(res.size());
@@ -145,16 +144,6 @@
     EXPECT_LE((unsigned int)3, transmitResponse.size());
     EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
     EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
-    command = SEQUENCE_COUNTER;
-    se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
-        transmitResponse.resize(res.size());
-        for (size_t i = 0; i < res.size(); i++) {
-            transmitResponse[i] = res[i];
-        }
-    });
-    EXPECT_LE((unsigned int)3, transmitResponse.size());
-    EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
-    EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
     EXPECT_EQ(SecureElementStatus::SUCCESS, se_->closeChannel(response.channelNumber));
 }
 
@@ -164,7 +153,7 @@
  *  open channel, check the length of selectResponse and close the channel
  */
 TEST_F(SecureElementHidlTest, openBasicChannel) {
-    std::vector<uint8_t> aid = CRS_AID;
+    std::vector<uint8_t> aid = ANDROID_TEST_AID;
     SecureElementStatus statusReturned;
     std::vector<uint8_t> response;
     se_->openBasicChannel(aid, 0x00,
@@ -180,17 +169,6 @@
                           });
     if (statusReturned == SecureElementStatus::SUCCESS) {
         EXPECT_LE((unsigned int)3, response.size());
-        std::vector<uint8_t> command = SELECT_ISD;
-        std::vector<uint8_t> transmitResponse;
-        se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
-            transmitResponse.resize(res.size());
-            for (size_t i = 0; i < res.size(); i++) {
-                transmitResponse[i] = res[i];
-            }
-        });
-        EXPECT_LE((unsigned int)3, transmitResponse.size());
-        EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
-        EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
         return;
     }
     EXPECT_EQ(SecureElementStatus::UNSUPPORTED_OPERATION, statusReturned);
@@ -221,7 +199,7 @@
  * Close Channel
  */
 TEST_F(SecureElementHidlTest, openCloseLogicalChannel) {
-    std::vector<uint8_t> aid = CRS_AID;
+    std::vector<uint8_t> aid = ANDROID_TEST_AID;
     SecureElementStatus statusReturned;
     LogicalChannelResponse response;
     se_->openLogicalChannel(
@@ -238,7 +216,7 @@
             }
         });
     EXPECT_EQ(SecureElementStatus::SUCCESS, statusReturned);
-    EXPECT_LE((unsigned int)3, response.selectResponse.size());
+    EXPECT_LE((unsigned int)2, response.selectResponse.size());
     EXPECT_LE(1, response.channelNumber);
     EXPECT_EQ(SecureElementStatus::SUCCESS, se_->closeChannel(response.channelNumber));
 }
diff --git a/wifi/1.2/IWifiStaIface.hal b/wifi/1.2/IWifiStaIface.hal
index be4e537..3a7f777 100644
--- a/wifi/1.2/IWifiStaIface.hal
+++ b/wifi/1.2/IWifiStaIface.hal
@@ -17,6 +17,7 @@
 package android.hardware.wifi@1.2;
 
 import @1.0::WifiStatus;
+import @1.0::MacAddress;
 import @1.0::IWifiStaIface;
 
 /**
@@ -51,4 +52,17 @@
      * @see installApfPacketFilter()
      */
     readApfPacketFilterData() generates (WifiStatus status, vec<uint8_t> data);
+
+    /**
+     * Changes the MAC address of the Sta Interface to the given
+     * MAC address.
+     *
+     * @param mac MAC address to change into.
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    setMacAddress(MacAddress mac) generates (WifiStatus status);
 };
diff --git a/wifi/1.2/default/android.hardware.wifi@1.0-service.rc b/wifi/1.2/default/android.hardware.wifi@1.0-service.rc
index eecb6d0..cf849d0 100644
--- a/wifi/1.2/default/android.hardware.wifi@1.0-service.rc
+++ b/wifi/1.2/default/android.hardware.wifi@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service
     class hal
+    capabilities NET_ADMIN NET_RAW SYS_MODULE
     user wifi
     group wifi gps
diff --git a/wifi/1.2/default/hidl_struct_util.cpp b/wifi/1.2/default/hidl_struct_util.cpp
index 33450ab..39ac544 100644
--- a/wifi/1.2/default/hidl_struct_util.cpp
+++ b/wifi/1.2/default/hidl_struct_util.cpp
@@ -2342,6 +2342,10 @@
             return RttStatus::NO_WIFI;
         case legacy_hal::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE:
             return RttStatus::FAIL_FTM_PARAM_OVERRIDE;
+        case legacy_hal::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE:
+            return RttStatus::FAILURE;  // TODO: add HIDL enumeration
+        case legacy_hal::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED:
+            return RttStatus::FAILURE;  // TODO: add HIDL enumeration
     };
     CHECK(false) << "Unknown legacy status: " << status;
 }
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 27c8d60..3928c9a 100644
--- a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
@@ -146,7 +146,7 @@
         } else if (type == IfaceType::STA) {
             chip_->createStaIface(
                 [&iface_name](const WifiStatus& status,
-                              const sp<IWifiStaIface>& iface) {
+                              const sp<V1_0::IWifiStaIface>& 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_legacy_hal.cpp b/wifi/1.2/default/wifi_legacy_hal.cpp
index 5f40d50..c314e64 100644
--- a/wifi/1.2/default/wifi_legacy_hal.cpp
+++ b/wifi/1.2/default/wifi_legacy_hal.cpp
@@ -360,12 +360,18 @@
         LOG(DEBUG) << "Legacy HAL already started";
         return WIFI_SUCCESS;
     }
+    LOG(DEBUG) << "Waiting for the driver ready";
+    wifi_error status = global_func_table_.wifi_wait_for_driver_ready();
+    if (status == WIFI_ERROR_TIMED_OUT) {
+        LOG(ERROR) << "Timed out awaiting driver ready";
+        return status;
+    }
     LOG(DEBUG) << "Starting legacy HAL";
     if (!iface_tool_.SetWifiUpState(true)) {
         LOG(ERROR) << "Failed to set WiFi interface up";
         return WIFI_ERROR_UNKNOWN;
     }
-    wifi_error status = global_func_table_.wifi_initialize(&global_handle_);
+    status = global_func_table_.wifi_initialize(&global_handle_);
     if (status != WIFI_SUCCESS || !global_handle_) {
         LOG(ERROR) << "Failed to retrieve global handle";
         return status;
@@ -486,6 +492,28 @@
         getIfaceHandle(iface_name), program.data(), program.size());
 }
 
+std::pair<wifi_error, std::vector<uint8_t>>
+WifiLegacyHal::readApfPacketFilterData(const std::string& iface_name) {
+    if (global_func_table_.wifi_read_packet_filter == nullptr) {
+        return {WIFI_ERROR_NOT_SUPPORTED, {}};
+    }
+
+    PacketFilterCapabilities caps;
+    wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
+        getIfaceHandle(iface_name), &caps.version, &caps.max_len);
+    if (status != WIFI_SUCCESS) {
+        return {status, {}};
+    }
+
+    // Size the buffer to read the entire program & work memory.
+    std::vector<uint8_t> buffer(caps.max_len);
+
+    status = global_func_table_.wifi_read_packet_filter(
+        getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(),
+        buffer.size());
+    return {status, move(buffer)};
+}
+
 std::pair<wifi_error, wifi_gscan_capabilities>
 WifiLegacyHal::getGscanCapabilities(const std::string& iface_name) {
     wifi_gscan_capabilities caps;
diff --git a/wifi/1.2/default/wifi_legacy_hal.h b/wifi/1.2/default/wifi_legacy_hal.h
index dedbbf8..60905ab 100644
--- a/wifi/1.2/default/wifi_legacy_hal.h
+++ b/wifi/1.2/default/wifi_legacy_hal.h
@@ -156,7 +156,7 @@
  * Class that encapsulates all legacy HAL interactions.
  * This class manages the lifetime of the event loop thread used by legacy HAL.
  *
- * Note: aThere will only be a single instance of this class created in the Wifi
+ * Note: There will only be a single instance of this class created in the Wifi
  * object and will be valid for the lifetime of the process.
  */
 class WifiLegacyHal {
@@ -188,6 +188,8 @@
         const std::string& iface_name);
     wifi_error setPacketFilter(const std::string& iface_name,
                                const std::vector<uint8_t>& program);
+    std::pair<wifi_error, std::vector<uint8_t>> readApfPacketFilterData(
+        const std::string& iface_name);
     // Gscan functions.
     std::pair<wifi_error, wifi_gscan_capabilities> getGscanCapabilities(
         const std::string& iface_name);
diff --git a/wifi/1.2/default/wifi_legacy_hal_stubs.cpp b/wifi/1.2/default/wifi_legacy_hal_stubs.cpp
index 2ee2aa2..24aaf15 100644
--- a/wifi/1.2/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.2/default/wifi_legacy_hal_stubs.cpp
@@ -45,6 +45,7 @@
         return false;
     }
     populateStubFor(&hal_fn->wifi_initialize);
+    populateStubFor(&hal_fn->wifi_wait_for_driver_ready);
     populateStubFor(&hal_fn->wifi_cleanup);
     populateStubFor(&hal_fn->wifi_event_loop);
     populateStubFor(&hal_fn->wifi_get_error_info);
diff --git a/wifi/1.2/default/wifi_sta_iface.cpp b/wifi/1.2/default/wifi_sta_iface.cpp
index 6faf009..daa5610 100644
--- a/wifi/1.2/default/wifi_sta_iface.cpp
+++ b/wifi/1.2/default/wifi_sta_iface.cpp
@@ -94,6 +94,13 @@
                            hidl_status_cb, cmd_id, program);
 }
 
+Return<void> WifiStaIface::readApfPacketFilterData(
+    readApfPacketFilterData_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::readApfPacketFilterDataInternal,
+                           hidl_status_cb);
+}
+
 Return<void> WifiStaIface::getBackgroundScanCapabilities(
     getBackgroundScanCapabilities_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
@@ -234,6 +241,13 @@
                            hidl_status_cb);
 }
 
+Return<void> WifiStaIface::setMacAddress(const hidl_array<uint8_t, 6>& mac,
+                                         setMacAddress_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::setMacAddressInternal, hidl_status_cb,
+                           mac);
+}
+
 std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() {
     return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
 }
@@ -297,6 +311,15 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
+std::pair<WifiStatus, std::vector<uint8_t>>
+WifiStaIface::readApfPacketFilterDataInternal() {
+    const std::pair<legacy_hal::wifi_error, std::vector<uint8_t>>
+        legacy_status_and_data =
+            legacy_hal_.lock()->readApfPacketFilterData(ifname_);
+    return {createWifiStatusFromLegacyError(legacy_status_and_data.first),
+            std::move(legacy_status_and_data.second)};
+}
+
 std::pair<WifiStatus, StaBackgroundScanCapabilities>
 WifiStaIface::getBackgroundScanCapabilitiesInternal() {
     legacy_hal::wifi_error legacy_status;
@@ -578,6 +601,26 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
 }
 
+WifiStatus WifiStaIface::setMacAddressInternal(
+    const std::array<uint8_t, 6>& mac) {
+    if (!iface_tool_.SetWifiUpState(false)) {
+        LOG(ERROR) << "SetWifiUpState(false) failed.";
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+
+    if (!iface_tool_.SetMacAddress(ifname_.c_str(), mac)) {
+        LOG(ERROR) << "SetMacAddress failed.";
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+
+    if (!iface_tool_.SetWifiUpState(true)) {
+        LOG(ERROR) << "SetWifiUpState(true) failed.";
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    LOG(DEBUG) << "Successfully SetMacAddress.";
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
 }  // namespace implementation
 }  // namespace V1_2
 }  // namespace wifi
diff --git a/wifi/1.2/default/wifi_sta_iface.h b/wifi/1.2/default/wifi_sta_iface.h
index 423365c..71cd17d 100644
--- a/wifi/1.2/default/wifi_sta_iface.h
+++ b/wifi/1.2/default/wifi_sta_iface.h
@@ -18,8 +18,10 @@
 #define WIFI_STA_IFACE_H_
 
 #include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiStaIface.h>
 #include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
+#include <android/hardware/wifi/1.2/IWifiStaIface.h>
+
+#include <wifi_system/interface_tool.h>
 
 #include "hidl_callback_util.h"
 #include "wifi_legacy_hal.h"
@@ -34,7 +36,7 @@
 /**
  * HIDL interface object used to control a STA Iface instance.
  */
-class WifiStaIface : public V1_0::IWifiStaIface {
+class WifiStaIface : public V1_2::IWifiStaIface {
    public:
     WifiStaIface(const std::string& ifname,
                  const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
@@ -56,6 +58,8 @@
     Return<void> installApfPacketFilter(
         uint32_t cmd_id, const hidl_vec<uint8_t>& program,
         installApfPacketFilter_cb hidl_status_cb) override;
+    Return<void> readApfPacketFilterData(
+        readApfPacketFilterData_cb hidl_status_cb) override;
     Return<void> getBackgroundScanCapabilities(
         getBackgroundScanCapabilities_cb hidl_status_cb) override;
     Return<void> getValidFrequenciesForBand(
@@ -101,6 +105,8 @@
         getDebugTxPacketFates_cb hidl_status_cb) override;
     Return<void> getDebugRxPacketFates(
         getDebugRxPacketFates_cb hidl_status_cb) override;
+    Return<void> setMacAddress(const hidl_array<uint8_t, 6>& mac,
+                               setMacAddress_cb hidl_status_cb) override;
 
    private:
     // Corresponding worker functions for the HIDL methods.
@@ -113,6 +119,8 @@
     getApfPacketFilterCapabilitiesInternal();
     WifiStatus installApfPacketFilterInternal(
         uint32_t cmd_id, const std::vector<uint8_t>& program);
+    std::pair<WifiStatus, std::vector<uint8_t>>
+    readApfPacketFilterDataInternal();
     std::pair<WifiStatus, StaBackgroundScanCapabilities>
     getBackgroundScanCapabilitiesInternal();
     std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
@@ -142,12 +150,14 @@
     getDebugTxPacketFatesInternal();
     std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
     getDebugRxPacketFatesInternal();
+    WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
 
     std::string ifname_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
     bool is_valid_;
     hidl_callback_util::HidlCallbackHandler<IWifiStaIfaceEventCallback>
         event_cb_handler_;
+    wifi_system::InterfaceTool iface_tool_;
 
     DISALLOW_COPY_AND_ASSIGN(WifiStaIface);
 };
diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp
index d85d42e..918e4a4 100644
--- a/wifi/1.2/vts/functional/Android.bp
+++ b/wifi/1.2/vts/functional/Android.bp
@@ -20,6 +20,7 @@
     srcs: [
         "VtsHalWifiV1_2TargetTest.cpp",
         "wifi_chip_hidl_test.cpp",
+        "wifi_sta_iface_hidl_test.cpp",
     ],
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
diff --git a/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp
new file mode 100644
index 0000000..fd4a671
--- /dev/null
+++ b/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Staache 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 <android/hardware/wifi/1.2/IWifiStaIface.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include "wifi_hidl_call_util.h"
+#include "wifi_hidl_test_utils.h"
+
+using ::android::sp;
+using ::android::hardware::wifi::V1_2::IWifiStaIface;
+using ::android::hardware::wifi::V1_0::WifiStatusCode;
+
+/**
+ * Fixture to use for all STA Iface HIDL interface tests.
+ */
+class WifiStaIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        wifi_sta_iface_ = IWifiStaIface::castFrom(getWifiStaIface());
+        ASSERT_NE(nullptr, wifi_sta_iface_.get());
+    }
+
+    virtual void TearDown() override { stopWifi(); }
+
+   protected:
+    sp<IWifiStaIface> wifi_sta_iface_;
+};
+
+/*
+ * SetMacAddress:
+ * Ensures that calls to set MAC address will return a success status
+ * code.
+ */
+TEST_F(WifiStaIfaceHidlTest, SetMacAddress) {
+    const android::hardware::hidl_array<uint8_t, 6> kMac{
+        std::array<uint8_t, 6>{{0x12, 0x22, 0x33, 0x52, 0x10, 0x41}}};
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, setMacAddress, kMac).code);
+}
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
index 5f51cfb..504f4c8 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
@@ -220,3 +220,11 @@
                     getInvalidPskNwParams());
     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
+
+/*
+ * Terminate
+ * This terminates the service.
+ */
+TEST_F(HostapdHidlTest, Terminate) {
+    hostapd_->terminate();
+}
diff --git a/wifi/supplicant/1.1/Android.bp b/wifi/supplicant/1.1/Android.bp
index fafd6ad..832d1ad 100644
--- a/wifi/supplicant/1.1/Android.bp
+++ b/wifi/supplicant/1.1/Android.bp
@@ -8,6 +8,8 @@
     },
     srcs: [
         "ISupplicant.hal",
+        "ISupplicantStaIface.hal",
+        "ISupplicantStaIfaceCallback.hal",
         "ISupplicantStaNetwork.hal",
     ],
     interfaces: [
diff --git a/wifi/supplicant/1.1/ISupplicantStaIface.hal b/wifi/supplicant/1.1/ISupplicantStaIface.hal
new file mode 100644
index 0000000..025cc6a
--- /dev/null
+++ b/wifi/supplicant/1.1/ISupplicantStaIface.hal
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package android.hardware.wifi.supplicant@1.1;
+
+import @1.0::ISupplicantStaIface;
+import @1.1::ISupplicantStaIfaceCallback;
+import @1.0::SupplicantStatus;
+
+/**
+ * Interface exposed by the supplicant for each station mode network
+ * interface (e.g wlan0) it controls.
+ */
+interface ISupplicantStaIface extends @1.0::ISupplicantStaIface {
+
+    /**
+     * Register for callbacks from this interface.
+     *
+     * These callbacks are invoked for events that are specific to this interface.
+     * Registration of multiple callback objects is supported. These objects must
+     * be automatically deleted when the corresponding client process is dead or
+     * if this interface is removed.
+     *
+     * @param callback An instance of the |ISupplicantStaIfaceCallback| HIDL
+     *        interface object.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    registerCallback_1_1(ISupplicantStaIfaceCallback callback)
+        generates (SupplicantStatus status);
+};
+
diff --git a/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.hal
new file mode 100644
index 0000000..8b92ee5
--- /dev/null
+++ b/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.hal
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package android.hardware.wifi.supplicant@1.1;
+
+import @1.0::ISupplicantStaIfaceCallback;
+
+/**
+ * Callback Interface exposed by the supplicant service
+ * for each station mode interface (ISupplicantStaIface).
+ *
+ * Clients need to host an instance of this HIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * corresponding |ISupplicantStaIface.registerCallback_1_1| method.
+ */
+interface ISupplicantStaIfaceCallback extends @1.0::ISupplicantStaIfaceCallback {
+
+    /* EapErrorCode: Error code for EAP or EAP Method as per RFC-4186 */
+    enum EapErrorCode : uint32_t {
+        SIM_GENERAL_FAILURE_AFTER_AUTH = 0,
+        SIM_TEMPORARILY_DENIED = 1026,
+        SIM_NOT_SUBSCRIBED = 1031,
+        SIM_GENERAL_FAILURE_BEFORE_AUTH = 16384,
+        SIM_VENDOR_SPECIFIC_EXPIRED_CERT = 16385,
+    };
+
+    /**
+     * Used to indicate an EAP authentication failure.
+     */
+    oneway onEapFailure_1_1(EapErrorCode errorCode);
+};
+
diff --git a/wifi/supplicant/1.1/vts/functional/Android.bp b/wifi/supplicant/1.1/vts/functional/Android.bp
index 3efe15d..3e65453 100644
--- a/wifi/supplicant/1.1/vts/functional/Android.bp
+++ b/wifi/supplicant/1.1/vts/functional/Android.bp
@@ -40,6 +40,7 @@
     srcs: [
         "VtsHalWifiSupplicantV1_1TargetTest.cpp",
         "supplicant_hidl_test.cpp",
+        "supplicant_sta_iface_hidl_test.cpp",
         "supplicant_sta_network_hidl_test.cpp",
     ],
     static_libs: [
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp
index c29fd0a..7e773d6 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp
@@ -137,3 +137,11 @@
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
         });
 }
+
+/*
+ * Terminate
+ * This terminates the service.
+ */
+TEST_F(SupplicantHidlTest, Terminate) {
+    supplicant_->terminate();
+}
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp
index 3f17740..04a5ed9 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp
@@ -21,6 +21,7 @@
 #include "supplicant_hidl_test_utils_1_1.h"
 
 using ::android::hardware::wifi::supplicant::V1_1::ISupplicant;
+using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface;
 using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaNetwork;
 using ::android::sp;
 
@@ -28,6 +29,10 @@
     return ISupplicant::castFrom(getSupplicant());
 }
 
+sp<ISupplicantStaIface> getSupplicantStaIface_1_1() {
+    return ISupplicantStaIface::castFrom(getSupplicantStaIface());
+}
+
 sp<ISupplicantStaNetwork> createSupplicantStaNetwork_1_1() {
     return ISupplicantStaNetwork::castFrom(createSupplicantStaNetwork());
 }
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
index e7ce54a..1c13325 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
@@ -18,11 +18,15 @@
 #define SUPPLICANT_HIDL_TEST_UTILS_1_1_H
 
 #include <android/hardware/wifi/supplicant/1.1/ISupplicant.h>
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIface.h>
 #include <android/hardware/wifi/supplicant/1.1/ISupplicantStaNetwork.h>
 
 android::sp<android::hardware::wifi::supplicant::V1_1::ISupplicant>
     getSupplicant_1_1();
 
+android::sp<android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface>
+    getSupplicantStaIface_1_1();
+
 android::sp<android::hardware::wifi::supplicant::V1_1::ISupplicantStaNetwork>
     createSupplicantStaNetwork_1_1();
 
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
new file mode 100644
index 0000000..c5e6319
--- /dev/null
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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 <android/hardware/wifi/supplicant/1.1/ISupplicantStaIface.h>
+
+#include "supplicant_hidl_test_utils.h"
+#include "supplicant_hidl_test_utils_1_1.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface;
+using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIfaceCallback;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+
+class SupplicantStaIfaceHidlTest
+    : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+  virtual void SetUp() override {
+      startSupplicantAndWaitForHidlService();
+      EXPECT_TRUE(turnOnExcessiveLogging());
+      sta_iface_ = getSupplicantStaIface_1_1();
+      ASSERT_NE(sta_iface_.get(), nullptr);
+  }
+
+  virtual void TearDown() override { stopSupplicant(); }
+
+ protected:
+  // ISupplicantStaIface object used for all tests in this fixture.
+  sp<ISupplicantStaIface> sta_iface_;
+};
+
+class IfaceCallback : public ISupplicantStaIfaceCallback {
+    Return<void> onNetworkAdded(uint32_t /* id */) override { return Void(); }
+    Return<void> onNetworkRemoved(uint32_t /* id */) override { return Void(); }
+    Return<void> onStateChanged(
+        ISupplicantStaIfaceCallback::State /* newState */,
+        const hidl_array<uint8_t, 6>& /*bssid */, uint32_t /* id */,
+        const hidl_vec<uint8_t>& /* ssid */) override {
+        return Void();
+    }
+    Return<void> onAnqpQueryDone(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        const ISupplicantStaIfaceCallback::AnqpData& /* data */,
+        const ISupplicantStaIfaceCallback::Hs20AnqpData& /* hs20Data */)
+        override {
+        return Void();
+    }
+    virtual Return<void> onHs20IconQueryDone(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        const hidl_string& /* fileName */,
+        const hidl_vec<uint8_t>& /* data */) override {
+        return Void();
+    }
+    virtual Return<void> onHs20SubscriptionRemediation(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        ISupplicantStaIfaceCallback::OsuMethod /* osuMethod */,
+        const hidl_string& /* url*/) override {
+        return Void();
+    }
+    Return<void> onHs20DeauthImminentNotice(
+        const hidl_array<uint8_t, 6>& /* bssid */, uint32_t /* reasonCode */,
+        uint32_t /* reAuthDelayInSec */,
+        const hidl_string& /* url */) override {
+        return Void();
+    }
+    Return<void> onDisconnected(const hidl_array<uint8_t, 6>& /* bssid */,
+                                bool /* locallyGenerated */,
+                                ISupplicantStaIfaceCallback::ReasonCode
+                                /* reasonCode */) override {
+        return Void();
+    }
+    Return<void> onAssociationRejected(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        ISupplicantStaIfaceCallback::StatusCode /* statusCode */,
+        bool /*timedOut */) override {
+        return Void();
+    }
+    Return<void> onAuthenticationTimeout(
+        const hidl_array<uint8_t, 6>& /* bssid */) override {
+        return Void();
+    }
+    Return<void> onBssidChanged(
+        ISupplicantStaIfaceCallback::BssidChangeReason /* reason */,
+        const hidl_array<uint8_t, 6>& /* bssid */) override {
+        return Void();
+    }
+    Return<void> onEapFailure() override { return Void(); }
+    Return<void> onEapFailure_1_1(
+        ISupplicantStaIfaceCallback::EapErrorCode /* eapErrorCode */) override {
+        return Void();
+    }
+    Return<void> onWpsEventSuccess() override { return Void(); }
+    Return<void> onWpsEventFail(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        ISupplicantStaIfaceCallback::WpsConfigError /* configError */,
+        ISupplicantStaIfaceCallback::WpsErrorIndication /* errorInd */)
+        override {
+        return Void();
+    }
+    Return<void> onWpsEventPbcOverlap() override { return Void(); }
+    Return<void> onExtRadioWorkStart(uint32_t /* id */) override {
+        return Void();
+    }
+    Return<void> onExtRadioWorkTimeout(uint32_t /* id*/) override {
+        return Void();
+    }
+};
+
+/*
+ * RegisterCallback_1_1
+ */
+TEST_F(SupplicantStaIfaceHidlTest, RegisterCallback_1_1) {
+  sta_iface_->registerCallback_1_1(
+      new IfaceCallback(), [](const SupplicantStatus& status) {
+          EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+      });
+}