Merge "vibrator: vts: correct the checking flag when testing on() interfaces"
diff --git a/audio/7.0/IDevice.hal b/audio/7.0/IDevice.hal
index eecd92e..e30e545 100644
--- a/audio/7.0/IDevice.hal
+++ b/audio/7.0/IDevice.hal
@@ -117,7 +117,7 @@
             AudioIoHandle ioHandle,
             DeviceAddress device,
             AudioConfig config,
-            bitfield<AudioOutputFlag> flags,
+            vec<AudioInOutFlag> flags,
             SourceMetadata sourceMetadata) generates (
                     Result retval,
                     IStreamOut outStream,
@@ -142,7 +142,7 @@
             AudioIoHandle ioHandle,
             DeviceAddress device,
             AudioConfig config,
-            bitfield<AudioInputFlag> flags,
+            vec<AudioInOutFlag> flags,
             SinkMetadata sinkMetadata) generates (
                     Result retval,
                     IStreamIn inStream,
diff --git a/audio/7.0/IStream.hal b/audio/7.0/IStream.hal
index 789cb1d..4fe8218 100644
--- a/audio/7.0/IStream.hal
+++ b/audio/7.0/IStream.hal
@@ -44,49 +44,23 @@
     getBufferSize() generates (uint64_t bufferSize);
 
     /**
-     * Return supported native sampling rates of the stream for a given format.
-     * A supported native sample rate is a sample rate that can be efficiently
-     * played by the hardware (typically without sample-rate conversions).
+     * Return supported audio profiles for this particular stream. This method
+     * is normally called for streams opened on devices that use dynamic
+     * profiles, e.g. HDMI and USB interfaces. Please note that supported
+     * profiles of the stream may differ from the capabilities of the connected
+     * physical device.
      *
-     * This function is only called for dynamic profile. If called for
-     * non-dynamic profile is should return NOT_SUPPORTED or the same list
-     * as in audio_policy_configuration.xml.
-     *
-     * Calling this method is equivalent to getting
-     * AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES on the legacy HAL.
-     *
-     *
-     * @param format audio format for which the sample rates are supported.
-     * @return retval operation completion status.
-     *                Must be OK if the format is supported.
-     * @return sampleRateHz supported sample rates.
-     */
-    getSupportedSampleRates(AudioFormat format)
-            generates (Result retval, vec<uint32_t> sampleRates);
-
-    /**
-     * Return supported channel masks of the stream. Calling this method is
-     * equivalent to getting AUDIO_PARAMETER_STREAM_SUP_CHANNELS on the legacy
-     * HAL.
-     *
-     * @param format audio format for which the channel masks are supported.
-     * @return retval operation completion status.
-     *                Must be OK if the format is supported.
-     * @return masks supported audio masks.
-     */
-    getSupportedChannelMasks(AudioFormat format)
-            generates (Result retval, vec<vec<AudioChannelMask>> masks);
-
-    /**
-     * Return supported audio formats of the stream. Calling this method is
-     * equivalent to getting AUDIO_PARAMETER_STREAM_SUP_FORMATS on the legacy
-     * HAL.
+     * For devices with fixed configurations, e.g. built-in audio devices, all
+     * the profiles are specified in the audio_policy_configuration.xml
+     * file. For such devices, this method must return the configuration from
+     * the config file, or NOT_SUPPORTED retval.
      *
      * @return retval operation completion status.
-     * @return formats supported audio formats.
+     * @return formats supported audio profiles.
      *                 Must be non empty if retval is OK.
      */
-    getSupportedFormats() generates (Result retval, vec<AudioFormat> formats);
+    getSupportedProfiles()
+            generates (Result retval, vec<AudioProfile> profiles);
 
     /**
      * Retrieves basic stream configuration: sample rate, audio format,
@@ -94,18 +68,18 @@
      *
      * @return config basic stream configuration.
      */
-    getAudioProperties() generates (AudioBasicConfig config);
+    getAudioProperties() generates (AudioConfigBase config);
 
     /**
      * Sets stream parameters. Only sets parameters that are specified.
-     * See the description of AudioBasicConfig for the details.
+     * See the description of AudioConfigBase for the details.
      *
      * Optional method. If implemented, only called on a stopped stream.
      *
      * @param config basic stream configuration.
      * @return retval operation completion status.
      */
-    setAudioProperties(AudioBasicConfig config) generates (Result retval);
+    setAudioProperties(AudioConfigBase config) generates (Result retval);
 
     /**
      * Applies audio effect to the stream.
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt
index fd9a8ef..ac8dc8a 100644
--- a/audio/7.0/config/api/current.txt
+++ b/audio/7.0/config/api/current.txt
@@ -228,6 +228,33 @@
     enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_WMA_PRO;
   }
 
+  public enum AudioInOutFlag {
+    method public String getRawName();
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_DIRECT;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_FAST;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_HW_AV_SYNC;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_HW_HOTWORD;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_MMAP_NOIRQ;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_RAW;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_SYNC;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_VOIP_TX;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT_PCM;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_FAST;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_NON_BLOCKING;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_PRIMARY;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_RAW;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_SYNC;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_TTS;
+    enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_VOIP_RX;
+  }
+
   public class AudioPolicyConfiguration {
     ctor public AudioPolicyConfiguration();
     method public audio.policy.configuration.V7_0.GlobalConfiguration getGlobalConfiguration();
@@ -396,7 +423,7 @@
 
   public static class MixPorts.MixPort {
     ctor public MixPorts.MixPort();
-    method public String getFlags();
+    method public java.util.List<audio.policy.configuration.V7_0.AudioInOutFlag> getFlags();
     method public audio.policy.configuration.V7_0.Gains getGains();
     method public long getMaxActiveCount();
     method public long getMaxOpenCount();
@@ -404,7 +431,7 @@
     method public java.util.List<audio.policy.configuration.V7_0.AudioUsage> getPreferredUsage();
     method public java.util.List<audio.policy.configuration.V7_0.Profile> getProfile();
     method public audio.policy.configuration.V7_0.Role getRole();
-    method public void setFlags(String);
+    method public void setFlags(java.util.List<audio.policy.configuration.V7_0.AudioInOutFlag>);
     method public void setGains(audio.policy.configuration.V7_0.Gains);
     method public void setMaxActiveCount(long);
     method public void setMaxOpenCount(long);
diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd
index 4555a88..20fe020 100644
--- a/audio/7.0/config/audio_policy_configuration.xsd
+++ b/audio/7.0/config/audio_policy_configuration.xsd
@@ -155,16 +155,41 @@
             <xs:element name="item" type="xs:token" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
-    <xs:simpleType name="audioInOutFlags">
+    <xs:simpleType name="audioInOutFlag">
         <xs:annotation>
             <xs:documentation xml:lang="en">
-                "|" separated list of audio_output_flags_t or audio_input_flags_t.
+              The flags indicate suggested stream attributes supported by the profile.
             </xs:documentation>
         </xs:annotation>
         <xs:restriction base="xs:string">
-            <xs:pattern value="|[_A-Z]+(\|[_A-Z]+)*"/>
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_DIRECT" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_PRIMARY" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_FAST" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_DEEP_BUFFER" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_NON_BLOCKING" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_HW_AV_SYNC" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_TTS" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_RAW" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_SYNC" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_DIRECT_PCM" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_MMAP_NOIRQ" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_VOIP_RX" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_INCALL_MUSIC" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_FAST" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_HW_HOTWORD" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_RAW" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_SYNC" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_MMAP_NOIRQ" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_VOIP_TX" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_HW_AV_SYNC" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_DIRECT" />
         </xs:restriction>
     </xs:simpleType>
+    <xs:simpleType name="audioInOutFlags">
+        <xs:list itemType="audioInOutFlag" />
+    </xs:simpleType>
     <xs:simpleType name="role">
         <xs:restriction base="xs:string">
             <xs:enumeration value="sink"/>
diff --git a/audio/7.0/config/update_audio_policy_config.sh b/audio/7.0/config/update_audio_policy_config.sh
index 8714b5f..051a0df 100755
--- a/audio/7.0/config/update_audio_policy_config.sh
+++ b/audio/7.0/config/update_audio_policy_config.sh
@@ -128,6 +128,7 @@
 for F in $SOURCE_FILES; do
     updateFile ${F} "channelMasks" ","
     updateFile ${F} "samplingRates" ","
+    updateFile ${F} "flags" "|"
 done;
 
 updateIncludes() {
diff --git a/audio/7.0/types.hal b/audio/7.0/types.hal
index 15ca492..4a9e289 100644
--- a/audio/7.0/types.hal
+++ b/audio/7.0/types.hal
@@ -357,56 +357,15 @@
 };
 
 /**
- * The audio output flags serve two purposes:
+ * The audio flags serve two purposes:
  *
- *  - when an output stream is created they indicate its attributes;
+ *  - when a stream is created they indicate its attributes;
  *
- *  - when present in an output profile descriptor listed for a particular audio
- *    hardware module, they indicate that an output stream can be opened that
+ *  - when present in a profile descriptor listed for a particular audio
+ *    hardware module, they indicate that a stream can be opened that
  *    supports the attributes indicated by the flags.
+ *
+ * See 'audioIoFlag' in audio_policy_configuration.xsd for the
+ * list of allowed values.
  */
-@export(name="audio_output_flags_t", value_prefix="AUDIO_OUTPUT_FLAG_")
-enum AudioOutputFlag : int32_t {
-    NONE    = 0x0, // no attributes
-    DIRECT  = 0x1, // this output directly connects a track
-                   // to one output stream: no software mixer
-    PRIMARY = 0x2, // this output is the primary output of the device. It is
-                   // unique and must be present. It is opened by default and
-                   // receives routing, audio mode and volume controls related
-                   // to voice calls.
-    FAST    = 0x4,    // output supports "fast tracks", defined elsewhere
-    DEEP_BUFFER      = 0x8,   // use deep audio buffers
-    COMPRESS_OFFLOAD = 0x10,  // offload playback of compressed streams to
-                              // hardware codec
-    NON_BLOCKING     = 0x20,  // use non-blocking write
-    HW_AV_SYNC = 0x40,   // output uses a hardware A/V sync
-    TTS        = 0x80,   // output for streams transmitted through speaker at a
-                         // sample rate high enough to accommodate lower-range
-                         // ultrasonic p/b
-    RAW        = 0x100,  // minimize signal processing
-    SYNC       = 0x200,  // synchronize I/O streams
-    IEC958_NONAUDIO = 0x400, // Audio stream contains compressed audio in SPDIF
-                             // data bursts, not PCM.
-    DIRECT_PCM = 0x2000,     // Audio stream containing PCM data that needs
-                             // to pass through compress path for DSP post proc.
-    MMAP_NOIRQ = 0x4000, // output operates in MMAP no IRQ mode.
-    VOIP_RX = 0x8000,    // preferred output for VoIP calls.
-    /** preferred output for call music */
-    INCALL_MUSIC = 0x10000,
-};
-
-/**
- * The audio input flags are analogous to audio output flags.
- */
-@export(name="audio_input_flags_t", value_prefix="AUDIO_INPUT_FLAG_")
-enum AudioInputFlag : int32_t {
-    NONE         = 0x0,  // no attributes
-    FAST         = 0x1,  // prefer an input that supports "fast tracks"
-    HW_HOTWORD   = 0x2,  // prefer an input that captures from hw hotword source
-    RAW          = 0x4,  // minimize signal processing
-    SYNC         = 0x8,  // synchronize I/O streams
-    MMAP_NOIRQ   = 0x10, // input operates in MMAP no IRQ mode.
-    VOIP_TX      = 0x20, // preferred input for VoIP calls.
-    HW_AV_SYNC   = 0x40, // input connected to an output that uses a hardware A/V sync
-    DIRECT       = 0x80, // for acquiring encoded streams
-};
+typedef string AudioInOutFlag;
diff --git a/audio/README b/audio/README
deleted file mode 100644
index afafbe3..0000000
--- a/audio/README
+++ /dev/null
@@ -1,36 +0,0 @@
-Directory structure of the audio HIDL related code.
-
-Run `common/all-versions/copyHAL.sh` to create a new version of the audio HAL
-based on an existing one.
-
-audio
-|-- 2.0              <== core 2.0 HIDL API. .hal can not be moved into the core directory
-|                        because that would change its namespace and include path
-|-- 4.0              <== Version 4.0 of the core API
-|
-|-- ...
-|
-|-- common           <== code common to audio core and effect API
-|   |-- 2.0          <== HIDL API of V2
-|   |-- 4.0
-|   |-- ...
-|   `-- all-versions <== code common to all version of both core and effect API
-|       |-- default  <== implementation shared code between core and effect impl
-|       |-- test     <== utilities used by tests
-|       `-- util     <== utilities used by both implementation and tests
-|
-|-- core             <== VTS and default implementation of the core API (not HIDL, see /audio/2.0))
-|   `-- all-versions <== Code is version independent through #if and separate files
-|       |-- default  <== code that wraps the legacy API
-|       `-- vts      <== vts of core API
-|           |-- 2.0  <== 2.0 specific tests and helpers
-|           |-- 4.0
-|           |-- ...
-|
-`-- effect           <== idem for the effect API
-    |-- 2.0
-    |-- 4.0
-    |-- ...
-    `-- all-versions
-        |-- default
-        `-- vts
diff --git a/audio/README.md b/audio/README.md
new file mode 100644
index 0000000..b77b9ba
--- /dev/null
+++ b/audio/README.md
@@ -0,0 +1,53 @@
+# Audio HAL
+
+Directory structure of the audio HAL related code.
+
+Run `common/all-versions/copyHAL.sh` to create a new version of the audio HAL
+based on an existing one.
+
+## Directory Structure
+
+* `2.0` -- version 2.0 of the core HIDL API. Note that `.hal` files
+  can not be moved into the `core` directory because that would change
+  its namespace and include path.
+   - `config` -- the XSD schema for the Audio Policy Manager
+     configuration file.
+* `4.0` -- version 4.0 of the core HIDL API.
+* ...
+* `common` -- common types for audio core and effect HIDL API.
+   - `2.0` -- version 2.0 of the common types HIDL API.
+   - `4.0` -- version 4.0.
+   - ...
+   - `7.0` -- version 7.0.
+      - `example` -- example implementation of the core and effect
+        V7.0 API. It represents a "fake" audio HAL that doesn't
+        actually communicate with hardware.
+   - `all-versions` -- code common to all version of both core and effect API.
+      - `default` -- shared code of the default implementation.
+         - `service` -- vendor HAL service for hosting the default
+           implementation.
+      - `test` -- utilities used by tests.
+      - `util` -- utilities used by both implementation and tests.
+* `core` -- VTS tests and the default implementation of the core API
+  (not HIDL API, it's in `audio/N.M`).
+   - `7.0` -- code specific to version V7.0 of the core HIDL API
+   - `all-versions` -- the code is common between all versions,
+     version-specific parts are enclosed into conditional directives
+     of preprocessor or reside in dedicated files.
+       - `default` -- code that wraps the legacy API (from
+         `hardware/libhardware`).
+       - `vts` VTS tests for the core HIDL API.
+* `effect` -- same for the effect HIDL API.
+   - `2.0`
+      - `config` -- the XSD schema for the Audio Effects configuration
+        file.
+   - `4.0`
+   - ...
+   - `all-versions`
+      - `default`
+      - `vts`
+* `policy` -- Configurable Audio Policy schemes.
+   - `1.0` -- note that versions of CAP are not linked to the versions
+     of audio HAL.
+      - `vts` -- VTS tests for validating actual configuration files.
+      - `xml` -- XSD schemas for CAP configuration files.
diff --git a/audio/common/7.0/Android.bp b/audio/common/7.0/Android.bp
index e24871c..1c016b4 100644
--- a/audio/common/7.0/Android.bp
+++ b/audio/common/7.0/Android.bp
@@ -16,9 +16,12 @@
 cc_library {
     name: "android.hardware.audio.common@7.0-enums",
     vendor_available: true,
-    generated_sources: ["audio_policy_configuration_V7_0"],
     generated_headers: ["audio_policy_configuration_V7_0"],
+    generated_sources: ["audio_policy_configuration_V7_0"],
     header_libs: ["libxsdc-utils"],
+    export_generated_headers: ["audio_policy_configuration_V7_0"],
+    export_header_lib_headers: ["libxsdc-utils"],
+    export_include_dirs: ["enums/include"],
     shared_libs: [
         "libbase",
         "liblog",
diff --git a/audio/common/7.0/enums/include/audio_policy_configuration_V7_0-enums.h b/audio/common/7.0/enums/include/audio_policy_configuration_V7_0-enums.h
new file mode 100644
index 0000000..d5fedce
--- /dev/null
+++ b/audio/common/7.0/enums/include/audio_policy_configuration_V7_0-enums.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
+#define AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
+
+#include <sys/types.h>
+
+#include <audio_policy_configuration_V7_0.h>
+
+namespace audio::policy::configuration::V7_0 {
+
+static inline size_t getChannelCount(AudioChannelMask mask) {
+    switch (mask) {
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_MONO:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_1:
+            return 1;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO_HAPTIC_A:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_HAPTIC_AB:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_STEREO:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_FRONT_BACK:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_CALL_MONO:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_2:
+            return 2;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT1:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_3:
+            return 3;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT0POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD_BACK:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD_SIDE:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_SURROUND:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_2POINT0POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_4:
+            return 4;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT0POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_PENTA:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_2POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_3POINT0POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_5:
+            return 5;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1_BACK:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1_SIDE:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_6:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_3POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_5POINT1:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_6:
+            return 6;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_6POINT1:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_7:
+            return 7;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_8:
+            return 8;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_9:
+            return 9;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1POINT4:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_10:
+            return 10;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_11:
+            return 11;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1POINT4:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_12:
+            return 12;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_13:
+            return 13;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_14:
+            return 14;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_15:
+            return 15;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_16:
+            return 16;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_17:
+            return 17;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_18:
+            return 18;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_19:
+            return 19;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_20:
+            return 20;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_21:
+            return 21;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_22:
+            return 22;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_23:
+            return 23;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_24:
+            return 24;
+        case AudioChannelMask::UNKNOWN:
+            return 0;
+            // No default to make sure all cases are covered.
+    }
+    // This is to avoid undefined behavior if 'mask' isn't a valid enum value.
+    return 0;
+}
+
+static inline ssize_t getChannelCount(const std::string& mask) {
+    return getChannelCount(stringToAudioChannelMask(mask));
+}
+
+static inline bool isOutputDevice(AudioDevice device) {
+    switch (device) {
+        case AudioDevice::UNKNOWN:
+        case AudioDevice::AUDIO_DEVICE_NONE:
+            return false;
+        case AudioDevice::AUDIO_DEVICE_OUT_EARPIECE:
+        case AudioDevice::AUDIO_DEVICE_OUT_SPEAKER:
+        case AudioDevice::AUDIO_DEVICE_OUT_WIRED_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+        case AudioDevice::AUDIO_DEVICE_OUT_AUX_DIGITAL:
+        case AudioDevice::AUDIO_DEVICE_OUT_HDMI:
+        case AudioDevice::AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_OUT_USB_ACCESSORY:
+        case AudioDevice::AUDIO_DEVICE_OUT_USB_DEVICE:
+        case AudioDevice::AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
+        case AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX:
+        case AudioDevice::AUDIO_DEVICE_OUT_LINE:
+        case AudioDevice::AUDIO_DEVICE_OUT_HDMI_ARC:
+        case AudioDevice::AUDIO_DEVICE_OUT_SPDIF:
+        case AudioDevice::AUDIO_DEVICE_OUT_FM:
+        case AudioDevice::AUDIO_DEVICE_OUT_AUX_LINE:
+        case AudioDevice::AUDIO_DEVICE_OUT_SPEAKER_SAFE:
+        case AudioDevice::AUDIO_DEVICE_OUT_IP:
+        case AudioDevice::AUDIO_DEVICE_OUT_BUS:
+        case AudioDevice::AUDIO_DEVICE_OUT_PROXY:
+        case AudioDevice::AUDIO_DEVICE_OUT_USB_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_OUT_HEARING_AID:
+        case AudioDevice::AUDIO_DEVICE_OUT_ECHO_CANCELLER:
+        case AudioDevice::AUDIO_DEVICE_OUT_DEFAULT:
+        case AudioDevice::AUDIO_DEVICE_OUT_STUB:
+            return true;
+        case AudioDevice::AUDIO_DEVICE_IN_COMMUNICATION:
+        case AudioDevice::AUDIO_DEVICE_IN_AMBIENT:
+        case AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC:
+        case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_IN_WIRED_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_IN_AUX_DIGITAL:
+        case AudioDevice::AUDIO_DEVICE_IN_HDMI:
+        case AudioDevice::AUDIO_DEVICE_IN_VOICE_CALL:
+        case AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX:
+        case AudioDevice::AUDIO_DEVICE_IN_BACK_MIC:
+        case AudioDevice::AUDIO_DEVICE_IN_REMOTE_SUBMIX:
+        case AudioDevice::AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_IN_USB_ACCESSORY:
+        case AudioDevice::AUDIO_DEVICE_IN_USB_DEVICE:
+        case AudioDevice::AUDIO_DEVICE_IN_FM_TUNER:
+        case AudioDevice::AUDIO_DEVICE_IN_TV_TUNER:
+        case AudioDevice::AUDIO_DEVICE_IN_LINE:
+        case AudioDevice::AUDIO_DEVICE_IN_SPDIF:
+        case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_A2DP:
+        case AudioDevice::AUDIO_DEVICE_IN_LOOPBACK:
+        case AudioDevice::AUDIO_DEVICE_IN_IP:
+        case AudioDevice::AUDIO_DEVICE_IN_BUS:
+        case AudioDevice::AUDIO_DEVICE_IN_PROXY:
+        case AudioDevice::AUDIO_DEVICE_IN_USB_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_BLE:
+        case AudioDevice::AUDIO_DEVICE_IN_HDMI_ARC:
+        case AudioDevice::AUDIO_DEVICE_IN_ECHO_REFERENCE:
+        case AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
+        case AudioDevice::AUDIO_DEVICE_IN_STUB:
+            return false;
+            // No default to make sure all cases are covered.
+    }
+    // This is to avoid undefined behavior if 'device' isn't a valid enum value.
+    return false;
+}
+
+static inline bool isOutputDevice(const std::string& device) {
+    return isOutputDevice(stringToAudioDevice(device));
+}
+
+}  // namespace audio::policy::configuration::V7_0
+
+#endif  // AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
diff --git a/audio/common/7.0/example/Android.bp b/audio/common/7.0/example/Android.bp
new file mode 100644
index 0000000..03c1cd8
--- /dev/null
+++ b/audio/common/7.0/example/Android.bp
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_binary {
+    name: "android.hardware.audio@7.0-service.example",
+    vendor: true,
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.audio@7.0-service.example.rc"],
+    vintf_fragments: ["android.hardware.audio@7.0-service.example.xml"],
+    srcs: [
+        "DevicesFactory.cpp",
+        "Effect.cpp",
+        "EffectsFactory.cpp",
+        "EqualizerEffect.cpp",
+        "LoudnessEnhancerEffect.cpp",
+        "service.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libxml2",
+        "libutils",
+        "android.hardware.audio@7.0",
+        "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.0-enums",
+        "android.hardware.audio.effect@7.0",
+    ],
+}
diff --git a/audio/common/7.0/example/DevicesFactory.cpp b/audio/common/7.0/example/DevicesFactory.cpp
new file mode 100644
index 0000000..ddd5fef
--- /dev/null
+++ b/audio/common/7.0/example/DevicesFactory.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "DevicesFactory7.0"
+#include <log/log.h>
+
+#include "DevicesFactory.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+namespace android::hardware::audio::V7_0::implementation {
+
+Return<void> DevicesFactory::openDevice(const hidl_string& device, openDevice_cb _hidl_cb) {
+    (void)device;
+    _hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
+    return Void();
+}
+
+Return<void> DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) {
+    _hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
+    return Void();
+}
+
+}  // namespace android::hardware::audio::V7_0::implementation
diff --git a/audio/common/7.0/example/DevicesFactory.h b/audio/common/7.0/example/DevicesFactory.h
new file mode 100644
index 0000000..00f665c
--- /dev/null
+++ b/audio/common/7.0/example/DevicesFactory.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/audio/7.0/IDevicesFactory.h>
+
+namespace android::hardware::audio::V7_0::implementation {
+
+class DevicesFactory : public IDevicesFactory {
+  public:
+    DevicesFactory() = default;
+
+    ::android::hardware::Return<void> openDevice(const ::android::hardware::hidl_string& device,
+                                                 openDevice_cb _hidl_cb) override;
+
+    ::android::hardware::Return<void> openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override;
+};
+
+}  // namespace android::hardware::audio::V7_0::implementation
diff --git a/audio/common/7.0/example/Effect.cpp b/audio/common/7.0/example/Effect.cpp
new file mode 100644
index 0000000..423754d
--- /dev/null
+++ b/audio/common/7.0/example/Effect.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "EffectsFactory7.0"
+#include <log/log.h>
+
+#include <audio_policy_configuration_V7_0.h>
+
+#include "Effect.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using namespace ::android::hardware::audio::common::V7_0;
+// Make an alias for enumerations generated from the APM config XSD.
+namespace xsd {
+using namespace ::audio::policy::configuration::V7_0;
+}
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+Return<Result> Effect::init() {
+    return Result::OK;
+}
+
+Return<Result> Effect::setConfig(
+        const EffectConfig& config,
+        const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    (void)config;
+    (void)inputBufferProvider;
+    (void)outputBufferProvider;
+    return Result::OK;
+}
+
+Return<Result> Effect::reset() {
+    return Result::OK;
+}
+
+Return<Result> Effect::enable() {
+    if (!mEnabled) {
+        mEnabled = true;
+        return Result::OK;
+    } else {
+        return Result::NOT_SUPPORTED;
+    }
+}
+
+Return<Result> Effect::disable() {
+    if (mEnabled) {
+        mEnabled = false;
+        return Result::OK;
+    } else {
+        return Result::NOT_SUPPORTED;
+    }
+}
+
+Return<Result> Effect::setDevice(const DeviceAddress& device) {
+    (void)device;
+    return Result::OK;
+}
+
+Return<void> Effect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+                                     setAndGetVolume_cb _hidl_cb) {
+    (void)volumes;
+    _hidl_cb(Result::OK, hidl_vec<uint32_t>{});
+    return Void();
+}
+
+Return<Result> Effect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
+    (void)volumes;
+    return Result::OK;
+}
+
+Return<Result> Effect::setAudioMode(AudioMode mode) {
+    (void)mode;
+    return Result::OK;
+}
+
+Return<Result> Effect::setConfigReverse(
+        const EffectConfig& config,
+        const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    (void)config;
+    (void)inputBufferProvider;
+    (void)outputBufferProvider;
+    return Result::OK;
+}
+
+Return<Result> Effect::setInputDevice(const DeviceAddress& device) {
+    (void)device;
+    return Result::OK;
+}
+
+Return<void> Effect::getConfig(getConfig_cb _hidl_cb) {
+    const EffectConfig config = {{} /* inputCfg */,
+                                 // outputCfg
+                                 {{} /* buffer */,
+                                  48000 /* samplingRateHz */,
+                                  toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
+                                  toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT),
+                                  EffectBufferAccess::ACCESS_ACCUMULATE,
+                                  0 /* mask */}};
+    _hidl_cb(Result::OK, config);
+    return Void();
+}
+
+Return<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    _hidl_cb(Result::OK, EffectConfig{});
+    return Void();
+}
+
+Return<void> Effect::getSupportedAuxChannelsConfigs(uint32_t maxConfigs,
+                                                    getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    (void)maxConfigs;
+    _hidl_cb(Result::OK, hidl_vec<EffectAuxChannelsConfig>{});
+    return Void();
+}
+
+Return<void> Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    _hidl_cb(Result::OK, EffectAuxChannelsConfig{});
+    return Void();
+}
+
+Return<Result> Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
+    (void)config;
+    return Result::OK;
+}
+
+Return<Result> Effect::setAudioSource(const hidl_string& source) {
+    (void)source;
+    return Result::OK;
+}
+
+Return<Result> Effect::offload(const EffectOffloadParameter& param) {
+    (void)param;
+    return Result::OK;
+}
+
+Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    _hidl_cb(Result::OK, mDescriptor);
+    return Void();
+}
+
+Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    _hidl_cb(Result::OK, MQDescriptor<Result, kSynchronizedReadWrite>{});
+    return Void();
+}
+
+Return<Result> Effect::setProcessBuffers(const AudioBuffer& inBuffer,
+                                         const AudioBuffer& outBuffer) {
+    (void)inBuffer;
+    (void)outBuffer;
+    return Result::OK;
+}
+
+Return<void> Effect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+                             uint32_t resultMaxSize, command_cb _hidl_cb) {
+    (void)commandId;
+    (void)data;
+    (void)resultMaxSize;
+    _hidl_cb(-EINVAL, hidl_vec<uint8_t>{});
+    return Void();
+}
+
+Return<Result> Effect::setParameter(const hidl_vec<uint8_t>& parameter,
+                                    const hidl_vec<uint8_t>& value) {
+    (void)parameter;
+    (void)value;
+    return Result::OK;
+}
+
+Return<void> Effect::getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+                                  getParameter_cb _hidl_cb) {
+    (void)parameter;
+    (void)valueMaxSize;
+    _hidl_cb(Result::OK, hidl_vec<uint8_t>{});
+    return Void();
+}
+
+Return<void> Effect::getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+                                                   uint32_t configSize,
+                                                   getSupportedConfigsForFeature_cb _hidl_cb) {
+    (void)featureId;
+    (void)maxConfigs;
+    (void)configSize;
+    _hidl_cb(Result::OK, 0, hidl_vec<uint8_t>{});
+    return Void();
+}
+
+Return<void> Effect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+                                                getCurrentConfigForFeature_cb _hidl_cb) {
+    (void)featureId;
+    (void)configSize;
+    _hidl_cb(Result::OK, hidl_vec<uint8_t>{});
+    return Void();
+}
+
+Return<Result> Effect::setCurrentConfigForFeature(uint32_t featureId,
+                                                  const hidl_vec<uint8_t>& configData) {
+    (void)featureId;
+    (void)configData;
+    return Result::OK;
+}
+
+Return<Result> Effect::close() {
+    return Result::OK;
+}
+
+}  // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/Effect.h b/audio/common/7.0/example/Effect.h
new file mode 100644
index 0000000..fa7f41b
--- /dev/null
+++ b/audio/common/7.0/example/Effect.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/audio/effect/7.0/IEffect.h>
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+class Effect : public IEffect {
+  public:
+    explicit Effect(const EffectDescriptor& descriptor) : mDescriptor(descriptor) {}
+
+    ::android::hardware::Return<Result> init() override;
+    ::android::hardware::Return<Result> setConfig(
+            const EffectConfig& config,
+            const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    ::android::hardware::Return<Result> reset() override;
+    ::android::hardware::Return<Result> enable() override;
+    ::android::hardware::Return<Result> disable() override;
+    ::android::hardware::Return<Result> setDevice(
+            const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override;
+    ::android::hardware::Return<void> setAndGetVolume(
+            const ::android::hardware::hidl_vec<uint32_t>& volumes,
+            setAndGetVolume_cb _hidl_cb) override;
+    ::android::hardware::Return<Result> volumeChangeNotification(
+            const ::android::hardware::hidl_vec<uint32_t>& volumes) override;
+    ::android::hardware::Return<Result> setAudioMode(
+            ::android::hardware::audio::common::V7_0::AudioMode mode) override;
+    ::android::hardware::Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+    ::android::hardware::Return<Result> setInputDevice(
+            const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override;
+    ::android::hardware::Return<void> getConfig(getConfig_cb _hidl_cb) override;
+    ::android::hardware::Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+    ::android::hardware::Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+    ::android::hardware::Return<void> getAuxChannelsConfig(
+            getAuxChannelsConfig_cb _hidl_cb) override;
+    ::android::hardware::Return<Result> setAuxChannelsConfig(
+            const EffectAuxChannelsConfig& config) override;
+    ::android::hardware::Return<Result> setAudioSource(
+            const ::android::hardware::hidl_string& source) override;
+    ::android::hardware::Return<Result> offload(const EffectOffloadParameter& param) override;
+    ::android::hardware::Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+    ::android::hardware::Return<void> prepareForProcessing(
+            prepareForProcessing_cb _hidl_cb) override;
+    ::android::hardware::Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                                          const AudioBuffer& outBuffer) override;
+    ::android::hardware::Return<void> command(uint32_t commandId,
+                                              const ::android::hardware::hidl_vec<uint8_t>& data,
+                                              uint32_t resultMaxSize, command_cb _hidl_cb) override;
+    ::android::hardware::Return<Result> setParameter(
+            const ::android::hardware::hidl_vec<uint8_t>& parameter,
+            const ::android::hardware::hidl_vec<uint8_t>& value) override;
+    ::android::hardware::Return<void> getParameter(
+            const ::android::hardware::hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb) override;
+    ::android::hardware::Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb) override;
+    ::android::hardware::Return<void> getCurrentConfigForFeature(
+            uint32_t featureId, uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb) override;
+    ::android::hardware::Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const ::android::hardware::hidl_vec<uint8_t>& configData) override;
+    ::android::hardware::Return<Result> close() override;
+
+  private:
+    const EffectDescriptor mDescriptor;
+    bool mEnabled = false;
+};
+
+}  // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/EffectsFactory.cpp b/audio/common/7.0/example/EffectsFactory.cpp
new file mode 100644
index 0000000..7d333ae
--- /dev/null
+++ b/audio/common/7.0/example/EffectsFactory.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "EffectsFactory7.0"
+#include <log/log.h>
+
+#include "EffectsFactory.h"
+#include "EqualizerEffect.h"
+#include "LoudnessEnhancerEffect.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using namespace ::android::hardware::audio::common::V7_0;
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+Return<void> EffectsFactory::getAllDescriptors(getAllDescriptors_cb _hidl_cb) {
+    hidl_vec<EffectDescriptor> descriptors;
+    descriptors.resize(2);
+    descriptors[0] = EqualizerEffect::getDescriptor();
+    descriptors[1] = LoudnessEnhancerEffect::getDescriptor();
+    _hidl_cb(Result::OK, descriptors);
+    return Void();
+}
+
+Return<void> EffectsFactory::getDescriptor(const Uuid& uuid, getDescriptor_cb _hidl_cb) {
+    if (auto desc = EqualizerEffect::getDescriptor(); uuid == desc.type || uuid == desc.uuid) {
+        _hidl_cb(Result::OK, desc);
+    } else if (auto desc = LoudnessEnhancerEffect::getDescriptor();
+               uuid == desc.type || uuid == desc.uuid) {
+        _hidl_cb(Result::OK, desc);
+    } else {
+        _hidl_cb(Result::INVALID_ARGUMENTS, EffectDescriptor{});
+    }
+    return Void();
+}
+
+Return<void> EffectsFactory::createEffect(const Uuid& uuid, int32_t session, int32_t ioHandle,
+                                          int32_t device, createEffect_cb _hidl_cb) {
+    (void)session;
+    (void)ioHandle;
+    (void)device;
+    if (auto desc = EqualizerEffect::getDescriptor(); uuid == desc.type || uuid == desc.uuid) {
+        _hidl_cb(Result::OK, new EqualizerEffect(), 0);
+    } else if (auto desc = LoudnessEnhancerEffect::getDescriptor();
+               uuid == desc.type || uuid == desc.uuid) {
+        _hidl_cb(Result::OK, new LoudnessEnhancerEffect(), 0);
+    } else {
+        _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, 0);
+    }
+    return Void();
+}
+
+Return<void> EffectsFactory::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+    (void)fd;
+    (void)options;
+    return Void();
+}
+
+}  // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/EffectsFactory.h b/audio/common/7.0/example/EffectsFactory.h
new file mode 100644
index 0000000..8fec70c
--- /dev/null
+++ b/audio/common/7.0/example/EffectsFactory.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/audio/effect/7.0/IEffectsFactory.h>
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+class EffectsFactory : public IEffectsFactory {
+  public:
+    EffectsFactory() = default;
+
+    ::android::hardware::Return<void> getAllDescriptors(getAllDescriptors_cb _hidl_cb) override;
+    ::android::hardware::Return<void> getDescriptor(
+            const ::android::hardware::audio::common::V7_0::Uuid& uuid,
+            getDescriptor_cb _hidl_cb) override;
+    ::android::hardware::Return<void> createEffect(
+            const ::android::hardware::audio::common::V7_0::Uuid& uuid, int32_t session,
+            int32_t ioHandle, int32_t device, createEffect_cb _hidl_cb) override;
+    ::android::hardware::Return<void>
+    debug(const ::android::hardware::hidl_handle& fd,
+          const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& options) override;
+};
+
+}  // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/EqualizerEffect.cpp b/audio/common/7.0/example/EqualizerEffect.cpp
new file mode 100644
index 0000000..c93c5a9
--- /dev/null
+++ b/audio/common/7.0/example/EqualizerEffect.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <limits>
+
+#define LOG_TAG "EffectsFactory7.0"
+#include <log/log.h>
+
+#include "EqualizerEffect.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using namespace ::android::hardware::audio::common::V7_0;
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+const EffectDescriptor& EqualizerEffect::getDescriptor() {
+    // Note: for VTS tests only 'type' and 'uuid' fields are required.
+    // The actual implementation must provide meaningful values
+    // for all fields of the descriptor.
+    static const EffectDescriptor descriptor = {
+            .type =
+                    {// Same UUID as AudioEffect.EFFECT_TYPE_EQUALIZER in Java.
+                     0x0bed4300, 0xddd6, 0x11db, 0x8f34,
+                     std::array<uint8_t, 6>{{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}},
+            .uuid = {0, 0, 0, 1, std::array<uint8_t, 6>{{0, 0, 0, 0, 0, 0}}}};
+    return descriptor;
+}
+
+EqualizerEffect::EqualizerEffect() : mEffect(new Effect(getDescriptor())) {
+    mProperties.bandLevels.resize(kNumBands);
+}
+
+Return<void> EqualizerEffect::getNumBands(getNumBands_cb _hidl_cb) {
+    _hidl_cb(Result::OK, kNumBands);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getLevelRange(getLevelRange_cb _hidl_cb) {
+    _hidl_cb(Result::OK, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max());
+    return Void();
+}
+
+Return<Result> EqualizerEffect::setBandLevel(uint16_t band, int16_t level) {
+    if (band < kNumBands) {
+        mProperties.bandLevels[band] = level;
+        return Result::OK;
+    } else {
+        return Result::INVALID_ARGUMENTS;
+    }
+}
+
+Return<void> EqualizerEffect::getBandLevel(uint16_t band, getBandLevel_cb _hidl_cb) {
+    if (band < kNumBands) {
+        _hidl_cb(Result::OK, mProperties.bandLevels[band]);
+    } else {
+        _hidl_cb(Result::INVALID_ARGUMENTS, 0);
+    }
+    return Void();
+}
+
+Return<void> EqualizerEffect::getBandCenterFrequency(uint16_t band,
+                                                     getBandCenterFrequency_cb _hidl_cb) {
+    (void)band;
+    _hidl_cb(Result::OK, 0);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getBandFrequencyRange(uint16_t band,
+                                                    getBandFrequencyRange_cb _hidl_cb) {
+    (void)band;
+    _hidl_cb(Result::OK, 0, 1);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getBandForFrequency(uint32_t freq, getBandForFrequency_cb _hidl_cb) {
+    (void)freq;
+    _hidl_cb(Result::OK, 0);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getPresetNames(getPresetNames_cb _hidl_cb) {
+    hidl_vec<hidl_string> presetNames;
+    presetNames.resize(kNumPresets);
+    presetNames[0] = "default";
+    _hidl_cb(Result::OK, presetNames);
+    return Void();
+}
+
+Return<Result> EqualizerEffect::setCurrentPreset(uint16_t preset) {
+    if (preset < kNumPresets) {
+        mProperties.curPreset = preset;
+        return Result::OK;
+    } else {
+        return Result::INVALID_ARGUMENTS;
+    }
+}
+
+Return<void> EqualizerEffect::getCurrentPreset(getCurrentPreset_cb _hidl_cb) {
+    _hidl_cb(Result::OK, mProperties.curPreset);
+    return Void();
+}
+
+Return<Result> EqualizerEffect::setAllProperties(
+        const IEqualizerEffect::AllProperties& properties) {
+    mProperties = properties;
+    return Result::OK;
+}
+
+Return<void> EqualizerEffect::getAllProperties(getAllProperties_cb _hidl_cb) {
+    _hidl_cb(Result::OK, mProperties);
+    return Void();
+}
+
+}  // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/EqualizerEffect.h b/audio/common/7.0/example/EqualizerEffect.h
new file mode 100644
index 0000000..11853c3
--- /dev/null
+++ b/audio/common/7.0/example/EqualizerEffect.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/audio/effect/7.0/IEqualizerEffect.h>
+
+#include "Effect.h"
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+class EqualizerEffect : public IEqualizerEffect {
+  public:
+    static const EffectDescriptor& getDescriptor();
+
+    EqualizerEffect();
+
+    // Methods from IEffect interface.
+    ::android::hardware::Return<Result> init() override { return mEffect->init(); }
+    ::android::hardware::Return<Result> setConfig(
+            const EffectConfig& config,
+            const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
+        return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+    }
+    ::android::hardware::Return<Result> reset() override { return mEffect->reset(); }
+    ::android::hardware::Return<Result> enable() override { return mEffect->enable(); }
+    ::android::hardware::Return<Result> disable() override { return mEffect->disable(); }
+    ::android::hardware::Return<Result> setDevice(
+            const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
+        return mEffect->setDevice(device);
+    }
+    ::android::hardware::Return<void> setAndGetVolume(
+            const ::android::hardware::hidl_vec<uint32_t>& volumes,
+            setAndGetVolume_cb _hidl_cb) override {
+        return mEffect->setAndGetVolume(volumes, _hidl_cb);
+    }
+    ::android::hardware::Return<Result> volumeChangeNotification(
+            const ::android::hardware::hidl_vec<uint32_t>& volumes) override {
+        return mEffect->volumeChangeNotification(volumes);
+    }
+    ::android::hardware::Return<Result> setAudioMode(
+            ::android::hardware::audio::common::V7_0::AudioMode mode) override {
+        return mEffect->setAudioMode(mode);
+    }
+    ::android::hardware::Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
+        return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+    }
+    ::android::hardware::Return<Result> setInputDevice(
+            const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
+        return mEffect->setInputDevice(device);
+    }
+    ::android::hardware::Return<void> getConfig(getConfig_cb _hidl_cb) override {
+        return mEffect->getConfig(_hidl_cb);
+    }
+    ::android::hardware::Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override {
+        return mEffect->getConfigReverse(_hidl_cb);
+    }
+    ::android::hardware::Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override {
+        return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+    }
+    ::android::hardware::Return<void> getAuxChannelsConfig(
+            getAuxChannelsConfig_cb _hidl_cb) override {
+        return mEffect->getAuxChannelsConfig(_hidl_cb);
+    }
+    ::android::hardware::Return<Result> setAuxChannelsConfig(
+            const EffectAuxChannelsConfig& config) override {
+        return mEffect->setAuxChannelsConfig(config);
+    }
+    ::android::hardware::Return<Result> setAudioSource(
+            const ::android::hardware::hidl_string& source) override {
+        return mEffect->setAudioSource(source);
+    }
+    ::android::hardware::Return<Result> offload(const EffectOffloadParameter& param) override {
+        return mEffect->offload(param);
+    }
+    ::android::hardware::Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override {
+        return mEffect->getDescriptor(_hidl_cb);
+    }
+    ::android::hardware::Return<void> prepareForProcessing(
+            prepareForProcessing_cb _hidl_cb) override {
+        return mEffect->prepareForProcessing(_hidl_cb);
+    }
+    ::android::hardware::Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                                          const AudioBuffer& outBuffer) override {
+        return mEffect->setProcessBuffers(inBuffer, outBuffer);
+    }
+    ::android::hardware::Return<void> command(uint32_t commandId,
+                                              const ::android::hardware::hidl_vec<uint8_t>& data,
+                                              uint32_t resultMaxSize,
+                                              command_cb _hidl_cb) override {
+        return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+    }
+    ::android::hardware::Return<Result> setParameter(
+            const ::android::hardware::hidl_vec<uint8_t>& parameter,
+            const ::android::hardware::hidl_vec<uint8_t>& value) override {
+        return mEffect->setParameter(parameter, value);
+    }
+    ::android::hardware::Return<void> getParameter(
+            const ::android::hardware::hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb) override {
+        return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+    }
+    ::android::hardware::Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb) override {
+        return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+    }
+    ::android::hardware::Return<void> getCurrentConfigForFeature(
+            uint32_t featureId, uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb) override {
+        return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+    }
+    ::android::hardware::Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const ::android::hardware::hidl_vec<uint8_t>& configData) override {
+        return mEffect->setCurrentConfigForFeature(featureId, configData);
+    }
+    ::android::hardware::Return<Result> close() override { return mEffect->close(); }
+
+    // Methods from IEqualizerEffect interface.
+    ::android::hardware::Return<void> getNumBands(getNumBands_cb _hidl_cb) override;
+    ::android::hardware::Return<void> getLevelRange(getLevelRange_cb _hidl_cb) override;
+    ::android::hardware::Return<Result> setBandLevel(uint16_t band, int16_t level) override;
+    ::android::hardware::Return<void> getBandLevel(uint16_t band,
+                                                   getBandLevel_cb _hidl_cb) override;
+    ::android::hardware::Return<void> getBandCenterFrequency(
+            uint16_t band, getBandCenterFrequency_cb _hidl_cb) override;
+    ::android::hardware::Return<void> getBandFrequencyRange(
+            uint16_t band, getBandFrequencyRange_cb _hidl_cb) override;
+    ::android::hardware::Return<void> getBandForFrequency(uint32_t freq,
+                                                          getBandForFrequency_cb _hidl_cb) override;
+    ::android::hardware::Return<void> getPresetNames(getPresetNames_cb _hidl_cb) override;
+    ::android::hardware::Return<Result> setCurrentPreset(uint16_t preset) override;
+    ::android::hardware::Return<void> getCurrentPreset(getCurrentPreset_cb _hidl_cb) override;
+    ::android::hardware::Return<Result> setAllProperties(
+            const IEqualizerEffect::AllProperties& properties) override;
+    ::android::hardware::Return<void> getAllProperties(getAllProperties_cb _hidl_cb) override;
+
+  private:
+    static constexpr size_t kNumBands = 1;
+    static constexpr size_t kNumPresets = 1;
+    sp<Effect> mEffect;
+    IEqualizerEffect::AllProperties mProperties{};
+};
+
+}  // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/LoudnessEnhancerEffect.cpp b/audio/common/7.0/example/LoudnessEnhancerEffect.cpp
new file mode 100644
index 0000000..38269b3
--- /dev/null
+++ b/audio/common/7.0/example/LoudnessEnhancerEffect.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "EffectsFactory7.0"
+#include <log/log.h>
+
+#include "LoudnessEnhancerEffect.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using namespace ::android::hardware::audio::common::V7_0;
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+const EffectDescriptor& LoudnessEnhancerEffect::getDescriptor() {
+    // Note: for VTS tests only 'type' and 'uuid' fields are required.
+    // The actual implementation must provide meaningful values
+    // for all fields of the descriptor.
+    static const EffectDescriptor descriptor = {
+            .type =
+                    {// Same UUID as AudioEffect.EFFECT_TYPE_LOUDNESS_ENHANCER in Java.
+                     0xfe3199be, 0xaed0, 0x413f, 0x87bb,
+                     std::array<uint8_t, 6>{{0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}}},
+            .uuid = {0, 0, 0, 2, std::array<uint8_t, 6>{{0, 0, 0, 0, 0, 0}}}};
+    return descriptor;
+}  // namespace android::hardware::audio::effect::V7_0::implementation
+
+LoudnessEnhancerEffect::LoudnessEnhancerEffect() : mEffect(new Effect(getDescriptor())) {}
+
+Return<Result> LoudnessEnhancerEffect::setTargetGain(int32_t targetGainMb) {
+    mTargetGainMb = targetGainMb;
+    return Result::OK;
+}
+
+Return<void> LoudnessEnhancerEffect::getTargetGain(getTargetGain_cb _hidl_cb) {
+    _hidl_cb(Result::OK, mTargetGainMb);
+    return Void();
+}
+
+}  // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/LoudnessEnhancerEffect.h b/audio/common/7.0/example/LoudnessEnhancerEffect.h
new file mode 100644
index 0000000..1af0d9f
--- /dev/null
+++ b/audio/common/7.0/example/LoudnessEnhancerEffect.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/audio/effect/7.0/ILoudnessEnhancerEffect.h>
+
+#include "Effect.h"
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+class LoudnessEnhancerEffect : public ILoudnessEnhancerEffect {
+  public:
+    static const EffectDescriptor& getDescriptor();
+
+    LoudnessEnhancerEffect();
+
+    // Methods from IEffect interface.
+    ::android::hardware::Return<Result> init() override { return mEffect->init(); }
+    ::android::hardware::Return<Result> setConfig(
+            const EffectConfig& config,
+            const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
+        return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+    }
+    ::android::hardware::Return<Result> reset() override { return mEffect->reset(); }
+    ::android::hardware::Return<Result> enable() override { return mEffect->enable(); }
+    ::android::hardware::Return<Result> disable() override { return mEffect->disable(); }
+    ::android::hardware::Return<Result> setDevice(
+            const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
+        return mEffect->setDevice(device);
+    }
+    ::android::hardware::Return<void> setAndGetVolume(
+            const ::android::hardware::hidl_vec<uint32_t>& volumes,
+            setAndGetVolume_cb _hidl_cb) override {
+        return mEffect->setAndGetVolume(volumes, _hidl_cb);
+    }
+    ::android::hardware::Return<Result> volumeChangeNotification(
+            const ::android::hardware::hidl_vec<uint32_t>& volumes) override {
+        return mEffect->volumeChangeNotification(volumes);
+    }
+    ::android::hardware::Return<Result> setAudioMode(
+            ::android::hardware::audio::common::V7_0::AudioMode mode) override {
+        return mEffect->setAudioMode(mode);
+    }
+    ::android::hardware::Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
+        return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+    }
+    ::android::hardware::Return<Result> setInputDevice(
+            const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
+        return mEffect->setInputDevice(device);
+    }
+    ::android::hardware::Return<void> getConfig(getConfig_cb _hidl_cb) override {
+        return mEffect->getConfig(_hidl_cb);
+    }
+    ::android::hardware::Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override {
+        return mEffect->getConfigReverse(_hidl_cb);
+    }
+    ::android::hardware::Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override {
+        return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+    }
+    ::android::hardware::Return<void> getAuxChannelsConfig(
+            getAuxChannelsConfig_cb _hidl_cb) override {
+        return mEffect->getAuxChannelsConfig(_hidl_cb);
+    }
+    ::android::hardware::Return<Result> setAuxChannelsConfig(
+            const EffectAuxChannelsConfig& config) override {
+        return mEffect->setAuxChannelsConfig(config);
+    }
+    ::android::hardware::Return<Result> setAudioSource(
+            const ::android::hardware::hidl_string& source) override {
+        return mEffect->setAudioSource(source);
+    }
+    ::android::hardware::Return<Result> offload(const EffectOffloadParameter& param) override {
+        return mEffect->offload(param);
+    }
+    ::android::hardware::Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override {
+        return mEffect->getDescriptor(_hidl_cb);
+    }
+    ::android::hardware::Return<void> prepareForProcessing(
+            prepareForProcessing_cb _hidl_cb) override {
+        return mEffect->prepareForProcessing(_hidl_cb);
+    }
+    ::android::hardware::Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+                                                          const AudioBuffer& outBuffer) override {
+        return mEffect->setProcessBuffers(inBuffer, outBuffer);
+    }
+    ::android::hardware::Return<void> command(uint32_t commandId,
+                                              const ::android::hardware::hidl_vec<uint8_t>& data,
+                                              uint32_t resultMaxSize,
+                                              command_cb _hidl_cb) override {
+        return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+    }
+    ::android::hardware::Return<Result> setParameter(
+            const ::android::hardware::hidl_vec<uint8_t>& parameter,
+            const ::android::hardware::hidl_vec<uint8_t>& value) override {
+        return mEffect->setParameter(parameter, value);
+    }
+    ::android::hardware::Return<void> getParameter(
+            const ::android::hardware::hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb) override {
+        return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+    }
+    ::android::hardware::Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb) override {
+        return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+    }
+    ::android::hardware::Return<void> getCurrentConfigForFeature(
+            uint32_t featureId, uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb) override {
+        return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+    }
+    ::android::hardware::Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const ::android::hardware::hidl_vec<uint8_t>& configData) override {
+        return mEffect->setCurrentConfigForFeature(featureId, configData);
+    }
+    ::android::hardware::Return<Result> close() override { return mEffect->close(); }
+
+    // Methods from ILoudnessEnhancerEffect interface.
+    ::android::hardware::Return<Result> setTargetGain(int32_t targetGainMb) override;
+    ::android::hardware::Return<void> getTargetGain(getTargetGain_cb _hidl_cb) override;
+
+  private:
+    sp<Effect> mEffect;
+    int32_t mTargetGainMb = 0;
+};
+
+}  // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/android.hardware.audio@7.0-service.example.rc b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.rc
new file mode 100644
index 0000000..cf8b51f
--- /dev/null
+++ b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.rc
@@ -0,0 +1,7 @@
+service vendor.audio-hal-7-0 /vendor/bin/hw/android.hardware.audio@7.0-service.example
+    class hal
+    user audioserver
+    group audio
+    capabilities BLOCK_SUSPEND
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh HighPerformance
diff --git a/audio/common/7.0/example/android.hardware.audio@7.0-service.example.xml b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.xml
new file mode 100644
index 0000000..b91b061
--- /dev/null
+++ b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.xml
@@ -0,0 +1,20 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.audio</name>
+        <transport>hwbinder</transport>
+        <version>7.0</version>
+        <interface>
+            <name>IDevicesFactory</name>
+            <instance>example</instance>
+        </interface>
+    </hal>
+    <hal format="hidl">
+        <name>android.hardware.audio.effect</name>
+        <transport>hwbinder</transport>
+        <version>7.0</version>
+        <interface>
+            <name>IEffectsFactory</name>
+            <instance>example</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/audio/common/7.0/example/service.cpp b/audio/common/7.0/example/service.cpp
new file mode 100644
index 0000000..641e2c9
--- /dev/null
+++ b/audio/common/7.0/example/service.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.audio@7.0-service.example"
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+
+#include "DevicesFactory.h"
+#include "EffectsFactory.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using namespace android;
+
+status_t registerDevicesFactoryService() {
+    sp<::android::hardware::audio::V7_0::IDevicesFactory> devicesFactory =
+            new ::android::hardware::audio::V7_0::implementation::DevicesFactory();
+    status_t status = devicesFactory->registerAsService("example");
+    ALOGE_IF(status != OK, "Error registering devices factory as service: %d", status);
+    return status;
+}
+
+status_t registerEffectsFactoryService() {
+    sp<::android::hardware::audio::effect::V7_0::IEffectsFactory> devicesFactory =
+            new ::android::hardware::audio::effect::V7_0::implementation::EffectsFactory();
+    status_t status = devicesFactory->registerAsService("example");
+    ALOGE_IF(status != OK, "Error registering effects factory as service: %d", status);
+    return status;
+}
+
+int main() {
+    configureRpcThreadpool(1, true);
+    status_t status = registerDevicesFactoryService();
+    if (status != OK) {
+        return status;
+    }
+    status = registerEffectsFactoryService();
+    if (status != OK) {
+        return status;
+    }
+    joinRpcThreadpool();
+
+    return 1;
+}
diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal
index 94d0af7..31c7388 100644
--- a/audio/common/7.0/types.hal
+++ b/audio/common/7.0/types.hal
@@ -112,12 +112,28 @@
 typedef string AudioChannelMask;
 
 /**
- * Basic configuration applicable to any stream of audio.
+ * Base configuration attributes applicable to any stream of audio.
  */
-struct AudioBasicConfig {
+struct AudioConfigBase {
+    AudioFormat format;                 // 'DEFAULT' means 'unspecified'
     uint32_t sampleRateHz;              // 0 means 'unspecified'
     vec<AudioChannelMask> channelMask;  // empty means 'unspecified'
-    AudioFormat format;                 // 'DEFAULT' means 'unspecified'
+};
+
+/**
+ * Configurations supported for a certain audio format.
+ */
+struct AudioProfile {
+    AudioFormat format;
+    /** List of the sample rates (in Hz) supported by the profile. */
+    vec<uint32_t> sampleRates;
+    /**
+     * List of channel masks supported by the profile. Every subvector might be
+     * comprised of several individual channel mask entries for non-traditional
+     * channel masks, e.g. a combination "OUT_FRONT_LEFT,OUT_FRONT_CENTER" which
+     * doesn't have a corresponding predefined channel mask.
+     */
+    vec<vec<AudioChannelMask>> channelMasks;
 };
 
 /**
@@ -137,17 +153,20 @@
 };
 
 /**
+ * Audio device specifies type (or category) of audio I/O device
+ * (e.g. speaker or headphones).
+ * See 'audioDevice' in audio_policy_configuration.xsd for the
+ * list of allowed values.
+ */
+typedef string AudioDevice;
+
+/**
  * Specifies a device address in case when several devices of the same type
  * can be connected (e.g. BT A2DP, USB).
  */
 struct DeviceAddress {
-    /**
-     * Audio device specifies type (or category) of audio I/O device
-     * (e.g. speaker or headphones).
-     * See 'audioDevice' in audio_policy_configuration.xsd for the
-     * list of allowed values.
-     */
-    string deviceType;
+    /** The type of the device. */
+    AudioDevice deviceType;
     safe_union Address {
         /**
          * The address may be left unspecified if 'device' specifies
@@ -209,7 +228,7 @@
  * Additional information about the stream passed to hardware decoders.
  */
 struct AudioOffloadInfo {
-    AudioBasicConfig base;
+    AudioConfigBase base;
     AudioStreamType streamType;
     uint32_t bitRatePerSecond;
     int64_t durationMicroseconds;  // -1 if unknown
@@ -227,7 +246,7 @@
  * Commonly used audio stream configuration parameters.
  */
 struct AudioConfig {
-    AudioBasicConfig base;
+    AudioConfigBase base;
     AudioOffloadInfo offloadInfo;
     uint64_t frameCount;
 };
@@ -372,9 +391,9 @@
     /**
      * Basic parameters: sampling rate, format, channel mask. Only some of the
      * parameters (or none) may be set. See the documentation of the
-     * AudioBasicConfig struct.
+     * AudioConfigBase struct.
      */
-    AudioBasicConfig config;
+    AudioConfigBase config;
     /** Associated gain control. */
     safe_union OptionalGain {
         Monostate unspecified;
@@ -401,13 +420,6 @@
      */
     string name;
     /** List of audio profiles supported by the port. */
-    struct AudioProfile {
-        AudioFormat format;
-        /** List of the sample rates supported by the profile. */
-        vec<uint32_t> sampleRates;
-        /** List of channel masks supported by the profile. */
-        vec<AudioChannelMask> channelMasks;
-    };
     vec<AudioProfile> profiles;
     /** List of gain controls attached to the port. */
     vec<AudioGain> gains;
diff --git a/audio/common/all-versions/default/VersionUtils.h b/audio/common/all-versions/default/VersionUtils.h
index e7755b1..9bfca0c 100644
--- a/audio/common/all-versions/default/VersionUtils.h
+++ b/audio/common/all-versions/default/VersionUtils.h
@@ -31,7 +31,7 @@
 typedef common::CPP_VERSION::AudioChannelMask AudioChannelBitfield;
 typedef common::CPP_VERSION::AudioOutputFlag AudioOutputFlagBitfield;
 typedef common::CPP_VERSION::AudioInputFlag AudioInputFlagBitfield;
-#elif MAJOR_VERSION >= 4
+#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
 typedef hidl_bitfield<common::CPP_VERSION::AudioDevice> AudioDeviceBitfield;
 typedef hidl_bitfield<common::CPP_VERSION::AudioChannelMask> AudioChannelBitfield;
 typedef hidl_bitfield<common::CPP_VERSION::AudioOutputFlag> AudioOutputFlagBitfield;
diff --git a/audio/core/all-versions/default/include/core/default/Device.h b/audio/core/all-versions/default/include/core/default/Device.h
index b0e72d9..907acd7 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -43,8 +43,10 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
+#if MAJOR_VERSION <= 6
 using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioInputFlagBitfield;
 using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioOutputFlagBitfield;
+#endif
 using namespace ::android::hardware::audio::common::CPP_VERSION;
 using namespace ::android::hardware::audio::CPP_VERSION;
 
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index b0eb2e0..2466fd1 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -16,6 +16,13 @@
 
 #include "AudioPrimaryHidlHalTest.h"
 
+#if MAJOR_VERSION >= 7
+#include <audio_policy_configuration_V7_0.h>
+#include <xsdc/XsdcSupport.h>
+
+using android::xsdc_enum_range;
+#endif
+
 TEST_P(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) {
     doc::test("Calling openDevice(\"primary\") should return the primary device.");
     if (getDeviceName() != DeviceManager::kPrimaryDevice) {
@@ -53,14 +60,29 @@
             "Make sure getMicrophones always succeeds"
             "and getActiveMicrophones always succeeds when recording from these microphones.");
         AudioConfig config{};
+#if MAJOR_VERSION <= 6
         config.channelMask = mkEnumBitfield(AudioChannelMask::IN_MONO);
         config.sampleRateHz = 8000;
         config.format = AudioFormat::PCM_16_BIT;
         auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
         const SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
+#elif MAJOR_VERSION >= 7
+        config.base.channelMask.resize(1);
+        config.base.channelMask[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO);
+        config.base.sampleRateHz = 8000;
+        config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+        hidl_vec<hidl_string> flags;
+        const SinkMetadata initMetadata = {
+                {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}};
+#endif
         EventFlag* efGroup;
         for (auto microphone : microphones) {
+#if MAJOR_VERSION <= 6
             if (microphone.deviceAddress.device != AudioDevice::IN_BUILTIN_MIC) {
+#elif MAJOR_VERSION >= 7
+            if (xsd::stringToAudioDevice(microphone.deviceAddress.deviceType) !=
+                xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC) {
+#endif
                 continue;
             }
             sp<IStreamIn> stream;
@@ -81,16 +103,16 @@
             size_t frameSize = stream->getFrameSize();
             size_t frameCount = stream->getBufferSize() / frameSize;
             ASSERT_OK(stream->prepareForReading(
-                frameSize, frameCount, [&](auto r, auto& c, auto& d, auto&, auto&) {
-                    readRes = r;
-                    if (readRes == Result::OK) {
-                        commandMQ.reset(new CommandMQ(c));
-                        dataMQ.reset(new DataMQ(d));
-                        if (dataMQ->isValid() && dataMQ->getEventFlagWord()) {
-                            EventFlag::createEventFlag(dataMQ->getEventFlagWord(), &efGroup);
+                    frameSize, frameCount, [&](auto r, auto& c, auto& d, auto&, auto) {
+                        readRes = r;
+                        if (readRes == Result::OK) {
+                            commandMQ.reset(new CommandMQ(c));
+                            dataMQ.reset(new DataMQ(d));
+                            if (dataMQ->isValid() && dataMQ->getEventFlagWord()) {
+                                EventFlag::createEventFlag(dataMQ->getEventFlagWord(), &efGroup);
+                            }
                         }
-                    }
-                }));
+                    }));
             ASSERT_OK(readRes);
             IStreamIn::ReadParameters params;
             params.command = IStreamIn::ReadCommand::READ;
@@ -116,13 +138,24 @@
 
 TEST_P(AudioHidlDeviceTest, SetConnectedState) {
     doc::test("Check that the HAL can be notified of device connection and deconnection");
+#if MAJOR_VERSION <= 6
     using AD = AudioDevice;
     for (auto deviceType : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
+#elif MAJOR_VERSION >= 7
+    using AD = xsd::AudioDevice;
+    for (auto deviceType :
+         {toString(AD::AUDIO_DEVICE_OUT_HDMI), toString(AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
+          toString(AD::AUDIO_DEVICE_IN_USB_HEADSET)}) {
+#endif
         SCOPED_TRACE("device=" + ::testing::PrintToString(deviceType));
         for (bool state : {true, false}) {
             SCOPED_TRACE("state=" + ::testing::PrintToString(state));
             DeviceAddress address = {};
+#if MAJOR_VERSION <= 6
             address.device = deviceType;
+#elif MAJOR_VERSION >= 7
+            address.deviceType = deviceType;
+#endif
             auto ret = getDevice()->setConnectedState(address, state);
             ASSERT_TRUE(ret.isOk());
             if (ret == Result::NOT_SUPPORTED) {
@@ -148,7 +181,11 @@
     }
     // The stream was constructed with one device, thus getDevices must only return one
     ASSERT_EQ(1U, devices.size());
+#if MAJOR_VERSION <= 6
     AudioDevice device = devices[0].device;
+#elif MAJOR_VERSION >= 7
+    auto device = devices[0].deviceType;
+#endif
     ASSERT_TRUE(device == expectedDevice)
         << "Expected: " << ::testing::PrintToString(expectedDevice)
         << "\n  Actual: " << ::testing::PrintToString(device);
@@ -156,12 +193,22 @@
 
 TEST_IO_STREAM(GetDevices, "Check that the stream device == the one it was opened with",
                areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
+#if MAJOR_VERSION <= 6
                                           : testGetDevices(stream.get(), address.device))
+#elif MAJOR_VERSION >= 7
+                                          : testGetDevices(stream.get(), address.deviceType))
+#endif
 
 static void testSetDevices(IStream* stream, const DeviceAddress& address) {
     DeviceAddress otherAddress = address;
+#if MAJOR_VERSION <= 6
     otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0 ? AudioDevice::OUT_SPEAKER
                                                                       : AudioDevice::IN_BUILTIN_MIC;
+#elif MAJOR_VERSION >= 7
+    otherAddress.deviceType = xsd::isOutputDevice(address.deviceType)
+                                      ? toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER)
+                                      : toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC);
+#endif
     EXPECT_RESULT(okOrNotSupported, stream->setDevices({otherAddress}));
 
     ASSERT_RESULT(okOrNotSupported,
@@ -186,11 +233,19 @@
 TEST_P(InputStreamTest, updateSinkMetadata) {
     doc::test("The HAL should not crash on metadata change");
 
+#if MAJOR_VERSION <= 6
     hidl_enum_range<AudioSource> range;
+#elif MAJOR_VERSION >= 7
+    xsdc_enum_range<audio::policy::configuration::V7_0::AudioSource> range;
+#endif
     // Test all possible track configuration
-    for (AudioSource source : range) {
+    for (auto source : range) {
         for (float volume : {0.0, 0.5, 1.0}) {
+#if MAJOR_VERSION <= 6
             const SinkMetadata metadata = {{{.source = source, .gain = volume}}};
+#elif MAJOR_VERSION >= 7
+            const SinkMetadata metadata = {{{.source = toString(source), .gain = volume}}};
+#endif
             ASSERT_OK(stream->updateSinkMetadata(metadata))
                 << "source=" << toString(source) << ", volume=" << volume;
         }
@@ -213,13 +268,22 @@
 TEST_P(OutputStreamTest, updateSourceMetadata) {
     doc::test("The HAL should not crash on metadata change");
 
+#if MAJOR_VERSION <= 6
     hidl_enum_range<AudioUsage> usageRange;
     hidl_enum_range<AudioContentType> contentRange;
+#elif MAJOR_VERSION >= 7
+    xsdc_enum_range<audio::policy::configuration::V7_0::AudioUsage> usageRange;
+    xsdc_enum_range<audio::policy::configuration::V7_0::AudioContentType> contentRange;
+#endif
     // Test all possible track configuration
     for (auto usage : usageRange) {
         for (auto content : contentRange) {
             for (float volume : {0.0, 0.5, 1.0}) {
+#if MAJOR_VERSION <= 6
                 const SourceMetadata metadata = {{{usage, content, volume}}};
+#elif MAJOR_VERSION >= 7
+                const SourceMetadata metadata = {{{toString(usage), toString(content), volume}}};
+#endif
                 ASSERT_OK(stream->updateSourceMetadata(metadata))
                     << "usage=" << toString(usage) << ", content=" << toString(content)
                     << ", volume=" << volume;
@@ -227,12 +291,26 @@
         }
     }
 
+    // clang-format off
     // Set many track of different configuration
     ASSERT_OK(stream->updateSourceMetadata(
+#if MAJOR_VERSION <= 6
         {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 0.1},
           {AudioUsage::VOICE_COMMUNICATION, AudioContentType::SPEECH, 1.0},
           {AudioUsage::ALARM, AudioContentType::SONIFICATION, 0.0},
-          {AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}}));
+          {AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}}
+#elif MAJOR_VERSION >= 7
+        {{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
+                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 0.1},
+          {toString(xsd::AudioUsage::AUDIO_USAGE_VOICE_COMMUNICATION),
+                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SPEECH), 1.0},
+          {toString(xsd::AudioUsage::AUDIO_USAGE_ALARM),
+                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SONIFICATION), 0.0},
+          {toString(xsd::AudioUsage::AUDIO_USAGE_ASSISTANT),
+                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN), 0.3}}}
+#endif
+    ));
+    // clang-format on
 
     // Set no metadata as if all stream track had stopped
     ASSERT_OK(stream->updateSourceMetadata({}));
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
index 7a52d0e..81a1f7b 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
@@ -56,6 +56,7 @@
     }
 };
 
+#if MAJOR_VERSION <= 6
 struct GetSupported {
     static auto getFormat(IStream* stream) {
         auto ret = stream->getFormat();
@@ -80,7 +81,7 @@
         EXPECT_OK(stream->getSupportedFormats(returnIn(capabilities)));
         return Result::OK;
     }
-#elif MAJOR_VERSION >= 6
+#else  // MAJOR_VERSION == 6
     static Result formats(IStream* stream, hidl_vec<AudioFormat>& capabilities) {
         Result res;
         EXPECT_OK(stream->getSupportedFormats(returnIn(res, capabilities)));
@@ -88,6 +89,7 @@
     }
 #endif
 };
+#endif  // MAJOR_VERSION <= 6
 
 template <class T>
 auto dump(T t, hidl_handle handle) {
diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
index 54d4bbd..bd8de2d 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -17,6 +17,7 @@
 // pull in all the <= 5.0 tests
 #include "5.0/AudioPrimaryHidlHalTest.cpp"
 
+#if MAJOR_VERSION <= 6
 const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
     static std::vector<DeviceConfigParameter> parameters = [] {
         std::vector<DeviceConfigParameter> result;
@@ -28,8 +29,8 @@
                     const auto& channels = profile->getChannels();
                     const auto& sampleRates = profile->getSampleRates();
                     auto configs = ConfigHelper::combineAudioConfig(
-                            vector<audio_channel_mask_t>(channels.begin(), channels.end()),
-                            vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
+                            std::vector<audio_channel_mask_t>(channels.begin(), channels.end()),
+                            std::vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
                             profile->getFormat());
                     auto flags = ioProfile->getFlags();
                     for (auto& config : configs) {
@@ -46,8 +47,8 @@
                             config.offloadInfo.bufferSize = 256;  // arbitrary value
                             config.offloadInfo.usage = AudioUsage::MEDIA;
                             result.emplace_back(device, config,
-                                                AudioOutputFlag(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
-                                                                AUDIO_OUTPUT_FLAG_DIRECT));
+                                                AudioOutputFlag(AudioOutputFlag::COMPRESS_OFFLOAD |
+                                                                AudioOutputFlag::DIRECT));
                         } else {
                             if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {  // ignore the flag
                                 flags &= ~AUDIO_OUTPUT_FLAG_PRIMARY;
@@ -74,8 +75,8 @@
                     const auto& channels = profile->getChannels();
                     const auto& sampleRates = profile->getSampleRates();
                     auto configs = ConfigHelper::combineAudioConfig(
-                            vector<audio_channel_mask_t>(channels.begin(), channels.end()),
-                            vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
+                            std::vector<audio_channel_mask_t>(channels.begin(), channels.end()),
+                            std::vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
                             profile->getFormat());
                     for (const auto& config : configs) {
                         result.emplace_back(device, config, AudioInputFlag(ioProfile->getFlags()));
@@ -87,13 +88,22 @@
     }();
     return parameters;
 }
+#endif  // MAJOR_VERSION <= 6
 
 TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) {
     doc::test("Verify that a device can't be closed if there are streams opened");
+#if MAJOR_VERSION <= 6
     DeviceAddress address{.device = AudioDevice::OUT_DEFAULT};
-    AudioConfig config{};
-    auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
     SourceMetadata initMetadata = {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}};
+    auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
+#elif MAJOR_VERSION >= 7
+    DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT)};
+    SourceMetadata initMetadata = {
+            {{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
+              toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 1 /* gain */}}};
+    hidl_vec<AudioInOutFlag> flags;
+#endif
+    AudioConfig config{};
     sp<IStreamOut> stream;
     StreamHelper<IStreamOut> helper(stream);
     AudioConfig suggestedConfig{};
@@ -111,14 +121,20 @@
 
 TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) {
     doc::test("Verify that a device can't be closed if there are streams opened");
-    auto module = getCachedPolicyConfig().getModuleFromName(getDeviceName());
-    if (module->getInputProfiles().empty()) {
+    if (!getCachedPolicyConfig().haveInputProfilesInModule(getDeviceName())) {
         GTEST_SKIP() << "Device doesn't have input profiles";
     }
+#if MAJOR_VERSION <= 6
     DeviceAddress address{.device = AudioDevice::IN_DEFAULT};
-    AudioConfig config{};
-    auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
     SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
+    auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
+#elif MAJOR_VERSION >= 7
+    DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT)};
+    SinkMetadata initMetadata = {
+            {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}};
+    hidl_vec<AudioInOutFlag> flags;
+#endif
+    AudioConfig config{};
     sp<IStreamIn> stream;
     StreamHelper<IStreamIn> helper(stream);
     AudioConfig suggestedConfig{};
@@ -137,9 +153,8 @@
 TEST_P(AudioPatchHidlTest, UpdatePatchInvalidHandle) {
     doc::test("Verify that passing an invalid handle to updateAudioPatch is checked");
     AudioPatchHandle ignored;
-    ASSERT_OK(getDevice()->updateAudioPatch(
-            static_cast<int32_t>(AudioHandleConsts::AUDIO_PATCH_HANDLE_NONE),
-            hidl_vec<AudioPortConfig>(), hidl_vec<AudioPortConfig>(), returnIn(res, ignored)));
+    ASSERT_OK(getDevice()->updateAudioPatch(AudioPatchHandle{}, hidl_vec<AudioPortConfig>(),
+                                            hidl_vec<AudioPortConfig>(), returnIn(res, ignored)));
     ASSERT_RESULT(Result::INVALID_ARGUMENTS, res);
 }
 
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index 33efa6f..63eaea8 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -16,3 +16,101 @@
 
 // pull in all the <= 6.0 tests
 #include "6.0/AudioPrimaryHidlHalTest.cpp"
+
+static std::vector<AudioConfig> combineAudioConfig(std::vector<xsd::AudioChannelMask> channelMasks,
+                                                   std::vector<int64_t> sampleRates,
+                                                   const std::string& format) {
+    std::vector<AudioConfig> configs;
+    configs.reserve(channelMasks.size() * sampleRates.size());
+    for (auto channelMask : channelMasks) {
+        for (auto sampleRate : sampleRates) {
+            AudioConfig config{};
+            // leave offloadInfo to 0
+            config.base.channelMask.resize(1);
+            config.base.channelMask[0] = toString(channelMask);
+            config.base.sampleRateHz = sampleRate;
+            config.base.format = format;
+            configs.push_back(config);
+        }
+    }
+    return configs;
+}
+
+const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
+    static std::vector<DeviceConfigParameter> parameters = [] {
+        std::vector<DeviceConfigParameter> result;
+        const std::vector<AudioInOutFlag> offloadFlags = {
+                toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
+                toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_DIRECT)};
+        for (const auto& device : getDeviceParameters()) {
+            auto module =
+                    getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+            for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
+                if (mixPort.getRole() != xsd::Role::source) continue;  // not an output profile
+                auto xsdFlags = mixPort.getFlags();
+                const bool isOffload =
+                        std::find(xsdFlags.begin(), xsdFlags.end(),
+                                  xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) !=
+                        xsdFlags.end();
+                std::vector<AudioInOutFlag> flags;
+                if (!isOffload) {
+                    for (auto flag : xsdFlags) {
+                        if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
+                            flags.push_back(toString(flag));
+                        }
+                    }
+                } else {
+                    flags = offloadFlags;
+                }
+                for (const auto& profile : mixPort.getProfile()) {
+                    auto configs =
+                            combineAudioConfig(profile.getChannelMasks(),
+                                               profile.getSamplingRates(), profile.getFormat());
+                    for (auto& config : configs) {
+                        // Some combinations of flags declared in the config file require special
+                        // treatment.
+                        if (isOffload) {
+                            config.offloadInfo.base = config.base;
+                            config.offloadInfo.streamType =
+                                    toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC);
+                            config.offloadInfo.usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA);
+                            config.offloadInfo.bitRatePerSecond = 320;
+                            config.offloadInfo.durationMicroseconds = -1;
+                            config.offloadInfo.bitWidth = 16;
+                            config.offloadInfo.bufferSize = 256;  // arbitrary value
+                        }
+                        result.emplace_back(device, config, flags);
+                    }
+                }
+            }
+        }
+        return result;
+    }();
+    return parameters;
+}
+
+const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters() {
+    static std::vector<DeviceConfigParameter> parameters = [] {
+        std::vector<DeviceConfigParameter> result;
+        for (const auto& device : getDeviceParameters()) {
+            auto module =
+                    getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+            for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
+                if (mixPort.getRole() != xsd::Role::sink) continue;  // not an input profile
+                std::vector<AudioInOutFlag> flags;
+                std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(), flags.begin(),
+                               [](auto flag) { return toString(flag); });
+                for (const auto& profile : mixPort.getProfile()) {
+                    auto configs =
+                            combineAudioConfig(profile.getChannelMasks(),
+                                               profile.getSamplingRates(), profile.getFormat());
+                    for (const auto& config : configs) {
+                        result.emplace_back(device, config, flags);
+                    }
+                }
+            }
+        }
+        return result;
+    }();
+    return parameters;
+}
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
new file mode 100644
index 0000000..d790b34
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h
+// and thus it doesn't have all '#include' and 'using' directives required
+// for a standalone compilation.
+
+namespace xsd {
+using Module = Modules::Module;
+}
+
+class PolicyConfig {
+  public:
+    explicit PolicyConfig(const std::string& configFileName)
+        : mConfigFileName{configFileName},
+          mFilePath{findExistingConfigurationFile(mConfigFileName)},
+          mConfig{xsd::read(mFilePath.c_str())} {
+        if (mConfig) {
+            mStatus = OK;
+            mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice);
+            for (const auto& module : mConfig->getFirstModules()->get_module()) {
+                auto attachedDevices = module.getFirstAttachedDevices()->getItem();
+                if (!attachedDevices.empty()) {
+                    mModulesWithDevicesNames.insert(module.getName());
+                }
+            }
+        }
+    }
+    status_t getStatus() const { return mStatus; }
+    std::string getError() const {
+        if (mFilePath.empty()) {
+            return std::string{"Could not find "} + mConfigFileName +
+                   " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
+        } else {
+            return "Invalid config file: " + mFilePath;
+        }
+    }
+    const std::string& getFilePath() const { return mFilePath; }
+    const xsd::Module* getModuleFromName(const std::string& name) const {
+        if (mConfig) {
+            for (const auto& module : mConfig->getFirstModules()->get_module()) {
+                if (module.getName() == name) return &module;
+            }
+        }
+        return nullptr;
+    }
+    const xsd::Module* getPrimaryModule() const { return mPrimaryModule; }
+    const std::set<std::string>& getModulesWithDevicesNames() const {
+        return mModulesWithDevicesNames;
+    }
+    bool haveInputProfilesInModule(const std::string& name) const {
+        auto module = getModuleFromName(name);
+        for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
+            if (mixPort.getRole() == xsd::Role::sink) return true;
+        }
+        return false;
+    }
+
+  private:
+    static std::string findExistingConfigurationFile(const std::string& fileName) {
+        for (const auto& location : android::audio_get_configuration_paths()) {
+            std::string path = location + '/' + fileName;
+            if (access(path.c_str(), F_OK) == 0) {
+                return path;
+            }
+        }
+        return std::string{};
+    }
+
+    const std::string mConfigFileName;
+    const std::string mFilePath;
+    std::optional<xsd::AudioPolicyConfiguration> mConfig;
+    status_t mStatus = NO_INIT;
+    const xsd::Module* mPrimaryModule;
+    std::set<std::string> mModulesWithDevicesNames;
+};
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index 6ac9b20..c7bfe08 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -19,9 +19,6 @@
     defaults: ["VtsHalTargetTestDefaults"],
     static_libs: [
         "android.hardware.audio.common.test.utility",
-        "libaudiofoundation",
-        "libaudiopolicycomponents",
-        "libmedia_helper",
         "libxml2",
     ],
     shared_libs: [
@@ -44,6 +41,9 @@
         "2.0/AudioPrimaryHidlHalTest.cpp",
     ],
     static_libs: [
+        "libaudiofoundation",
+        "libaudiopolicycomponents",
+        "libmedia_helper",
         "android.hardware.audio@2.0",
         "android.hardware.audio.common@2.0",
     ],
@@ -67,6 +67,9 @@
         "4.0/AudioPrimaryHidlHalTest.cpp",
     ],
     static_libs: [
+        "libaudiofoundation",
+        "libaudiopolicycomponents",
+        "libmedia_helper",
         "android.hardware.audio@4.0",
         "android.hardware.audio.common@4.0",
     ],
@@ -90,6 +93,9 @@
         "5.0/AudioPrimaryHidlHalTest.cpp",
     ],
     static_libs: [
+        "libaudiofoundation",
+        "libaudiopolicycomponents",
+        "libmedia_helper",
         "android.hardware.audio@5.0",
         "android.hardware.audio.common@5.0",
     ],
@@ -113,6 +119,9 @@
         "6.0/AudioPrimaryHidlHalTest.cpp",
     ],
     static_libs: [
+        "libaudiofoundation",
+        "libaudiopolicycomponents",
+        "libmedia_helper",
         "android.hardware.audio@6.0",
         "android.hardware.audio.common@6.0",
     ],
@@ -130,7 +139,6 @@
 }
 
 cc_test {
-    enabled: false,
     name: "VtsHalAudioV7_0TargetTest",
     defaults: ["VtsHalAudioTargetTest_defaults"],
     srcs: [
@@ -139,6 +147,7 @@
     static_libs: [
         "android.hardware.audio@7.0",
         "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.0-enums",
     ],
     cflags: [
         "-DMAJOR_VERSION=7",
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 01bdd69..5e4b414 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -42,8 +42,11 @@
 #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
 #include PATH(android/hardware/audio/FILE_VERSION/types.h)
 #include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#if MAJOR_VERSION >= 7
+#include <audio_policy_configuration_V7_0-enums.h>
+#include <audio_policy_configuration_V7_0.h>
+#endif
 
-#include <Serializer.h>
 #include <fmq/EventFlag.h>
 #include <fmq/MessageQueue.h>
 #include <hidl/GtestPrinter.h>
@@ -63,14 +66,6 @@
 #include "4.0/AudioPrimaryHidlHalUtils.h"
 #endif
 
-using std::initializer_list;
-using std::list;
-using std::string;
-using std::to_string;
-using std::vector;
-
-using ::android::AudioPolicyConfig;
-using ::android::HwModule;
 using ::android::NO_INIT;
 using ::android::OK;
 using ::android::sp;
@@ -93,6 +88,12 @@
 using namespace ::android::hardware::audio::common::CPP_VERSION;
 using namespace ::android::hardware::audio::common::test::utility;
 using namespace ::android::hardware::audio::CPP_VERSION;
+#if MAJOR_VERSION >= 7
+// Make an alias for enumerations generated from the APM config XSD.
+namespace xsd {
+using namespace ::audio::policy::configuration::CPP_VERSION;
+}
+#endif
 
 // Typical accepted results from interface methods
 static auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
@@ -103,8 +104,12 @@
 static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
 static auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUPPORTED};
 
-#define AUDIO_PRIMARY_HIDL_HAL_TEST
 #include "DeviceManager.h"
+#if MAJOR_VERSION <= 6
+#include "PolicyConfig.h"
+#elif MAJOR_VERSION >= 7
+#include "7.0/PolicyConfig.h"
+#endif
 
 class HidlTest : public ::testing::Test {
   public:
@@ -136,83 +141,16 @@
 ////////////////////////// Audio policy configuration ////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-static constexpr char kConfigFileName[] = "audio_policy_configuration.xml";
-
 // Stringify the argument.
 #define QUOTE(x) #x
 #define STRINGIFY(x) QUOTE(x)
 
-struct PolicyConfigData {
-    android::HwModuleCollection hwModules;
-    android::DeviceVector availableOutputDevices;
-    android::DeviceVector availableInputDevices;
-    sp<android::DeviceDescriptor> defaultOutputDevice;
-};
-
-class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig {
-   public:
-    PolicyConfig()
-        : AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices,
-                            defaultOutputDevice) {
-        for (const auto& location : android::audio_get_configuration_paths()) {
-            std::string path = location + '/' + kConfigFileName;
-            if (access(path.c_str(), F_OK) == 0) {
-                mFilePath = path;
-                break;
-            }
-        }
-        mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this);
-        if (mStatus == OK) {
-            mPrimaryModule = getHwModules().getModuleFromName(DeviceManager::kPrimaryDevice);
-            // Available devices are not 'attached' to modules at this moment.
-            // Need to go over available devices and find their module.
-            for (const auto& device : availableOutputDevices) {
-                for (const auto& module : hwModules) {
-                    if (module->getDeclaredDevices().indexOf(device) >= 0) {
-                        mModulesWithDevicesNames.insert(module->getName());
-                        break;
-                    }
-                }
-            }
-            for (const auto& device : availableInputDevices) {
-                for (const auto& module : hwModules) {
-                    if (module->getDeclaredDevices().indexOf(device) >= 0) {
-                        mModulesWithDevicesNames.insert(module->getName());
-                        break;
-                    }
-                }
-            }
-        }
-    }
-    status_t getStatus() const { return mStatus; }
-    std::string getError() const {
-        if (mFilePath.empty()) {
-            return std::string{"Could not find "} + kConfigFileName +
-                   " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
-        } else {
-            return "Invalid config file: " + mFilePath;
-        }
-    }
-    const std::string& getFilePath() const { return mFilePath; }
-    sp<const HwModule> getModuleFromName(const std::string& name) const {
-        return getHwModules().getModuleFromName(name.c_str());
-    }
-    sp<const HwModule> getPrimaryModule() const { return mPrimaryModule; }
-    const std::set<std::string>& getModulesWithDevicesNames() const {
-        return mModulesWithDevicesNames;
-    }
-
-   private:
-    status_t mStatus = NO_INIT;
-    std::string mFilePath;
-    sp<HwModule> mPrimaryModule = nullptr;
-    std::set<std::string> mModulesWithDevicesNames;
-};
+static constexpr char kConfigFileName[] = "audio_policy_configuration.xml";
 
 // Cached policy config after parsing for faster test startup
 const PolicyConfig& getCachedPolicyConfig() {
     static std::unique_ptr<PolicyConfig> policyConfig = [] {
-        auto config = std::make_unique<PolicyConfig>();
+        auto config = std::make_unique<PolicyConfig>(kConfigFileName);
         return config;
     }();
     return *policyConfig;
@@ -449,9 +387,10 @@
      *  The getter and/or the setter may return NOT_SUPPORTED if optionality == OPTIONAL.
      */
     template <Optionality optionality = REQUIRED, class IUTGetter, class Getter, class Setter>
-    void testAccessors(IUTGetter iutGetter, const string& propertyName,
-                       const Initial expectedInitial, list<Property> valuesToTest, Setter setter,
-                       Getter getter, const vector<Property>& invalidValues = {}) {
+    void testAccessors(IUTGetter iutGetter, const std::string& propertyName,
+                       const Initial expectedInitial, std::list<Property> valuesToTest,
+                       Setter setter, Getter getter,
+                       const std::vector<Property>& invalidValues = {}) {
         const auto expectedResults = {Result::OK,
                                       optionality == OPTIONAL ? Result::NOT_SUPPORTED : Result::OK};
 
@@ -495,9 +434,9 @@
         EXPECT_RESULT(expectedResults, ((this->*iutGetter)().get()->*setter)(initialValue));
     }
     template <Optionality optionality = REQUIRED, class Getter, class Setter>
-    void testAccessors(const string& propertyName, const Initial expectedInitial,
-                       list<Property> valuesToTest, Setter setter, Getter getter,
-                       const vector<Property>& invalidValues = {}) {
+    void testAccessors(const std::string& propertyName, const Initial expectedInitial,
+                       std::list<Property> valuesToTest, Setter setter, Getter getter,
+                       const std::vector<Property>& invalidValues = {}) {
         testAccessors<optionality>(&BaseTestClass::getDevice, propertyName, expectedInitial,
                                    valuesToTest, setter, getter, invalidValues);
     }
@@ -573,9 +512,13 @@
 // Nesting a tuple in another tuple allows to use GTest Combine function to generate
 // all combinations of devices and configs.
 enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS };
+#if MAJOR_VERSION <= 6
 enum { INDEX_INPUT, INDEX_OUTPUT };
 using DeviceConfigParameter =
         std::tuple<DeviceParameter, AudioConfig, std::variant<AudioInputFlag, AudioOutputFlag>>;
+#elif MAJOR_VERSION >= 7
+using DeviceConfigParameter = std::tuple<DeviceParameter, AudioConfig, std::vector<AudioInOutFlag>>;
+#endif
 
 #if MAJOR_VERSION >= 6
 const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters();
@@ -583,8 +526,8 @@
 #endif
 
 #if MAJOR_VERSION >= 4
-static string SanitizeStringForGTestName(const string& s) {
-    string result = s;
+static std::string SanitizeStringForGTestName(const std::string& s) {
+    std::string result = s;
     for (size_t i = 0; i < result.size(); i++) {
         // gtest test names must only contain alphanumeric characters
         if (!std::isalnum(result[i])) result[i] = '_';
@@ -598,43 +541,57 @@
  * As the only parameter changing are channel mask and sample rate,
  * only print those ones in the test name.
  */
-static string DeviceConfigParameterToString(
+static std::string DeviceConfigParameterToString(
         const testing::TestParamInfo<DeviceConfigParameter>& info) {
     const AudioConfig& config = std::get<PARAM_CONFIG>(info.param);
     const auto deviceName = DeviceParameterToString(::testing::TestParamInfo<DeviceParameter>{
             std::get<PARAM_DEVICE>(info.param), info.index});
-    return (deviceName.empty() ? "" : deviceName + "_") + to_string(info.index) + "__" +
-           to_string(config.sampleRateHz) + "_" +
-           // "MONO" is more clear than "FRONT_LEFT"
-           ((config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) ||
-             config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO))
-                    ? "MONO"
+    const auto devicePart =
+            (deviceName.empty() ? "" : deviceName + "_") + std::to_string(info.index);
+    // The types had changed a lot between versions 2, 4..6 and 7. Use separate
+    // code sections for easier understanding.
 #if MAJOR_VERSION == 2
-                    : ::testing::PrintToString(config.channelMask)
-#elif MAJOR_VERSION >= 4
-                    // In V4 and above the channel mask is a bitfield.
-                    // Printing its value using HIDL's toString for a bitfield emits a lot of extra
-                    // text due to overlapping constant values. Instead, we print the bitfield value
-                    // as if it was a single value + its hex representation
-                    : SanitizeStringForGTestName(
-                              ::testing::PrintToString(AudioChannelMask(config.channelMask)) + "_" +
-                              toHexString(config.channelMask))
+    const auto configPart =
+            std::to_string(config.sampleRateHz) + "_" +
+            // "MONO" is more clear than "FRONT_LEFT"
+            (config.channelMask == AudioChannelMask::OUT_MONO ||
+                             config.channelMask == AudioChannelMask::IN_MONO
+                     ? "MONO"
+                     : ::testing::PrintToString(config.channelMask)) +
+            "_" +
+            std::visit([](auto&& arg) -> std::string { return ::testing::PrintToString(arg); },
+                       std::get<PARAM_FLAGS>(info.param));
+#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
+    const auto configPart =
+            std::to_string(config.sampleRateHz) + "_" +
+            // "MONO" is more clear than "FRONT_LEFT"
+            (config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) ||
+                             config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO)
+                     ? "MONO"
+                     // In V4 and above the channel mask is a bitfield.
+                     // Printing its value using HIDL's toString for a bitfield emits a lot of extra
+                     // text due to overlapping constant values. Instead, we print the bitfield
+                     // value as if it was a single value + its hex representation
+                     : SanitizeStringForGTestName(
+                               ::testing::PrintToString(AudioChannelMask(config.channelMask)) +
+                               "_" + toHexString(config.channelMask))) +
+            "_" +
+            SanitizeStringForGTestName(std::visit(
+                    [](auto&& arg) -> std::string {
+                        using T = std::decay_t<decltype(arg)>;
+                        // Need to use FQN of toString to avoid confusing the compiler
+                        return ::android::hardware::audio::common::CPP_VERSION::toString<T>(
+                                hidl_bitfield<T>(arg));
+                    },
+                    std::get<PARAM_FLAGS>(info.param)));
+#elif MAJOR_VERSION >= 7
+    const auto configPart =
+            std::to_string(config.base.sampleRateHz) + "_" +
+            // The channel masks and flags are vectors of strings, just need to sanitize them.
+            SanitizeStringForGTestName(::testing::PrintToString(config.base.channelMask)) + "_" +
+            SanitizeStringForGTestName(::testing::PrintToString(std::get<PARAM_FLAGS>(info.param)));
 #endif
-                    ) +
-           "_" +
-#if MAJOR_VERSION == 2
-           std::visit([](auto&& arg) -> std::string { return ::testing::PrintToString(arg); },
-                      std::get<PARAM_FLAGS>(info.param));
-#elif MAJOR_VERSION >= 4
-           SanitizeStringForGTestName(std::visit(
-                   [](auto&& arg) -> std::string {
-                       using T = std::decay_t<decltype(arg)>;
-                       // Need to use FQN of toString to avoid confusing the compiler
-                       return ::android::hardware::audio::common::CPP_VERSION::toString<T>(
-                               hidl_bitfield<T>(arg));
-                   },
-                   std::get<PARAM_FLAGS>(info.param)));
-#endif
+    return devicePart + "__" + configPart;
 }
 
 class AudioHidlTestWithDeviceConfigParameter
@@ -660,7 +617,7 @@
     AudioOutputFlag getOutputFlags() const {
         return std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam()));
     }
-#elif MAJOR_VERSION >= 4
+#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
     hidl_bitfield<AudioInputFlag> getInputFlags() const {
         return hidl_bitfield<AudioInputFlag>(
                 std::get<INDEX_INPUT>(std::get<PARAM_FLAGS>(GetParam())));
@@ -669,10 +626,17 @@
         return hidl_bitfield<AudioOutputFlag>(
                 std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam())));
     }
+#elif MAJOR_VERSION >= 7
+    hidl_vec<AudioInOutFlag> getInputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
+    hidl_vec<AudioInOutFlag> getOutputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
 #endif
 };
 
+#if MAJOR_VERSION <= 6
+#define AUDIO_PRIMARY_HIDL_HAL_TEST
 #include "ConfigHelper.h"
+#undef AUDIO_PRIMARY_HIDL_HAL_TEST
+#endif
 
 //////////////////////////////////////////////////////////////////////////////
 ///////////////////////////// getInputBufferSize /////////////////////////////
@@ -839,7 +803,7 @@
               AudioConfig* suggestedConfigPtr) {
         // FIXME: Open a stream without an IOHandle
         //        This is not required to be accepted by hal implementations
-        AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
+        AudioIoHandle ioHandle{};
         AudioConfig suggestedConfig{};
         bool retryWithSuggestedConfig = true;
         if (suggestedConfigPtr == nullptr) {
@@ -932,7 +896,11 @@
 class OutputStreamTest : public OpenStreamTest<IStreamOut> {
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
+#if MAJOR_VERSION <= 6
         address.device = AudioDevice::OUT_DEFAULT;
+#elif MAJOR_VERSION >= 7
+        address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT);
+#endif
         const AudioConfig& config = getConfig();
         auto flags = getOutputFlags();
         testOpen(
@@ -946,13 +914,19 @@
                 },
                 config);
     }
-#if MAJOR_VERSION >= 4
+#if MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
 
-   protected:
+  protected:
     const SourceMetadata initMetadata = {
         { { AudioUsage::MEDIA,
             AudioContentType::MUSIC,
             1 /* gain */ } }};
+#elif MAJOR_VERSION >= 7
+  protected:
+    const SourceMetadata initMetadata = {
+            { { toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
+                toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
+                1 /* gain */ } }};
 #endif
 };
 TEST_P(OutputStreamTest, OpenOutputStreamTest) {
@@ -995,7 +969,11 @@
 class InputStreamTest : public OpenStreamTest<IStreamIn> {
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
+#if MAJOR_VERSION <= 6
         address.device = AudioDevice::IN_DEFAULT;
+#elif MAJOR_VERSION <= 7
+        address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
+#endif
         const AudioConfig& config = getConfig();
         auto flags = getInputFlags();
         testOpen(
@@ -1009,8 +987,11 @@
    protected:
 #if MAJOR_VERSION == 2
     const AudioSource initMetadata = AudioSource::DEFAULT;
-#elif MAJOR_VERSION >= 4
-    const SinkMetadata initMetadata = {{{.source = AudioSource::DEFAULT, .gain = 1}}};
+#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
+     const SinkMetadata initMetadata = {{ {.source = AudioSource::DEFAULT, .gain = 1 } }};
+#elif MAJOR_VERSION >= 7
+     const SinkMetadata initMetadata = {
+             {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT), .gain = 1}}};
 #endif
 };
 
@@ -1067,6 +1048,7 @@
 TEST_IO_STREAM(GetFrameCount, "Check that getting stream frame count does not crash the HAL.",
                ASSERT_TRUE(stream->getFrameCount().isOk()))
 
+#if MAJOR_VERSION <= 6
 TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with",
                ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
 
@@ -1075,6 +1057,7 @@
 
 TEST_IO_STREAM(GetFormat, "Check that the stream format == the one it was opened with",
                ASSERT_EQ(audioConfig.format, extract(stream->getFormat())))
+#endif
 
 // 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",
@@ -1084,7 +1067,7 @@
                ASSERT_GE(extract(stream->getBufferSize()), extract(stream->getFrameSize())));
 
 template <class Property, class CapabilityGetter>
-static void testCapabilityGetter(const string& name, IStream* stream,
+static void testCapabilityGetter(const std::string& name, IStream* stream,
                                  CapabilityGetter capabilityGetter,
                                  Return<Property> (IStream::*getter)(),
                                  Return<Result> (IStream::*setter)(Property),
@@ -1120,6 +1103,7 @@
     }
 }
 
+#if MAJOR_VERSION <= 6
 TEST_IO_STREAM(SupportedSampleRate, "Check that the stream sample rate is declared as supported",
                testCapabilityGetter("getSupportedSampleRate", stream.get(),
                                     &GetSupported::sampleRates, &IStream::getSampleRate,
@@ -1137,19 +1121,71 @@
 TEST_IO_STREAM(SupportedFormat, "Check that the stream format is declared as supported",
                testCapabilityGetter("getSupportedFormat", stream.get(), &GetSupported::formats,
                                     &IStream::getFormat, &IStream::setFormat))
+#else
+static void testGetSupportedProfiles(IStream* stream) {
+    Result res;
+    hidl_vec<AudioProfile> profiles;
+    auto ret = stream->getSupportedProfiles(returnIn(res, profiles));
+    EXPECT_TRUE(ret.isOk());
+    if (res == Result::OK) {
+        EXPECT_GT(profiles.size(), 0);
+    } else {
+        EXPECT_EQ(Result::NOT_SUPPORTED, res);
+    }
+}
+
+TEST_IO_STREAM(GetSupportedProfiles, "Try to call optional method GetSupportedProfiles",
+               testGetSupportedProfiles(stream.get()))
+
+static void testSetAudioProperties(IStream* stream) {
+    Result res;
+    hidl_vec<AudioProfile> profiles;
+    auto ret = stream->getSupportedProfiles(returnIn(res, profiles));
+    EXPECT_TRUE(ret.isOk());
+    if (res == Result::NOT_SUPPORTED) {
+        GTEST_SKIP() << "Retrieving supported profiles is not implemented";
+    }
+    for (const auto& profile : profiles) {
+        for (const auto& sampleRate : profile.sampleRates) {
+            for (const auto& channelMask : profile.channelMasks) {
+                AudioConfigBase config{.format = profile.format,
+                                       .sampleRateHz = sampleRate,
+                                       .channelMask = channelMask};
+                auto ret = stream->setAudioProperties(config);
+                EXPECT_TRUE(ret.isOk());
+                EXPECT_EQ(Result::OK, ret) << config.format << "; " << config.sampleRateHz << "; "
+                                           << toString(config.channelMask);
+            }
+        }
+    }
+}
+
+TEST_IO_STREAM(SetAudioProperties, "Call setAudioProperties for all supported profiles",
+               testSetAudioProperties(stream.get()))
+#endif
 
 static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
+#if MAJOR_VERSION <= 6
     uint32_t sampleRateHz;
     auto mask = mkEnumBitfield<AudioChannelMask>({});
     AudioFormat format;
 
-    stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
+    auto ret = stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
+    EXPECT_TRUE(ret.isOk());
 
     // 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);
+#elif MAJOR_VERSION >= 7
+    AudioConfigBase actualConfig{};
+    auto ret = stream->getAudioProperties(returnIn(actualConfig));
+    EXPECT_TRUE(ret.isOk());
+    EXPECT_EQ(expectedConfig.base.sampleRateHz, actualConfig.sampleRateHz);
+    EXPECT_EQ(expectedConfig.base.channelMask, actualConfig.channelMask);
+    EXPECT_EQ(expectedConfig.base.format, actualConfig.format);
+#endif
 }
 
 TEST_IO_STREAM(GetAudioProperties,
@@ -1160,7 +1196,7 @@
                ASSERT_RESULT(okOrNotSupportedOrInvalidArgs, stream->setHwAvSync(666)))
 
 static void checkGetNoParameter(IStream* stream, hidl_vec<hidl_string> keys,
-                                initializer_list<Result> expectedResults) {
+                                std::initializer_list<Result> expectedResults) {
     hidl_vec<ParameterValue> parameters;
     Result res;
     ASSERT_OK(Parameters::get(stream, keys, returnIn(res, parameters)));
@@ -1271,7 +1307,11 @@
         return;
     }
     ASSERT_OK(res);
+#if MAJOR_VERSION <= 6
     ASSERT_EQ(AudioSource::DEFAULT, source);
+#elif MAJOR_VERSION >= 7
+    ASSERT_EQ(xsd::AudioSource::AUDIO_SOURCE_DEFAULT, xsd::stringToAudioSource(source));
+#endif
 }
 
 static void testUnitaryGain(std::function<Return<Result>(float)> setGain) {
@@ -1286,7 +1326,7 @@
 }
 
 static void testOptionalUnitaryGain(std::function<Return<Result>(float)> setGain,
-                                    string debugName) {
+                                    std::string debugName) {
     auto result = setGain(1);
     ASSERT_IS_OK(result);
     if (result == Result::NOT_SUPPORTED) {
@@ -1306,7 +1346,7 @@
     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; }));
+                                        [&res](auto r, auto&, auto&, auto&, auto) { res = r; }));
     EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
 }
 
@@ -1371,7 +1411,7 @@
     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; }));
+                                        [&res](auto r, auto&, auto&, auto&, auto) { res = r; }));
     EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
 }
 
diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h
index 8ef2b43..1a1dbea 100644
--- a/audio/core/all-versions/vts/functional/ConfigHelper.h
+++ b/audio/core/all-versions/vts/functional/ConfigHelper.h
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#pragma once
+
 // Code in this file uses 'getCachedPolicyConfig'
 #ifndef AUDIO_PRIMARY_HIDL_HAL_TEST
 #error Must be included from AudioPrimaryHidlTest.h
@@ -46,32 +48,32 @@
     }
 
     // Cache result ?
-    static const vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
+    static const std::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() {
+    static const std::vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
         return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
                                   {24000, 48000}, {AudioFormat::PCM_16_BIT});
     }
 
-    static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
+    static const std::vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
         if (!primaryHasMic()) return {};
         return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100},
                                   {AudioFormat::PCM_16_BIT});
     }
-    static const vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
+    static const std::vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
         if (!primaryHasMic()) return {};
         return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000},
                                   {AudioFormat::PCM_16_BIT});
     }
 
-    static vector<AudioConfig> combineAudioConfig(vector<audio_channel_mask_t> channelMasks,
-                                                  vector<uint32_t> sampleRates,
-                                                  audio_format_t format) {
-        vector<AudioConfig> configs;
+    static std::vector<AudioConfig> combineAudioConfig(
+            std::vector<audio_channel_mask_t> channelMasks, std::vector<uint32_t> sampleRates,
+            audio_format_t format) {
+        std::vector<AudioConfig> configs;
         configs.reserve(channelMasks.size() * sampleRates.size());
         for (auto channelMask : channelMasks) {
             for (auto sampleRate : sampleRates) {
@@ -86,10 +88,10 @@
         return configs;
     }
 
-    static vector<AudioConfig> combineAudioConfig(vector<AudioChannelMask> channelMasks,
-                                                  vector<uint32_t> sampleRates,
-                                                  vector<AudioFormat> formats) {
-        vector<AudioConfig> configs;
+    static std::vector<AudioConfig> combineAudioConfig(std::vector<AudioChannelMask> channelMasks,
+                                                       std::vector<uint32_t> sampleRates,
+                                                       std::vector<AudioFormat> formats) {
+        std::vector<AudioConfig> configs;
         configs.reserve(channelMasks.size() * sampleRates.size() * formats.size());
         for (auto channelMask : channelMasks) {
             for (auto sampleRate : sampleRates) {
diff --git a/audio/core/all-versions/vts/functional/DeviceManager.h b/audio/core/all-versions/vts/functional/DeviceManager.h
index 0c0727f..6efed79 100644
--- a/audio/core/all-versions/vts/functional/DeviceManager.h
+++ b/audio/core/all-versions/vts/functional/DeviceManager.h
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-// Code in this file uses 'environment'
-#ifndef AUDIO_PRIMARY_HIDL_HAL_TEST
-#error Must be included from AudioPrimaryHidlTest.h
-#endif
+#pragma once
+
+// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h
+// and thus it doesn't have all '#include' and 'using' directives required
+// for a standalone compilation.
 
 template <class Derived, class Key, class Interface>
 class InterfaceManager {
diff --git a/audio/core/all-versions/vts/functional/PolicyConfig.h b/audio/core/all-versions/vts/functional/PolicyConfig.h
new file mode 100644
index 0000000..c9e0c0d
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/PolicyConfig.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h
+// and thus it doesn't have all '#include' and 'using' directives required
+// for a standalone compilation.
+
+#include <Serializer.h>
+
+struct PolicyConfigData {
+    android::HwModuleCollection hwModules;
+    android::DeviceVector availableOutputDevices;
+    android::DeviceVector availableInputDevices;
+    sp<android::DeviceDescriptor> defaultOutputDevice;
+};
+
+class PolicyConfig : private PolicyConfigData, public android::AudioPolicyConfig {
+  public:
+    explicit PolicyConfig(const std::string& configFileName)
+        : android::AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices,
+                                     defaultOutputDevice),
+          mConfigFileName{configFileName} {
+        for (const auto& location : android::audio_get_configuration_paths()) {
+            std::string path = location + '/' + mConfigFileName;
+            if (access(path.c_str(), F_OK) == 0) {
+                mFilePath = path;
+                break;
+            }
+        }
+        mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this);
+        if (mStatus == OK) {
+            mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice);
+            // Available devices are not 'attached' to modules at this moment.
+            // Need to go over available devices and find their module.
+            for (const auto& device : availableOutputDevices) {
+                for (const auto& module : hwModules) {
+                    if (module->getDeclaredDevices().indexOf(device) >= 0) {
+                        mModulesWithDevicesNames.insert(module->getName());
+                        break;
+                    }
+                }
+            }
+            for (const auto& device : availableInputDevices) {
+                for (const auto& module : hwModules) {
+                    if (module->getDeclaredDevices().indexOf(device) >= 0) {
+                        mModulesWithDevicesNames.insert(module->getName());
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    status_t getStatus() const { return mStatus; }
+    std::string getError() const {
+        if (mFilePath.empty()) {
+            return std::string{"Could not find "} + mConfigFileName +
+                   " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
+        } else {
+            return "Invalid config file: " + mFilePath;
+        }
+    }
+    const std::string& getFilePath() const { return mFilePath; }
+    sp<const android::HwModule> getModuleFromName(const std::string& name) const {
+        return getHwModules().getModuleFromName(name.c_str());
+    }
+    sp<const android::HwModule> getPrimaryModule() const { return mPrimaryModule; }
+    const std::set<std::string>& getModulesWithDevicesNames() const {
+        return mModulesWithDevicesNames;
+    }
+    bool haveInputProfilesInModule(const std::string& name) const {
+        auto module = getModuleFromName(name);
+        return module && !module->getInputProfiles().empty();
+    }
+
+  private:
+    const std::string mConfigFileName;
+    status_t mStatus = NO_INIT;
+    std::string mFilePath;
+    sp<const android::HwModule> mPrimaryModule = nullptr;
+    std::set<std::string> mModulesWithDevicesNames;
+};
diff --git a/audio/effect/all-versions/vts/functional/Android.bp b/audio/effect/all-versions/vts/functional/Android.bp
index 7cdb18f..f4a7283 100644
--- a/audio/effect/all-versions/vts/functional/Android.bp
+++ b/audio/effect/all-versions/vts/functional/Android.bp
@@ -118,7 +118,6 @@
 }
 
 cc_test {
-    enabled: false,
     name: "VtsHalAudioEffectV7_0TargetTest",
     defaults: ["VtsHalAudioEffectTargetTest_default"],
     // Use test_config for vts suite.
@@ -126,6 +125,7 @@
     test_config: "VtsHalAudioEffectV7_0TargetTest.xml",
     static_libs: [
         "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.0-enums",
         "android.hardware.audio.effect@7.0",
     ],
     data: [
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
index 4787c09..b64f105 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
@@ -16,7 +16,9 @@
 
 #define LOG_TAG "AudioEffectHidlHalTest"
 #include <android-base/logging.h>
+#if MAJOR_VERSION <= 6
 #include <system/audio.h>
+#endif
 
 #include PATH(android/hardware/audio/effect/FILE_VERSION/IEffect.h)
 #include PATH(android/hardware/audio/effect/FILE_VERSION/IEffectsFactory.h)
@@ -25,6 +27,10 @@
 #include PATH(android/hardware/audio/effect/FILE_VERSION/types.h)
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
+#if MAJOR_VERSION >= 7
+#include <audio_policy_configuration_V7_0-enums.h>
+#include <audio_policy_configuration_V7_0.h>
+#endif
 
 #include <common/all-versions/VersionUtils.h>
 
@@ -45,6 +51,12 @@
 using ::android::hidl::memory::V1_0::IMemory;
 using namespace ::android::hardware::audio::common::CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
+#if MAJOR_VERSION >= 7
+// Make an alias for enumerations generated from the APM config XSD.
+namespace xsd {
+using namespace ::audio::policy::configuration::CPP_VERSION;
+}
+#endif
 
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
@@ -171,7 +183,7 @@
         effectsFactory = IEffectsFactory::getService(std::get<PARAM_FACTORY_NAME>(GetParam()));
         ASSERT_NE(nullptr, effectsFactory.get());
 
-        findAndCreateEffect(getEffectType());
+        ASSERT_NO_FATAL_FAILURE(findAndCreateEffect(getEffectType()));
         ASSERT_NE(nullptr, effect.get());
 
         Return<Result> ret = effect->init();
@@ -201,7 +213,7 @@
 
 void AudioEffectHidlTest::findAndCreateEffect(const Uuid& type) {
     Uuid effectUuid;
-    findEffectInstance(type, &effectUuid);
+    ASSERT_NO_FATAL_FAILURE(findEffectInstance(type, &effectUuid));
     Return<void> ret = effectsFactory->createEffect(
             effectUuid, 1 /*session*/, 1 /*ioHandle*/,
 #if MAJOR_VERSION >= 6
@@ -244,10 +256,16 @@
     });
     ASSERT_TRUE(ret.isOk());
     ASSERT_EQ(Result::OK, retval);
+#if MAJOR_VERSION <= 6
     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));
+#else
+    *channelCount =
+            audio::policy::configuration::V7_0::getChannelCount(currentConfig.outputCfg.channels);
+    ASSERT_NE(*channelCount, 0);
+#endif
 }
 
 TEST_P(AudioEffectHidlTest, Close) {
@@ -391,7 +409,12 @@
 
 TEST_P(AudioEffectHidlTest, SetDevice) {
     description("Verify that SetDevice works for an output chain effect");
+#if MAJOR_VERSION <= 6
     Return<Result> ret = effect->setDevice(mkEnumBitfield(AudioDevice::OUT_SPEAKER));
+#else
+    DeviceAddress device{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER)};
+    Return<Result> ret = effect->setDevice(device);
+#endif
     EXPECT_TRUE(ret.isOk());
     EXPECT_EQ(Result::OK, ret);
 }
@@ -441,22 +464,28 @@
 
 TEST_P(AudioEffectHidlTest, SetInputDevice) {
     description("Verify that SetInputDevice does not crash");
+#if MAJOR_VERSION <= 6
     Return<Result> ret = effect->setInputDevice(mkEnumBitfield(AudioDevice::IN_BUILTIN_MIC));
+#else
+    DeviceAddress device{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC)};
+    Return<Result> ret = effect->setInputDevice(device);
+#endif
     EXPECT_TRUE(ret.isOk());
 }
 
 TEST_P(AudioEffectHidlTest, SetAudioSource) {
     description("Verify that SetAudioSource does not crash");
+#if MAJOR_VERSION <= 6
     Return<Result> ret = effect->setAudioSource(AudioSource::MIC);
+#else
+    Return<Result> ret = effect->setAudioSource(toString(xsd::AudioSource::AUDIO_SOURCE_MIC));
+#endif
     EXPECT_TRUE(ret.isOk());
 }
 
 TEST_P(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);
+    Return<Result> ret = effect->offload(EffectOffloadParameter{});
     EXPECT_TRUE(ret.isOk());
 }
 
diff --git a/bluetooth/1.0/default/h4_protocol.cc b/bluetooth/1.0/default/h4_protocol.cc
index 8c24f76..43abbe4 100644
--- a/bluetooth/1.0/default/h4_protocol.cc
+++ b/bluetooth/1.0/default/h4_protocol.cc
@@ -90,6 +90,7 @@
     hci_packet_type_ = static_cast<HciPacketType>(buffer[0]);
     if (hci_packet_type_ != HCI_PACKET_TYPE_ACL_DATA &&
         hci_packet_type_ != HCI_PACKET_TYPE_SCO_DATA &&
+        hci_packet_type_ != HCI_PACKET_TYPE_ISO_DATA &&
         hci_packet_type_ != HCI_PACKET_TYPE_EVENT) {
       LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__,
                        static_cast<int>(hci_packet_type_));
diff --git a/bluetooth/1.0/default/hci_internals.h b/bluetooth/1.0/default/hci_internals.h
index 24e944f..6f7ff90 100644
--- a/bluetooth/1.0/default/hci_internals.h
+++ b/bluetooth/1.0/default/hci_internals.h
@@ -44,6 +44,10 @@
 const size_t HCI_EVENT_PREAMBLE_SIZE = 2;
 const size_t HCI_LENGTH_OFFSET_EVT = 1;
 
+// 2 bytes for handle and flags, 2 byte for data length (Volume 4, Part E, 5.4.5)
+const size_t HCI_ISO_PREAMBLE_SIZE = 4;
+const size_t HCI_LENGTH_OFFSET_ISO = 2;
+
 const size_t HCI_PREAMBLE_SIZE_MAX = HCI_ACL_PREAMBLE_SIZE;
 
 // Event codes (Volume 2, Part E, 7.7.14)
diff --git a/bluetooth/1.0/default/hci_packetizer.cc b/bluetooth/1.0/default/hci_packetizer.cc
index 7cb3a11..78ce61d 100644
--- a/bluetooth/1.0/default/hci_packetizer.cc
+++ b/bluetooth/1.0/default/hci_packetizer.cc
@@ -26,17 +26,27 @@
 
 namespace {
 
-const size_t preamble_size_for_type[] = {
-    0, HCI_COMMAND_PREAMBLE_SIZE, HCI_ACL_PREAMBLE_SIZE, HCI_SCO_PREAMBLE_SIZE,
-    HCI_EVENT_PREAMBLE_SIZE};
-const size_t packet_length_offset_for_type[] = {
-    0, HCI_LENGTH_OFFSET_CMD, HCI_LENGTH_OFFSET_ACL, HCI_LENGTH_OFFSET_SCO,
-    HCI_LENGTH_OFFSET_EVT};
+const size_t preamble_size_for_type[] = {0,
+                                         HCI_COMMAND_PREAMBLE_SIZE,
+                                         HCI_ACL_PREAMBLE_SIZE,
+                                         HCI_SCO_PREAMBLE_SIZE,
+                                         HCI_EVENT_PREAMBLE_SIZE,
+                                         HCI_ISO_PREAMBLE_SIZE};
+const size_t packet_length_offset_for_type[] = {0,
+                                                HCI_LENGTH_OFFSET_CMD,
+                                                HCI_LENGTH_OFFSET_ACL,
+                                                HCI_LENGTH_OFFSET_SCO,
+                                                HCI_LENGTH_OFFSET_EVT,
+                                                HCI_LENGTH_OFFSET_ISO};
 
 size_t HciGetPacketLengthForType(HciPacketType type, const uint8_t* preamble) {
   size_t offset = packet_length_offset_for_type[type];
-  if (type != HCI_PACKET_TYPE_ACL_DATA) return preamble[offset];
-  return (((preamble[offset + 1]) << 8) | preamble[offset]);
+  if (type == HCI_PACKET_TYPE_ACL_DATA) {
+    return (((preamble[offset + 1]) << 8) | preamble[offset]);
+  } else if (type == HCI_PACKET_TYPE_ISO_DATA) {
+    return ((((preamble[offset + 1]) & 0x3f) << 8) | preamble[offset]);
+  }
+  return preamble[offset];
 }
 
 }  // namespace
diff --git a/bluetooth/1.0/default/test/h4_protocol_unittest.cc b/bluetooth/1.0/default/test/h4_protocol_unittest.cc
index 283243d..174861c 100644
--- a/bluetooth/1.0/default/test/h4_protocol_unittest.cc
+++ b/bluetooth/1.0/default/test/h4_protocol_unittest.cc
@@ -190,8 +190,10 @@
 
   void WriteAndExpectInboundIsoData(char* payload) {
     // h4 type[1] + handle[2] + size[1]
-    char preamble[4] = {HCI_PACKET_TYPE_ISO_DATA, 20, 17, 0};
-    preamble[3] = strlen(payload) & 0xFF;
+    char preamble[5] = {HCI_PACKET_TYPE_ISO_DATA, 19, 92, 0, 0};
+    int length = strlen(payload);
+    preamble[3] = length & 0xFF;
+    preamble[4] = (length >> 8) & 0x3F;
 
     ALOGD("%s writing", __func__);
     TEMP_FAILURE_RETRY(write(fake_uart_, preamble, sizeof(preamble)));
diff --git a/current.txt b/current.txt
index 91494f2..cbf965f 100644
--- a/current.txt
+++ b/current.txt
@@ -769,6 +769,10 @@
 # ABI preserving changes to HALs during Android S
 2c331a9605f3a08d9c1e0a36169ca57758bc43c11a78ef3f3730509885e52c15 android.hardware.graphics.composer@2.4::IComposerClient
 3da3ce039247872d95c6bd48621dbfdfa1c2d2a91a90f257862f87ee2bc46300 android.hardware.health@2.1::types
+9679f27a42f75781c8993ef163ed92808a1928de186639834841d0b8e326e63d android.hardware.gatekeeper@1.0::IGatekeeper
+40456eb90ea88b62d18ad3fbf1da8917981cd55ac04ce69c8e058d49ff5beff4 android.hardware.keymaster@3.0::IKeymasterDevice
+6017b4f2481feb0fffceae81c62bc372c898998b2d8fe69fbd39859d3a315e5e android.hardware.keymaster@4.0::IKeymasterDevice
+dabe23dde7c9e3ad65c61def7392f186d7efe7f4216f9b6f9cf0863745b1a9f4 android.hardware.keymaster@4.1::IKeymasterDevice
 cd84ab19c590e0e73dd2307b591a3093ee18147ef95e6d5418644463a6620076 android.hardware.neuralnetworks@1.2::IDevice
 9625e85f56515ad2cf87b6a1847906db669f746ea4ab02cd3d4ca25abc9b0109 android.hardware.neuralnetworks@1.2::types
 9e758e208d14f7256e0885d6d8ad0b61121b21d8c313864f981727ae55bffd16 android.hardware.neuralnetworks@1.3::types
diff --git a/gatekeeper/1.0/Android.bp b/gatekeeper/1.0/Android.bp
index 28fd5b6..f5cb8e4 100644
--- a/gatekeeper/1.0/Android.bp
+++ b/gatekeeper/1.0/Android.bp
@@ -10,5 +10,5 @@
     interfaces: [
         "android.hidl.base@1.0",
     ],
-    gen_java: true,
+    gen_java: false,
 }
diff --git a/gatekeeper/1.0/IGatekeeper.hal b/gatekeeper/1.0/IGatekeeper.hal
index 59dd7d1..84e8e06 100644
--- a/gatekeeper/1.0/IGatekeeper.hal
+++ b/gatekeeper/1.0/IGatekeeper.hal
@@ -15,6 +15,7 @@
  */
 package android.hardware.gatekeeper@1.0;
 
+@SensitiveData
 interface IGatekeeper {
 
 /**
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 57cdc98..77b795b 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -1023,11 +1023,12 @@
     // relying party is ever going to trust our batch key and those keys above
     // it.
     //
-    ::keymaster::PureSoftKeymasterContext context(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
+    ::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMASTER_4_1,
+                                                  KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
 
     error = generate_attestation_from_EVP(key, swEnforced, hwEnforced, auth_set, context,
-                                          ::keymaster::kCurrentKeymasterVersion, *attestation_chain,
-                                          *attestation_signing_key, &cert_chain_out);
+                                          *attestation_chain, *attestation_signing_key,
+                                          &cert_chain_out);
 
     if (KM_ERROR_OK != error || !cert_chain_out) {
         LOG(ERROR) << "Error generate attestation from EVP key" << error;
@@ -2402,7 +2403,6 @@
     return ret;
 }
 
-
 vector<uint8_t> testHardwareBoundKey = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
 const vector<uint8_t>& getTestHardwareBoundKey() {
diff --git a/keymaster/3.0/IKeymasterDevice.hal b/keymaster/3.0/IKeymasterDevice.hal
index 2664765..9bd8602 100644
--- a/keymaster/3.0/IKeymasterDevice.hal
+++ b/keymaster/3.0/IKeymasterDevice.hal
@@ -20,6 +20,7 @@
  * Keymaster device definition.  For thorough documentation see the implementer's reference, at
  * https://source.android.com/security/keystore/implementer-ref.html
  */
+@SensitiveData
 interface IKeymasterDevice {
 
     /**
diff --git a/keymaster/4.0/IKeymasterDevice.hal b/keymaster/4.0/IKeymasterDevice.hal
index 3475f79..dfde060 100644
--- a/keymaster/4.0/IKeymasterDevice.hal
+++ b/keymaster/4.0/IKeymasterDevice.hal
@@ -195,7 +195,7 @@
  * Tag::VENDOR_PATCHLEVEL, and Tag::BOOT_PATCHLEVEL must be cryptographically bound to every
  * IKeymasterDevice key, as described in the Key Access Control section above.
  */
-
+@SensitiveData
 interface IKeymasterDevice {
 
     /**
diff --git a/keymaster/4.1/IKeymasterDevice.hal b/keymaster/4.1/IKeymasterDevice.hal
index bbeccaa..ccb9f2e 100644
--- a/keymaster/4.1/IKeymasterDevice.hal
+++ b/keymaster/4.1/IKeymasterDevice.hal
@@ -37,6 +37,7 @@
  * versions will be numbered as major_version * 10 + minor version.  The addition of new attestable
  * tags changes the attestation format again, slightly, so the attestationVersion must be 4.
  */
+@SensitiveData
 interface IKeymasterDevice extends @4.0::IKeymasterDevice {
     /**
      * Called by client to notify the IKeymasterDevice that the device is now locked, and keys with
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidBuffer.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBuffer.h
new file mode 100644
index 0000000..8c04b88
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBuffer.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BUFFER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BUFFER_H
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class InvalidBuffer final : public nn::IBuffer {
+  public:
+    nn::Request::MemoryDomainToken getToken() const override;
+
+    nn::GeneralResult<void> copyTo(const nn::Memory& dst) const override;
+
+    nn::GeneralResult<void> copyFrom(const nn::Memory& src,
+                                     const nn::Dimensions& dimensions) const override;
+};
+
+}  // namespace android::hardware::neuralnetworks::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BUFFER_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
new file mode 100644
index 0000000..5e62b9a
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_DEVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_DEVICE_H
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class InvalidDevice final : public nn::IDevice {
+  public:
+    InvalidDevice(std::string name, std::string versionString, nn::Version featureLevel,
+                  nn::DeviceType type, std::vector<nn::Extension> extensions,
+                  nn::Capabilities capabilities,
+                  std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded);
+
+    const std::string& getName() const override;
+    const std::string& getVersionString() const override;
+    nn::Version getFeatureLevel() const override;
+    nn::DeviceType getType() const override;
+    const std::vector<nn::Extension>& getSupportedExtensions() const override;
+    const nn::Capabilities& getCapabilities() const override;
+    std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
+
+    nn::GeneralResult<void> wait() const override;
+
+    nn::GeneralResult<std::vector<bool>> getSupportedOperations(
+            const nn::Model& model) const override;
+
+    nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
+            const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+            nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+            const std::vector<nn::SharedHandle>& dataCache,
+            const nn::CacheToken& token) const override;
+
+    nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
+            nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+            const std::vector<nn::SharedHandle>& dataCache,
+            const nn::CacheToken& token) const override;
+
+    nn::GeneralResult<nn::SharedBuffer> allocate(
+            const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
+            const std::vector<nn::BufferRole>& inputRoles,
+            const std::vector<nn::BufferRole>& outputRoles) const override;
+
+  private:
+    const std::string kName;
+    const std::string kVersionString;
+    const nn::Version kFeatureLevel;
+    const nn::DeviceType kType;
+    const std::vector<nn::Extension> kExtensions;
+    const nn::Capabilities kCapabilities;
+    const std::pair<uint32_t, uint32_t> kNumberOfCacheFilesNeeded;
+};
+
+}  // namespace android::hardware::neuralnetworks::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_DEVICE_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
new file mode 100644
index 0000000..4b32b4e
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_PREPARED_MODEL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_PREPARED_MODEL_H
+
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class InvalidPreparedModel final : public nn::IPreparedModel {
+  public:
+    nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
+            const nn::Request& request, nn::MeasureTiming measure,
+            const nn::OptionalTimePoint& deadline,
+            const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+
+    nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
+            const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+            nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+            const nn::OptionalTimeoutDuration& loopTimeoutDuration,
+            const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+
+    std::any getUnderlyingResource() const override;
+};
+
+}  // namespace android::hardware::neuralnetworks::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_PREPARED_MODEL_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
index 4a84e4d..4bfed6c 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
@@ -45,8 +45,9 @@
                              std::string versionString, std::vector<nn::Extension> extensions,
                              nn::Capabilities capabilities, nn::SharedDevice device);
 
-    nn::SharedDevice getDevice() const;
-    nn::SharedDevice recover(const nn::IDevice* failingDevice, bool blocking) const;
+    nn::SharedDevice getDevice() const EXCLUDES(mMutex);
+    nn::SharedDevice recover(const nn::IDevice* failingDevice, bool blocking) const
+            EXCLUDES(mMutex);
 
     const std::string& getName() const override;
     const std::string& getVersionString() const override;
@@ -78,6 +79,7 @@
             const std::vector<nn::BufferRole>& outputRoles) const override;
 
   private:
+    bool isValidInternal() const EXCLUDES(mMutex);
     nn::GeneralResult<nn::SharedPreparedModel> prepareModelInternal(
             bool blocking, const nn::Model& model, nn::ExecutionPreference preference,
             nn::Priority priority, nn::OptionalTimePoint deadline,
@@ -100,6 +102,7 @@
     const nn::Capabilities kCapabilities;
     mutable std::mutex mMutex;
     mutable nn::SharedDevice mDevice GUARDED_BY(mMutex);
+    mutable bool mIsValid GUARDED_BY(mMutex) = true;
 };
 
 }  // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidBuffer.cpp b/neuralnetworks/utils/common/src/InvalidBuffer.cpp
new file mode 100644
index 0000000..c6f75d7
--- /dev/null
+++ b/neuralnetworks/utils/common/src/InvalidBuffer.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "InvalidBuffer.h"
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+nn::Request::MemoryDomainToken InvalidBuffer::getToken() const {
+    return nn::Request::MemoryDomainToken{};
+}
+
+nn::GeneralResult<void> InvalidBuffer::copyTo(const nn::Memory& /*dst*/) const {
+    return NN_ERROR() << "InvalidBuffer";
+}
+
+nn::GeneralResult<void> InvalidBuffer::copyFrom(const nn::Memory& /*src*/,
+                                                const nn::Dimensions& /*dimensions*/) const {
+    return NN_ERROR() << "InvalidBuffer";
+}
+
+}  // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidDevice.cpp b/neuralnetworks/utils/common/src/InvalidDevice.cpp
new file mode 100644
index 0000000..535ccb4
--- /dev/null
+++ b/neuralnetworks/utils/common/src/InvalidDevice.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "InvalidDevice.h"
+
+#include "InvalidBuffer.h"
+#include "InvalidPreparedModel.h"
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+InvalidDevice::InvalidDevice(std::string name, std::string versionString, nn::Version featureLevel,
+                             nn::DeviceType type, std::vector<nn::Extension> extensions,
+                             nn::Capabilities capabilities,
+                             std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded)
+    : kName(std::move(name)),
+      kVersionString(std::move(versionString)),
+      kFeatureLevel(featureLevel),
+      kType(type),
+      kExtensions(std::move(extensions)),
+      kCapabilities(std::move(capabilities)),
+      kNumberOfCacheFilesNeeded(numberOfCacheFilesNeeded) {}
+
+const std::string& InvalidDevice::getName() const {
+    return kName;
+}
+
+const std::string& InvalidDevice::getVersionString() const {
+    return kVersionString;
+}
+
+nn::Version InvalidDevice::getFeatureLevel() const {
+    return kFeatureLevel;
+}
+
+nn::DeviceType InvalidDevice::getType() const {
+    return kType;
+}
+
+const std::vector<nn::Extension>& InvalidDevice::getSupportedExtensions() const {
+    return kExtensions;
+}
+
+const nn::Capabilities& InvalidDevice::getCapabilities() const {
+    return kCapabilities;
+}
+
+std::pair<uint32_t, uint32_t> InvalidDevice::getNumberOfCacheFilesNeeded() const {
+    return kNumberOfCacheFilesNeeded;
+}
+
+nn::GeneralResult<void> InvalidDevice::wait() const {
+    return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<std::vector<bool>> InvalidDevice::getSupportedOperations(
+        const nn::Model& /*model*/) const {
+    return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> InvalidDevice::prepareModel(
+        const nn::Model& /*model*/, nn::ExecutionPreference /*preference*/,
+        nn::Priority /*priority*/, nn::OptionalTimePoint /*deadline*/,
+        const std::vector<nn::SharedHandle>& /*modelCache*/,
+        const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+    return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> InvalidDevice::prepareModelFromCache(
+        nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& /*modelCache*/,
+        const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+    return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<nn::SharedBuffer> InvalidDevice::allocate(
+        const nn::BufferDesc& /*desc*/,
+        const std::vector<nn::SharedPreparedModel>& /*preparedModels*/,
+        const std::vector<nn::BufferRole>& /*inputRoles*/,
+        const std::vector<nn::BufferRole>& /*outputRoles*/) const {
+    return NN_ERROR() << "InvalidDevice";
+}
+
+}  // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
new file mode 100644
index 0000000..9ae7a63
--- /dev/null
+++ b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "InvalidPreparedModel.h"
+
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+InvalidPreparedModel::execute(const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
+                              const nn::OptionalTimePoint& /*deadline*/,
+                              const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/) const {
+    return NN_ERROR() << "InvalidPreparedModel";
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+InvalidPreparedModel::executeFenced(
+        const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
+        nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
+        const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/,
+        const nn::OptionalTimeoutDuration& /*timeoutDurationAfterFence*/) const {
+    return NN_ERROR() << "InvalidPreparedModel";
+}
+
+std::any InvalidPreparedModel::getUnderlyingResource() const {
+    return {};
+}
+
+}  // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/ResilientDevice.cpp b/neuralnetworks/utils/common/src/ResilientDevice.cpp
index 26025a5..2f83c5c 100644
--- a/neuralnetworks/utils/common/src/ResilientDevice.cpp
+++ b/neuralnetworks/utils/common/src/ResilientDevice.cpp
@@ -16,6 +16,9 @@
 
 #include "ResilientDevice.h"
 
+#include "InvalidBuffer.h"
+#include "InvalidDevice.h"
+#include "InvalidPreparedModel.h"
 #include "ResilientBuffer.h"
 #include "ResilientPreparedModel.h"
 
@@ -107,12 +110,21 @@
     }
     auto device = std::move(maybeDevice).value();
 
-    // TODO(b/173081926): Instead of CHECKing to ensure the cache has not been changed, return an
-    // invalid/"null" IDevice object that always fails.
-    CHECK_EQ(kName, device->getName());
-    CHECK_EQ(kVersionString, device->getVersionString());
-    CHECK(kExtensions == device->getSupportedExtensions());
-    CHECK_EQ(kCapabilities, device->getCapabilities());
+    // If recovered device has different metadata than what is cached (i.e., because it was
+    // updated), mark the device as invalid and preserve the cached data.
+    auto compare = [this, &device](auto fn) REQUIRES(mMutex) {
+        return std::invoke(fn, mDevice) != std::invoke(fn, device);
+    };
+    if (compare(&IDevice::getName) || compare(&IDevice::getVersionString) ||
+        compare(&IDevice::getFeatureLevel) || compare(&IDevice::getType) ||
+        compare(&IDevice::getSupportedExtensions) || compare(&IDevice::getCapabilities)) {
+        LOG(ERROR) << "Recovered device has different metadata than what is cached. Marking "
+                      "IDevice object as invalid.";
+        device = std::make_shared<const InvalidDevice>(
+                kName, kVersionString, mDevice->getFeatureLevel(), mDevice->getType(), kExtensions,
+                kCapabilities, mDevice->getNumberOfCacheFilesNeeded());
+        mIsValid = false;
+    }
 
     mDevice = std::move(device);
     return mDevice;
@@ -199,11 +211,19 @@
     return ResilientBuffer::create(std::move(makeBuffer));
 }
 
+bool ResilientDevice::isValidInternal() const {
+    std::lock_guard hold(mMutex);
+    return mIsValid;
+}
+
 nn::GeneralResult<nn::SharedPreparedModel> ResilientDevice::prepareModelInternal(
         bool blocking, const nn::Model& model, nn::ExecutionPreference preference,
         nn::Priority priority, nn::OptionalTimePoint deadline,
         const std::vector<nn::SharedHandle>& modelCache,
         const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+    if (!isValidInternal()) {
+        return std::make_shared<const InvalidPreparedModel>();
+    }
     const auto fn = [&model, preference, priority, deadline, &modelCache, &dataCache,
                      token](const nn::IDevice& device) {
         return device.prepareModel(model, preference, priority, deadline, modelCache, dataCache,
@@ -216,6 +236,9 @@
         bool blocking, nn::OptionalTimePoint deadline,
         const std::vector<nn::SharedHandle>& modelCache,
         const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+    if (!isValidInternal()) {
+        return std::make_shared<const InvalidPreparedModel>();
+    }
     const auto fn = [deadline, &modelCache, &dataCache, token](const nn::IDevice& device) {
         return device.prepareModelFromCache(deadline, modelCache, dataCache, token);
     };
@@ -227,6 +250,9 @@
         const std::vector<nn::SharedPreparedModel>& preparedModels,
         const std::vector<nn::BufferRole>& inputRoles,
         const std::vector<nn::BufferRole>& outputRoles) const {
+    if (!isValidInternal()) {
+        return std::make_shared<const InvalidBuffer>();
+    }
     const auto fn = [&desc, &preparedModels, &inputRoles, &outputRoles](const nn::IDevice& device) {
         return device.allocate(desc, preparedModels, inputRoles, outputRoles);
     };
diff --git a/tests/foo/1.0/IFoo.hal b/tests/foo/1.0/IFoo.hal
index 4c54427..e242616 100644
--- a/tests/foo/1.0/IFoo.hal
+++ b/tests/foo/1.0/IFoo.hal
@@ -21,6 +21,7 @@
 import ISimple;
 import ITheirTypes.FloatArray;
 
+@SensitiveData // for test
 interface IFoo {
 
     enum SomeBaseEnum : uint8_t {